diff options
author | nealsid <nealsid@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2009-02-19 21:26:20 +0000 |
---|---|---|
committer | nealsid <nealsid@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2009-02-19 21:26:20 +0000 |
commit | 0fd2f1ae2152782f2127c56fb5302002c95502d3 (patch) | |
tree | 021783dc670766ed1781eb79fde45c30fb55a964 /src/processor/basic_source_line_resolver.cc | |
parent | Issue 275: patch to include list of loaded modules in crash_report output (diff) | |
download | breakpad-0fd2f1ae2152782f2127c56fb5302002c95502d3.tar.xz |
Modify symbol supplier interface to support an overload that takes a symbol data buffer, to get around an extraneous read/write of symbol data
R=doshimun
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@311 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/processor/basic_source_line_resolver.cc')
-rw-r--r-- | src/processor/basic_source_line_resolver.cc | 148 |
1 files changed, 124 insertions, 24 deletions
diff --git a/src/processor/basic_source_line_resolver.cc b/src/processor/basic_source_line_resolver.cc index 6baa1a8b..bba86599 100644 --- a/src/processor/basic_source_line_resolver.cc +++ b/src/processor/basic_source_line_resolver.cc @@ -29,6 +29,9 @@ #include <stdio.h> #include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include <map> #include <utility> @@ -106,9 +109,13 @@ class BasicSourceLineResolver::Module { public: Module(const string &name) : name_(name) { } - // Loads the given map file, returning true on success. + // Loads the given map file, returning true on success. Reads the + // map file into memory and calls LoadMapFromBuffer bool LoadMap(const string &map_file); + // Loads a map from the given buffer, returning true on success + bool LoadMapFromBuffer(const string &map_buffer); + // Looks up the given relative address, and fills the StackFrame struct // with the result. Additional debugging information, if available, is // returned. If no additional information is available, returns NULL. @@ -211,6 +218,27 @@ bool BasicSourceLineResolver::LoadModule(const string &module_name, return true; } +bool BasicSourceLineResolver::LoadModuleUsingMapBuffer( + const string &module_name, + const string &map_buffer) { + // Make sure we don't already have a module with the given name. + if (modules_->find(module_name) != modules_->end()) { + BPLOG(INFO) << "Symbols for module " << module_name << " already loaded"; + return false; + } + + BPLOG(INFO) << "Loading symbols for module " << module_name << " from buffer"; + + Module *module = new Module(module_name); + if (!module->LoadMapFromBuffer(map_buffer)) { + delete module; + return false; + } + + modules_->insert(make_pair(module_name, module)); + return true; +} + bool BasicSourceLineResolver::HasModule(const string &module_name) const { return modules_->find(module_name) != modules_->end(); } @@ -238,44 +266,56 @@ class AutoFileCloser { FILE *file_; }; -bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) { - FILE *f = fopen(map_file.c_str(), "r"); - if (!f) { - string error_string; - int error_code = ErrnoString(&error_string); - BPLOG(ERROR) << "Could not open " << map_file << - ", error " << error_code << ": " << error_string; +bool BasicSourceLineResolver::Module::LoadMapFromBuffer( + const string &map_buffer) { + linked_ptr<Function> cur_func; + int line_number = 0; + const char *map_buffer_c_str = map_buffer.c_str(); + char *save_ptr; + + // set up our input buffer as a c-style string so we + // can we use strtok() + // have to copy because modifying the result of string::c_str is not + // permitted + size_t map_buffer_length = strlen(map_buffer_c_str); + char *map_buffer_chars = new char[map_buffer_length]; + if (map_buffer_chars == NULL) { + BPLOG(ERROR) << "Memory allocation of " << map_buffer_length << + " bytes failed"; return false; } - AutoFileCloser closer(f); + strncpy(map_buffer_chars, map_buffer_c_str, map_buffer_length); - // TODO(mmentovai): this might not be large enough to handle really long - // lines, which might be present for FUNC lines of highly-templatized - // code. - char buffer[8192]; - linked_ptr<Function> cur_func; + if (map_buffer_chars[map_buffer_length - 1] == '\n') { + map_buffer_chars[map_buffer_length - 1] = '\0'; + } + char *buffer; + buffer = strtok_r(map_buffer_chars, "\r\n", &save_ptr); - int line_number = 0; - while (fgets(buffer, sizeof(buffer), f)) { + while (buffer != NULL) { ++line_number; + if (strncmp(buffer, "FILE ", 5) == 0) { if (!ParseFile(buffer)) { - BPLOG(ERROR) << "ParseFile failed at " << - map_file << ":" << line_number; + BPLOG(ERROR) << "ParseFile on buffer failed at " << + ":" << line_number; + delete [] map_buffer_chars; return false; } } else if (strncmp(buffer, "STACK ", 6) == 0) { if (!ParseStackInfo(buffer)) { BPLOG(ERROR) << "ParseStackInfo failed at " << - map_file << ":" << line_number; + ":" << line_number; + delete [] map_buffer_chars; return false; } } else if (strncmp(buffer, "FUNC ", 5) == 0) { cur_func.reset(ParseFunction(buffer)); if (!cur_func.get()) { BPLOG(ERROR) << "ParseFunction failed at " << - map_file << ":" << line_number; + ":" << line_number; + delete [] map_buffer_chars; return false; } // StoreRange will fail if the function has an invalid address or size. @@ -288,7 +328,8 @@ bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) { if (!ParsePublicSymbol(buffer)) { BPLOG(ERROR) << "ParsePublicSymbol failed at " << - map_file << ":" << line_number; + ":" << line_number; + delete [] map_buffer_chars; return false; } } else if (strncmp(buffer, "MODULE ", 7) == 0) { @@ -301,23 +342,82 @@ bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) { } else { if (!cur_func.get()) { BPLOG(ERROR) << "Found source line data without a function at " << - map_file << ":" << line_number; + ":" << line_number; + delete [] map_buffer_chars; return false; } Line *line = ParseLine(buffer); if (!line) { - BPLOG(ERROR) << "ParseLine failed at " << - map_file << ":" << line_number; + BPLOG(ERROR) << "ParseLine failed at " << line_number << " for " << + buffer; + delete [] map_buffer_chars; return false; } cur_func->lines.StoreRange(line->address, line->size, linked_ptr<Line>(line)); } + + buffer = strtok_r(NULL, "\r\n", &save_ptr); } return true; } +bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) { + struct stat buf; + int error_code = stat(map_file.c_str(), &buf); + if (error_code == -1) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Could not open " << map_file << + ", error " << error_code << ": " << error_string; + return false; + } + + off_t file_size = buf.st_size; + + // Allocate memory for file contents, plus a null terminator + // since we'll use strtok() on the contents. + char *file_buffer = new char[sizeof(char)*file_size + 1]; + + if (file_buffer == NULL) { + BPLOG(ERROR) << "Could not allocate memory for " << map_file; + return false; + } + + BPLOG(ERROR) << "Opening " << map_file; + + FILE *f = fopen(map_file.c_str(), "rt"); + if (!f) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Could not open " << map_file << + ", error " << error_code << ": " << error_string; + delete [] file_buffer; + return false; + } + + AutoFileCloser closer(f); + + int items_read = 0; + + items_read = fread(file_buffer, 1, file_size, f); + + if (items_read != file_size) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Could not slurp " << map_file << + ", error " << error_code << ": " << error_string; + delete [] file_buffer; + return false; + } + file_buffer[file_size] = '\0'; + string map_buffer(file_buffer); + delete [] file_buffer; + + return LoadMapFromBuffer(map_buffer); +} + StackFrameInfo* BasicSourceLineResolver::Module::LookupAddress( StackFrame *frame) const { MemAddr address = frame->instruction - frame->module->base_address(); |