aboutsummaryrefslogtreecommitdiff
path: root/src/common/windows
diff options
context:
space:
mode:
authorwfh@chromium.org <wfh@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2014-04-16 22:50:28 +0000
committerwfh@chromium.org <wfh@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2014-04-16 22:50:28 +0000
commitc83a81450c7d7a2b11a99eb4efff9f90fee8d3b2 (patch)
tree97dbb99d2d8f501038cd62c90e18004731b4bf8a /src/common/windows
parentAllow symupload to upload to multiple URLs on the same command line. (diff)
downloadbreakpad-c83a81450c7d7a2b11a99eb4efff9f90fee8d3b2.tar.xz
Change the way function and public symbols are obtained to use the findChildren DIA function.
This has a substantial performance improvement over using the getSymbolsByAddr iterator, especially on certain 64bit DLLS. e.g. Time to process chrome_child.dll drops from 51 minutes to 21 secs. Note: new test data looks different because the ordering of lines is no longer by memory address. This does not affect processing. The test data has been manually compared to old data and matches (except additional PUBLIC symbols). Also, INFO lines are omitted because the source executable files are not checked in, so they are unavailable. R=ivanpe@chromium.org, mark@chromium.org Review URL: https://breakpad.appspot.com/1574002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1316 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common/windows')
-rw-r--r--src/common/windows/pdb_source_line_writer.cc85
1 files changed, 48 insertions, 37 deletions
diff --git a/src/common/windows/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc
index 516f2f48..e1307f78 100644
--- a/src/common/windows/pdb_source_line_writer.cc
+++ b/src/common/windows/pdb_source_line_writer.cc
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <limits>
+#include <set>
#include "common/windows/dia_util.h"
#include "common/windows/guid_string.h"
@@ -54,9 +55,12 @@
*
*/
typedef unsigned char UBYTE;
+
+#if !defined(_WIN64)
#define UNW_FLAG_EHANDLER 0x01
#define UNW_FLAG_UHANDLER 0x02
#define UNW_FLAG_CHAININFO 0x04
+#endif
union UnwindCode {
struct {
@@ -340,47 +344,59 @@ bool PDBSourceLineWriter::PrintSourceFiles() {
}
bool PDBSourceLineWriter::PrintFunctions() {
- CComPtr<IDiaEnumSymbolsByAddr> symbols;
- if (FAILED(session_->getSymbolsByAddr(&symbols))) {
- fprintf(stderr, "failed to get symbol enumerator\n");
- return false;
- }
+ ULONG count = 0;
+ DWORD rva = 0;
+ CComPtr<IDiaSymbol> global;
+ std::set<DWORD> rvas;
+ HRESULT hr;
- CComPtr<IDiaSymbol> symbol;
- if (FAILED(symbols->symbolByAddr(1, 0, &symbol))) {
- fprintf(stderr, "failed to enumerate symbols\n");
+ if (FAILED(session_->get_globalScope(&global))) {
+ fprintf(stderr, "get_globalScope failed\n");
return false;
}
- DWORD rva_last = 0;
- if (FAILED(symbol->get_relativeVirtualAddress(&rva_last))) {
- fprintf(stderr, "failed to get symbol rva\n");
- return false;
- }
+ CComPtr<IDiaEnumSymbols> symbols = NULL;
- ULONG count;
- do {
- DWORD tag;
- if (FAILED(symbol->get_symTag(&tag))) {
- fprintf(stderr, "failed to get symbol tag\n");
- return false;
- }
+ // Find all public symbols.
+ hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols);
- // For a given function, DIA seems to give either a symbol with
- // SymTagFunction or SymTagPublicSymbol, but not both. This means
- // that PDBSourceLineWriter will output either a FUNC or PUBLIC line,
- // but not both.
- if (tag == SymTagFunction) {
- if (!PrintFunction(symbol, symbol)) {
+ if (SUCCEEDED(hr)) {
+ CComPtr<IDiaSymbol> symbol = NULL;
+
+ while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
+ if (!PrintCodePublicSymbol(symbol))
return false;
- }
- } else if (tag == SymTagPublicSymbol) {
- if (!PrintCodePublicSymbol(symbol)) {
+ symbol.Release();
+ }
+
+ symbols.Release();
+ }
+
+ // Find all function symbols.
+ hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols);
+
+ if (SUCCEEDED(hr)) {
+ CComPtr<IDiaSymbol> symbol = NULL;
+
+ while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
+ if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) {
+ // To maintain existing behavior of one symbol per address, place the
+ // rva onto a set here to uniquify them.
+ if (rvas.count(rva) == 0) {
+ rvas.insert(rva);
+ if (!PrintFunction(symbol, symbol))
+ return false;
+ }
+ } else {
+ fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
return false;
}
+
+ symbol.Release();
}
- symbol.Release();
- } while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1);
+
+ symbols.Release();
+ }
// When building with PGO, the compiler can split functions into
// "hot" and "cold" blocks, and move the "cold" blocks out to separate
@@ -389,12 +405,6 @@ bool PDBSourceLineWriter::PrintFunctions() {
// that are children of them. We can then find the lexical parents
// of those blocks and print out an extra FUNC line for blocks
// that are not contained in their parent functions.
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global))) {
- fprintf(stderr, "get_globalScope failed\n");
- return false;
- }
-
CComPtr<IDiaEnumSymbols> compilands;
if (FAILED(global->findChildren(SymTagCompiland, NULL,
nsNone, &compilands))) {
@@ -440,6 +450,7 @@ bool PDBSourceLineWriter::PrintFunctions() {
compiland.Release();
}
+ global.Release();
return true;
}