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.