This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: loadbase alignment - ld.so/prelink/kernel or bfd_elf_bfd_from_remote_memory() bug?


On Wed, Aug 15, 2007 at 03:56:10PM +0200, Jan Kratochvil wrote:
> Hi,
> 
> bfd_elf_bfd_from_remote_memory() would almost work for general ELF files but it
> fails (I have no simple testcase) now due to the ELF `Base address' alignment.
> BFD uses `& -i_phdrs[i].p_align' for the VMA addresses but the real mapping
> is only PAGE_SIZE aligned (illustrated in the `BEFORE' dumps below).
> 
> For x86_64:
> 
> * bfd_elf_bfd_from_remote_memory() expects `loadbase' is P_ALIGN aligned.
> 
>   * GCC on x86_64 produces P_ALIGN 0x200000 == 2MB.
> 
> * ld.so loads ELF to `l_map_start' being only PAGE_SIZE aligned.
>   (The same problem applies to prelink and Linux kernel elf loading.)
> 
> * gELF standard in its `Base Address' computation expects the `base address' to
>   be `maximum page size' aligned, according to the last sentence:
>   	http://x86.ddj.com/ftp/manuals/tools/elf.pdf
>   	This address is truncated to the nearest multiple of the maximum page
>   	size.  The corresponding p_vaddr value itself is also truncated to the
>   	nearest multiple of the maximum page size. The base address is the
>   	difference between the truncated memory address and the truncated
>   	p_vaddr value.
> 
>   * x86_64 ELF standard in its `3.3.3 Page Size' talks about maximum page size
>     64KB (I would expect it should scale up to 2MB for the 2MB PSE pages).
>     	http://www.x86-64.org/documentation/abi.pdf
>     	Systems are permitted to use any power-of-two page size between 4KB and
>     	64KB, inclusive.
> 
> According to the Roland's mail below (p_align is supposed to match "maxpage")
> IMO ld.so + prelink + kernel violate the gELF standard.
> 
> Proper ld.so P_ALIGN-compliant mapping would also make possible a kernel 2MB
> PSE pages optimized mapping for very large .so libraries.
> 
> Removing P_ALIGN masking from bfd_elf_bfd_from_remote_memory() workarounds it
> well but I expect this problem should move to glibc + prelink + kernel, right?
> 
> 
> Proposing ld.so patch which fixes the bfd_elf_bfd_from_remote_memory() problem.
> 
> Program Headers:
>   Type           Offset             VirtAddr           PhysAddr
>                  FileSiz            MemSiz              Flags  Align
>   LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
>                  0x00000000000004bc 0x00000000000004bc  R E    200000
>   LOAD           0x00000000000004c0 0x00000000002004c0 0x00000000002004c0
>                  0x00000000000001e8 0x00000000000001f8  RW     200000
> 
> BEFORE:
> 00400000-00401000 r-xp 00000000 08:01 4717502                            /tmp/alignmain
> 00600000-00601000 rw-p 00000000 08:01 4717502                            /tmp/alignmain
> ...
> 2aaaaaaad000-2aaaaaaae000 r-xp 00000000 08:01 4717503                    /tmp/alignlib.so
> 2aaaaaaae000-2aaaaacad000 ---p 00001000 08:01 4717503                    /tmp/alignlib.so
> 2aaaaacad000-2aaaaacae000 rw-p 00000000 08:01 4717503                    /tmp/alignlib.so
> 
> open("./alignlib.so", O_RDONLY)         = 3
> ...
> mmap(NULL, 2098872, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2aaaaaaad000
> mprotect(0x2aaaaaaae000, 2093056, PROT_NONE) = 0
> mmap(0x2aaaaacad000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x2aaaaacad000
> close(3)                                = 0
> 
> 
> AFTER:
> 00400000-00401000 r-xp 00000000 08:01 4717502                            /tmp/alignmain
> 00600000-00601000 rw-p 00000000 08:01 4717502                            /tmp/alignmain
> ...
> 2aaaaac00000-2aaaaac01000 r-xp 00000000 08:01 4717503                    /tmp/alignlib.so
> 2aaaaac01000-2aaaaae00000 ---p 2aaaaac01000 00:00 0 
> 2aaaaae00000-2aaaaae01000 rw-p 00000000 08:01 4717503                    /tmp/alignlib.so
> 
> open("./alignlib.so", O_RDONLY)         = 3
> ...
> mmap(NULL, 4194304, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_DENYWRITE, -1, 0) = 0x2aaaaaaad000
> munmap(0x2aaaaaaad000, 1388544)         = 0
> munmap(0x2aaaaae01000, 704512)          = 0
> mprotect(0x2aaaaac01000, 2093056, PROT_NONE) = 0
> mmap(0x2aaaaac00000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x2aaaaac00000
> mmap(0x2aaaaae00000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x2aaaaae00000
> close(3)                                = 0
> 
> 
> 
> Regards,
> Jan
> 
> 
> http://sourceware.org/ml/binutils/2007-08/msg00184.html
> 
> On Mon, 13 Aug 2007 03:15:44 +0200, Roland McGrath wrote:
> ...
> > The file itself doesn't tell you what "maxpage" is, but p_align is
> > supposed to match it.
> 
> > You can't presume the actual memory addresses
> > used will be so aligned (it's the maximum page size, not the minimum).
> 
> This sentence contradicts my deduction above.
> 
> 
> > However, in a correct ELF object's phdrs, each p_vaddr and p_offset
> > must be congruent to that alignment.
> ...
> > you need to know the actual page size.  bfd_elf_bfd_from_remote_memory
> > doesn't know this.  (The debugger might know it by some external means.

> 2007-08-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	* elf/dl-load.c (_dl_map_object_from_fd): New variable ALIGNMAX.
> 	New sanity check if P_ALIGN is a power of two.
> 	New variables ALIGNEDSTART, ALIGNEDMAPPEDEND and ALIGNEDMAPLENGTH.
> 	Map ET_DYN ELFs with the P_ALIGN compliant ELF Base address.
> 
> --- glibc-20070810T2152-orig/elf/dl-load.c	2007-08-03 17:50:24.000000000 +0200
> +++ glibc-20070810T2152/elf/dl-load.c	2007-08-15 00:41:03.000000000 +0200
> @@ -1012,6 +1012,7 @@ _dl_map_object_from_fd (const char *name
>  	int prot;
>        } loadcmds[l->l_phnum], *c;
>      size_t nloadcmds = 0;
> +    ElfW(Addr) alignmax = GLRO(dl_pagesize);

Why not replace all GLRO(dl_pagesize) with alignmax?


H.J.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]