ld: Add fold_segment_align/fold_segment_relro_end/fold_segment_end
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 13 Nov 2017 01:20:09 +0000 (17:20 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 13 Nov 2017 01:20:18 +0000 (17:20 -0800)
Extract DATA_SEGMENT_END/DATA_SEGMENT_ALIGN/DATA_SEGMENT_RELRO_END cases
for GNU_RELRO segment into separate functions so that they can also be
used for text-only LOAD segment.

* ldexp.c (fold_unary): Extract the DATA_SEGMENT_END case to ...
(fold_segment_end): New function.
(fold_binary): Extract the DATA_SEGMENT_ALIGN case to ...
(fold_segment_align): New function.
(fold_binary): Extract the DATA_SEGMENT_RELRO_END case to ...
(fold_segment_relro_end): New function.

ld/ChangeLog
ld/ldexp.c

index 0a39d744394a4719121b5a54583df33f355821de..bee75c182429b6630602b2825e88fbd171425d60 100644 (file)
@@ -1,3 +1,12 @@
+2017-11-12  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * ldexp.c (fold_unary): Extract the DATA_SEGMENT_END case to ...
+       (fold_segment_end): New function.
+       (fold_binary): Extract the DATA_SEGMENT_ALIGN case to ...
+       (fold_segment_align): New function.
+       (fold_binary): Extract the DATA_SEGMENT_RELRO_END case to ...
+       (fold_segment_relro_end): New function.
+
 2017-11-12  H.J. Lu  <hongjiu.lu@intel.com>
 
        * ldexp.h (phase_enum): Rename exp_dataseg_none,
index 5633e5071487932be695c2c7bf646a16f7c959c7..83d9f8f2a7fddf38ac21a1a7f712f92250932b34 100644 (file)
@@ -342,6 +342,30 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
   return ret;
 }
 
+static void
+fold_segment_end (seg_align_type *seg)
+{
+  if (expld.phase == lang_first_phase_enum
+      || expld.section != bfd_abs_section_ptr)
+    {
+      expld.result.valid_p = FALSE;
+    }
+  else if (seg->phase == exp_seg_align_seen
+          || seg->phase == exp_seg_relro_seen)
+    {
+      seg->phase = exp_seg_end_seen;
+      seg->end = expld.result.value;
+    }
+  else if (seg->phase == exp_seg_done
+          || seg->phase == exp_seg_adjust
+          || seg->phase == exp_seg_relro_adjust)
+    {
+      /* OK.  */
+    }
+  else
+    expld.result.valid_p = FALSE;
+}
+
 static void
 fold_unary (etree_type *tree)
 {
@@ -389,25 +413,7 @@ fold_unary (etree_type *tree)
          break;
 
        case DATA_SEGMENT_END:
-         if (expld.phase == lang_first_phase_enum
-             || expld.section != bfd_abs_section_ptr)
-           {
-             expld.result.valid_p = FALSE;
-           }
-         else if (expld.dataseg.phase == exp_seg_align_seen
-                  || expld.dataseg.phase == exp_seg_relro_seen)
-           {
-             expld.dataseg.phase = exp_seg_end_seen;
-             expld.dataseg.end = expld.result.value;
-           }
-         else if (expld.dataseg.phase == exp_seg_done
-                  || expld.dataseg.phase == exp_seg_adjust
-                  || expld.dataseg.phase == exp_seg_relro_adjust)
-           {
-             /* OK.  */
-           }
-         else
-           expld.result.valid_p = FALSE;
+         fold_segment_end (&expld.dataseg);
          break;
 
        default:
@@ -443,6 +449,84 @@ arith_result_section (const etree_value_type *lhs)
     }
 }
 
+static void
+fold_segment_align (seg_align_type *seg, etree_value_type *lhs)
+{
+  seg->relro = exp_seg_relro_start;
+  if (expld.phase == lang_first_phase_enum
+      || expld.section != bfd_abs_section_ptr)
+    expld.result.valid_p = FALSE;
+  else
+    {
+      bfd_vma maxpage = lhs->value;
+      bfd_vma commonpage = expld.result.value;
+
+      expld.result.value = align_n (expld.dot, maxpage);
+      if (seg->phase == exp_seg_relro_adjust)
+       expld.result.value = seg->base;
+      else if (seg->phase == exp_seg_adjust)
+       {
+         if (commonpage < maxpage)
+           expld.result.value += ((expld.dot + commonpage - 1)
+                                  & (maxpage - commonpage));
+       }
+      else
+       {
+         expld.result.value += expld.dot & (maxpage - 1);
+         if (seg->phase == exp_seg_done)
+           {
+             /* OK.  */
+           }
+         else if (seg->phase == exp_seg_none)
+           {
+             seg->phase = exp_seg_align_seen;
+             seg->base = expld.result.value;
+             seg->pagesize = commonpage;
+             seg->maxpagesize = maxpage;
+             seg->relro_end = 0;
+           }
+         else
+           expld.result.valid_p = FALSE;
+       }
+    }
+}
+
+static void
+fold_segment_relro_end (seg_align_type *seg, etree_value_type *lhs)
+{
+  /* Operands swapped!  XXX_SEGMENT_RELRO_END(offset,exp) has offset
+     in expld.result and exp in lhs.  */
+  seg->relro = exp_seg_relro_end;
+  seg->relro_offset = expld.result.value;
+  if (expld.phase == lang_first_phase_enum
+      || expld.section != bfd_abs_section_ptr)
+    expld.result.valid_p = FALSE;
+  else if (seg->phase == exp_seg_align_seen
+          || seg->phase == exp_seg_adjust
+          || seg->phase == exp_seg_relro_adjust
+          || seg->phase == exp_seg_done)
+    {
+      if (seg->phase == exp_seg_align_seen
+         || seg->phase == exp_seg_relro_adjust)
+       seg->relro_end = lhs->value + expld.result.value;
+
+      if (seg->phase == exp_seg_relro_adjust
+         && (seg->relro_end & (seg->pagesize - 1)))
+       {
+         seg->relro_end += seg->pagesize - 1;
+         seg->relro_end &= ~(seg->pagesize - 1);
+         expld.result.value = seg->relro_end - expld.result.value;
+       }
+      else
+       expld.result.value = lhs->value;
+
+      if (seg->phase == exp_seg_align_seen)
+       seg->phase = exp_seg_relro_seen;
+    }
+  else
+    expld.result.valid_p = FALSE;
+}
+
 static void
 fold_binary (etree_type *tree)
 {
@@ -573,79 +657,11 @@ fold_binary (etree_type *tree)
          break;
 
        case DATA_SEGMENT_ALIGN:
-         expld.dataseg.relro = exp_seg_relro_start;
-         if (expld.phase == lang_first_phase_enum
-             || expld.section != bfd_abs_section_ptr)
-           expld.result.valid_p = FALSE;
-         else
-           {
-             bfd_vma maxpage = lhs.value;
-             bfd_vma commonpage = expld.result.value;
-
-             expld.result.value = align_n (expld.dot, maxpage);
-             if (expld.dataseg.phase == exp_seg_relro_adjust)
-               expld.result.value = expld.dataseg.base;
-             else if (expld.dataseg.phase == exp_seg_adjust)
-               {
-                 if (commonpage < maxpage)
-                   expld.result.value += ((expld.dot + commonpage - 1)
-                                          & (maxpage - commonpage));
-               }
-             else
-               {
-                 expld.result.value += expld.dot & (maxpage - 1);
-                 if (expld.dataseg.phase == exp_seg_done)
-                   {
-                     /* OK.  */
-                   }
-                 else if (expld.dataseg.phase == exp_seg_none)
-                   {
-                     expld.dataseg.phase = exp_seg_align_seen;
-                     expld.dataseg.base = expld.result.value;
-                     expld.dataseg.pagesize = commonpage;
-                     expld.dataseg.maxpagesize = maxpage;
-                     expld.dataseg.relro_end = 0;
-                   }
-                 else
-                   expld.result.valid_p = FALSE;
-               }
-           }
+         fold_segment_align (&expld.dataseg, &lhs);
          break;
 
        case DATA_SEGMENT_RELRO_END:
-         /* Operands swapped!  DATA_SEGMENT_RELRO_END(offset,exp)
-            has offset in expld.result and exp in lhs.  */
-         expld.dataseg.relro = exp_seg_relro_end;
-         expld.dataseg.relro_offset = expld.result.value;
-         if (expld.phase == lang_first_phase_enum
-             || expld.section != bfd_abs_section_ptr)
-           expld.result.valid_p = FALSE;
-         else if (expld.dataseg.phase == exp_seg_align_seen
-                  || expld.dataseg.phase == exp_seg_adjust
-                  || expld.dataseg.phase == exp_seg_relro_adjust
-                  || expld.dataseg.phase == exp_seg_done)
-           {
-             if (expld.dataseg.phase == exp_seg_align_seen
-                 || expld.dataseg.phase == exp_seg_relro_adjust)
-               expld.dataseg.relro_end = lhs.value + expld.result.value;
-
-             if (expld.dataseg.phase == exp_seg_relro_adjust
-                 && (expld.dataseg.relro_end
-                     & (expld.dataseg.pagesize - 1)))
-               {
-                 expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
-                 expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
-                 expld.result.value = (expld.dataseg.relro_end
-                                       - expld.result.value);
-               }
-             else
-               expld.result.value = lhs.value;
-
-             if (expld.dataseg.phase == exp_seg_align_seen)
-               expld.dataseg.phase = exp_seg_relro_seen;
-           }
-         else
-           expld.result.valid_p = FALSE;
+         fold_segment_relro_end (&expld.dataseg, &lhs);
          break;
 
        default: