Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 313 Vote(s) - 3.52 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ELF Shared Object in x86-64 Assembly language

#1
I'm trying to create a Shared library (*.so) in ASM and I'm not sure that i do it correct...

My code is:

.section .data
.globl var1
var1:
.quad 0x012345

.section .text
.globl func1
func1:
xor %rax, %rax
# mov var1, %rcx # this is commented
ret
To compile it i run

gcc ker.s -g -fPIC -m64 -o ker.o
gcc ker.o -shared -fPIC -m64 -o libker.so

I can access variable var1 and call func1 with dlopen() and dlsym() from a program in C.

The problem is in variable var1. When i try to access it from func1, i.e. uncomment that line, the compiler generates an error:

/usr/bin/ld: ker.o: relocation R_X86_64_32S against `var1' can not be used when making a shared object; recompile with -fPIC
ker.o: could not read symbols: Bad value
collect2: ld returned 1 exit status

I don't understand. I've already compiled with -fPIC, so what's wrong?
Reply

#2
> I don't understand. I've already compiled with -fPIC, so what's wrong?

`-fPIC` is a flag concerning the creation of machine code from non-machine code, i.e. which operations to use. In the compilation stage. **Assembly is not compiled, though!** Each assembly mnemonic maps directly to a machine instruction, your code is not compiled. It's just transcribed into a slightly different format.

Since you're writing it in assembly, your assembly code must be position independent to be linkable into a shared library. `-fPIC` has not effect in your case, because it only affects code generation.
Reply

#3
Ok, i think i found something...

First solution from *drhirsch* gives almost the same error but the relocation type is changed. And type is always ended with 32. Why is it? Why 64 bit program uses 32-bit relocation?

I found this from googling:

[To see links please register here]


It says:

> For code optimisation purposes, the default immediate size to the mov
> instructions is a 32-bit value

So that's the case. I use 64-bit program but relocation is 32-bit and all i need is to force it to be 64 bit with `movabs` instruction.

This code is assembling and working (access to `var1` from internal function `func1` and from external C program via `dlsym()`):

.section .data
.globl var1
var1:
.quad 0x012345

.section .text
.globl func1
func1:
movabs var1, %rax # if one is symbol, other must be %rax
inc %rax
movabs %rax, var1
ret

But i'm in doubt about Global Offset Table. Must i use it, or this "direct" access is absolutely correct?
Reply

#4
> I've already compiled with -fPIC, so what's wrong?

That part of the error message is for people who are linking compiler-generated code.

You're writing asm by hand, so as datenwolf correctly wrote, when writing a shared library in assembly, you have to take care for yourself that the code is position independent.

This means file must not contain any 32-bit absolute addresses (because relocation to an arbitrary 64-bit base is impossible). 64-bit absolute relocations *are* supported, but normally you should only use that for jump tables.

---

**`mov var1, %rcx` uses a 32-bit absolute addressing mode**. You should normally never do this, even in position-dependent x86-64 code. The normal use-cases for 32-bit absolute addresses are: putting an address into a 64-bit register with`mov $var1, %edi` (zero-extends into RDI)
and indexing static arrays: `mov arr(,%rdx,4), %edx`

**`mov var1(%rip), %rcx` uses a RIP-relative 32-bit offset**. It's the efficient way to address static data, and compilers always use this even without `-fPIE` or ` -fPIC` for static/global variables.

You have basically two possibilities:

* **Normal library-private static data**, like C compilers will make for `__attribute__((visibility("hidden"))) long var1;`, **same as for `-fno-PIC`**.

```
.data
.globl var1 # linkable from other .o files in the same shared object / library
.hidden var1 # not visible for *dynamic* linking outside the library
var1:
.quad 0x012345

.text
.globl func1
func1:
xor %eax, %eax # return 0
mov var1(%rip), %rcx
ret
```

* **full symbol-interposition-aware code like compilers generate for `-fPIC`**.

You have to use the Global Offset Table. This is how a compiler does it, if you tell him to produce code for a shared library.
Note that this comes with a performance hit because of the additional indirection.

See [Sorry state of dynamic libraries on Linux](

[To see links please register here]

) for more about symbol-interposition and the overheads it imposes on code-gen for shared libraries if you're not careful about restricting symbol visibility to allow inlining.

`var1@GOTPCREL` is the address of a pointer to your `var1`, the pointer itself is reachable with rip-relative addressing, while the content (the address of `var1`) is filled by the linker during loading of the library. This supports the case where the program using your library defined `var1`, so `var1` in your library should resolve to that memory location instead of the one in the `.data` or `.bss` (or `.text`) of your `.so`.

```
.section .data
.globl var1
# without .hidden
var1:
.quad 0x012345

.section .text
.globl func1
func1:
xor %eax, %eax
mov var1@GOTPCREL(%rip), %rcx
mov (%rcx), %rcx
ret
```

See some additional information at

[To see links please register here]



[An example on the Godbolt compiler explorer][1] of `-fPIC` vs. `-fPIE` shows the difference that symbol-interposition makes for **getting the address of non-hidden global variables**:

* `movl $x, %eax` 5 bytes, `-fno-pie`
* `leaq x(%rip), %rax` 7 bytes, `-fPIE` and hidden globals or `static` with `-fPIC`
* `y@GOTPCREL(%rip), %rax` 7 bytes and a load instead of just ALU, `-fPIC` with non-hidden globals.

Actually loading always uses `x(%rip)`, except for non-hidden / non-`static` vars with `-fPIC` where it has to get the runtime address from the GOT first, because it's not a link-time constant offset relative to the code.

Related:

[To see links please register here]

(PIE executables).

----

A previous version of this answer stated that the DATA and BSS segments could move relative to TEXT when loading a dynamic library. This is incorrect, only the library base address is relocatable. RIP-relative access to other segments within the same library is guaranteed to be ok, and compilers emit code that does this. The ELF headers specify how the segments (which contain the sections) need to be loaded/mapped into memory.



[1]:

[To see links please register here]

:'__attribute__((visibility(%22hidden%22)))+int+x+%3D+123%3B+//+.data+section+/+DATA+segment%0Aint+y+%3D+456%3B+++//+same+but+not+%22hidden%22%0A%0Aint+getx()+%7B+return+x%3B+%7D%0Aconst+int+*getxaddr()+%7B+return+%26x%3B+%7D%0A%0Aint+gety()+%7B+return+y%3B+%7D%0Aconst+int+*getyaddr()+%7B+return+%26y%3B+%7D%0A%0A%0Aconst+int+z+%3D+789%3B++++++++//+can+still+fill+in+the+value+as+an+immediate%0Aint+getz()+%7B+return+z%3B+%7D++//+even+though+it!'s+not+%22hidden%22'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:36.669774412248145,l:'4',m:51.306267359626545,n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:g82,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'1',libraryCode:'1',trim:'1'),lang:c%2B%2B,libs:!(),options:'-O3+-fno-pie',source:1),l:'5',n:'0',o:'x86-64+gcc+8.2+(Editor+%231,+Compiler+%233)+C%2B%2B',t:'0')),header:(),l:'4',m:48.693732640373455,n:'0',o:'',s:0,t:'0')),k:36.669774412248145,l:'3',n:'0',o:'',t:'0'),(g:!((h:compiler,i:(compiler:g82,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'1',libraryCode:'1',trim:'1'),lang:c%2B%2B,libs:!(),options:'-O3+-fPIC',source:1),l:'5',n:'0',o:'x86-64+gcc+8.2+(Editor+%231,+Compiler+%231)+C%2B%2B',t:'0')),k:32.12383930530354,l:'4',m:100,n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:g82,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'1',libraryCode:'1',trim:'1'),lang:c%2B%2B,libs:!(),options:'-O3+-fPIE',source:1),l:'5',n:'0',o:'x86-64+gcc+8.2+(Editor+%231,+Compiler+%232)+C%2B%2B',t:'0')),k:31.206386282448314,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through