mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-28 12:04:18 +01:00
output function names for PGO-optimized cold function blocks. r=mark at http://breakpad.appspot.com/40007
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@430 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
2712a8c712
commit
927cc8fa2a
@ -136,17 +136,18 @@ bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function) {
|
bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function,
|
||||||
|
IDiaSymbol *block) {
|
||||||
// The function format is:
|
// The function format is:
|
||||||
// FUNC <address> <length> <param_stack_size> <function>
|
// FUNC <address> <length> <param_stack_size> <function>
|
||||||
DWORD rva;
|
DWORD rva;
|
||||||
if (FAILED(function->get_relativeVirtualAddress(&rva))) {
|
if (FAILED(block->get_relativeVirtualAddress(&rva))) {
|
||||||
fprintf(stderr, "couldn't get rva\n");
|
fprintf(stderr, "couldn't get rva\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONGLONG length;
|
ULONGLONG length;
|
||||||
if (FAILED(function->get_length(&length))) {
|
if (FAILED(block->get_length(&length))) {
|
||||||
fprintf(stderr, "failed to get function length\n");
|
fprintf(stderr, "failed to get function length\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -255,7 +256,7 @@ bool PDBSourceLineWriter::PrintFunctions() {
|
|||||||
// that PDBSourceLineWriter will output either a FUNC or PUBLIC line,
|
// that PDBSourceLineWriter will output either a FUNC or PUBLIC line,
|
||||||
// but not both.
|
// but not both.
|
||||||
if (tag == SymTagFunction) {
|
if (tag == SymTagFunction) {
|
||||||
if (!PrintFunction(symbol)) {
|
if (!PrintFunction(symbol, symbol)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (tag == SymTagPublicSymbol) {
|
} else if (tag == SymTagPublicSymbol) {
|
||||||
@ -266,6 +267,64 @@ bool PDBSourceLineWriter::PrintFunctions() {
|
|||||||
symbol.Release();
|
symbol.Release();
|
||||||
} while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1);
|
} while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1);
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
// we have to iterate over all the compilands, and then find blocks
|
||||||
|
// 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))) {
|
||||||
|
fprintf(stderr, "findChildren failed on the global\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CComPtr<IDiaSymbol> compiland;
|
||||||
|
while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) {
|
||||||
|
CComPtr<IDiaEnumSymbols> blocks;
|
||||||
|
if (FAILED(compiland->findChildren(SymTagBlock, NULL,
|
||||||
|
nsNone, &blocks))) {
|
||||||
|
fprintf(stderr, "findChildren failed on a compiland\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CComPtr<IDiaSymbol> block;
|
||||||
|
while (SUCCEEDED(blocks->Next(1, &block, &count)) && count == 1) {
|
||||||
|
// find this block's lexical parent function
|
||||||
|
CComPtr<IDiaSymbol> parent;
|
||||||
|
DWORD tag;
|
||||||
|
if (SUCCEEDED(block->get_lexicalParent(&parent)) &&
|
||||||
|
SUCCEEDED(parent->get_symTag(&tag)) &&
|
||||||
|
tag == SymTagFunction) {
|
||||||
|
// now get the block's offset and the function's offset and size,
|
||||||
|
// and determine if the block is outside of the function
|
||||||
|
DWORD func_rva, block_rva;
|
||||||
|
ULONGLONG func_length;
|
||||||
|
if (SUCCEEDED(block->get_relativeVirtualAddress(&block_rva)) &&
|
||||||
|
SUCCEEDED(parent->get_relativeVirtualAddress(&func_rva)) &&
|
||||||
|
SUCCEEDED(parent->get_length(&func_length))) {
|
||||||
|
if (block_rva < func_rva || block_rva > (func_rva + func_length)) {
|
||||||
|
if (!PrintFunction(parent, block)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent.Release();
|
||||||
|
block.Release();
|
||||||
|
}
|
||||||
|
blocks.Release();
|
||||||
|
compiland.Release();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,8 +111,11 @@ class PDBSourceLineWriter {
|
|||||||
bool PrintLines(IDiaEnumLineNumbers *lines);
|
bool PrintLines(IDiaEnumLineNumbers *lines);
|
||||||
|
|
||||||
// Outputs a function address and name, followed by its source line list.
|
// Outputs a function address and name, followed by its source line list.
|
||||||
|
// block can be the same object as function, or it can be a reference
|
||||||
|
// to a code block that is lexically part of this function, but
|
||||||
|
// resides at a separate address.
|
||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
bool PrintFunction(IDiaSymbol *function);
|
bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block);
|
||||||
|
|
||||||
// Outputs all functions as described above. Returns true on success.
|
// Outputs all functions as described above. Returns true on success.
|
||||||
bool PrintFunctions();
|
bool PrintFunctions();
|
||||||
|
Loading…
Reference in New Issue
Block a user