diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/windows/pdb_source_line_writer.cc | 64 |
1 files changed, 53 insertions, 11 deletions
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<IDiaSymbol> global; - std::set<DWORD> rvas; HRESULT hr; if (FAILED(session_->get_globalScope(&global))) { @@ -357,35 +356,42 @@ bool PDBSourceLineWriter::PrintFunctions() { CComPtr<IDiaEnumSymbols> symbols = NULL; - // Find all public symbols. - hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols); + // Find all function symbols first. + std::set<DWORD> rvas; + hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols); if (SUCCEEDED(hr)) { CComPtr<IDiaSymbol> 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<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))) { - // 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<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, |