aboutsummaryrefslogtreecommitdiff
path: root/gold/object.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-11-02 23:02:44 +0000
committerIan Lance Taylor <iant@google.com>2007-11-02 23:02:44 +0000
commit5c2c6c957be387f3649b143508a2b5c730c0b6f5 (patch)
tree50bcf3279038a085b36033f3b5005c61b9d51c9a /gold/object.cc
parent8942f2584cd5e11f2d512c5cf42747644be2735a (diff)
downloadgdb-5c2c6c957be387f3649b143508a2b5c730c0b6f5.zip
gdb-5c2c6c957be387f3649b143508a2b5c730c0b6f5.tar.gz
gdb-5c2c6c957be387f3649b143508a2b5c730c0b6f5.tar.bz2
From Craig Silverstein: Add first version of generating error messages
with file name and line number.
Diffstat (limited to 'gold/object.cc')
-rw-r--r--gold/object.cc52
1 files changed, 41 insertions, 11 deletions
diff --git a/gold/object.cc b/gold/object.cc
index 269acc5..58f0db0 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -27,6 +27,7 @@
#include <cstdarg>
#include "target-select.h"
+#include "dwarf_reader.h"
#include "layout.h"
#include "output.h"
#include "symtab.h"
@@ -844,7 +845,7 @@ Sized_relobj<size, big_endian>::get_symbol_location_info(
else if (sym.get_st_shndx() == shndx
&& static_cast<off_t>(sym.get_st_value()) <= offset
&& (static_cast<off_t>(sym.get_st_value() + sym.get_st_size())
- >= offset))
+ > offset))
{
if (sym.get_st_name() > names_size)
info->enclosing_symbol_name = "(invalid)";
@@ -907,25 +908,54 @@ template<int size, bool big_endian>
std::string
Relocate_info<size, big_endian>::location(size_t, off_t offset) const
{
- // FIXME: We would like to print the following:
- // /tmp/foo.o: in function 'fn':foo.c:12: undefined reference to 'xxx'
- // We're missing line numbers.
+ // 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")
+ {
+ off_t debuglines_size;
+ const unsigned char* debuglines = this->object->section_contents(
+ shndx, &debuglines_size, false);
+ if (debuglines)
+ {
+ Dwarf_line_info line_info(debuglines, debuglines_size);
+ line_info.read_line_mappings<size, big_endian>();
+ file_and_lineno = line_info.addr2line(this->data_shndx, offset);
+ }
+ break;
+ }
+
std::string ret(this->object->name());
ret += ':';
Symbol_location_info info;
if (this->object->get_symbol_location_info(this->data_shndx, offset, &info))
{
ret += " in function ";
+ // We could demangle this name before printing, but we don't
+ // bother because gcc runs linker output through a demangle
+ // filter itself. The only advantage to demangling here is if
+ // someone might call ld directly, rather than via gcc. If we
+ // did want to demangle, cplus_demangle() is in libiberty.
ret += info.enclosing_symbol_name;
ret += ":";
- ret += info.source_file;
+ filename = info.source_file;
+ }
+
+ if (!file_and_lineno.empty())
+ ret += file_and_lineno;
+ else
+ {
+ if (!filename.empty())
+ ret += filename;
+ ret += "(";
+ ret += this->object->section_name(this->data_shndx);
+ char buf[100];
+ // Offsets into sections have to be positive.
+ snprintf(buf, sizeof(buf), "+0x%lx", static_cast<long>(offset));
+ ret += buf;
+ ret += ")";
}
- ret += "(";
- ret += this->object->section_name(this->data_shndx);
- char buf[100];
- // Offsets into sections have to be positive.
- snprintf(buf, sizeof(buf), "+0x%lx)", static_cast<long>(offset));
- ret += buf;
return ret;
}