指定 ELF 的装载位置
在 Linux 下,可指定 ELF 的装载位置,包括可执行程序和共享库。这在一定程度上给了程序员控制进程空间地址分配的能力。
1 2 3 4 5 6 7 8 | // test.cc #include <stdio.h> int main(int argc, const char* argv[]) { printf("%s\n", __func__); while(1) {} return 0; } |
1 2 3 4 5 6 7 | // liba.cc #include <stdio.h> __attribute__((constructor)) static void liba_init() { printf("%s\n", __func__); } |
直接编译并运行,其内存地址映射如下:
1 2 | $ gcc test.c -o a.out $ gcc liba.c -o liba.so -fPIE -shared |
1 2 3 4 | $ LD_PRELOAD=liba.so ./a.out& [2] 125787 liba_init main |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | $ pmap -x 125787 125787: ./a.out Address Kbytes RSS Dirty Mode Mapping 0000000000400000 4 4 0 r-x-- a.out 0000000000600000 4 4 4 r---- a.out 0000000000601000 4 4 4 rw--- a.out 00007fe1c17dc000 1784 848 0 r-x-- libc-2.19.so 00007fe1c199a000 2048 0 0 ----- libc-2.19.so 00007fe1c1b9a000 16 16 16 r---- libc-2.19.so 00007fe1c1b9e000 8 8 8 rw--- libc-2.19.so 00007fe1c1ba0000 20 12 12 rw--- [ anon ] 00007fe1c1ba5000 4 4 0 r-x-- liba.so 00007fe1c1ba6000 2044 0 0 ----- liba.so 00007fe1c1da5000 4 4 4 r---- liba.so 00007fe1c1da6000 4 4 4 rw--- liba.so 00007fe1c1da7000 140 140 0 r-x-- ld-2.19.so 00007fe1c1fb0000 12 12 12 rw--- [ anon ] 00007fe1c1fc7000 8 8 8 rw--- [ anon ] 00007fe1c1fc9000 4 4 4 r---- ld-2.19.so 00007fe1c1fca000 4 4 4 rw--- ld-2.19.so 00007fe1c1fcb000 4 4 4 rw--- [ anon ] 00007ffdc3a70000 136 16 16 rw--- [ stack ] 00007ffdc3be9000 8 4 0 r-x-- [ anon ] 00007ffdc3beb000 8 0 0 r---- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------- ------- ------- total kB 6272 1100 100 |
编译时通过 linker 分别指定装载位置,观察运行时的内存地址映射:
1 2 | $ gcc test.c -o a.out -Wl,-Ttext-segment=0x40000000 $ gcc liba.c -o liba.so -fPIE -shared -Wl,-Ttext-segment=0x20000000 |
1 2 3 4 | $ LD_PRELOAD=liba.so ./a.out& [1] 85460 liba_init main |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | $ pmap -x 85460 85460: ./a.out Address Kbytes RSS Dirty Mode Mapping 0000000020000000 4 4 0 r-x-- liba.so 0000000020001000 2044 0 0 ----- liba.so 0000000020200000 4 4 4 r---- liba.so 0000000020201000 4 4 4 rw--- liba.so 0000000040000000 4 4 0 r-x-- a.out 0000000040200000 4 4 4 r---- a.out 0000000040201000 4 4 4 rw--- a.out 00007faac8c62000 1784 888 0 r-x-- libc-2.19.so 00007faac8e20000 2048 0 0 ----- libc-2.19.so 00007faac9020000 16 16 16 r---- libc-2.19.so 00007faac9024000 8 8 8 rw--- libc-2.19.so 00007faac9026000 20 12 12 rw--- [ anon ] 00007faac902b000 140 140 0 r-x-- ld-2.19.so 00007faac9234000 12 12 12 rw--- [ anon ] 00007faac924b000 8 8 8 rw--- [ anon ] 00007faac924d000 4 4 4 r---- ld-2.19.so 00007faac924e000 4 4 4 rw--- ld-2.19.so 00007faac924f000 4 4 4 rw--- [ anon ] 00007ffcf0833000 136 16 16 rw--- [ stack ] 00007ffcf0978000 8 4 0 r-x-- [ anon ] 00007ffcf097a000 8 0 0 r---- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------- ------- ------- total kB 6272 1140 100 |
可以看到,可执行程序 a.out 和 共享库 liba.so 均按指定的位置被装载。