From 9aaae654660bedfb521bfc1c4eec5b953b2a6aca Mon Sep 17 00:00:00 2001 From: "wfh@chromium.org" Date: Wed, 23 Apr 2014 17:27:01 +0000 Subject: 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 --- src/common/windows/pdb_source_line_writer.cc | 64 +++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 11 deletions(-) (limited to 'src/common') diff --git a/src/common/windows/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc index e1307f78..9f4041d5 100644 --- a/src/common/windows/pdb_source_line_writer.cc +++ b/src/common/windows/pdb_source_line_writer.cc @@ -347,7 +347,6 @@ bool PDBSourceLineWriter::PrintFunctions() { ULONG count = 0; DWORD rva = 0; CComPtr global; - std::set rvas; HRESULT hr; if (FAILED(session_->get_globalScope(&global))) { @@ -357,35 +356,42 @@ bool PDBSourceLineWriter::PrintFunctions() { CComPtr symbols = NULL; - // Find all public symbols. - hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols); + // Find all function symbols first. + std::set rvas; + hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols); if (SUCCEEDED(hr)) { CComPtr symbol = NULL; while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) { - if (!PrintCodePublicSymbol(symbol)) + 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 function symbols. - hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols); + // Find all public symbols. Store public symbols that are not also private + // symbols for later. + std::set public_only_rvas; + hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols); if (SUCCEEDED(hr)) { CComPtr 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; + 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::iterator it; + + // For each rva, dump the first symbol DIA knows about at the address. + for (it = rvas.begin(); it != rvas.end(); ++it) { + CComPtr 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, -- cgit v1.2.1