aboutsummaryrefslogtreecommitdiff
path: root/gold/object.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-12-21 21:19:45 +0000
committerIan Lance Taylor <iant@google.com>2007-12-21 21:19:45 +0000
commita9a60db6891083f0afc4df6353a0c7ef80508874 (patch)
tree4a78b23b559b910d217cc25c71fbfea946f646cd /gold/object.cc
parentdf1764b8ab18419eab855810f86419777d12925a (diff)
downloadgdb-a9a60db6891083f0afc4df6353a0c7ef80508874.zip
gdb-a9a60db6891083f0afc4df6353a0c7ef80508874.tar.gz
gdb-a9a60db6891083f0afc4df6353a0c7ef80508874.tar.bz2
Speed up relocations against local symbols in merged sections.
Diffstat (limited to 'gold/object.cc')
-rw-r--r--gold/object.cc56
1 files changed, 19 insertions, 37 deletions
diff --git a/gold/object.cc b/gold/object.cc
index 5216049..e92a66d 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -889,14 +889,30 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
}
else if (mo[shndx].offset == -1)
{
- // Leave the input value in place for SHF_MERGE sections.
+ // This is a SHF_MERGE section or one which otherwise
+ // requires special handling. We get the output address
+ // of the start of the merged section. If this is not a
+ // section symbol, we can then determine the final
+ // value. If it is a section symbol, we can not, as in
+ // that case we have to consider the addend to determine
+ // the value to use in a relocation.
+ section_offset_type start =
+ os->starting_output_address(this, shndx);
+ if (!lv.is_section_symbol())
+ lv.set_output_value(lv.input_value() + start);
+ else
+ {
+ Merged_symbol_value<size>* msv =
+ new Merged_symbol_value<size>(lv.input_value(), start);
+ lv.set_merged_symbol_value(msv);
+ }
}
else if (lv.is_tls_symbol())
- lv.set_output_value(mo[shndx].output_section->tls_offset()
+ lv.set_output_value(os->tls_offset()
+ mo[shndx].offset
+ lv.input_value());
else
- lv.set_output_value(mo[shndx].output_section->address()
+ lv.set_output_value(os->address()
+ mo[shndx].offset
+ lv.input_value());
}
@@ -953,40 +969,6 @@ Sized_relobj<size, big_endian>::local_symbol_value(unsigned int symndx) const
return lv.value(this, 0);
}
-// Return the value of a local symbol defined in input section SHNDX,
-// with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL
-// indicates whether the symbol is a section symbol. This handles
-// SHF_MERGE sections.
-template<int size, bool big_endian>
-typename elfcpp::Elf_types<size>::Elf_Addr
-Sized_relobj<size, big_endian>::local_value(unsigned int shndx,
- Address value,
- bool is_section_symbol,
- Address addend) const
-{
- const std::vector<Map_to_output>& mo(this->map_to_output());
- Output_section* os = mo[shndx].output_section;
- if (os == NULL)
- return addend;
- gold_assert(mo[shndx].offset == -1);
-
- // Do the mapping required by the output section. If this is not a
- // section symbol, then we want to map the symbol value, and then
- // include the addend. If this is a section symbol, then we need to
- // include the addend to figure out where in the section we are,
- // before we do the mapping. This will do the right thing provided
- // the assembler is careful to only convert a relocation in a merged
- // section to a section symbol if there is a zero addend. If the
- // assembler does not do this, then in general we can't know what to
- // do, because we can't distinguish the addend for the instruction
- // format from the addend for the section offset.
-
- if (is_section_symbol)
- return os->output_address(this, shndx, value + addend);
- else
- return addend + os->output_address(this, shndx, value);
-}
-
// Write out the local symbols.
template<int size, bool big_endian>