aboutsummaryrefslogtreecommitdiff
path: root/src/processor/basic_source_line_resolver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor/basic_source_line_resolver.cc')
-rw-r--r--src/processor/basic_source_line_resolver.cc100
1 files changed, 68 insertions, 32 deletions
diff --git a/src/processor/basic_source_line_resolver.cc b/src/processor/basic_source_line_resolver.cc
index 55f8f9a1..6fb47b3b 100644
--- a/src/processor/basic_source_line_resolver.cc
+++ b/src/processor/basic_source_line_resolver.cc
@@ -60,25 +60,65 @@ namespace google_breakpad {
#endif
static const char *kWhitespace = " \r\n";
+static const int kMaxErrorsPrinted = 5;
+static const int kMaxErrorsBeforeBailing = 100;
BasicSourceLineResolver::BasicSourceLineResolver() :
SourceLineResolverBase(new BasicModuleFactory) { }
-bool BasicSourceLineResolver::Module::LoadMapFromMemory(char *memory_buffer) {
+// static
+void BasicSourceLineResolver::Module::LogParseError(
+ const string &message,
+ int line_number,
+ int *num_errors) {
+ if (++(*num_errors) <= kMaxErrorsPrinted) {
+ if (line_number > 0) {
+ BPLOG(ERROR) << "Line " << line_number << ": " << message;
+ } else {
+ BPLOG(ERROR) << message;
+ }
+ }
+}
+
+bool BasicSourceLineResolver::Module::LoadMapFromMemory(
+ char *memory_buffer,
+ size_t memory_buffer_size) {
linked_ptr<Function> cur_func;
int line_number = 0;
+ int num_errors = 0;
char *save_ptr;
- size_t map_buffer_length = strlen(memory_buffer);
// If the length is 0, we can still pretend we have a symbol file. This is
// for scenarios that want to test symbol lookup, but don't necessarily care
// if certain modules do not have any information, like system libraries.
- if (map_buffer_length == 0) {
+ if (memory_buffer_size == 0) {
return true;
}
- if (memory_buffer[map_buffer_length - 1] == '\n') {
- memory_buffer[map_buffer_length - 1] = '\0';
+ // Make sure the last character is null terminator.
+ size_t last_null_terminator = memory_buffer_size - 1;
+ if (memory_buffer[last_null_terminator] != '\0') {
+ memory_buffer[last_null_terminator] = '\0';
+ }
+
+ // Skip any null terminators at the end of the memory buffer, and make sure
+ // there are no other null terminators in the middle of the memory buffer.
+ bool has_null_terminator_in_the_middle = false;
+ while (last_null_terminator > 0 &&
+ memory_buffer[last_null_terminator - 1] == '\0') {
+ last_null_terminator--;
+ }
+ for (size_t i = 0; i < last_null_terminator; i++) {
+ if (memory_buffer[i] == '\0') {
+ memory_buffer[i] = '_';
+ has_null_terminator_in_the_middle = true;
+ }
+ }
+ if (has_null_terminator_in_the_middle) {
+ LogParseError(
+ "Null terminator is not expected in the middle of the symbol data",
+ line_number,
+ &num_errors);
}
char *buffer;
@@ -89,35 +129,28 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory(char *memory_buffer) {
if (strncmp(buffer, "FILE ", 5) == 0) {
if (!ParseFile(buffer)) {
- BPLOG(ERROR) << "ParseFile on buffer failed at " <<
- ":" << line_number;
- return false;
+ LogParseError("ParseFile on buffer failed", line_number, &num_errors);
}
} else if (strncmp(buffer, "STACK ", 6) == 0) {
if (!ParseStackInfo(buffer)) {
- BPLOG(ERROR) << "ParseStackInfo failed at " <<
- ":" << line_number;
- return false;
+ LogParseError("ParseStackInfo failed", line_number, &num_errors);
}
} else if (strncmp(buffer, "FUNC ", 5) == 0) {
cur_func.reset(ParseFunction(buffer));
if (!cur_func.get()) {
- BPLOG(ERROR) << "ParseFunction failed at " <<
- ":" << line_number;
- return false;
+ LogParseError("ParseFunction failed", line_number, &num_errors);
+ } else {
+ // StoreRange will fail if the function has an invalid address or size.
+ // We'll silently ignore this, the function and any corresponding lines
+ // will be destroyed when cur_func is released.
+ functions_.StoreRange(cur_func->address, cur_func->size, cur_func);
}
- // StoreRange will fail if the function has an invalid address or size.
- // We'll silently ignore this, the function and any corresponding lines
- // will be destroyed when cur_func is released.
- functions_.StoreRange(cur_func->address, cur_func->size, cur_func);
} else if (strncmp(buffer, "PUBLIC ", 7) == 0) {
// Clear cur_func: public symbols don't contain line number information.
cur_func.reset();
if (!ParsePublicSymbol(buffer)) {
- BPLOG(ERROR) << "ParsePublicSymbol failed at " <<
- ":" << line_number;
- return false;
+ LogParseError("ParsePublicSymbol failed", line_number, &num_errors);
}
} else if (strncmp(buffer, "MODULE ", 7) == 0) {
// Ignore these. They're not of any use to BasicSourceLineResolver,
@@ -132,21 +165,24 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory(char *memory_buffer) {
// INFO CODE_ID <code id> <filename>
} else {
if (!cur_func.get()) {
- BPLOG(ERROR) << "Found source line data without a function at " <<
- ":" << line_number;
- return false;
- }
- Line *line = ParseLine(buffer);
- if (!line) {
- BPLOG(ERROR) << "ParseLine failed at " << line_number << " for " <<
- buffer;
- return false;
+ LogParseError("Found source line data without a function",
+ line_number, &num_errors);
+ } else {
+ Line *line = ParseLine(buffer);
+ if (!line) {
+ LogParseError("ParseLine failed", line_number, &num_errors);
+ } else {
+ cur_func->lines.StoreRange(line->address, line->size,
+ linked_ptr<Line>(line));
+ }
}
- cur_func->lines.StoreRange(line->address, line->size,
- linked_ptr<Line>(line));
+ }
+ if (num_errors > kMaxErrorsBeforeBailing) {
+ break;
}
buffer = strtok_r(NULL, "\r\n", &save_ptr);
}
+ is_corrupt_ = num_errors > 0;
return true;
}