mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-12-23 07:45:36 +00: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;
|
||||
}
|
||||
|
||||
bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function) {
|
||||
bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function,
|
||||
IDiaSymbol *block) {
|
||||
// The function format is:
|
||||
// FUNC <address> <length> <param_stack_size> <function>
|
||||
DWORD rva;
|
||||
if (FAILED(function->get_relativeVirtualAddress(&rva))) {
|
||||
if (FAILED(block->get_relativeVirtualAddress(&rva))) {
|
||||
fprintf(stderr, "couldn't get rva\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ULONGLONG length;
|
||||
if (FAILED(function->get_length(&length))) {
|
||||
if (FAILED(block->get_length(&length))) {
|
||||
fprintf(stderr, "failed to get function length\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -255,7 +256,7 @@ bool PDBSourceLineWriter::PrintFunctions() {
|
|||
// that PDBSourceLineWriter will output either a FUNC or PUBLIC line,
|
||||
// but not both.
|
||||
if (tag == SymTagFunction) {
|
||||
if (!PrintFunction(symbol)) {
|
||||
if (!PrintFunction(symbol, symbol)) {
|
||||
return false;
|
||||
}
|
||||
} else if (tag == SymTagPublicSymbol) {
|
||||
|
@ -266,6 +267,64 @@ bool PDBSourceLineWriter::PrintFunctions() {
|
|||
symbol.Release();
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,8 +111,11 @@ class PDBSourceLineWriter {
|
|||
bool PrintLines(IDiaEnumLineNumbers *lines);
|
||||
|
||||
// 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.
|
||||
bool PrintFunction(IDiaSymbol *function);
|
||||
bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block);
|
||||
|
||||
// Outputs all functions as described above. Returns true on success.
|
||||
bool PrintFunctions();
|
||||
|
|
Loading…
Reference in a new issue