1

While examining the /proc/<PID>/maps file for an aarch64 process running on an Android (8), I notice this section:

726048e000-7260564000 r-xp 00000000 103:00 5402 /system/lib64/libc++.so 7260564000-7260565000 ---p 00000000 00:00 0 7260565000-726056d000 r--p 000d6000 103:00 5402 /system/lib64/libc++.so 726056d000-726056e000 rw-p 000de000 103:00 5402 /system/lib64/libc++.so 726056e000-7260571000 rw-p 00000000 00:00 0 [anon:.bss] 72605b3000-72605b5000 r-xp 00000000 103:00 5641 /system/lib64/libpackagelistparser.so 

Here's the program header table for libc++.so:

Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000040 0x0000000000009040 0x0000000000009040 0x0001c0 0x0001c0 R 0x8 LOAD 0x000000 0x0000000000009000 0x0000000000009000 0x0d58fc 0x0d58fc R E 0x1000 LOAD 0x0d68e0 0x00000000000e08e0 0x00000000000e08e0 0x007770 0x00aea8 RW 0x1000 DYNAMIC 0x0dbb40 0x00000000000e5b40 0x00000000000e5b40 0x000220 0x000220 RW 0x8 NOTE 0x000200 0x0000000000009200 0x0000000000009200 0x000038 0x000038 R 0x4 GNU_EH_FRAME 0x0d3058 0x00000000000dc058 0x00000000000dc058 0x0028a4 0x0028a4 R 0x4 GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0 GNU_RELRO 0x0d68e0 0x00000000000e08e0 0x00000000000e08e0 0x007720 0x007720 RW 0x10 

Taking the address 0xe08e0 of the second LOAD segment and adding the base of 0x726048e000, I come up with 0x726056e8e0. However, as seen in maps file above, there's no segment mapped right at that address. Instead, it overlaps with the [anon:.bss] segment. It's not even fully contained in the segment as, with a size of 0xaea8, its ending address would be 0x7260579788.

1 Answer 1

3

The last column of the program header table printed by readelf is the p_align member of the header, which defines an alignment requirement for the defined segment. From Linux man page elf(5):

This member holds the value to which the segments are aligned in memory and in the file. Loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size. Values of zero and one mean no alignment is required. Otherwise, p_align should be a positive, integral power of two, and p_vaddr should equal p_offset, modulo p_align.

Because of the alignment value 0x1000, the initialized, read-only, data segment will be included in a memory mapping with offset 0x0d6000 (0x0d68e0 rounded down) and size 0x008000 (0x007770 rounded up), which is exactly what the maps file shows (the fourth field is the file offset and the mapping length can be calculated by substracting the end and start addresses. 0x726056d000 - 0x7260565000 = 0x8000). The two following mappings have the same alignment, and by their protection flags you can guess they correspond to the initialized data segment (.data) and the uninitialized data segment (.bss).

5
  • Wouldn't you use the virtual address (0xe08e0) instead of the file offset (0xd68e0)? Commented Aug 28, 2022 at 1:55
  • Also, wouldn't the size in memory be 0xaea8 instead of the file size of 0x7770? Commented Aug 28, 2022 at 1:57
  • Why would the segment be read-only? The program header lists it as RW. Commented Aug 28, 2022 at 2:19
  • 1
    @DanielWalker 1. you'd need to provide the virtual address of the first LOAD segment to check if it matches too. 2. the file size is used for file mapping (5th field in maps is not 00:00), the memory size is used for uninitialized data, which isn't included in the executable image. 3. the GNU_RELRO segment header specifies that during dynamic linking the section should be made read-only after relocations are done. (see ld(1)) Commented Aug 28, 2022 at 17:06
  • I've added the full program header table. Commented Aug 29, 2022 at 12:20

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.