0

A simple c function.

void sum ()
{
    return ;
}

Command

gcc -c -m32 -o simple simpleProg.c -O0 && objdump -d simple -M intel

simple:     file format elf32-i386


Disassembly of section .text:

00000000 <sum>:
   0:   f3 0f 1e fb             endbr32 
   4:   55                      push   ebp
   5:   89 e5                   mov    ebp,esp
   7:   e8 fc ff ff ff          call   8 <sum+0x8> --->This
   c:   05 01 00 00 00          add    eax,0x1
  11:   90                      nop
  12:   5d                      pop    ebp
  13:   c3                      ret    

What does this call 8 statement do here? Also do void need to return as 0x01 in eax?

Sreeraj Chundayil
  • 5,548
  • 3
  • 29
  • 68

1 Answers1

3

You're actually looking at the code before fixups have been applied to it (something typically done during the link phase). If you add -r to see the relocation entries, you'll see this (I don't get the endbr32 but that's probably because I'm running with an older compiler):

00000000 <sum>:
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   e8 fc ff ff ff          call   4 <sum+0x4>
                        4: R_386_PC32   __x86.get_pc_thunk.ax
   8:   05 01 00 00 00          add    eax,0x1
                        9: R_386_GOTPC  _GLOBAL_OFFSET_TABLE_
   d:   90                      nop
   e:   5d                      pop    ebp
   f:   c3                      ret

Disassembly of section .text.__x86.get_pc_thunk.ax:

00000000 <__x86.get_pc_thunk.ax>:
   0:   8b 04 24                mov    eax,DWORD PTR [esp]
   3:   c3                      ret

At fixup time, line 3 will actually be modified to call __x86.get_pc_thunk.ax (using relative address since e8 is a relative call). This function effectively loads eax with the return address (the bytes starting at line 8).

Line 8 is also fixed up so that, rather than adding one, it adds the global offset table (GOT) "relative to PC" address. So, after all that, eax contains the absolute address of the global offset table, so you can call whatever functions you want from there.


So, bottom line, it's not actually calling the address it appears to be calling. That would be starting to run code mid-instruction which, unless you know what you're doing, is generally a bad thing :-)

It's also not specifically loading up eax with the return code. What it's doing is preparing to be able to access the GOT from the function, despite the fact it's not actually going to use it.

Instead, it throws all that information away and exits, leaving eax holding some arbitrary value, since the void function doesn't care. Were you to actually call a function such as puts("Hello"), you would see it using this value to locate the correct address for the puts function.

It's a near certainty that, if you cranked up the optimisation level, a lot of this (unnecessary) code would disappear.

For a deeper overview on the GOT (and the procedure linkage table, or PLT), see this answer, posted by some incredibly smart and good-looking person many moons ago :-)

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953