aboutsummaryrefslogtreecommitdiff
path: root/src/common/windows
diff options
context:
space:
mode:
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;
}