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]

[patch] bfd_elf_bfd_from_remote_memory() workaround for the ELF misalignment [Re: loadbase alignment - ld.so/prelink/kernel or bfd_elf_bfd_from_remote_memory() bug?]


On Wed, 15 Aug 2007 18:00:43 +0200, H.J. Lu wrote:
> On Wed, Aug 15, 2007 at 05:13:48PM +0200, Jakub Jelinek wrote:
> > On Wed, Aug 15, 2007 at 03:56:10PM +0200, Jan Kratochvil wrote:
...
> > > 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.
> > 
> > If bfd_elf_bfd_from_remote_memory() doesn't handle it, then it should be
> > fixed.  The current ld.so/prelink/kernel behavior is desirable.
> 
> I can see both approaches make senses. On one hand, BFD doesn't
> know what the run-time page size is.
...
> 2. Modify BFD to take the maximum run-time page size, which can
> be set at run-time, and use it to compute base address.

You were suggesting a new parameter for bfd_elf_bfd_from_remote_memory()?
Attached a patch using TEMPL's MINPAGESIZE value instead, isn't that sufficient?

It may have a regression due to a smaller alignment on these arches:
$ egrep -l 'ELF_MAXPAGESIZE.*\<(0x)?1\>' *.c
elf32-avr.c elf32-cr16.c elf32-cr16c.c elf32-crx.c elf32-dlx.c elf32-gen.c
elf32-h8300.c elf32-i960.c elf32-ip2k.c elf32-m32r.c elf32-m88k.c
elf32-msp430.c elf32-mt.c elf32-xtensa.c elf64-gen.c

Is there a chance these arches would use bfd_elf_bfd_from_remote_memory()?
They should fix their MINPAGESIZE, in many cases there is even a FIXME note.


Tried to remove the P_ALIGN use there completely - besides missing PHDRs read
(EHDR is already read there) there should be no alignment requirements.
Unfortunately IA64 Linux kernel vDSO provides debug symbols after the last
segment ends but still in the same page - no symbols without the aligning:
contents_size  == 2512
i_ehdr.e_shoff == 2640
ia64 minpagesize == 16384
i_phdrs[i].p_align == 0x10000



Regards,
Jan
2007-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* elfcode.h (NAME(_bfd_elf,bfd_from_remote_memory)): New variable
	PAGESIZE.  Replaced P_ALIGN by backend's MINPAGESIZE.  Fixed LOADBASE
	computation for segments without P_ALIGN alignment.

--- bfd/elfcode.h	14 Aug 2007 08:04:47 -0000	1.86
+++ bfd/elfcode.h	17 Aug 2007 18:09:00 -0000
@@ -1636,6 +1636,7 @@ NAME(_bfd_elf,bfd_from_remote_memory)
   unsigned int i;
   bfd_vma loadbase;
   bfd_boolean loadbase_set;
+  bfd_vma pagesize = get_elf_backend_data (templ)->minpagesize;
 
   /* Read in the ELF header in external format.  */
   err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr);
@@ -1720,7 +1721,7 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 	{
 	  bfd_vma segment_end;
 	  segment_end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
-			 + i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align;
+			 + pagesize - 1) & -pagesize;
 	  if (segment_end > (bfd_vma) contents_size)
 	    contents_size = segment_end;
 
@@ -1729,7 +1730,9 @@ NAME(_bfd_elf,bfd_from_remote_memory)
 	     first PT_LOAD as PT_LOADs are ordered by P_VADDR.  */
 	  if (!loadbase_set && (i_phdrs[i].p_offset & -i_phdrs[i].p_align) == 0)
 	    {
-	      loadbase = ehdr_vma - (i_phdrs[i].p_vaddr & -i_phdrs[i].p_align);
+	      /* LOADBASE may not be P_ALIGN aligned.  It violates the gELF
+	         standard but it is a common practice.  */
+	      loadbase = ehdr_vma - (i_phdrs[i].p_vaddr - i_phdrs[i].p_offset);
 	      loadbase_set = TRUE;
 	    }
 
@@ -1771,13 +1775,12 @@ NAME(_bfd_elf,bfd_from_remote_memory)
   for (i = 0; i < i_ehdr.e_phnum; ++i)
     if (i_phdrs[i].p_type == PT_LOAD)
       {
-	bfd_vma start = i_phdrs[i].p_offset & -i_phdrs[i].p_align;
+	bfd_vma start = i_phdrs[i].p_offset & -pagesize;
 	bfd_vma end = (i_phdrs[i].p_offset + i_phdrs[i].p_filesz
-		       + i_phdrs[i].p_align - 1) & -i_phdrs[i].p_align;
+		       + pagesize - 1) & -pagesize;
 	if (end > (bfd_vma) contents_size)
 	  end = contents_size;
-	err = target_read_memory ((loadbase + i_phdrs[i].p_vaddr)
-				  & -i_phdrs[i].p_align,
+	err = target_read_memory ((loadbase + i_phdrs[i].p_vaddr) & -pagesize,
 				  contents + start, end - start);
 	if (err)
 	  {

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