Skip to content
Advertisement

Calling libc functions from another shared library in AT&T syntax?

i was trying to assemble codes below to shared library via gcc.

.section .text

.global S_0x400607
.type S_0x400607, @function
S_0x400607:
push %rbp
mov %rsp,%rbp
sub $0x10,%rsp
mov %edi,-0x4(%rbp)
mov -0x4(%rbp),%eax
mov %eax,%esi
lea S_0x400724(%rip),%rdi
mov $0x0,%eax
callq printf
nop
leaveq
retq


.section .rodata

S_0x400724:
.byte 0x25
.byte 0x64
.byte 0x0a
.byte 0x00

i used command below in terminal and got errors.

$ gcc zzz_out.s -shared -fPIC  -o libzzz.so
/usr/bin/ld: /tmp/ccq8FvIT.o: relocation R_X86_64_PC32 against symbol `printf@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

Then i googled the question and got a seemingly feasible answer in undefined-reference-to-main-for-shared-library. Then i added option -no-pie, used commands below and got another error.

$ gcc zzz_out.s -shared -fPIC -no-pie  -o libzzz.so
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

It seems that the order of options matters. But i used codes in 32-bits like this.

.section .text

.globl S_0x8048506
.type  S_0x8048506, @function
S_0x8048506:
push %ebp
mov %esp,%ebp
push %ebx
sub $0x4,%esp
call S_0x80485CC
add $_GLOBAL_OFFSET_TABLE_,%eax
sub $0x8,%esp
pushl 0x8(%ebp)
lea S_0x8048670,%edx
push %edx
mov %eax,%ebx
call printf
add $0x10,%esp
nop
mov -0x4(%ebp),%ebx
leave
ret

S_0x80485CC:
mov (%esp),%eax
ret

.section .rodata
S_0x8048670:
.byte 0x25
.byte 0x64
.byte 0x0a
.byte 0x00

gcc works perfectly and libzzz.so generated in current directory. Sorry if i asked a simple question. I’m totally new in this region.

Advertisement

Answer

You only get undefined reference to `main' with -no-pie.

I think -no-pie is overriding -shared, so you’re telling GCC to link a position-dependent executable, not a shared-library at all. (ELF shared libraries aka “shared objects” always have to be position-independent, there’s no such thing as a non-PIC .so. Fun fact: PIE executables are another type of ELF shared object.)


Unlike when linking a non-PIE executable, ld rewrites call printf into a call through the PLT for you. But when linking a PIE or shared library, you have to do it manually. (Newer ld might do this for you, at least in a PIE, but this was a recent change.)

In 32-bit code, call printf likely assembles and links with a runtime fixup that rewrites the call rel32 instruction at runtime to be printf‘s actual address in libc, once it’s loaded to a randomized base address. But that doesn’t work for 64-bit code because it might be more than +-2GiB away. Similar to why 32-bit absolute addresses no longer allowed in x86-64 Linux? after distros made PIE executables the default GCC config.

Your options for 64-bit code are:

  • call *printf@GOTPCREL(%rip), like gcc -fno-plt would emit when compiling C.
  • call printf@plt like compilers have historically used.
  • non-PIE executable isn’t an option; you’re making a -shared library.

For a NASM-syntax version of this with more detail about what this means, and the machine code, see Can’t call C standard library function on 64-bit Linux from assembly (yasm) code. Also has some examples at the bottom which include AT&T syntax, of how the linker “relaxes” this to a call rel32 if you do call *foobar@GOTPCREL(%rip) but then foobar is defined in the same shared library after all (with “hidden” visibility, not global, so symbol interposition isn’t necessary).

See Unexpected value of a function pointer local variable for some examples of compiler output for a PIE vs. non-PIE executable (the PIE executable code will also work in a shared library.)

-fno-plt style of code-gen is probably not worth it in 32-bit mode, where you don’t have efficient EIP-relative addressing to reach the GOT, unless you already needed a GOT pointer for something else in this funciton.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement