Didier Kryn <kryn@???> writes:
> Le 25/07/2016 23:35, fsmithred a écrit :
>> Either way, it
>> looks like libsystemd is passively providing code for something else to
>> use.
> Calling a function does not mean that this function passively
> provides code to the caller.
But the library does that (or at least, that's how its function could be
described). After compiling the following program,
----
#include <stdio.h>
int main(void)
{
puts("Hello?");
return 0;
}
-----
the resulting ELF binary records the name of the C library in its
DT_NEEDED section,
[rw@doppelsaurus]/tmp#objdump -p a.out | grep NEEDED
NEEDED libc.so.6
and its symbol table contains an 'undefined' entry for puts
[rw@doppelsaurus]/tmp#objdump --syms a.out | grep puts
0000000000000000 F *UND* 0000000000000000 puts@@GLIBC_2.2.5
When starting the program, the dynamic linker loads the needed libraries
and then tries to resolve any undefind symbols:
[rw@doppelsaurus]/tmp#LD_DEBUG=libs,symbols,bindings ./a.out 2>&1
3922: find library=libc.so.6 [0]; searching
3922: search cache=/etc/ld.so.cache
3922: trying file=/lib/x86_64-linux-gnu/libc.so.6
[...]
3922: symbol=puts; lookup in file=./a.out [0]
3922: symbol=puts; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
3922: binding file ./a.out [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `puts' [GLIBC_2.2.5]
This means in order to start the program, both the library file and the
actual symbol definition is needed. The dynamic symbol table of the
library provides the address of the entry point in the function,
[rw@doppelsaurus]/tmp#objdump -T /lib/x86_64-linux-gnu/libc.so.6 | grep puts
0000000000068e90 g DF .text 00000000000001b2 GLIBC_2.2.5 _IO_puts
0000000000068e90 w DF .text 00000000000001b2 GLIBC_2.2.5 puts
And this address is then used to 'connect' calls made by the program to
the code provided by the library. The code of the function can be found
by running
objdump -d /lib/x86_64-linux-gnu/libc.so.6 | less
and searching for address recorded in the dynamic symbol table (with
leading zeroes omitted, ie, 68e90).
> What happens is (simplified) the program
> counter (the address from which instructions are fetched) jumps to the
> called function, and, when the function has finished execution
> (encountering the return instruction, returns to the caller, just one
> instruction after the initial jump.
This is what happens after the program was started if a from the library
is actually called. The following program
------
#include <stdio.h>
int main(void)
{
printf("%p\n", puts);
return 0;
}
-------
uses the puts symbol without calling the function.
A program may also load a library (shared object, actually) at run time
and perform all these steps with explictly written code instead of
relying on the dynamic linker (containing similar code).