aboutsummaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2015-04-22 22:46:19 +0930
committerAlan Modra <amodra@gmail.com>2015-04-22 23:19:59 +0930
commit0e5fabeb2c4b90857403995e14550210fe1cae71 (patch)
tree12b7bf30c5412d4e094c9aba11b0123877ef1831 /ld/ldexp.c
parentd5597ebccca6761fb641b7fc99b6e8b56fbac6e2 (diff)
downloadgdb-0e5fabeb2c4b90857403995e14550210fe1cae71.zip
gdb-0e5fabeb2c4b90857403995e14550210fe1cae71.tar.gz
gdb-0e5fabeb2c4b90857403995e14550210fe1cae71.tar.bz2
Rewrite relro adjusting code
The linker tries to put the end of the last section in the relro segment exactly on a page boundary, because the relro segment itself must end on a page boundary. If for any reason this can't be done, padding is inserted. Since the end of the relro segment is typically between .got and .got.plt, padding effectively increases the size of the GOT. This isn't nice for targets and code models with limited GOT addressing. The problem with the current code is that it doesn't cope very well with aligned sections in the relro segment. When making .got aligned to a 256 byte boundary for PowerPC64, I found that often the initial alignment attempt failed and the fallback attempt to be less than adequate. This is a particular problem for PowerPC64 since the distance between .got and .plt affects the size of plt call stubs, leading to "stubs don't match calculated size" errors. So this rewrite takes a direct approach to calculating a new relro base. Starting from the last section in the segment, we calculate where it must start to position its end on the boundary, or as near as possible considering alignment requirements. The new start then becomes the goal for the previous section to end, and so on for all sections. This of course ignores the possibility that user scripts will place . = ALIGN(xxx); in the relro segment, or provide section address expressions. In those cases we might fail, but the old code probably did too, and a fallback is provided. ld/ * ldexp.h (struct ldexp_control): Delete dataseg.min_base. Add data_seg.relro_offset. * ldexp.c (fold_binary <DATA_SEGMENT_ALIGN>): Don't set min_base. (fold_binary <DATA_SEGMENT_RELRO_END>): Do set relro_offset. * ldlang.c (lang_size_sections): Rewrite code adjusting relro segment base to line up last section on page boundary. ld/testsuite/ * ld-x86-64/pr18176.d: Update.
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 9cd9e29..a5192b1 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -575,7 +575,6 @@ fold_binary (etree_type *tree)
else if (expld.dataseg.phase == exp_dataseg_none)
{
expld.dataseg.phase = exp_dataseg_align_seen;
- expld.dataseg.min_base = expld.dot;
expld.dataseg.base = expld.result.value;
expld.dataseg.pagesize = commonpage;
expld.dataseg.maxpagesize = maxpage;
@@ -591,6 +590,7 @@ fold_binary (etree_type *tree)
/* Operands swapped! DATA_SEGMENT_RELRO_END(offset,exp)
has offset in expld.result and exp in lhs. */
expld.dataseg.relro = exp_dataseg_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;