* ldgram.y (DATA_SEGMENT_RELRO_END): Add one argument.
authorJakub Jelinek <jakub@redhat.com>
Mon, 4 Oct 2004 13:41:15 +0000 (13:41 +0000)
committerJakub Jelinek <jakub@redhat.com>
Mon, 4 Oct 2004 13:41:15 +0000 (13:41 +0000)
* scripttempl/elf.sc (DATA_SEGMENT_RELRO_END): Add 0 as first
argument.
(DATA_SEGMENT_RELRO_GOTPLT_END): Pass $SEPARATE_GOTPLT as first
and . as second argument.
(GOTPLT): Move $DATA_SEGMENT_RELRO_GOTPLT_END before the section.
* ldexp.c (fold_unary): Remove DATA_SEGMENT_RELRO_END handling here.
(fold_binary): Add it here.  Insert padding to make relro_end
COMMONPAGESIZE bytes aligned.  For DATA_SEGMENT_ALIGN in
exp_dataseg_relro_adjust phase just use previously computed
exp_data_seg.base.
* ldlang.c (lang_size_sections): Set exp_data_seg.base for
relro_adjust here.  Call lang_size_sections_1 once more if there
was too big padding at DATA_SEGMENT_RELRO_END.
* ld.texinfo (DATA_SEGMENT_RELRO_END): Add documentation.

ld/ChangeLog
ld/ld.texinfo
ld/ldexp.c
ld/ldgram.y
ld/ldlang.c
ld/scripttempl/elf.sc

index 68853ce91fe4bc87e4b2f6bc9b41dabacc82536b..d39892c06da19d585c752dae6973b9ddd716c09e 100644 (file)
@@ -1,3 +1,21 @@
+2004-10-04  Jakub Jelinek  <jakub@redhat.com>
+
+       * ldgram.y (DATA_SEGMENT_RELRO_END): Add one argument.
+       * scripttempl/elf.sc (DATA_SEGMENT_RELRO_END): Add 0 as first
+       argument.
+       (DATA_SEGMENT_RELRO_GOTPLT_END): Pass $SEPARATE_GOTPLT as first
+       and . as second argument.
+       (GOTPLT): Move $DATA_SEGMENT_RELRO_GOTPLT_END before the section.
+       * ldexp.c (fold_unary): Remove DATA_SEGMENT_RELRO_END handling here.
+       (fold_binary): Add it here.  Insert padding to make relro_end
+       COMMONPAGESIZE bytes aligned.  For DATA_SEGMENT_ALIGN in
+       exp_dataseg_relro_adjust phase just use previously computed
+       exp_data_seg.base.
+       * ldlang.c (lang_size_sections): Set exp_data_seg.base for
+       relro_adjust here.  Call lang_size_sections_1 once more if there
+       was too big padding at DATA_SEGMENT_RELRO_END.
+       * ld.texinfo (DATA_SEGMENT_RELRO_END): Add documentation.
+
 2004-10-01  Paul Brook  <paul@codesourcery.com>
 
        * emulparams/armelf.sh: Add unwinding table sections.
index 047933aaf0bb6abf5fb4179c5e8462e4dffb84a0..10134a648afed530b3f0c3970be3668479c87309 100644 (file)
@@ -4545,6 +4545,21 @@ evaluation purposes.
   . = DATA_SEGMENT_END(.);
 @end smallexample
 
+@item DATA_SEGMENT_RELRO_END(@var{offset}, @var{exp})
+@kindex DATA_SEGMENT_RELRO_END(@var{offset}, @var{exp})
+This defines the end of the @code{PT_GNU_RELRO} segment when
+@samp{-z relro} option is used.  Second argument is returned.
+When @samp{-z relro} option is not present, @code{DATA_SEGMENT_RELRO_END}
+does nothing, otherwise @code{DATA_SEGMENT_ALIGN} is padded so that
+@var{exp} + @var{offset} is aligned to the most commonly used page
+boundary for particular target.  If present in the linker script,
+it must always come in between @code{DATA_SEGMENT_ALIGN} and
+@code{DATA_SEGMENT_END}.
+
+@smallexample
+  . = DATA_SEGMENT_RELRO_END(24, .);
+@end smallexample
+
 @item DEFINED(@var{symbol})
 @kindex DEFINED(@var{symbol})
 @cindex symbol defaults
index de239b225215c85fbfe3c2e5ac4dd13be08581ef..4110f57ec4ca905a9eb3b064b3ddd3a8094aa9e7 100644 (file)
@@ -265,25 +265,6 @@ fold_unary (etree_type *tree,
            result.valid_p = FALSE;
          break;
 
-       case DATA_SEGMENT_RELRO_END:
-         if (allocation_done != lang_first_phase_enum
-             && (exp_data_seg.phase == exp_dataseg_align_seen
-                 || exp_data_seg.phase == exp_dataseg_adjust
-                 || exp_data_seg.phase == exp_dataseg_relro_adjust
-                 || allocation_done != lang_allocating_phase_enum))
-           {
-             if (exp_data_seg.phase == exp_dataseg_align_seen
-                 || exp_data_seg.phase == exp_dataseg_relro_adjust)
-               exp_data_seg.relro_end
-                 = result.value + current_section->bfd_section->vma;
-             if (exp_data_seg.phase == exp_dataseg_align_seen)
-               exp_data_seg.phase = exp_dataseg_relro_seen;
-             result.value = dot - current_section->bfd_section->vma;
-           }
-         else
-           result.valid_p = FALSE;
-         break;
-
        case DATA_SEGMENT_END:
          if (allocation_done != lang_first_phase_enum
              && current_section == abs_output_section
@@ -422,13 +403,7 @@ fold_binary (etree_type *tree,
 
                  result.value = align_n (dot, maxpage);
                  if (exp_data_seg.phase == exp_dataseg_relro_adjust)
-                   {
-                     /* Attempt to align DATA_SEGMENT_RELRO_END at
-                        a common page boundary.  */
-                     exp_data_seg.base += (-exp_data_seg.relro_end
-                                           & (other.value - 1));
-                     result.value = exp_data_seg.base;
-                   }
+                   result.value = exp_data_seg.base;
                  else if (exp_data_seg.phase != exp_dataseg_adjust)
                    {
                      result.value += dot & (maxpage - 1);
@@ -448,6 +423,32 @@ fold_binary (etree_type *tree,
                result.valid_p = FALSE;
              break;
 
+           case DATA_SEGMENT_RELRO_END:
+             if (allocation_done != lang_first_phase_enum
+                 && (exp_data_seg.phase == exp_dataseg_align_seen
+                     || exp_data_seg.phase == exp_dataseg_adjust
+                     || exp_data_seg.phase == exp_dataseg_relro_adjust
+                     || allocation_done != lang_allocating_phase_enum))
+               {
+                 if (exp_data_seg.phase == exp_dataseg_align_seen
+                     || exp_data_seg.phase == exp_dataseg_relro_adjust)
+                   exp_data_seg.relro_end
+                     = result.value + other.value;
+                 if (exp_data_seg.phase == exp_dataseg_relro_adjust
+                     && (exp_data_seg.relro_end
+                         & (exp_data_seg.pagesize - 1)))
+                   {
+                     exp_data_seg.relro_end += exp_data_seg.pagesize - 1;
+                     exp_data_seg.relro_end &= ~(exp_data_seg.pagesize - 1);
+                     result.value = exp_data_seg.relro_end - other.value;
+                   }
+                 if (exp_data_seg.phase == exp_dataseg_align_seen)
+                   exp_data_seg.phase = exp_dataseg_relro_seen;
+               }
+             else
+               result.valid_p = FALSE;
+             break;
+
            default:
              FAIL ();
            }
index 75f4e70089878a30d273faa7fc2abb6171821dda..f4f4589327e8b252fd354a129dc12a770ddb0b71 100644 (file)
@@ -808,8 +808,8 @@ exp :
                        { $$ = exp_binop(ALIGN_K,$3,$5); }
        |       DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
                        { $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
-       |       DATA_SEGMENT_RELRO_END '(' exp ')'
-                       { $$ = exp_unop(DATA_SEGMENT_RELRO_END, $3); }
+       |       DATA_SEGMENT_RELRO_END '(' exp ',' exp ')'
+                       { $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3); }
        |       DATA_SEGMENT_END '(' exp ')'
                        { $$ = exp_unop(DATA_SEGMENT_END, $3); }
        |       BLOCK '(' exp ')'
index 5988635e42ac8d143dfbed85c1f3dd23f53ddf70..55a42bebe0cf9c265c817473ef25b62a78c057ee 100644 (file)
@@ -3286,10 +3286,44 @@ 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;
 
       exp_data_seg.phase = exp_dataseg_relro_adjust;
+      old_base = exp_data_seg.base;
+      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);
       result = lang_size_sections_1 (s, output_section_statement, prev, fill,
                                     dot, relax, check_regions);
+      if (exp_data_seg.relro_end > relro_end)
+       {
+         /* The alignment of sections between DATA_SEGMENT_ALIGN
+            and DATA_SEGMENT_RELRO_END caused huge padding to be
+            inserted at DATA_SEGMENT_RELRO_END.  Try some other base.  */
+         asection *sec;
+         unsigned int max_alignment_power = 0;
+
+         /* Find maximum alignment power of sections between
+            DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END.  */
+         for (sec = output_bfd->sections; sec; sec = sec->next)
+           if (sec->vma >= exp_data_seg.base
+               && sec->vma < exp_data_seg.relro_end
+               && sec->alignment_power > max_alignment_power)
+             max_alignment_power = sec->alignment_power;
+
+         if (((bfd_vma) 1 << max_alignment_power) < exp_data_seg.pagesize)
+           {
+             if (exp_data_seg.base - (1 << max_alignment_power)
+                 < old_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,
+                                            prev, fill, dot, relax,
+                                            check_regions);
+           }
+       }
       link_info.relro_start = exp_data_seg.base;
       link_info.relro_end = exp_data_seg.relro_end;
     }
index 245ab030bd89304f8838c8443d9b3b71cefba7f8..d560f58fe6f9d2c57ff2cada4179107a50df7c57 100644 (file)
@@ -90,9 +90,9 @@ if test -n "${COMMONPAGESIZE}"; then
   DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
   DATA_SEGMENT_END=". = DATA_SEGMENT_END (.);"
   if test -n "${SEPARATE_GOTPLT}"; then
-    DATA_SEGMENT_RELRO_GOTPLT_END=". = DATA_SEGMENT_RELRO_END (. + ${SEPARATE_GOTPLT});"
+    DATA_SEGMENT_RELRO_GOTPLT_END=". = DATA_SEGMENT_RELRO_END (${SEPARATE_GOTPLT}, .);"
   else
-    DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (.);"
+    DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (0, .);"
   fi
 fi
 INTERP=".interp       ${RELOCATING-0} : { *(.interp) }"
@@ -102,7 +102,8 @@ if test -z "$GOT"; then
     GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) }"
   else
     GOT=".got          ${RELOCATING-0} : { *(.got) }"
-    GOTPLT=".got.plt      ${RELOCATING-0} : { ${RELOCATING+${DATA_SEGMENT_RELRO_GOTPLT_END}} *(.got.plt) }"
+    GOTPLT="${RELOCATING+${DATA_SEGMENT_RELRO_GOTPLT_END}}
+  .got.plt      ${RELOCATING-0} : { *(.got.plt) }"
   fi
 fi
 DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
This page took 0.035632 seconds and 4 git commands to generate.