0

I wrote the following 2 programs using C:

First:

int foo(int x)
{
    return 1;
}

int main()
{
    return foo(4);
}

Second:

static int foo(int x)
{
    return 1;
}

int main()
{
    return foo(4);
}

Then I ran:

gcc -c my_file.c

For the first file I saw (Not full output):

000000000000000e <main>:
   e:   55                      push   %rbp
   f:   48 89 e5                mov    %rsp,%rbp
  12:   bf 04 00 00 00          mov    $0x4,%edi
  17:   e8 00 00 00 00          callq  1c <main+0xe>
  1c:   5d                      pop    %rbp
  1d:   c3                      retq   

And for the second:

000000000000000e <main>:
   e:   55                      push   %rbp
   f:   48 89 e5                mov    %rsp,%rbp
  12:   bf 04 00 00 00          mov    $0x4,%edi
  17:   e8 e4 ff ff ff          callq  0 <foo>
  1c:   5d                      pop    %rbp
  1d:   c3                      retq   

My question is, why in the first file we needed relocation when the function is defined (and not only declared) in the current file? This sounds too strange to me.

john
  • 35
  • 3

1 Answers1

1

You look at unresolved code.

The first version makes foo() global, and therefore there are entries in appropriate tables, symbols and relocations, not shown in the listing. <Edit>Most probably because the compiler works that way, when it emits a call to a global function, it puts zeroes (or anything else) in the address field. It does not matter that this global function is in the same translation unit. Called with other options or other versions of the compiler or other compilers might yield a different result.</Edit>

In the second version the compiler knows that foo() is local and resolves the call instantly without the need to generate relocation entries.

The calls will be resolved to equal values if you link the program.

<Edit>Interesting: I tried to reproduce this with GCC 8.1.0 (MinGW-W64) on Windows, and both calls are resolved by the compiler. However, with GCC 11.1.0 of the current Manjaro Linux, it shows the described behaviour.</Edit>

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • This doesn't answer my question... In first case why the symbol wasn't resolved it's global right but it's in the current file. – john Aug 18 '21 at 15:59
  • In the case where the symbol is global, it might be overridden later during dynamic linking. So even if the compiler knows the address of foo in *this* translation unit, it can't know whether that's the version of foo that should eventually be called, and has to leave in a relocation for the linker. – knatten Sep 06 '21 at 20:02