Change PrintFunctions to print functions in address order and not print duplicate public functions.

BUG=427
R=mark@chromium.org

Review URL: https://breakpad.appspot.com/1634002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1319 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
wfh@chromium.org 2014-04-23 17:27:01 +00:00
parent 1c8e155b3a
commit 9aaae65466
7 changed files with 13891 additions and 14789 deletions

View file

@ -347,7 +347,6 @@ bool PDBSourceLineWriter::PrintFunctions() {
ULONG count = 0;
DWORD rva = 0;
CComPtr<IDiaSymbol> global;
std::set<DWORD> rvas;
HRESULT hr;
if (FAILED(session_->get_globalScope(&global))) {
@ -357,22 +356,8 @@ bool PDBSourceLineWriter::PrintFunctions() {
CComPtr<IDiaEnumSymbols> symbols = NULL;
// Find all public symbols.
hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols);
if (SUCCEEDED(hr)) {
CComPtr<IDiaSymbol> symbol = NULL;
while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
if (!PrintCodePublicSymbol(symbol))
return false;
symbol.Release();
}
symbols.Release();
}
// Find all function symbols.
// Find all function symbols first.
std::set<DWORD> rvas;
hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols);
if (SUCCEEDED(hr)) {
@ -382,10 +367,31 @@ bool PDBSourceLineWriter::PrintFunctions() {
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.
rvas.insert(rva);
} else {
fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
return false;
}
symbol.Release();
}
symbols.Release();
}
// Find all public symbols. Store public symbols that are not also private
// symbols for later.
std::set<DWORD> public_only_rvas;
hr = global->findChildren(SymTagPublicSymbol, 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))) {
if (rvas.count(rva) == 0) {
rvas.insert(rva);
if (!PrintFunction(symbol, symbol))
return false;
rvas.insert(rva); // Keep symbols in rva order.
public_only_rvas.insert(rva);
}
} else {
fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
@ -398,6 +404,42 @@ bool PDBSourceLineWriter::PrintFunctions() {
symbols.Release();
}
std::set<DWORD>::iterator it;
// For each rva, dump the first symbol DIA knows about at the address.
for (it = rvas.begin(); it != rvas.end(); ++it) {
CComPtr<IDiaSymbol> symbol = NULL;
// If the symbol is not in the public list, look for SymTagFunction. This is
// a workaround to a bug where DIA will hang if searching for a private
// symbol at an address where only a public symbol exists.
// See http://connect.microsoft.com/VisualStudio/feedback/details/722366
if (public_only_rvas.count(*it) == 0) {
if (SUCCEEDED(session_->findSymbolByRVA(*it, SymTagFunction, &symbol))) {
// Sometimes findSymbolByRVA returns S_OK, but NULL.
if (symbol) {
if (!PrintFunction(symbol, symbol))
return false;
symbol.Release();
}
} else {
fprintf(stderr, "findSymbolByRVA SymTagFunction failed\n");
return false;
}
} else if (SUCCEEDED(session_->findSymbolByRVA(*it,
SymTagPublicSymbol,
&symbol))) {
// Sometimes findSymbolByRVA returns S_OK, but NULL.
if (symbol) {
if (!PrintCodePublicSymbol(symbol))
return false;
symbol.Release();
}
} else {
fprintf(stderr, "findSymbolByRVA SymTagPublicSymbol failed\n");
return false;
}
}
// When building with PGO, the compiler can split functions into
// "hot" and "cold" blocks, and move the "cold" blocks out to separate
// pages, so the function can be noncontiguous. To find these blocks,