aboutsummaryrefslogtreecommitdiff
path: root/src/common/stabs_reader.cc
diff options
context:
space:
mode:
authorjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-05-05 17:34:19 +0000
committerjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-05-05 17:34:19 +0000
commit775c6f7640a02841b667fd6300e877bbed574544 (patch)
tree0d0b83bd37a170951f968aafd1daa6d595f00b8b /src/common/stabs_reader.cc
parentBreakpad STABS parser: Use a test fixture in StabsReader unit tests. (diff)
downloadbreakpad-775c6f7640a02841b667fd6300e877bbed574544.tar.xz
Breakpad Linux dumper: Handle STABS-in-symbol-table, and line number records outside functions.
This patch addresses two differences between Linux and Macintosh OS X STABS data: - StabsReader assumes that the STABS entries follow the conventions for storing STABS data in object file sections (that is, .stabs and .stabstr), rather than in the object files's linker symbol table. On Mac OS X, STABS entries live in the Mach-O file's LC_SYMTAB load command, along with all the other linker symbols; they are not grouped into units by N_UNDF entries. This patch adds a boolean argument to the StabsReader constructor indicating whether the parser should treat N_UNDF entries as unit boundaries; this argument should be true on Linux, and false on Mac. The patch changes src/common/linux/dump_symbols.cc to pass this new argument. - Mac OS X STABS place SLINE (line number) records immediately before the FUN record for the function to which they belong, and the values of such records are absolute, not relative to the function start. This patch extends the parser to queue up such records and report them to the handler when we do see the FUN record. The meaning of StabsHandler::Line remains unchanged; existing handlers do not need to be adjusted. This patch also adds unit tests for the new parser behaviors. a=jimblandy, r=mark git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@587 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common/stabs_reader.cc')
-rw-r--r--src/common/stabs_reader.cc49
1 files changed, 40 insertions, 9 deletions
diff --git a/src/common/stabs_reader.cc b/src/common/stabs_reader.cc
index cdad80e7..1ca97412 100644
--- a/src/common/stabs_reader.cc
+++ b/src/common/stabs_reader.cc
@@ -37,6 +37,8 @@
#include <stab.h>
#include <string.h>
+using std::vector;
+
namespace google_breakpad {
StabsReader::EntryIterator::EntryIterator(const ByteBuffer *buffer,
@@ -61,11 +63,12 @@ void StabsReader::EntryIterator::Fetch() {
StabsReader::StabsReader(const uint8_t *stab, size_t stab_size,
const uint8_t *stabstr, size_t stabstr_size,
- bool big_endian, size_t value_size,
+ bool big_endian, size_t value_size, bool unitized,
StabsHandler *handler)
: entries_(stab, stab_size),
strings_(stabstr, stabstr_size),
iterator_(&entries_, big_endian, value_size),
+ unitized_(unitized),
handler_(handler),
string_offset_(0),
next_cu_string_offset_(0),
@@ -88,13 +91,14 @@ bool StabsReader::Process() {
if (iterator_->type == N_SO) {
if (! ProcessCompilationUnit())
return false;
- } else if (iterator_->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.
+ } else if (iterator_->type == N_UNDF && unitized_) {
+ // In unitized STABS (including Linux STABS, and pretty much anything
+ // else that puts STABS data in sections), 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
@@ -157,9 +161,26 @@ bool StabsReader::ProcessCompilationUnit() {
if (iterator_->type == N_FUN) {
if (! ProcessFunction())
return false;
- } else
+ } else if (iterator_->type == N_SLINE) {
+ // Mac OS X STABS place SLINE records before functions.
+ Line line;
+ // The value of an N_SLINE entry that appears outside a function is
+ // the absolute address of the line.
+ line.address = iterator_->value;
+ line.filename = current_source_file_;
+ // The n_desc of a N_SLINE entry is the line number. It's a
+ // signed 16-bit field; line numbers from 32768 to 65535 are
+ // stored as n-65536.
+ line.number = (uint16_t) iterator_->descriptor;
+ queued_lines_.push_back(line);
+ ++iterator_;
+ } else if (iterator_->type == N_SOL) {
+ current_source_file_ = SymbolString();
+ ++iterator_;
+ } else {
// Ignore anything else.
++iterator_;
+ }
}
// An N_SO with an empty name indicates the end of the compilation
@@ -177,6 +198,8 @@ bool StabsReader::ProcessCompilationUnit() {
if (! handler_->EndCompilationUnit(ending_address))
return false;
+ queued_lines_.clear();
+
return true;
}
@@ -196,6 +219,14 @@ bool StabsReader::ProcessFunction() {
return false;
++iterator_;
+ // If there were any SLINE records given before the function, report them now.
+ for (vector<Line>::const_iterator it = queued_lines_.begin();
+ it != queued_lines_.end(); it++) {
+ if (!handler_->Line(it->address, it->filename, it->number))
+ return false;
+ }
+ queued_lines_.clear();
+
while (!iterator_->at_end) {
if (iterator_->type == N_SO || iterator_->type == N_FUN)
break;