aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux/stabs_reader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/linux/stabs_reader.cc')
-rw-r--r--src/common/linux/stabs_reader.cc19
1 files changed, 18 insertions, 1 deletions
diff --git a/src/common/linux/stabs_reader.cc b/src/common/linux/stabs_reader.cc
index 23b6edbc..67956930 100644
--- a/src/common/linux/stabs_reader.cc
+++ b/src/common/linux/stabs_reader.cc
@@ -43,6 +43,8 @@ StabsReader::StabsReader(const uint8_t *stab, size_t stab_size,
stabstr_(stabstr),
stabstr_size_(stabstr_size),
handler_(handler),
+ string_offset_(0),
+ next_cu_string_offset_(0),
symbol_(NULL),
current_source_file_(NULL) {
symbols_ = reinterpret_cast<const struct nlist *>(stab);
@@ -50,7 +52,7 @@ StabsReader::StabsReader(const uint8_t *stab, size_t stab_size,
}
const char *StabsReader::SymbolString() {
- ptrdiff_t offset = symbol_->n_un.n_strx;
+ ptrdiff_t offset = string_offset_ + symbol_->n_un.n_strx;
if (offset < 0 || (size_t) offset >= stabstr_size_) {
handler_->Warning("symbol %d: name offset outside the string section",
symbol_ - symbols_);
@@ -67,6 +69,21 @@ bool StabsReader::Process() {
if (symbol_->n_type == N_SO) {
if (! ProcessCompilationUnit())
return false;
+ } else if (symbol_->n_type == N_UNDF) {
+ // At the head of each compilation unit's entries there is an
+ // N_UNDF stab giving the number of symbols in the compilation
+ // unit, and the number of bytes that compilation unit's strings
+ // take up in the .stabstr section. Each CU's strings are
+ // separate; the n_strx values are offsets within the current
+ // CU's portion of the .stabstr section.
+ //
+ // As an optimization, the GNU linker combines all the
+ // compilation units into one, with a single N_UNDF at the
+ // beginning. However, other linkers, like Gold, do not perform
+ // this optimization.
+ string_offset_ = next_cu_string_offset_;
+ next_cu_string_offset_ = SymbolValue();
+ symbol_++;
} else
symbol_++;
}