elf

Why are some ELF sections mapped to multiple segments


When using readelf on a simple android ndk binary I get section to segment mapping where sections seem to be mapped to multiple segments. E.g. .note.gnu.build-id, .note.android.ident, .eh_frame_hdr, .dynamic, .got, ...

What is the reason for that?

readelf libhellondk.so -lW

Elf file type is DYN (Shared object file)
Entry point 0xef30
There are 8 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0301d8 0x0301d8 R E 0x1000
  LOAD           0x030d48 0x0000000000031d48 0x0000000000031d48 0x0032e0 0x003768 RW  0x1000
  DYNAMIC        0x033aa0 0x0000000000034aa0 0x0000000000034aa0 0x0001f0 0x0001f0 RW  0x8
  NOTE           0x000200 0x0000000000000200 0x0000000000000200 0x000024 0x000024 R   0x4
  NOTE           0x030140 0x0000000000030140 0x0000000000030140 0x000098 0x000098 R   0x4
  GNU_EH_FRAME   0x02b144 0x000000000002b144 0x000000000002b144 0x000e34 0x000e34 R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x030d48 0x0000000000031d48 0x0000000000031d48 0x0032b8 0x0032b8 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .plt .text .rodata .eh_frame_hdr .eh_frame .gcc_except_table .note.android.ident
   01     .fini_array .data.rel.ro .dynamic .got .data .bss
   02     .dynamic
   03     .note.gnu.build-id
   04     .note.android.ident
   05     .eh_frame_hdr
   06
   07     .fini_array .data.rel.ro .dynamic .got

Solution

  • You've got multiple segments defined within the address ranges assigned to the first two segments, which means if a section resides in a sub-segment like 03, it is obviously located in both segments 00 and 03 (Because 00's address space includes 03's).

    The reason that the segments are not contiguous may be specifically related to your case. One thing I‌ can point out is that the section data defined within the sub-segment (Like .note.gnu.build-id, which is defined within 03 sub-segment) is going to inherit the segment permissions (p_flags) of the sub-segment, not the parent segment; so in this case, .note.gnu.build-id is NOT going to be Executable, but is going to be Read-only (As it is specified by segment 03).