aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/merge.cc39
-rw-r--r--gold/merge.h12
-rw-r--r--gold/output.cc14
-rw-r--r--gold/output.h6
4 files changed, 49 insertions, 22 deletions
diff --git a/gold/merge.cc b/gold/merge.cc
index fc6bffb..beb0906 100644
--- a/gold/merge.cc
+++ b/gold/merge.cc
@@ -49,7 +49,8 @@ class Object_merge_map
// Add a mapping for MERGE_MAP, for the bytes from OFFSET to OFFSET
// + LENGTH in the input section SHNDX to OUTPUT_OFFSET in the
// output section. An OUTPUT_OFFSET of -1 means that the bytes are
- // discarded.
+ // discarded. OUTPUT_OFFSET is relative to the start of the merged
+ // data in the output section.
void
add_mapping(const Merge_map*, unsigned int shndx, section_offset_type offset,
section_size_type length, section_offset_type output_offset);
@@ -58,7 +59,8 @@ class Object_merge_map
// input address is at offset OFFSET in section SHNDX. This sets
// *OUTPUT_OFFSET to the offset in the output section; this will be
// -1 if the bytes are not being copied to the output. This returns
- // true if the mapping is known, false otherwise.
+ // true if the mapping is known, false otherwise. *OUTPUT_OFFSET is
+ // relative to the start of the merged data in the output section.
bool
get_output_offset(const Merge_map*, unsigned int shndx,
section_offset_type offset,
@@ -86,10 +88,28 @@ class Object_merge_map
{ return i1.input_offset < i2.input_offset; }
};
- // A list of entries for a particular section.
+ // A list of entries for a particular input section.
struct Input_merge_map
{
- // The Merge_map for this section.
+ // We store these with the Relobj, and we look them up by input
+ // section. It is possible to have two different merge maps
+ // associated with a single output section. For example, this
+ // happens routinely with .rodata, when merged string constants
+ // and merged fixed size constants are both put into .rodata. The
+ // output offset that we store is not the offset from the start of
+ // the output section; it is the offset from the start of the
+ // merged data in the output section. That means that the caller
+ // is going to add the offset of the merged data within the output
+ // section, which means that the caller needs to know which set of
+ // merged data it found the entry in. So it's not enough to find
+ // this data based on the input section and the output section; we
+ // also have to find it based on a set of merged data in the
+ // output section. In order to verify that we are looking at the
+ // right data, we store a pointer to the Merge_map here, and we
+ // pass in a pointer when looking at the data. If we are asked to
+ // look up information for a different Merge_map, we report that
+ // we don't have it, rather than trying a lookup and returning an
+ // answer which will receive the wrong offset.
const Merge_map* merge_map;
// The list of mappings.
std::vector<Input_merge_entry> entries;
@@ -162,7 +182,7 @@ Object_merge_map::get_or_make_input_merge_map(const Merge_map* merge_map,
if (map != NULL)
{
// For a given input section in a given object, every mapping
- // must be donw with the same Merge_map.
+ // must be done with the same Merge_map.
gold_assert(map->merge_map == merge_map);
return map;
}
@@ -277,8 +297,8 @@ Object_merge_map::get_output_offset(const Merge_map* merge_map,
// Class Merge_map.
// Add a mapping for the bytes from OFFSET to OFFSET + LENGTH in input
-// section SHNDX in object OBJECT to an OUTPUT_OFFSET in a merged
-// output section.
+// section SHNDX in object OBJECT to an OUTPUT_OFFSET in merged data
+// in an output section.
void
Merge_map::add_mapping(Relobj* object, unsigned int shndx,
@@ -297,8 +317,9 @@ Merge_map::add_mapping(Relobj* object, unsigned int shndx,
// Return the output offset for an input address. The input address
// is at offset OFFSET in section SHNDX in OBJECT. This sets
-// *OUTPUT_OFFSET to the offset in the output section. This returns
-// true if the mapping is known, false otherwise.
+// *OUTPUT_OFFSET to the offset in the merged data in the output
+// section. This returns true if the mapping is known, false
+// otherwise.
bool
Merge_map::get_output_offset(const Relobj* object, unsigned int shndx,
diff --git a/gold/merge.h b/gold/merge.h
index bf6a407..c232ab0 100644
--- a/gold/merge.h
+++ b/gold/merge.h
@@ -44,7 +44,9 @@ class Merge_map
// Add a mapping for the bytes from OFFSET to OFFSET + LENGTH in the
// input section SHNDX in object OBJECT to OUTPUT_OFFSET in the
// output section. An OUTPUT_OFFSET of -1 means that the bytes are
- // discarded.
+ // discarded. OUTPUT_OFFSET is not the offset from the start of the
+ // output section, it is the offset from the start of the merged
+ // data within the output section.
void
add_mapping(Relobj* object, unsigned int shndx,
section_offset_type offset, section_size_type length,
@@ -54,7 +56,9 @@ class Merge_map
// is at offset OFFSET in section SHNDX in OBJECT. This sets
// *OUTPUT_OFFSET to the offset in the output section; this will be
// -1 if the bytes are not being copied to the output. This returns
- // true if the mapping is known, false otherwise.
+ // true if the mapping is known, false otherwise. This returns the
+ // value stored by add_mapping, namely the offset from the start of
+ // the merged data within the output section.
bool
get_output_offset(const Relobj* object, unsigned int shndx,
section_offset_type offset,
@@ -84,7 +88,9 @@ class Output_merge_base : public Output_section_data
{ return this->entsize_; }
// Add a mapping from an OFFSET in input section SHNDX in object
- // OBJECT to an OUTPUT_OFFSET in the output section.
+ // OBJECT to an OUTPUT_OFFSET in the output section. OUTPUT_OFFSET
+ // is the offset from the start of the merged data in the output
+ // section.
void
add_mapping(Relobj* object, unsigned int shndx, section_offset_type offset,
section_size_type length, section_offset_type output_offset)
diff --git a/gold/output.cc b/gold/output.cc
index fa2bff0..793d6a3 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1347,7 +1347,9 @@ Output_section::Input_section::finalize_data_size()
this->u2_.posd->finalize_data_size();
}
-// Try to turn an input offset into an output offset.
+// Try to turn an input offset into an output offset. We want to
+// return the output offset relative to the start of this
+// Input_section in the output section.
inline bool
Output_section::Input_section::output_offset(
@@ -1362,11 +1364,7 @@ Output_section::Input_section::output_offset(
{
if (this->shndx_ != shndx || this->u2_.object != object)
return false;
- section_offset_type output_offset;
- Output_section* os = object->output_section(shndx, &output_offset);
- gold_assert(os != NULL);
- gold_assert(output_offset != -1);
- *poutput = output_offset + offset;
+ *poutput = offset;
return true;
}
}
@@ -1655,8 +1653,8 @@ Output_section::is_input_address_mapped(const Relobj* object,
// Given an address OFFSET relative to the start of input section
// SHNDX in object OBJECT, return the output offset relative to the
-// start of the section. This should only be called if SHNDX in
-// OBJECT has a special mapping.
+// start of the input section in the output section. This should only
+// be called if SHNDX in OBJECT has a special mapping.
section_offset_type
Output_section::output_offset(const Relobj* object, unsigned int shndx,
diff --git a/gold/output.h b/gold/output.h
index 38e5c48..a244fa5 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -1895,8 +1895,10 @@ class Output_section : public Output_data
// Given an input OBJECT, an input section index SHNDX within that
// object, and an OFFSET relative to the start of that input
// section, return whether or not the output offset is known. If
- // this function returns true, it sets *POUTPUT to the output
- // offset.
+ // this function returns true, it sets *POUTPUT to the offset in
+ // the output section, relative to the start of the input section
+ // in the output section. *POUTPUT may be different from OFFSET
+ // for a merged section.
bool
output_offset(const Relobj* object, unsigned int shndx,
section_offset_type offset,