diff options
author | Ian Lance Taylor <iant@google.com> | 2007-11-02 23:02:44 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2007-11-02 23:02:44 +0000 |
commit | 5c2c6c957be387f3649b143508a2b5c730c0b6f5 (patch) | |
tree | 50bcf3279038a085b36033f3b5005c61b9d51c9a /gold/object.cc | |
parent | 8942f2584cd5e11f2d512c5cf42747644be2735a (diff) | |
download | gdb-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.cc | 52 |
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; } |