public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Try to avoid unneeded gaps with -z relro
@ 2004-12-13 16:46 Jakub Jelinek
  2004-12-14 15:11 ` [PATCH] Try to avoid unneeded gaps with -z relro (take 2) Jakub Jelinek
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Jelinek @ 2004-12-13 16:46 UTC (permalink / raw)
  To: binutils; +Cc: Ulrich Drepper

Hi!

When linking i686 libc.so which is -z relro, we sometimes end up with
unneeded gap between RE and RW segments:
  [17] .eh_frame         PROGBITS        001234d8 1234d8 004108 00   A  0   0  4
  [18] .gcc_except_table PROGBITS        001275e0 1275e0 000252 00   A  0   0  1
  [19] .tdata            PROGBITS        001295f4 1285f4 000008 00 WAT  0   0  4
  [20] .tbss             NOBITS          001295fc 1285fc 000020 00 WAT  0   0  4
...
  LOAD           0x000000 0x00000000 0x00000000 0x127832 0x127832 R E 0x1000
  LOAD           0x1285f4 0x001295f4 0x001295f4 0x02a50 0x056a8 RW  0x1000
This is because when calculating the base of the RW segment, we first
align 0x127832 up to maxpagesize == pagesize boundary, i.e. 0x128000
(this step is necessary, 0x128000 is the smallest address where RW segment
could start), then in case DATA_SEGMENT_ALIGN we:
result.value += dot & (maxpage - 1);
which means exp_data_seg.base is 0x128832 and then add in adjustement
to make sure end of relro segment is page aligned:
      exp_data_seg.base += (-exp_data_seg.relro_end
                            & (exp_data_seg.pagesize - 1));
In this case 0x1285f4 would be better, but lang_size_sections doesn't have
enough information to try this.

The following patch adds additional exp_data_seg fields that are used solely
for -z relro and allow lang_size_sections to make better choices.
Ok to commit?

2004-12-13  Jakub Jelinek  <jakub@redhat.com>

	* ldexp.h (exp_data_seg): Add min_base and maxpagesize fields.
	* ldexp.c (fold_binary) <case DATA_SEGMENT_ALIGN>: Initialize them.
	* ldlang.c (lang_size_sections): Use them to avoid wasting virtual
	address space at DATA_SEGMENT_ALIGN.

--- ld/ldexp.h.jj	2004-12-09 14:21:39.000000000 +0100
+++ ld/ldexp.h	2004-12-13 16:38:26.116870243 +0100
@@ -100,7 +100,7 @@ extern struct exp_data_seg {
     exp_dataseg_relro_adjust,
     exp_dataseg_adjust
   } phase;
-  bfd_vma base, relro_end, end, pagesize;
+  bfd_vma base, min_base, relro_end, end, pagesize, maxpagesize;
 } exp_data_seg;
 
 /* A maps from a segment name to a base address.  */
--- ld/ldexp.c.jj	2004-12-09 14:21:39.000000000 +0100
+++ ld/ldexp.c	2004-12-13 16:38:43.427776138 +0100
@@ -435,8 +435,10 @@ fold_binary (etree_type *tree,
 		      if (allocation_done == lang_allocating_phase_enum)
 			{
 			  exp_data_seg.phase = exp_dataseg_align_seen;
+			  exp_data_seg.min_base = align_n (dot, maxpage);
 			  exp_data_seg.base = result.value;
 			  exp_data_seg.pagesize = other.value;
+			  exp_data_seg.maxpagesize = maxpage;
 			  exp_data_seg.relro_end = 0;
 			}
 		    }
--- ld/ldlang.c.jj	2004-12-09 14:21:39.000000000 +0100
+++ ld/ldlang.c	2004-12-13 16:51:33.065231485 +0100
@@ -3858,15 +3858,21 @@ lang_size_sections
     {
       /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
 	 to put exp_data_seg.relro on a (common) page boundary.  */
-      bfd_vma old_base, relro_end;
+      bfd_vma old_min_base, relro_end, maxpage;
 
       exp_data_seg.phase = exp_dataseg_relro_adjust;
-      old_base = exp_data_seg.base;
+      old_min_base = exp_data_seg.min_base;
+      maxpage = exp_data_seg.maxpagesize;
       exp_data_seg.base += (-exp_data_seg.relro_end
 			    & (exp_data_seg.pagesize - 1));
       /* Compute the expected PT_GNU_RELRO segment end.  */
       relro_end = (exp_data_seg.relro_end + exp_data_seg.pagesize - 1)
 		  & (exp_data_seg.pagesize - 1);
+      if (old_min_base + maxpage < exp_data_seg.base)
+	{
+	  exp_data_seg.base -= maxpage;
+	  relro_end -= maxpage;
+	}
       result = lang_size_sections_1 (s, output_section_statement, prev, fill,
 				     dot, relax, check_regions);
       if (exp_data_seg.relro_end > relro_end)
@@ -3888,7 +3894,7 @@ lang_size_sections
 	  if (((bfd_vma) 1 << max_alignment_power) < exp_data_seg.pagesize)
 	    {
 	      if (exp_data_seg.base - (1 << max_alignment_power)
-		  < old_base)
+		  < old_min_base)
 		exp_data_seg.base += exp_data_seg.pagesize;
 	      exp_data_seg.base -= (1 << max_alignment_power);
 	      result = lang_size_sections_1 (s, output_section_statement,

	Jakub

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

* [PATCH] Try to avoid unneeded gaps with -z relro (take 2)
  2004-12-13 16:46 [PATCH] Try to avoid unneeded gaps with -z relro Jakub Jelinek
@ 2004-12-14 15:11 ` Jakub Jelinek
  2004-12-16 12:09   ` Nick Clifton
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Jelinek @ 2004-12-14 15:11 UTC (permalink / raw)
  To: binutils; +Cc: Ulrich Drepper

On Mon, Dec 13, 2004 at 05:46:24PM +0100, Jakub Jelinek wrote:
> When linking i686 libc.so which is -z relro, we sometimes end up with
> unneeded gap between RE and RW segments:

Unfortunately, on i686 linuxthreads glibc build this patch uncovered
a typo that has been introduced in early October.

So here is updated patch that fixes that problem (missing ~) as well.

Ok to commit?

2004-12-14  Jakub Jelinek  <jakub@redhat.com>

	* ldexp.h (exp_data_seg): Add min_base and maxpagesize fields.
	* ldexp.c (fold_binary) <case DATA_SEGMENT_ALIGN>: Initialize them.
	* ldlang.c (lang_size_sections): Use them to avoid wasting virtual
	address space at DATA_SEGMENT_ALIGN.  Fix computation of expected
	PT_GNU_RELRO segment end.

--- ld/ldexp.h.jj	2004-12-09 14:21:39.000000000 +0100
+++ ld/ldexp.h	2004-12-13 16:38:26.000000000 +0100
@@ -100,7 +100,7 @@ extern struct exp_data_seg {
     exp_dataseg_relro_adjust,
     exp_dataseg_adjust
   } phase;
-  bfd_vma base, relro_end, end, pagesize;
+  bfd_vma base, min_base, relro_end, end, pagesize, maxpagesize;
 } exp_data_seg;
 
 /* A maps from a segment name to a base address.  */
--- ld/ldexp.c.jj	2004-12-09 14:21:39.000000000 +0100
+++ ld/ldexp.c	2004-12-13 16:38:43.000000000 +0100
@@ -435,8 +435,10 @@ fold_binary (etree_type *tree,
 		      if (allocation_done == lang_allocating_phase_enum)
 			{
 			  exp_data_seg.phase = exp_dataseg_align_seen;
+			  exp_data_seg.min_base = align_n (dot, maxpage);
 			  exp_data_seg.base = result.value;
 			  exp_data_seg.pagesize = other.value;
+			  exp_data_seg.maxpagesize = maxpage;
 			  exp_data_seg.relro_end = 0;
 			}
 		    }
--- ld/ldlang.c.jj	2004-12-09 14:21:39.000000000 +0100
+++ ld/ldlang.c	2004-12-14 11:50:31.243330544 +0100
@@ -3858,15 +3858,21 @@ lang_size_sections
     {
       /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
 	 to put exp_data_seg.relro on a (common) page boundary.  */
-      bfd_vma old_base, relro_end;
+      bfd_vma old_min_base, relro_end, maxpage;
 
       exp_data_seg.phase = exp_dataseg_relro_adjust;
-      old_base = exp_data_seg.base;
+      old_min_base = exp_data_seg.min_base;
+      maxpage = exp_data_seg.maxpagesize;
       exp_data_seg.base += (-exp_data_seg.relro_end
 			    & (exp_data_seg.pagesize - 1));
       /* Compute the expected PT_GNU_RELRO segment end.  */
       relro_end = (exp_data_seg.relro_end + exp_data_seg.pagesize - 1)
-		  & (exp_data_seg.pagesize - 1);
+		  & ~(exp_data_seg.pagesize - 1);
+      if (old_min_base + maxpage < exp_data_seg.base)
+	{
+	  exp_data_seg.base -= maxpage;
+	  relro_end -= maxpage;
+	}
       result = lang_size_sections_1 (s, output_section_statement, prev, fill,
 				     dot, relax, check_regions);
       if (exp_data_seg.relro_end > relro_end)
@@ -3888,7 +3894,7 @@ lang_size_sections
 	  if (((bfd_vma) 1 << max_alignment_power) < exp_data_seg.pagesize)
 	    {
 	      if (exp_data_seg.base - (1 << max_alignment_power)
-		  < old_base)
+		  < old_min_base)
 		exp_data_seg.base += exp_data_seg.pagesize;
 	      exp_data_seg.base -= (1 << max_alignment_power);
 	      result = lang_size_sections_1 (s, output_section_statement,


	Jakub

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

* Re: [PATCH] Try to avoid unneeded gaps with -z relro (take 2)
  2004-12-14 15:11 ` [PATCH] Try to avoid unneeded gaps with -z relro (take 2) Jakub Jelinek
@ 2004-12-16 12:09   ` Nick Clifton
  0 siblings, 0 replies; 3+ messages in thread
From: Nick Clifton @ 2004-12-16 12:09 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: binutils, Ulrich Drepper

Hi Jakub,

> 2004-12-14  Jakub Jelinek  <jakub@redhat.com>
> 
> 	* ldexp.h (exp_data_seg): Add min_base and maxpagesize fields.
> 	* ldexp.c (fold_binary) <case DATA_SEGMENT_ALIGN>: Initialize them.
> 	* ldlang.c (lang_size_sections): Use them to avoid wasting virtual
> 	address space at DATA_SEGMENT_ALIGN.  Fix computation of expected
> 	PT_GNU_RELRO segment end.

Approved - please apply.

Cheers
   Nick


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

end of thread, other threads:[~2004-12-16 12:09 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-12-13 16:46 [PATCH] Try to avoid unneeded gaps with -z relro Jakub Jelinek
2004-12-14 15:11 ` [PATCH] Try to avoid unneeded gaps with -z relro (take 2) Jakub Jelinek
2004-12-16 12:09   ` Nick Clifton

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).