gPXE memory layout
Currently the linker script for each arch is locate at:
src/arch/x86/scripts/efi.lds
src/arch/i386/scripts/i386-kir.lds
src/arch/i386/scripts/i386.lds
We can reference src/arch/i386/README.i386
for the difference
between i386-kir.lds
and i386.lds
, the efi.lds
should
be obvious as its file name that is for Extensible Firmware Interface
(EFI). In this note we take the binary linked against
src/arch/i386/scripts/i386.lds
linker script for instance.
To see the memory layout of an target image, for instance gpxe.pxe
,
the all driver PXE loadable image. Use one of the following command:
- objdump -h bin/gpxe.pxe.tmp
- readelf -S bin/gpxe.pxe.tmp
It can tell you each section's size and where it will put in the memory while execution(VMA).
objdump -h bin/gpxe.pxe.tmp
bin/gpxe.pxe.tmp: file format elf32-i386 Sections: Idx Name Size VMA LMA File off Algn 0 .prefix 0000081a 00000000 00000000 00000160 2**4 CONTENTS, ALLOC, LOAD, CODE 1 .text16 00000854 00000000 00000820 00000980 2**4 CONTENTS, ALLOC, LOAD, CODE 2 .data16 000004a2 00000000 00001080 000011e0 2**4 CONTENTS, ALLOC, LOAD, DATA 3 .bss.data16 000029a0 000004a8 000963f0 00096540 2**3 ALLOC 4 .textdata 00094e7c 00000000 00001530 00001684 2**2 CONTENTS, ALLOC, LOAD, CODE 5 .bss.textdata 00058b68 00094e80 000963f0 00096580 2**7 ALLOC 6 .zinfo 00000040 00000000 000963b0 00096500 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .debug_abbrev 000346c3 00000000 00000000 00096540 2**0 CONTENTS, READONLY, DEBUGGING 8 .debug_info 002274b7 00000000 00000000 000cac03 2**0 CONTENTS, READONLY, DEBUGGING 9 .debug_line 000384b6 00000000 00000000 002f20ba 2**0 CONTENTS, READONLY, DEBUGGING 10 .debug_frame 0001953c 00000000 00000000 0032a570 2**2 CONTENTS, READONLY, DEBUGGING 11 .debug_loc 00091542 00000000 00000000 00343aac 2**0 CONTENTS, READONLY, DEBUGGING 12 .debug_pubnames 0000fffd 00000000 00000000 003d4fee 2**0 CONTENTS, READONLY, DEBUGGING 13 .debug_aranges 00002460 00000000 00000000 003e4feb 2**0 CONTENTS, READONLY, DEBUGGING 14 .debug_ranges 00006f58 00000000 00000000 003e744b 2**0 CONTENTS, READONLY, DEBUGGING 15 .debug_str 0003c4ef 00000000 00000000 003ee3a3 2**0 CONTENTS, READONLY, DEBUGGING
To see each symbol's memory location, use one of the following command:
- objdump -t bin/gpxe.pxe.tmp
- readelf -s bin/gpxe.pxe.tmp
objdump -t bin/gpxe.pxe.tmp | sort -k1 | tail -n 30
000ec9e4 g O .bss.textdata 00000000 .hidden obj_dhcppkt 000ec9e4 g O .bss.textdata 00000000 .hidden obj_eapol 000ec9e4 g O .bss.textdata 00000000 .hidden obj_editstring 000ec9e4 g O .bss.textdata 00000000 .hidden obj_hmac 000ec9e4 g O .bss.textdata 00000000 .hidden obj_ib_mcast 000ec9e4 g O .bss.textdata 00000000 .hidden obj_ib_pathrec 000ec9e4 g O .bss.textdata 00000000 .hidden obj_icmp 000ec9e4 g O .bss.textdata 00000000 .hidden obj_iwmgmt 000ec9e4 g O .bss.textdata 00000000 .hidden obj_iwmgmt_cmd 000ec9e4 g O .bss.textdata 00000000 .hidden obj_job 000ec9e4 g O .bss.textdata 00000000 .hidden obj_linebuf 000ec9e4 g O .bss.textdata 00000000 .hidden obj_monojob 000ec9e4 g O .bss.textdata 00000000 .hidden obj_readline 000ec9e4 g O .bss.textdata 00000000 .hidden obj_sec80211 000ec9e4 g O .bss.textdata 00000000 .hidden obj_sha1 000ec9e4 g O .bss.textdata 00000000 .hidden obj_sha1extra 000ec9e4 g O .bss.textdata 00000000 .hidden obj_smbios 000ec9e4 g O .bss.textdata 00000000 .hidden obj_tcp 000ec9e4 g O .bss.textdata 00000000 .hidden obj_wep 000ec9e4 g O .bss.textdata 00000000 .hidden obj_wpa 000ec9e4 g O .bss.textdata 00000000 .hidden obj_wpa_ccmp 000ec9e4 g O .bss.textdata 00000000 .hidden obj_wpa_psk 000ec9e4 g O .bss.textdata 00000000 .hidden obj_wpa_tkip 000ec9e8 g .bss.textdata 00000000 _stack 000ed9e8 g *ABS* 00000000 _textdata_memsz 000ed9e8 g .bss.textdata 00000000 _estack 000ed9e8 g .bss.textdata 00000000 .hidden _etextdata 00400000 g *ABS* 00000000 HIGHMEM_LOADPOINT bin/gpxe.pxe.tmp: file format elf32-i386 SYMBOL TABLE:
Memory usage
We can see the current memory usage by the symbols exported by linker. Which is defined in the linker script mentioned in the previours section.
For i386.lds
, if we want to know how much memory
was used. We can simply check for _etextdata, or _stack.
The heap was declared as globle variable in src/core/malloc.c
,
which would put in bss section. We can get its address by:
objdump -t bin/gpxe.pxe.tmp | grep ' heap$'
000b3c5c l O .bss.textdata 00020000 heap
As long as the _stack plus real stack usage at runtime dose not exceed 1MB, we should be safe.
We can also exam the what symbol cost most memory size by:
readelf -W -s bin/gpxe.pxe.tmp | sort -n -k 3 | tail
463: 0007c7a4 6104 OBJECT LOCAL DEFAULT 5 bnx2_rv2p_proc2 1337: 000a505c 6320 OBJECT LOCAL DEFAULT 6 rxb 3869: 00091738 8192 OBJECT GLOBAL HIDDEN 5 linda_ib_fw 1351: 000a6f4c 9084 OBJECT LOCAL DEFAULT 6 rx_buffer 391: 00094e9c 9348 OBJECT LOCAL DEFAULT 6 amd8111e 469: 00083838 22348 OBJECT LOCAL DEFAULT 5 bnx2_TXP_b06FwText 479: 0008a1b4 22464 OBJECT LOCAL DEFAULT 5 bnx2_COM_b06FwText 464: 0007df7c 22672 OBJECT LOCAL DEFAULT 5 bnx2_RXP_b06FwText 461: 00099874 41848 OBJECT LOCAL DEFAULT 6 bnx2_bss 1344: 000a92c8 43064 OBJECT LOCAL DEFAULT 6 virtqueue
The number bigger than 5 digits in decimal, were displayed as hex.
readelf -W -s bin/gpxe.pxe.tmp | grep ' 0x[0-9]\+ '
2052: 000b3c5c 0x20000 OBJECT LOCAL DEFAULT 6 heap 3141: 000d4100 0x18808 OBJECT GLOBAL HIDDEN 6 _shared_bss