aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/Makefile.am2
-rw-r--r--gold/Makefile.in19
-rw-r--r--gold/dwarf_reader.cc529
-rw-r--r--gold/dwarf_reader.h150
-rw-r--r--gold/object.cc52
-rw-r--r--gold/po/POTFILES.in2
-rw-r--r--gold/po/gold.pot458
7 files changed, 1022 insertions, 190 deletions
diff --git a/gold/Makefile.am b/gold/Makefile.am
index c9cde9c..a91a1c8 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -33,6 +33,7 @@ CCFILES = \
defstd.cc \
dirsearch.cc \
dynobj.cc \
+ dwarf_reader.cc \
ehframe.cc \
errors.cc \
fileread.cc \
@@ -60,6 +61,7 @@ HFILES = \
defstd.h \
dirsearch.h \
dynobj.h \
+ dwarf_reader.h \
ehframe.h \
errors.h \
fileread.h \
diff --git a/gold/Makefile.in b/gold/Makefile.in
index a7e3f73..9ca3701 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -71,14 +71,14 @@ ARFLAGS = cru
libgold_a_AR = $(AR) $(ARFLAGS)
libgold_a_LIBADD =
am__objects_1 = archive.$(OBJEXT) common.$(OBJEXT) defstd.$(OBJEXT) \
- dirsearch.$(OBJEXT) dynobj.$(OBJEXT) ehframe.$(OBJEXT) \
- errors.$(OBJEXT) fileread.$(OBJEXT) gold.$(OBJEXT) \
- gold-threads.$(OBJEXT) layout.$(OBJEXT) merge.$(OBJEXT) \
- object.$(OBJEXT) options.$(OBJEXT) output.$(OBJEXT) \
- parameters.$(OBJEXT) readsyms.$(OBJEXT) reloc.$(OBJEXT) \
- resolve.$(OBJEXT) script.$(OBJEXT) symtab.$(OBJEXT) \
- stringpool.$(OBJEXT) target-select.$(OBJEXT) version.$(OBJEXT) \
- workqueue.$(OBJEXT)
+ dirsearch.$(OBJEXT) dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) \
+ ehframe.$(OBJEXT) errors.$(OBJEXT) fileread.$(OBJEXT) \
+ gold.$(OBJEXT) gold-threads.$(OBJEXT) layout.$(OBJEXT) \
+ merge.$(OBJEXT) object.$(OBJEXT) options.$(OBJEXT) \
+ output.$(OBJEXT) parameters.$(OBJEXT) readsyms.$(OBJEXT) \
+ reloc.$(OBJEXT) resolve.$(OBJEXT) script.$(OBJEXT) \
+ symtab.$(OBJEXT) stringpool.$(OBJEXT) target-select.$(OBJEXT) \
+ version.$(OBJEXT) workqueue.$(OBJEXT)
am__objects_2 =
am__objects_3 = yyscript.$(OBJEXT)
am_libgold_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
@@ -287,6 +287,7 @@ CCFILES = \
defstd.cc \
dirsearch.cc \
dynobj.cc \
+ dwarf_reader.cc \
ehframe.cc \
errors.cc \
fileread.cc \
@@ -314,6 +315,7 @@ HFILES = \
defstd.h \
dirsearch.h \
dynobj.h \
+ dwarf_reader.h \
ehframe.h \
errors.h \
fileread.h \
@@ -462,6 +464,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defstd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirsearch.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynobj.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ehframe.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Po@am__quote@
diff --git a/gold/dwarf_reader.cc b/gold/dwarf_reader.cc
new file mode 100644
index 0000000..05809a7
--- /dev/null
+++ b/gold/dwarf_reader.cc
@@ -0,0 +1,529 @@
+// dwarf_reader.cc -- parse dwarf2/3 debug information
+
+// Copyright 2007 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#include "gold.h"
+
+#include "elfcpp_swap.h"
+#include "dwarf.h"
+#include "dwarf_reader.h"
+
+namespace {
+
+// Read an unsigned LEB128 number. Each byte contains 7 bits of
+// information, plus one bit saying whether the number continues or
+// not.
+
+uint64_t
+read_unsigned_LEB_128(const unsigned char* buffer, size_t* len)
+{
+ uint64_t result = 0;
+ size_t num_read = 0;
+ unsigned int shift = 0;
+ unsigned char byte;
+
+ do
+ {
+ byte = *buffer++;
+ num_read++;
+ result |= (static_cast<uint64_t>(byte & 0x7f)) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+
+ *len = num_read;
+
+ return result;
+}
+
+// Read a signed LEB128 number. These are like regular LEB128
+// numbers, except the last byte may have a sign bit set.
+
+int64_t
+read_signed_LEB_128(const unsigned char* buffer, size_t* len)
+{
+ int64_t result = 0;
+ int shift = 0;
+ size_t num_read = 0;
+ unsigned char byte;
+
+ do
+ {
+ byte = *buffer++;
+ num_read++;
+ result |= (static_cast<uint64_t>(byte & 0x7f) << shift);
+ shift += 7;
+ }
+ while (byte & 0x80);
+
+ if ((shift < 8 * static_cast<int>(sizeof(result))) && (byte & 0x40))
+ result |= -((static_cast<int64_t>(1)) << shift);
+ *len = num_read;
+ return result;
+}
+
+} // End anonymous namespace.
+
+
+namespace gold {
+
+// This is the format of a DWARF2/3 line state machine that we process
+// opcodes using. There is no need for anything outside the lineinfo
+// processor to know how this works.
+
+struct LineStateMachine
+{
+ int file_num;
+ uint64_t address;
+ int line_num;
+ int column_num;
+ unsigned int shndx; // the section address refers to
+ bool is_stmt; // stmt means statement.
+ bool basic_block;
+ bool end_sequence;
+};
+
+static void
+ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt)
+{
+ lsm->file_num = 1;
+ lsm->address = 0;
+ lsm->line_num = 1;
+ lsm->column_num = 0;
+ lsm->shndx = -1;
+ lsm->is_stmt = default_is_stmt;
+ lsm->basic_block = false;
+ lsm->end_sequence = false;
+}
+
+// Read the DWARF header.
+
+template<int size, bool big_endian>
+const unsigned char*
+Dwarf_line_info::read_header_prolog(const unsigned char* lineptr)
+{
+ uint32_t initial_length = elfcpp::Swap<32, big_endian>::readval(lineptr);
+ lineptr += 4;
+
+ // In DWARF2/3, if the initial length is all 1 bits, then the offset
+ // size is 8 and we need to read the next 8 bytes for the real length.
+ if (initial_length == 0xffffffff)
+ {
+ header_.offset_size = 8;
+ initial_length = elfcpp::Swap<64, big_endian>::readval(lineptr);
+ lineptr += 8;
+ }
+ else
+ header_.offset_size = 4;
+
+ header_.total_length = initial_length;
+
+ gold_assert(lineptr + header_.total_length <= buffer_end_);
+
+ header_.version = elfcpp::Swap<16, big_endian>::readval(lineptr);
+ lineptr += 2;
+
+ if (header_.offset_size == 4)
+ header_.prologue_length = elfcpp::Swap<32, big_endian>::readval(lineptr);
+ else
+ header_.prologue_length = elfcpp::Swap<64, big_endian>::readval(lineptr);
+ lineptr += header_.offset_size;
+
+ header_.min_insn_length = *lineptr;
+ lineptr += 1;
+
+ header_.default_is_stmt = *lineptr;
+ lineptr += 1;
+
+ header_.line_base = *reinterpret_cast<const signed char*>(lineptr);
+ lineptr += 1;
+
+ header_.line_range = *lineptr;
+ lineptr += 1;
+
+ header_.opcode_base = *lineptr;
+ lineptr += 1;
+
+ header_.std_opcode_lengths.reserve(header_.opcode_base + 1);
+ header_.std_opcode_lengths[0] = 0;
+ for (int i = 1; i < header_.opcode_base; i++)
+ {
+ header_.std_opcode_lengths[i] = *lineptr;
+ lineptr += 1;
+ }
+
+ return lineptr;
+}
+
+// The header for a debug_line section is mildly complicated, because
+// the line info is very tightly encoded.
+
+const unsigned char*
+Dwarf_line_info::read_header_tables(const unsigned char* lineptr)
+{
+ // It is legal for the directory entry table to be empty.
+ if (*lineptr)
+ {
+ int dirindex = 1;
+ while (*lineptr)
+ {
+ const unsigned char* dirname = lineptr;
+ gold_assert(dirindex == static_cast<int>(directories_.size()));
+ directories_.push_back(reinterpret_cast<const char*>(dirname));
+ lineptr += directories_.back().size() + 1;
+ dirindex++;
+ }
+ }
+ lineptr++;
+
+ // It is also legal for the file entry table to be empty.
+ if (*lineptr)
+ {
+ int fileindex = 1;
+ size_t len;
+ while (*lineptr)
+ {
+ const char* filename = reinterpret_cast<const char*>(lineptr);
+ lineptr += strlen(filename) + 1;
+
+ uint64_t dirindex = read_unsigned_LEB_128(lineptr, &len);
+ if (dirindex >= directories_.size())
+ dirindex = 0;
+ lineptr += len;
+
+ read_unsigned_LEB_128(lineptr, &len); // mod_time
+ lineptr += len;
+
+ read_unsigned_LEB_128(lineptr, &len); // filelength
+ lineptr += len;
+
+ gold_assert(fileindex == static_cast<int>(files_.size()));
+ files_.push_back(std::pair<int, std::string>(dirindex, filename));
+ fileindex++;
+ }
+ }
+ lineptr++;
+
+ return lineptr;
+}
+
+// Process a single opcode in the .debug.line structure.
+
+// Templating on size and big_endian would yield more efficient (and
+// simpler) code, but would bloat the binary. Speed isn't important
+// here.
+
+bool
+Dwarf_line_info::process_one_opcode(int size, bool big_endian,
+ const unsigned char* start,
+ struct LineStateMachine* lsm,
+ size_t* len)
+{
+ size_t oplen = 0;
+ size_t templen;
+ unsigned char opcode = *start;
+ oplen++;
+ start++;
+
+ // If the opcode is great than the opcode_base, it is a special
+ // opcode. Most line programs consist mainly of special opcodes.
+ if (opcode >= header_.opcode_base)
+ {
+ opcode -= header_.opcode_base;
+ const int advance_address = ((opcode / header_.line_range)
+ * header_.min_insn_length);
+ lsm->address += advance_address;
+
+ const int advance_line = ((opcode % header_.line_range)
+ + header_.line_base);
+ lsm->line_num += advance_line;
+ lsm->basic_block = true;
+ *len = oplen;
+ return true;
+ }
+
+ // Otherwise, we have the regular opcodes
+ switch (opcode)
+ {
+ case elfcpp::DW_LNS_copy:
+ lsm->basic_block = false;
+ *len = oplen;
+ return true;
+
+ case elfcpp::DW_LNS_advance_pc:
+ {
+ const uint64_t advance_address
+ = read_unsigned_LEB_128(start, &templen);
+ oplen += templen;
+ lsm->address += header_.min_insn_length * advance_address;
+ }
+ break;
+
+ case elfcpp::DW_LNS_advance_line:
+ {
+ const uint64_t advance_line = read_signed_LEB_128(start, &templen);
+ oplen += templen;
+ lsm->line_num += advance_line;
+ }
+ break;
+
+ case elfcpp::DW_LNS_set_file:
+ {
+ const uint64_t fileno = read_unsigned_LEB_128(start, &templen);
+ oplen += templen;
+ lsm->file_num = fileno;
+ }
+ break;
+
+ case elfcpp::DW_LNS_set_column:
+ {
+ const uint64_t colno = read_unsigned_LEB_128(start, &templen);
+ oplen += templen;
+ lsm->column_num = colno;
+ }
+ break;
+
+ case elfcpp::DW_LNS_negate_stmt:
+ lsm->is_stmt = !lsm->is_stmt;
+ break;
+
+ case elfcpp::DW_LNS_set_basic_block:
+ lsm->basic_block = true;
+ break;
+
+ case elfcpp::DW_LNS_fixed_advance_pc:
+ {
+ int advance_address;
+ if (big_endian)
+ advance_address = elfcpp::Swap<16, true>::readval(start);
+ else
+ advance_address = elfcpp::Swap<16, false>::readval(start);
+ oplen += 2;
+ lsm->address += advance_address;
+ }
+ break;
+
+ case elfcpp::DW_LNS_const_add_pc:
+ {
+ const int advance_address = (header_.min_insn_length
+ * ((255 - header_.opcode_base)
+ / header_.line_range));
+ lsm->address += advance_address;
+ }
+ break;
+
+ case elfcpp::DW_LNS_extended_op:
+ {
+ const uint64_t extended_op_len
+ = read_unsigned_LEB_128(start, &templen);
+ start += templen;
+ oplen += templen + extended_op_len;
+
+ const unsigned char extended_op = *start;
+ start++;
+
+ switch (extended_op)
+ {
+ case elfcpp::DW_LNE_end_sequence:
+ lsm->end_sequence = true;
+ *len = oplen;
+ return true;
+
+ case elfcpp::DW_LNE_set_address:
+ // FIXME: modify the address based on the reloc
+ if (size == 32 && big_endian == false)
+ lsm->address = elfcpp::Swap<32, false>::readval(start);
+ else if (size == 32 && big_endian == true)
+ lsm->address = elfcpp::Swap<32, true>::readval(start);
+ else if (size == 64 && big_endian == false)
+ lsm->address = elfcpp::Swap<64, false>::readval(start);
+ else if (size == 64 && big_endian == true)
+ lsm->address = elfcpp::Swap<64, true>::readval(start);
+ else
+ gold_assert(false); // We need to implement more cases, then.
+ // FIXME: set lsm->shndx from the reloc
+ lsm->shndx = 1;
+ break;
+
+ case elfcpp::DW_LNE_define_file:
+ {
+ const char* filename = reinterpret_cast<const char*>(start);
+ templen = strlen(filename) + 1;
+ start += templen;
+
+ uint64_t dirindex = read_unsigned_LEB_128(start, &templen);
+ if (dirindex >= directories_.size())
+ dirindex = 0;
+ oplen += templen;
+
+ read_unsigned_LEB_128(start, &templen); // mod_time
+ oplen += templen;
+
+ read_unsigned_LEB_128(start, &templen); // filelength
+ oplen += templen;
+
+ files_.push_back(std::pair<int, std::string>(dirindex,
+ filename));
+ }
+ break;
+ }
+ }
+ break;
+
+ default:
+ {
+ // Ignore unknown opcode silently
+ for (int i = 0; i < header_.std_opcode_lengths[opcode]; i++)
+ {
+ size_t templen;
+ read_unsigned_LEB_128(start, &templen);
+ start += templen;
+ oplen += templen;
+ }
+ }
+ break;
+ }
+ *len = oplen;
+ return false;
+}
+
+// Read the debug information at LINEPTR and store it in the line
+// number map.
+
+unsigned const char*
+Dwarf_line_info::read_lines(int size, bool big_endian,
+ unsigned const char* lineptr)
+{
+ struct LineStateMachine lsm;
+
+ // LENGTHSTART is the place the length field is based on. It is the
+ // point in the header after the initial length field.
+ const unsigned char* lengthstart = buffer_;
+
+ // In 64 bit dwarf, the initial length is 12 bytes, because of the
+ // 0xffffffff at the start.
+ if (header_.offset_size == 8)
+ lengthstart += 12;
+ else
+ lengthstart += 4;
+
+ while (lineptr < lengthstart + header_.total_length)
+ {
+ ResetLineStateMachine(&lsm, header_.default_is_stmt);
+ while (!lsm.end_sequence)
+ {
+ size_t oplength;
+ bool add_line = this->process_one_opcode(size, big_endian,
+ lineptr, &lsm, &oplength);
+ if (add_line)
+ {
+ Offset_to_lineno_entry entry
+ = { lsm.address, lsm.file_num, lsm.line_num };
+ line_number_map_[lsm.shndx].push_back(entry);
+ }
+ lineptr += oplength;
+ }
+ }
+
+ return lengthstart + header_.total_length;
+}
+
+// Called after all line numbers have been read.
+
+void
+Dwarf_line_info::finalize_line_number_map()
+{
+ for (Lineno_map::iterator it = line_number_map_.begin();
+ it != line_number_map_.end();
+ ++it)
+ // Each vector needs to be sorted by offset.
+ sort(it->second.begin(), it->second.end());
+}
+
+// Return a string for a file name and line number.
+
+std::string
+Dwarf_line_info::addr2line(unsigned int shndx, off_t offset)
+{
+ const Offset_to_lineno_entry lookup_key = { offset, 0, 0 };
+ std::vector<Offset_to_lineno_entry>& offsets = line_number_map_[shndx];
+ std::vector<Offset_to_lineno_entry>::const_iterator it
+ = std::lower_bound(offsets.begin(), offsets.end(), lookup_key);
+
+ // If we found an exact match, great, otherwise find the last entry
+ // before the passed-in offset.
+ if (it->offset > offset)
+ {
+ if (it == offsets.begin())
+ return "";
+ --it;
+ gold_assert(it->offset < offset);
+ }
+
+ // Convert the file_num + line_num into a string.
+ std::string ret;
+ gold_assert(it->file_num < static_cast<int>(files_.size()));
+ const std::pair<int, std::string>& filename_pair = files_[it->file_num];
+ gold_assert(filename_pair.first < static_cast<int>(directories_.size()));
+ const std::string& dirname = directories_[filename_pair.first];
+ const std::string& filename = filename_pair.second;
+ if (!dirname.empty())
+ {
+ ret += dirname;
+ ret += "/";
+ }
+ ret += filename;
+ if (ret.empty())
+ ret = "(unknown)";
+
+ char buffer[64]; // enough to hold a line number
+ snprintf(buffer, sizeof(buffer), "%d", it->line_num);
+ ret += ":";
+ ret += buffer;
+
+ return ret;
+}
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+const unsigned char*
+Dwarf_line_info::read_header_prolog<32, false>(const unsigned char* lineptr);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+const unsigned char*
+Dwarf_line_info::read_header_prolog<32, true>(const unsigned char* lineptr);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+const unsigned char*
+Dwarf_line_info::read_header_prolog<64, false>(const unsigned char* lineptr);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+const unsigned char*
+Dwarf_line_info::read_header_prolog<64, true>(const unsigned char* lineptr);
+#endif
+
+} // End namespace gold.
diff --git a/gold/dwarf_reader.h b/gold/dwarf_reader.h
new file mode 100644
index 0000000..a367715
--- /dev/null
+++ b/gold/dwarf_reader.h
@@ -0,0 +1,150 @@
+// dwarf_reader.h -- parse dwarf2/3 debug information for gold -*- C++ -*-
+
+// Copyright 2007 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#ifndef GOLD_DWARF_READER_H
+#define GOLD_DWARF_READER_H
+
+#include <vector>
+
+#include "elfcpp_swap.h"
+#include "dwarf.h"
+
+namespace gold
+{
+
+struct LineStateMachine;
+
+// This class is used to read the line information from the debugging
+// section of an object file.
+
+class Dwarf_line_info
+{
+ public:
+ // Initializes a .debug_line reader. Buffer and buffer length point
+ // to the beginning and length of the line information to read.
+ // Reader is a ByteReader class that has the endianness set
+ // properly.
+ Dwarf_line_info(const unsigned char* buffer, off_t buffer_length)
+ : buffer_(buffer), buffer_end_(buffer + buffer_length),
+ directories_(1), files_(1)
+ { }
+
+ // Start processing line info, and populates the offset_map_.
+ template<int size, bool big_endian>
+ void
+ read_line_mappings()
+ {
+ while (buffer_ < buffer_end_)
+ {
+ const unsigned char* lineptr = buffer_;
+ lineptr = this->read_header_prolog<size, big_endian>(lineptr);
+ lineptr = this->read_header_tables(lineptr);
+ lineptr = this->read_lines(size, big_endian, lineptr);
+ buffer_ = lineptr;
+ }
+ finalize_line_number_map();
+ }
+
+ // Given a section number and an offset, returns the associated
+ // file and line-number, as a string: "file:lineno". If unable
+ // to do the mapping, returns the empty string. You must call
+ // read_line_mappings() before calling this function.
+ std::string
+ addr2line(unsigned int shndx, off_t offset);
+
+ private:
+ // Reads the DWARF2/3 header for this line info. Each takes as input
+ // a starting buffer position, and returns the ending position.
+ template<int size, bool big_endian>
+ const unsigned char*
+ read_header_prolog(const unsigned char* lineptr);
+
+ const unsigned char*
+ read_header_tables(const unsigned char* lineptr);
+
+ // Reads the DWARF2/3 line information.
+ const unsigned char*
+ read_lines(int size, bool big_endian, const unsigned char* lineptr);
+
+ // Process a single line info opcode at START using the state
+ // machine at LSM. Return true if we should define a line using the
+ // current state of the line state machine. Place the length of the
+ // opcode in LEN.
+ bool
+ process_one_opcode(int size, bool big_endian,
+ const unsigned char* start,
+ struct LineStateMachine* lsm, size_t* len);
+
+ // Called after all line number have been read, to ready
+ // line_number_map_ for calls to addr2line().
+ void
+ finalize_line_number_map();
+
+ // A DWARF2/3 line info header. This is not the same size as in the
+ // actual file, as the one in the file may have a 32 bit or 64 bit
+ // lengths.
+
+ struct Dwarf_line_infoHeader
+ {
+ off_t total_length;
+ int version;
+ off_t prologue_length;
+ int min_insn_length; // insn stands for instructin
+ bool default_is_stmt; // stmt stands for statement
+ signed char line_base;
+ int line_range;
+ unsigned char opcode_base;
+ std::vector<unsigned char> std_opcode_lengths;
+ int offset_size;
+ } header_;
+
+ // buffer is the buffer for our line info, starting at exactly where
+ // the line info to read is.
+ const unsigned char* buffer_;
+ const unsigned char* const buffer_end_;
+
+ // Holds the directories and files as we see them.
+ std::vector<std::string> directories_;
+ // The first part is an index into directories_, the second the filename.
+ std::vector< std::pair<int, std::string> > files_;
+
+ // We can't do better than to keep the offsets in a sorted vector.
+ // Here, offset is the key, and file_num/line_num is the value.
+ struct Offset_to_lineno_entry
+ {
+ off_t offset;
+ int file_num; // a pointer into files_
+ int line_num;
+ // Offsets are unique within a section, so that's a sufficient sort key.
+ bool operator<(const Offset_to_lineno_entry& that) const
+ { return this->offset < that.offset; }
+ };
+ // We have a vector of offset->lineno entries for every input section.
+ typedef Unordered_map<unsigned int, std::vector<Offset_to_lineno_entry> >
+ Lineno_map;
+
+ Lineno_map line_number_map_;
+};
+
+} // End namespace gold.
+
+#endif // !defined(GOLD_DWARF_READER_H)
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;
}
diff --git a/gold/po/POTFILES.in b/gold/po/POTFILES.in
index bb32fdf..a78d65d 100644
--- a/gold/po/POTFILES.in
+++ b/gold/po/POTFILES.in
@@ -6,6 +6,8 @@ defstd.cc
defstd.h
dirsearch.cc
dirsearch.h
+dwarf_reader.cc
+dwarf_reader.h
dynobj.cc
dynobj.h
ehframe.cc
diff --git a/gold/po/gold.pot b/gold/po/gold.pot
index 12770a6..d79701c 100644
--- a/gold/po/gold.pot
+++ b/gold/po/gold.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-10-13 23:40-0700\n"
+"POT-Creation-Date: 2007-11-02 16:01-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -38,7 +38,7 @@ msgstr ""
#: archive.cc:199
#, c-format
-msgid "%s: malformed archive header name at %zu\n"
+msgid "%s: malformed archive header name at %zu"
msgstr ""
#: archive.cc:224
@@ -105,7 +105,7 @@ msgstr ""
msgid "dynamic symbol table name section has wrong type: %u"
msgstr ""
-#: dynobj.cc:365 object.cc:428
+#: dynobj.cc:365 object.cc:447
#, c-format
msgid "bad section name offset for section %u: %lu"
msgstr ""
@@ -169,7 +169,7 @@ msgstr ""
msgid "size of dynamic symbols is not multiple of symbol size"
msgstr ""
-#: dynobj.cc:1253
+#: dynobj.cc:1265
#, c-format
msgid "symbol %s has undefined version %s"
msgstr ""
@@ -229,19 +229,19 @@ msgstr ""
msgid "%s: maximum bytes mapped for read at one time: %llu\n"
msgstr ""
-#: fileread.cc:441
+#: fileread.cc:442
#, c-format
-msgid "cannot find -l%s\n"
+msgid "cannot find -l%s"
msgstr ""
-#: fileread.cc:468
+#: fileread.cc:469
#, c-format
-msgid "cannot find %s\n"
+msgid "cannot find %s"
msgstr ""
-#: fileread.cc:479
+#: fileread.cc:480
#, c-format
-msgid "cannot open %s: %s\n"
+msgid "cannot open %s: %s"
msgstr ""
#: gold.cc:72
@@ -249,468 +249,576 @@ msgstr ""
msgid "%s: internal error in %s, at %s:%d\n"
msgstr ""
-#: gold.cc:118
+#. We had some input files, but we weren't able to open any of
+#. them.
+#: gold.cc:118 gold.cc:164
msgid "no input files"
msgstr ""
#. We print out just the first .so we see; there may be others.
-#: gold.cc:161
+#: gold.cc:179
#, c-format
msgid "cannot mix -static with dynamic object %s"
msgstr ""
-#: gold-threads.cc:66
-msgid "pthead_mutextattr_init failed"
-msgstr ""
-
#: gold-threads.cc:69
-msgid "pthread_mutextattr_settype failed"
+#, c-format
+msgid "pthead_mutextattr_init failed: %s"
msgstr ""
-#: gold-threads.cc:73
-msgid "pthread_mutex_init failed"
+#: gold-threads.cc:72
+#, c-format
+msgid "pthread_mutextattr_settype failed: %s"
msgstr ""
#: gold-threads.cc:76
-msgid "pthread_mutexattr_destroy failed"
+#, c-format
+msgid "pthread_mutex_init failed: %s"
msgstr ""
-#: gold-threads.cc:82
-msgid "pthread_mutex_destroy failed"
+#: gold-threads.cc:79
+#, c-format
+msgid "pthread_mutexattr_destroy failed: %s"
msgstr ""
-#: gold-threads.cc:89
-msgid "pthread_mutex_lock failed"
+#: gold-threads.cc:85
+#, c-format
+msgid "pthread_mutex_destroy failed: %s"
msgstr ""
-#: gold-threads.cc:96
-msgid "pthread_mutex_unlock failed"
+#: gold-threads.cc:92
+#, c-format
+msgid "pthread_mutex_lock failed: %s"
msgstr ""
-#: gold-threads.cc:177
-msgid "pthread_cond_init failed"
+#: gold-threads.cc:99
+#, c-format
+msgid "pthread_mutex_unlock failed: %s"
msgstr ""
-#: gold-threads.cc:183
-msgid "pthread_cond_destroy failed"
+#: gold-threads.cc:180
+#, c-format
+msgid "pthread_cond_init failed: %s"
+msgstr ""
+
+#: gold-threads.cc:186
+#, c-format
+msgid "pthread_cond_destroy failed: %s"
msgstr ""
-#: gold-threads.cc:190
-msgid "pthread_cond_wait failed"
+#: gold-threads.cc:193
+#, c-format
+msgid "pthread_cond_wait failed: %s"
msgstr ""
-#: gold-threads.cc:197
-msgid "pthread_cond_signal failed"
+#: gold-threads.cc:200
+#, c-format
+msgid "pthread_cond_signal failed: %s"
msgstr ""
#. FIXME: This needs to specify the location somehow.
-#: i386.cc:142 i386.cc:1160 x86_64.cc:1138
+#: i386.cc:150 i386.cc:1296 x86_64.cc:162 x86_64.cc:1228
msgid "missing expected TLS relocation"
msgstr ""
-#: i386.cc:728 x86_64.cc:700 x86_64.cc:840
+#: i386.cc:746 x86_64.cc:709 x86_64.cc:876
#, c-format
msgid "%s: unsupported reloc %u against local symbol"
msgstr ""
-#: i386.cc:782
+#: i386.cc:840 i386.cc:1070 x86_64.cc:817 x86_64.cc:1055
#, c-format
-msgid "%s: unexpected reloc %u in object file\n"
+msgid "%s: unexpected reloc %u in object file"
msgstr ""
-#: i386.cc:870 x86_64.cc:854 x86_64.cc:1024
+#: i386.cc:926 x86_64.cc:890 x86_64.cc:1114
#, c-format
msgid "%s: unsupported reloc %u against global symbol %s"
msgstr ""
-#: i386.cc:974 x86_64.cc:778 x86_64.cc:965
-#, c-format
-msgid "%s: unexpected reloc %u in object file"
-msgstr ""
-
-#: i386.cc:1070
+#: i386.cc:1166
#, c-format
msgid "%s: unsupported RELA reloc section"
msgstr ""
-#: i386.cc:1252 x86_64.cc:1315
+#: i386.cc:1423 x86_64.cc:1426
#, c-format
msgid "unexpected reloc %u in object file"
msgstr ""
-#: i386.cc:1284 i386.cc:1343 i386.cc:1356 i386.cc:1376 i386.cc:1397
-#: x86_64.cc:1337 x86_64.cc:1404 x86_64.cc:1413
+#: i386.cc:1455 i386.cc:1502 i386.cc:1509 i386.cc:1529 i386.cc:1558
+#: x86_64.cc:1447 x86_64.cc:1496 x86_64.cc:1507
#, c-format
msgid "unsupported reloc %u"
msgstr ""
-#: i386.cc:1309 x86_64.cc:1362
+#: i386.cc:1480 x86_64.cc:1472
msgid "TLS reloc but no TLS segment"
msgstr ""
-#: i386.cc:1364
+#: i386.cc:1517
msgid "both SUN and GNU model TLS relocations"
msgstr ""
-#: merge.cc:254
+#: merge.cc:258
msgid "mergeable string section length not multiple of character size"
msgstr ""
-#: merge.cc:269
+#: merge.cc:274
msgid "entry in mergeable string section not null terminated"
msgstr ""
-#: object.cc:49
+#: object.cc:50
#, c-format
msgid "%s: unsupported ELF machine number %d"
msgstr ""
-#: object.cc:67
+#: object.cc:68 script.cc:1222
#, c-format
msgid "%s: %s"
msgstr ""
-#: object.cc:102
+#: object.cc:103
#, c-format
msgid "section name section has wrong type: %u"
msgstr ""
-#: object.cc:243
+#: object.cc:244
#, c-format
msgid "invalid symbol table name index: %u"
msgstr ""
-#: object.cc:249
+#: object.cc:250
#, c-format
msgid "symbol table name section has wrong type: %u"
msgstr ""
-#: object.cc:304
+#: object.cc:305
#, c-format
msgid "section group %u info %u out of range"
msgstr ""
-#: object.cc:322
+#: object.cc:323
#, c-format
msgid "symbol %u name offset %u out of range"
msgstr ""
-#: object.cc:354
+#: object.cc:355
#, c-format
msgid "section %u in section group %u out of range"
msgstr ""
-#: object.cc:494
+#: object.cc:525
msgid "size of symbols is not multiple of symbol size"
msgstr ""
#. FIXME: Handle SHN_XINDEX.
-#: object.cc:584
+#: object.cc:615
#, c-format
msgid "unknown section index %u for local symbol %u"
msgstr ""
-#: object.cc:593
+#: object.cc:624
#, c-format
msgid "local symbol %u section index %u out of range"
msgstr ""
-#: object.cc:625
+#: object.cc:656
#, c-format
msgid "local symbol %u section name out of range: %u >= %u"
msgstr ""
-#: object.cc:805
+#: object.cc:892
#, c-format
msgid "%s: incompatible target"
msgstr ""
-#: object.cc:872
+#: object.cc:994
#, c-format
msgid "%s: unsupported ELF file type %d"
msgstr ""
-#: object.cc:891 object.cc:937 object.cc:971
+#: object.cc:1013 object.cc:1059 object.cc:1093
#, c-format
msgid "%s: ELF file too short"
msgstr ""
-#: object.cc:899
+#: object.cc:1021
#, c-format
msgid "%s: invalid ELF version 0"
msgstr ""
-#: object.cc:901
+#: object.cc:1023
#, c-format
msgid "%s: unsupported ELF version %d"
msgstr ""
-#: object.cc:908
+#: object.cc:1030
#, c-format
msgid "%s: invalid ELF class 0"
msgstr ""
-#: object.cc:914
+#: object.cc:1036
#, c-format
msgid "%s: unsupported ELF class %d"
msgstr ""
-#: object.cc:921
+#: object.cc:1043
#, c-format
msgid "%s: invalid ELF data encoding"
msgstr ""
-#: object.cc:927
+#: object.cc:1049
#, c-format
msgid "%s: unsupported ELF data encoding %d"
msgstr ""
-#: object.cc:947
+#: object.cc:1069
#, c-format
msgid "%s: not configured to support 32-bit big-endian object"
msgstr ""
-#: object.cc:960
+#: object.cc:1082
#, c-format
msgid "%s: not configured to support 32-bit little-endian object"
msgstr ""
-#: object.cc:981
+#: object.cc:1103
#, c-format
msgid "%s: not configured to support 64-bit big-endian object"
msgstr ""
-#: object.cc:994
+#: object.cc:1116
#, c-format
msgid "%s: not configured to support 64-bit little-endian object"
msgstr ""
-#: options.cc:139
+#: options.cc:142
+#, c-format
+msgid "%s: unable to parse script file %s\n"
+msgstr ""
+
+#: options.cc:170
#, c-format
msgid ""
"Usage: %s [options] file...\n"
"Options:\n"
msgstr ""
-#: options.cc:309
-msgid "Search for library LIBNAME"
+#: options.cc:341
+msgid "Only set DT_NEEDED for dynamic libs if used"
msgstr ""
-#: options.cc:310
-msgid "-lLIBNAME, --library LIBNAME"
+#: options.cc:344
+msgid "Always DT_NEEDED for dynamic libs (default)"
msgstr ""
-#: options.cc:312
-msgid "Start a library search group"
+#: options.cc:347
+msgid "-l searches for shared libraries"
msgstr ""
-#: options.cc:314
-msgid "End a library search group"
+#: options.cc:351
+msgid "-l does not search for shared libraries"
msgstr ""
-#: options.cc:316
+#: options.cc:354
+msgid "Bind defined symbols locally"
+msgstr ""
+
+#: options.cc:356
msgid "Export all dynamic symbols"
msgstr ""
-#: options.cc:318
+#: options.cc:358
+msgid "Create exception frame header"
+msgstr ""
+
+#: options.cc:360
msgid "Set dynamic linker path"
msgstr ""
-#: options.cc:319
+#: options.cc:361
msgid "-I PROGRAM, --dynamic-linker PROGRAM"
msgstr ""
-#: options.cc:321
+#: options.cc:363
+msgid "Search for library LIBNAME"
+msgstr ""
+
+#: options.cc:364
+msgid "-lLIBNAME, --library LIBNAME"
+msgstr ""
+
+#: options.cc:366
msgid "Add directory to search path"
msgstr ""
-#: options.cc:322
+#: options.cc:367
msgid "-L DIR, --library-path DIR"
msgstr ""
-#: options.cc:324
+#: options.cc:369
msgid "Ignored for compatibility"
msgstr ""
-#: options.cc:326
-msgid "Optimize output file size"
+#: options.cc:371
+msgid "Set output file name"
msgstr ""
-#: options.cc:327
-msgid "-O level"
+#: options.cc:372
+msgid "-o FILE, --output FILE"
msgstr ""
-#: options.cc:329
-msgid "Set output file name"
+#: options.cc:374
+msgid "Optimize output file size"
msgstr ""
-#: options.cc:330
-msgid "-o FILE, --output FILE"
+#: options.cc:375
+msgid "-O level"
msgstr ""
-#: options.cc:332
+#: options.cc:377
msgid "Generate relocatable output"
msgstr ""
-#: options.cc:334
+#: options.cc:379
msgid "Add DIR to runtime search path"
msgstr ""
-#: options.cc:335
+#: options.cc:380
msgid "-R DIR, -rpath DIR"
msgstr ""
-#: options.cc:337
-msgid "Strip all symbols"
-msgstr ""
-
-#: options.cc:339
-msgid "Strip debugging information"
+#: options.cc:383
+msgid "Add DIR to link time shared library search path"
msgstr ""
-#: options.cc:341
-msgid "Create exception frame header"
+#: options.cc:384
+msgid "--rpath-link DIR"
msgstr ""
-#: options.cc:344
-msgid "Add DIR to link time shared library search path"
+#: options.cc:386
+msgid "Strip all symbols"
msgstr ""
-#: options.cc:345
-msgid "--rpath-link DIR"
+#: options.cc:388
+msgid "Strip debugging information"
msgstr ""
-#: options.cc:347
+#: options.cc:390
msgid "Generate shared library"
msgstr ""
-#: options.cc:349
+#: options.cc:392
msgid "Do not link against shared libraries"
msgstr ""
-#: options.cc:351
+#: options.cc:394
msgid "Print resource usage statistics"
msgstr ""
-#: options.cc:353
+#: options.cc:396
msgid "Set target system root directory"
msgstr ""
-#: options.cc:354
+#: options.cc:397
msgid "--sysroot DIR"
msgstr ""
-#: options.cc:356
-msgid "Only set DT_NEEDED for dynamic libs if used"
+#: options.cc:398
+msgid "Set the address of the .text section"
msgstr ""
-#: options.cc:359
-msgid "Always DT_NEEDED for dynamic libs (default)"
+#: options.cc:399
+msgid "-Ttext ADDRESS"
+msgstr ""
+
+#. This must come after -Ttext since it's a prefix of it.
+#: options.cc:402
+msgid "Read linker script"
+msgstr ""
+
+#: options.cc:403
+msgid "-T FILE, --script FILE"
+msgstr ""
+
+#: options.cc:405
+msgid "Run the linker multi-threaded"
+msgstr ""
+
+#: options.cc:407
+msgid "Do not run the linker multi-threaded"
+msgstr ""
+
+#: options.cc:409
+msgid "Number of threads to use"
+msgstr ""
+
+#: options.cc:410
+msgid "--thread-count COUNT"
+msgstr ""
+
+#: options.cc:413
+msgid "Number of threads to use in initial pass"
+msgstr ""
+
+#: options.cc:414
+msgid "--thread-count-initial COUNT"
+msgstr ""
+
+#: options.cc:417
+msgid "Number of threads to use in middle pass"
+msgstr ""
+
+#: options.cc:418
+msgid "--thread-count-middle COUNT"
+msgstr ""
+
+#: options.cc:421
+msgid "Number of threads to use in final pass"
+msgstr ""
+
+#: options.cc:422
+msgid "--thread-count-final COUNT"
msgstr ""
-#: options.cc:362
+#: options.cc:425
msgid "Include all archive contents"
msgstr ""
-#: options.cc:366
+#: options.cc:429
msgid "Include only needed archive contents"
msgstr ""
-#: options.cc:369
+#: options.cc:434
+msgid ""
+"Subcommands as follows:\n"
+" -z execstack Mark output as requiring executable stack\n"
+" -z noexecstack Mark output as not requiring executable stack"
+msgstr ""
+
+#: options.cc:437
+msgid "-z SUBCOMMAND"
+msgstr ""
+
+#: options.cc:440
+msgid "Start a library search group"
+msgstr ""
+
+#: options.cc:442
+msgid "End a library search group"
+msgstr ""
+
+#: options.cc:444
msgid "Report usage information"
msgstr ""
-#: options.cc:371
+#: options.cc:446
msgid "Report version information"
msgstr ""
-#: options.cc:576
+#: options.cc:518
+#, c-format
+msgid "%s: unrecognized -z subcommand: %s\n"
+msgstr ""
+
+#: options.cc:698
msgid "unexpected argument"
msgstr ""
-#: options.cc:583 options.cc:634 options.cc:735
+#: options.cc:705 options.cc:757 options.cc:838
msgid "missing argument"
msgstr ""
-#: options.cc:596 options.cc:643
+#: options.cc:718 options.cc:766
msgid "unknown option"
msgstr ""
-#: options.cc:651
+#: options.cc:784
#, c-format
-msgid "%s: missing group end"
+msgid "%s: missing group end\n"
msgstr ""
-#: options.cc:748
+#: options.cc:912
msgid "may not nest groups"
msgstr ""
-#: options.cc:758
+#: options.cc:922
msgid "group end without group start"
msgstr ""
-#: options.cc:768
+#: options.cc:932
#, c-format
msgid "%s: use the --help option for usage information\n"
msgstr ""
-#: options.cc:777
+#: options.cc:941
#, c-format
msgid "%s: %s: %s\n"
msgstr ""
-#: options.cc:786
+#: options.cc:950
#, c-format
msgid "%s: -%c: %s\n"
msgstr ""
-#: output.cc:1031
+#: options.h:338
+#, c-format
+msgid "%s: invalid argument to -Ttext: %s\n"
+msgstr ""
+
+#: options.h:351
+#, c-format
+msgid "%s: invalid thread count: %s\n"
+msgstr ""
+
+#: output.cc:1038
#, c-format
msgid "invalid alignment %lu for section \"%s\""
msgstr ""
-#: output.cc:1697
+#: output.cc:1703
#, c-format
msgid "%s: open: %s"
msgstr ""
-#: output.cc:1702
+#: output.cc:1708
#, c-format
msgid "%s: lseek: %s"
msgstr ""
-#: output.cc:1705
+#: output.cc:1711
#, c-format
msgid "%s: write: %s"
msgstr ""
-#: output.cc:1711
+#: output.cc:1717
#, c-format
msgid "%s: mmap: %s"
msgstr ""
-#: output.cc:1721
+#: output.cc:1727
#, c-format
-msgid "%s: munmap: %s\n"
+msgid "%s: munmap: %s"
msgstr ""
-#: output.cc:1725
+#: output.cc:1731
#, c-format
msgid "%s: close: %s"
msgstr ""
-#: readsyms.cc:94
+#: readsyms.cc:147
#, c-format
msgid "%s: file is empty"
msgstr ""
-#: readsyms.cc:129
+#: readsyms.cc:182
#, c-format
msgid "%s: ordinary object found in input group"
msgstr ""
#. Here we have to handle any other input file types we need.
-#: readsyms.cc:177
+#: readsyms.cc:230
#, c-format
msgid "%s: not an object or archive"
msgstr ""
@@ -735,53 +843,66 @@ msgstr ""
msgid "reloc section %u size %lu uneven"
msgstr ""
-#: resolve.cc:136
+#: resolve.cc:165
#, c-format
msgid "%s: invalid STB_LOCAL symbol %s in external symbols"
msgstr ""
-#: resolve.cc:142
+#: resolve.cc:171
#, c-format
msgid "%s: unsupported symbol binding %d for symbol %s"
msgstr ""
#. Two definitions of the same symbol.
-#. FIXME: Report locations.
-#: resolve.cc:280
+#. FIXME: Do a better job of reporting locations.
+#: resolve.cc:310
#, c-format
-msgid "multiple definition of %s\n"
+msgid "%s: multiple definition of %s"
msgstr ""
-#: script.cc:1169
+#: resolve.cc:311 resolve.cc:316
+msgid "command line"
+msgstr ""
+
+#: resolve.cc:313
+#, c-format
+msgid "%s: previous definition here"
+msgstr ""
+
+#. There are some options that we could handle here--e.g.,
+#. -lLIBRARY. Should we bother?
+#: script.cc:1326
#, c-format
-msgid "%s: %s\n"
+msgid ""
+"%s: Ignoring command OPTION; OPTION is only valid for scripts specified via -"
+"T"
msgstr ""
-#: symtab.cc:517
+#: symtab.cc:540
#, c-format
msgid "bad global symbol name offset %u at %zu"
msgstr ""
-#: symtab.cc:595
+#: symtab.cc:618
msgid "too few symbol versions"
msgstr ""
-#: symtab.cc:614
+#: symtab.cc:647
#, c-format
msgid "bad symbol name offset %u at %zu"
msgstr ""
-#: symtab.cc:665
+#: symtab.cc:701
#, c-format
msgid "versym for symbol %zu out of range: %u"
msgstr ""
-#: symtab.cc:672
+#: symtab.cc:709
#, c-format
msgid "versym for symbol %zu has no name: %u"
msgstr ""
-#: symtab.cc:1241 symtab.cc:1444
+#: symtab.cc:1427 symtab.cc:1630
#, c-format
msgid "%s: unsupported symbol section 0x%x"
msgstr ""
@@ -791,11 +912,11 @@ msgstr ""
msgid "reloc has bad offset %zu"
msgstr ""
-#: tls.h:58 x86_64.cc:1538
+#: tls.h:58
msgid "TLS relocation out of range"
msgstr ""
-#: tls.h:72 x86_64.cc:1551
+#: tls.h:72
msgid "TLS relocation against invalid instruction"
msgstr ""
@@ -814,17 +935,12 @@ msgid ""
"This program has absolutely no warranty.\n"
msgstr ""
-#. FIXME: This needs to specify the location somehow.
-#: x86_64.cc:154
-msgid "missing expected TLS relocation\n"
-msgstr ""
-
-#: x86_64.cc:1047
+#: x86_64.cc:1137
#, c-format
msgid "%s: unsupported REL reloc section"
msgstr ""
-#: x86_64.cc:1389
+#: x86_64.cc:1535
#, c-format
msgid "unsupported reloc type %u"
msgstr ""