Issue
With help of dl_iterate_phdr I can load start address of main executable and all binaries via dlpi_addr
and it is correlates to function pointers address I can print via printf, however other fields , such as p_offset
p_vaddr
p_paddr
p_memsz
and even p_filesz
show me very small numbers for my case (my executable is 1.7G alone as well as tons of dependencies).
For reference this is what kind of output I do get when I print with following string for 64bit PIE executable for dlpi_addr dlpi_name dlpi_phdr.p_offset dlpi_phdr.p_vaddr dlpi_phdr.p_paddr dlpi_phdr.p_memsz dlpi_phdr.p_filesz
"sec 0x%lx %s %ld %ld %ld %ld %ld \n\0"
sec 0x55bf2722f000 64 64 64 784 784
sec 0x7fff8a3ea000 linux-vdso.so.1 0 0 0 4079 4079
sec 0x7f03ce15d000 /lib/x86_64-linux-gnu/libgstplayer-1.0.so.0 0 0 0 21128 21128
sec 0x7f03ce08b000 /lib/x86_64-linux-gnu/libgstvideo-1.0.so.0 0 0 0 108632 108632
sec 0x7f03ce004000 /lib/x86_64-linux-gnu/libgstbase-1.0.so.0 0 0 0 57520 57520
sec 0x7f03cdeae000 /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0 0 0 0 192512 192512
sec 0x7f03cde4d000 /lib/x86_64-linux-gnu/libgobject-2.0.so.0 0 0 0 59216 59216
sec 0x7f03cdd05000 /lib/x86_64-linux-gnu/libglib-2.0.so.0 0 0 0 119968 119968
sec 0x7f03cdcf2000 /lib/x86_64-linux-gnu/libgstwebrtc-1.0.so.0 0 0 0 16776 16776
sec 0x7f03cdcd7000 /lib/x86_64-linux-gnu/libgstsdp-1.0.so.0 0 0 0 20248 20248
sec 0x7f03cdc54000 /lib/x86_64-linux-gnu/libgstaudio-1.0.so.0 0 0 0 64008 64008
sec 0x7f03cdc3e000 /lib/x86_64-linux-gnu/libgstapp-1.0.so.0 0 0 0 15208 15208
sec 0x7f03cdbb6000 /lib/x86_64-linux-gnu/libgstgl-1.0.so.0 0 0 0 92984 92984
sec 0x7f03cd9c7000 /lib/x86_64-linux-gnu/libgio-2.0.so.0 0 0 0 236080 236080
sec 0x7f03cd600000 /lib/x86_64-linux-gnu/libstdc++.so.6 0 0 0 637488 637488
sec 0x7f03cd9a8000 /lib/x86_64-linux-gnu/libz.so.1 0 0 0 8832 8832
...and more
and here is elf executable objdump section list
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000000350 0000000000000350 00000350 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.property 00000020 0000000000000370 0000000000000370 00000370 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 0000000000000390 0000000000000390 00000390 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .note.ABI-tag 00000020 00000000000003b4 00000000000003b4 000003b4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 00000624 00000000000003d8 00000000000003d8 000003d8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 000059a0 0000000000000a00 0000000000000a00 00000a00 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 00004e8a 00000000000063a0 00000000000063a0 000063a0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000778 000000000000b22a 000000000000b22a 0000b22a 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 000002c0 000000000000b9a8 000000000000b9a8 0000b9a8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00552480 000000000000bc68 000000000000bc68 0000bc68 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 00001290 000000000055e0e8 000000000055e0e8 0055e0e8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000017 0000000000560000 0000000000560000 00560000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 00000c70 0000000000560020 0000000000560020 00560020 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .plt.got 00000288 0000000000560c90 0000000000560c90 00560c90 2**3
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .text 03693fac 0000000000560f40 0000000000560f40 00560f40 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .fini 00000009 0000000003bf4eec 0000000003bf4eec 03bf4eec 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
16 .rodata 01f5cd20 0000000003bf5000 0000000003bf5000 03bf5000 2**12
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .debug_gdb_scripts 00000022 0000000005b51d20 0000000005b51d20 05b51d20 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .eh_frame_hdr 0012f7a4 0000000005b51d44 0000000005b51d44 05b51d44 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
19 .eh_frame 00755710 0000000005c814e8 0000000005c814e8 05c814e8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
20 .gcc_except_table 002634a8 00000000063d6bf8 00000000063d6bf8 063d6bf8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
21 .tdata 00005398 000000000663b740 000000000663b740 0663a740 2**3
CONTENTS, ALLOC, LOAD, DATA, THREAD_LOCAL
22 .tbss 00000a00 0000000006640ad8 0000000006640ad8 0663fad8 2**3
ALLOC, THREAD_LOCAL
23 .init_array 00000090 0000000006640ad8 0000000006640ad8 0663fad8 2**3
CONTENTS, ALLOC, LOAD, DATA
24 .fini_array 00000008 0000000006640b68 0000000006640b68 0663fb68 2**3
CONTENTS, ALLOC, LOAD, DATA
25 .data.rel.ro 00367708 0000000006640b70 0000000006640b70 0663fb70 2**4
CONTENTS, ALLOC, LOAD, DATA
26 .dynamic 00000360 00000000069a8278 00000000069a8278 069a7278 2**3
CONTENTS, ALLOC, LOAD, DATA
27 .got 0001ba20 00000000069a85d8 00000000069a85d8 069a75d8 2**3
CONTENTS, ALLOC, LOAD, DATA
28 .data 00037c58 00000000069c4000 00000000069c4000 069c3000 2**4
CONTENTS, ALLOC, LOAD, DATA
29 .bss 026a5348 00000000069fbc80 00000000069fbc80 069fac58 2**7
ALLOC
30 .comment 0000006b 0000000000000000 0000000000000000 069fac58 2**0
CONTENTS, READONLY
31 .debug_aranges 00420190 0000000000000000 0000000000000000 069facc3 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
32 .debug_pubnames 08936c54 0000000000000000 0000000000000000 06e1ae53 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
33 .debug_info 1df05433 0000000000000000 0000000000000000 0f751aa7 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
34 .debug_abbrev 00442a52 0000000000000000 0000000000000000 2d656eda 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
35 .debug_line 0423eb3e 0000000000000000 0000000000000000 2da9992c 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
36 .debug_str 0b447666 0000000000000000 0000000000000000 31cd846a 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
37 .debug_loc 123b4882 0000000000000000 0000000000000000 3d11fad0 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
38 .debug_pubtypes 0cce2c03 0000000000000000 0000000000000000 4f4d4352 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
39 .debug_ranges 07b1f340 0000000000000000 0000000000000000 5c1b6f55 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
40 .debug_addr 0000d840 0000000000000000 0000000000000000 63cd6295 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
41 .debug_line_str 00001f90 0000000000000000 0000000000000000 63ce3ad5 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
42 .debug_loclists 00039d5e 0000000000000000 0000000000000000 63ce5a65 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
43 .debug_rnglists 00009afd 0000000000000000 0000000000000000 63d1f7c3 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
44 .debug_str_offsets 0001c6c0 0000000000000000 0000000000000000 63d292c0 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
So, whats up with all these tiny numbers and how do I get proper with linux api?
For reference the existing answer How do you detect the size of a dynamic library(shared object) in the current process? suggest to parse /proc/self/maps which is kind of silly and this one Getting the ELF header of the main executable only shows start address which I already have
I tried dladdr as well dladdr1 to load some info, i was loaded file sections with of /proc/self/exe in various ways, but i dont see how output of dl_iterate_phdr can let me correlate it info to third party libs
Update: Here is output of readelf utility
Elf file type is DYN (Position-Independent Executable file)
Entry point 0x6cfe20
There are 14 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x000310 0x000310 R 0x8
INTERP 0x000350 0x0000000000000350 0x0000000000000350 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x55f378 0x55f378 R 0x1000
LOAD 0x560000 0x0000000000560000 0x0000000000560000 0x3694ef5 0x3694ef5 R E 0x1000
LOAD 0x3bf5000 0x0000000003bf5000 0x0000000003bf5000 0x2a450a0 0x2a450a0 R 0x1000
LOAD 0x663a740 0x000000000663b740 0x000000000663b740 0x3c0518 0x2a65888 RW 0x1000
DYNAMIC 0x69a7278 0x00000000069a8278 0x00000000069a8278 0x000360 0x000360 RW 0x8
NOTE 0x000370 0x0000000000000370 0x0000000000000370 0x000020 0x000020 R 0x8
NOTE 0x000390 0x0000000000000390 0x0000000000000390 0x000044 0x000044 R 0x4
TLS 0x663a740 0x000000000663b740 0x000000000663b740 0x005398 0x005d98 R 0x8
GNU_PROPERTY 0x000370 0x0000000000000370 0x0000000000000370 0x000020 0x000020 R 0x8
GNU_EH_FRAME 0x5b51d44 0x0000000005b51d44 0x0000000005b51d44 0x12f7a4 0x12f7a4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x663a740 0x000000000663b740 0x000000000663b740 0x3888c0 0x3888c0 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
03 .init .plt .plt.got .text .fini
04 .rodata .debug_gdb_scripts .eh_frame_hdr .eh_frame .gcc_except_table
05 .tdata .init_array .fini_array .data.rel.ro .dynamic .got .data .bss
06 .dynamic
07 .note.gnu.property
08 .note.gnu.build-id .note.ABI-tag
09 .tdata .tbss
10 .note.gnu.property
11 .eh_frame_hdr
12
13 .tdata .init_array .fini_array .data.rel.ro .dynamic .got
Im using rust bindings, but answer in c/c++/whatever-calling-libc is appreciated
libc::dl_iterate_phdr(Some(collect_objs), std::ptr::null_mut());
unsafe extern "C" fn collect_objs(
info: *mut dl_phdr_info,
_sz: usize,
data: *mut c_void,
) -> c_int {
libc::printf("sec 0x%lx %s %ld %ld %ld %ld %ld \n\0".as_bytes().as_ptr() as *const i8,
(*info).dlpi_addr,
(*info).dlpi_name,
(*(*info).dlpi_phdr).p_offset,
(*(*info).dlpi_phdr).p_vaddr,
(*(*info).dlpi_phdr).p_paddr,
(*(*info).dlpi_phdr).p_memsz,
(*(*info).dlpi_phdr).p_filesz);
0
}
Solution
It turns out name of function describes what function doing internally and not describing what it returns and in reality instead of dl_iterate_phdr
should be called dl_iterate_objects
, because in callback as stated by documentation it returns you (surprise surprise) shared object, which are executable/lib and not section headers themselve. The name of variables it returns p_memsz
is not actually a pointer/pointer offset to a memory object somewhere as you might think from its name but a size of a section, but an actual size, regarless if other field of structure is actuall pointers as mentioned in manual, and dlpi_phnum
is not a number of current section but length of array of sections.
The documentation is contradictionary between names of things and what the things are actually going which leaded me to load first section of object and (which was header section) and get surprised why its so small relative to executable size, and i should looked at example at the bottom of manual to understand what it actually returning instead of piecing together a puzzle of what this api actually is
Here is the code output from example program from manual
#define _GNU_SOURCE
#include <link.h>
#include <stdlib.h>
#include <stdio.h>
static int
callback(struct dl_phdr_info *info, size_t size, void *data)
{
char *type;
int p_type, j;
printf("Name: \"%s\" (%d segments)\n", info->dlpi_name,
info->dlpi_phnum);
for (j = 0; j < info->dlpi_phnum; j++) {
p_type = info->dlpi_phdr[j].p_type;
type = (p_type == PT_LOAD) ? "PT_LOAD" :
(p_type == PT_DYNAMIC) ? "PT_DYNAMIC" :
(p_type == PT_INTERP) ? "PT_INTERP" :
(p_type == PT_NOTE) ? "PT_NOTE" :
(p_type == PT_INTERP) ? "PT_INTERP" :
(p_type == PT_PHDR) ? "PT_PHDR" :
(p_type == PT_TLS) ? "PT_TLS" :
(p_type == PT_GNU_EH_FRAME) ? "PT_GNU_EH_FRAME" :
(p_type == PT_GNU_STACK) ? "PT_GNU_STACK" :
(p_type == PT_GNU_RELRO) ? "PT_GNU_RELRO" : NULL;
printf(" %2d: [%14p; memsz:%7lx] flags: 0x%x; ", j,
(void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr),
info->dlpi_phdr[j].p_memsz,
info->dlpi_phdr[j].p_flags);
if (type != NULL)
printf("%s\n", type);
else
printf("[other (0x%x)]\n", p_type);
}
return 0;
}
int
main(int argc, char *argv[])
{
dl_iterate_phdr(callback, NULL);
exit(EXIT_SUCCESS);
}
and output for it for huge executable im running
Name: "" (14 segments)
0: [0x563b1048e040; memsz: 310] flags: 0x4; PT_PHDR
1: [0x563b1048e350; memsz: 1c] flags: 0x4; PT_INTERP
2: [0x563b1048e000; memsz: 55f180] flags: 0x4; PT_LOAD
3: [0x563b109ee000; memsz:36936b5] flags: 0x5; PT_LOAD
4: [0x563b14082000; memsz:2a44490] flags: 0x4; PT_LOAD
5: [0x563b16ac78e0; memsz:2a656e8] flags: 0x6; PT_LOAD
6: [0x563b16e342a8; memsz: 360] flags: 0x6; PT_DYNAMIC
7: [0x563b1048e370; memsz: 20] flags: 0x4; PT_NOTE
8: [0x563b1048e390; memsz: 44] flags: 0x4; PT_NOTE
9: [0x563b16ac78e0; memsz: 5d98] flags: 0x4; PT_TLS
10: [0x563b1048e370; memsz: 20] flags: 0x4; [other (0x6474e553)]
11: [0x563b15fded44; memsz: 12f6c4] flags: 0x4; PT_GNU_EH_FRAME
12: [0x563b1048e000; memsz: 0] flags: 0x6; PT_GNU_STACK
13: [0x563b16ac78e0; memsz: 388720] flags: 0x4; PT_GNU_RELRO
Name: "linux-vdso.so.1" (4 segments)
0: [0x7ffe23dbc000; memsz: fef] flags: 0x5; PT_LOAD
1: [0x7ffe23dbc3e0; memsz: 120] flags: 0x4; PT_DYNAMIC
2: [0x7ffe23dbc500; memsz: 60] flags: 0x4; PT_NOTE
3: [0x7ffe23dbc560; memsz: 4c] flags: 0x4; PT_GNU_EH_FRAME
Name: "/lib/x86_64-linux-gnu/libgstplayer-1.0.so.0" (9 segments)
0: [0x7ff5f2572000; memsz: 5288] flags: 0x4; PT_LOAD
1: [0x7ff5f2578000; memsz: 6261] flags: 0x5; PT_LOAD
2: [0x7ff5f257f000; memsz: 443c] flags: 0x4; PT_LOAD
3: [0x7ff5f2584750; memsz: b60] flags: 0x6; PT_LOAD
4: [0x7ff5f25848e0; memsz: 250] flags: 0x6; PT_DYNAMIC
5: [0x7ff5f2572238; memsz: 24] flags: 0x4; PT_NOTE
6: [0x7ff5f2580fc0; memsz: 64c] flags: 0x4; PT_GNU_EH_FRAME
7: [0x7ff5f2572000; memsz: 0] flags: 0x6; PT_GNU_STACK
8: [0x7ff5f2584750; memsz: 8b0] flags: 0x4; PT_GNU_RELRO
Name: "/lib/x86_64-linux-gnu/libgstvideo-1.0.so.0" (9 segments)
0: [0x7ff5f24a0000; memsz: 1a858] flags: 0x4; PT_LOAD
1: [0x7ff5f24bb000; memsz: 73271] flags: 0x5; PT_LOAD
2: [0x7ff5f252f000; memsz: 2f4f4] flags: 0x4; PT_LOAD
3: [0x7ff5f255f870; memsz: 118e8] flags: 0x6; PT_LOAD
4: [0x7ff5f256ee20; memsz: 250] flags: 0x6; PT_DYNAMIC
5: [0x7ff5f24a0238; memsz: 24] flags: 0x4; PT_NOTE
6: [0x7ff5f2545d08; memsz: 2e14] flags: 0x4; PT_GNU_EH_FRAME
7: [0x7ff5f24a0000; memsz: 0] flags: 0x6; PT_GNU_STACK
8: [0x7ff5f255f870; memsz: 10790] flags: 0x4; PT_GNU_RELRO
Name: "/lib/x86_64-linux-gnu/libgstbase-1.0.so.0" (9 segments)
0: [0x7ff5f2419000; memsz: e0b0] flags: 0x4; PT_LOAD
1: [0x7ff5f2428000; memsz: 54c5d] flags: 0x5; PT_LOAD
2: [0x7ff5f247d000; memsz: 20650] flags: 0x4; PT_LOAD
3: [0x7ff5f249e9f0; memsz: 1450] flags: 0x6; PT_LOAD
4: [0x7ff5f249ece8; memsz: 220] flags: 0x6; PT_DYNAMIC
5: [0x7ff5f2419238; memsz: 24] flags: 0x4; PT_NOTE
6: [0x7ff5f248d9c4; memsz: 153c] flags: 0x4; PT_GNU_EH_FRAME
7: [0x7ff5f2419000; memsz: 0] flags: 0x6; PT_GNU_STACK
8: [0x7ff5f249e9f0; memsz: 610] flags: 0x4; PT_GNU_RELRO
...and more
Answered By - Igor B Answer Checked By - Marie Seifert (WPSolving Admin)