aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/windows/pdb_source_line_writer.cc17
-rw-r--r--src/common/windows/pdb_source_line_writer.h40
2 files changed, 54 insertions, 3 deletions
diff --git a/src/common/windows/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc
index 9525efe2..9cd0d2e3 100644
--- a/src/common/windows/pdb_source_line_writer.cc
+++ b/src/common/windows/pdb_source_line_writer.cc
@@ -118,11 +118,13 @@ bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) {
return false;
}
- DWORD source_id;
- if (FAILED(line->get_sourceFileId(&source_id))) {
+ DWORD dia_source_id;
+ if (FAILED(line->get_sourceFileId(&dia_source_id))) {
fprintf(stderr, "failed to get line source file id\n");
return false;
}
+ // duplicate file names are coalesced to share one ID
+ DWORD source_id = GetRealFileID(dia_source_id);
DWORD line_num;
if (FAILED(line->get_lineNumber(&line_num))) {
@@ -216,7 +218,16 @@ bool PDBSourceLineWriter::PrintSourceFiles() {
return false;
}
- fwprintf(output_, L"FILE %d %s\n", file_id, file_name);
+ wstring file_name_string(file_name);
+ if (!FileIDIsCached(file_name_string)) {
+ // this is a new file name, cache it and output a FILE line.
+ CacheFileID(file_name_string, file_id);
+ fwprintf(output_, L"FILE %d %s\n", file_id, file_name);
+ } else {
+ // this file name has already been seen, just save this
+ // ID for later lookup.
+ StoreDuplicateFileID(file_name_string, file_id);
+ }
file.Release();
}
compiland.Release();
diff --git a/src/common/windows/pdb_source_line_writer.h b/src/common/windows/pdb_source_line_writer.h
index 346d4549..8524d8b0 100644
--- a/src/common/windows/pdb_source_line_writer.h
+++ b/src/common/windows/pdb_source_line_writer.h
@@ -35,6 +35,7 @@
#include <atlcomcli.h>
+#include <hash_map>
#include <string>
struct IDiaEnumLineNumbers;
@@ -44,6 +45,7 @@ struct IDiaSymbol;
namespace google_breakpad {
using std::wstring;
+using stdext::hash_map;
// A structure that carries information that identifies a pdb file.
struct PDBModuleInfo {
@@ -137,6 +139,37 @@ class PDBSourceLineWriter {
// its uuid and age.
bool PrintPDBInfo();
+ // Returns true if this filename has already been seen,
+ // and an ID is stored for it, or false if it has not.
+ bool FileIDIsCached(const wstring &file) {
+ return unique_files_.find(file) != unique_files_.end();
+ };
+
+ // Cache this filename and ID for later reuse.
+ void CacheFileID(const wstring &file, DWORD id) {
+ unique_files_[file] = id;
+ };
+
+ // Store this ID in the cache as a duplicate for this filename.
+ void StoreDuplicateFileID(const wstring &file, DWORD id) {
+ hash_map<wstring, DWORD>::iterator iter = unique_files_.find(file);
+ if (iter != unique_files_.end()) {
+ // map this id to the previously seen one
+ file_ids_[id] = iter->second;
+ }
+ };
+
+ // Given a file's unique ID, return the ID that should be used to
+ // reference it. There may be multiple files with identical filenames
+ // but different unique IDs. The cache attempts to coalesce these into
+ // one ID per unique filename.
+ DWORD GetRealFileID(DWORD id) {
+ hash_map<DWORD, DWORD>::iterator iter = file_ids_.find(id);
+ if (iter == file_ids_.end())
+ return id;
+ return iter->second;
+ };
+
// Returns the function name for a symbol. If possible, the name is
// undecorated. If the symbol's decorated form indicates the size of
// parameters on the stack, this information is returned in stack_param_size.
@@ -156,6 +189,13 @@ class PDBSourceLineWriter {
// The current output file for this WriteMap invocation.
FILE *output_;
+ // There may be many duplicate filenames with different IDs.
+ // This maps from the DIA "unique ID" to a single ID per unique
+ // filename.
+ hash_map<DWORD, DWORD> file_ids_;
+ // This maps unique filenames to file IDs.
+ hash_map<wstring, DWORD> unique_files_;
+
// Disallow copy ctor and operator=
PDBSourceLineWriter(const PDBSourceLineWriter&);
void operator=(const PDBSourceLineWriter&);