I just discovered that shared libraries also have got start address
:
objdump -f /usr/lib/libTH.so
/usr/lib/libTH.so: file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000026e60
It is clear what it does mean for executable, but what is it for shared objects?
Just as in a program, the start address (a.k.a entry point address) of a shared library is simply
the start address of the .text
segment, containing all the executable
code.
Here's a toy shared library too illustrate:
foo.c
#include <stdio.h>
void foo(void)
{
printf(__func__);
}
Compile and link:
$ gcc -Wall -Wextra -fPIC -c foo.c
$ gcc -shared -o libfoo.so foo.o -Wl,-Map=libfoo.map
Let's see its start address:
$ objdump -f libfoo.so
libfoo.so: file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000000530
We requested a linker map file, libfoo.map
, when we linked the SO. Here's
the .text
section from that map file:
.text 0x0000000000000530 0xf2
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
.text 0x0000000000000530 0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
.text 0x0000000000000530 0xda /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
.text 0x000000000000060a 0x18 foo.o
0x000000000000060a foo
.text 0x0000000000000622 0x0 /usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o
.text 0x0000000000000622 0x0 /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
*(.gnu.warning)
As per objdump
, it starts at address 0x530. It is 0xf2 bytes long. From the five
files that the linker loaded:
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o
foo.o
/usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
The input .text
section of crti.o
was empty and contributed 0 bytes.
Then crtbeginS.o
contributed 0xda bytes, but no symbols. Then foo.o
contributed 0x18 bytes at address 0x60a, including the symbol foo
. Then
crtendS.o
and crtn.o
each contributed 0 bytes. 0xda + 0x18 = 0xf2. (The
files that had empty .text
sections will have contributed something to
other output sections, not shown).
So, at the start address of the library we find the code crtbeginS.o
,
which is C runtime initialization code - the shared library version -
for finding global constructor functions (i.e. constructors of any C++
global objects or C functions qualified
with __attribute((constructor))
). See this question and answer.
In summary, the start address of the shared library enters that library's contribution to the runtime initialization of the program with which it is dynamically linked.
User contributions licensed under CC BY-SA 3.0