summaryrefslogtreecommitdiff
path: root/gold/object.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/object.cc')
-rw-r--r--gold/object.cc62
1 files changed, 50 insertions, 12 deletions
diff --git a/gold/object.cc b/gold/object.cc
index d334b172d7d..44ebcaabb5c 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -31,6 +31,7 @@
#include "layout.h"
#include "output.h"
#include "symtab.h"
+#include "reloc.h"
#include "object.h"
#include "dynobj.h"
@@ -1091,22 +1092,59 @@ Relocate_info<size, big_endian>::location(size_t, off_t offset) const
// See if we can get line-number information from debugging sections.
std::string filename;
std::string file_and_lineno; // Better than filename-only, if available.
- for (unsigned int shndx = 0; shndx < this->object->shnum(); ++shndx)
- if (this->object->section_name(shndx) == ".debug_line")
+
+ // The line-number information is in the ".debug_line" section.
+ unsigned int debug_shndx;
+ off_t debuglines_size;
+ const unsigned char* debuglines = NULL;
+ for (debug_shndx = 0; debug_shndx < this->object->shnum(); ++debug_shndx)
+ if (this->object->section_name(debug_shndx) == ".debug_line")
{
- off_t debuglines_size;
- const unsigned char* debuglines = this->object->section_contents(
- shndx, &debuglines_size, false);
- if (debuglines)
- {
- Dwarf_line_info<size, big_endian> line_info(debuglines,
- debuglines_size);
- line_info.read_line_mappings();
- file_and_lineno = line_info.addr2line(this->data_shndx, offset);
- }
+ debuglines = this->object->section_contents(
+ debug_shndx, &debuglines_size, false);
break;
}
+ // Find the relocation section for ".debug_line".
+ Track_relocs<size, big_endian> track_relocs;
+ bool got_relocs;
+ for (unsigned int reloc_shndx = 0;
+ reloc_shndx < this->object->shnum();
+ ++reloc_shndx)
+ {
+ unsigned int reloc_sh_type = this->object->section_type(reloc_shndx);
+ if ((reloc_sh_type == elfcpp::SHT_REL
+ || reloc_sh_type == elfcpp::SHT_RELA)
+ && this->object->section_info(reloc_shndx) == debug_shndx)
+ {
+ got_relocs = track_relocs.initialize(this->object, reloc_shndx,
+ reloc_sh_type);
+ break;
+ }
+ }
+
+ // Finally, we need the symtab section to interpret the relocs.
+ unsigned int symtab_shndx;
+ off_t symtab_size;
+ const unsigned char* symtab = NULL;
+ for (symtab_shndx = 0; symtab_shndx < this->object->shnum(); ++symtab_shndx)
+ if (this->object->section_type(symtab_shndx) == elfcpp::SHT_SYMTAB)
+ {
+ symtab = this->object->section_contents(
+ symtab_shndx, &symtab_size, false);
+ break;
+ }
+
+ // If we got all three sections we need, we can try to read debug info.
+ if (debuglines != NULL && got_relocs && symtab != NULL)
+ {
+ Dwarf_line_info<size, big_endian> line_info(debuglines, debuglines_size,
+ &track_relocs,
+ symtab, symtab_size);
+ line_info.read_line_mappings();
+ file_and_lineno = line_info.addr2line(this->data_shndx, offset);
+ }
+
std::string ret(this->object->name());
ret += ':';
Symbol_location_info info;