+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>
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)
{
// 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))
{
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());
{
// 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);
}
}
+ 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());
}
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
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());
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:
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(),
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)
{
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());
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());
// 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.
//
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);
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)
// 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)
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)
{
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
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);
// 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)
{
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;
__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
#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;
}
.text : {
*(.text*)
}
- .rodata.cst16 : {
- *(.rodata.cst16*)
+ .rodata :
+ {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
}
.data.rel.ro : {
*(.data.rel.ro*)