aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog21
-rw-r--r--gold/object.cc42
-rw-r--r--gold/object.h4
-rw-r--r--gold/powerpc.cc17
-rw-r--r--gold/target-reloc.h19
-rw-r--r--gold/testsuite/pr22266_a.c8
-rw-r--r--gold/testsuite/pr22266_main.c4
-rw-r--r--gold/testsuite/pr22266_script.t5
8 files changed, 92 insertions, 28 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 4c631ca..c3c7481 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,24 @@
+2017-11-27 Cary Coutant <ccoutant@gmail.com>
+
+ PR gold/19291
+ PR gold/22266
+ * object.cc (Sized_relobj_file::compute_final_local_value_internal):
+ Revert changes from 2017-11-08 patch. Adjust symbol value in
+ relocatable links for non-section symbols.
+ (Sized_relobj_file::compute_final_local_value): Revert changes from
+ 2017-11-08 patch.
+ (Sized_relobj_file::do_finalize_local_symbols): Likewise.
+ (Sized_relobj_file::write_local_symbols): Revert changes from
+ 2015-11-25 patch.
+ * object.h (Sized_relobj_file::compute_final_local_value_internal):
+ Revert changes from 2017-11-08 patch.
+ * powerpc.cc (Target_powerpc::relocate_relocs): Adjust addend for
+ relocatable links.
+ * target-reloc.h (relocate_relocs): Adjust addend for relocatable links.
+ * testsuite/pr22266_a.c (hello): New function.
+ * testsuite/pr22266_main.c (main): Add test for merge sections.
+ * testsuite/pr22266_script.t: Add rule for .rodata.
+
2017-11-19 Ian Lance Taylor <iant@google.com>
Cary Coutant <ccoutant@gmail.com>
diff --git a/gold/object.cc b/gold/object.cc
index 2e975bb..f7fe088 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -2318,6 +2318,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
unsigned int r_sym,
const Symbol_value<size>* lv_in,
Symbol_value<size>* lv_out,
+ bool relocatable,
const Output_sections& out_sections,
const std::vector<Address>& out_offsets,
const Symbol_table* symtab)
@@ -2404,8 +2405,11 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
{
// This is not a section symbol. We can determine
// the final value now.
- lv_out->set_output_value(
- os->output_address(this, shndx, lv_in->input_value()));
+ uint64_t value =
+ os->output_address(this, shndx, lv_in->input_value());
+ if (relocatable)
+ value -= os->address();
+ lv_out->set_output_value(value);
}
else if (!os->find_starting_output_address(this, shndx, &start))
{
@@ -2419,7 +2423,10 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
os->find_relaxed_input_section(this, shndx);
if (posd != NULL)
{
- lv_out->set_output_value(posd->address());
+ uint64_t value = posd->address();
+ if (relocatable)
+ value -= os->address();
+ lv_out->set_output_value(value);
}
else
lv_out->set_output_value(os->address());
@@ -2428,10 +2435,14 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
{
// We have to consider the addend to determine the
// value to use in a relocation. START is the start
- // of this input section.
+ // of this input section. If we are doing a relocatable
+ // link, use offset from start output section instead of
+ // address.
+ Address adjusted_start =
+ relocatable ? start - os->address() : start;
Merged_symbol_value<size>* msv =
new Merged_symbol_value<size>(lv_in->input_value(),
- start);
+ adjusted_start);
lv_out->set_merged_symbol_value(msv);
}
}
@@ -2442,7 +2453,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
+ secoffset
+ lv_in->input_value());
else
- lv_out->set_output_value(os->address()
+ lv_out->set_output_value((relocatable ? 0 : os->address())
+ secoffset
+ lv_in->input_value());
}
@@ -2468,11 +2479,12 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value(
const Symbol_table* symtab)
{
// This is just a wrapper of compute_final_local_value_internal.
+ const bool relocatable = parameters->options().relocatable();
const Output_sections& out_sections(this->output_sections());
const std::vector<Address>& out_offsets(this->section_offsets());
return this->compute_final_local_value_internal(r_sym, lv_in, lv_out,
- out_sections, out_offsets,
- symtab);
+ relocatable, out_sections,
+ out_offsets, symtab);
}
// Finalize the local symbols. Here we set the final value in
@@ -2492,6 +2504,7 @@ Sized_relobj_file<size, big_endian>::do_finalize_local_symbols(
const unsigned int loccount = this->local_symbol_count_;
this->local_symbol_offset_ = off;
+ const bool relocatable = parameters->options().relocatable();
const Output_sections& out_sections(this->output_sections());
const std::vector<Address>& out_offsets(this->section_offsets());
@@ -2500,8 +2513,9 @@ Sized_relobj_file<size, big_endian>::do_finalize_local_symbols(
Symbol_value<size>* lv = &this->local_values_[i];
Compute_final_local_value_status cflv_status =
- this->compute_final_local_value_internal(i, lv, lv, out_sections,
- out_offsets, symtab);
+ this->compute_final_local_value_internal(i, lv, lv, relocatable,
+ out_sections, out_offsets,
+ symtab);
switch (cflv_status)
{
case CFLV_OK:
@@ -2666,7 +2680,6 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
elfcpp::Sym<size, big_endian> isym(psyms);
Symbol_value<size>& lv(this->local_values_[i]);
- typename elfcpp::Elf_types<size>::Elf_Addr sym_value = lv.value(this, 0);
bool is_ordinary;
unsigned int st_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(),
@@ -2676,9 +2689,6 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
gold_assert(st_shndx < out_sections.size());
if (out_sections[st_shndx] == NULL)
continue;
- // In relocatable object files symbol values are section relative.
- if (parameters->options().relocatable())
- sym_value -= out_sections[st_shndx]->address();
st_shndx = out_sections[st_shndx]->out_shndx();
if (st_shndx >= elfcpp::SHN_LORESERVE)
{
@@ -2698,7 +2708,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
gold_assert(isym.get_st_name() < strtab_size);
const char* name = pnames + isym.get_st_name();
osym.put_st_name(sympool->get_offset(name));
- osym.put_st_value(sym_value);
+ osym.put_st_value(lv.value(this, 0));
osym.put_st_size(isym.get_st_size());
osym.put_st_info(isym.get_st_info());
osym.put_st_other(isym.get_st_other());
@@ -2716,7 +2726,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
gold_assert(isym.get_st_name() < strtab_size);
const char* name = pnames + isym.get_st_name();
osym.put_st_name(dynpool->get_offset(name));
- osym.put_st_value(sym_value);
+ osym.put_st_value(lv.value(this, 0));
osym.put_st_size(isym.get_st_size());
osym.put_st_info(isym.get_st_info());
osym.put_st_other(isym.get_st_other());
diff --git a/gold/object.h b/gold/object.h
index c6c4927..508e79c 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -2772,7 +2772,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
// LV_IN points to a local symbol value containing the input value.
// LV_OUT points to a local symbol value storing the final output value,
// which must not be a merged symbol value since before calling this
- // method to avoid memory leak. OUT_SECTIONS is an array of output
+ // method to avoid memory leak. RELOCATABLE indicates whether we are
+ // linking a relocatable output. OUT_SECTIONS is an array of output
// sections. OUT_OFFSETS is an array of offsets of the sections. SYMTAB
// points to a symbol table.
//
@@ -2784,6 +2785,7 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
compute_final_local_value_internal(unsigned int r_sym,
const Symbol_value<size>* lv_in,
Symbol_value<size>* lv_out,
+ bool relocatable,
const Output_sections& out_sections,
const std::vector<Address>& out_offsets,
const Symbol_table* symtab);
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 244c221..d529519 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -9734,6 +9734,8 @@ Target_powerpc<size, big_endian>::relocate_relocs(
gold_assert(got2_addend != invalid_address);
}
+ const bool relocatable = parameters->options().relocatable();
+
unsigned char* pwrite = reloc_view;
bool zap_next = false;
for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
@@ -9829,7 +9831,7 @@ Target_powerpc<size, big_endian>::relocate_relocs(
// In an object file, r_offset is an offset within the section.
// In an executable or dynamic object, generated by
// --emit-relocs, r_offset is an absolute address.
- if (!parameters->options().relocatable())
+ if (!relocatable)
{
offset += view_address;
if (static_cast<Address>(offset_in_output_section) != invalid_address)
@@ -9842,8 +9844,15 @@ Target_powerpc<size, big_endian>::relocate_relocs(
else if (strategy == Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA)
{
const Symbol_value<size>* psymval = object->local_symbol(orig_r_sym);
- gold_assert(os != NULL);
- addend = psymval->value(object, addend) - os->address();
+ addend = psymval->value(object, addend);
+ // In a relocatable link, the symbol value is relative to
+ // the start of the output section. For a non-relocatable
+ // link, we need to adjust the addend.
+ if (!relocatable)
+ {
+ gold_assert(os != NULL);
+ addend -= os->address();
+ }
}
else if (strategy == Relocatable_relocs::RELOC_SPECIAL)
{
@@ -9866,7 +9875,7 @@ Target_powerpc<size, big_endian>::relocate_relocs(
else
gold_unreachable();
- if (!parameters->options().relocatable())
+ if (!relocatable)
{
if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
|| r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO
diff --git a/gold/target-reloc.h b/gold/target-reloc.h
index c8b86c6..79ed1d3 100644
--- a/gold/target-reloc.h
+++ b/gold/target-reloc.h
@@ -755,6 +755,8 @@ relocate_relocs(
unsigned char* pwrite = reloc_view;
+ const bool relocatable = parameters->options().relocatable();
+
for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
{
Relocatable_relocs::Reloc_strategy strategy = relinfo->rr->strategy(i);
@@ -857,7 +859,7 @@ relocate_relocs(
// In an object file, r_offset is an offset within the section.
// In an executable or dynamic object, generated by
// --emit-relocs, r_offset is an absolute address.
- if (!parameters->options().relocatable())
+ if (!relocatable)
{
new_offset += view_address;
if (offset_in_output_section != invalid_address)
@@ -892,10 +894,17 @@ relocate_relocs(
{
case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA:
{
- typename elfcpp::Elf_types<size>::Elf_Swxword addend;
- addend = Classify_reloc::get_r_addend(&reloc);
- gold_assert(os != NULL);
- addend = psymval->value(object, addend) - os->address();
+ typename elfcpp::Elf_types<size>::Elf_Swxword addend
+ = Classify_reloc::get_r_addend(&reloc);
+ addend = psymval->value(object, addend);
+ // In a relocatable link, the symbol value is relative to
+ // the start of the output section. For a non-relocatable
+ // link, we need to adjust the addend.
+ if (!relocatable)
+ {
+ gold_assert(os != NULL);
+ addend -= os->address();
+ }
Classify_reloc::put_r_addend(&reloc_write, addend);
}
break;
diff --git a/gold/testsuite/pr22266_a.c b/gold/testsuite/pr22266_a.c
index b58254c..bdc09d4 100644
--- a/gold/testsuite/pr22266_a.c
+++ b/gold/testsuite/pr22266_a.c
@@ -3,3 +3,11 @@ static int int_from_a_1 = 0x11223344;
__attribute__((section(".data.rel.ro.a")))
int *p_int_from_a_2 = &int_from_a_1;
+
+const char *hello (void);
+
+const char *
+hello (void)
+{
+ return "XXXHello, world!" + 3;
+} \ No newline at end of file
diff --git a/gold/testsuite/pr22266_main.c b/gold/testsuite/pr22266_main.c
index 1f3476e..b49b5e1 100644
--- a/gold/testsuite/pr22266_main.c
+++ b/gold/testsuite/pr22266_main.c
@@ -1,9 +1,13 @@
#include <stdlib.h>
+#include <string.h>
extern int *p_int_from_a_2;
+extern const char *hello (void);
int main (void) {
if (*p_int_from_a_2 != 0x11223344)
abort ();
+ if (strcmp(hello(), "Hello, world!") != 0)
+ abort ();
return 0;
}
diff --git a/gold/testsuite/pr22266_script.t b/gold/testsuite/pr22266_script.t
index a9bc364..7b49988 100644
--- a/gold/testsuite/pr22266_script.t
+++ b/gold/testsuite/pr22266_script.t
@@ -8,8 +8,9 @@ SECTIONS
.text : {
*(.text*)
}
- .rodata.cst16 : {
- *(.rodata.cst16*)
+ .rodata :
+ {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
}
.data.rel.ro : {
*(.data.rel.ro*)