public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Fix relro strip test for MIPS
@ 2007-09-19 16:23 Daniel Jacobowitz
  2007-09-19 17:52 ` H.J. Lu
  2007-09-24 22:18 ` Daniel Jacobowitz
  0 siblings, 2 replies; 16+ messages in thread
From: Daniel Jacobowitz @ 2007-09-19 16:23 UTC (permalink / raw)
  To: binutils

There are two unique things about MIPS which conspire to fail the
ld -z relro -shared tests (which test that objcopy and strip do not
change the binary).  One is that .dynamic is writable and there is no
.got.plt section, so a typical shared library has no PT_GNU_RELRO;
it gets added and then converted to PT_NULL.  The other is that it
adds a second PT_NULL program header for prelinker support.
These combine to produce an input file with two PT_NULL segments.
There's a FIXME in copy_elf_program_header above some code which
seems clearly wrong for this case.

Deleting that turns up a second problem.  The input file to strip
has a PT_NULL segment with alignment of zero (I believe this is the
aborted PT_GNU_RELRO segment, but it might have been the MIPS-specific
one; I'm not completely sure).  We were overriding its input alignment
and I don't see any reason to do so.

With this patch two more tests pass on mips-linux.  Unless someone
sees a problem with them, I will apply them in a few days.

-- 
Daniel Jacobowitz
CodeSourcery

2007-09-19  Daniel Jacobowitz  <dan@codesourcery.com>

	* elf.c (assign_file_positions_for_load_sections): Trust
	p_align_valid.
	(copy_elf_program_header): Copy PT_NULL segments.

Index: elf.c
===================================================================
--- elf.c	(revision 181978)
+++ elf.c	(working copy)
@@ -4108,10 +4108,10 @@ assign_file_positions_for_load_sections 
 
 	  p->p_align = maxpagesize;
 	}
-      else if (m->count == 0)
-	p->p_align = 1 << bed->s->log_file_align;
       else if (m->p_align_valid)
 	p->p_align = m->p_align;
+      else if (m->count == 0)
+	p->p_align = 1 << bed->s->log_file_align;
       else
 	p->p_align = 0;
 
@@ -5590,10 +5590,6 @@ copy_elf_program_header (bfd *ibfd, bfd 
       asection *first_section = NULL;
       asection *lowest_section = NULL;
 
-      /* FIXME: Do we need to copy PT_NULL segment?  */
-      if (segment->p_type == PT_NULL)
-	continue;
-
       /* Compute how many sections are in this segment.  */
       for (section = ibfd->sections, section_count = 0;
 	   section != NULL;

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-19 16:23 Fix relro strip test for MIPS Daniel Jacobowitz
@ 2007-09-19 17:52 ` H.J. Lu
  2007-09-19 18:10   ` Daniel Jacobowitz
  2007-09-24 22:18 ` Daniel Jacobowitz
  1 sibling, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-09-19 17:52 UTC (permalink / raw)
  To: binutils

On Wed, Sep 19, 2007 at 12:05:54PM -0400, Daniel Jacobowitz wrote:
> There are two unique things about MIPS which conspire to fail the
> ld -z relro -shared tests (which test that objcopy and strip do not
> change the binary).  One is that .dynamic is writable and there is no
> .got.plt section, so a typical shared library has no PT_GNU_RELRO;
> it gets added and then converted to PT_NULL.  The other is that it

We shouldn't generate a PT_NULL segment when PT_GNU_RELRO is unused.
X86 linkers should handle it correctly.

> adds a second PT_NULL program header for prelinker support.

That may be a MIPS specific problem since PT_NULL is special
for MIPS.

> These combine to produce an input file with two PT_NULL segments.
> There's a FIXME in copy_elf_program_header above some code which
> seems clearly wrong for this case.
> 

H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-19 17:52 ` H.J. Lu
@ 2007-09-19 18:10   ` Daniel Jacobowitz
  2007-09-19 18:29     ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Jacobowitz @ 2007-09-19 18:10 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Wed, Sep 19, 2007 at 10:49:36AM -0700, H.J. Lu wrote:
> On Wed, Sep 19, 2007 at 12:05:54PM -0400, Daniel Jacobowitz wrote:
> > There are two unique things about MIPS which conspire to fail the
> > ld -z relro -shared tests (which test that objcopy and strip do not
> > change the binary).  One is that .dynamic is writable and there is no
> > .got.plt section, so a typical shared library has no PT_GNU_RELRO;
> > it gets added and then converted to PT_NULL.  The other is that it
> 
> We shouldn't generate a PT_NULL segment when PT_GNU_RELRO is unused.
> X86 linkers should handle it correctly.

What avoids the extra segment?  There's definitely code in elf.c to
convert PT_GNU_RELRO to PT_NULL.

-- 
Daniel Jacobowitz
CodeSourcery

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-19 18:10   ` Daniel Jacobowitz
@ 2007-09-19 18:29     ` H.J. Lu
  2007-09-20  7:09       ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-09-19 18:29 UTC (permalink / raw)
  To: binutils

On Wed, Sep 19, 2007 at 01:52:01PM -0400, Daniel Jacobowitz wrote:
> On Wed, Sep 19, 2007 at 10:49:36AM -0700, H.J. Lu wrote:
> > On Wed, Sep 19, 2007 at 12:05:54PM -0400, Daniel Jacobowitz wrote:
> > > There are two unique things about MIPS which conspire to fail the
> > > ld -z relro -shared tests (which test that objcopy and strip do not
> > > change the binary).  One is that .dynamic is writable and there is no
> > > .got.plt section, so a typical shared library has no PT_GNU_RELRO;
> > > it gets added and then converted to PT_NULL.  The other is that it
> > 
> > We shouldn't generate a PT_NULL segment when PT_GNU_RELRO is unused.
> > X86 linkers should handle it correctly.
> 
> What avoids the extra segment?  There's definitely code in elf.c to
> convert PT_GNU_RELRO to PT_NULL.

I believe Alan checked in a patch to remove PT_NULL segment.
x86 linker won't generate PT_GNU_RELRO for -z relro if it
isn't needed. Some linker relro tests I checked in are specific
to test this.  My goal was to turn on -z relro unconditonally and
PT_GNU_RELRO won't be generated if it isn't supported or used. It
works on x86 and ia64.



H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-19 18:29     ` H.J. Lu
@ 2007-09-20  7:09       ` Alan Modra
  2007-09-20 18:08         ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2007-09-20  7:09 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Wed, Sep 19, 2007 at 11:14:13AM -0700, H.J. Lu wrote:
> I believe Alan checked in a patch to remove PT_NULL segment.

I did commit a patch to remove empty PT_LOAD segments, but I don't
recall doing anything with PT_NULL segments.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-20  7:09       ` Alan Modra
@ 2007-09-20 18:08         ` H.J. Lu
  2007-09-20 18:58           ` Daniel Jacobowitz
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-09-20 18:08 UTC (permalink / raw)
  To: binutils

On Thu, Sep 20, 2007 at 04:02:12PM +0930, Alan Modra wrote:
> On Wed, Sep 19, 2007 at 11:14:13AM -0700, H.J. Lu wrote:
> > I believe Alan checked in a patch to remove PT_NULL segment.
> 
> I did commit a patch to remove empty PT_LOAD segments, but I don't
> recall doing anything with PT_NULL segments.
> 

What happens is linker will allocate a segment for PT_GNU_RELRO
if there is a .dynamic section. But it doesn't work for MIPS.
Is there a way for linker to remove a segment reserved for
PT_GNU_RELRO?


H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-20 18:08         ` H.J. Lu
@ 2007-09-20 18:58           ` Daniel Jacobowitz
  2007-09-20 19:02             ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Daniel Jacobowitz @ 2007-09-20 18:58 UTC (permalink / raw)
  To: binutils

On Thu, Sep 20, 2007 at 10:57:25AM -0700, H.J. Lu wrote:
> What happens is linker will allocate a segment for PT_GNU_RELRO
> if there is a .dynamic section. But it doesn't work for MIPS.
> Is there a way for linker to remove a segment reserved for
> PT_GNU_RELRO?

Not and reclaim its space.  That's why we convert it to PT_NULL.

On targets where .dynamic is not required to be writable, we know in
advance whether PT_GNU_RELRO will be necessary.  On MIPS we don't;
it depends on the link inputs.

-- 
Daniel Jacobowitz
CodeSourcery

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-20 18:58           ` Daniel Jacobowitz
@ 2007-09-20 19:02             ` H.J. Lu
  2007-09-21 17:17               ` PATCH: " H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-09-20 19:02 UTC (permalink / raw)
  To: binutils

On Thu, Sep 20, 2007 at 02:07:51PM -0400, Daniel Jacobowitz wrote:
> On Thu, Sep 20, 2007 at 10:57:25AM -0700, H.J. Lu wrote:
> > What happens is linker will allocate a segment for PT_GNU_RELRO
> > if there is a .dynamic section. But it doesn't work for MIPS.
> > Is there a way for linker to remove a segment reserved for
> > PT_GNU_RELRO?
> 
> Not and reclaim its space.  That's why we convert it to PT_NULL.
> 

That was done before Alan wrote a patch to remove the empty PT_LOAD
segment. Maybe we can use the similar approach to remove empty
PT_GNU_RELRO segment.


H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* PATCH: Fix relro strip test for MIPS
  2007-09-20 19:02             ` H.J. Lu
@ 2007-09-21 17:17               ` H.J. Lu
  2007-09-23 15:36                 ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-09-21 17:17 UTC (permalink / raw)
  To: binutils

On Thu, Sep 20, 2007 at 11:58:20AM -0700, H.J. Lu wrote:
> On Thu, Sep 20, 2007 at 02:07:51PM -0400, Daniel Jacobowitz wrote:
> > On Thu, Sep 20, 2007 at 10:57:25AM -0700, H.J. Lu wrote:
> > > What happens is linker will allocate a segment for PT_GNU_RELRO
> > > if there is a .dynamic section. But it doesn't work for MIPS.
> > > Is there a way for linker to remove a segment reserved for
> > > PT_GNU_RELRO?
> > 
> > Not and reclaim its space.  That's why we convert it to PT_NULL.
> > 
> 
> That was done before Alan wrote a patch to remove the empty PT_LOAD
> segment. Maybe we can use the similar approach to remove empty
> PT_GNU_RELRO segment.
> 
> 

This patch may not be perfect. We may need to a better way to check if
a PT_GNU_RELRO segment is needed in _bfd_elf_map_sections_to_segments.


H.J.
----
2007-09-21  H.J. Lu  <hongjiu.lu@intel.com>

	* elf.c (get_program_header_size): Always add a PT_GNU_RELRO
	segment for -z relro.
	(_bfd_elf_map_sections_to_segments): Make a PT_GNU_RELRO
	segment only when needed.

--- bfd/elf.c.relro	2007-09-21 09:37:29.000000000 -0700
+++ bfd/elf.c	2007-09-21 09:52:42.000000000 -0700
@@ -3362,13 +3362,12 @@ get_program_header_size (bfd *abfd, stru
     {
       /* We need a PT_DYNAMIC segment.  */
       ++segs;
+    }
 
-      if (info->relro)
-	{
-	  /* We need a PT_GNU_RELRO segment only when there is a
-	     PT_DYNAMIC segment.  */
-	  ++segs;
-	}
+  if (info->relro)
+    {
+      /* We need a PT_GNU_RELRO segment.  */
+      ++segs;
     }
 
   if (elf_tdata (abfd)->eh_frame_hdr)
@@ -3991,21 +3990,43 @@ _bfd_elf_map_sections_to_segments (bfd *
 	  pm = &m->next;
 	}
 
-      if (dynsec != NULL && info->relro)
+      if (info->relro)
 	{
-	  /* We make a PT_GNU_RELRO segment only when there is a
-	     PT_DYNAMIC segment.  */
-	  amt = sizeof (struct elf_segment_map);
-	  m = bfd_zalloc (abfd, amt);
-	  if (m == NULL)
-	    goto error_return;
-	  m->next = NULL;
-	  m->p_type = PT_GNU_RELRO;
-	  m->p_flags = PF_R;
-	  m->p_flags_valid = 1;
+	  bfd_vma vaddr;
 
-	  *pm = m;
-	  pm = &m->next;
+	  for (m = mfirst; m != NULL; m = m->next)
+	    {
+	      vaddr = 0;
+	      if (m->p_type == PT_LOAD)
+		{
+		  bfd_vma filesz = 0;
+
+		  vaddr = m->sections[0]->vma;
+		  for (i = 0; i < m->count; i++)
+		    filesz = (m->sections[i]->vma - vaddr
+			      + m->sections[i]->size);
+
+		  if (vaddr <= info->relro_end
+		      && vaddr >= info->relro_start
+		      && (vaddr + filesz >= info->relro_end))
+		    break;
+		}
+	      }
+
+	  if (m != NULL && info->relro_end > vaddr)
+	    {
+	      amt = sizeof (struct elf_segment_map);
+	      m = bfd_zalloc (abfd, amt);
+	      if (m == NULL)
+		goto error_return;
+	      m->next = NULL;
+	      m->p_type = PT_GNU_RELRO;
+	      m->p_flags = PF_R;
+	      m->p_flags_valid = 1;
+
+	      *pm = m;
+	      pm = &m->next;
+	    }
 	}
 
       free (sections);

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: Fix relro strip test for MIPS
  2007-09-21 17:17               ` PATCH: " H.J. Lu
@ 2007-09-23 15:36                 ` H.J. Lu
  2007-09-27  6:44                   ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-09-23 15:36 UTC (permalink / raw)
  To: binutils

On Fri, Sep 21, 2007 at 09:59:00AM -0700, H.J. Lu wrote:
> On Thu, Sep 20, 2007 at 11:58:20AM -0700, H.J. Lu wrote:
> > On Thu, Sep 20, 2007 at 02:07:51PM -0400, Daniel Jacobowitz wrote:
> > > On Thu, Sep 20, 2007 at 10:57:25AM -0700, H.J. Lu wrote:
> > > > What happens is linker will allocate a segment for PT_GNU_RELRO
> > > > if there is a .dynamic section. But it doesn't work for MIPS.
> > > > Is there a way for linker to remove a segment reserved for
> > > > PT_GNU_RELRO?
> > > 
> > > Not and reclaim its space.  That's why we convert it to PT_NULL.
> > > 
> > 
> > That was done before Alan wrote a patch to remove the empty PT_LOAD
> > segment. Maybe we can use the similar approach to remove empty
> > PT_GNU_RELRO segment.
> > 
> > 
> 
> This patch may not be perfect. We may need to a better way to check if
> a PT_GNU_RELRO segment is needed in _bfd_elf_map_sections_to_segments.
> 
> 

I believe each call to assign_file_positions_for_load_sections
will assign file positions for load sections based on the current
segment layout. For -z relro, we only need to know if we need
to make a PT_GNU_RELRO segment in _bfd_elf_map_sections_to_segments.
We can call assign_file_positions_for_load_sections to get the
load section layout and find out if the PT_GNU_RELRO segment will
be empty or not.  If it will be empty, we don't need to make the
PT_GNU_RELRO segment. I don't think a PT_GNU_RELRO segment will
affect load section lay out due to extra segment in such a way
that the PT_GNU_RELRO segment won't be empty. If it is the case,
we don't need to call assign_file_positions_for_load_sections with
an argument of extra segments.

assign_file_positions_for_load_sections needs to know ELF section
header. I break set_elf_section from elf_fake_sections and call
it before calling assign_file_positions_for_load_sections.

H.J.
----
2007-09-22  H.J. Lu  <hongjiu.lu@intel.com>

	* elf.c (assign_file_positions_for_load_sections): Declared.
	Take an argument of extra segments.
	(set_elf_section): New.
	(elf_fake_sections ): Use set_elf_section.
	(get_program_header_size): Always add a PT_GNU_RELRO segment
	for -z relro.
	(_bfd_elf_map_sections_to_segments): For -z relro, call
	assign_file_positions_for_load_sections and make a PT_GNU_RELRO
	segment only when it isn't empty.
	(assign_file_positions_for_non_load_sections): Abort when
	the PT_GNU_RELRO segment is empty.
	(assign_file_positions_except_relocs): Updated.
	(prep_headers): Don't set e_phentsize and e_phoff twice.

--- bfd/elf.c.relro	2007-09-22 08:26:46.000000000 -0700
+++ bfd/elf.c	2007-09-22 14:09:55.000000000 -0700
@@ -51,6 +51,8 @@ static bfd_boolean swap_out_syms (bfd *,
 static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ;
 static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
 				    file_ptr offset);
+static bfd_boolean assign_file_positions_for_load_sections 
+  (bfd *abfd, struct bfd_link_info *link_info, unsigned int extra);
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -2434,15 +2436,18 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
   return TRUE;
 }
 
-/* Set up an ELF internal section header for a section.  */
+/* Set the ELF internal section header fields for a section, except for
+   sh_name
+   */
 
 static void
-elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
+set_elf_section (bfd *abfd, asection *asect, void *failedptrarg)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   bfd_boolean *failedptr = failedptrarg;
   Elf_Internal_Shdr *this_hdr;
   unsigned int sh_type;
+  bfd_vma sh_flags;
 
   if (*failedptr)
     {
@@ -2453,14 +2458,6 @@ elf_fake_sections (bfd *abfd, asection *
 
   this_hdr = &elf_section_data (asect)->this_hdr;
 
-  this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
-							  asect->name, FALSE);
-  if (this_hdr->sh_name == (unsigned int) -1)
-    {
-      *failedptr = TRUE;
-      return;
-    }
-
   /* Don't clear sh_flags. Assembler may set additional bits.  */
 
   if ((asect->flags & SEC_ALLOC) != 0
@@ -2470,13 +2467,15 @@ elf_fake_sections (bfd *abfd, asection *
     this_hdr->sh_addr = 0;
 
   this_hdr->sh_offset = 0;
-  this_hdr->sh_size = asect->size;
+  if (this_hdr->bfd_section)
+    BFD_ASSERT (this_hdr->sh_size == asect->size);
+  else
+    this_hdr->sh_size = asect->size;
   this_hdr->sh_link = 0;
   this_hdr->sh_addralign = 1 << asect->alignment_power;
   /* The sh_entsize and sh_info fields may have been set already by
      copy_private_section_data.  */
 
-  this_hdr->bfd_section = asect;
   this_hdr->contents = NULL;
 
   /* If the section type is unspecified, we set it based on
@@ -2578,24 +2577,25 @@ elf_fake_sections (bfd *abfd, asection *
       break;
     }
 
+  sh_flags = this_hdr->sh_flags;
   if ((asect->flags & SEC_ALLOC) != 0)
-    this_hdr->sh_flags |= SHF_ALLOC;
+    sh_flags |= SHF_ALLOC;
   if ((asect->flags & SEC_READONLY) == 0)
-    this_hdr->sh_flags |= SHF_WRITE;
+    sh_flags |= SHF_WRITE;
   if ((asect->flags & SEC_CODE) != 0)
-    this_hdr->sh_flags |= SHF_EXECINSTR;
+    sh_flags |= SHF_EXECINSTR;
   if ((asect->flags & SEC_MERGE) != 0)
     {
-      this_hdr->sh_flags |= SHF_MERGE;
+      sh_flags |= SHF_MERGE;
       this_hdr->sh_entsize = asect->entsize;
       if ((asect->flags & SEC_STRINGS) != 0)
-	this_hdr->sh_flags |= SHF_STRINGS;
+	sh_flags |= SHF_STRINGS;
     }
   if ((asect->flags & SEC_GROUP) == 0 && elf_group_name (asect) != NULL)
-    this_hdr->sh_flags |= SHF_GROUP;
+    sh_flags |= SHF_GROUP;
   if ((asect->flags & SEC_THREAD_LOCAL) != 0)
     {
-      this_hdr->sh_flags |= SHF_TLS;
+      sh_flags |= SHF_TLS;
       if (asect->size == 0
 	  && (asect->flags & SEC_HAS_CONTENTS) == 0)
 	{
@@ -2611,6 +2611,16 @@ elf_fake_sections (bfd *abfd, asection *
 	}
     }
 
+  if (this_hdr->bfd_section)
+    BFD_ASSERT (this_hdr->sh_flags == sh_flags);
+  else
+    this_hdr->sh_flags = sh_flags;
+
+  if (this_hdr->bfd_section)
+    BFD_ASSERT (this_hdr->bfd_section == asect);
+  else
+    this_hdr->bfd_section = asect;
+
   /* Check for processor-specific section types.  */
   sh_type = this_hdr->sh_type;
   if (bed->elf_backend_fake_sections
@@ -2623,6 +2633,34 @@ elf_fake_sections (bfd *abfd, asection *
 	 called for objcopy --only-keep-debug.  */
       this_hdr->sh_type = sh_type;
     }
+}
+
+/* Set up an ELF internal section header for a section.  */
+
+static void
+elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
+{
+  bfd_boolean *failedptr = failedptrarg;
+  Elf_Internal_Shdr *this_hdr;
+
+  set_elf_section (abfd, asect, failedptrarg);
+
+  if (*failedptr)
+    {
+      /* We already failed; just get out of the bfd_map_over_sections
+	 loop.  */
+      return;
+    }
+
+  this_hdr = &elf_section_data (asect)->this_hdr;
+
+  this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+							  asect->name, FALSE);
+  if (this_hdr->sh_name == (unsigned int) -1)
+    {
+      *failedptr = TRUE;
+      return;
+    }
 
   /* If the section has relocs, set up a section header for the
      SHT_REL[A] section.  If two relocation sections are required for
@@ -3362,13 +3400,12 @@ get_program_header_size (bfd *abfd, stru
     {
       /* We need a PT_DYNAMIC segment.  */
       ++segs;
+    }
 
-      if (info->relro)
-	{
-	  /* We need a PT_GNU_RELRO segment only when there is a
-	     PT_DYNAMIC segment.  */
-	  ++segs;
-	}
+  if (info->relro)
+    {
+      /* We need a PT_GNU_RELRO segment.  */
+      ++segs;
     }
 
   if (elf_tdata (abfd)->eh_frame_hdr)
@@ -3991,25 +4028,58 @@ _bfd_elf_map_sections_to_segments (bfd *
 	  pm = &m->next;
 	}
 
-      if (dynsec != NULL && info->relro)
+      elf_tdata (abfd)->segment_map = mfirst;
+
+      if (info->relro)
 	{
-	  /* We make a PT_GNU_RELRO segment only when there is a
-	     PT_DYNAMIC segment.  */
-	  amt = sizeof (struct elf_segment_map);
-	  m = bfd_zalloc (abfd, amt);
-	  if (m == NULL)
-	    goto error_return;
-	  m->next = NULL;
-	  m->p_type = PT_GNU_RELRO;
-	  m->p_flags = PF_R;
-	  m->p_flags_valid = 1;
+	  Elf_Internal_Phdr *p;
+	  bfd_boolean failed = FALSE;
+	  
+	  if (!elf_modify_segment_map (abfd, info, no_user_phdrs))
+	    return FALSE;
 
-	  *pm = m;
-	  pm = &m->next;
+	  bfd_map_over_sections (abfd, set_elf_section, &failed);
+	  if (failed)
+	    return FALSE;
+
+	  /* We need file positions of loaded sectons to check if
+	     the PT_GNU_RELRO segment is needed.  Assign file positions
+	     for the loaded sections based on the assignment of sections
+	     to segments.  */
+	  if (!assign_file_positions_for_load_sections (abfd, info, 1))
+	    {
+	      elf_tdata (abfd)->segment_map = NULL;
+	      return FALSE;
+	    }
+
+	  p = elf_tdata (abfd)->phdr;
+	  for (m = mfirst; m != NULL; m = m->next, p++)
+	    {
+	      if (p->p_type == PT_LOAD
+		  && p->p_vaddr <= info->relro_end
+		  && p->p_vaddr >= info->relro_start
+		  && (p->p_vaddr + p->p_filesz >= info->relro_end))
+		break;
+	    }
+
+	  /* Make a PT_GNU_RELRO segment only when it isn't empty.  */
+	  if (m != NULL && info->relro_end > p->p_vaddr)
+	    {
+	      amt = sizeof (struct elf_segment_map);
+	      m = bfd_zalloc (abfd, amt);
+	      if (m == NULL)
+		goto error_return;
+	      m->next = NULL;
+	      m->p_type = PT_GNU_RELRO;
+	      m->p_flags = PF_R;
+	      m->p_flags_valid = 1;
+
+	      *pm = m;
+	      pm = &m->next;
+	    }
 	}
 
       free (sections);
-      elf_tdata (abfd)->segment_map = mfirst;
     }
 
   if (!elf_modify_segment_map (abfd, info, no_user_phdrs))
@@ -4146,7 +4216,8 @@ print_segment_map (const struct elf_segm
 
 static bfd_boolean
 assign_file_positions_for_load_sections (bfd *abfd,
-					 struct bfd_link_info *link_info)
+					 struct bfd_link_info *link_info,
+					 unsigned int extra)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_segment_map *m;
@@ -4169,7 +4240,9 @@ assign_file_positions_for_load_sections 
   elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
   elf_elfheader (abfd)->e_phnum = alloc;
 
-  if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
+  /* When extra is 0, number of segments won't change.  */
+  if (extra == 0
+      || elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
     elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr;
   else
     BFD_ASSERT (elf_tdata (abfd)->program_header_size
@@ -4191,7 +4264,7 @@ assign_file_positions_for_load_sections 
     maxpagesize = bed->maxpagesize;
 
   off = bed->s->sizeof_ehdr;
-  off += alloc * bed->s->sizeof_phdr;
+  off += (alloc + extra) * bed->s->sizeof_phdr;
 
   for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
        m != NULL;
@@ -4380,8 +4453,8 @@ assign_file_positions_for_load_sections 
 		}
 	    }
 
-	  p->p_filesz += alloc * bed->s->sizeof_phdr;
-	  p->p_memsz += alloc * bed->s->sizeof_phdr;
+	  p->p_filesz += (alloc + extra) * bed->s->sizeof_phdr;
+	  p->p_memsz += (alloc + extra) * bed->s->sizeof_phdr;
 	}
 
       if (p->p_type == PT_LOAD
@@ -4735,10 +4808,7 @@ assign_file_positions_for_non_load_secti
 		  p->p_flags = (lp->p_flags & ~PF_W);
 		}
 	      else
-		{
-		  memset (p, 0, sizeof *p);
-		  p->p_type = PT_NULL;
-		}
+		abort ();
 	    }
 	}
     }
@@ -4814,7 +4884,7 @@ assign_file_positions_except_relocs (bfd
 
       /* Assign file positions for the loaded sections based on the
 	 assignment of sections to segments.  */
-      if (!assign_file_positions_for_load_sections (abfd, link_info))
+      if (!assign_file_positions_for_load_sections (abfd, link_info, 0))
 	return FALSE;
 
       /* And for non-load sections.  */
@@ -4918,11 +4988,7 @@ prep_headers (bfd *abfd)
     /* It all happens later.  */
     ;
   else
-    {
-      i_ehdrp->e_phentsize = 0;
-      i_phdrp = 0;
-      i_ehdrp->e_phoff = 0;
-    }
+    i_phdrp = 0;
 
   elf_tdata (abfd)->symtab_hdr.sh_name =
     (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", FALSE);

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Fix relro strip test for MIPS
  2007-09-19 16:23 Fix relro strip test for MIPS Daniel Jacobowitz
  2007-09-19 17:52 ` H.J. Lu
@ 2007-09-24 22:18 ` Daniel Jacobowitz
  1 sibling, 0 replies; 16+ messages in thread
From: Daniel Jacobowitz @ 2007-09-24 22:18 UTC (permalink / raw)
  To: binutils

On Wed, Sep 19, 2007 at 12:05:54PM -0400, Daniel Jacobowitz wrote:
> There are two unique things about MIPS which conspire to fail the
> ld -z relro -shared tests (which test that objcopy and strip do not
> change the binary).  One is that .dynamic is writable and there is no
> .got.plt section, so a typical shared library has no PT_GNU_RELRO;
> it gets added and then converted to PT_NULL.  The other is that it
> adds a second PT_NULL program header for prelinker support.
> These combine to produce an input file with two PT_NULL segments.
> There's a FIXME in copy_elf_program_header above some code which
> seems clearly wrong for this case.
> 
> Deleting that turns up a second problem.  The input file to strip
> has a PT_NULL segment with alignment of zero (I believe this is the
> aborted PT_GNU_RELRO segment, but it might have been the MIPS-specific
> one; I'm not completely sure).  We were overriding its input alignment
> and I don't see any reason to do so.
> 
> With this patch two more tests pass on mips-linux.  Unless someone
> sees a problem with them, I will apply them in a few days.

I agree with H.J. that we should not generate the extra PT_NULL
segment, and I'm keeping an eye on his patch to prevent that
(thanks!).  Meanwhile, there were no concerns about this patch
for copying odd binaries; I've checked it in.

-- 
Daniel Jacobowitz
CodeSourcery

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: Fix relro strip test for MIPS
  2007-09-23 15:36                 ` H.J. Lu
@ 2007-09-27  6:44                   ` Alan Modra
  2007-10-10 21:31                     ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2007-09-27  6:44 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Sat, Sep 22, 2007 at 02:17:08PM -0700, H.J. Lu wrote:
> We can call assign_file_positions_for_load_sections to get the
> load section layout and find out if the PT_GNU_RELRO segment will
> be empty or not.

I haven't been following this thread closely, but I really don't like
calling assign_file_positions_for_load_sections early like this.
Can't you determine whether a PT_GNU_RELRO program header will be
needed just by looking at the PT_LOAD sections in
_bfd_elf_map_sections_to_segments?

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: Fix relro strip test for MIPS
  2007-09-27  6:44                   ` Alan Modra
@ 2007-10-10 21:31                     ` H.J. Lu
  2007-10-11  2:25                       ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-10-10 21:31 UTC (permalink / raw)
  To: binutils

On Thu, Sep 27, 2007 at 01:54:44PM +0930, Alan Modra wrote:
> On Sat, Sep 22, 2007 at 02:17:08PM -0700, H.J. Lu wrote:
> > We can call assign_file_positions_for_load_sections to get the
> > load section layout and find out if the PT_GNU_RELRO segment will
> > be empty or not.
> 
> I haven't been following this thread closely, but I really don't like
> calling assign_file_positions_for_load_sections early like this.
> Can't you determine whether a PT_GNU_RELRO program header will be
> needed just by looking at the PT_LOAD sections in
> _bfd_elf_map_sections_to_segments?
> 

This patch

http://sourceware.org/ml/binutils/2007-09/msg00324.html

doesn't call assign_file_positions_for_load_sections.


H.J.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: Fix relro strip test for MIPS
  2007-10-10 21:31                     ` H.J. Lu
@ 2007-10-11  2:25                       ` Alan Modra
  2007-10-11  3:30                         ` H.J. Lu
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Modra @ 2007-10-11  2:25 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Wed, Oct 10, 2007 at 11:11:18AM -0700, H.J. Lu wrote:
> On Thu, Sep 27, 2007 at 01:54:44PM +0930, Alan Modra wrote:
> > On Sat, Sep 22, 2007 at 02:17:08PM -0700, H.J. Lu wrote:
> > > We can call assign_file_positions_for_load_sections to get the
> > > load section layout and find out if the PT_GNU_RELRO segment will
> > > be empty or not.
> > 
> > I haven't been following this thread closely, but I really don't like
> > calling assign_file_positions_for_load_sections early like this.
> > Can't you determine whether a PT_GNU_RELRO program header will be
> > needed just by looking at the PT_LOAD sections in
> > _bfd_elf_map_sections_to_segments?
> > 
> 
> This patch
> 
> http://sourceware.org/ml/binutils/2007-09/msg00324.html
> 
> doesn't call assign_file_positions_for_load_sections.

This patch is OK.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: Fix relro strip test for MIPS
  2007-10-11  2:25                       ` Alan Modra
@ 2007-10-11  3:30                         ` H.J. Lu
  2007-10-11 10:36                           ` Alan Modra
  0 siblings, 1 reply; 16+ messages in thread
From: H.J. Lu @ 2007-10-11  3:30 UTC (permalink / raw)
  To: binutils

On Thu, Oct 11, 2007 at 09:35:31AM +0930, Alan Modra wrote:
> On Wed, Oct 10, 2007 at 11:11:18AM -0700, H.J. Lu wrote:
> > On Thu, Sep 27, 2007 at 01:54:44PM +0930, Alan Modra wrote:
> > > On Sat, Sep 22, 2007 at 02:17:08PM -0700, H.J. Lu wrote:
> > > > We can call assign_file_positions_for_load_sections to get the
> > > > load section layout and find out if the PT_GNU_RELRO segment will
> > > > be empty or not.
> > > 
> > > I haven't been following this thread closely, but I really don't like
> > > calling assign_file_positions_for_load_sections early like this.
> > > Can't you determine whether a PT_GNU_RELRO program header will be
> > > needed just by looking at the PT_LOAD sections in
> > > _bfd_elf_map_sections_to_segments?
> > > 
> > 
> > This patch
> > 
> > http://sourceware.org/ml/binutils/2007-09/msg00324.html
> > 
> > doesn't call assign_file_positions_for_load_sections.
> 
> This patch is OK.
> 

I am checking in this equivalent patch. There is no need for the
loop. We can just use the first and last sections to compute the
file size.


H.J.
----
2007-10-10  H.J. Lu  <hongjiu.lu@intel.com>

	* elf.c (get_program_header_size): Always add a PT_GNU_RELRO
	segment for -z relro.
	(_bfd_elf_map_sections_to_segments): Make a PT_GNU_RELRO
	segment only when needed.

--- bfd/elf.c.relro	2007-10-10 19:02:12.000000000 -0700
+++ bfd/elf.c	2007-10-10 19:16:42.000000000 -0700
@@ -3362,13 +3362,12 @@ get_program_header_size (bfd *abfd, stru
     {
       /* We need a PT_DYNAMIC segment.  */
       ++segs;
+    }
 
-      if (info->relro)
-	{
-	  /* We need a PT_GNU_RELRO segment only when there is a
-	     PT_DYNAMIC segment.  */
-	  ++segs;
-	}
+  if (info->relro)
+    {
+      /* We need a PT_GNU_RELRO segment.  */
+      ++segs;
     }
 
   if (elf_tdata (abfd)->eh_frame_hdr)
@@ -3991,21 +3990,38 @@ _bfd_elf_map_sections_to_segments (bfd *
 	  pm = &m->next;
 	}
 
-      if (dynsec != NULL && info->relro)
+      if (info->relro)
 	{
-	  /* We make a PT_GNU_RELRO segment only when there is a
-	     PT_DYNAMIC segment.  */
-	  amt = sizeof (struct elf_segment_map);
-	  m = bfd_zalloc (abfd, amt);
-	  if (m == NULL)
-	    goto error_return;
-	  m->next = NULL;
-	  m->p_type = PT_GNU_RELRO;
-	  m->p_flags = PF_R;
-	  m->p_flags_valid = 1;
+	  for (m = mfirst; m != NULL; m = m->next)
+	    {
+	      if (m->p_type == PT_LOAD)
+		{
+		  asection *last = m->sections[m->count - 1];
+		  bfd_vma vaddr = m->sections[0]->vma;
+		  bfd_vma filesz = last->vma - vaddr + last->size;
+
+		  if (vaddr < info->relro_end
+		      && vaddr >= info->relro_start
+		      && (vaddr + filesz) >= info->relro_end)
+		    break;
+		}
+	      }
 
-	  *pm = m;
-	  pm = &m->next;
+	  /* Make a PT_GNU_RELRO segment only when it isn't empty.  */
+	  if (m != NULL)
+	    {
+	      amt = sizeof (struct elf_segment_map);
+	      m = bfd_zalloc (abfd, amt);
+	      if (m == NULL)
+		goto error_return;
+	      m->next = NULL;
+	      m->p_type = PT_GNU_RELRO;
+	      m->p_flags = PF_R;
+	      m->p_flags_valid = 1;
+
+	      *pm = m;
+	      pm = &m->next;
+	    }
 	}
 
       free (sections);

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: PATCH: Fix relro strip test for MIPS
  2007-10-11  3:30                         ` H.J. Lu
@ 2007-10-11 10:36                           ` Alan Modra
  0 siblings, 0 replies; 16+ messages in thread
From: Alan Modra @ 2007-10-11 10:36 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Wed, Oct 10, 2007 at 07:25:27PM -0700, H.J. Lu wrote:
> I am checking in this equivalent patch. There is no need for the
> loop. We can just use the first and last sections to compute the
> file size.

Fine by me.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2007-10-11  4:22 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-09-19 16:23 Fix relro strip test for MIPS Daniel Jacobowitz
2007-09-19 17:52 ` H.J. Lu
2007-09-19 18:10   ` Daniel Jacobowitz
2007-09-19 18:29     ` H.J. Lu
2007-09-20  7:09       ` Alan Modra
2007-09-20 18:08         ` H.J. Lu
2007-09-20 18:58           ` Daniel Jacobowitz
2007-09-20 19:02             ` H.J. Lu
2007-09-21 17:17               ` PATCH: " H.J. Lu
2007-09-23 15:36                 ` H.J. Lu
2007-09-27  6:44                   ` Alan Modra
2007-10-10 21:31                     ` H.J. Lu
2007-10-11  2:25                       ` Alan Modra
2007-10-11  3:30                         ` H.J. Lu
2007-10-11 10:36                           ` Alan Modra
2007-09-24 22:18 ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).