mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 20:49:27 +00:00
bug 778364 - Update Breakpad to r1064. r=upstream
This commit is contained in:
parent
42c894c446
commit
d26b78e2ae
11
toolkit/crashreporter/google-breakpad/SVN-INFO
Normal file
11
toolkit/crashreporter/google-breakpad/SVN-INFO
Normal file
@ -0,0 +1,11 @@
|
||||
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: 1064
|
||||
Node Kind: directory
|
||||
Schedule: normal
|
||||
Last Changed Author: jimblandy
|
||||
Last Changed Rev: 1064
|
||||
Last Changed Date: 2012-10-05 18:07:48 -0400 (Fri, 05 Oct 2012)
|
||||
|
@ -1 +0,0 @@
|
||||
/usr/share/automake-1.11/compile
|
1
toolkit/crashreporter/google-breakpad/autotools/compile
Symbolic link
1
toolkit/crashreporter/google-breakpad/autotools/compile
Symbolic link
@ -0,0 +1 @@
|
||||
/usr/share/automake-1.11/compile
|
@ -37,7 +37,7 @@ class CrashGenerationServer;
|
||||
class ClientInfo {
|
||||
public:
|
||||
ClientInfo(pid_t pid, CrashGenerationServer* crash_server)
|
||||
: crash_server_(crash_server_),
|
||||
: crash_server_(crash_server),
|
||||
pid_(pid) {}
|
||||
|
||||
CrashGenerationServer* crash_server() const { return crash_server_; }
|
||||
|
@ -60,8 +60,8 @@ const int kGUIDStringSize = 37;
|
||||
|
||||
void sigchld_handler(int signo) { }
|
||||
|
||||
int CreateTMPFile(const std::string& dir, std::string* path) {
|
||||
std::string file = dir + "/exception-handler-unittest.XXXXXX";
|
||||
int CreateTMPFile(const string& dir, string* path) {
|
||||
string file = dir + "/exception-handler-unittest.XXXXXX";
|
||||
const char* c_file = file.c_str();
|
||||
// Copy that string, mkstemp needs a C string it can modify.
|
||||
char* c_path = strdup(c_file);
|
||||
@ -98,7 +98,7 @@ void WaitForProcessToTerminate(pid_t process_id, int expected_status) {
|
||||
}
|
||||
|
||||
// Reads the minidump path sent over the pipe |fd| and sets it in |path|.
|
||||
void ReadMinidumpPathFromPipe(int fd, std::string* path) {
|
||||
void ReadMinidumpPathFromPipe(int fd, string* path) {
|
||||
struct pollfd pfd;
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.fd = fd;
|
||||
@ -133,7 +133,7 @@ TEST(ExceptionHandlerTest, SimpleWithPath) {
|
||||
|
||||
TEST(ExceptionHandlerTest, SimpleWithFD) {
|
||||
AutoTempDir temp_dir;
|
||||
std::string path;
|
||||
string path;
|
||||
const int fd = CreateTMPFile(temp_dir.path(), &path);
|
||||
ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, true, -1);
|
||||
close(fd);
|
||||
@ -159,7 +159,7 @@ void ChildCrash(bool use_fd) {
|
||||
AutoTempDir temp_dir;
|
||||
int fds[2] = {0};
|
||||
int minidump_fd = -1;
|
||||
std::string minidump_path;
|
||||
string minidump_path;
|
||||
if (use_fd) {
|
||||
minidump_fd = CreateTMPFile(temp_dir.path(), &minidump_path);
|
||||
} else {
|
||||
@ -169,7 +169,7 @@ void ChildCrash(bool use_fd) {
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
{
|
||||
scoped_ptr<ExceptionHandler> handler;
|
||||
google_breakpad::scoped_ptr<ExceptionHandler> handler;
|
||||
if (use_fd) {
|
||||
handler.reset(new ExceptionHandler(MinidumpDescriptor(minidump_fd),
|
||||
NULL, NULL, NULL, true, -1));
|
||||
@ -222,6 +222,7 @@ static bool DoneCallbackRaiseSIGKILL(const MinidumpDescriptor& descriptor,
|
||||
void* context,
|
||||
bool succeeded) {
|
||||
raise(SIGKILL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FilterCallbackReturnFalse(void* context) {
|
||||
@ -916,7 +917,7 @@ TEST(ExceptionHandlerTest, WriteMinidumpExceptionStream) {
|
||||
|
||||
TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithFD) {
|
||||
AutoTempDir temp_dir;
|
||||
std::string path;
|
||||
string path;
|
||||
const int fd = CreateTMPFile(temp_dir.path(), &path);
|
||||
ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, false, -1);
|
||||
ASSERT_TRUE(handler.WriteMinidump());
|
||||
@ -941,7 +942,7 @@ TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) {
|
||||
struct stat st;
|
||||
ASSERT_EQ(0, stat(minidump_1.path(), &st));
|
||||
ASSERT_GT(st.st_size, 0U);
|
||||
std::string minidump_1_path(minidump_1.path());
|
||||
string minidump_1_path(minidump_1.path());
|
||||
// Check it is a valid minidump.
|
||||
Minidump minidump1(minidump_1_path);
|
||||
ASSERT_TRUE(minidump1.Read());
|
||||
@ -952,7 +953,7 @@ TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) {
|
||||
const MinidumpDescriptor& minidump_2 = handler.minidump_descriptor();
|
||||
ASSERT_EQ(0, stat(minidump_2.path(), &st));
|
||||
ASSERT_GT(st.st_size, 0U);
|
||||
std::string minidump_2_path(minidump_2.path());
|
||||
string minidump_2_path(minidump_2.path());
|
||||
// Check it is a valid minidump.
|
||||
Minidump minidump2(minidump_2_path);
|
||||
ASSERT_TRUE(minidump2.Read());
|
||||
|
@ -62,9 +62,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "client/minidump_file_writer.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
#include "client/linux/minidump_writer/line_reader.h"
|
||||
#include "client/linux/minidump_writer/linux_dumper.h"
|
||||
@ -1008,7 +1005,8 @@ class MinidumpWriter {
|
||||
for (int i = 0;;) {
|
||||
ElfW(Dyn) dyn;
|
||||
dynamic_length += sizeof(dyn);
|
||||
dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic+i++, sizeof(dyn));
|
||||
dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic+i++,
|
||||
sizeof(dyn));
|
||||
if (dyn.d_tag == DT_DEBUG) {
|
||||
r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
|
||||
continue;
|
||||
@ -1083,7 +1081,7 @@ class MinidumpWriter {
|
||||
debug.get()->ldbase = (void*)debug_entry.r_ldbase;
|
||||
debug.get()->dynamic = dynamic;
|
||||
|
||||
char *dso_debug_data = new char[dynamic_length];
|
||||
char* dso_debug_data = new char[dynamic_length];
|
||||
dumper_->CopyFromProcess(dso_debug_data, GetCrashThread(), dynamic,
|
||||
dynamic_length);
|
||||
debug.CopyIndexAfterObject(0, dso_debug_data, dynamic_length);
|
||||
@ -1210,8 +1208,14 @@ class MinidumpWriter {
|
||||
if (space_ptr != value)
|
||||
continue;
|
||||
|
||||
// skip past the colon and all the spaces that follow
|
||||
do {
|
||||
value++;
|
||||
} while (my_isspace(*value));
|
||||
|
||||
uintptr_t val;
|
||||
my_read_decimal_ptr(&val, ++value);
|
||||
if (my_read_decimal_ptr(&val, value) == value)
|
||||
continue;
|
||||
entry->value = static_cast<int>(val);
|
||||
entry->found = true;
|
||||
}
|
||||
@ -1223,7 +1227,7 @@ class MinidumpWriter {
|
||||
if (!value)
|
||||
goto popline;
|
||||
|
||||
// skip ':" and all the spaces that follows
|
||||
// skip past the colon and all the spaces that follow
|
||||
do {
|
||||
value++;
|
||||
} while (my_isspace(*value));
|
||||
|
@ -35,6 +35,10 @@
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
162F64F2161C577500CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F0161C577500CD68D5 /* arch_utilities.cc */; };
|
||||
162F64F3161C577500CD68D5 /* arch_utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 162F64F1161C577500CD68D5 /* arch_utilities.h */; };
|
||||
162F64F4161C579B00CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F0161C577500CD68D5 /* arch_utilities.cc */; };
|
||||
162F64F5161C579B00CD68D5 /* arch_utilities.h in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F1161C577500CD68D5 /* arch_utilities.h */; };
|
||||
163201D61443019E00C4DBF5 /* ConfigFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 163201D41443019E00C4DBF5 /* ConfigFile.h */; };
|
||||
163201D71443019E00C4DBF5 /* ConfigFile.mm in Sources */ = {isa = PBXBuildFile; fileRef = 163201D51443019E00C4DBF5 /* ConfigFile.mm */; };
|
||||
163201E31443029300C4DBF5 /* ConfigFile.mm in Sources */ = {isa = PBXBuildFile; fileRef = 163201D51443019E00C4DBF5 /* ConfigFile.mm */; };
|
||||
@ -555,6 +559,8 @@
|
||||
0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
162F64F0161C577500CD68D5 /* arch_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../common/mac/arch_utilities.cc; sourceTree = "<group>"; };
|
||||
162F64F1161C577500CD68D5 /* arch_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../common/mac/arch_utilities.h; sourceTree = "<group>"; };
|
||||
163201D41443019E00C4DBF5 /* ConfigFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConfigFile.h; path = crash_generation/ConfigFile.h; sourceTree = "<group>"; };
|
||||
163201D51443019E00C4DBF5 /* ConfigFile.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = ConfigFile.mm; path = crash_generation/ConfigFile.mm; sourceTree = "<group>"; };
|
||||
163202431443201300C4DBF5 /* uploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uploader.h; path = sender/uploader.h; sourceTree = "<group>"; };
|
||||
@ -940,6 +946,8 @@
|
||||
F92C53840ECCE68D009BE4BA /* mac */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
162F64F0161C577500CD68D5 /* arch_utilities.cc */,
|
||||
162F64F1161C577500CD68D5 /* arch_utilities.h */,
|
||||
8B31022211F0CE1000FCF3E4 /* GTMGarbageCollection.h */,
|
||||
8B31007011F0CD3C00FCF3E4 /* GTMDefines.h */,
|
||||
F9C77E0F0F7DDF650045F7DB /* testing */,
|
||||
@ -1142,6 +1150,7 @@
|
||||
D2F9A4CC121336C7002747C1 /* crash_generation_server.h in Headers */,
|
||||
163201D61443019E00C4DBF5 /* ConfigFile.h in Headers */,
|
||||
16C7C918147D45AE00776EAD /* BreakpadDefines.h in Headers */,
|
||||
162F64F3161C577500CD68D5 /* arch_utilities.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1666,6 +1675,7 @@
|
||||
D2F9A4CB121336C7002747C1 /* crash_generation_client.cc in Sources */,
|
||||
D2F9A4CD121336C7002747C1 /* crash_generation_server.cc in Sources */,
|
||||
163201D71443019E00C4DBF5 /* ConfigFile.mm in Sources */,
|
||||
162F64F2161C577500CD68D5 /* arch_utilities.cc in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1747,6 +1757,8 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
162F64F4161C579B00CD68D5 /* arch_utilities.cc in Sources */,
|
||||
162F64F5161C579B00CD68D5 /* arch_utilities.h in Sources */,
|
||||
D2A5DD301188633800081F03 /* breakpad_nlist_64.cc in Sources */,
|
||||
F92C563F0ECD10CA009BE4BA /* convert_UTF.c in Sources */,
|
||||
F92C56400ECD10CA009BE4BA /* dynamic_images.cc in Sources */,
|
||||
|
@ -475,8 +475,6 @@ void ReadImageInfo(DynamicImages& images,
|
||||
mach_header_bytes) != KERN_SUCCESS)
|
||||
continue;
|
||||
|
||||
header = reinterpret_cast<mach_header_type*>(&mach_header_bytes[0]);
|
||||
|
||||
// Read the file name from the task's memory space.
|
||||
string file_path;
|
||||
if (info.file_path_) {
|
||||
|
@ -103,11 +103,10 @@ exception_mask_t s_exception_mask = EXC_MASK_BAD_ACCESS |
|
||||
EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
extern "C"
|
||||
{
|
||||
extern "C" {
|
||||
// Forward declarations for functions that need "C" style compilation
|
||||
boolean_t exc_server(mach_msg_header_t *request,
|
||||
mach_msg_header_t *reply);
|
||||
boolean_t exc_server(mach_msg_header_t* request,
|
||||
mach_msg_header_t* reply);
|
||||
|
||||
// This symbol must be visible to dlsym() - see
|
||||
// http://code.google.com/p/google-breakpad/issues/detail?id=345 for details.
|
||||
@ -129,19 +128,19 @@ kern_return_t ForwardException(mach_port_t task,
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// Implementation is based on the implementation generated by mig.
|
||||
boolean_t breakpad_exc_server(mach_msg_header_t *InHeadP,
|
||||
mach_msg_header_t *OutHeadP) {
|
||||
OutHeadP->msgh_bits =
|
||||
MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InHeadP->msgh_bits), 0);
|
||||
OutHeadP->msgh_remote_port = InHeadP->msgh_remote_port;
|
||||
/* Minimal size: routine() will update it if different */
|
||||
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
|
||||
OutHeadP->msgh_local_port = MACH_PORT_NULL;
|
||||
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
|
||||
boolean_t breakpad_exc_server(mach_msg_header_t* InHeadP,
|
||||
mach_msg_header_t* OutHeadP) {
|
||||
OutHeadP->msgh_bits =
|
||||
MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InHeadP->msgh_bits), 0);
|
||||
OutHeadP->msgh_remote_port = InHeadP->msgh_remote_port;
|
||||
/* Minimal size: routine() will update it if different */
|
||||
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
|
||||
OutHeadP->msgh_local_port = MACH_PORT_NULL;
|
||||
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
|
||||
|
||||
if (InHeadP->msgh_id != 2401) {
|
||||
((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
|
||||
((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
|
||||
((mig_reply_error_t*)OutHeadP)->NDR = NDR_record;
|
||||
((mig_reply_error_t*)OutHeadP)->RetCode = MIG_BAD_ID;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -171,8 +170,8 @@ boolean_t breakpad_exc_server(mach_msg_header_t *InHeadP,
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
Request *In0P = (Request *)InHeadP;
|
||||
Reply *OutP = (Reply *)OutHeadP;
|
||||
Request* In0P = (Request*)InHeadP;
|
||||
Reply* OutP = (Reply*)OutHeadP;
|
||||
|
||||
if (In0P->task.name != mach_task_self()) {
|
||||
return FALSE;
|
||||
@ -186,8 +185,8 @@ boolean_t breakpad_exc_server(mach_msg_header_t *InHeadP,
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
boolean_t breakpad_exc_server(mach_msg_header_t *request,
|
||||
mach_msg_header_t *reply) {
|
||||
boolean_t breakpad_exc_server(mach_msg_header_t* request,
|
||||
mach_msg_header_t* reply) {
|
||||
return exc_server(request, reply);
|
||||
}
|
||||
|
||||
@ -207,9 +206,9 @@ kern_return_t catch_exception_raise(mach_port_t port, mach_port_t failed_thread,
|
||||
ExceptionHandler::ExceptionHandler(const string &dump_path,
|
||||
FilterCallback filter,
|
||||
MinidumpCallback callback,
|
||||
void *callback_context,
|
||||
void* callback_context,
|
||||
bool install_handler,
|
||||
const char *port_name)
|
||||
const char* port_name)
|
||||
: dump_path_(),
|
||||
filter_(filter),
|
||||
callback_(callback),
|
||||
@ -235,7 +234,7 @@ ExceptionHandler::ExceptionHandler(const string &dump_path,
|
||||
// special constructor if we want to bypass minidump writing and
|
||||
// simply get a callback with the exception information
|
||||
ExceptionHandler::ExceptionHandler(DirectCallback callback,
|
||||
void *callback_context,
|
||||
void* callback_context,
|
||||
bool install_handler)
|
||||
: dump_path_(),
|
||||
filter_(NULL),
|
||||
@ -287,18 +286,18 @@ bool ExceptionHandler::WriteMinidump(bool write_exception_stream) {
|
||||
bool ExceptionHandler::WriteMinidump(const string &dump_path,
|
||||
bool write_exception_stream,
|
||||
MinidumpCallback callback,
|
||||
void *callback_context) {
|
||||
void* callback_context) {
|
||||
ExceptionHandler handler(dump_path, NULL, callback, callback_context, false,
|
||||
NULL);
|
||||
NULL);
|
||||
return handler.WriteMinidump(write_exception_stream);
|
||||
}
|
||||
|
||||
// static
|
||||
bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
|
||||
mach_port_t child_blamed_thread,
|
||||
const string &dump_path,
|
||||
MinidumpCallback callback,
|
||||
void *callback_context) {
|
||||
mach_port_t child_blamed_thread,
|
||||
const string &dump_path,
|
||||
MinidumpCallback callback,
|
||||
void* callback_context) {
|
||||
ScopedTaskSuspend suspend(child);
|
||||
|
||||
MinidumpGenerator generator(child, MACH_PORT_NULL);
|
||||
@ -306,22 +305,22 @@ bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
|
||||
string dump_filename = generator.UniqueNameInDirectory(dump_path, &dump_id);
|
||||
|
||||
generator.SetExceptionInformation(EXC_BREAKPOINT,
|
||||
#if defined (__i386__) || defined(__x86_64__)
|
||||
EXC_I386_BPT,
|
||||
#elif defined (__ppc__) || defined (__ppc64__)
|
||||
EXC_PPC_BREAKPOINT,
|
||||
#elif defined (__arm__)
|
||||
EXC_ARM_BREAKPOINT,
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
EXC_I386_BPT,
|
||||
#elif defined(__ppc__) || defined(__ppc64__)
|
||||
EXC_PPC_BREAKPOINT,
|
||||
#elif defined(__arm__)
|
||||
EXC_ARM_BREAKPOINT,
|
||||
#else
|
||||
#error architecture not supported
|
||||
#endif
|
||||
0,
|
||||
child_blamed_thread);
|
||||
0,
|
||||
child_blamed_thread);
|
||||
bool result = generator.Write(dump_filename.c_str());
|
||||
|
||||
if (callback) {
|
||||
return callback(dump_path.c_str(), dump_id.c_str(),
|
||||
callback_context, result);
|
||||
callback_context, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -329,7 +328,7 @@ bool ExceptionHandler::WriteMinidumpForChild(mach_port_t child,
|
||||
bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
|
||||
int exception_code,
|
||||
int exception_subcode,
|
||||
ucontext_t *task_context,
|
||||
ucontext_t* task_context,
|
||||
mach_port_t thread_name,
|
||||
bool exit_after_write,
|
||||
bool report_current_thread) {
|
||||
@ -350,12 +349,12 @@ bool ExceptionHandler::WriteMinidumpWithException(int exception_type,
|
||||
// If this is a real exception, give the filter (if any) a chance to
|
||||
// decide if this should be sent.
|
||||
if (filter_ && !filter_(callback_context_))
|
||||
return false;
|
||||
return false;
|
||||
return crash_generation_client_->RequestDumpForException(
|
||||
exception_type,
|
||||
exception_code,
|
||||
exception_subcode,
|
||||
thread_name);
|
||||
exception_type,
|
||||
exception_code,
|
||||
exception_subcode,
|
||||
thread_name);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@ -450,9 +449,9 @@ kern_return_t ForwardException(mach_port_t task, mach_port_t failed_thread,
|
||||
}
|
||||
|
||||
// static
|
||||
void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
||||
ExceptionHandler *self =
|
||||
reinterpret_cast<ExceptionHandler *>(exception_handler_class);
|
||||
void* ExceptionHandler::WaitForMessage(void* exception_handler_class) {
|
||||
ExceptionHandler* self =
|
||||
reinterpret_cast<ExceptionHandler*>(exception_handler_class);
|
||||
ExceptionMessage receive;
|
||||
|
||||
// Wait for the exception info
|
||||
@ -497,11 +496,11 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
||||
if (receive.header.msgh_id == kWriteDumpWithExceptionMessage) {
|
||||
thread = receive.thread.name;
|
||||
exception_type = EXC_BREAKPOINT;
|
||||
#if defined (__i386__) || defined(__x86_64__)
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
exception_code = EXC_I386_BPT;
|
||||
#elif defined (__ppc__) || defined (__ppc64__)
|
||||
#elif defined(__ppc__) || defined(__ppc64__)
|
||||
exception_code = EXC_PPC_BREAKPOINT;
|
||||
#elif defined (__arm__)
|
||||
#elif defined(__arm__)
|
||||
exception_code = EXC_ARM_BREAKPOINT;
|
||||
#else
|
||||
#error architecture not supported
|
||||
@ -582,7 +581,7 @@ void *ExceptionHandler::WaitForMessage(void *exception_handler_class) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//static
|
||||
// static
|
||||
void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||
#if USE_PROTECTED_ALLOCATIONS
|
||||
if (gBreakpadAllocator)
|
||||
@ -636,7 +635,6 @@ bool ExceptionHandler::InstallHandler() {
|
||||
#else
|
||||
previous_ = new ExceptionParameters();
|
||||
#endif
|
||||
|
||||
}
|
||||
catch (std::bad_alloc) {
|
||||
return false;
|
||||
@ -735,7 +733,7 @@ bool ExceptionHandler::Setup(bool install_handler) {
|
||||
result = thread_create_result ? KERN_FAILURE : KERN_SUCCESS;
|
||||
}
|
||||
|
||||
return result == KERN_SUCCESS ? true : false;
|
||||
return result == KERN_SUCCESS;
|
||||
}
|
||||
|
||||
bool ExceptionHandler::Teardown() {
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include <mach/host_info.h>
|
||||
#include <mach/machine.h>
|
||||
#include <mach/vm_statistics.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach-o/loader.h>
|
||||
@ -1304,14 +1305,15 @@ bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type,
|
||||
MacFileUtilities::MachoID macho(module_path,
|
||||
reinterpret_cast<void *>(module->base_of_image),
|
||||
static_cast<size_t>(module->size_of_image));
|
||||
result = macho.UUIDCommand(cpu_type, identifier);
|
||||
result = macho.UUIDCommand(cpu_type, CPU_SUBTYPE_MULTIPLE, identifier);
|
||||
if (!result)
|
||||
result = macho.MD5(cpu_type, identifier);
|
||||
result = macho.MD5(cpu_type, CPU_SUBTYPE_MULTIPLE, identifier);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
FileID file_id(module_path);
|
||||
result = file_id.MachoIdentifier(cpu_type, identifier);
|
||||
result = file_id.MachoIdentifier(cpu_type, CPU_SUBTYPE_MULTIPLE,
|
||||
identifier);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
|
@ -84,6 +84,7 @@ int pthread_barrier_destroy(pthread_barrier_t *barrier) {
|
||||
barrier->count = 0;
|
||||
pthread_cond_destroy(&barrier->cond);
|
||||
pthread_mutex_destroy(&barrier->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "common/dwarf_cu_to_module.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cxxabi.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -56,7 +57,7 @@ using std::set;
|
||||
using std::vector;
|
||||
|
||||
// Data provided by a DWARF specification DIE.
|
||||
//
|
||||
//
|
||||
// In DWARF, the DIE for a definition may contain a DW_AT_specification
|
||||
// attribute giving the offset of the corresponding declaration DIE, and
|
||||
// the definition DIE may omit information given in the declaration. For
|
||||
@ -73,6 +74,9 @@ using std::vector;
|
||||
// A Specification holds information gathered from a declaration DIE that
|
||||
// we may need if we find a DW_AT_specification link pointing to it.
|
||||
struct DwarfCUToModule::Specification {
|
||||
// The qualified name that can be found by demangling DW_AT_MIPS_linkage_name.
|
||||
string qualified_name;
|
||||
|
||||
// The name of the enclosing scope, or the empty string if there is none.
|
||||
string enclosing_name;
|
||||
|
||||
@ -97,12 +101,20 @@ struct DwarfCUToModule::FilePrivate {
|
||||
// A set of strings used in this CU. Before storing a string in one of
|
||||
// our data structures, insert it into this set, and then use the string
|
||||
// from the set.
|
||||
//
|
||||
// Because std::string uses reference counting internally, simply using
|
||||
// strings from this set, even if passed by value, assigned, or held
|
||||
// directly in structures and containers (map<string, ...>, for example),
|
||||
// causes those strings to share a single instance of each distinct piece
|
||||
// of text.
|
||||
//
|
||||
// In some STL implementations, strings are reference-counted internally,
|
||||
// meaning that simply using strings from this set, even if passed by
|
||||
// value, assigned, or held directly in structures and containers
|
||||
// (map<string, ...>, for example), causes those strings to share a
|
||||
// single instance of each distinct piece of text. GNU's libstdc++ uses
|
||||
// reference counts, and I believe MSVC did as well, at some point.
|
||||
// However, C++ '11 implementations are moving away from reference
|
||||
// counting.
|
||||
//
|
||||
// In other implementations, string assignments copy the string's text,
|
||||
// so this set will actually hold yet another copy of the string (although
|
||||
// everything will still work). To improve memory consumption portably,
|
||||
// we will probably need to use pointers to strings held in this set.
|
||||
set<string> common_strings;
|
||||
|
||||
// A map from offsets of DIEs within the .debug_info section to
|
||||
@ -218,6 +230,14 @@ class DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler {
|
||||
DIEContext *parent_context_;
|
||||
uint64 offset_;
|
||||
|
||||
// Place the name in the global set of strings. Even though this looks
|
||||
// like a copy, all the major std::string implementations use reference
|
||||
// counting internally, so the effect is to have all the data structures
|
||||
// share copies of strings whenever possible.
|
||||
// FIXME: Should this return something like a string_ref to avoid the
|
||||
// assumption about how strings are implemented?
|
||||
string AddStringToPool(const string &str);
|
||||
|
||||
// If this DIE has a DW_AT_declaration attribute, this is its value.
|
||||
// It is false on DIEs with no DW_AT_declaration attribute.
|
||||
bool declaration_;
|
||||
@ -230,6 +250,11 @@ class DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler {
|
||||
// The value of the DW_AT_name attribute, or the empty string if the
|
||||
// DIE has no such attribute.
|
||||
string name_attribute_;
|
||||
|
||||
// The demangled value of the DW_AT_MIPS_linkage_name attribute, or the empty
|
||||
// string if the DIE has no such attribute or its content could not be
|
||||
// demangled.
|
||||
string demangled_name_;
|
||||
};
|
||||
|
||||
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeUnsigned(
|
||||
@ -273,20 +298,26 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
|
||||
}
|
||||
}
|
||||
|
||||
string DwarfCUToModule::GenericDIEHandler::AddStringToPool(const string &str) {
|
||||
pair<set<string>::iterator, bool> result =
|
||||
cu_context_->file_context->file_private->common_strings.insert(str);
|
||||
return *result.first;
|
||||
}
|
||||
|
||||
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
|
||||
enum DwarfAttribute attr,
|
||||
enum DwarfForm form,
|
||||
const string &data) {
|
||||
switch (attr) {
|
||||
case dwarf2reader::DW_AT_name: {
|
||||
// Place the name in our global set of strings, and then use the
|
||||
// string from the set. Even though the assignment looks like a copy,
|
||||
// all the major std::string implementations use reference counting
|
||||
// internally, so the effect is to have all our data structures share
|
||||
// copies of strings whenever possible.
|
||||
pair<set<string>::iterator, bool> result =
|
||||
cu_context_->file_context->file_private->common_strings.insert(data);
|
||||
name_attribute_ = *result.first;
|
||||
case dwarf2reader::DW_AT_name:
|
||||
name_attribute_ = AddStringToPool(data);
|
||||
break;
|
||||
case dwarf2reader::DW_AT_MIPS_linkage_name: {
|
||||
char* demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, NULL);
|
||||
if (demangled) {
|
||||
demangled_name_ = AddStringToPool(demangled);
|
||||
free(reinterpret_cast<void*>(demangled));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@ -294,33 +325,54 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
|
||||
}
|
||||
|
||||
string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
|
||||
// Find our unqualified name. If the DIE has its own DW_AT_name
|
||||
// attribute, then use that; otherwise, check our specification.
|
||||
const string *unqualified_name;
|
||||
if (name_attribute_.empty() && specification_)
|
||||
unqualified_name = &specification_->unqualified_name;
|
||||
else
|
||||
unqualified_name = &name_attribute_;
|
||||
// Use the demangled name, if one is available. Demangled names are
|
||||
// preferable to those inferred from the DWARF structure because they
|
||||
// include argument types.
|
||||
const string *qualified_name = NULL;
|
||||
if (!demangled_name_.empty()) {
|
||||
// Found it is this DIE.
|
||||
qualified_name = &demangled_name_;
|
||||
} else if (specification_ && !specification_->qualified_name.empty()) {
|
||||
// Found it on the specification.
|
||||
qualified_name = &specification_->qualified_name;
|
||||
}
|
||||
|
||||
// Find the name of our enclosing context. If we have a
|
||||
// specification, it's the specification's enclosing context that
|
||||
// counts; otherwise, use this DIE's context.
|
||||
const string *unqualified_name;
|
||||
const string *enclosing_name;
|
||||
if (specification_)
|
||||
enclosing_name = &specification_->enclosing_name;
|
||||
else
|
||||
enclosing_name = &parent_context_->name;
|
||||
if (!qualified_name) {
|
||||
// Find our unqualified name. If the DIE has its own DW_AT_name
|
||||
// attribute, then use that; otherwise, check our specification.
|
||||
if (name_attribute_.empty() && specification_)
|
||||
unqualified_name = &specification_->unqualified_name;
|
||||
else
|
||||
unqualified_name = &name_attribute_;
|
||||
|
||||
// Find the name of our enclosing context. If we have a
|
||||
// specification, it's the specification's enclosing context that
|
||||
// counts; otherwise, use this DIE's context.
|
||||
if (specification_)
|
||||
enclosing_name = &specification_->enclosing_name;
|
||||
else
|
||||
enclosing_name = &parent_context_->name;
|
||||
}
|
||||
|
||||
// If this DIE was marked as a declaration, record its names in the
|
||||
// specification table.
|
||||
if (declaration_) {
|
||||
FileContext *file_context = cu_context_->file_context;
|
||||
Specification spec;
|
||||
spec.enclosing_name = *enclosing_name;
|
||||
spec.unqualified_name = *unqualified_name;
|
||||
if (qualified_name)
|
||||
spec.qualified_name = *qualified_name;
|
||||
else {
|
||||
spec.enclosing_name = *enclosing_name;
|
||||
spec.unqualified_name = *unqualified_name;
|
||||
}
|
||||
file_context->file_private->specifications[offset_] = spec;
|
||||
}
|
||||
|
||||
if (qualified_name)
|
||||
return *qualified_name;
|
||||
|
||||
// Combine the enclosing name and unqualified name to produce our
|
||||
// own fully-qualified name.
|
||||
return cu_context_->language->MakeQualifiedName(*enclosing_name,
|
||||
@ -474,7 +526,7 @@ bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
|
||||
dwarf2reader::DIEHandler *DwarfCUToModule::NamedScopeHandler::FindChildHandler(
|
||||
uint64 offset,
|
||||
enum DwarfTag tag,
|
||||
const AttributeList &attrs) {
|
||||
const AttributeList &/*attrs*/) {
|
||||
switch (tag) {
|
||||
case dwarf2reader::DW_TAG_subprogram:
|
||||
return new FuncHandler(cu_context_, &child_context_, offset);
|
||||
@ -616,7 +668,7 @@ bool DwarfCUToModule::EndAttributes() {
|
||||
dwarf2reader::DIEHandler *DwarfCUToModule::FindChildHandler(
|
||||
uint64 offset,
|
||||
enum DwarfTag tag,
|
||||
const AttributeList &attrs) {
|
||||
const AttributeList &/*attrs*/) {
|
||||
switch (tag) {
|
||||
case dwarf2reader::DW_TAG_subprogram:
|
||||
return new FuncHandler(cu_context_, child_context_, offset);
|
||||
@ -927,7 +979,7 @@ bool DwarfCUToModule::StartCompilationUnit(uint64 offset,
|
||||
}
|
||||
|
||||
bool DwarfCUToModule::StartRootDIE(uint64 offset, enum DwarfTag tag,
|
||||
const AttributeList& attrs) {
|
||||
const AttributeList& /*attrs*/) {
|
||||
// We don't deal with partial compilation units (the only other tag
|
||||
// likely to be used for root DIE).
|
||||
return tag == dwarf2reader::DW_TAG_compile_unit;
|
||||
|
@ -202,13 +202,15 @@ class CUFixtureBase {
|
||||
// address, and size. Call EndAttributes and Finish; one cannot
|
||||
// define children of the defined function's DIE.
|
||||
void DefineFunction(DIEHandler *parent, const string &name,
|
||||
Module::Address address, Module::Address size);
|
||||
Module::Address address, Module::Address size,
|
||||
const char* mangled_name);
|
||||
|
||||
// Create a declaration DIE as a child of PARENT with the given
|
||||
// offset, tag and name. If NAME is the empty string, don't provide
|
||||
// a DW_AT_name attribute. Call EndAttributes and Finish.
|
||||
void DeclarationDIE(DIEHandler *parent, uint64 offset,
|
||||
DwarfTag tag, const string &name);
|
||||
DwarfTag tag, const string &name,
|
||||
const string &mangled_name);
|
||||
|
||||
// Create a definition DIE as a child of PARENT with the given tag
|
||||
// that refers to the declaration DIE at offset SPECIFICATION as its
|
||||
@ -452,7 +454,8 @@ DIEHandler *CUFixtureBase::StartSpecifiedDIE(DIEHandler *parent,
|
||||
|
||||
void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
|
||||
const string &name, Module::Address address,
|
||||
Module::Address size) {
|
||||
Module::Address size,
|
||||
const char* mangled_name) {
|
||||
dwarf2reader::AttributeList func_attrs;
|
||||
func_attrs.push_back(make_pair(dwarf2reader::DW_AT_name,
|
||||
dwarf2reader::DW_FORM_strp));
|
||||
@ -475,6 +478,11 @@ void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
|
||||
func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
|
||||
dwarf2reader::DW_FORM_addr,
|
||||
address + size);
|
||||
if (mangled_name)
|
||||
func->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
|
||||
dwarf2reader::DW_FORM_strp,
|
||||
mangled_name);
|
||||
|
||||
ProcessStrangeAttributes(func);
|
||||
EXPECT_TRUE(func->EndAttributes());
|
||||
func->Finish();
|
||||
@ -483,11 +491,14 @@ void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
|
||||
|
||||
void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset,
|
||||
DwarfTag tag,
|
||||
const string &name) {
|
||||
const string &name,
|
||||
const string &mangled_name) {
|
||||
dwarf2reader::AttributeList attrs;
|
||||
if (!name.empty())
|
||||
attrs.push_back(make_pair(dwarf2reader::DW_AT_name,
|
||||
dwarf2reader::DW_FORM_strp));
|
||||
|
||||
|
||||
attrs.push_back(make_pair(dwarf2reader::DW_AT_declaration,
|
||||
dwarf2reader::DW_FORM_flag));
|
||||
dwarf2reader::DIEHandler *die = parent->FindChildHandler(offset, tag, attrs);
|
||||
@ -496,6 +507,11 @@ void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset,
|
||||
die->ProcessAttributeString(dwarf2reader::DW_AT_name,
|
||||
dwarf2reader::DW_FORM_strp,
|
||||
name);
|
||||
if (!mangled_name.empty())
|
||||
die->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
|
||||
dwarf2reader::DW_FORM_strp,
|
||||
mangled_name);
|
||||
|
||||
die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_declaration,
|
||||
dwarf2reader::DW_FORM_flag,
|
||||
1);
|
||||
@ -675,8 +691,8 @@ void CUFixtureBase::TestLine(int i, int j,
|
||||
#define PushLine(a,b,c,d) TRACE(PushLine((a),(b),(c),(d)))
|
||||
#define SetLanguage(a) TRACE(SetLanguage(a))
|
||||
#define StartCU() TRACE(StartCU())
|
||||
#define DefineFunction(a,b,c,d) TRACE(DefineFunction((a),(b),(c),(d)))
|
||||
#define DeclarationDIE(a,b,c,d) TRACE(DeclarationDIE((a),(b),(c),(d)))
|
||||
#define DefineFunction(a,b,c,d,e) TRACE(DefineFunction((a),(b),(c),(d),(e)))
|
||||
#define DeclarationDIE(a,b,c,d,e) TRACE(DeclarationDIE((a),(b),(c),(d),(e)))
|
||||
#define DefinitionDIE(a,b,c,d,e,f) TRACE(DefinitionDIE((a),(b),(c),(d),(e),(f)))
|
||||
#define TestFunctionCount(a) TRACE(TestFunctionCount(a))
|
||||
#define TestFunction(a,b,c,d) TRACE(TestFunction((a),(b),(c),(d)))
|
||||
@ -691,7 +707,7 @@ TEST_F(SimpleCU, OneFunc) {
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1",
|
||||
0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
|
||||
0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(1);
|
||||
@ -701,6 +717,18 @@ TEST_F(SimpleCU, OneFunc) {
|
||||
246571772);
|
||||
}
|
||||
|
||||
TEST_F(SimpleCU, MangledName) {
|
||||
PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1",
|
||||
0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "_ZN1n1fEi");
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(1);
|
||||
TestFunction(0, "n::f(int)", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
|
||||
}
|
||||
|
||||
TEST_F(SimpleCU, IrrelevantRootChildren) {
|
||||
StartCU();
|
||||
dwarf2reader::AttributeList no_attrs;
|
||||
@ -805,7 +833,7 @@ TEST_F(SimpleCU, UnnamedFunction) {
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "",
|
||||
0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL);
|
||||
0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(1);
|
||||
@ -882,10 +910,10 @@ TEST_P(FuncLinePairing, Pairing) {
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1",
|
||||
s.functions[0].start,
|
||||
s.functions[0].end - s.functions[0].start);
|
||||
s.functions[0].end - s.functions[0].start, NULL);
|
||||
DefineFunction(&root_handler_, "function2",
|
||||
s.functions[1].start,
|
||||
s.functions[1].end - s.functions[1].start);
|
||||
s.functions[1].end - s.functions[1].start, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(2);
|
||||
@ -929,7 +957,8 @@ TEST_F(FuncLinePairing, FuncsNoLines) {
|
||||
EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1", 0x127da12ffcf5c51fULL, 0x1000U);
|
||||
DefineFunction(&root_handler_, "function1", 0x127da12ffcf5c51fULL, 0x1000U,
|
||||
NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(1);
|
||||
@ -941,8 +970,8 @@ TEST_F(FuncLinePairing, GapThenFunction) {
|
||||
PushLine(10, 2, "line-file-1", 263008005);
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1", 10, 2);
|
||||
DefineFunction(&root_handler_, "function2", 20, 2);
|
||||
DefineFunction(&root_handler_, "function1", 10, 2, NULL);
|
||||
DefineFunction(&root_handler_, "function2", 20, 2, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(2);
|
||||
@ -967,10 +996,10 @@ TEST_F(FuncLinePairing, GCCAlignmentStretch) {
|
||||
PushLine(20, 10, "line-file", 61661044);
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1", 10, 5);
|
||||
DefineFunction(&root_handler_, "function1", 10, 5, NULL);
|
||||
// five-byte gap between functions, covered by line 63351048.
|
||||
// This should not elicit a warning.
|
||||
DefineFunction(&root_handler_, "function2", 20, 10);
|
||||
DefineFunction(&root_handler_, "function2", 20, 10, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(2);
|
||||
@ -991,8 +1020,8 @@ TEST_F(FuncLinePairing, LineAtEndOfAddressSpace) {
|
||||
EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1", 0xfffffffffffffff0ULL, 6);
|
||||
DefineFunction(&root_handler_, "function2", 0xfffffffffffffffaULL, 5);
|
||||
DefineFunction(&root_handler_, "function1", 0xfffffffffffffff0ULL, 6, NULL);
|
||||
DefineFunction(&root_handler_, "function2", 0xfffffffffffffffaULL, 5, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(2);
|
||||
@ -1012,7 +1041,7 @@ TEST_F(FuncLinePairing, WarnOnceFunc) {
|
||||
EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function", 10, 11);
|
||||
DefineFunction(&root_handler_, "function", 10, 11, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(1);
|
||||
@ -1029,8 +1058,8 @@ TEST_F(FuncLinePairing, WarnOnceLine) {
|
||||
EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
|
||||
|
||||
StartCU();
|
||||
DefineFunction(&root_handler_, "function1", 11, 1);
|
||||
DefineFunction(&root_handler_, "function2", 13, 1);
|
||||
DefineFunction(&root_handler_, "function1", 11, 1, NULL);
|
||||
DefineFunction(&root_handler_, "function2", 13, 1, NULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(2);
|
||||
@ -1062,8 +1091,8 @@ TEST_P(CXXQualifiedNames, TwoFunctions) {
|
||||
DIEHandler *enclosure_handler = StartNamedDIE(&root_handler_, tag,
|
||||
"Enclosure");
|
||||
EXPECT_TRUE(enclosure_handler != NULL);
|
||||
DefineFunction(enclosure_handler, "func_B", 10, 1);
|
||||
DefineFunction(enclosure_handler, "func_C", 20, 1);
|
||||
DefineFunction(enclosure_handler, "func_B", 10, 1, NULL);
|
||||
DefineFunction(enclosure_handler, "func_C", 20, 1, NULL);
|
||||
enclosure_handler->Finish();
|
||||
delete enclosure_handler;
|
||||
root_handler_.Finish();
|
||||
@ -1087,7 +1116,7 @@ TEST_P(CXXQualifiedNames, FuncInEnclosureInNamespace) {
|
||||
DIEHandler *enclosure_handler = StartNamedDIE(namespace_handler, tag,
|
||||
"Enclosure");
|
||||
EXPECT_TRUE(enclosure_handler != NULL);
|
||||
DefineFunction(enclosure_handler, "function", 10, 1);
|
||||
DefineFunction(enclosure_handler, "function", 10, 1, NULL);
|
||||
enclosure_handler->Finish();
|
||||
delete enclosure_handler;
|
||||
namespace_handler->Finish();
|
||||
@ -1114,7 +1143,7 @@ TEST_F(CXXQualifiedNames, FunctionInClassInStructInNamespace) {
|
||||
DIEHandler *class_handler
|
||||
= StartNamedDIE(struct_handler, dwarf2reader::DW_TAG_class_type,
|
||||
"class_C");
|
||||
DefineFunction(class_handler, "function_D", 10, 1);
|
||||
DefineFunction(class_handler, "function_D", 10, 1, NULL);
|
||||
class_handler->Finish();
|
||||
delete class_handler;
|
||||
struct_handler->Finish();
|
||||
@ -1160,7 +1189,7 @@ TEST_P(QualifiedForLanguage, MemberFunction) {
|
||||
DIEHandler *class_handler
|
||||
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
|
||||
"class_A");
|
||||
DefineFunction(class_handler, "function_B", 10, 1);
|
||||
DefineFunction(class_handler, "function_B", 10, 1, NULL);
|
||||
class_handler->Finish();
|
||||
delete class_handler;
|
||||
root_handler_.Finish();
|
||||
@ -1184,7 +1213,7 @@ TEST_P(QualifiedForLanguage, MemberFunctionSignedLanguage) {
|
||||
DIEHandler *class_handler
|
||||
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
|
||||
"class_A");
|
||||
DefineFunction(class_handler, "function_B", 10, 1);
|
||||
DefineFunction(class_handler, "function_B", 10, 1, NULL);
|
||||
class_handler->Finish();
|
||||
delete class_handler;
|
||||
root_handler_.Finish();
|
||||
@ -1204,7 +1233,7 @@ TEST_F(Specifications, Function) {
|
||||
|
||||
StartCU();
|
||||
DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name");
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
|
||||
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
|
||||
0xcd3c51b946fb1eeeLL, "",
|
||||
0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
|
||||
@ -1215,6 +1244,23 @@ TEST_F(Specifications, Function) {
|
||||
0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
|
||||
}
|
||||
|
||||
TEST_F(Specifications, MangledName) {
|
||||
PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661);
|
||||
|
||||
StartCU();
|
||||
DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name",
|
||||
"_ZN1C1fEi");
|
||||
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
|
||||
0xcd3c51b946fb1eeeLL, "",
|
||||
0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
|
||||
root_handler_.Finish();
|
||||
|
||||
TestFunctionCount(1);
|
||||
TestFunction(0, "C::f(int)",
|
||||
0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
|
||||
}
|
||||
|
||||
TEST_F(Specifications, MemberFunction) {
|
||||
PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691);
|
||||
|
||||
@ -1222,7 +1268,7 @@ TEST_F(Specifications, MemberFunction) {
|
||||
DIEHandler *class_handler
|
||||
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A");
|
||||
DeclarationDIE(class_handler, 0x7d83028c431406e8ULL,
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name");
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
|
||||
class_handler->Finish();
|
||||
delete class_handler;
|
||||
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
|
||||
@ -1247,7 +1293,7 @@ TEST_F(Specifications, FunctionDeclarationParent) {
|
||||
"class_A");
|
||||
ASSERT_TRUE(class_handler != NULL);
|
||||
DeclarationDIE(class_handler, 0x0e0e877c8404544aULL,
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name");
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
|
||||
class_handler->Finish();
|
||||
delete class_handler;
|
||||
}
|
||||
@ -1275,7 +1321,8 @@ TEST_F(Specifications, NamedScopeDeclarationParent) {
|
||||
"space_A");
|
||||
ASSERT_TRUE(space_handler != NULL);
|
||||
DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL,
|
||||
dwarf2reader::DW_TAG_class_type, "class-declaration-name");
|
||||
dwarf2reader::DW_TAG_class_type, "class-declaration-name",
|
||||
"");
|
||||
space_handler->Finish();
|
||||
delete space_handler;
|
||||
}
|
||||
@ -1286,7 +1333,7 @@ TEST_F(Specifications, NamedScopeDeclarationParent) {
|
||||
0x419bb1d12f9a73a2ULL, "class-definition-name");
|
||||
ASSERT_TRUE(class_handler != NULL);
|
||||
DefineFunction(class_handler, "function",
|
||||
0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL);
|
||||
0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, NULL);
|
||||
class_handler->Finish();
|
||||
delete class_handler;
|
||||
}
|
||||
@ -1304,7 +1351,7 @@ TEST_F(Specifications, InlineFunction) {
|
||||
|
||||
StartCU();
|
||||
DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
|
||||
dwarf2reader::DW_TAG_subprogram, "inline-name");
|
||||
dwarf2reader::DW_TAG_subprogram, "inline-name", "");
|
||||
AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
|
||||
dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, "");
|
||||
DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
|
||||
@ -1354,7 +1401,7 @@ TEST_F(Specifications, LongChain) {
|
||||
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
|
||||
"space_A");
|
||||
DeclarationDIE(space_A_handler, 0x2e111126496596e2ULL,
|
||||
dwarf2reader::DW_TAG_namespace, "space_B");
|
||||
dwarf2reader::DW_TAG_namespace, "space_B", "");
|
||||
space_A_handler->Finish();
|
||||
delete space_A_handler;
|
||||
}
|
||||
@ -1367,7 +1414,7 @@ TEST_F(Specifications, LongChain) {
|
||||
= StartNamedDIE(space_B_handler, dwarf2reader::DW_TAG_structure_type,
|
||||
"struct_C");
|
||||
DeclarationDIE(struct_C_handler, 0x20cd423bf2a25a4cULL,
|
||||
dwarf2reader::DW_TAG_structure_type, "struct_D");
|
||||
dwarf2reader::DW_TAG_structure_type, "struct_D", "");
|
||||
struct_C_handler->Finish();
|
||||
delete struct_C_handler;
|
||||
space_B_handler->Finish();
|
||||
@ -1382,7 +1429,7 @@ TEST_F(Specifications, LongChain) {
|
||||
= StartNamedDIE(struct_D_handler, dwarf2reader::DW_TAG_union_type,
|
||||
"union_E");
|
||||
DeclarationDIE(union_E_handler, 0xe25c84805aa58c32ULL,
|
||||
dwarf2reader::DW_TAG_union_type, "union_F");
|
||||
dwarf2reader::DW_TAG_union_type, "union_F", "");
|
||||
union_E_handler->Finish();
|
||||
delete union_E_handler;
|
||||
struct_D_handler->Finish();
|
||||
@ -1397,7 +1444,7 @@ TEST_F(Specifications, LongChain) {
|
||||
= StartNamedDIE(union_F_handler, dwarf2reader::DW_TAG_class_type,
|
||||
"class_G");
|
||||
DeclarationDIE(class_G_handler, 0xb70d960dcc173b6eULL,
|
||||
dwarf2reader::DW_TAG_class_type, "class_H");
|
||||
dwarf2reader::DW_TAG_class_type, "class_H", "");
|
||||
class_G_handler->Finish();
|
||||
delete class_G_handler;
|
||||
union_F_handler->Finish();
|
||||
@ -1409,7 +1456,7 @@ TEST_F(Specifications, LongChain) {
|
||||
= StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
|
||||
0xb70d960dcc173b6eULL);
|
||||
DeclarationDIE(class_H_handler, 0x27ff829e3bf69f37ULL,
|
||||
dwarf2reader::DW_TAG_subprogram, "func_I");
|
||||
dwarf2reader::DW_TAG_subprogram, "func_I", "");
|
||||
class_H_handler->Finish();
|
||||
delete class_H_handler;
|
||||
}
|
||||
@ -1447,7 +1494,7 @@ TEST_F(Specifications, InterCU) {
|
||||
ProcessStrangeAttributes(&root1_handler);
|
||||
ASSERT_TRUE(root1_handler.EndAttributes());
|
||||
DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL,
|
||||
dwarf2reader::DW_TAG_class_type, "class_A");
|
||||
dwarf2reader::DW_TAG_class_type, "class_A", "");
|
||||
root1_handler.Finish();
|
||||
}
|
||||
|
||||
@ -1462,7 +1509,7 @@ TEST_F(Specifications, InterCU) {
|
||||
= StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type,
|
||||
0xb8fbfdd5f0b26fceULL);
|
||||
DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL,
|
||||
dwarf2reader::DW_TAG_subprogram, "member_func_B");
|
||||
dwarf2reader::DW_TAG_subprogram, "member_func_B", "");
|
||||
class_A_handler->Finish();
|
||||
delete class_A_handler;
|
||||
root2_handler.Finish();
|
||||
@ -1494,7 +1541,7 @@ TEST_F(Specifications, BadOffset) {
|
||||
|
||||
StartCU();
|
||||
DeclarationDIE(&root_handler_, 0xefd7f7752c27b7e4ULL,
|
||||
dwarf2reader::DW_TAG_subprogram, "");
|
||||
dwarf2reader::DW_TAG_subprogram, "", "");
|
||||
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
|
||||
0x2be953efa6f9a996ULL, "function",
|
||||
0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL);
|
||||
@ -1506,7 +1553,7 @@ TEST_F(Specifications, FunctionDefinitionHasOwnName) {
|
||||
|
||||
StartCU();
|
||||
DeclarationDIE(&root_handler_, 0xc34ff4786cae78bdULL,
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name");
|
||||
dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
|
||||
DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
|
||||
0xc34ff4786cae78bdULL, "definition-name",
|
||||
0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL);
|
||||
@ -1522,7 +1569,7 @@ TEST_F(Specifications, ClassDefinitionHasOwnName) {
|
||||
|
||||
StartCU();
|
||||
DeclarationDIE(&root_handler_, 0xd0fe467ec2f1a58cULL,
|
||||
dwarf2reader::DW_TAG_class_type, "class-declaration-name");
|
||||
dwarf2reader::DW_TAG_class_type, "class-declaration-name", "");
|
||||
|
||||
dwarf2reader::DIEHandler *class_definition
|
||||
= StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
|
||||
@ -1530,7 +1577,7 @@ TEST_F(Specifications, ClassDefinitionHasOwnName) {
|
||||
ASSERT_TRUE(class_definition);
|
||||
DeclarationDIE(class_definition, 0x6d028229c15623dbULL,
|
||||
dwarf2reader::DW_TAG_subprogram,
|
||||
"function-declaration-name");
|
||||
"function-declaration-name", "");
|
||||
class_definition->Finish();
|
||||
delete class_definition;
|
||||
|
||||
@ -1558,7 +1605,8 @@ TEST_F(Specifications, PreferSpecificationParents) {
|
||||
dwarf2reader::DIEHandler *declaration_class_handler
|
||||
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "declaration-class");
|
||||
DeclarationDIE(declaration_class_handler, 0x9ddb35517455ef7aULL,
|
||||
dwarf2reader::DW_TAG_subprogram, "function-declaration");
|
||||
dwarf2reader::DW_TAG_subprogram, "function-declaration",
|
||||
"");
|
||||
declaration_class_handler->Finish();
|
||||
delete declaration_class_handler;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ extern unsigned my_uint_len(uintmax_t i);
|
||||
|
||||
// Convert an unsigned integer to a string
|
||||
// output: (output) the resulting string is written here. This buffer must be
|
||||
// large enough to hold the resulting string. Call |my_int_len| to get the
|
||||
// large enough to hold the resulting string. Call |my_uint_len| to get the
|
||||
// required length.
|
||||
// i: the unsigned integer to serialise.
|
||||
// i_len: the length of the integer in base 10 (see |my_uint_len|).
|
||||
|
@ -19,6 +19,7 @@ LOCAL_INCLUDES = -I$(srcdir)/../..
|
||||
# The host lib is used for dump_syms, and the target lib for the
|
||||
# crash reporter client. Therefore, we don't need all the srcs in both.
|
||||
CPPSRCS = \
|
||||
arch_utilities.cc \
|
||||
bootstrap_compat.cc \
|
||||
file_id.cc \
|
||||
macho_id.cc \
|
||||
|
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2012, 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.
|
||||
|
||||
#include "common/mac/arch_utilities.h"
|
||||
|
||||
#include <mach-o/arch.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef CPU_TYPE_ARM
|
||||
#define CPU_TYPE_ARM (static_cast<cpu_type_t>(12))
|
||||
#endif // CPU_TYPE_ARM
|
||||
|
||||
#ifndef CPU_SUBTYPE_ARM_V7
|
||||
#define CPU_SUBTYPE_ARM_V7 (static_cast<cpu_subtype_t>(9))
|
||||
#endif // CPU_SUBTYPE_ARM_V7
|
||||
|
||||
#ifndef CPU_SUBTYPE_ARM_V7S
|
||||
#define CPU_SUBTYPE_ARM_V7S (static_cast<cpu_subtype_t>(11))
|
||||
#endif // CPU_SUBTYPE_ARM_V7S
|
||||
|
||||
namespace {
|
||||
|
||||
const NXArchInfo* ArchInfo_armv7s() {
|
||||
NXArchInfo* armv7s = new NXArchInfo;
|
||||
*armv7s = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
|
||||
CPU_SUBTYPE_ARM_V7);
|
||||
armv7s->name = "armv7s";
|
||||
armv7s->cpusubtype = CPU_SUBTYPE_ARM_V7S;
|
||||
armv7s->description = "arm v7s";
|
||||
return armv7s;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name) {
|
||||
// TODO: Remove this when the OS knows about armv7s.
|
||||
if (!strcmp("armv7s", arch_name))
|
||||
return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S);
|
||||
return NXGetArchInfoFromName(arch_name);
|
||||
}
|
||||
|
||||
const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype) {
|
||||
// TODO: Remove this when the OS knows about armv7s.
|
||||
if (cpu_type == CPU_TYPE_ARM && cpu_subtype == CPU_SUBTYPE_ARM_V7S) {
|
||||
static const NXArchInfo* armv7s = ArchInfo_armv7s();
|
||||
return armv7s;
|
||||
}
|
||||
return NXGetArchInfoFromCpuType(cpu_type, cpu_subtype);
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2012, 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.
|
||||
|
||||
// arch_utilities.h: Utilities for architecture introspection for Mac platform.
|
||||
|
||||
#ifndef COMMON_MAC_ARCH_UTILITIES_H__
|
||||
#define COMMON_MAC_ARCH_UTILITIES_H__
|
||||
|
||||
#include <mach-o/arch.h>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Custom implementation of |NXGetArchInfoFromName| and
|
||||
// |NXGetArchInfoFromCpuType| that handle newer CPU on older OSes.
|
||||
const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name);
|
||||
const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_MAC_ARCH_UTILITIES_H__
|
@ -50,6 +50,7 @@
|
||||
#include "common/dwarf_cu_to_module.h"
|
||||
#include "common/dwarf_line_to_module.h"
|
||||
#include "common/mac/file_id.h"
|
||||
#include "common/mac/arch_utilities.h"
|
||||
#include "common/mac/macho_reader.h"
|
||||
#include "common/module.h"
|
||||
#include "common/stabs_reader.h"
|
||||
@ -191,7 +192,8 @@ bool DumpSymbols::SetArchitecture(cpu_type_t cpu_type,
|
||||
|
||||
bool DumpSymbols::SetArchitecture(const std::string &arch_name) {
|
||||
bool arch_set = false;
|
||||
const NXArchInfo *arch_info = NXGetArchInfoFromName(arch_name.c_str());
|
||||
const NXArchInfo *arch_info =
|
||||
google_breakpad::BreakpadGetArchInfoFromName(arch_name.c_str());
|
||||
if (arch_info) {
|
||||
arch_set = SetArchitecture(arch_info->cputype, arch_info->cpusubtype);
|
||||
}
|
||||
@ -202,7 +204,8 @@ string DumpSymbols::Identifier() {
|
||||
FileID file_id([object_filename_ fileSystemRepresentation]);
|
||||
unsigned char identifier_bytes[16];
|
||||
cpu_type_t cpu_type = selected_object_file_->cputype;
|
||||
if (!file_id.MachoIdentifier(cpu_type, identifier_bytes)) {
|
||||
cpu_subtype_t cpu_subtype = selected_object_file_->cpusubtype;
|
||||
if (!file_id.MachoIdentifier(cpu_type, cpu_subtype, identifier_bytes)) {
|
||||
fprintf(stderr, "Unable to calculate UUID of mach-o binary %s!\n",
|
||||
[object_filename_ fileSystemRepresentation]);
|
||||
return "";
|
||||
@ -312,9 +315,8 @@ bool DumpSymbols::ReadCFI(google_breakpad::Module *module,
|
||||
register_names = DwarfCFIToModule::RegisterNames::ARM();
|
||||
break;
|
||||
default: {
|
||||
const NXArchInfo *arch =
|
||||
NXGetArchInfoFromCpuType(macho_reader.cpu_type(),
|
||||
macho_reader.cpu_subtype());
|
||||
const NXArchInfo *arch = google_breakpad::BreakpadGetArchInfoFromCpuType(
|
||||
macho_reader.cpu_type(), macho_reader.cpu_subtype());
|
||||
fprintf(stderr, "%s: cannot convert DWARF call frame information for ",
|
||||
selected_object_name_.c_str());
|
||||
if (arch)
|
||||
@ -446,9 +448,9 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream, bool cfi) {
|
||||
|
||||
// Find the name of the selected file's architecture, to appear in
|
||||
// the MODULE record and in error messages.
|
||||
const NXArchInfo *selected_arch_info
|
||||
= NXGetArchInfoFromCpuType(selected_object_file_->cputype,
|
||||
selected_object_file_->cpusubtype);
|
||||
const NXArchInfo *selected_arch_info =
|
||||
google_breakpad::BreakpadGetArchInfoFromCpuType(
|
||||
selected_object_file_->cputype, selected_object_file_->cpusubtype);
|
||||
|
||||
const char *selected_arch_name = selected_arch_info->name;
|
||||
if (strcmp(selected_arch_name, "i386") == 0)
|
||||
|
@ -70,13 +70,15 @@ bool FileID::FileIdentifier(unsigned char identifier[16]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileID::MachoIdentifier(int cpu_type, unsigned char identifier[16]) {
|
||||
bool FileID::MachoIdentifier(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
unsigned char identifier[16]) {
|
||||
MachoID macho(path_);
|
||||
|
||||
if (macho.UUIDCommand(cpu_type, identifier))
|
||||
if (macho.UUIDCommand(cpu_type, cpu_subtype, identifier))
|
||||
return true;
|
||||
|
||||
return macho.MD5(cpu_type, identifier);
|
||||
return macho.MD5(cpu_type, cpu_subtype, identifier);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define COMMON_MAC_FILE_ID_H__
|
||||
|
||||
#include <limits.h>
|
||||
#include <mach/machine.h>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
@ -50,15 +51,18 @@ class FileID {
|
||||
bool FileIdentifier(unsigned char identifier[16]);
|
||||
|
||||
// Treat the file as a mach-o file that will contain one or more archicture.
|
||||
// Accepted values for |cpu_type| (e.g., CPU_TYPE_X86 or CPU_TYPE_POWERPC)
|
||||
// are listed in /usr/include/mach/machine.h.
|
||||
// If |cpu_type| is 0, then the native cpu type is used.
|
||||
// Returns false if opening the file failed or if the |cpu_type| is not
|
||||
// present in the file.
|
||||
// Accepted values for |cpu_type| and |cpu_subtype| (e.g., CPU_TYPE_X86 or
|
||||
// CPU_TYPE_POWERPC) are listed in /usr/include/mach/machine.h.
|
||||
// If |cpu_type| is 0, then the native cpu type is used. If |cpu_subtype| is
|
||||
// CPU_SUBTYPE_MULTIPLE, the match is only done on |cpu_type|.
|
||||
// Returns false if opening the file failed or if the |cpu_type|/|cpu_subtype|
|
||||
// is not present in the file.
|
||||
// Return the unique identifier in |identifier|.
|
||||
// The current implementation will look for the (in order of priority):
|
||||
// LC_UUID, LC_ID_DYLIB, or MD5 hash of the given |cpu_type|.
|
||||
bool MachoIdentifier(int cpu_type, unsigned char identifier[16]);
|
||||
bool MachoIdentifier(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
unsigned char identifier[16]);
|
||||
|
||||
// Convert the |identifier| data to a NULL terminated string. The string will
|
||||
// be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE).
|
||||
@ -75,4 +79,3 @@ class FileID {
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_MAC_FILE_ID_H__
|
||||
|
||||
|
@ -153,10 +153,12 @@ void MachoID::Update(MachoWalker *walker, off_t offset, size_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) {
|
||||
bool MachoID::UUIDCommand(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
unsigned char bytes[16]) {
|
||||
struct breakpad_uuid_command uuid_cmd;
|
||||
uuid_cmd.cmd = 0;
|
||||
if (!WalkHeader(cpu_type, UUIDWalkerCB, &uuid_cmd))
|
||||
if (!WalkHeader(cpu_type, cpu_subtype, UUIDWalkerCB, &uuid_cmd))
|
||||
return false;
|
||||
|
||||
// If we found the command, we'll have initialized the uuid_command
|
||||
@ -169,10 +171,12 @@ bool MachoID::UUIDCommand(int cpu_type, unsigned char bytes[16]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachoID::IDCommand(int cpu_type, unsigned char identifier[16]) {
|
||||
bool MachoID::IDCommand(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
unsigned char identifier[16]) {
|
||||
struct dylib_command dylib_cmd;
|
||||
dylib_cmd.cmd = 0;
|
||||
if (!WalkHeader(cpu_type, IDWalkerCB, &dylib_cmd))
|
||||
if (!WalkHeader(cpu_type, cpu_subtype, IDWalkerCB, &dylib_cmd))
|
||||
return false;
|
||||
|
||||
// If we found the command, we'll have initialized the dylib_command
|
||||
@ -210,37 +214,38 @@ bool MachoID::IDCommand(int cpu_type, unsigned char identifier[16]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t MachoID::Adler32(int cpu_type) {
|
||||
uint32_t MachoID::Adler32(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
|
||||
update_function_ = &MachoID::UpdateCRC;
|
||||
crc_ = 0;
|
||||
|
||||
if (!WalkHeader(cpu_type, WalkerCB, this))
|
||||
if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this))
|
||||
return 0;
|
||||
|
||||
return crc_;
|
||||
}
|
||||
|
||||
bool MachoID::MD5(int cpu_type, unsigned char identifier[16]) {
|
||||
bool MachoID::MD5(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype, unsigned char identifier[16]) {
|
||||
update_function_ = &MachoID::UpdateMD5;
|
||||
|
||||
MD5Init(&md5_context_);
|
||||
|
||||
if (!WalkHeader(cpu_type, WalkerCB, this))
|
||||
if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this))
|
||||
return false;
|
||||
|
||||
MD5Final(identifier, &md5_context_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MachoID::WalkHeader(int cpu_type,
|
||||
bool MachoID::WalkHeader(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
MachoWalker::LoadCommandCallback callback,
|
||||
void *context) {
|
||||
if (memory_) {
|
||||
MachoWalker walker(memory_, memory_size_, callback, context);
|
||||
return walker.WalkHeader(cpu_type);
|
||||
return walker.WalkHeader(cpu_type, cpu_subtype);
|
||||
} else {
|
||||
MachoWalker walker(path_, callback, context);
|
||||
return walker.WalkHeader(cpu_type);
|
||||
return walker.WalkHeader(cpu_type, cpu_subtype);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define COMMON_MAC_MACHO_ID_H__
|
||||
|
||||
#include <limits.h>
|
||||
#include <mach/machine.h>
|
||||
#include <mach-o/loader.h>
|
||||
|
||||
#include "common/mac/macho_walker.h"
|
||||
@ -48,22 +49,32 @@ class MachoID {
|
||||
MachoID(const char *path, void *memory, size_t size);
|
||||
~MachoID();
|
||||
|
||||
// For the given |cpu_type|, return a UUID from the LC_UUID command.
|
||||
// For the given |cpu_type| and |cpu_subtype|, return a UUID from the LC_UUID
|
||||
// command.
|
||||
// Return false if there isn't a LC_UUID command.
|
||||
bool UUIDCommand(int cpu_type, unsigned char identifier[16]);
|
||||
bool UUIDCommand(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
unsigned char identifier[16]);
|
||||
|
||||
// For the given |cpu_type|, return a UUID from the LC_ID_DYLIB command.
|
||||
// For the given |cpu_type| and |cpu_subtype|, return a UUID from the
|
||||
// LC_ID_DYLIB command.
|
||||
// Return false if there isn't a LC_ID_DYLIB command.
|
||||
bool IDCommand(int cpu_type, unsigned char identifier[16]);
|
||||
bool IDCommand(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
unsigned char identifier[16]);
|
||||
|
||||
// For the given |cpu_type|, return the Adler32 CRC for the mach-o data
|
||||
// segment(s).
|
||||
// For the given |cpu_type| and |cpu_subtype|, return the Adler32 CRC for the
|
||||
// mach-o data segment(s).
|
||||
// Return 0 on error (e.g., if the file is not a mach-o file)
|
||||
uint32_t Adler32(int cpu_type);
|
||||
uint32_t Adler32(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype);
|
||||
|
||||
// For the given |cpu_type|, return the MD5 for the mach-o data segment(s).
|
||||
// For the given |cpu_type|, and |cpu_subtype| return the MD5 for the mach-o
|
||||
// data segment(s).
|
||||
// Return true on success, false otherwise
|
||||
bool MD5(int cpu_type, unsigned char identifier[16]);
|
||||
bool MD5(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
unsigned char identifier[16]);
|
||||
|
||||
private:
|
||||
// Signature of class member function to be called with data read from file
|
||||
@ -81,8 +92,8 @@ class MachoID {
|
||||
void Update(MachoWalker *walker, off_t offset, size_t size);
|
||||
|
||||
// Factory for the MachoWalker
|
||||
bool WalkHeader(int cpu_type, MachoWalker::LoadCommandCallback callback,
|
||||
void *context);
|
||||
bool WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype,
|
||||
MachoWalker::LoadCommandCallback callback, void *context);
|
||||
|
||||
// The callback from the MachoWalker for CRC and MD5
|
||||
static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
|
||||
|
@ -79,21 +79,18 @@ MachoWalker::~MachoWalker() {
|
||||
close(file_);
|
||||
}
|
||||
|
||||
int MachoWalker::ValidateCPUType(int cpu_type) {
|
||||
// If the user didn't specify, use the local architecture.
|
||||
bool MachoWalker::WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
|
||||
cpu_type_t valid_cpu_type = cpu_type;
|
||||
cpu_subtype_t valid_cpu_subtype = cpu_subtype;
|
||||
// if |cpu_type| is 0, use the native cpu type.
|
||||
if (cpu_type == 0) {
|
||||
const NXArchInfo *arch = NXGetLocalArchInfo();
|
||||
assert(arch);
|
||||
cpu_type = arch->cputype;
|
||||
valid_cpu_type = arch->cputype;
|
||||
valid_cpu_subtype = CPU_SUBTYPE_MULTIPLE;
|
||||
}
|
||||
|
||||
return cpu_type;
|
||||
}
|
||||
|
||||
bool MachoWalker::WalkHeader(int cpu_type) {
|
||||
int valid_cpu_type = ValidateCPUType(cpu_type);
|
||||
off_t offset;
|
||||
if (FindHeader(valid_cpu_type, offset)) {
|
||||
if (FindHeader(valid_cpu_type, valid_cpu_subtype, offset)) {
|
||||
if (cpu_type & CPU_ARCH_ABI64)
|
||||
return WalkHeader64AtOffset(offset);
|
||||
|
||||
@ -131,8 +128,9 @@ bool MachoWalker::CurrentHeader(struct mach_header_64 *header, off_t *offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachoWalker::FindHeader(int cpu_type, off_t &offset) {
|
||||
int valid_cpu_type = ValidateCPUType(cpu_type);
|
||||
bool MachoWalker::FindHeader(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
off_t &offset) {
|
||||
// Read the magic bytes that's common amongst all mach-o files
|
||||
uint32_t magic;
|
||||
if (!ReadBytes(&magic, sizeof(magic), 0))
|
||||
@ -153,15 +151,18 @@ bool MachoWalker::FindHeader(int cpu_type, off_t &offset) {
|
||||
if (!is_fat) {
|
||||
// If we don't have a fat header, check if the cpu type matches the single
|
||||
// header
|
||||
cpu_type_t header_cpu_type;
|
||||
if (!ReadBytes(&header_cpu_type, sizeof(header_cpu_type), offset))
|
||||
struct mach_header header;
|
||||
if (!ReadBytes(&header, sizeof(header), 0))
|
||||
return false;
|
||||
|
||||
if (magic == MH_CIGAM || magic == MH_CIGAM_64)
|
||||
header_cpu_type = ByteSwap(header_cpu_type);
|
||||
swap_mach_header(&header, NXHostByteOrder());
|
||||
|
||||
if (valid_cpu_type != header_cpu_type)
|
||||
if (cpu_type != header.cputype ||
|
||||
(cpu_subtype != CPU_SUBTYPE_MULTIPLE &&
|
||||
cpu_subtype != header.cpusubtype)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
return true;
|
||||
@ -186,7 +187,9 @@ bool MachoWalker::FindHeader(int cpu_type, off_t &offset) {
|
||||
if (NXHostByteOrder() != NX_BigEndian)
|
||||
swap_fat_arch(&arch, 1, NXHostByteOrder());
|
||||
|
||||
if (arch.cputype == valid_cpu_type) {
|
||||
if (arch.cputype == cpu_type &&
|
||||
(cpu_subtype == CPU_SUBTYPE_MULTIPLE ||
|
||||
arch.cpusubtype == cpu_subtype)) {
|
||||
offset = arch.offset;
|
||||
return true;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#ifndef COMMON_MAC_MACHO_WALKER_H__
|
||||
#define COMMON_MAC_MACHO_WALKER_H__
|
||||
|
||||
#include <mach/machine.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@ -56,16 +57,14 @@ class MachoWalker {
|
||||
void *context);
|
||||
~MachoWalker();
|
||||
|
||||
// Begin walking the header for |cpu_type|. If |cpu_type| is 0, then the
|
||||
// native cpu type is used. Otherwise, accepted values are listed in
|
||||
// /usr/include/mach/machine.h (e.g., CPU_TYPE_X86 or CPU_TYPE_POWERPC).
|
||||
// Returns false if opening the file failed or if the |cpu_type| is not
|
||||
// present in the file.
|
||||
bool WalkHeader(int cpu_type);
|
||||
|
||||
// Locate (if any) the header offset for |cpu_type| and return in |offset|.
|
||||
// Return true if found, false otherwise.
|
||||
bool FindHeader(int cpu_type, off_t &offset);
|
||||
// Begin walking the header for |cpu_type| and |cpu_subtype|. If |cpu_type|
|
||||
// is 0, then the native cpu type is used. Otherwise, accepted values are
|
||||
// listed in /usr/include/mach/machine.h (e.g., CPU_TYPE_X86 or
|
||||
// CPU_TYPE_POWERPC). If |cpu_subtype| is CPU_SUBTYPE_MULTIPLE, the match is
|
||||
// only done on |cpu_type|.
|
||||
// Returns false if opening the file failed or if the |cpu_type|/|cpu_subtype|
|
||||
// is not present in the file.
|
||||
bool WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
|
||||
|
||||
// Read |size| bytes from the opened file at |offset| into |buffer|
|
||||
bool ReadBytes(void *buffer, size_t size, off_t offset);
|
||||
@ -74,8 +73,11 @@ class MachoWalker {
|
||||
bool CurrentHeader(struct mach_header_64 *header, off_t *offset);
|
||||
|
||||
private:
|
||||
// Validate the |cpu_type|
|
||||
int ValidateCPUType(int cpu_type);
|
||||
// Locate (if any) the header offset for |cpu_type| and return in |offset|.
|
||||
// Return true if found, false otherwise.
|
||||
bool FindHeader(cpu_type_t cpu_type,
|
||||
cpu_subtype_t cpu_subtype,
|
||||
off_t &offset);
|
||||
|
||||
// Process an individual header starting at |offset| from the start of the
|
||||
// file. Return true if successful, false otherwise.
|
||||
|
@ -115,7 +115,7 @@ void UTF32ToUTF16Char(wchar_t in, u_int16_t out[2]) {
|
||||
}
|
||||
|
||||
static inline u_int16_t Swap(u_int16_t value) {
|
||||
return (value >> 8) | static_cast<uint16_t>(value << 8);
|
||||
return (value >> 8) | static_cast<u_int16_t>(value << 8);
|
||||
}
|
||||
|
||||
string UTF16ToUTF8(const vector<u_int16_t> &in, bool swap) {
|
||||
|
@ -80,7 +80,8 @@ typedef enum {
|
||||
MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGSYS = 31, /* Bad system call */
|
||||
MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED = -1 /* No exception, dump requested */
|
||||
MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED = 0xFFFFFFFF /* No exception,
|
||||
dump requested. */
|
||||
} MDExceptionCodeLinux;
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ */
|
||||
|
@ -93,6 +93,16 @@ typedef enum {
|
||||
/* Custom values */
|
||||
MD_EXCEPTION_CODE_MAC_NS_EXCEPTION = 0xDEADC0DE, /* uncaught NSException */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_ACCESS on arm */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN = 0x0101, /* EXC_ARM_DA_ALIGN */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG = 0x0102, /* EXC_ARM_DA_DEBUG */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on arm */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED = 1, /* EXC_ARM_UNDEFINED */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BREAKPOINT on arm */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT = 1, /* EXC_ARM_BREAKPOINT */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101,
|
||||
/* EXC_PPC_VM_PROT_READ */
|
||||
|
@ -484,26 +484,61 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, u_int64_t *address) {
|
||||
case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR:
|
||||
reason.append("KERN_MEMORY_ERROR");
|
||||
break;
|
||||
// These are ppc only but shouldn't be a problem as they're
|
||||
// unused on x86
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ:
|
||||
reason.append("EXC_PPC_VM_PROT_READ");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE:
|
||||
reason.append("EXC_PPC_BADSPACE");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED:
|
||||
reason.append("EXC_PPC_UNALIGNED");
|
||||
break;
|
||||
default:
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
// arm and ppc overlap
|
||||
if (raw_system_info->processor_architecture ==
|
||||
MD_CPU_ARCHITECTURE_ARM) {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
|
||||
reason.append("EXC_ARM_DA_ALIGN");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
|
||||
reason.append("EXC_ARM_DA_DEBUG");
|
||||
break;
|
||||
default:
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
break;
|
||||
}
|
||||
} else if (raw_system_info->processor_architecture ==
|
||||
MD_CPU_ARCHITECTURE_PPC) {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ:
|
||||
reason.append("EXC_PPC_VM_PROT_READ");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE:
|
||||
reason.append("EXC_PPC_BADSPACE");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED:
|
||||
reason.append("EXC_PPC_UNALIGNED");
|
||||
break;
|
||||
default:
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MD_EXCEPTION_MAC_BAD_INSTRUCTION:
|
||||
reason = "EXC_BAD_INSTRUCTION / ";
|
||||
switch (raw_system_info->processor_architecture) {
|
||||
case MD_CPU_ARCHITECTURE_ARM: {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED:
|
||||
reason.append("EXC_ARM_UNDEFINED");
|
||||
break;
|
||||
default:
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MD_CPU_ARCHITECTURE_PPC: {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL:
|
||||
@ -671,6 +706,24 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, u_int64_t *address) {
|
||||
case MD_EXCEPTION_MAC_BREAKPOINT:
|
||||
reason = "EXC_BREAKPOINT / ";
|
||||
switch (raw_system_info->processor_architecture) {
|
||||
case MD_CPU_ARCHITECTURE_ARM: {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN:
|
||||
reason.append("EXC_ARM_DA_ALIGN");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG:
|
||||
reason.append("EXC_ARM_DA_DEBUG");
|
||||
break;
|
||||
case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT:
|
||||
reason.append("EXC_ARM_BREAKPOINT");
|
||||
break;
|
||||
default:
|
||||
reason.append(flags_string);
|
||||
BPLOG(INFO) << "Unknown exception reason " << reason;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MD_CPU_ARCHITECTURE_PPC: {
|
||||
switch (exception_flags) {
|
||||
case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT:
|
||||
|
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
162F64FE161C5ECB00CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */; };
|
||||
4D2C721B126F9ACC00B43EAF /* source_line_resolver_base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */; };
|
||||
4D2C721F126F9ADE00B43EAF /* exploitability.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721E126F9ADE00B43EAF /* exploitability.cc */; };
|
||||
4D2C7223126F9AF900B43EAF /* exploitability_win.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7222126F9AF900B43EAF /* exploitability_win.cc */; };
|
||||
@ -66,6 +67,8 @@
|
||||
/* Begin PBXFileReference section */
|
||||
08FB7796FE84155DC02AAC07 /* crash_report.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = crash_report.mm; sourceTree = "<group>"; };
|
||||
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../../common/mac/arch_utilities.cc; sourceTree = "<group>"; };
|
||||
162F64FD161C5ECB00CD68D5 /* arch_utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../../common/mac/arch_utilities.h; sourceTree = "<group>"; };
|
||||
4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = source_line_resolver_base.cc; path = ../../../processor/source_line_resolver_base.cc; sourceTree = SOURCE_ROOT; };
|
||||
4D2C721E126F9ADE00B43EAF /* exploitability.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability.cc; path = ../../../processor/exploitability.cc; sourceTree = SOURCE_ROOT; };
|
||||
4D2C7222126F9AF900B43EAF /* exploitability_win.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability_win.cc; path = ../../../processor/exploitability_win.cc; sourceTree = SOURCE_ROOT; };
|
||||
@ -183,6 +186,8 @@
|
||||
8B3102DA11F0D65600FCF3E4 /* BreakpadDebug.xcconfig */,
|
||||
8B3102DB11F0D65600FCF3E4 /* BreakpadRelease.xcconfig */,
|
||||
F9C7ECE10E8ABC7F00E953AD /* DWARF */,
|
||||
162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */,
|
||||
162F64FD161C5ECB00CD68D5 /* arch_utilities.h */,
|
||||
5578003E0BE1F28500EC23E0 /* macho_utilities.cc */,
|
||||
5578003F0BE1F28500EC23E0 /* macho_utilities.h */,
|
||||
8B31FF7211F0C6E000FCF3E4 /* macho_reader.cc */,
|
||||
@ -410,6 +415,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
162F64FE161C5ECB00CD68D5 /* arch_utilities.cc in Sources */,
|
||||
8DD76F9A0486AA7600D96B5E /* crash_report.mm in Sources */,
|
||||
9BDF172C0B1B8B2400F8391B /* call_stack.cc in Sources */,
|
||||
9BDF172D0B1B8B2400F8391B /* minidump_processor.cc in Sources */,
|
||||
|
@ -33,6 +33,8 @@
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
|
||||
162F6500161C5F2200CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
|
||||
4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D72CAF413DFBAC2006CABE3 /* md5.cc */; };
|
||||
B84A91F8116CF78F006C210E /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
|
||||
B84A91FB116CF7AF006C210E /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
|
||||
@ -270,6 +272,8 @@
|
||||
/* Begin PBXFileReference section */
|
||||
08FB7796FE84155DC02AAC07 /* dump_syms.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.mm; path = ../../../common/mac/dump_syms.mm; sourceTree = "<group>"; };
|
||||
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
162F64F8161C591500CD68D5 /* arch_utilities.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../../common/mac/arch_utilities.cc; sourceTree = "<group>"; };
|
||||
162F64F9161C591500CD68D5 /* arch_utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../../common/mac/arch_utilities.h; sourceTree = "<group>"; };
|
||||
4D72CAF413DFBAC2006CABE3 /* md5.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = md5.cc; path = ../../../common/md5.cc; sourceTree = SOURCE_ROOT; };
|
||||
557800890BE1F3AB00EC23E0 /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../../common/mac/macho_utilities.cc; sourceTree = SOURCE_ROOT; };
|
||||
5578008A0BE1F3AB00EC23E0 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; };
|
||||
@ -481,6 +485,8 @@
|
||||
B89E0E6C1166569700DD08C9 /* MACHO */,
|
||||
B88FAE3811666A1700407530 /* STABS */,
|
||||
B88FAE1C11665FFD00407530 /* MODULE */,
|
||||
162F64F8161C591500CD68D5 /* arch_utilities.cc */,
|
||||
162F64F9161C591500CD68D5 /* arch_utilities.h */,
|
||||
B88FAE1D1166603300407530 /* byte_cursor.h */,
|
||||
B88FB0D4116CEC0600407530 /* byte_cursor_unittest.cc */,
|
||||
B8E8CA0C1156C854009E61B2 /* byteswap.h */,
|
||||
@ -1044,6 +1050,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
162F6500161C5F2200CD68D5 /* arch_utilities.cc in Sources */,
|
||||
B89E0E781166576C00DD08C9 /* macho_reader.cc in Sources */,
|
||||
B89E0E7A1166576C00DD08C9 /* macho_dump.cc in Sources */,
|
||||
);
|
||||
@ -1062,6 +1069,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */,
|
||||
B88FAE2C1166606200407530 /* macho_reader.cc in Sources */,
|
||||
B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */,
|
||||
B8C5B5181166534700D34F4E /* bytereader.cc in Sources */,
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "common/mac/dump_syms.h"
|
||||
#include "common/mac/arch_utilities.h"
|
||||
#include "common/mac/macho_utilities.h"
|
||||
|
||||
using google_breakpad::DumpSymbols;
|
||||
@ -73,7 +74,8 @@ static bool Start(const Options &options) {
|
||||
for (size_t i = 0; i < available_size; i++) {
|
||||
const struct fat_arch *arch = &available[i];
|
||||
const NXArchInfo *arch_info =
|
||||
NXGetArchInfoFromCpuType(arch->cputype, arch->cpusubtype);
|
||||
google_breakpad::BreakpadGetArchInfoFromCpuType(
|
||||
arch->cputype, arch->cpusubtype);
|
||||
if (arch_info)
|
||||
fprintf(stderr, "%s (%s)\n", arch_info->name, arch_info->description);
|
||||
else
|
||||
@ -107,7 +109,8 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
|
||||
while ((ch = getopt(argc, (char * const *)argv, "a:ch?")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a': {
|
||||
const NXArchInfo *arch_info = NXGetArchInfoFromName(optarg);
|
||||
const NXArchInfo *arch_info =
|
||||
google_breakpad::BreakpadGetArchInfoFromName(optarg);
|
||||
if (!arch_info) {
|
||||
fprintf(stderr, "%s: Invalid architecture: %s\n", argv[0], optarg);
|
||||
Usage(argc, argv);
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "common/byte_cursor.h"
|
||||
#include "common/mac/arch_utilities.h"
|
||||
#include "common/mac/macho_reader.h"
|
||||
|
||||
using google_breakpad::ByteBuffer;
|
||||
@ -142,8 +143,9 @@ void DumpFile(const char *filename) {
|
||||
printf(" object file count: %ld\n", object_files_size);
|
||||
for (size_t i = 0; i < object_files_size; i++) {
|
||||
const struct fat_arch &file = object_files[i];
|
||||
const NXArchInfo *fat_arch_info
|
||||
= NXGetArchInfoFromCpuType(file.cputype, file.cpusubtype);
|
||||
const NXArchInfo *fat_arch_info =
|
||||
google_breakpad::BreakpadGetArchInfoFromCpuType(
|
||||
file.cputype, file.cpusubtype);
|
||||
printf("\n object file %ld:\n"
|
||||
" fat header:\n:"
|
||||
" CPU type: %s (%s)\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user