add section in ELF file : unexpected section size
Describe the bug I'm trying to add a binary as a section in an existing elf file. my code is
def main():
logging.basicConfig()
logger = logging.getLogger(os.path.basename(__file__))
elffile = lief.parse("input.elf")
if elffile.format != lief.EXE_FORMATS.ELF:
raise Exception('"%s" invalid executable format %s, expected %s'
% (args.inf, elffile.format, lief.EXE_FORMATS.ELF))
return
with open("binary.bin", 'rb') as f:
bin_img = f.read()
new_sec = lief.ELF.Section()
new_sec.name = ".ext_bin"
new_sec.content = bytearray(bin_img)
new_sec.size = len(bin_img)
new_sec.alignment = 4
new_sec.virtual_address = 100000
elffile.add(new_sec, True)
print ('size written : %s' % new_sec.size, 'size expected: %s' % len(bin_img))
elffile.write("out.elf")
read_sec = elffile.get_section(".ext_bin")
print ('size read : %s' % read_sec.size, 'size expected: %s' % new_sec.size)
read_sec.size = len(bin_img)
elffile.write("out.elf")
on console the result is
$ ./test.py
size written : 1900 size expected: 1900
size read : 4096 size expected: 1900
Seems that the new_sec.size is not reported in the out.elf ( readelf -S confirm it).
does the issue come from the elffile.add? or does is a normal behavior ( 4k page alignment forced)?
To Reproduce Steps to reproduce the behavior: explained above
Expected behavior size written : 1900 size expected: 1900 size read : 4096 size expected: 1900
Environment (please complete the following information):
- Ubuntu 20.04
- Target format: ELF
- LIEF commit version:0.11.5-37bc2c9
Additional context The elf file used for my test is generated for arm Cortex-M4 target
Thanks in advance for the help
Hi @arnopo
Yes the +4k when adding a new section is the normal behavior as the loader enforces a relationship between segment VA and offset (c.f the recent blog post: Challenges in Modifying ELF Binaries)
In addition and for the specific case of AArch64, the ADRP instruction also makes this +4k mandatory.
Hi @romainthomas Thanks for your answer! Agree that the elf format is quite tricky...
Does the rule your point out is applicable for all elf files? I'm working on micro-controllers such as Arm Cortex-M architecture... Regarding Zephyr project elf files generated by gcc-arm-none-eabi, seems that this page alignment rule is not respected.
objdump -hw build/zephyr/zephyr_openamp_rsc_table.elf
build/zephyr/zephyr_openamp_rsc_table.elf: file format elf32-little
Sections:
Idx Name Size VMA LMA File off Algn Flags
0 rom_start 00000298 00000000 00000000 000000d4 2**2 CONTENTS, ALLOC, LOAD, CODE
1 text 0000659e 00000298 00000298 0000036c 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .ARM.exidx 00000008 00006838 00006838 0000690c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
3 initlevel 000000a8 00006840 00006840 00006914 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
4 devices 00000198 000068e8 000068e8 000069bc 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
5 sw_isr_table 000004b0 00006a80 00006a80 00006b54 2**2 CONTENTS, ALLOC, LOAD, DATA
6 device_handles 0000008e 00006f30 00006f30 00007004 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA
7 rodata 000005b4 00006fc0 00006fc0 00007094 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .ramfunc 00000000 10000000 10000000 00007860 2**0 CONTENTS
9 datas 00000104 10000000 00007574 00007648 2**2 CONTENTS, ALLOC, LOAD, DATA
10 device_states 00000044 10000104 00007678 0000774c 2**2 CONTENTS, ALLOC, LOAD, DATA
11 k_heap_area 00000014 10000148 000076bc 00007790 2**2 CONTENTS, ALLOC, LOAD, DATA
12 k_sem_area 00000030 1000015c 000076d0 000077a4 2**2 CONTENTS, ALLOC, LOAD, DATA
13 bss 000009eb 10000190 10000190 00007870 2**3 ALLOC
14 noinit 000017c0 10000b80 10000b80 00007870 2**5 ALLOC
15 .comment 0000002e 00000000 00000000 00007860 2**0 CONTENTS, READONLY
16 .debug_aranges 000014e8 00000000 00000000 00007890 2**3 CONTENTS, READONLY, DEBUGGING, OCTETS
17 .debug_info 0004b876 00000000 00000000 00008d78 2**0 CONTENTS, READONLY, DEBUGGING, OCTETS
18 .debug_abbrev 0000ab14 00000000 00000000 000545ee 2**0 CONTENTS, READONLY, DEBUGGING, OCTETS
19 .debug_line 0001b477 00000000 00000000 0005f102 2**0 CONTENTS, READONLY, DEBUGGING, OCTETS
20 .debug_frame 00003198 00000000 00000000 0007a57c 2**2 CONTENTS, READONLY, DEBUGGING, OCTETS
21 .debug_str 0000b18e 00000000 00000000 0007d714 2**0 CONTENTS, READONLY, DEBUGGING, OCTETS
22 .debug_loc 000197ea 00000000 00000000 000888a2 2**0 CONTENTS, READONLY, DEBUGGING, OCTETS
23 .debug_ranges 000057b8 00000000 00000000 000a2090 2**3 CONTENTS, READONLY, DEBUGGING, OCTETS
24 .ARM.attributes 00000033 00000000 00000000 000a7848 2**0 CONTENTS, READONLY
25 .resource_table 0000008c 00007700 00007700 000077d4 2**2 CONTENTS, ALLOC, LOAD, DATA
Sections are not aligned on page but on cache line or memory word size (32 bits in this case). And for this it seems to rely on the alignment property instead of the page alignment.
Yes at least for Linux & Android it is applicable for all the ELF LOAD segments but not necessarily the sections.
Could you add a reference to the Zephyr Project, I'll check if the loader enforces this rule?
Yes at least for Linux & Android it is applicable for all the ELF LOAD segments but not necessarily the sections.
Regarding same elf file:
$ readelf -l build/zephyr/zephyr_openamp_rsc_table.elf
Elf file type is EXEC (Executable file)
Entry point 0x1c0d
There are 5 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x00690c 0x00006838 0x00006838 0x00008 0x00008 R 0x4
LOAD 0x0000d4 0x00000000 0x00000000 0x07574 0x07574 RWE 0x4
LOAD 0x007648 0x10000000 0x00007574 0x0018c 0x0018c RW 0x4
LOAD 0x0077d4 0x00007700 0x00007700 0x0008c 0x0008c RW 0x4
LOAD 0x000000 0x10000190 0x10000190 0x00000 0x021b0 RW 0x20
Section to Segment mapping:
Segment Sections...
00 .ARM.exidx
01 rom_start text .ARM.exidx initlevel devices sw_isr_table device_handles rodata
02 datas device_states k_heap_area k_sem_area
03 .resource_table
04 bss noinit
Could you add a reference to the Zephyr Project, I'll check if the loader enforces this rule?
The zephyr Project supports more than 300 platforms, the flasher used to load the firmware in embedded flashes depends on the platform, so not an unique loader.
If you need a reference perhaps the linux remoteproc elf loader is a good candidate. It is used to load the coprocessor firmware based on a ELF file.
if you want more details on arm elf format: https://developer.arm.com/documentation/dui0101/a/
Thanks Arnaud