1

I have a function defined in assembly that is calling a libc function (swapcontext). I invoke that function from my C code. For the purpose of creating a reproducible example, I'm using 'puts' instead:

foo.S:

.globl foo 
foo:
    call puts
    ret

test.c:

void foo(char *str);

int main() {
    foo("Hello World\n");
    return 0;
}

Compile:

gcc test.c foo.S  -o test

This compiles fine. Dis-assembling the result binary however shows that a valid call instruction wasn't inserted by the linker:

objdump -dR:

0000000000000671 <foo>:
 671:   e8 00 00 00 00          callq  676 <foo+0x5>
            672: R_X86_64_PC32  puts@GLIBC_2.2.5-0x4
 676:   c3                      retq   
 677:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
 67e:   00 00 

0000000000000530 <puts@plt>:
 530:   ff 25 9a 0a 20 00       jmpq   *0x200a9a(%rip)        # 200fd0 <puts@GLIBC_2.2.5>
 536:   68 00 00 00 00          pushq  $0x0
 53b:   e9 e0 ff ff ff          jmpq   520 <.plt>

Execution:

./test1: Symbol `puts' causes overflow in R_X86_64_PC32 relocation
Segmentation fault

Any ideas why?

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
cradical
  • 117
  • 7
  • `objdump -dR test` may be enlightening. Also, don't you need a `ret` in the definition of `foo`? Also also, `swapcontext` has abnormal control flow, you need to take special care to call it safely. – zwol Aug 28 '19 at 20:53
  • 1
    Appears you OBJDUMP'ed an object file that has relocations. Try OBJDUMPing the final executable or OBJDUMP a `.o` file using the `-r` option to show relocation entries. – Michael Petch Aug 28 '19 at 20:54
  • [mcve], please. This doesn't reproduce the behavior, and doesn't work when run. – S.S. Anne Aug 28 '19 at 21:03
  • ... What's `# 200fd0 `, then? – S.S. Anne Aug 28 '19 at 21:09
  • I've updated the original example to make it a valid by using puts with the argument to it stored in %rdi. I've also indicated the failure when I run it. – cradical Aug 28 '19 at 21:26
  • Interesting - when I add '-no-pie' to the compile argument, it works fine. Any ideas why? – cradical Aug 28 '19 at 21:28
  • Possible duplicate of [Can't call C standard library function on 64-bit Linux from assembly (yasm) code](https://stackoverflow.com/questions/52126328/cant-call-c-standard-library-function-on-64-bit-linux-from-assembly-yasm-code) – S.S. Anne Aug 28 '19 at 22:08

2 Answers2

4

For your updated totally separate question, which replaced your question about disassembling a .o:

semi-related: Unexpected value of a function pointer local variable mentions the fact that the linker transforms references to puts to puts@plt for you in a non-PIE (because that lets you get efficient code if statically linking), but not in a PIE.

libc gets mapped more than 2GiB away from the main executable so a call rel32 can't reach it.

See also Can't call C standard library function on 64-bit Linux from assembly (yasm) code, which shows AT&T and NASM syntax for calling libc functions from a PIE executable, either via the PLT call puts@plt or gcc -fno-plt style with call *puts@gotpcrel(%rip).

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Thank you for those links, those completely explained that concisely! – cradical Aug 28 '19 at 21:45
  • As for the updating of the original post, I was attempting to create a valid example (as opposed to the one I had originally that invoked swapcontext), and provide not just the disassembled output, but the eventual failure I ran into it as well. Thank you for your patience! – cradical Aug 28 '19 at 21:47
2

You appear to be disassembling an object file with relocations.

Relocations are stubs for the linker to resolve when the file is loaded.

To properly view the relocations and symbol names, use objdump -dr test or objdump -dR test.

The output will be similar to this:

0000000000000000 <foo>:
   0:   e8 00 00 00 00          callq  5 <foo+0x5>
                        1: R_X86_64_PLT32       swapcontext-0x4

You may also consider adding a ret instruction at the end of foo, just in case swapcontext errors.

As shown by your objdump -dR output, both of these refer to libc functions:

            670: R_X86_64_PC32  swapcontext@GLIBC_2.2.5-0x4
        # 200fd0 <swapcontext@GLIBC_2.2.5>
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76