bug 848880 - Update to Breakpad SVN r1128. r=upstream

This commit is contained in:
Ted Mielczarek 2013-03-07 13:50:42 -05:00
Родитель 75c8a44a47
Коммит a30e14f4ea
40 изменённых файлов: 3615 добавлений и 16614 удалений

Просмотреть файл

@ -1,15 +1,20 @@
# HG changeset patch
# User Ted Mielczarek <ted@mielczarek.org>
# Date 1352220493 18000
# Node ID a38d670da97e338234375756313b2f47650e01fb
# Parent 201b7c6793586b6b7cfcaa02f4e29700c4c12ef1
# Node ID c3b1109dd392c16a9fe4e85da693010966dbbf0b
# Parent 03db269a2868503cca9e80f62ce676aabbf967fd
Add APIs for querying Module data
R=glandium at https://breakpad.appspot.com/511003/
diff --git a/src/common/module.cc b/src/common/module.cc
--- a/src/common/module.cc
+++ b/src/common/module.cc
@@ -63,7 +63,7 @@
@@ -58,17 +58,17 @@
Module::~Module() {
for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
delete it->second;
for (FunctionSet::iterator it = functions_.begin();
it != functions_.end(); ++it) {
delete *it;
}
@ -18,7 +23,17 @@ diff --git a/src/common/module.cc b/src/common/module.cc
it != stack_frame_entries_.end(); ++it) {
delete *it;
}
@@ -93,8 +93,14 @@
for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it)
delete *it;
}
void Module::SetLoadAddress(Address address) {
@@ -88,39 +88,84 @@
}
void Module::AddFunctions(vector<Function *>::iterator begin,
vector<Function *>::iterator end) {
for (vector<Function *>::iterator it = begin; it != end; ++it)
AddFunction(*it);
}
@ -35,7 +50,16 @@ diff --git a/src/common/module.cc b/src/common/module.cc
}
void Module::AddExtern(Extern *ext) {
@@ -111,11 +117,50 @@
std::pair<ExternSet::iterator,bool> ret = externs_.insert(ext);
if (!ret.second) {
// Free the duplicate that was not inserted because this Module
// now owns it.
delete ext;
}
}
void Module::GetFunctions(vector<Function *> *vec,
vector<Function *>::iterator i) {
vec->insert(i, functions_.begin(), functions_.end());
}
@ -86,7 +110,17 @@ diff --git a/src/common/module.cc b/src/common/module.cc
Module::File *Module::FindFile(const string &name) {
// A tricky bit here. The key of each map entry needs to be a
// pointer to the entry's File's name string. This means that we
@@ -155,8 +200,25 @@
// can't do the initial lookup with any operation that would create
// an empty entry for us if the name isn't found (like, say,
// operator[] or insert do), because such a created entry's key will
// be a pointer the string passed as our argument. Since the key of
// a map's value type is const, we can't fix it up once we've
@@ -150,18 +195,35 @@
}
void Module::GetFiles(vector<File *> *vec) {
vec->clear();
for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
vec->push_back(it->second);
}
@ -114,19 +148,39 @@ diff --git a/src/common/module.cc b/src/common/module.cc
}
void Module::AssignSourceIds() {
@@ -261,7 +323,7 @@
// First, give every source file an id of -1.
for (FileByNameMap::iterator file_it = files_.begin();
file_it != files_.end(); ++file_it) {
file_it->second->source_id = -1;
}
@@ -256,17 +318,17 @@
stream << "PUBLIC " << hex
<< (ext->address - load_address_) << " 0 "
<< ext->name << dec << endl;
}
}
if (cfi) {
if (symbol_data != NO_CFI) {
// Write out 'STACK CFI INIT' and 'STACK CFI' records.
- vector<StackFrameEntry *>::const_iterator frame_it;
+ StackFrameEntrySet::const_iterator frame_it;
for (frame_it = stack_frame_entries_.begin();
frame_it != stack_frame_entries_.end(); ++frame_it) {
StackFrameEntry *entry = *frame_it;
stream << "STACK CFI INIT " << hex
<< (entry->address - load_address_) << " "
<< entry->size << " " << dec;
if (!stream.good()
|| !WriteRuleMap(entry->initial_rules, stream))
diff --git a/src/common/module.h b/src/common/module.h
--- a/src/common/module.h
+++ b/src/common/module.h
@@ -168,6 +168,13 @@
@@ -164,16 +164,23 @@
struct ExternCompare {
bool operator() (const Extern *lhs,
const Extern *rhs) const {
return lhs->address < rhs->address;
}
};
@ -140,7 +194,17 @@ diff --git a/src/common/module.h b/src/common/module.h
// Create a new module with the given name, operating system,
// architecture, and ID string.
Module(const string &name, const string &os, const string &architecture,
@@ -227,6 +234,10 @@
const string &id);
~Module();
// Set the module's load address to LOAD_ADDRESS; addresses given
// for functions and lines will be written to the Breakpad symbol
@@ -223,37 +230,49 @@
// Insert pointers to the functions added to this module at I in
// VEC. The pointed-to Functions are still owned by this module.
// (Since this is effectively a copy of the function list, this is
// mostly useful for testing; other uses should probably get a more
// appropriate interface.)
void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i);
@ -151,7 +215,7 @@ diff --git a/src/common/module.h b/src/common/module.h
// Insert pointers to the externs added to this module at I in
// VEC. The pointed-to Externs are still owned by this module.
// (Since this is effectively a copy of the extern list, this is
@@ -234,6 +245,10 @@
// mostly useful for testing; other uses should probably get a more
// appropriate interface.)
void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i);
@ -162,7 +226,14 @@ diff --git a/src/common/module.h b/src/common/module.h
// Clear VEC and fill it with pointers to the Files added to this
// module, sorted by name. The pointed-to Files are still owned by
// this module. (Since this is effectively a copy of the file list,
@@ -248,6 +263,10 @@
// this is mostly useful for testing; other uses should probably get
// a more appropriate interface.)
void GetFiles(vector<File *> *vec);
// Clear VEC and fill it with pointers to the StackFrameEntry
// objects that have been added to this module. (Since this is
// effectively a copy of the stack frame entry list, this is mostly
// useful for testing; other uses should probably get
// a more appropriate interface.)
void GetStackFrameEntries(vector<StackFrameEntry *> *vec);
@ -173,7 +244,17 @@ diff --git a/src/common/module.h b/src/common/module.h
// Find those files in this module that are actually referred to by
// functions' line number data, and assign them source id numbers.
// Set the source id numbers for all other files --- unused by the
@@ -301,6 +320,9 @@
// source line data --- to -1. We do this before writing out the
// symbol file, at which point we omit any unused files.
void AssignSourceIds();
// Call AssignSourceIds, and write this module to STREAM in the
@@ -299,25 +318,28 @@
typedef map<const string *, File *, CompareStringPtrs> FileByNameMap;
// A set containing Function structures, sorted by address.
typedef set<Function *, FunctionCompare> FunctionSet;
// A set containing Extern structures, sorted by address.
typedef set<Extern *, ExternCompare> ExternSet;
@ -183,7 +264,8 @@ diff --git a/src/common/module.h b/src/common/module.h
// The module owns all the files and functions that have been added
// to it; destroying the module frees the Files and Functions these
// point to.
@@ -309,7 +331,7 @@
FileByNameMap files_; // This module's source files.
FunctionSet functions_; // This module's functions.
// The module owns all the call frame info entries that have been
// added to it.
@ -192,11 +274,21 @@ diff --git a/src/common/module.h b/src/common/module.h
// The module owns all the externs that have been added to it;
// destroying the module frees the Externs these point to.
ExternSet externs_;
};
} // namespace google_breakpad
diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
--- a/src/common/module_unittest.cc
+++ b/src/common/module_unittest.cc
@@ -334,11 +334,6 @@
m.Write(s, true);
@@ -329,63 +329,63 @@
entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
"I think I know";
m.AddStackFrameEntry(entry3);
// Check that Write writes STACK CFI records properly.
m.Write(s, ALL_SYMBOL_DATA);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n"
@ -207,7 +299,7 @@ diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
"STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
" .cfa: Whose woods are these\n"
"STACK CFI 36682fad3763ffff"
@@ -346,7 +341,12 @@
" .cfa: I think I know"
" stromboli: his house is in\n"
"STACK CFI 47ceb0f63c269d7f"
" calzone: the village though"
@ -221,7 +313,7 @@ diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
contents.c_str());
// Check that GetStackFrameEntries works.
@@ -354,10 +354,18 @@
vector<Module::StackFrameEntry *> entries;
m.GetStackFrameEntries(&entries);
ASSERT_EQ(3U, entries.size());
// Check first entry.
@ -244,7 +336,11 @@ diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
// Check second entry.
EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
@@ -369,18 +377,10 @@
ASSERT_EQ(3U, entries[1]->initial_rules.size());
Module::RuleMap entry2_initial;
entry2_initial[".cfa"] = "I think that I shall never see";
entry2_initial["stromboli"] = "a poem lovely as a tree";
entry2_initial["cannoli"] = "a tree whose hungry mouth is prest";
EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
ASSERT_EQ(0U, entries[1]->rule_changes.size());
// Check third entry.
@ -267,7 +363,17 @@ diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
}
TEST(Construct, UniqueFiles) {
@@ -488,3 +488,150 @@
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
Module::File *file1 = m.FindFile("foo");
Module::File *file2 = m.FindFile(string("bar"));
Module::File *file3 = m.FindFile(string("foo"));
Module::File *file4 = m.FindFile("bar");
@@ -483,8 +483,155 @@
m.Write(s, ALL_SYMBOL_DATA);
string contents = s.str();
EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
MODULE_ID " " MODULE_NAME "\n"
"PUBLIC ffff 0 _xyz\n",
contents.c_str());
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,10 +1,10 @@
# HG changeset patch
# User Ted Mielczarek <ted.mielczarek@gmail.com>
# Date 1360255134 18000
# Node ID 229852c0b835929a56f207996034cf072307b343
# Parent c53ab35ef4dce39824c2d8103f75faccb4c380e9
# Node ID d7bfb673574a3afe8b4f76f42fb52e2545770dad
# Parent d23a69a6c34a1f1c21e241f37b388c8689f2386b
Rework PostfixEvaluator to use a UniqueString type
R=ted
Patch by Julian Seward <jseward@acm.org>, R=ted
diff --git a/Makefile.am b/Makefile.am
--- a/Makefile.am
@ -1353,15 +1353,15 @@ diff --git a/src/common/dwarf_cfi_to_module_unittest.cc b/src/common/dwarf_cfi_t
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -76,16 +76,17 @@
using google_breakpad::ElfClass;
using google_breakpad::ElfClass32;
@@ -80,16 +80,17 @@
using google_breakpad::ElfClass64;
using google_breakpad::FindElfSectionByName;
using google_breakpad::GetOffset;
using google_breakpad::IsValidElf;
using google_breakpad::Module;
#ifndef NO_STABS_SUPPORT
using google_breakpad::StabsToModule;
#endif
+using google_breakpad::UniqueString;
using google_breakpad::scoped_ptr;
@ -1371,7 +1371,7 @@ diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
// Wrapper class to make sure opened file is closed.
//
class FDWrapper {
@@ -264,17 +265,17 @@
@@ -270,17 +271,17 @@
// Fill REGISTER_NAMES with the register names appropriate to the
// machine architecture given in HEADER, indexed by the register
@ -1390,7 +1390,7 @@ diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
*register_names = DwarfCFIToModule::RegisterNames::ARM();
return true;
case EM_X86_64:
@@ -292,17 +293,17 @@
@@ -298,17 +299,17 @@
const typename ElfClass::Shdr* section,
const bool eh_frame,
const typename ElfClass::Shdr* got_section,
@ -2357,8 +2357,8 @@ diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
namespace google_breakpad {
template<typename V>
@@ -61,33 +62,33 @@
#ifdef _WIN32
@@ -65,33 +66,33 @@
V cfa;
working = registers;
if (!evaluator.EvaluateForValue(cfa_rule_, &cfa))
@ -2396,7 +2396,7 @@ diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
template bool CFIFrameInfo::FindCallerRegs<uint32_t>(
const RegisterValueMap<uint32_t> &registers,
const MemoryRegion &memory,
@@ -103,81 +104,98 @@
@@ -107,81 +108,98 @@
if (!cfa_rule_.invalid()) {
stream << ".cfa: " << cfa_rule_;
}
@ -4397,7 +4397,7 @@ diff --git a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/src/t
B88FB0D7116CEC0600407530 /* dwarf_line_to_module_unittest.cc */,
B88FAE221166603300407530 /* language.cc */,
B88FAE231166603300407530 /* language.h */,
@@ -937,16 +947,17 @@
@@ -940,16 +950,17 @@
};
/* End PBXShellScriptBuildPhase section */
@ -4415,7 +4415,7 @@ diff --git a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/src/t
};
B88FAF2C116A591D00407530 /* Sources */ = {
isa = PBXSourcesBuildPhase;
@@ -980,56 +991,60 @@
@@ -983,56 +994,60 @@
runOnlyForDeploymentPostprocessing = 0;
};
B88FB0B6116CEABF00407530 /* Sources */ = {
@ -4476,7 +4476,7 @@ diff --git a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/src/t
buildActionMask = 2147483647;
files = (
B88FB13D116CF38300407530 /* cfi_assembler.cc in Sources */,
@@ -1083,16 +1098,17 @@
@@ -1086,16 +1101,17 @@
B88FAE261166603300407530 /* dwarf_cu_to_module.cc in Sources */,
B88FAE271166603300407530 /* dwarf_line_to_module.cc in Sources */,
B88FAE281166603300407530 /* language.cc in Sources */,

Просмотреть файл

@ -1,15 +1,20 @@
# HG changeset patch
# User Ted Mielczarek <ted.mielczarek@gmail.com>
# Date 1360255134 18000
# Node ID 97572beba4ad7fa4f76c3d1871d2001839a65b32
# Parent 229852c0b835929a56f207996034cf072307b343
# Node ID 294ce0d64d35a90be8ea91b719ead8b82aed29f7
# Parent d7bfb673574a3afe8b4f76f42fb52e2545770dad
Rework PostfixEvaluator to use UniqueStringMap
R=ted
Patch by Julian Seward <jseward@acm.org>, R=ted
diff --git a/src/common/unique_string.h b/src/common/unique_string.h
--- a/src/common/unique_string.h
+++ b/src/common/unique_string.h
@@ -30,6 +30,7 @@
@@ -25,16 +25,17 @@
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef COMMON_UNIQUE_STRING_H_
#define COMMON_UNIQUE_STRING_H_
@ -17,7 +22,17 @@ diff --git a/src/common/unique_string.h b/src/common/unique_string.h
#include <string>
#include "common/using_std_string.h"
@@ -234,6 +235,107 @@
namespace google_breakpad {
// Abstract type
class UniqueString;
@@ -229,11 +230,112 @@
// ".ra"
inline static const UniqueString* ustr__ZDra() {
static const UniqueString* us = NULL;
if (!us) us = ToUniqueString(".ra");
return us;
}
@ -128,7 +143,12 @@ diff --git a/src/common/unique_string.h b/src/common/unique_string.h
diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc
--- a/src/processor/basic_source_line_resolver_unittest.cc
+++ b/src/processor/basic_source_line_resolver_unittest.cc
@@ -29,6 +29,7 @@
@@ -24,16 +24,17 @@
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
@ -136,7 +156,17 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
#include <string>
#include "breakpad_googletest_includes.h"
@@ -52,6 +53,7 @@
#include "common/scoped_ptr.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/stack_frame.h"
@@ -47,16 +48,17 @@
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CFIFrameInfo;
using google_breakpad::CodeModule;
using google_breakpad::FromUniqueString;
using google_breakpad::MemoryRegion;
using google_breakpad::StackFrame;
using google_breakpad::ToUniqueString;
@ -144,7 +174,17 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
using google_breakpad::WindowsFrameInfo;
using google_breakpad::linked_ptr;
using google_breakpad::scoped_ptr;
@@ -118,9 +120,12 @@
using google_breakpad::ustr__ZDcfa;
using google_breakpad::ustr__ZDra;
using google_breakpad::ustr__ZSebx;
using google_breakpad::ustr__ZSebp;
using google_breakpad::ustr__ZSedi;
@@ -113,27 +115,30 @@
};
// Verify that, for every association in ACTUAL, EXPECTED has the same
// association. (That is, ACTUAL's associations should be a subset of
// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
// ".cfa".
static bool VerifyRegisters(
const char *file, int line,
@ -160,7 +200,7 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
a = actual.find(ustr__ZDcfa());
if (a == actual.end())
return false;
@@ -128,7 +133,7 @@
a = actual.find(ustr__ZDra());
if (a == actual.end())
return false;
for (a = actual.begin(); a != actual.end(); a++) {
@ -169,7 +209,17 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
expected.find(a->first);
if (e == expected.end()) {
fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
@@ -263,7 +268,7 @@
file, line, FromUniqueString(a->first), a->second);
return false;
}
if (e->second != a->second) {
fprintf(stderr,
@@ -258,86 +263,86 @@
frame.instruction = 0x3e9f;
frame.module = &module1;
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
ASSERT_FALSE(cfi_frame_info.get());
CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
@ -178,7 +228,14 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
MockMemoryRegion memory;
// Regardless of which instruction evaluation takes place at, it
@@ -278,11 +283,11 @@
// should produce the same values for the caller's registers.
expected_caller_registers[ustr__ZDcfa()] = 0x1001c;
expected_caller_registers[ustr__ZDra()] = 0xf6438648;
expected_caller_registers[ustr__ZSebp()] = 0x10038;
expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
frame.instruction = 0x3d40;
frame.module = &module1;
current_registers.clear();
@ -195,7 +252,9 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -292,7 +297,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers));
frame.instruction = 0x3d41;
@ -204,7 +263,9 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -302,7 +307,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers));
frame.instruction = 0x3d43;
@ -213,7 +274,9 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -312,7 +317,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d54;
@ -222,7 +285,9 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -322,7 +327,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d5a;
@ -231,7 +296,9 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -332,7 +337,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d84;
@ -240,10 +307,20 @@ diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processo
cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
diff --git a/src/processor/cfi_frame_info-inl.h b/src/processor/cfi_frame_info-inl.h
--- a/src/processor/cfi_frame_info-inl.h
+++ b/src/processor/cfi_frame_info-inl.h
@@ -40,30 +40,29 @@
@@ -35,64 +35,64 @@
#ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_
#define PROCESSOR_CFI_FRAME_INFO_INL_H_
#include <string.h>
namespace google_breakpad {
@ -281,7 +358,8 @@ diff --git a/src/processor/cfi_frame_info-inl.h b/src/processor/cfi_frame_info-i
return false;
// Populate *caller_context with the values the rules placed in
@@ -72,12 +71,12 @@
// caller_registers.
memset(caller_context, 0xda, sizeof(*caller_context));
*caller_validity = 0;
for (size_t i = 0; i < map_size_; i++) {
const RegisterSet &r = register_map_[i];
@ -298,7 +376,7 @@ diff --git a/src/processor/cfi_frame_info-inl.h b/src/processor/cfi_frame_info-i
*caller_validity |= r.validity_flag;
continue;
}
@@ -85,9 +84,10 @@
// Did the rules provide a value for this register under its
// alternate name?
if (r.alternate_name) {
@ -312,10 +390,20 @@ diff --git a/src/processor/cfi_frame_info-inl.h b/src/processor/cfi_frame_info-i
*caller_validity |= r.validity_flag;
continue;
}
}
// Is this a callee-saves register? The walker assumes that these
// still hold the caller's value if the CFI doesn't mention them.
//
diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
--- a/src/processor/cfi_frame_info.cc
+++ b/src/processor/cfi_frame_info.cc
@@ -67,7 +67,7 @@
@@ -66,33 +66,33 @@
V cfa;
working = registers;
if (!evaluator.EvaluateForValue(cfa_rule_, &cfa))
return false;
// Then, compute the return address.
V ra;
working = registers;
@ -324,7 +412,8 @@ diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
if (!evaluator.EvaluateForValue(ra_rule_, &ra))
return false;
@@ -76,14 +76,14 @@
// Now, compute values for all the registers register_rules_ mentions.
for (RuleMap::const_iterator it = register_rules_.begin();
it != register_rules_.end(); it++) {
V value;
working = registers;
@ -343,10 +432,20 @@ diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
return true;
}
// Explicit instantiations for 32-bit and 64-bit architectures.
template bool CFIFrameInfo::FindCallerRegs<uint32_t>(
const RegisterValueMap<uint32_t> &registers,
const MemoryRegion &memory,
diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
--- a/src/processor/cfi_frame_info.h
+++ b/src/processor/cfi_frame_info.h
@@ -69,7 +69,7 @@
@@ -64,17 +64,17 @@
// changes given by the 'STACK CFI' records up to our instruction's
// address. Then, use the FindCallerRegs member function to apply the
// rules to the callee frame's register values, yielding the caller
// frame's register values.
class CFIFrameInfo {
public:
// A map from register names onto values.
template<typename ValueType> class RegisterValueMap:
@ -355,10 +454,20 @@ diff --git a/src/processor/cfi_frame_info.h b/src/processor/cfi_frame_info.h
// Set the expression for computing a call frame address, return
// address, or register's value. At least the CFA rule and the RA
// rule must be set before calling FindCallerRegs.
void SetCFARule(const Module::Expr& rule) { cfa_rule_ = rule; }
void SetRARule(const Module::Expr& rule) { ra_rule_ = rule; }
void SetRegisterRule(const UniqueString* register_name,
const Module::Expr& rule) {
diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc
--- a/src/processor/cfi_frame_info_unittest.cc
+++ b/src/processor/cfi_frame_info_unittest.cc
@@ -116,9 +116,8 @@
@@ -111,19 +111,18 @@
TEST_F(Simple, SetCFAAndRARule) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("330903416631436410"));
cfi.SetRARule(Module::Expr("5870666104170902211"));
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
&caller_registers));
@ -370,7 +479,17 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211",
cfi.Serialize());
@@ -141,13 +140,12 @@
}
TEST_F(Simple, SetManyRules) {
ExpectNoMemoryReferences();
@@ -136,23 +135,22 @@
const UniqueString* reg4 = ToUniqueString("uncopyrightables");
cfi.SetRegisterRule(reg1, Module::Expr(".cfa 54370437 *"));
cfi.SetRegisterRule(reg2, Module::Expr("24076308 .cfa +"));
cfi.SetRegisterRule(reg3, Module::Expr(".cfa 29801007 -"));
cfi.SetRegisterRule(reg4, Module::Expr("92642917 .cfa /"));
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
&caller_registers));
@ -390,7 +509,17 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - "
".ra: .cfa 99804755 + "
"pubvexingfjordschmaltzy: .cfa 29801007 - "
@@ -165,9 +163,8 @@
"register1: .cfa 54370437 * "
"uncopyrightables: 92642917 .cfa / "
"vodkathumbscrewingly: 24076308 .cfa +",
cfi.Serialize());
}
@@ -160,19 +158,18 @@
TEST_F(Simple, RulesOverride) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("330903416631436410"));
cfi.SetRARule(Module::Expr("5870666104170902211"));
cfi.SetCFARule(Module::Expr("2828089117179001"));
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
&caller_registers));
@ -402,7 +531,17 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211",
cfi.Serialize());
}
@@ -201,15 +198,14 @@
class Scope: public CFIFixture, public Test { };
// There should be no value for .cfa in scope when evaluating the CFA rule.
TEST_F(Scope, CFALacksCFA) {
@@ -196,37 +193,35 @@
// The current frame's registers should be in scope when evaluating
// the CFA rule.
TEST_F(Scope, CFASeesCurrentRegs) {
ExpectNoMemoryReferences();
const UniqueString* reg1 = ToUniqueString(".baraminology");
const UniqueString* reg2 = ToUniqueString(".ornithorhynchus");
@ -421,7 +560,10 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
}
// .cfa should be in scope in the return address expression.
@@ -220,8 +216,7 @@
TEST_F(Scope, RASeesCFA) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("48364076"));
cfi.SetRARule(Module::Expr(".cfa"));
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
&caller_registers));
@ -431,7 +573,17 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
}
// There should be no value for .ra in scope when evaluating the CFA rule.
@@ -241,12 +236,11 @@
TEST_F(Scope, RALacksRA) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("0"));
cfi.SetRARule(Module::Expr(".ra"));
@@ -236,36 +231,34 @@
// The current frame's registers should be in scope in the return
// address expression.
TEST_F(Scope, RASeesCurrentRegs) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("10359370"));
const UniqueString* reg1 = ToUniqueString("noachian");
@ -446,7 +598,12 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
}
// .cfa should be in scope for register rules.
@@ -259,8 +253,7 @@
TEST_F(Scope, RegistersSeeCFA) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("6515179"));
cfi.SetRARule(Module::Expr(".cfa"));
const UniqueString* reg1 = ToUniqueString("rogerian");
cfi.SetRegisterRule(reg1, Module::Expr(".cfa"));
ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory,
&caller_registers));
@ -456,7 +613,17 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
}
// The return address should not be in scope for register rules.
@@ -281,17 +274,16 @@
TEST_F(Scope, RegsLackRA) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("42740329"));
cfi.SetRARule(Module::Expr("27045204"));
@@ -276,27 +269,26 @@
}
// Register rules can see the current frame's register values.
TEST_F(Scope, RegsSeeRegs) {
ExpectNoMemoryReferences();
const UniqueString* reg1 = ToUniqueString("$r1");
const UniqueString* reg2 = ToUniqueString("$r2");
@ -478,7 +645,17 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
}
// Each rule's temporaries are separate.
@@ -445,12 +437,12 @@
TEST_F(Scope, SeparateTempsRA) {
ExpectNoMemoryReferences();
cfi.SetCFARule(Module::Expr("$temp1 76569129 = $temp1"));
cfi.SetRARule(Module::Expr("0"));
@@ -440,39 +432,39 @@
CFIFrameInfoParseHandler handler;
};
class ParseHandler: public ParseHandlerFixture, public Test { };
TEST_F(ParseHandler, CFARARule) {
handler.CFARule("reg-for-cfa");
handler.RARule("reg-for-ra");
@ -495,7 +672,7 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
}
TEST_F(ParseHandler, RegisterRules) {
@@ -458,16 +450,16 @@
handler.CFARule("reg-for-cfa");
handler.RARule("reg-for-ra");
handler.RegisterRule(ToUniqueString("reg1"), "reg-for-reg1");
handler.RegisterRule(ToUniqueString("reg2"), "reg-for-reg2");
@ -520,10 +697,20 @@ diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_
}
struct SimpleCFIWalkerFixture {
struct RawContext {
uint64_t r0, r1, r2, r3, r4, sp, pc;
};
enum Validity {
R0_VALID = 0x01,
diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
--- a/src/processor/fast_source_line_resolver_unittest.cc
+++ b/src/processor/fast_source_line_resolver_unittest.cc
@@ -64,6 +64,7 @@
@@ -59,16 +59,17 @@
using google_breakpad::FromUniqueString;
using google_breakpad::ModuleSerializer;
using google_breakpad::ModuleComparer;
using google_breakpad::CFIFrameInfo;
using google_breakpad::CodeModule;
using google_breakpad::MemoryRegion;
using google_breakpad::StackFrame;
using google_breakpad::ToUniqueString;
@ -531,7 +718,17 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
using google_breakpad::WindowsFrameInfo;
using google_breakpad::linked_ptr;
using google_breakpad::scoped_ptr;
@@ -130,9 +131,12 @@
using google_breakpad::ustr__ZDcfa;
using google_breakpad::ustr__ZDra;
using google_breakpad::ustr__ZSebx;
using google_breakpad::ustr__ZSebp;
using google_breakpad::ustr__ZSedi;
@@ -125,27 +126,30 @@
};
// Verify that, for every association in ACTUAL, EXPECTED has the same
// association. (That is, ACTUAL's associations should be a subset of
// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and
// ".cfa".
static bool VerifyRegisters(
const char *file, int line,
@ -547,7 +744,7 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
a = actual.find(ustr__ZDcfa());
if (a == actual.end())
return false;
@@ -140,7 +144,7 @@
a = actual.find(ustr__ZDra());
if (a == actual.end())
return false;
for (a = actual.begin(); a != actual.end(); a++) {
@ -556,7 +753,17 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
expected.find(a->first);
if (e == expected.end()) {
fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n",
@@ -291,13 +295,14 @@
file, line, FromUniqueString(a->first), a->second);
return false;
}
if (e->second != a->second) {
fprintf(stderr,
@@ -286,86 +290,87 @@
frame.instruction = 0x3e9f;
frame.module = &module1;
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_FALSE(cfi_frame_info.get());
CFIFrameInfo::RegisterValueMap<uint32_t> current_registers;
CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
@ -573,7 +780,8 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
expected_caller_registers[ustr__ZSebp()] = 0x10038;
expected_caller_registers[ustr__ZSebx()] = 0x98ecadc3;
expected_caller_registers[ustr__ZSesi()] = 0x878f7524;
@@ -306,11 +311,11 @@
expected_caller_registers[ustr__ZSedi()] = 0x6312f9a5;
frame.instruction = 0x3d40;
frame.module = &module1;
current_registers.clear();
@ -590,7 +798,9 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -320,7 +325,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers));
frame.instruction = 0x3d41;
@ -599,7 +809,9 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -330,7 +335,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers));
frame.instruction = 0x3d43;
@ -608,7 +820,9 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -340,7 +345,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d54;
@ -617,7 +831,9 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -350,7 +355,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d5a;
@ -626,7 +842,9 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
@@ -360,7 +365,7 @@
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
frame.instruction = 0x3d84;
@ -635,10 +853,20 @@ diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor
cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame));
ASSERT_TRUE(cfi_frame_info.get());
ASSERT_TRUE(cfi_frame_info.get()
->FindCallerRegs<uint32_t>(current_registers, memory,
&caller_registers));
VerifyRegisters(__FILE__, __LINE__,
expected_caller_registers, caller_registers);
diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h
--- a/src/processor/postfix_evaluator-inl.h
+++ b/src/processor/postfix_evaluator-inl.h
@@ -190,9 +190,9 @@
@@ -185,19 +185,19 @@
return false;
}
if (identifier == ustr__empty() || Index(identifier,0) != '$') {
BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " <<
identifier << ": " << expression;
return false;
}
@ -650,7 +878,17 @@ diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evalu
} else {
// Push it onto the stack as-is, but first convert it either to a
// ValueType (if a literal) or to a UniqueString* (if an identifier).
@@ -305,18 +305,18 @@
//
// First, try to treat the value as a literal. Literals may have leading
// '-' sign, and the entire remaining string must be parseable as
// ValueType. If this isn't possible, it can't be a literal, so treat it
// as an identifier instead.
@@ -300,28 +300,28 @@
return PopValue(result);
}
// Simple-form expressions
case Module::kExprSimple:
case Module::kExprSimpleMem: {
// Look up the base value
@ -674,7 +912,17 @@ diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evalu
// and dereference if necessary
if (expr.how_ == Module::kExprSimpleMem) {
@@ -373,9 +373,9 @@
ValueType derefd;
if (!memory_ || !memory_->GetMemoryAtAddress(sum, &derefd)) {
return false;
}
*result = derefd;
@@ -368,27 +368,27 @@
if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) {
return false;
} else if (result == POP_RESULT_VALUE) {
// This is the easy case.
*value = literal;
} else { // result == POP_RESULT_IDENTIFIER
// There was an identifier at the top of the stack. Resolve it to a
// value by looking it up in the dictionary.
@ -687,7 +935,7 @@ diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evalu
// The identifier wasn't found in the dictionary. Don't imply any
// default value, just fail.
BPLOG(INFO) << "Identifier " << FromUniqueString(token)
@@ -383,7 +383,7 @@
<< " not in dictionary";
return false;
}
@ -696,10 +944,20 @@ diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evalu
}
return true;
}
template<typename ValueType>
bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1,
diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator.h
--- a/src/processor/postfix_evaluator.h
+++ b/src/processor/postfix_evaluator.h
@@ -98,8 +98,8 @@
@@ -93,18 +93,18 @@
StackElem(const UniqueString* ustr) { isValue = false; u.ustr = ustr; }
bool isValue;
union { ValueType val; const UniqueString* ustr; } u;
};
template<typename ValueType>
class PostfixEvaluator {
public:
@ -710,10 +968,20 @@ diff --git a/src/processor/postfix_evaluator.h b/src/processor/postfix_evaluator
// Create a PostfixEvaluator object that may be used (with Evaluate) on
// one or more expressions. PostfixEvaluator does not take ownership of
// either argument. |memory| may be NULL, in which case dereferencing
// (^) will not be supported. |dictionary| may be NULL, but evaluation
// will fail in that case unless set_dictionary is used before calling
// Evaluate.
PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory)
diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc
--- a/src/processor/postfix_evaluator_unittest.cc
+++ b/src/processor/postfix_evaluator_unittest.cc
@@ -183,12 +183,12 @@
@@ -178,22 +178,22 @@
validate_data_0[ToUniqueString("$rAdd3")] = 4;
validate_data_0[ToUniqueString("$rMul2")] = 54;
// The second test set simulates a couple of MSVC program strings.
// The data is fudged a little bit because the tests use FakeMemoryRegion
// instead of a real stack snapshot, but the program strings are real and
// the implementation doesn't know or care that the data is not real.
PostfixEvaluator<unsigned int>::DictionaryType dictionary_1;
@ -732,7 +1000,17 @@ diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix
const EvaluateTest evaluate_tests_1[] = {
{ "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
"$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true },
@@ -278,12 +278,8 @@
// Intermediate state: $T0 = 0xbfff0010, $eip = 0xbfff0015,
// $ebp = 0xbfff0011, $esp = 0xbfff0018,
// $L = 0xbfff000c, $P = 0xbfff001c
{ "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = "
"$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =",
@@ -273,70 +273,65 @@
for (map<const UniqueString*, unsigned int>::const_iterator
validate_iterator =
evaluate_test_set->validate_data->begin();
validate_iterator != evaluate_test_set->validate_data->end();
++validate_iterator) {
const UniqueString* identifier = validate_iterator->first;
unsigned int expected_value = validate_iterator->second;
@ -746,7 +1024,9 @@ diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
"validate identifier \"%s\", "
"expected %d, observed not found\n",
@@ -293,7 +289,8 @@
evaluate_test_set_index, evaluate_test_set_count,
FromUniqueString(identifier), expected_value);
return false;
}
// The value in the dictionary must be the same as the expected value.
@ -756,7 +1036,13 @@ diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix
if (expected_value != observed_value) {
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
"validate identifier \"%s\", "
@@ -307,10 +304,8 @@
"expected %d, observed %d\n",
evaluate_test_set_index, evaluate_test_set_count,
FromUniqueString(identifier), expected_value, observed_value);
return false;
}
// The value must be set in the "assigned" dictionary if it was a
// variable. It must not have been assigned if it was a constant.
bool expected_assigned = FromUniqueString(identifier)[0] == '$';
bool observed_assigned = false;
@ -769,7 +1055,15 @@ diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix
}
if (expected_assigned != observed_assigned) {
fprintf(stderr, "FAIL: evaluate test set %d/%d, "
@@ -326,12 +321,12 @@
"validate assignment of \"%s\", "
"expected %d, observed %d\n",
evaluate_test_set_index, evaluate_test_set_count,
FromUniqueString(identifier), expected_assigned,
observed_assigned);
return false;
}
}
}
// EvaluateForValue tests.
PostfixEvaluator<unsigned int>::DictionaryType dictionary_2;
@ -788,7 +1082,17 @@ diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix
const EvaluateForValueTest evaluate_for_value_tests_2[] = {
{ "28907223", true, 28907223 }, // simple constant
{ "89854293 40010015 +", true, 89854293 + 40010015 }, // arithmetic
@@ -375,12 +370,14 @@
{ "-870245 8769343 +", true, 7899098 }, // negative constants
{ "$ebp $esp - $eip +", true, 0x10000010 }, // variable references
{ "18929794 34015074", false, 0 }, // too many values
{ "$ebp $ebp 4 - =", false, 0 }, // too few values
{ "$new $eip = $new", true, 0x10000000 }, // make new variable
@@ -370,41 +365,43 @@
if (test->evaluable && result != test->value) {
fprintf(stderr, "FAIL: evaluate for value test %d, "
"expected value to be 0x%x, but it was 0x%x\n",
i, test->value, result);
return false;
}
}
@ -805,7 +1109,9 @@ diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix
fprintf(stderr, "FAIL: evaluate for value dictionary check: "
"expected dict[\"%s\"] to be 0x%x, but it was unset\n",
FromUniqueString(v->first), v->second);
@@ -390,16 +387,16 @@
return false;
} else if (a->second != v->second) {
fprintf(stderr, "FAIL: evaluate for value dictionary check: "
"expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n",
FromUniqueString(v->first), v->second, a->second);
return false;
@ -828,10 +1134,20 @@ diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix
fprintf(stderr, " dict[\"%s\"] == 0x%x\n",
FromUniqueString(remaining->first), remaining->second);
return false;
}
return true;
}
diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
--- a/src/processor/stackwalker_arm.cc
+++ b/src/processor/stackwalker_arm.cc
@@ -102,7 +102,7 @@
@@ -97,70 +97,70 @@
ToUniqueString("fps"), ToUniqueString("cpsr"),
NULL
};
// Populate a dictionary with the valid register values in last_frame.
CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers;
for (int i = 0; register_names[i]; i++)
if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i))
@ -840,7 +1156,10 @@ diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
// Use the STACK CFI data to recover the caller's register values.
CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers;
@@ -113,13 +113,13 @@
if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
&caller_registers))
return NULL;
// Construct a new stack frame given the values the CFI recovered.
scoped_ptr<StackFrameARM> frame(new StackFrameARM());
for (int i = 0; register_names[i]; i++) {
@ -858,7 +1177,12 @@ diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
} else if (4 <= i && i <= 11 && (last_frame->context_validity &
StackFrameARM::RegisterValidFlag(i))) {
// If the STACK CFI data doesn't mention some callee-saves register, and
@@ -132,18 +132,18 @@
// it is valid in the callee, assume the callee has not yet changed it.
// Registers r4 through r11 are callee-saves, according to the Procedure
// Call Standard for the ARM Architecture, which the Linux ABI follows.
frame->context_validity |= StackFrameARM::RegisterValidFlag(i);
frame->context.iregs[i] = last_frame->context.iregs[i];
}
}
// If the CFI doesn't recover the PC explicitly, then use .ra.
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
@ -882,7 +1206,7 @@ diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
frame->context.iregs[MD_CONTEXT_ARM_REG_PC] =
last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR];
}
@@ -151,11 +151,11 @@
}
}
// If the CFI doesn't recover the SP explicitly, then use .cfa.
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
@ -898,10 +1222,20 @@ diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
}
}
// If we didn't recover the PC and the SP, then the frame isn't very useful.
static const int essentials = (StackFrameARM::CONTEXT_VALID_SP
| StackFrameARM::CONTEXT_VALID_PC);
if ((frame->context_validity & essentials) != essentials)
return NULL;
diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
--- a/src/processor/stackwalker_x86.cc
+++ b/src/processor/stackwalker_x86.cc
@@ -199,16 +199,16 @@
@@ -194,26 +194,26 @@
}
}
// Set up the dictionary for the PostfixEvaluator. %ebp and %esp are used
// in each program string, and their previous values are known, so set them
// here.
PostfixEvaluator<uint32_t>::DictionaryType dictionary;
// Provide the current register values.
@ -923,7 +1257,17 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
uint32_t raSearchStart = last_frame->context.esp +
last_frame_callee_parameter_size +
@@ -237,10 +237,10 @@
last_frame_info->local_size +
last_frame_info->saved_register_size;
uint32_t raSearchStartOld = raSearchStart;
uint32_t found = 0; // dummy value
@@ -232,20 +232,20 @@
// Skip one slot from the stack and do another scan in order to get the
// actual return address.
raSearchStart += 4;
ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3);
}
// The difference between raSearch and raSearchStart is unknown,
// but making them the same seems to work well in practice.
@ -937,7 +1281,17 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
// Decide what type of program string to use. The program string is in
// postfix notation and will be passed to PostfixEvaluator::Evaluate.
@@ -330,8 +330,8 @@
// Given the dictionary and the program string, it is possible to compute
// the return address and the values of other registers in the calling
// function. Because of bugs described below, the stack may need to be
// scanned for these values. The results of program string evaluation
// will be used to determine whether to scan for better values.
@@ -325,18 +325,18 @@
}
// Now crank it out, making sure that the program string set at least the
// two required variables.
PostfixEvaluator<uint32_t> evaluator =
PostfixEvaluator<uint32_t>(&dictionary, memory_);
PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity;
if (!evaluator.Evaluate(program_string, &dictionary_validity) ||
@ -948,7 +1302,17 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
// Program string evaluation failed. It may be that %eip is not somewhere
// with stack frame info, and %ebp is pointing to non-stack memory, so
// our evaluation couldn't succeed. We'll scan the stack for a return
@@ -349,8 +349,8 @@
// address. This can happen if the stack is in a module for which
// we don't have symbols, and that module is compiled without a
// frame pointer.
uint32_t location_start = last_frame->context.esp;
uint32_t location, eip;
@@ -344,69 +344,70 @@
// if we can't find an instruction pointer even with stack scanning,
// give up.
return NULL;
}
// This seems like a reasonable return address. Since program string
// evaluation failed, use it and set %esp to the location above the
// one where the return address was found.
@ -959,7 +1323,10 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
trust = StackFrame::FRAME_TRUST_SCAN;
}
@@ -361,7 +361,8 @@
// Since this stack frame did not use %ebp in a traditional way,
// locating the return address isn't entirely deterministic. In that
// case, the stack can be scanned to locate the return address.
//
// However, if program string evaluation resulted in both %eip and
// %ebp values of 0, trust that the end of the stack has been
// reached and don't scan for anything else.
@ -969,7 +1336,14 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
int offset = 0;
// This scan can only be done if a CodeModules object is available, to
@@ -376,18 +377,18 @@
// check that candidate return addresses are in fact inside a module.
//
// TODO(mmentovai): This ignores dynamically-generated code. One possible
// solution is to check the minidump's memory map to see if the candidate
// %eip value comes from a mapped executable page, although this would
// require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad
// client doesn't currently write (it would need to call MiniDumpWriteDump
// with the MiniDumpWithFullMemoryInfo type bit set). Even given this
// ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce
// an independent execute privilege on memory pages.
@ -992,7 +1366,13 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
offset = location - location_start;
trust = StackFrame::FRAME_TRUST_CFI_SCAN;
}
@@ -401,7 +402,7 @@
}
if (recover_ebp) {
// When trying to recover the previous value of the frame pointer (%ebp),
// start looking at the lowest possible address in the saved-register
// area, and look at the entire saved register area, increased by the
// size of |offset| to account for additional data that may be on the
// stack. The scan is performed from the highest possible address to
// the lowest, because the expectation is that the function's prolog
// would have saved %ebp early.
@ -1001,7 +1381,17 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
// When a scan for return address is used, it is possible to skip one or
// more frames (when return address is not in a known module). One
@@ -425,7 +426,7 @@
// indication for skipped frames is when the value of %ebp is lower than
// the location of the return address on the stack
bool has_skipped_frames =
(trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset);
@@ -420,49 +421,49 @@
location >= location_end;
location -= 4) {
if (!memory_->GetMemoryAtAddress(location, &ebp))
break;
if (memory_->GetMemoryAtAddress(ebp, &value)) {
// The candidate value is a pointer to the same memory region
// (the stack). Prefer it as a recovered %ebp result.
@ -1010,7 +1400,13 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
break;
}
}
@@ -439,25 +440,25 @@
}
}
}
// Create a new stack frame (ownership will be transferred to the caller)
// and fill it in.
StackFrameX86* frame = new StackFrameX86();
frame->trust = trust;
frame->context = last_frame->context;
@ -1045,3 +1441,8 @@ diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI;
}
return frame;
}
StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
const vector<StackFrame*> &frames,

Просмотреть файл

@ -1,46 +0,0 @@
# HG changeset patch
# User Ted Mielczarek <ted.mielczarek@gmail.com>
# Date 1360255134 18000
# Node ID 74d4bb64dc84b4bc73939af06d804b71425e51d4
# Parent 97572beba4ad7fa4f76c3d1871d2001839a65b32
Minor Android fixup for symbol dumping code
R=ted
diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc
--- a/src/common/dwarf_cu_to_module.cc
+++ b/src/common/dwarf_cu_to_module.cc
@@ -39,7 +39,9 @@
#include "common/dwarf_cu_to_module.h"
#include <assert.h>
+#if !defined(__ANDROID__)
#include <cxxabi.h>
+#endif
#include <inttypes.h>
#include <stdio.h>
@@ -313,7 +315,10 @@
name_attribute_ = AddStringToPool(data);
break;
case dwarf2reader::DW_AT_MIPS_linkage_name: {
- char* demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, NULL);
+ char* demangled = NULL;
+#if !defined(__ANDROID__)
+ demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, NULL);
+#endif
if (demangled) {
demangled_name_ = AddStringToPool(demangled);
free(reinterpret_cast<void*>(demangled));
@@ -783,9 +788,9 @@
// complexity from here on out is linear.
// Put both our functions and lines in order by address.
- sort(functions->begin(), functions->end(),
- Module::Function::CompareByAddress);
- sort(lines_.begin(), lines_.end(), Module::Line::CompareByAddress);
+ std::sort(functions->begin(), functions->end(),
+ Module::Function::CompareByAddress);
+ std::sort(lines_.begin(), lines_.end(), Module::Line::CompareByAddress);
// The last line that we used any piece of. We use this only for
// generating warnings.

Просмотреть файл

@ -1,97 +0,0 @@
# HG changeset patch
# User Ted Mielczarek <ted.mielczarek@gmail.com>
# Date 1360255134 18000
# Node ID 47146439a92d83b7add8af766ec53eaf41c10ec2
# Parent 74d4bb64dc84b4bc73939af06d804b71425e51d4
Provide a ReadSymbolData API for Mac dump_syms
R=mark at https://breakpad.appspot.com/522002/
diff --git a/src/common/mac/dump_syms.h b/src/common/mac/dump_syms.h
--- a/src/common/mac/dump_syms.h
+++ b/src/common/mac/dump_syms.h
@@ -116,6 +116,11 @@
// return false.
bool WriteSymbolFile(std::ostream &stream);
+ // As above, but simply return the debugging information in module
+ // instead of writing it to a stream. The caller owns the resulting
+ // module object and must delete it when finished.
+ bool ReadSymbolData(Module** module);
+
private:
// Used internally.
class DumperLineToModule;
diff --git a/src/common/mac/dump_syms.mm b/src/common/mac/dump_syms.mm
--- a/src/common/mac/dump_syms.mm
+++ b/src/common/mac/dump_syms.mm
@@ -53,9 +53,11 @@
#include "common/mac/arch_utilities.h"
#include "common/mac/macho_reader.h"
#include "common/module.h"
+#include "common/scoped_ptr.h"
#include "common/stabs_reader.h"
#include "common/stabs_to_module.h"
#include "common/symbol_data.h"
+#include "common/unique_string.h"
#ifndef CPU_TYPE_ARM
#define CPU_TYPE_ARM (static_cast<cpu_type_t>(12))
@@ -71,6 +73,7 @@
using google_breakpad::Module;
using google_breakpad::StabsReader;
using google_breakpad::StabsToModule;
+using google_breakpad::scoped_ptr;
using std::make_pair;
using std::pair;
using std::string;
@@ -439,7 +442,7 @@
return true;
}
-bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
+bool DumpSymbols::ReadSymbolData(Module** out_module) {
// Select an object file, if SetArchitecture hasn't been called to set one
// explicitly.
if (!selected_object_file_) {
@@ -490,8 +493,10 @@
identifier += "0";
// Create a module to hold the debugging information.
- Module module([module_name UTF8String], "mac", selected_arch_name,
- identifier);
+ scoped_ptr<Module> module(new Module([module_name UTF8String],
+ "mac",
+ selected_arch_name,
+ identifier));
// Parse the selected object file.
mach_o::Reader::Reporter reporter(selected_object_name_);
@@ -504,11 +509,26 @@
return false;
// Walk its load commands, and deal with whatever is there.
- LoadCommandDumper load_command_dumper(*this, &module, reader, symbol_data_);
+ LoadCommandDumper load_command_dumper(*this, module.get(), reader,
+ symbol_data_);
if (!reader.WalkLoadCommands(&load_command_dumper))
return false;
- return module.Write(stream, symbol_data_);
+ *out_module = module.release();
+
+ return true;
+}
+
+bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
+ Module* module = NULL;
+
+ if (ReadSymbolData(&module) && module) {
+ bool res = module->Write(stream, symbol_data_);
+ delete module;
+ return res;
+ }
+
+ return false;
}
} // namespace google_breakpad

Просмотреть файл

@ -1,174 +0,0 @@
# HG changeset patch
# Parent 6131d396790eefed8441bf0566ff38f59ca092b3
Fix some more Win32 compat issues in processor code
R=mark at https://breakpad.appspot.com/535003/
diff --git a/src/google_breakpad/common/breakpad_types.h b/src/google_breakpad/common/breakpad_types.h
--- a/src/google_breakpad/common/breakpad_types.h
+++ b/src/google_breakpad/common/breakpad_types.h
@@ -57,16 +57,17 @@
* there are often subtle type incompatibilities.
*/
#include BREAKPAD_CUSTOM_STDINT_H
#else
#include <WTypes.h>
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#endif
#endif /* !_WIN32 */
typedef struct {
uint64_t high;
diff --git a/src/processor/basic_source_line_resolver.cc b/src/processor/basic_source_line_resolver.cc
--- a/src/processor/basic_source_line_resolver.cc
+++ b/src/processor/basic_source_line_resolver.cc
@@ -49,16 +49,21 @@
#include "processor/tokenize.h"
using std::map;
using std::vector;
using std::make_pair;
namespace google_breakpad {
+#ifdef _WIN32
+#define strtok_r strtok_s
+#define strtoull _strtoui64
+#endif
+
static const char *kWhitespace = " \r\n";
BasicSourceLineResolver::BasicSourceLineResolver() :
SourceLineResolverBase(new BasicModuleFactory) { }
bool BasicSourceLineResolver::Module::LoadMapFromMemory(char *memory_buffer) {
linked_ptr<Function> cur_func;
int line_number = 0;
diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc
--- a/src/processor/cfi_frame_info.cc
+++ b/src/processor/cfi_frame_info.cc
@@ -39,16 +39,20 @@
#include <algorithm>
#include <sstream>
#include "common/scoped_ptr.h"
#include "processor/postfix_evaluator-inl.h"
namespace google_breakpad {
+#ifdef _WIN32
+#define strtok_r strtok_s
+#endif
+
template<typename V>
bool CFIFrameInfo::FindCallerRegs(const RegisterValueMap<V> &registers,
const MemoryRegion &memory,
RegisterValueMap<V> *caller_registers) const {
// If there are not rules for both .ra and .cfa in effect at this address,
// don't use this CFI data for stack walking.
if (cfa_rule_.invalid() || ra_rule_.invalid())
return false;
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -32,25 +32,23 @@
// See minidump.h for documentation.
//
// Author: Mark Mentovai
#include "google_breakpad/processor/minidump.h"
#include <assert.h>
#include <fcntl.h>
+#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
#include <io.h>
-#if _MSC_VER < 1600
-typedef SSIZE_T ssize_t;
-#endif
#define PRIx64 "llx"
#define PRIx32 "lx"
#define snprintf _snprintf
#else // _WIN32
#include <unistd.h>
#define O_BINARY 0
#endif // _WIN32
diff --git a/src/processor/source_line_resolver_base_types.h b/src/processor/source_line_resolver_base_types.h
--- a/src/processor/source_line_resolver_base_types.h
+++ b/src/processor/source_line_resolver_base_types.h
@@ -38,16 +38,17 @@
//
// Author: Siyang Xie (lambxsy@google.com)
#include <stdio.h>
#include <map>
#include <string>
+#include "google_breakpad/common/breakpad_types.h"
#include "google_breakpad/processor/source_line_resolver_base.h"
#include "google_breakpad/processor/stack_frame.h"
#include "processor/cfi_frame_info.h"
#include "processor/windows_frame_info.h"
#ifndef PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
#define PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__
diff --git a/src/processor/tokenize.cc b/src/processor/tokenize.cc
--- a/src/processor/tokenize.cc
+++ b/src/processor/tokenize.cc
@@ -31,16 +31,20 @@
#include <string>
#include <vector>
#include "common/using_std_string.h"
namespace google_breakpad {
+#ifdef _WIN32
+#define strtok_r strtok_s
+#endif
+
using std::vector;
bool Tokenize(char *line,
const char *separators,
int max_tokens,
vector<char*> *tokens) {
tokens->clear();
tokens->reserve(max_tokens);
diff --git a/src/processor/windows_frame_info.h b/src/processor/windows_frame_info.h
--- a/src/processor/windows_frame_info.h
+++ b/src/processor/windows_frame_info.h
@@ -46,16 +46,20 @@
#include "common/using_std_string.h"
#include "google_breakpad/common/breakpad_types.h"
#include "processor/logging.h"
#include "processor/tokenize.h"
namespace google_breakpad {
+#ifdef _WIN32
+#define strtoull _strtoui64
+#endif
+
struct WindowsFrameInfo {
public:
enum Validity {
VALID_NONE = 0,
VALID_PARAMETER_SIZE = 1,
VALID_ALL = -1
};

Просмотреть файл

@ -1,5 +1,8 @@
# HG changeset patch
# Parent 370ef99fecb269ea8c30a56c4a0cf5ab11844868
# User Ted Mielczarek <ted@mielczarek.org>
# Date 1362600444 18000
# Node ID 0eb3c7ba8a38a269ab975eff3f95a1a5d5d937b9
# Parent 6b68e82037b8322fb392cea369d517aeeaaee9d3
Stop using dynamic_cast in dwarf2reader
Patch by Julian Seward <jseward@acm.org>, R=ted

Просмотреть файл

@ -1,118 +0,0 @@
# HG changeset patch
# Parent b82a8a320d2e1fc61565872cdd355605895a7602
Allow building symbol dumping without STABS support
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -58,34 +58,38 @@
#include "common/dwarf_cu_to_module.h"
#include "common/dwarf_line_to_module.h"
#include "common/linux/elfutils.h"
#include "common/linux/elfutils-inl.h"
#include "common/linux/elf_symbols_to_module.h"
#include "common/linux/file_id.h"
#include "common/module.h"
#include "common/scoped_ptr.h"
+#ifndef NO_STABS_SUPPORT
#include "common/stabs_reader.h"
#include "common/stabs_to_module.h"
+#endif
#include "common/using_std_string.h"
// This namespace contains helper functions.
namespace {
using google_breakpad::DwarfCFIToModule;
using google_breakpad::DwarfCUToModule;
using google_breakpad::DwarfLineToModule;
using google_breakpad::ElfClass;
using google_breakpad::ElfClass32;
using google_breakpad::ElfClass64;
using google_breakpad::FindElfSectionByName;
using google_breakpad::GetOffset;
using google_breakpad::IsValidElf;
using google_breakpad::Module;
+#ifndef NO_STABS_SUPPORT
using google_breakpad::StabsToModule;
+#endif
using google_breakpad::UniqueString;
using google_breakpad::scoped_ptr;
//
// FDWrapper
//
// Wrapper class to make sure opened file is closed.
//
@@ -154,16 +158,17 @@
if (header.p_type == PT_LOAD &&
header.p_offset == 0)
return header.p_vaddr;
}
// For other types of ELF, return 0.
return 0;
}
+#ifndef NO_STABS_SUPPORT
template<typename ElfClass>
bool LoadStabs(const typename ElfClass::Ehdr* elf_header,
const typename ElfClass::Shdr* stab_section,
const typename ElfClass::Shdr* stabstr_section,
const bool big_endian,
Module* module) {
// A callback object to handle data from the STABS reader.
StabsToModule handler(module);
@@ -179,16 +184,17 @@
stabstr, stabstr_section->sh_size,
big_endian, 4, true, &handler);
// Read the STABS data, and do post-processing.
if (!reader.Process())
return false;
handler.Finalize();
return true;
}
+#endif // NO_STABS_SUPPORT
// A line-to-module loader that accepts line number info parsed by
// dwarf2reader::LineInfo and populates a Module and a line vector
// with the results.
class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler {
public:
// Create a line-to-module converter using BYTE_READER.
explicit DumperLineToModule(dwarf2reader::ByteReader *byte_reader)
@@ -533,16 +539,17 @@
const Shdr* section_names = sections + elf_header->e_shstrndx;
const char* names =
GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
const char *names_end = names + section_names->sh_size;
bool found_debug_info_section = false;
bool found_usable_info = false;
if (symbol_data != ONLY_CFI) {
+#ifndef NO_STABS_SUPPORT
// Look for STABS debugging information, and load it if present.
const Shdr* stab_section =
FindElfSectionByName<ElfClass>(".stab", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
if (stab_section) {
const Shdr* stabstr_section = stab_section->sh_link + sections;
if (stabstr_section) {
@@ -551,16 +558,17 @@
info->LoadedSection(".stab");
if (!LoadStabs<ElfClass>(elf_header, stab_section, stabstr_section,
big_endian, module)) {
fprintf(stderr, "%s: \".stab\" section found, but failed to load"
" STABS debugging information\n", obj_file.c_str());
}
}
}
+#endif // NO_STABS_SUPPORT
// Look for DWARF debugging information, and load it if present.
const Shdr* dwarf_section =
FindElfSectionByName<ElfClass>(".debug_info", SHT_PROGBITS,
sections, names, names_end,
elf_header->e_shnum);
if (dwarf_section) {
found_debug_info_section = true;

Просмотреть файл

@ -2,10 +2,10 @@ Path: ../google-breakpad-svn
URL: https://google-breakpad.googlecode.com/svn/trunk
Repository Root: https://google-breakpad.googlecode.com/svn
Repository UUID: 4c0a9323-5329-0410-9bdc-e9ce6186880e
Revision: 1120
Revision: 1128
Node Kind: directory
Schedule: normal
Last Changed Author: ted.mielczarek@gmail.com
Last Changed Rev: 1120
Last Changed Date: 2013-03-04 10:42:50 -0500 (Mon, 04 Mar 2013)
Last Changed Rev: 1128
Last Changed Date: 2013-03-06 15:14:34 -0500 (Wed, 06 Mar 2013)

Просмотреть файл

@ -363,11 +363,14 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
// decide if this should be sent.
if (filter_ && !filter_(callback_context_))
return false;
return crash_generation_client_->RequestDumpForException(
result = crash_generation_client_->RequestDumpForException(
exception_type,
exception_code,
exception_subcode,
thread_name);
if (result && exit_after_write) {
_exit(exception_type);
}
}
#endif
} else {

Просмотреть файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -210,7 +210,7 @@ class MachMessage {
struct MessageDataPacket {
int32_t id; // little-endian
int32_t data_length; // little-endian
uint8_t data[1]; // actual size limited by sizeof(MachMessage)
uint8_t data[1]; // actual size limited by sizeof(MachMessage)
};
MessageDataPacket* GetDataPacket();
@ -223,7 +223,7 @@ class MachMessage {
mach_msg_header_t head;
mach_msg_body_t body;
uint8_t padding[1024]; // descriptors and data may be embedded here
uint8_t padding[1024]; // descriptors and data may be embedded here
};
//==============================================================================

Просмотреть файл

@ -57,7 +57,6 @@
#include "common/stabs_reader.h"
#include "common/stabs_to_module.h"
#include "common/symbol_data.h"
#include "common/unique_string.h"
#ifndef CPU_TYPE_ARM
#define CPU_TYPE_ARM (static_cast<cpu_type_t>(12))

Просмотреть файл

@ -328,9 +328,9 @@ bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
<< func->size << " "
<< func->parameter_size << " "
<< func->name << dec << endl;
if (!stream.good())
return ReportError();
for (vector<Line>::iterator line_it = func->lines.begin();
line_it != func->lines.end(); ++line_it) {
stream << hex
@ -351,8 +351,6 @@ bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
stream << "PUBLIC " << hex
<< (ext->address - load_address_) << " 0 "
<< ext->name << dec << endl;
if (!stream.good())
return ReportError();
}
}

Просмотреть файл

@ -72,7 +72,7 @@ typedef unsigned __int64 uint64_t;
typedef struct {
uint64_t high;
uint64_t low;
} uint128_t;
} uint128_struct;
typedef uint64_t breakpad_time_t;

Просмотреть файл

@ -67,7 +67,7 @@
* equivalent types and values in the Windows Platform SDK are given in
* comments.
*
* Author: Mark Mentovai
* Author: Mark Mentovai
* Change to split into its own file: Neal Sidhwaney */
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__
@ -79,22 +79,22 @@
*/
typedef struct {
uint16_t control_word;
uint16_t status_word;
uint8_t tag_word;
uint8_t reserved1;
uint16_t error_opcode;
uint32_t error_offset;
uint16_t error_selector;
uint16_t reserved2;
uint32_t data_offset;
uint16_t data_selector;
uint16_t reserved3;
uint32_t mx_csr;
uint32_t mx_csr_mask;
uint128_t float_registers[8];
uint128_t xmm_registers[16];
uint8_t reserved4[96];
uint16_t control_word;
uint16_t status_word;
uint8_t tag_word;
uint8_t reserved1;
uint16_t error_opcode;
uint32_t error_offset;
uint16_t error_selector;
uint16_t reserved2;
uint32_t data_offset;
uint16_t data_selector;
uint16_t reserved3;
uint32_t mx_csr;
uint32_t mx_csr_mask;
uint128_struct float_registers[8];
uint128_struct xmm_registers[16];
uint8_t reserved4[96];
} MDXmmSaveArea32AMD64; /* XMM_SAVE_AREA32 */
#define MD_CONTEXT_AMD64_VR_COUNT 26
@ -127,7 +127,7 @@ typedef struct {
/* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */
uint16_t ss;
uint32_t eflags;
/* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
uint64_t dr0;
uint64_t dr1;
@ -167,29 +167,29 @@ typedef struct {
union {
MDXmmSaveArea32AMD64 flt_save;
struct {
uint128_t header[2];
uint128_t legacy[8];
uint128_t xmm0;
uint128_t xmm1;
uint128_t xmm2;
uint128_t xmm3;
uint128_t xmm4;
uint128_t xmm5;
uint128_t xmm6;
uint128_t xmm7;
uint128_t xmm8;
uint128_t xmm9;
uint128_t xmm10;
uint128_t xmm11;
uint128_t xmm12;
uint128_t xmm13;
uint128_t xmm14;
uint128_t xmm15;
uint128_struct header[2];
uint128_struct legacy[8];
uint128_struct xmm0;
uint128_struct xmm1;
uint128_struct xmm2;
uint128_struct xmm3;
uint128_struct xmm4;
uint128_struct xmm5;
uint128_struct xmm6;
uint128_struct xmm7;
uint128_struct xmm8;
uint128_struct xmm9;
uint128_struct xmm10;
uint128_struct xmm11;
uint128_struct xmm12;
uint128_struct xmm13;
uint128_struct xmm14;
uint128_struct xmm15;
} sse_registers;
};
uint128_t vector_register[MD_CONTEXT_AMD64_VR_COUNT];
uint64_t vector_control;
uint128_struct vector_register[MD_CONTEXT_AMD64_VR_COUNT];
uint64_t vector_control;
/* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
uint64_t debug_control;
@ -197,7 +197,7 @@ typedef struct {
uint64_t last_branch_from_rip;
uint64_t last_exception_to_rip;
uint64_t last_exception_from_rip;
} MDRawContextAMD64; /* CONTEXT */
/* For (MDRawContextAMD64).context_flags. These values indicate the type of

Просмотреть файл

@ -77,10 +77,10 @@
* are not exactly minidumps.
*/
typedef struct {
uint64_t fpscr; /* FPU status register */
uint64_t fpscr; /* FPU status register */
/* 32 64-bit floating point registers, d0 .. d31. */
uint64_t regs[MD_FLOATINGSAVEAREA_ARM_FPR_COUNT];
uint64_t regs[MD_FLOATINGSAVEAREA_ARM_FPR_COUNT];
/* Miscellaneous control words */
uint32_t extra[MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT];
@ -92,7 +92,7 @@ typedef struct {
/* The next field determines the layout of the structure, and which parts
* of it are populated
*/
uint32_t context_flags;
uint32_t context_flags;
/* 16 32-bit integer registers, r0 .. r15
* Note the following fixed uses:
@ -116,7 +116,7 @@ typedef struct {
} MDRawContextARM;
/* Indices into iregs for registers with a dedicated or conventional
/* Indices into iregs for registers with a dedicated or conventional
* purpose.
*/
enum MDARMRegisterNumbers {

Просмотреть файл

@ -94,11 +94,11 @@ typedef struct {
typedef struct {
/* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h
* exposes them as four 32-bit quantities. */
uint128_t save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT];
uint128_t save_vscr; /* Status/control */
uint32_t save_pad5[4];
uint32_t save_vrvalid; /* Identifies which vector registers are saved */
uint32_t save_pad6[7];
uint128_struct save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT];
uint128_struct save_vscr; /* Status/control */
uint32_t save_pad5[4];
uint32_t save_vrvalid; /* Indicates which vector registers are saved */
uint32_t save_pad6[7];
} MDVectorSaveAreaPPC; /* ppc_vector_state */
@ -117,21 +117,21 @@ typedef struct {
/* context_flags is not present in ppc_thread_state, but it aids
* identification of MDRawContextPPC among other raw context types,
* and it guarantees alignment when we get to float_save. */
uint32_t context_flags;
uint32_t context_flags;
uint32_t srr0; /* Machine status save/restore: stores pc
uint32_t srr0; /* Machine status save/restore: stores pc
* (instruction) */
uint32_t srr1; /* Machine status save/restore: stores msr
uint32_t srr1; /* Machine status save/restore: stores msr
* (ps, program/machine state) */
/* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
* used for brevity. */
uint32_t gpr[MD_CONTEXT_PPC_GPR_COUNT];
uint32_t cr; /* Condition */
uint32_t xer; /* Integer (fiXed-point) exception */
uint32_t lr; /* Link */
uint32_t ctr; /* Count */
uint32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */
uint32_t vrsave; /* Vector save */
uint32_t gpr[MD_CONTEXT_PPC_GPR_COUNT];
uint32_t cr; /* Condition */
uint32_t xer; /* Integer (fiXed-point) exception */
uint32_t lr; /* Link */
uint32_t ctr; /* Count */
uint32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */
uint32_t vrsave; /* Vector save */
/* float_save and vector_save aren't present in ppc_thread_state, but
* are represented in separate structures that still define a thread's

Просмотреть файл

@ -90,20 +90,20 @@ typedef struct {
/* context_flags is not present in ppc_thread_state, but it aids
* identification of MDRawContextPPC among other raw context types,
* and it guarantees alignment when we get to float_save. */
uint64_t context_flags;
uint64_t context_flags;
uint64_t srr0; /* Machine status save/restore: stores pc
uint64_t srr0; /* Machine status save/restore: stores pc
* (instruction) */
uint64_t srr1; /* Machine status save/restore: stores msr
uint64_t srr1; /* Machine status save/restore: stores msr
* (ps, program/machine state) */
/* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
* used for brevity. */
uint64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT];
uint64_t cr; /* Condition */
uint64_t xer; /* Integer (fiXed-point) exception */
uint64_t lr; /* Link */
uint64_t ctr; /* Count */
uint64_t vrsave; /* Vector save */
uint64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT];
uint64_t cr; /* Condition */
uint64_t xer; /* Integer (fiXed-point) exception */
uint64_t lr; /* Link */
uint64_t ctr; /* Count */
uint64_t vrsave; /* Vector save */
/* float_save and vector_save aren't present in ppc_thread_state, but
* are represented in separate structures that still define a thread's

Просмотреть файл

@ -82,10 +82,10 @@
typedef struct {
/* FPU floating point regs */
uint64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT];
uint64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT];
uint64_t filler;
uint64_t fsr; /* FPU status register */
uint64_t filler;
uint64_t fsr; /* FPU status register */
} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */
#define MD_CONTEXT_SPARC_GPR_COUNT 32
@ -94,8 +94,8 @@ typedef struct {
/* The next field determines the layout of the structure, and which parts
* of it are populated
*/
uint32_t context_flags;
uint32_t flag_pad;
uint32_t context_flags;
uint32_t flag_pad;
/*
* General register access (SPARC).
* Don't confuse definitions here with definitions in <sys/regset.h>.

Просмотреть файл

@ -234,7 +234,7 @@ typedef struct {
typedef uint32_t MDRVA; /* RVA */
typedef struct {
uint32_t data_size;
uint32_t data_size;
MDRVA rva;
} MDLocationDescriptor; /* MINIDUMP_LOCATION_DESCRIPTOR */
@ -242,22 +242,22 @@ typedef struct {
typedef struct {
/* The base address of the memory range on the host that produced the
* minidump. */
uint64_t start_of_memory_range;
uint64_t start_of_memory_range;
MDLocationDescriptor memory;
} MDMemoryDescriptor; /* MINIDUMP_MEMORY_DESCRIPTOR */
typedef struct {
uint32_t signature;
uint32_t version;
uint32_t stream_count;
uint32_t signature;
uint32_t version;
uint32_t stream_count;
MDRVA stream_directory_rva; /* A |stream_count|-sized array of
* MDRawDirectory structures. */
uint32_t checksum; /* Can be 0. In fact, that's all that's
uint32_t checksum; /* Can be 0. In fact, that's all that's
* been found in minidump files. */
uint32_t time_date_stamp; /* time_t */
uint64_t flags;
uint32_t time_date_stamp; /* time_t */
uint64_t flags;
} MDRawHeader; /* MINIDUMP_HEADER */
/* For (MDRawHeader).signature and (MDRawHeader).version. Note that only the
@ -302,7 +302,7 @@ typedef enum {
typedef struct {
uint32_t stream_type;
uint32_t stream_type;
MDLocationDescriptor location;
} MDRawDirectory; /* MINIDUMP_DIRECTORY */
@ -355,18 +355,18 @@ static const size_t MDString_minsize = offsetof(MDString, buffer[0]);
typedef struct {
uint32_t thread_id;
uint32_t suspend_count;
uint32_t priority_class;
uint32_t priority;
uint64_t teb; /* Thread environment block */
uint32_t thread_id;
uint32_t suspend_count;
uint32_t priority_class;
uint32_t priority;
uint64_t teb; /* Thread environment block */
MDMemoryDescriptor stack;
MDLocationDescriptor thread_context; /* MDRawContext[CPU] */
} MDRawThread; /* MINIDUMP_THREAD */
typedef struct {
uint32_t number_of_threads;
uint32_t number_of_threads;
MDRawThread threads[1];
} MDRawThreadList; /* MINIDUMP_THREAD_LIST */
@ -375,10 +375,10 @@ static const size_t MDRawThreadList_minsize = offsetof(MDRawThreadList,
typedef struct {
uint64_t base_of_image;
uint32_t size_of_image;
uint32_t checksum; /* 0 if unknown */
uint32_t time_date_stamp; /* time_t */
uint64_t base_of_image;
uint32_t size_of_image;
uint32_t checksum; /* 0 if unknown */
uint32_t time_date_stamp; /* time_t */
MDRVA module_name_rva; /* MDString, pathname or filename */
MDVSFixedFileInfo version_info;
@ -402,8 +402,8 @@ typedef struct {
* As a workaround, reserved0 and reserved1 are instead defined here as
* four 32-bit quantities. This should be harmless, as there are
* currently no known uses for these fields. */
uint32_t reserved0[2];
uint32_t reserved1[2];
uint32_t reserved0[2];
uint32_t reserved1[2];
} MDRawModule; /* MINIDUMP_MODULE */
/* The inclusion of a 64-bit type in MINIDUMP_MODULE forces the struct to
@ -425,9 +425,9 @@ typedef struct {
typedef struct {
MDCVHeader cv_header;
uint32_t signature; /* time_t debug information created */
uint32_t age; /* revision of PDB file */
uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file */
uint32_t signature; /* time_t debug information created */
uint32_t age; /* revision of PDB file */
uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file */
} MDCVInfoPDB20;
static const size_t MDCVInfoPDB20_minsize = offsetof(MDCVInfoPDB20,
@ -436,10 +436,10 @@ static const size_t MDCVInfoPDB20_minsize = offsetof(MDCVInfoPDB20,
#define MD_CVINFOPDB20_SIGNATURE 0x3031424e /* cvHeader.signature = '01BN' */
typedef struct {
uint32_t cv_signature;
uint32_t cv_signature;
MDGUID signature; /* GUID, identifies PDB file */
uint32_t age; /* Identifies incremental changes to PDB file */
uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file,
uint32_t age; /* Identifies incremental changes to PDB file */
uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file,
* 0-terminated 8-bit character data (UTF-8?) */
} MDCVInfoPDB70;
@ -454,7 +454,7 @@ typedef struct {
uint32_t data3;
uint32_t data4;
uint32_t data5[3];
uint8_t extra[2];
uint8_t extra[2];
} MDCVInfoELF;
/* In addition to the two CodeView record formats above, used for linking
@ -479,12 +479,12 @@ typedef struct {
* obsolete with modules built by recent toolchains. */
typedef struct {
uint32_t data_type; /* IMAGE_DEBUG_TYPE_*, not defined here because
uint32_t data_type; /* IMAGE_DEBUG_TYPE_*, not defined here because
* this debug record type is mostly obsolete. */
uint32_t length; /* Length of entire MDImageDebugMisc structure */
uint8_t unicode; /* True if data is multibyte */
uint8_t reserved[3];
uint8_t data[1];
uint32_t length; /* Length of entire MDImageDebugMisc structure */
uint8_t unicode; /* True if data is multibyte */
uint8_t reserved[3];
uint8_t data[1];
} MDImageDebugMisc; /* IMAGE_DEBUG_MISC */
static const size_t MDImageDebugMisc_minsize = offsetof(MDImageDebugMisc,
@ -492,7 +492,7 @@ static const size_t MDImageDebugMisc_minsize = offsetof(MDImageDebugMisc,
typedef struct {
uint32_t number_of_modules;
uint32_t number_of_modules;
MDRawModule modules[1];
} MDRawModuleList; /* MINIDUMP_MODULE_LIST */
@ -501,7 +501,7 @@ static const size_t MDRawModuleList_minsize = offsetof(MDRawModuleList,
typedef struct {
uint32_t number_of_memory_ranges;
uint32_t number_of_memory_ranges;
MDMemoryDescriptor memory_ranges[1];
} MDRawMemoryList; /* MINIDUMP_MEMORY_LIST */
@ -512,21 +512,21 @@ static const size_t MDRawMemoryList_minsize = offsetof(MDRawMemoryList,
#define MD_EXCEPTION_MAXIMUM_PARAMETERS 15
typedef struct {
uint32_t exception_code; /* Windows: MDExceptionCodeWin,
uint32_t exception_code; /* Windows: MDExceptionCodeWin,
* Mac OS X: MDExceptionMac,
* Linux: MDExceptionCodeLinux. */
uint32_t exception_flags; /* Windows: 1 if noncontinuable,
uint32_t exception_flags; /* Windows: 1 if noncontinuable,
Mac OS X: MDExceptionCodeMac. */
uint64_t exception_record; /* Address (in the minidump-producing host's
uint64_t exception_record; /* Address (in the minidump-producing host's
* memory) of another MDException, for
* nested exceptions. */
uint64_t exception_address; /* The address that caused the exception.
uint64_t exception_address; /* The address that caused the exception.
* Mac OS X: exception subcode (which is
* typically the address). */
uint32_t number_parameters; /* Number of valid elements in
uint32_t number_parameters; /* Number of valid elements in
* exception_information. */
uint32_t __align;
uint64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS];
uint32_t __align;
uint64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS];
} MDException; /* MINIDUMP_EXCEPTION */
#include "minidump_exception_win32.h"
@ -535,10 +535,10 @@ typedef struct {
#include "minidump_exception_solaris.h"
typedef struct {
uint32_t thread_id; /* Thread in which the exception
uint32_t thread_id; /* Thread in which the exception
* occurred. Corresponds to
* (MDRawThread).thread_id. */
uint32_t __align;
uint32_t __align;
MDException exception_record;
MDLocationDescriptor thread_context; /* MDRawContext[CPU] */
} MDRawExceptionStream; /* MINIDUMP_EXCEPTION_STREAM */
@ -560,20 +560,20 @@ typedef union {
typedef struct {
/* The next 3 fields and numberOfProcessors are from the SYSTEM_INFO
* structure as returned by GetSystemInfo */
uint16_t processor_architecture;
uint16_t processor_level; /* x86: 5 = 586, 6 = 686, ... */
uint16_t processor_revision; /* x86: 0xMMSS, where MM=model,
uint16_t processor_architecture;
uint16_t processor_level; /* x86: 5 = 586, 6 = 686, ... */
uint16_t processor_revision; /* x86: 0xMMSS, where MM=model,
* SS=stepping */
uint8_t number_of_processors;
uint8_t product_type; /* Windows: VER_NT_* from WinNT.h */
uint8_t number_of_processors;
uint8_t product_type; /* Windows: VER_NT_* from WinNT.h */
/* The next 5 fields are from the OSVERSIONINFO structure as returned
* by GetVersionEx */
uint32_t major_version;
uint32_t minor_version;
uint32_t build_number;
uint32_t platform_id;
uint32_t major_version;
uint32_t minor_version;
uint32_t build_number;
uint32_t platform_id;
MDRVA csd_version_rva; /* MDString further identifying the
* host OS.
* Windows: name of the installed OS
@ -582,8 +582,8 @@ typedef struct {
* (sw_vers -buildVersion).
* Linux: uname -srvmo */
uint16_t suite_mask; /* Windows: VER_SUITE_* from WinNT.h */
uint16_t reserved2;
uint16_t suite_mask; /* Windows: VER_SUITE_* from WinNT.h */
uint16_t reserved2;
MDCPUInformation cpu;
} MDRawSystemInfo; /* MINIDUMP_SYSTEM_INFO */
@ -666,7 +666,7 @@ typedef enum {
/* MINIDUMP_MISC1_PROCESSOR_POWER_INFO */
} MDMiscInfoFlags1;
/*
/*
* Around DbgHelp version 6.0, the style of new LIST structures changed
* from including an array of length 1 at the end of the struct to
* represent the variable-length data to including explicit
@ -683,18 +683,18 @@ typedef struct {
} MDRawMemoryInfoList; /* MINIDUMP_MEMORY_INFO_LIST */
typedef struct {
uint64_t base_address; /* Base address of a region of pages */
uint64_t allocation_base; /* Base address of a range of pages
uint64_t base_address; /* Base address of a region of pages */
uint64_t allocation_base; /* Base address of a range of pages
* within this region. */
uint32_t allocation_protection; /* Memory protection when this region
uint32_t allocation_protection; /* Memory protection when this region
* was originally allocated:
* MDMemoryProtection */
uint32_t __alignment1;
uint64_t region_size;
uint32_t state; /* MDMemoryState */
uint32_t protection; /* MDMemoryProtection */
uint32_t type; /* MDMemoryType */
uint32_t __alignment2;
uint32_t __alignment1;
uint64_t region_size;
uint32_t state; /* MDMemoryState */
uint32_t protection; /* MDMemoryProtection */
uint32_t type; /* MDMemoryType */
uint32_t __alignment2;
} MDRawMemoryInfo; /* MINIDUMP_MEMORY_INFO */
/* For (MDRawMemoryInfo).state */
@ -806,9 +806,9 @@ typedef struct {
} MDRawLinkMap;
typedef struct {
uint32_t version;
uint32_t version;
MDRVA map;
uint32_t dso_count;
uint32_t dso_count;
void* brk;
void* ldbase;
void* dynamic;

Просмотреть файл

@ -63,10 +63,10 @@ class MemoryRegion {
// program. Returns true on success. Fails and returns false if address
// is out of the region's bounds (after considering the width of value),
// or for other types of errors.
virtual bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const =0;
virtual bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const =0;
virtual bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const =0;
virtual bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const =0;
virtual bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const = 0;
virtual bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const = 0;
virtual bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const = 0;
virtual bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const = 0;
};

Просмотреть файл

@ -106,6 +106,9 @@ class ProcessState {
}
const SystemInfo* system_info() const { return &system_info_; }
const CodeModules* modules() const { return modules_; }
const vector<const CodeModule*>* modules_without_symbols() const {
return &modules_without_symbols_;
}
ExploitabilityRating exploitability() const { return exploitability_; }
private:
@ -158,6 +161,9 @@ class ProcessState {
// ProcessState.
const CodeModules *modules_;
// The modules that didn't have symbols when the report was processed.
vector<const CodeModule*> modules_without_symbols_;
// The exploitability rating as determined by the exploitability
// engine. When the exploitability engine is not enabled this
// defaults to EXPLOITABILITY_NONE.

Просмотреть файл

@ -43,6 +43,7 @@
#include <set>
#include <string>
#include <vector>
#include "common/using_std_string.h"
#include "google_breakpad/common/breakpad_types.h"
@ -57,6 +58,7 @@ class MinidumpContext;
class StackFrameSymbolizer;
using std::set;
using std::vector;
class Stackwalker {
public:
@ -66,7 +68,15 @@ class Stackwalker {
// GetCallerFrame. The frames are further processed to fill all available
// data. Returns true if the stackwalk completed, or false if it was
// interrupted by SymbolSupplier::GetSymbolFile().
bool Walk(CallStack* stack);
// Upon return, modules_without_symbols will be populated with pointers to
// the code modules (CodeModule*) that DON'T have symbols.
// modules_without_symbols DOES NOT take ownership of the code modules.
// The lifetime of these code modules is the same as the lifetime of the
// CodeModules passed to the StackWalker constructor (which currently
// happens to be the lifetime of the Breakpad's ProcessingState object).
// There is a check for duplicate modules so no duplicates are expected.
bool Walk(CallStack* stack,
vector<const CodeModule*>* modules_without_symbols);
// Returns a new concrete subclass suitable for the CPU that a stack was
// generated on, according to the CPU type indicated by the context

Просмотреть файл

@ -304,8 +304,8 @@ BasicSourceLineResolver::Module::ParseFunction(char *function_line) {
return NULL;
}
uint64_t address = strtoull(tokens[0], NULL, 16);
uint64_t size = strtoull(tokens[1], NULL, 16);
uint64_t address = strtoull(tokens[0], NULL, 16);
uint64_t size = strtoull(tokens[1], NULL, 16);
int stack_param_size = strtoull(tokens[2], NULL, 16);
char *name = tokens[3];
@ -320,8 +320,8 @@ BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine(
return NULL;
}
uint64_t address = strtoull(tokens[0], NULL, 16);
uint64_t size = strtoull(tokens[1], NULL, 16);
uint64_t address = strtoull(tokens[0], NULL, 16);
uint64_t size = strtoull(tokens[1], NULL, 16);
int line_number = atoi(tokens[2]);
int source_file = atoi(tokens[3]);
if (line_number <= 0) {
@ -342,7 +342,7 @@ bool BasicSourceLineResolver::Module::ParsePublicSymbol(char *public_line) {
return false;
}
uint64_t address = strtoull(tokens[0], NULL, 16);
uint64_t address = strtoull(tokens[0], NULL, 16);
int stack_param_size = strtoull(tokens[1], NULL, 16);
char *name = tokens[2];

Просмотреть файл

@ -1,450 +0,0 @@
// Copyright (c) 2010 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// basic_source_line_resolver.cc: BasicSourceLineResolver implementation.
//
// See basic_source_line_resolver.h and basic_source_line_resolver_types.h
// for documentation.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <map>
#include <utility>
#include <vector>
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "processor/basic_source_line_resolver_types.h"
#include "processor/module_factory.h"
#include "processor/tokenize.h"
using std::map;
using std::vector;
using std::make_pair;
namespace google_breakpad {
static const char *kWhitespace = " \r\n";
BasicSourceLineResolver::BasicSourceLineResolver() :
SourceLineResolverBase(new BasicModuleFactory) { }
bool BasicSourceLineResolver::Module::LoadMapFromMemory(char *memory_buffer) {
linked_ptr<Function> cur_func;
int line_number = 0;
char *save_ptr;
size_t map_buffer_length = strlen(memory_buffer);
// If the length is 0, we can still pretend we have a symbol file. This is
// for scenarios that want to test symbol lookup, but don't necessarily care
// if certain modules do not have any information, like system libraries.
if (map_buffer_length == 0) {
return true;
}
if (memory_buffer[map_buffer_length - 1] == '\n') {
memory_buffer[map_buffer_length - 1] = '\0';
}
char *buffer;
buffer = strtok_r(memory_buffer, "\r\n", &save_ptr);
while (buffer != NULL) {
++line_number;
if (strncmp(buffer, "FILE ", 5) == 0) {
if (!ParseFile(buffer)) {
BPLOG(ERROR) << "ParseFile on buffer failed at " <<
":" << line_number;
return false;
}
} else if (strncmp(buffer, "STACK ", 6) == 0) {
if (!ParseStackInfo(buffer)) {
BPLOG(ERROR) << "ParseStackInfo failed at " <<
":" << line_number;
return false;
}
} else if (strncmp(buffer, "FUNC ", 5) == 0) {
cur_func.reset(ParseFunction(buffer));
if (!cur_func.get()) {
BPLOG(ERROR) << "ParseFunction failed at " <<
":" << line_number;
return false;
}
// StoreRange will fail if the function has an invalid address or size.
// We'll silently ignore this, the function and any corresponding lines
// will be destroyed when cur_func is released.
functions_.StoreRange(cur_func->address, cur_func->size, cur_func);
} else if (strncmp(buffer, "PUBLIC ", 7) == 0) {
// Clear cur_func: public symbols don't contain line number information.
cur_func.reset();
if (!ParsePublicSymbol(buffer)) {
BPLOG(ERROR) << "ParsePublicSymbol failed at " <<
":" << line_number;
return false;
}
} else if (strncmp(buffer, "MODULE ", 7) == 0) {
// Ignore these. They're not of any use to BasicSourceLineResolver,
// which is fed modules by a SymbolSupplier. These lines are present to
// aid other tools in properly placing symbol files so that they can
// be accessed by a SymbolSupplier.
//
// MODULE <guid> <age> <filename>
} else if (strncmp(buffer, "INFO ", 5) == 0) {
// Ignore these as well, they're similarly just for housekeeping.
//
// INFO CODE_ID <code id> <filename>
} else {
if (!cur_func.get()) {
BPLOG(ERROR) << "Found source line data without a function at " <<
":" << line_number;
return false;
}
Line *line = ParseLine(buffer);
if (!line) {
BPLOG(ERROR) << "ParseLine failed at " << line_number << " for " <<
buffer;
return false;
}
cur_func->lines.StoreRange(line->address, line->size,
linked_ptr<Line>(line));
}
buffer = strtok_r(NULL, "\r\n", &save_ptr);
}
return true;
}
void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
// First, look for a FUNC record that covers address. Use
// RetrieveNearestRange instead of RetrieveRange so that, if there
// is no such function, we can use the next function to bound the
// extent of the PUBLIC symbol we find, below. This does mean we
// need to check that address indeed falls within the function we
// find; do the range comparison in an overflow-friendly way.
linked_ptr<Function> func;
linked_ptr<PublicSymbol> public_symbol;
MemAddr function_base;
MemAddr function_size;
MemAddr public_address;
if (functions_.RetrieveNearestRange(address, &func,
&function_base, &function_size) &&
address >= function_base && address - function_base < function_size) {
frame->function_name = func->name;
frame->function_base = frame->module->base_address() + function_base;
linked_ptr<Line> line;
MemAddr line_base;
if (func->lines.RetrieveRange(address, &line, &line_base, NULL)) {
FileMap::const_iterator it = files_.find(line->source_file_id);
if (it != files_.end()) {
frame->source_file_name = files_.find(line->source_file_id)->second;
}
frame->source_line = line->line;
frame->source_line_base = frame->module->base_address() + line_base;
}
} else if (public_symbols_.Retrieve(address,
&public_symbol, &public_address) &&
(!func.get() || public_address > function_base)) {
frame->function_name = public_symbol->name;
frame->function_base = frame->module->base_address() + public_address;
}
}
WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
const StackFrame *frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
scoped_ptr<WindowsFrameInfo> result(new WindowsFrameInfo());
// We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and
// WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order.
// WindowsFrameInfo::STACK_INFO_FRAME_DATA is the newer type that
// includes its own program string.
// WindowsFrameInfo::STACK_INFO_FPO is the older type
// corresponding to the FPO_DATA struct. See stackwalker_x86.cc.
linked_ptr<WindowsFrameInfo> frame_info;
if ((windows_frame_info_[WindowsFrameInfo::STACK_INFO_FRAME_DATA]
.RetrieveRange(address, &frame_info))
|| (windows_frame_info_[WindowsFrameInfo::STACK_INFO_FPO]
.RetrieveRange(address, &frame_info))) {
result->CopyFrom(*frame_info.get());
return result.release();
}
// Even without a relevant STACK line, many functions contain
// information about how much space their parameters consume on the
// stack. Use RetrieveNearestRange instead of RetrieveRange, so that
// we can use the function to bound the extent of the PUBLIC symbol,
// below. However, this does mean we need to check that ADDRESS
// falls within the retrieved function's range; do the range
// comparison in an overflow-friendly way.
linked_ptr<Function> function;
MemAddr function_base, function_size;
if (functions_.RetrieveNearestRange(address, &function,
&function_base, &function_size) &&
address >= function_base && address - function_base < function_size) {
result->parameter_size = function->parameter_size;
result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
return result.release();
}
// PUBLIC symbols might have a parameter size. Use the function we
// found above to limit the range the public symbol covers.
linked_ptr<PublicSymbol> public_symbol;
MemAddr public_address;
if (public_symbols_.Retrieve(address, &public_symbol, &public_address) &&
(!function.get() || public_address > function_base)) {
result->parameter_size = public_symbol->parameter_size;
}
return NULL;
}
CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
const StackFrame *frame) const {
MemAddr address = frame->instruction - frame->module->base_address();
MemAddr initial_base, initial_size;
string initial_rules;
// Find the initial rule whose range covers this address. That
// provides an initial set of register recovery rules. Then, walk
// forward from the initial rule's starting address to frame's
// instruction address, applying delta rules.
if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules,
&initial_base, &initial_size)) {
return NULL;
}
// Create a frame info structure, and populate it with the rules from
// the STACK CFI INIT record.
scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo());
if (!ParseCFIRuleSet(initial_rules, rules.get()))
return NULL;
// Find the first delta rule that falls within the initial rule's range.
map<MemAddr, string>::const_iterator delta =
cfi_delta_rules_.lower_bound(initial_base);
// Apply delta rules up to and including the frame's address.
while (delta != cfi_delta_rules_.end() && delta->first <= address) {
ParseCFIRuleSet(delta->second, rules.get());
delta++;
}
return rules.release();
}
bool BasicSourceLineResolver::Module::ParseFile(char *file_line) {
// FILE <id> <filename>
file_line += 5; // skip prefix
vector<char*> tokens;
if (!Tokenize(file_line, kWhitespace, 2, &tokens)) {
return false;
}
int index = atoi(tokens[0]);
if (index < 0) {
return false;
}
char *filename = tokens[1];
if (!filename) {
return false;
}
files_.insert(make_pair(index, string(filename)));
return true;
}
BasicSourceLineResolver::Function*
BasicSourceLineResolver::Module::ParseFunction(char *function_line) {
// FUNC <address> <size> <stack_param_size> <name>
function_line += 5; // skip prefix
vector<char*> tokens;
if (!Tokenize(function_line, kWhitespace, 4, &tokens)) {
return NULL;
}
u_int64_t address = strtoull(tokens[0], NULL, 16);
u_int64_t size = strtoull(tokens[1], NULL, 16);
int stack_param_size = strtoull(tokens[2], NULL, 16);
char *name = tokens[3];
return new Function(name, address, size, stack_param_size);
}
BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine(
char *line_line) {
// <address> <line number> <source file id>
vector<char*> tokens;
if (!Tokenize(line_line, kWhitespace, 4, &tokens)) {
return NULL;
}
u_int64_t address = strtoull(tokens[0], NULL, 16);
u_int64_t size = strtoull(tokens[1], NULL, 16);
int line_number = atoi(tokens[2]);
int source_file = atoi(tokens[3]);
if (line_number <= 0) {
return NULL;
}
return new Line(address, size, source_file, line_number);
}
bool BasicSourceLineResolver::Module::ParsePublicSymbol(char *public_line) {
// PUBLIC <address> <stack_param_size> <name>
// Skip "PUBLIC " prefix.
public_line += 7;
vector<char*> tokens;
if (!Tokenize(public_line, kWhitespace, 3, &tokens)) {
return false;
}
u_int64_t address = strtoull(tokens[0], NULL, 16);
int stack_param_size = strtoull(tokens[1], NULL, 16);
char *name = tokens[2];
// A few public symbols show up with an address of 0. This has been seen
// in the dumped output of ntdll.pdb for symbols such as _CIlog, _CIpow,
// RtlDescribeChunkLZNT1, and RtlReserveChunkLZNT1. They would conflict
// with one another if they were allowed into the public_symbols_ map,
// but since the address is obviously invalid, gracefully accept them
// as input without putting them into the map.
if (address == 0) {
return true;
}
linked_ptr<PublicSymbol> symbol(new PublicSymbol(name, address,
stack_param_size));
return public_symbols_.Store(address, symbol);
}
bool BasicSourceLineResolver::Module::ParseStackInfo(char *stack_info_line) {
// Skip "STACK " prefix.
stack_info_line += 6;
// Find the token indicating what sort of stack frame walking
// information this is.
while (*stack_info_line == ' ')
stack_info_line++;
const char *platform = stack_info_line;
while (!strchr(kWhitespace, *stack_info_line))
stack_info_line++;
*stack_info_line++ = '\0';
// MSVC stack frame info.
if (strcmp(platform, "WIN") == 0) {
int type = 0;
u_int64_t rva, code_size;
linked_ptr<WindowsFrameInfo>
stack_frame_info(WindowsFrameInfo::ParseFromString(stack_info_line,
type,
rva,
code_size));
if (stack_frame_info == NULL)
return false;
// TODO(mmentovai): I wanted to use StoreRange's return value as this
// method's return value, but MSVC infrequently outputs stack info that
// violates the containment rules. This happens with a section of code
// in strncpy_s in test_app.cc (testdata/minidump2). There, problem looks
// like this:
// STACK WIN 4 4242 1a a 0 ... (STACK WIN 4 base size prolog 0 ...)
// STACK WIN 4 4243 2e 9 0 ...
// ContainedRangeMap treats these two blocks as conflicting. In reality,
// when the prolog lengths are taken into account, the actual code of
// these blocks doesn't conflict. However, we can't take the prolog lengths
// into account directly here because we'd wind up with a different set
// of range conflicts when MSVC outputs stack info like this:
// STACK WIN 4 1040 73 33 0 ...
// STACK WIN 4 105a 59 19 0 ...
// because in both of these entries, the beginning of the code after the
// prolog is at 0x1073, and the last byte of contained code is at 0x10b2.
// Perhaps we could get away with storing ranges by rva + prolog_size
// if ContainedRangeMap were modified to allow replacement of
// already-stored values.
windows_frame_info_[type].StoreRange(rva, code_size, stack_frame_info);
return true;
} else if (strcmp(platform, "CFI") == 0) {
// DWARF CFI stack frame info
return ParseCFIFrameInfo(stack_info_line);
} else {
// Something unrecognized.
return false;
}
}
bool BasicSourceLineResolver::Module::ParseCFIFrameInfo(
char *stack_info_line) {
char *cursor;
// Is this an INIT record or a delta record?
char *init_or_address = strtok_r(stack_info_line, " \r\n", &cursor);
if (!init_or_address)
return false;
if (strcmp(init_or_address, "INIT") == 0) {
// This record has the form "STACK INIT <address> <size> <rules...>".
char *address_field = strtok_r(NULL, " \r\n", &cursor);
if (!address_field) return false;
char *size_field = strtok_r(NULL, " \r\n", &cursor);
if (!size_field) return false;
char *initial_rules = strtok_r(NULL, "\r\n", &cursor);
if (!initial_rules) return false;
MemAddr address = strtoul(address_field, NULL, 16);
MemAddr size = strtoul(size_field, NULL, 16);
cfi_initial_rules_.StoreRange(address, size, initial_rules);
return true;
}
// This record has the form "STACK <address> <rules...>".
char *address_field = init_or_address;
char *delta_rules = strtok_r(NULL, "\r\n", &cursor);
if (!delta_rules) return false;
MemAddr address = strtoul(address_field, NULL, 16);
cfi_delta_rules_[address] = delta_rules;
return true;
}
} // namespace google_breakpad

Просмотреть файл

@ -125,7 +125,7 @@ static inline void Swap(uint64_t* value) {
// Given a pointer to a 128-bit int in the minidump data, set the "low"
// and "high" fields appropriately.
static void Normalize128(uint128_t* value, bool is_big_endian) {
static void Normalize128(uint128_struct* value, bool is_big_endian) {
// The struct format is [high, low], so if the format is big-endian,
// the most significant bytes will already be in the high field.
if (!is_big_endian) {
@ -137,7 +137,7 @@ static void Normalize128(uint128_t* value, bool is_big_endian) {
// This just swaps each int64 half of the 128-bit value.
// The value should also be normalized by calling Normalize128().
static void Swap(uint128_t* value) {
static void Swap(uint128_struct* value) {
Swap(&value->low);
Swap(&value->high);
}

Просмотреть файл

@ -227,9 +227,10 @@ ProcessResult MinidumpProcessor::Process(
scoped_ptr<CallStack> stack(new CallStack());
if (stackwalker.get()) {
if (!stackwalker->Walk(stack.get())) {
BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " <<
thread_string;
if (!stackwalker->Walk(stack.get(),
&process_state->modules_without_symbols_)) {
BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at "
<< thread_string;
interrupted = true;
}
} else {

Просмотреть файл

@ -333,7 +333,51 @@ static void PrintStackMachineReadable(int thread_num, const CallStack *stack) {
}
}
static void PrintModules(const CodeModules *modules) {
// ContainsModule checks whether a given |module| is in the vector
// |modules_without_symbols|.
static bool ContainsModule(
const vector<const CodeModule*> *modules,
const CodeModule *module) {
assert(modules);
assert(module);
vector<const CodeModule*>::const_iterator iter;
for (iter = modules->begin(); iter != modules->end(); ++iter) {
if (module->debug_file().compare((*iter)->debug_file()) == 0 &&
module->debug_identifier().compare((*iter)->debug_identifier()) == 0) {
return true;
}
}
return false;
}
// PrintModule prints a single |module| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModule(
const CodeModule *module,
const vector<const CodeModule*> *modules_without_symbols,
uint64_t main_address) {
string missing_symbols;
if (ContainsModule(modules_without_symbols, module)) {
missing_symbols = " (WARNING: No symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
}
uint64_t base_address = module->base_address();
printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n",
base_address, base_address + module->size() - 1,
PathnameStripper::File(module->code_file()).c_str(),
module->version().empty() ? "???" : module->version().c_str(),
main_address != 0 && base_address == main_address ? " (main)" : "",
missing_symbols.c_str());
}
// PrintModules prints the list of all loaded |modules| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModules(
const CodeModules *modules,
const vector<const CodeModule*> *modules_without_symbols) {
if (!modules)
return;
@ -351,13 +395,7 @@ static void PrintModules(const CodeModules *modules) {
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
uint64_t base_address = module->base_address();
printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s\n",
base_address, base_address + module->size() - 1,
PathnameStripper::File(module->code_file()).c_str(),
module->version().empty() ? "???" : module->version().c_str(),
main_module != NULL && base_address == main_address ?
" (main)" : "");
PrintModule(module, modules_without_symbols, main_address);
}
}
@ -449,7 +487,8 @@ static void PrintProcessState(const ProcessState& process_state) {
}
}
PrintModules(process_state.modules());
PrintModules(process_state.modules(),
process_state.modules_without_symbols());
}
static void PrintProcessStateMachineReadable(const ProcessState& process_state)

Просмотреть файл

@ -57,6 +57,9 @@ void ProcessState::Clear() {
}
threads_.clear();
system_info_.Clear();
// modules_without_symbols_ DOES NOT owns the underlying CodeModule pointers.
// Just clear the vector.
modules_without_symbols_.clear();
delete modules_;
modules_ = NULL;
}

Просмотреть файл

@ -70,11 +70,16 @@ Stackwalker::Stackwalker(const SystemInfo* system_info,
}
bool Stackwalker::Walk(CallStack* stack) {
bool Stackwalker::Walk(CallStack* stack,
vector<const CodeModule*>* modules_without_symbols) {
BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|";
assert(stack);
stack->Clear();
BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires "
<< "|modules_without_symbols|";
assert(modules_without_symbols);
// Begin with the context frame, and keep getting callers until there are
// no more.
@ -95,6 +100,27 @@ bool Stackwalker::Walk(CallStack* stack) {
return false;
}
// Keep track of modules that have no symbols.
if (symbolizer_result == StackFrameSymbolizer::kError &&
frame->module != NULL) {
bool found = false;
vector<const CodeModule*>::iterator iter;
for (iter = modules_without_symbols->begin();
iter != modules_without_symbols->end();
++iter) {
if (*iter == frame->module) {
found = true;
break;
}
}
if (!found) {
BPLOG(INFO) << "Couldn't load symbols for: "
<< frame->module->debug_file() << "|"
<< frame->module->debug_identifier();
modules_without_symbols->push_back(frame->module);
}
}
// Add the frame to the call stack. Relinquish the ownership claim
// over the frame, because the stack now owns it.
stack->frames_.push_back(frame.release());

Просмотреть файл

@ -41,6 +41,7 @@
#include "google_breakpad/common/minidump_format.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/source_line_resolver_interface.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/stackwalker_unittest_utils.h"
@ -48,6 +49,7 @@
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::CodeModule;
using google_breakpad::StackFrameSymbolizer;
using google_breakpad::StackFrame;
using google_breakpad::StackFrameAMD64;
@ -143,7 +145,10 @@ TEST_F(SanityCheck, NoResolver) {
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
// This should succeed even without a resolver or supplier.
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_GE(1U, frames->size());
StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
@ -163,7 +168,10 @@ TEST_F(GetContextFrame, Simple) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_GE(1U, frames->size());
StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
@ -181,7 +189,10 @@ TEST_F(GetContextFrame, NoStackMemory) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_GE(1U, frames->size());
StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
@ -236,7 +247,11 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(2U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -304,7 +319,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -369,7 +386,9 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -445,7 +464,9 @@ struct CFIFixture: public StackwalkerAMD64Fixture {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());

Просмотреть файл

@ -41,6 +41,7 @@
#include "google_breakpad/common/minidump_format.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/source_line_resolver_interface.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/stackwalker_unittest_utils.h"
@ -49,6 +50,7 @@
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::CodeModule;
using google_breakpad::StackFrameSymbolizer;
using google_breakpad::StackFrame;
using google_breakpad::StackFrameARM;
@ -139,7 +141,9 @@ TEST_F(SanityCheck, NoResolver) {
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&frame_symbolizer);
// This should succeed even without a resolver or supplier.
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
@ -157,7 +161,9 @@ TEST_F(GetContextFrame, Simple) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
@ -172,7 +178,9 @@ TEST_F(GetContextFrame, NoStackMemory) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, NULL, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
@ -220,7 +228,11 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(2U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -284,7 +296,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -345,7 +359,11 @@ TEST_F(GetCallerFrame, ScanFirstFrame) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(2U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -453,7 +471,9 @@ struct CFIFixture: public StackwalkerARMFixture {
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region,
&modules, &frame_symbolizer);
walker.SetContextFrameValidity(context_frame_validity);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -645,7 +665,9 @@ TEST_F(CFI, RejectBackwards) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
}
@ -657,7 +679,9 @@ TEST_F(CFI, RejectBadExpressions) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
}
@ -715,7 +739,11 @@ TEST_F(GetFramesByFramePointer, OnlyFramePointer) {
StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP,
&stack_region, &modules, &frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(2U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
ASSERT_EQ("module2", modules_without_symbols[1]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -805,7 +833,10 @@ TEST_F(GetFramesByFramePointer, FramePointerAndCFI) {
StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP,
&stack_region, &modules, &frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());

Просмотреть файл

@ -69,12 +69,14 @@
#include "google_breakpad/common/minidump_format.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/memory_region.h"
#include "google_breakpad/processor/stack_frame.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::CodeModule;
using google_breakpad::MemoryRegion;
using google_breakpad::scoped_ptr;
using google_breakpad::StackFrame;
@ -337,7 +339,8 @@ static unsigned int CountCallerFrames() {
#endif // __i386__ || __ppc__ || __sparc__
CallStack stack;
stackwalker.Walk(&stack);
vector<const CodeModule*> modules_without_symbols;
stackwalker.Walk(&stack, &modules_without_symbols);
#ifdef PRINT_STACKS
printf("\n");

Просмотреть файл

@ -40,6 +40,7 @@
#include "google_breakpad/common/minidump_format.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/source_line_resolver_interface.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/stackwalker_unittest_utils.h"
@ -48,6 +49,7 @@
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::CodeModule;
using google_breakpad::StackFrameSymbolizer;
using google_breakpad::StackFrame;
using google_breakpad::StackFrameX86;
@ -153,7 +155,10 @@ TEST_F(SanityCheck, NoResolver) {
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
// This should succeed, even without a resolver or supplier.
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
// Check that the values from the original raw context made it
@ -173,7 +178,10 @@ TEST_F(GetContextFrame, Simple) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
// Check that the values from the original raw context made it
@ -190,7 +198,10 @@ TEST_F(GetContextFrame, NoStackMemory) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
// Check that the values from the original raw context made it
@ -223,7 +234,10 @@ TEST_F(GetCallerFrame, Traditional) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -279,7 +293,10 @@ TEST_F(GetCallerFrame, TraditionalScan) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -341,7 +358,10 @@ TEST_F(GetCallerFrame, TraditionalScanLongWay) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module1", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -413,7 +433,9 @@ TEST_F(GetCallerFrame, WindowsFrameData) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -485,7 +507,10 @@ TEST_F(GetCallerFrame, WindowsFrameDataAligned) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(1U, modules_without_symbols.size());
ASSERT_EQ("module2", modules_without_symbols[0]->debug_file());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -568,7 +593,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -663,7 +690,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -747,7 +776,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -815,7 +846,9 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -892,7 +925,9 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -1030,7 +1065,9 @@ TEST_F(GetCallerFrame, WindowsFPOSystemCall) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(4U, frames->size());
@ -1238,7 +1275,9 @@ TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region,
&local_modules, &frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -1365,7 +1404,9 @@ struct CFIFixture: public StackwalkerX86Fixture {
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
vector<const CodeModule*> modules_without_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols));
ASSERT_EQ(0U, modules_without_symbols.size());
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());

Просмотреть файл

@ -116,7 +116,7 @@ struct WindowsFrameInfo {
int &type,
uint64_t &rva,
uint64_t &code_size) {
// The format of a STACK WIN record is documented at:
// The format of a STACK WIN record is documented at:
//
// http://code.google.com/p/google-breakpad/wiki/SymbolFiles
@ -132,12 +132,12 @@ struct WindowsFrameInfo {
rva = strtoull(tokens[1], NULL, 16);
code_size = strtoull(tokens[2], NULL, 16);
uint32_t prolog_size = strtoul(tokens[3], NULL, 16);
uint32_t epilog_size = strtoul(tokens[4], NULL, 16);
uint32_t parameter_size = strtoul(tokens[5], NULL, 16);
uint32_t saved_register_size = strtoul(tokens[6], NULL, 16);
uint32_t local_size = strtoul(tokens[7], NULL, 16);
uint32_t max_stack_size = strtoul(tokens[8], NULL, 16);
uint32_t prolog_size = strtoul(tokens[3], NULL, 16);
uint32_t epilog_size = strtoul(tokens[4], NULL, 16);
uint32_t parameter_size = strtoul(tokens[5], NULL, 16);
uint32_t saved_register_size = strtoul(tokens[6], NULL, 16);
uint32_t local_size = strtoul(tokens[7], NULL, 16);
uint32_t max_stack_size = strtoul(tokens[8], NULL, 16);
int has_program_string = strtoul(tokens[9], NULL, 16);
const char *program_string = "";