Albert Lee wrote:

> http://trisk.acm.jhu.edu/ntdll.dll.so.gz is a copy.

% elfdump -pNPT_LOAD ntdll.dll.so

Program Header[0]:
     p_vaddr:      0           p_flags:    [ PF_X PF_R ]
     p_paddr:      0           p_type:     [ PT_LOAD ]
     p_filesz:     0x8e8d1     p_memsz:    0x8e8d1
     p_offset:     0           p_align:    0x10000

Program Header[1]:
     p_vaddr:      0x9e8d4     p_flags:    [ PF_X PF_W PF_R ]
     p_paddr:      0           p_type:     [ PT_LOAD ]
     p_filesz:     0x8dc0      p_memsz:    0x1b720
     p_offset:     0x8e8d4     p_align:    0x10000

 From a Nevada box:

% truss -f ldd ntdll.dll.so
...
12790:  open("./ntdll.dll.so", O_RDONLY)          = 4
12790:  mmap(0x00010000, 32768, PROT_READ|PROT_EXEC, \
             MAP_PRIVATE|MAP_ALIGN, 4, 0)          = 0xFEFB0000

This mapping allows ld.so.1 to look at the ELF header and Program
headers and determine the "total" memory reservation required.
Think of this as a temporary mapping to let ld.so.1 investigate the
file .... it'll be reused to inspect the next file.

12790:  mmap(0x00010000, 761856, PROT_NONE, \
            MAP_PRIVATE|MAP_NORESERVE|MAP_ANON|MAP_ALIGN, \
             -1, 0)                                 = 0xFEEF0000

This mapping makes the reservation - the kernel has returned a
base address of 0xfeef0000.

12790:  mmap(0xFEEF0000, 583889, PROT_READ|PROT_EXEC, \
            MAP_PRIVATE|MAP_FIXED|MAP_TEXT, 4, 0)  = 0xFEEF0000

This mapping fixes the text segment to start at 0xfeef0000.

12790:  mmap(0xFEF8E000, 38548, PROT_READ|PROT_WRITE|PROT_EXEC, \
            MAP_PRIVATE|MAP_FIXED|MAP_INITDATA, \
            4, 581632)                             = 0xFEF8E000

This mapping fixes the data segment (note PROT_WRITE) at 0xfef8e000.

12790:  mmap(0xFEF98000, 73720, PROT_READ|PROT_WRITE|PROT_EXEC, \
            MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) = 0xFEF98000

This mapping adds /dev/zero to contribute to the bss at 0xfef98000.

12790:  munmap(0xFEF7F000, 61440)                  = 0

This umap frees the area between the text and data segment.

Hence proc reveals:

FEEF0000     572K r-x--  /home/rie/wine/ntdll.dll.so   (text segment)
FEF80000       4K rwx--    [ anon ]
FEF8E000      40K rwx--  /home/rie/wine/ntdll.dll.so   (data segment)
FEF98000      72K rwx--  /home/rie/wine/ntdll.dll.so   (additional bss)

And someone (probably ld.so.1 asking for its own memory allocation)
has snuck in and stolen 4k from the "hole".  Sometimes, single segment
ELF files, like filters (libdl etc.) are small enough to be mapped
into these "holes".  Again, it's the kernel that dictates how the
hole is used.   ld.so.1 revolves around mmap(0) requests, that ask
the kernel for memory, and then ld.so.1 "fills" the returned reservation.

You can affect this "hole" by changing the required alignment of the
data segment.  The ABI aligns the text and data at 0x10000 (i386).
If you reduce the alignment requirement of the data segment you'll make
a smaller "hole".  Drop the alignment to a page size and you'll get no
"hole".  There's a rather terse mapfile syntax for doing this:

  % cat mapfile
  data = A0x1000;


But, as you start to take control of how an object is laid out so
you might take control from the kernel optimizing where your dependency
is loaded.

-- 

Rod.

Reply via email to