12 Commits

Author SHA1 Message Date
primiano@chromium.org
c86860f5e2 Merge trunk r1454 to the chrome_43 branch.
> Fix signal propagation logic for Linux/Android exception handler.
>
> The current code is relying on info->si_pid to figure out whether
> the exception handler was triggered by a signal coming from the kernel
> (that will re-trigger until the cause that triggered the signal has
> been cleared) or from user-space e.g., kill -SIGNAL pid, which will NOT
> automatically re-trigger in the next signal handler in the chain.
> While the intentions are good (manually re-triggering user-space
> signals), the current implementation mistakenly looks at the si_pid
> field in siginfo_t, assuming that it is coming from the kernel if
> si_pid == 0.
> This is wrong. siginfo_t, in fact, is a union and si_pid is meaningful
> only for userspace signals. For signals originated by the kernel,
> instead, si_pid overlaps with si_addr (the faulting address).
> As a matter of facts, the current implementation is mistakenly
> re-triggering the signal using tgkill for most of the kernel-space
> signals (unless the fault address is exactly 0x0).
> This is not completelly correct for the case of SIGSEGV/SIGBUS. The
> next handler in the chain will stil see the signal, but the |siginfo|
> and the |context| arguments of the handler will be meaningless
> (retriggering a signal with tgkill doesn't preserve them).
> Therefore, if the next handler in the chain expects those arguments
> to be set, it will fail.
> Concretelly, this is causing problems to WebView. In some rare
> circumstances, the next handler in the chain is a user-space runtime
> which does SIGSEGV handling to implement speculative null pointer
> managed exceptions (see as an example
> http://www.mono-project.com/docs/advanced/runtime/docs/exception-handling/)
>
> The fix herein proposed consists in using the si_code (see SI_FROMUSER
> macros) to determine whether a signal is coming form the kernel
> (and therefore just re-establish the next signal handler) or from
> userspace (and use the tgkill logic).
>
> Repro case:
> This issue is visible in Chrome for Android with this simple repro case:
> - Add a non-null pointer dereference in the codebase:
>   *((volatile int*)0xbeef) = 42
> Without this change: the next handler (the libc trap) prints:
>   F/libc  (  595): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x487
>   where 0x487 is actually the PID of the process (which is wrong).
> With this change: the next handler prints:
>   F/libc  (  595): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xbeef
>   which is the correct answer.
>
> BUG=chromium:481937
> R=mark@chromium.org
>
> Review URL: https://breakpad.appspot.com/6844002

BUG=chromium:481937

git-svn-id: http://google-breakpad.googlecode.com/svn/branches/chrome_43@1457 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-05-19 08:01:12 +00:00
cjhopman@chromium.org
ef04c53283 Merge 1447 "Fix call to rt_sigaction"
> Fix call to rt_sigaction
> 
> Despite the fact that many places imply that sigaction and rt_sigaction
> are essentially the same, rt_sigaction's signature is actually
> different-- it takes the size of the kernel's sigset_t as an extra argument.
> 
> BUG=473973
> 

TBR=cjhopman@chromium.org

Review URL: https://breakpad.appspot.com/6834002

git-svn-id: http://google-breakpad.googlecode.com/svn/branches/chrome_43@1449 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-15 23:13:38 +00:00
mark@chromium.org
897c1bb4d6 Merge trunk r1443 to the chrome_43 branch.
Use __NR_rt_sigaction instead of __NR_sigaction

__NR_sigaction is not defined on arm64/x64/etc (or rather, it's defined
in unistd-32.h instead of unistd.h).

Patch by Chris Hopman <cjhopman@chromium.org>
Review URL: https://breakpad.appspot.com/10724002/


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/chrome_43@1445 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-14 00:01:05 +00:00
mark@chromium.org
7ac616335d Merge trunk r1438 to the chrome_43 branch.
Workaround Android sigaction bug

On Android L+, signal and sigaction symbols are provided by libsigchain
that override the system's versions. There is a bug in these functions
where they essentially ignore requests to install SIG_DFL.

Workaround this issue by explicitly performing a syscall to
__NR_rt_sigaction to install SIG_DFL on Android.

BUG=473973

Patch by Chris Hopman <cjhopman@chromium.org>
Review URL: https://breakpad.appspot.com/1804002/


git-svn-id: http://google-breakpad.googlecode.com/svn/branches/chrome_43@1440 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-10 18:03:12 +00:00
mark@chromium.org
5b47d9d474 Branch at trunk r1434 for Chrome 43.0.2357
git-svn-id: http://google-breakpad.googlecode.com/svn/branches/chrome_43@1437 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-10 17:54:42 +00:00
primiano@chromium.org
622588226d Fix compatibility with Android NDK r10d.
This is a reland of the previous CL (r1433). r1433 did not achieve what
intended and failed the x86_64 build of Chrome with NDK r10c.
The workaround logic in this CL is identical to r1433, but the #define
magic is applied in a more appropriate proper place this time. Turns
out Breakpad already has an Android compatibility layer, which is
common/android/include. Piggybacking the fix there.

BUG=breakpad:642
R=fdegans@chromium.org, rmcilroy@chromium.org

Review URL: https://breakpad.appspot.com/3794002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1434 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-03-16 14:12:20 +00:00
primiano@chromium.org
be470f3a11 Make breakpad compatible with Android NDK r10d.
r1397 did introduce a workaround to deal with a typo in sys/user.h
in the Android NDK. The typo has been fixed in [1]. However, breakpad
cannot just switch to the fixed version as this would require atomic
rolls of Breakpad and NDK in chromium, which would make reverts hard
to handle.
This change introduces an inelegant yet functional hack which makes
breakpad compatible with both versions of the NDK, with and without
the typo. It can be reverted once Chrome has stably rolled to NDK
r10d.

[1] https://android.googlesource.com/platform/bionic/+/f485547b

BUG=breakpad:642
R=fdegans@chromium.org, rmcilroy@chromium.org

Review URL: https://breakpad.appspot.com/7814002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1433 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-03-10 20:09:06 +00:00
primiano@chromium.org
eb81077a4f Microdump writer: stop using new/malloc in compromised context
A recent change in the client-side microdump write (r1404) ended up
introducing a call to new() to instantiate the line buffer that
microdump uses to dump its lines. new/malloc is a luxury we cannot
afford in a compromised context.
This change switches the line buffer to be backed by the dumper
page allocator, which on Linux/Android ends up requesting pages
via mmap.
Also, the microdump write bails out without crashing if the page
allocator failed (crash during severe OOM).

BUG=640

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1432 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-03-10 20:06:04 +00:00
ted.mielczarek@gmail.com
8ba5453573 Fix Windows dump_syms x64 linking
The dia_sdk GYP target points at the x86 diaguids.lib, it needs to
point at the x64 one for x64 builds.
R=mark at https://breakpad.appspot.com/9784002/

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1431 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-03-06 20:12:00 +00:00
ted.mielczarek@gmail.com
b0fbff302a Formatting tweak for https://breakpad.appspot.com/9774002, add more newlines
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1430 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-27 13:40:41 +00:00
hashimoto@chromium.org
43b75f42a7 Add stack contents output functionality to minidump_stackwalk
This feature is enabled only when "-s" is provided as a commandline option.

minidump_stackwalk.cc:
 - Add a new commandline option "-s" to output stack contents.
 - Instantiate Minidump object in PrintMinidumpProcess() to keep it alive longer so that accessing process_state.thread_memory_regions() in stackwalk_common.cc doesn't result in use-after-free.

stackwalk_common.cc:
 - Add a new function PrintStackContents() to output stack contents.

R=mark@chromium.org

Review URL: https://breakpad.appspot.com/9774002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1429 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-27 04:52:21 +00:00
mark@chromium.org
8ca937a3a7 Update license on convert_UTF.* to the standard Unicode license.
BUG=google-breakpad:270
R=ted.mielczarek@gmail.com

Review URL: https://breakpad.appspot.com/9764002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1428 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-25 21:16:43 +00:00
11 changed files with 327 additions and 68 deletions

View File

@@ -178,12 +178,8 @@ void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
out->flt_save.data_offset = fpregs.rdp;
out->flt_save.data_selector = 0; // We don't have this.
out->flt_save.mx_csr = fpregs.mxcsr;
#if defined (__ANDROID__)
// Internal bug b/18097559
out->flt_save.mx_csr_mask = fpregs.mxcsr_mask;
#else
out->flt_save.mx_csr_mask = fpregs.mxcr_mask;
#endif
my_memcpy(&out->flt_save.float_registers, &fpregs.st_space, 8 * 16);
my_memcpy(&out->flt_save.xmm_registers, &fpregs.xmm_space, 16 * 16);
}

View File

@@ -188,6 +188,24 @@ void RestoreAlternateStackLocked() {
stack_installed = false;
}
void InstallDefaultHandler(int sig) {
#if defined(__ANDROID__)
// Android L+ expose signal and sigaction symbols that override the system
// ones. There is a bug in these functions where a request to set the handler
// to SIG_DFL is ignored. In that case, an infinite loop is entered as the
// signal is repeatedly sent to breakpad's signal handler.
// To work around this, directly call the system's sigaction.
struct kernel_sigaction sa;
memset(&sa, 0, sizeof(sa));
sys_sigemptyset(&sa.sa_mask);
sa.sa_handler_ = SIG_DFL;
sa.sa_flags = SA_RESTART;
sys_rt_sigaction(sig, &sa, NULL, sizeof(kernel_sigset_t));
#else
signal(sig, SIG_DFL);
#endif
}
// The global exception handler stack. This is needed because there may exist
// multiple ExceptionHandler instances in a process. Each will have itself
// registered in this stack.
@@ -283,7 +301,7 @@ void ExceptionHandler::RestoreHandlersLocked() {
for (int i = 0; i < kNumHandledSignals; ++i) {
if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
signal(kExceptionSignals[i], SIG_DFL);
InstallDefaultHandler(kExceptionSignals[i]);
}
}
handlers_installed = false;
@@ -323,7 +341,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
if (sigaction(sig, &cur_handler, NULL) == -1) {
// When resetting the handler fails, try to reset the
// default one to avoid an infinite loop here.
signal(sig, SIG_DFL);
InstallDefaultHandler(sig);
}
pthread_mutex_unlock(&g_handler_stack_mutex_);
return;
@@ -340,14 +358,15 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
// previously installed handler. Then, when the signal is retriggered, it will
// be delivered to the appropriate handler.
if (handled) {
signal(sig, SIG_DFL);
InstallDefaultHandler(sig);
} else {
RestoreHandlersLocked();
}
pthread_mutex_unlock(&g_handler_stack_mutex_);
if (info->si_pid || sig == SIGABRT) {
// info->si_code <= 0 iff SI_FROMUSER (SI_FROMKERNEL otherwise).
if (info->si_code <= 0 || sig == SIGABRT) {
// This signal was triggered by somebody sending us the signal with kill().
// In order to retrigger it, we have to queue a new signal by calling
// kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is

View File

@@ -41,7 +41,6 @@
#include "client/linux/log/log.h"
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
#include "common/linux/linux_libc_support.h"
#include "common/scoped_ptr.h"
namespace {
@@ -51,7 +50,6 @@ using google_breakpad::LinuxPtraceDumper;
using google_breakpad::MappingInfo;
using google_breakpad::MappingList;
using google_breakpad::RawContextCPU;
using google_breakpad::scoped_array;
using google_breakpad::SeccompUnwinder;
using google_breakpad::ThreadInfo;
using google_breakpad::UContextReader;
@@ -69,14 +67,20 @@ class MicrodumpWriter {
#endif
dumper_(dumper),
mapping_list_(mappings),
log_line_(new char[kLineBufferSize]) {
log_line_.get()[0] = '\0'; // Clear out the log line buffer.
log_line_(NULL) {
log_line_ = reinterpret_cast<char*>(Alloc(kLineBufferSize));
if (log_line_)
log_line_[0] = '\0'; // Clear out the log line buffer.
}
~MicrodumpWriter() { dumper_->ThreadsResume(); }
bool Init() {
if (!dumper_->Init())
// In the exceptional case where the system was out of memory and there
// wasn't even room to allocate the line buffer, bail out. There is nothing
// useful we can possibly achieve without the ability to Log. At least let's
// try to not crash.
if (!dumper_->Init() || !log_line_)
return false;
return dumper_->ThreadsSuspend();
}
@@ -105,7 +109,7 @@ class MicrodumpWriter {
// Stages the given string in the current line buffer.
void LogAppend(const char* str) {
my_strlcat(log_line_.get(), str, kLineBufferSize);
my_strlcat(log_line_, str, kLineBufferSize);
}
// As above (required to take precedence over template specialization below).
@@ -135,8 +139,8 @@ class MicrodumpWriter {
// Writes out the current line buffer on the system log.
void LogCommitLine() {
LogLine(log_line_.get());
my_strlcpy(log_line_.get(), "", kLineBufferSize);
LogLine(log_line_);
my_strlcpy(log_line_, "", kLineBufferSize);
}
bool DumpOSInformation() {
@@ -363,7 +367,7 @@ class MicrodumpWriter {
#endif
LinuxDumper* dumper_;
const MappingList& mapping_list_;
scoped_array<char> log_line_;
char* log_line_;
};
} // namespace

View File

@@ -34,9 +34,11 @@
// glibc) and therefore avoid doing otherwise awkward #ifdefs in the code.
// The following quirks are currently handled by this file:
// - MIPS: Keep using forked definitions of user.h structs. The definition in
// the NDK is completely different.
// Internal bug b/18097715
// the NDK is completely different. Internal bug b/18097715
// - i386: Use the Android NDK but alias user_fxsr_struct > user_fpxregs_struct.
// - x86_64: Override a typo in user_fpregs_struct (mxcsr_mask -> mxcr_mask).
// The typo has been fixed in NDK r10d, but a preprocessor workaround is
// required to make breakpad build with r10c and lower (more details below).
// - Other platforms: Just use the Android NDK unchanged.
#ifdef __mips__
@@ -113,8 +115,24 @@ struct user_fpregs_struct {
#else // __mips__
// TODO(primiano): remove this after Chromium has stably rolled to NDK r10d.
// Historical context: NDK releases < r10d had a typo in sys/user.h (mxcsr_mask
// instead of mxcr_mask), which is fixed in r10d. However, just switching to use
// the correct one (mxcr_mask) would put Breakpad in a state where it can be
// rolled in chromium only atomically with the r10d NDK. A revert of either
// project (android_tools, breakpad) would make the other one unrollable.
// This hack makes breakpad code compatible with both r10c and r10d NDKs,
// reducing the dependency entangling with android_tools.
#if defined(__x86_64__)
#define mxcsr_mask mxcr_mask
#endif
#include_next <sys/user.h>
#if defined(__x86_64__)
#undef mxcsr_mask
#endif
#ifdef __i386__
#ifdef __cplusplus
extern "C" {

View File

@@ -1,23 +1,39 @@
/*
* Copyright 2001-2004 Unicode, Inc.
* Copyright © 1991-2015 Unicode, Inc. All rights reserved.
* Distributed under the Terms of Use in
* http://www.unicode.org/copyright.html.
*
* Disclaimer
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of the Unicode data files and any associated documentation
* (the "Data Files") or Unicode software and any associated documentation
* (the "Software") to deal in the Data Files or Software
* without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, and/or sell copies of
* the Data Files or Software, and to permit persons to whom the Data Files
* or Software are furnished to do so, provided that
* (a) this copyright and permission notice appear with all copies
* of the Data Files or Software,
* (b) this copyright and permission notice appear in associated
* documentation, and
* (c) there is clear notice in each modified Data File or in the Software
* as well as in the documentation associated with the Data File(s) or
* Software that the data or software has been modified.
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
* THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
* NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
* DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THE DATA FILES OR SOFTWARE.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
* Except as contained in this notice, the name of a copyright holder
* shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in these Data Files or Software without prior
* written authorization of the copyright holder.
*/
/* ---------------------------------------------------------------------

View File

@@ -1,23 +1,39 @@
/*
* Copyright 2001-2004 Unicode, Inc.
* Copyright © 1991-2015 Unicode, Inc. All rights reserved.
* Distributed under the Terms of Use in
* http://www.unicode.org/copyright.html.
*
* Disclaimer
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of the Unicode data files and any associated documentation
* (the "Data Files") or Unicode software and any associated documentation
* (the "Software") to deal in the Data Files or Software
* without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, and/or sell copies of
* the Data Files or Software, and to permit persons to whom the Data Files
* or Software are furnished to do so, provided that
* (a) this copyright and permission notice appear with all copies
* of the Data Files or Software,
* (b) this copyright and permission notice appear in associated
* documentation, and
* (c) there is clear notice in each modified Data File or in the Software
* as well as in the documentation associated with the Data File(s) or
* Software that the data or software has been modified.
*
* This source code is provided as is by Unicode, Inc. No claims are
* made as to fitness for any particular purpose. No warranties of any
* kind are expressed or implied. The recipient agrees to determine
* applicability of information provided. If this file has been
* purchased on magnetic or optical media from Unicode, Inc., the
* sole remedy for any claim will be exchange of defective media
* within 90 days of receipt.
* THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
* NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
* DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THE DATA FILES OR SOFTWARE.
*
* Limitations on Rights to Redistribute This Code
*
* Unicode, Inc. hereby grants the right to freely use the information
* supplied in this file in the creation of products supporting the
* Unicode Standard, and to make copies of this file in any form
* for internal or external distribution as long as this notice
* remains attached.
* Except as contained in this notice, the name of a copyright holder
* shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in these Data Files or Software without prior
* written authorization of the copyright holder.
*/
#ifndef COMMON_CONVERT_UTF_H_

View File

@@ -37,16 +37,34 @@
'all_dependent_settings': {
'include_dirs': [
'<(DEPTH)',
'$(VSInstallDir)\DIA SDK\include',
'$(VSInstallDir)/DIA SDK/include',
],
'msvs_settings': {
'VCLinkerTool': {
'AdditionalDependencies': [
'$(VSInstallDir)\DIA SDK\lib\diaguids.lib',
'diaguids.lib',
'imagehlp.lib',
],
},
},
'configurations': {
'x86_Base': {
'msvs_settings': {
'VCLinkerTool': {
'AdditionalLibraryDirectories':
['$(VSInstallDir)/DIA SDK/lib'],
},
},
},
'x64_Base': {
'msvs_settings': {
'VCLinkerTool': {
'AdditionalLibraryDirectories':
['$(VSInstallDir)/DIA SDK/lib/amd64'],
},
},
},
},
},
},
{

View File

@@ -94,7 +94,7 @@ int PrintMicrodumpProcess(const char* microdump_file,
if (machine_readable) {
PrintProcessStateMachineReadable(process_state);
} else {
PrintProcessState(process_state);
PrintProcessState(process_state, false, &resolver);
}
return 0;
}

View File

@@ -41,6 +41,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/minidump.h"
#include "google_breakpad/processor/minidump_processor.h"
#include "google_breakpad/processor/process_state.h"
#include "processor/logging.h"
@@ -51,6 +52,7 @@
namespace {
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::Minidump;
using google_breakpad::MinidumpProcessor;
using google_breakpad::ProcessState;
using google_breakpad::SimpleSymbolSupplier;
@@ -68,7 +70,8 @@ using google_breakpad::scoped_ptr;
// is printed to stdout.
bool PrintMinidumpProcess(const string &minidump_file,
const std::vector<string> &symbol_paths,
bool machine_readable) {
bool machine_readable,
bool output_stack_contents) {
scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
if (!symbol_paths.empty()) {
// TODO(mmentovai): check existence of symbol_path if specified?
@@ -79,8 +82,13 @@ bool PrintMinidumpProcess(const string &minidump_file,
MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver);
// Process the minidump.
Minidump dump(minidump_file);
if (!dump.Read()) {
BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read";
return false;
}
ProcessState process_state;
if (minidump_processor.Process(minidump_file, &process_state) !=
if (minidump_processor.Process(&dump, &process_state) !=
google_breakpad::PROCESS_OK) {
BPLOG(ERROR) << "MinidumpProcessor::Process failed";
return false;
@@ -89,15 +97,16 @@ bool PrintMinidumpProcess(const string &minidump_file,
if (machine_readable) {
PrintProcessStateMachineReadable(process_state);
} else {
PrintProcessState(process_state);
PrintProcessState(process_state, output_stack_contents, &resolver);
}
return true;
}
void usage(const char *program_name) {
fprintf(stderr, "usage: %s [-m] <minidump-file> [symbol-path ...]\n"
" -m : Output in machine-readable format\n",
fprintf(stderr, "usage: %s [-m|-s] <minidump-file> [symbol-path ...]\n"
" -m : Output in machine-readable format\n"
" -s : Output stack contents\n",
program_name);
}
@@ -112,7 +121,8 @@ int main(int argc, char **argv) {
}
const char *minidump_file;
bool machine_readable;
bool machine_readable = false;
bool output_stack_contents = false;
int symbol_path_arg;
if (strcmp(argv[1], "-m") == 0) {
@@ -124,8 +134,16 @@ int main(int argc, char **argv) {
machine_readable = true;
minidump_file = argv[2];
symbol_path_arg = 3;
} else if (strcmp(argv[1], "-s") == 0) {
if (argc < 3) {
usage(argv[0]);
return 1;
}
output_stack_contents = true;
minidump_file = argv[2];
symbol_path_arg = 3;
} else {
machine_readable = false;
minidump_file = argv[1];
symbol_path_arg = 2;
}
@@ -139,5 +157,6 @@ int main(int argc, char **argv) {
return PrintMinidumpProcess(minidump_file,
symbol_paths,
machine_readable) ? 0 : 1;
machine_readable,
output_stack_contents) ? 0 : 1;
}

View File

@@ -47,6 +47,7 @@
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/code_modules.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/source_line_resolver_interface.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/logging.h"
#include "processor/pathname_stripper.h"
@@ -110,6 +111,135 @@ static string StripSeparator(const string &original) {
return result;
}
// PrintStackContents prints the stack contents of the current frame to stdout.
static void PrintStackContents(const std::string &indent,
const StackFrame *frame,
const StackFrame *prev_frame,
const std::string &cpu,
const MemoryRegion *memory,
const CodeModules* modules,
SourceLineResolverInterface *resolver) {
// Find stack range.
int word_length = 0;
uint64_t stack_begin = 0, stack_end = 0;
if (cpu == "x86") {
word_length = 4;
const StackFrameX86 *frame_x86 = static_cast<const StackFrameX86*>(frame);
const StackFrameX86 *prev_frame_x86 =
static_cast<const StackFrameX86*>(prev_frame);
if ((frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP) &&
(prev_frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)) {
stack_begin = frame_x86->context.esp;
stack_end = prev_frame_x86->context.esp;
}
} else if (cpu == "amd64") {
word_length = 8;
const StackFrameAMD64 *frame_amd64 =
static_cast<const StackFrameAMD64*>(frame);
const StackFrameAMD64 *prev_frame_amd64 =
static_cast<const StackFrameAMD64*>(prev_frame);
if ((frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP) &&
(prev_frame_amd64->context_validity &
StackFrameAMD64::CONTEXT_VALID_RSP)) {
stack_begin = frame_amd64->context.rsp;
stack_end = prev_frame_amd64->context.rsp;
}
} else if (cpu == "arm") {
word_length = 4;
const StackFrameARM *frame_arm = static_cast<const StackFrameARM*>(frame);
const StackFrameARM *prev_frame_arm =
static_cast<const StackFrameARM*>(prev_frame);
if ((frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP) &&
(prev_frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
stack_begin = frame_arm->context.iregs[13];
stack_end = prev_frame_arm->context.iregs[13];
}
} else if (cpu == "arm64") {
word_length = 8;
const StackFrameARM64 *frame_arm64 =
static_cast<const StackFrameARM64*>(frame);
const StackFrameARM64 *prev_frame_arm64 =
static_cast<const StackFrameARM64*>(prev_frame);
if ((frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) &&
(prev_frame_arm64->context_validity &
StackFrameARM64::CONTEXT_VALID_SP)) {
stack_begin = frame_arm64->context.iregs[31];
stack_end = prev_frame_arm64->context.iregs[31];
}
}
if (!word_length || !stack_begin || !stack_end)
return;
// Print stack contents.
printf("\n%sStack contents:", indent.c_str());
for(uint64_t address = stack_begin; address < stack_end; ) {
// Print the start address of this row.
if (word_length == 4)
printf("\n%s %08x", indent.c_str(), static_cast<uint32_t>(address));
else
printf("\n%s %016" PRIx64, indent.c_str(), address);
// Print data in hex.
const int kBytesPerRow = 16;
std::string data_as_string;
for (int i = 0; i < kBytesPerRow; ++i, ++address) {
uint8_t value = 0;
if (address < stack_end &&
memory->GetMemoryAtAddress(address, &value)) {
printf(" %02x", value);
data_as_string.push_back(isprint(value) ? value : '.');
} else {
printf(" ");
data_as_string.push_back(' ');
}
}
// Print data as string.
printf(" %s", data_as_string.c_str());
}
// Try to find instruction pointers from stack.
printf("\n%sPossible instruction pointers:\n", indent.c_str());
for (uint64_t address = stack_begin; address < stack_end;
address += word_length) {
StackFrame pointee_frame;
// Read a word (possible instruction pointer) from stack.
if (word_length == 4) {
uint32_t data32 = 0;
memory->GetMemoryAtAddress(address, &data32);
pointee_frame.instruction = data32;
} else {
uint64_t data64 = 0;
memory->GetMemoryAtAddress(address, &data64);
pointee_frame.instruction = data64;
}
pointee_frame.module =
modules->GetModuleForAddress(pointee_frame.instruction);
// Try to look up the function name.
if (pointee_frame.module)
resolver->FillSourceLineInfo(&pointee_frame);
// Print function name.
if (!pointee_frame.function_name.empty()) {
if (word_length == 4) {
printf("%s *(0x%08x) = 0x%08x", indent.c_str(),
static_cast<uint32_t>(address),
static_cast<uint32_t>(pointee_frame.instruction));
} else {
printf("%s *(0x%016" PRIx64 ") = 0x%016" PRIx64,
indent.c_str(), address, pointee_frame.instruction);
}
printf(" <%s> [%s : %d + 0x%" PRIx64 "]\n",
pointee_frame.function_name.c_str(),
PathnameStripper::File(pointee_frame.source_file_name).c_str(),
pointee_frame.source_line,
pointee_frame.instruction - pointee_frame.source_line_base);
}
}
printf("\n");
}
// PrintStack prints the call stack in |stack| to stdout, in a reasonably
// useful form. Module, function, and source file names are displayed if
// they are available. The code offset to the base code address of the
@@ -119,7 +249,12 @@ static string StripSeparator(const string &original) {
//
// If |cpu| is a recognized CPU name, relevant register state for each stack
// frame printed is also output, if available.
static void PrintStack(const CallStack *stack, const string &cpu) {
static void PrintStack(const CallStack *stack,
const string &cpu,
bool output_stack_contents,
const MemoryRegion* memory,
const CodeModules* modules,
SourceLineResolverInterface* resolver) {
int frame_count = stack->frames()->size();
if (frame_count == 0) {
printf(" <no frames>\n");
@@ -469,6 +604,13 @@ static void PrintStack(const CallStack *stack, const string &cpu) {
sequence);
}
printf("\n Found by: %s\n", frame->trust_description().c_str());
// Print stack contents.
if (output_stack_contents && frame_index + 1 < frame_count) {
const std::string indent(" ");
PrintStackContents(indent, frame, stack->frames()->at(frame_index + 1),
cpu, memory, modules, resolver);
}
}
}
@@ -642,7 +784,9 @@ static void PrintModulesMachineReadable(const CodeModules *modules) {
} // namespace
void PrintProcessState(const ProcessState& process_state) {
void PrintProcessState(const ProcessState& process_state,
bool output_stack_contents,
SourceLineResolverInterface* resolver) {
// Print OS and CPU information.
string cpu = process_state.system_info()->cpu;
string cpu_info = process_state.system_info()->cpu_info;
@@ -692,7 +836,10 @@ void PrintProcessState(const ProcessState& process_state) {
requesting_thread,
process_state.crashed() ? "crashed" :
"requested dump, did not crash");
PrintStack(process_state.threads()->at(requesting_thread), cpu);
PrintStack(process_state.threads()->at(requesting_thread), cpu,
output_stack_contents,
process_state.thread_memory_regions()->at(requesting_thread),
process_state.modules(), resolver);
}
// Print all of the threads in the dump.
@@ -702,7 +849,10 @@ void PrintProcessState(const ProcessState& process_state) {
// Don't print the crash thread again, it was already printed.
printf("\n");
printf("Thread %d\n", thread_index);
PrintStack(process_state.threads()->at(thread_index), cpu);
PrintStack(process_state.threads()->at(thread_index), cpu,
output_stack_contents,
process_state.thread_memory_regions()->at(thread_index),
process_state.modules(), resolver);
}
}

View File

@@ -37,9 +37,12 @@
namespace google_breakpad {
class ProcessState;
class SourceLineResolverInterface;
void PrintProcessStateMachineReadable(const ProcessState& process_state);
void PrintProcessState(const ProcessState& process_state);
void PrintProcessState(const ProcessState& process_state,
bool output_stack_contents,
SourceLineResolverInterface* resolver);
} // namespace google_breakpad