Compare commits

...

37 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
wfh@chromium.org
2b7360217e Add option to Breakpad to consume INVALID_HANDLE_VALUE exceptions.
BUG=chromium:452613
R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1427 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-22 02:27:35 +00:00
thestig@chromium.org
4aeb452cdd Cleanup Linux debug link file handling code.
- Handle the case when the debug link points back to the object file.
- Move some checks into a separate SanitizeDebugFile() function.

BUG=636
Review URL: https://breakpad.appspot.com/3784002/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1426 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-10 22:36:39 +00:00
mark@chromium.org
19a35ba066 Fix overflow error in breakpad for linux
A computation in the stack unwind algorithm could cause an overflow if a base
pointer read from crashed process is sufficiently close to top of address space.
This causes a memory read that causes the dump thread to crash, resulting in a
failure to generate crash dump. Check fixed to properly detect that this pointer
is greater than actual memory range of current stack.

Patch by Kyle Joswiak <kjoswiak@chromium.org>

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


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1425 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-05 23:01:31 +00:00
thestig@chromium.org
5bf649f336 Add unit tests for overlapping functions and externs.
R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1424 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-04 00:03:58 +00:00
thestig@chromium.org
41f858a4d7 Handle ARM THUMB functions when removing duplicate PUBLIC entries.
In ELF symtab/dynsym sections, THUMB function addresses have bit 0 set,
whereas the DWARF function entries are not.

R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1423 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-03 23:13:04 +00:00
hashimoto@chromium.org
54d899d631 Follow debug link correctly
As thestig@chromium.org pointed out in https://breakpad.appspot.com/9684002,
LoadSymbols() should return false if |read_gnu_debug_link| is false.

BUG=chromium:453498
R=thestig@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1422 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-03 07:16:04 +00:00
hashimoto@chromium.org
16ab317dfc Demangle symbol name
The spec says it should be demangled.
https://code.google.com/p/google-breakpad/wiki/SymbolFiles

BUG=chromium:453498
R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1421 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-03 03:17:30 +00:00
benchan@chromium.org
d6eb7fa1b8 Handle failures of copying process data from a core file.
When LinuxCoreDumper fails to copy process data from a core file, it
fills the return buffer with a repeated sequence of a special marker.
However, MinidumpWriter doesn't know about that and may incorrectly
interpret the data. In many cases, MinidumpWriter simply copies the
gibberish data to the minidump, which isn't too bad. However, the
gibberish data may cause MinidumpWriter to behave badly in some other
cases. For example, when MinidumpWriter tries to iterate through the
linked list of all loaded DSOs via the r_map field of a r_debug struct,
if the linked list is filed with the special marker, the code keeps
iterating through the same address.

This CL addresses the issue by having LinuxCoreDumper::CopyFromProcess()
returns a Boolean value to indicate if the expected data is found from
the core file. MinidumpWriter can then decide how to handle that.

BUG=chromium:453484
TEST=Run core2md with the test data attached to chromium:453484.
R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1420 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-02 23:27:27 +00:00
ted.mielczarek@gmail.com
d2904bb421 Replace uses of hash_map with unordered_map
hash_map no longer exists in Visual C++ 2015.
A=Brian Smith <brian@briansmith.org>
R=ted at https://bugzilla.mozilla.org/show_bug.cgi?id=1119072

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1419 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-02-02 14:05:45 +00:00
vapier@chromium.org
7c7366dd6d Remove unneeded definitions of O_BINARY
Review URL: https://breakpad.appspot.com/6684002/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1418 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-01-28 21:47:31 +00:00
benchan@chromium.org
55f879151c Remove unused variable 'kGUIDStringSize' in microdump_writer_unittest.
R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1417 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-01-28 18:33:50 +00:00
hashimoto@chromium.org
a4eb2e302c Stop calling memmove when unnecessary
BUG=chromium:450137
R=mark@chromium.org



git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1416 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-01-27 03:27:08 +00:00
erikchen@chromium.org
ccc06f4798 Fix some fragile code that is likely to cause future memory corruption
problems.

- The ordering of keys in stl containers cannot change. Make the relevant
members const to guarantee this assumption.
- Add handling and logging for demangle errors.
- Fix a potential double-delete bug if a function passed to AddFunction() is
already present.

BUG=chromium:449214
R=mark@chromium.org

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


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1415 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-01-27 01:20:59 +00:00
erikchen@chromium.org
acb33ed38f Fix a source of memory corruption.
This error was causing crashes in official Chrome Mac builds on 10.8.5
machines.

BUG=chromium:449214
R=mark@chromium.org


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1414 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-01-26 23:19:04 +00:00
primiano@chromium.org
2f77d4e41c Fix the scope on the initialization of kMicrodumpOnConsole to match header.
I whish I knew how this worked for months in chromium as it is clearly wrong.
As reported by azarchs@ it is breaking the cygprofile instrumented build.

BUG=chromium:410294

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1413 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-01-09 17:58:19 +00:00
wfh@chromium.org
0a5700b594 Modify minidump_stackwalk to be more tolerant of overlapping ranges.
These ranges can be seen in some Android minidumps.

BUG=chromium:439531
R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1412 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-12-20 00:47:07 +00:00
jessicag.feedback@gmail.com
e0d5189f74 Add microdump files to project.
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1411 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-12-11 19:30:37 +00:00
mdempsky@chromium.org
c32b7ad535 Remove pointers from serialized file format
BUG=breakpad:621
R=thestig@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1410 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-12-11 01:17:43 +00:00
mark@chromium.org
aad5d66fa5 Breakpad: Fix build with new clang versions.
gcc has a single exception setting for all languages. Saying -fno-exceptions
in gcc disables exceptions and cleanups for cc files, but has no effect for mm
files.

In clang, -fno-exceptions only disables c++ exceptions, but keeps objective-c
exceptions and cleanups enabled.

http://llvm.org/viewvc/llvm-project?view=revision&revision=220714 changed
__EXCEPTIONS to be defined for clang when cleanups are enabled, independent of
if c++ exceptions are enabled. (This was necessary to have clang work with
glibc which looks at __EXCEPTIONS to decide if cleanups are enabled.)

Breakpad tried to use __EXCEPTIONS to figure out if c++ exceptions are enabled.
In cc files, this works: -fno-exceptions will disable c++ exceptions and
cleanups. But in mm files, -fno-exceptions will disable c++ exceptions and
objective-c exceptions will still be enabled, and so cleanups must run and hence
__EXCEPTIONS is defined.

To make things work with both old and new compilers, do the try/catch hack in
mm files either if __EXCEPTIONS is not defined (for old compilers) or if the
compiler is clang and __has_feature(cxx_exceptions) isn't set (which will work
for new clangs too, and which cleanly maps to if c++ exceptions are enabled).

Patch by Nico Weber <thakis@chromium.org>

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


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1409 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-12-10 16:08:09 +00:00
mseaborn@chromium.org
e9df0305d3 dump_syms: Fix handling of DW_FORM_ref_addr to work with DWARF 4
Previously, dump_syms did not handle DW_FORM_ref_addr if it appeared
in DWARF 4 debugging info.

Also fix a DW_FORM_ref_addr case so that it doesn't fall through to
the next switch case when assertions are disabled and the DWARF
version isn't recognised.

The following steps will reproduce the problem when using LLVM 3.4:

cat <<END >example1.c
int main() { return 0; }
END
cat <<END >example2.c
void foo(int x) {}
END

clang -emit-llvm -g -c example1.c -o example1.bc
clang -emit-llvm -g -c example2.c -o example2.bc
llvm-link-3.4 example1.bc example2.bc -o combined.bc
clang combined.bc -o executable
./google-breakpad/build/src/tools/linux/dump_syms/dump_syms executable

When using LLVM bitcode linking in this way, LLVM's backend generates
partially-merged DWARF debugging info in which some of the references
to the "int" type go via "DW_FORM_ref_addr".  Since PNaCl uses LLVM
bitcode linking, this dump_syms failure occurs with nexes produced by
the PNaCl toolchain.

BUG= https://code.google.com/p/chromium/issues/detail?id=416368
TEST= see above
R=mark@chromium.org, mcgrathr@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1408 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-12-03 20:39:55 +00:00
primiano@chromium.org
a4283fc4cf Microdumps: support aarch64 and lib mapping from APK
- Filter modules by prot flags (only +x) not extensions. It wouldn't
  otherwise catch the case of Chrome mapping the library from the
  apk (which is mapped r-x but doesn't end in .so).
- Use compile-time detection of target arch, in order to cope with
  multilib OSes, where uname() doesn't reflect the run-time arch.
- Add OS information and CPU arch / count.
- Add support for aarch64.
- Add tests and stackwalk expectations for aarch64.
- Fix a potential overflow bug in the processor.
- Rebaseline the tests using smaller symbols.
- Fix microdump_writer_unittest.cc on 32-bit host.

BUG=chromium:410294

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1407 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-12-02 15:31:25 +00:00
ivanpe@chromium.org
259512f933 Surfacing the process create time in google_breakpad::ProcessState
and updating minidump_stackwalk to show process uptime.

I tested this with a minidump from Chrome and I got a result that
is inline with what the Windows debugger is showing for that dump:

minidump_stackwalk output:
--------------------------
Process uptime: 601 seconds

WinDBG output:
--------------
Process Uptime: 0 days 0:10:01.000

I didn't update the machine readable output of minidump_stackwalk
on purpose in order to avoid breaking someone that uses it.
It can be added later to the machine output if needed.

R=mark@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1406 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-11-25 22:45:23 +00:00
primiano@chromium.org
725a5dff8a Introduce microdump_stackwalk comand line executable
This introduces the microdump_stackwalk binary which takes advantage
of the MicrodumpProcessor to symbolize microdumps.
Its operation is identical to the one of minidump_stackwalk.
This CL, in fact, is also refactoring most of the common bits into
stackwalk_common.

BUG=chromium:410294
R=mmandlis@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1405 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-11-25 11:36:38 +00:00
primiano@chromium.org
63f4e5f479 Fix microdump_writer and add unittest.
This adds some small fixes to the microdump writer and introduces
a unittest.

BUG=chromium:410294
R=mmandlis@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1404 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-11-25 10:35:53 +00:00
mmandlis@chromium.org
7de07eed33 Microdump processing implementation
According to design document: http://goo.gl/B3wIRN
This is an initial implementation version, support ARM architecture only.

BUG=chromium:410294
R=primiano@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1403 4c0a9323-5329-0410-9bdc-e9ce6186880e
2014-11-19 21:33:26 +00:00
69 changed files with 151913 additions and 1100 deletions

View File

@ -168,6 +168,7 @@ src_libbreakpad_a_SOURCES = \
src/google_breakpad/processor/exploitability.h \
src/google_breakpad/processor/fast_source_line_resolver.h \
src/google_breakpad/processor/memory_region.h \
src/google_breakpad/processor/microdump.h \
src/google_breakpad/processor/microdump_processor.h \
src/google_breakpad/processor/minidump.h \
src/google_breakpad/processor/minidump_processor.h \
@ -211,6 +212,7 @@ src_libbreakpad_a_SOURCES = \
src/processor/logging.cc \
src/processor/map_serializers-inl.h \
src/processor/map_serializers.h \
src/processor/microdump.cc \
src/processor/microdump_processor.cc \
src/processor/minidump.cc \
src/processor/minidump_processor.cc \
@ -299,6 +301,7 @@ src_third_party_libdisasm_libdisasm_a_SOURCES = \
## Programs
bin_PROGRAMS += \
src/processor/microdump_stackwalk \
src/processor/minidump_dump \
src/processor/minidump_stackwalk
endif !DISABLE_PROCESSOR
@ -373,6 +376,8 @@ endif !DISABLE_PROCESSOR
if !DISABLE_PROCESSOR
check_SCRIPTS = \
src/processor/microdump_stackwalk_test \
src/processor/microdump_stackwalk_machine_readable_test \
src/processor/minidump_dump_test \
src/processor/minidump_stackwalk_test \
src/processor/minidump_stackwalk_machine_readable_test
@ -433,6 +438,10 @@ if ANDROID_HOST
src_client_linux_linux_client_unittest_shlib_SOURCES += \
src/common/android/breakpad_getcontext.S
endif
if LINUX_HOST
src_client_linux_linux_client_unittest_shlib_SOURCES += \
src/client/linux/microdump_writer/microdump_writer_unittest.cc
endif
src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \
-I$(top_srcdir)/src \
@ -704,10 +713,10 @@ src_processor_exploitability_unittest_LDADD = \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
@ -781,6 +790,31 @@ src_processor_microdump_processor_unittest_CPPFLAGS = \
-I$(top_srcdir)/src/testing/gtest \
-I$(top_srcdir)/src/testing
src_processor_microdump_processor_unittest_LDADD = \
src/processor/basic_code_modules.o \
src/processor/basic_source_line_resolver.o \
src/processor/call_stack.o \
src/processor/cfi_frame_info.o \
src/processor/dump_context.o \
src/processor/dump_object.o \
src/processor/logging.o \
src/processor/microdump.o \
src/processor/microdump_processor.o \
src/processor/pathname_stripper.o \
src/processor/process_state.o \
src/processor/simple_symbol_supplier.o \
src/processor/source_line_resolver_base.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
src/processor/stackwalker_sparc.o \
src/processor/stackwalker_x86.o \
src/processor/tokenize.o \
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
src_processor_minidump_processor_unittest_SOURCES = \
@ -813,10 +847,10 @@ src_processor_minidump_processor_unittest_LDADD = \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
@ -945,10 +979,10 @@ src_processor_stackwalker_selftest_LDADD = \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
@ -1099,6 +1133,40 @@ src_processor_minidump_dump_LDADD = \
src/processor/minidump.o \
src/processor/pathname_stripper.o
src_processor_microdump_stackwalk_SOURCES = \
src/processor/microdump_stackwalk.cc
src_processor_microdump_stackwalk_LDADD = \
src/processor/basic_code_modules.o \
src/processor/basic_source_line_resolver.o \
src/processor/binarystream.o \
src/processor/call_stack.o \
src/processor/cfi_frame_info.o \
src/processor/disassembler_x86.o \
src/processor/dump_context.o \
src/processor/dump_object.o \
src/processor/logging.o \
src/processor/microdump.o \
src/processor/microdump_processor.o \
src/processor/pathname_stripper.o \
src/processor/process_state.o \
src/processor/simple_symbol_supplier.o \
src/processor/source_line_resolver_base.o \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalk_common.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \
src/processor/stackwalker_sparc.o \
src/processor/stackwalker_x86.o \
src/processor/tokenize.o \
src/third_party/libdisasm/libdisasm.a
src_processor_minidump_stackwalk_SOURCES = \
src/processor/minidump_stackwalk.cc
src_processor_minidump_stackwalk_LDADD = \
@ -1122,11 +1190,12 @@ src_processor_minidump_stackwalk_LDADD = \
src/processor/source_line_resolver_base.o \
src/processor/stack_frame_cpu.o \
src/processor/stack_frame_symbolizer.o \
src/processor/stackwalk_common.o \
src/processor/stackwalker.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_amd64.o \
src/processor/stackwalker_arm.o \
src/processor/stackwalker_arm64.o \
src/processor/stackwalker_address_list.o \
src/processor/stackwalker_mips.o \
src/processor/stackwalker_ppc.o \
src/processor/stackwalker_ppc64.o \

View File

@ -145,6 +145,7 @@ check_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext.S
@DISABLE_PROCESSOR_FALSE@am__append_11 = \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk
@ -198,12 +199,16 @@ check_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
@DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__append_17 = \
@DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@ src/processor/stackwalker_selftest
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_18 = src/common/android/breakpad_getcontext.S \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext_unittest.cc
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_18 = \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext.S
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_19 = \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog -lm
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext_unittest.cc
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_20 = \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog -lm
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_21 = \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog
noinst_PROGRAMS =
@ -342,6 +347,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
src/google_breakpad/processor/exploitability.h \
src/google_breakpad/processor/fast_source_line_resolver.h \
src/google_breakpad/processor/memory_region.h \
src/google_breakpad/processor/microdump.h \
src/google_breakpad/processor/microdump_processor.h \
src/google_breakpad/processor/minidump.h \
src/google_breakpad/processor/minidump_processor.h \
@ -378,7 +384,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
src/processor/fast_source_line_resolver.cc \
src/processor/linked_ptr.h src/processor/logging.h \
src/processor/logging.cc src/processor/map_serializers-inl.h \
src/processor/map_serializers.h \
src/processor/map_serializers.h src/processor/microdump.cc \
src/processor/microdump_processor.cc src/processor/minidump.cc \
src/processor/minidump_processor.cc \
src/processor/module_comparer.cc \
@ -442,6 +448,7 @@ am__src_libbreakpad_a_SOURCES_DIST = \
@DISABLE_PROCESSOR_FALSE@ src/processor/exploitability_win.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/fast_source_line_resolver.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.$(OBJEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.$(OBJEXT) \
@ -510,7 +517,7 @@ am__src_third_party_libdisasm_libdisasm_a_SOURCES_DIST = \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_operand_list.$(OBJEXT)
src_third_party_libdisasm_libdisasm_a_OBJECTS = \
$(am_src_third_party_libdisasm_libdisasm_a_OBJECTS)
@DISABLE_PROCESSOR_FALSE@am__EXEEXT_1 = \
@DISABLE_PROCESSOR_FALSE@am__EXEEXT_1 = src/processor/microdump_stackwalk$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk$(EXEEXT)
@LINUX_HOST_TRUE@am__EXEEXT_2 = src/client/linux/linux_dumper_unittest_helper$(EXEEXT)
@ -580,9 +587,10 @@ am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \
src/processor/logging.cc src/processor/minidump.cc \
src/processor/pathname_stripper.cc \
src/common/android/breakpad_getcontext.S \
src/client/linux/microdump_writer/microdump_writer_unittest.cc \
src/common/android/breakpad_getcontext_unittest.cc
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_2 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT) \
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT)
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_2 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT)
@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_3 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT)
@LINUX_HOST_TRUE@am_src_client_linux_linux_client_unittest_shlib_OBJECTS = src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.$(OBJEXT) \
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.$(OBJEXT) \
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.$(OBJEXT) \
@ -607,7 +615,9 @@ am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \
@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-logging.$(OBJEXT) \
@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-minidump.$(OBJEXT) \
@LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.$(OBJEXT) \
@LINUX_HOST_TRUE@ $(am__objects_2)
@LINUX_HOST_TRUE@ $(am__objects_2) \
@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.$(OBJEXT) \
@LINUX_HOST_TRUE@ $(am__objects_3)
src_client_linux_linux_client_unittest_shlib_OBJECTS = \
$(am_src_client_linux_linux_client_unittest_shlib_OBJECTS)
am__DEPENDENCIES_1 =
@ -843,10 +853,10 @@ src_processor_exploitability_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -899,8 +909,69 @@ am__src_processor_microdump_processor_unittest_SOURCES_DIST = \
src_processor_microdump_processor_unittest_OBJECTS = \
$(am_src_processor_microdump_processor_unittest_OBJECTS)
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_processor_unittest_DEPENDENCIES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
am__src_processor_microdump_stackwalk_SOURCES_DIST = \
src/processor/microdump_stackwalk.cc
@DISABLE_PROCESSOR_FALSE@am_src_processor_microdump_stackwalk_OBJECTS = src/processor/microdump_stackwalk.$(OBJEXT)
src_processor_microdump_stackwalk_OBJECTS = \
$(am_src_processor_microdump_stackwalk_OBJECTS)
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_DEPENDENCIES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
am__src_processor_minidump_dump_SOURCES_DIST = \
src/processor/minidump_dump.cc
@DISABLE_PROCESSOR_FALSE@am_src_processor_minidump_dump_OBJECTS = src/processor/minidump_dump.$(OBJEXT)
@ -942,10 +1013,10 @@ src_processor_minidump_processor_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -981,11 +1052,12 @@ src_processor_minidump_stackwalk_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -1151,10 +1223,10 @@ src_processor_stackwalker_selftest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -1406,6 +1478,7 @@ SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \
$(src_processor_fast_source_line_resolver_unittest_SOURCES) \
$(src_processor_map_serializers_unittest_SOURCES) \
$(src_processor_microdump_processor_unittest_SOURCES) \
$(src_processor_microdump_stackwalk_SOURCES) \
$(src_processor_minidump_dump_SOURCES) \
$(src_processor_minidump_processor_unittest_SOURCES) \
$(src_processor_minidump_stackwalk_SOURCES) \
@ -1450,6 +1523,7 @@ DIST_SOURCES = \
$(am__src_processor_fast_source_line_resolver_unittest_SOURCES_DIST) \
$(am__src_processor_map_serializers_unittest_SOURCES_DIST) \
$(am__src_processor_microdump_processor_unittest_SOURCES_DIST) \
$(am__src_processor_microdump_stackwalk_SOURCES_DIST) \
$(am__src_processor_minidump_dump_SOURCES_DIST) \
$(am__src_processor_minidump_processor_unittest_SOURCES_DIST) \
$(am__src_processor_minidump_stackwalk_SOURCES_DIST) \
@ -1888,6 +1962,7 @@ lib_LIBRARIES = $(am__append_5) $(am__append_8)
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/exploitability.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/fast_source_line_resolver.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/memory_region.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/microdump.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/microdump_processor.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump.h \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/processor/minidump_processor.h \
@ -1931,6 +2006,7 @@ lib_LIBRARIES = $(am__append_5) $(am__append_8)
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers-inl.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/map_serializers.h \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.cc \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_processor.cc \
@ -2017,6 +2093,8 @@ lib_LIBRARIES = $(am__append_5) $(am__append_8)
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/x86_operand_list.h
@DISABLE_PROCESSOR_FALSE@check_SCRIPTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk_machine_readable_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_dump_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk_test \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk_machine_readable_test
@ -2063,7 +2141,9 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@LINUX_HOST_TRUE@ src/processor/logging.cc \
@LINUX_HOST_TRUE@ src/processor/minidump.cc \
@LINUX_HOST_TRUE@ src/processor/pathname_stripper.cc \
@LINUX_HOST_TRUE@ $(am__append_18)
@LINUX_HOST_TRUE@ $(am__append_18) \
@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer_unittest.cc \
@LINUX_HOST_TRUE@ $(am__append_19)
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \
@LINUX_HOST_TRUE@ -I$(top_srcdir)/src \
@LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/include \
@ -2073,7 +2153,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_LDFLAGS = \
@LINUX_HOST_TRUE@ -shared -Wl,-h,linux_client_unittest_shlib \
@LINUX_HOST_TRUE@ $(am__append_19)
@LINUX_HOST_TRUE@ $(am__append_20)
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_LDADD = \
@LINUX_HOST_TRUE@ src/client/linux/crash_generation/crash_generation_client.o \
@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/seccomp_unwinder.o \
@ -2105,7 +2185,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_SOURCES =
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDFLAGS = \
@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' $(am__append_20)
@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' $(am__append_21)
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDADD = \
@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib
@ -2332,10 +2412,10 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -2417,6 +2497,31 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ -I$(top_srcdir)/src/testing
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_processor_unittest_LDADD = \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_processor_unittest_SOURCES = \
@ -2451,10 +2556,10 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -2597,10 +2702,10 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -2763,6 +2868,41 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_stackwalk.cc
@DISABLE_PROCESSOR_FALSE@src_processor_microdump_stackwalk_LDADD = \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_code_modules.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/basic_source_line_resolver.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/binarystream.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/call_stack.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/cfi_frame_info.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/disassembler_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_context.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/dump_object.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/microdump_processor.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/process_state.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/simple_symbol_supplier.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_sparc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/tokenize.o \
@DISABLE_PROCESSOR_FALSE@ src/third_party/libdisasm/libdisasm.a
@DISABLE_PROCESSOR_FALSE@src_processor_minidump_stackwalk_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/minidump_stackwalk.cc
@ -2787,11 +2927,12 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/source_line_resolver_base.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_cpu.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stack_frame_symbolizer.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalk_common.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm64.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_address_list.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_mips.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_ppc64.o \
@ -3199,6 +3340,8 @@ src/processor/fast_source_line_resolver.$(OBJEXT): \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/logging.$(OBJEXT): src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/microdump.$(OBJEXT): src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/microdump_processor.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
@ -3473,6 +3616,9 @@ src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.$(O
src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT): \
src/common/android/$(am__dirstamp) \
src/common/android/$(DEPDIR)/$(am__dirstamp)
src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.$(OBJEXT): \
src/client/linux/microdump_writer/$(am__dirstamp) \
src/client/linux/microdump_writer/$(DEPDIR)/$(am__dirstamp)
src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT): \
src/common/android/$(am__dirstamp) \
src/common/android/$(DEPDIR)/$(am__dirstamp)
@ -3781,6 +3927,13 @@ src/testing/src/src_processor_microdump_processor_unittest-gmock-all.$(OBJEXT):
src/processor/microdump_processor_unittest$(EXEEXT): $(src_processor_microdump_processor_unittest_OBJECTS) $(src_processor_microdump_processor_unittest_DEPENDENCIES) $(EXTRA_src_processor_microdump_processor_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/microdump_processor_unittest$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_microdump_processor_unittest_OBJECTS) $(src_processor_microdump_processor_unittest_LDADD) $(LIBS)
src/processor/microdump_stackwalk.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/microdump_stackwalk$(EXEEXT): $(src_processor_microdump_stackwalk_OBJECTS) $(src_processor_microdump_stackwalk_DEPENDENCIES) $(EXTRA_src_processor_microdump_stackwalk_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/microdump_stackwalk$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_microdump_stackwalk_OBJECTS) $(src_processor_microdump_stackwalk_LDADD) $(LIBS)
src/processor/minidump_dump.$(OBJEXT): src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
@ -4199,6 +4352,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/log/$(DEPDIR)/log.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/microdump_writer/$(DEPDIR)/microdump_writer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_core_dumper.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_dumper.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_ptrace_dumper.Po@am__quote@
@ -4313,7 +4467,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/exploitability_win.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/fast_source_line_resolver.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/logging.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump_processor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/microdump_stackwalk.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Po@am__quote@
@ -4854,6 +5010,20 @@ src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj `if test -f 'src/processor/pathname_stripper.cc'; then $(CYGPATH_W) 'src/processor/pathname_stripper.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/pathname_stripper.cc'; fi`
src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o: src/client/linux/microdump_writer/microdump_writer_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o -MD -MP -MF src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o `test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/microdump_writer/microdump_writer_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/microdump_writer/microdump_writer_unittest.cc' object='src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o `test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/microdump_writer/microdump_writer_unittest.cc
src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj: src/client/linux/microdump_writer/microdump_writer_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj -MD -MP -MF src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj `if test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/microdump_writer/microdump_writer_unittest.cc'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/microdump_writer/microdump_writer_unittest.cc' object='src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj `if test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/microdump_writer/microdump_writer_unittest.cc'; fi`
src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o: src/common/android/breakpad_getcontext_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o -MD -MP -MF src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o `test -f 'src/common/android/breakpad_getcontext_unittest.cc' || echo '$(srcdir)/'`src/common/android/breakpad_getcontext_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po
@ -7455,6 +7625,20 @@ src/processor/stackwalker_selftest.log: src/processor/stackwalker_selftest$(EXEE
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
src/processor/microdump_stackwalk_test.log: src/processor/microdump_stackwalk_test
@p='src/processor/microdump_stackwalk_test'; \
b='src/processor/microdump_stackwalk_test'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
src/processor/microdump_stackwalk_machine_readable_test.log: src/processor/microdump_stackwalk_machine_readable_test
@p='src/processor/microdump_stackwalk_machine_readable_test'; \
b='src/processor/microdump_stackwalk_machine_readable_test'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
src/processor/minidump_dump_test.log: src/processor/minidump_dump_test
@p='src/processor/minidump_dump_test'; \
b='src/processor/minidump_dump_test'; \

View File

@ -45,7 +45,7 @@
#import "client/mac/handler/protected_memory_allocator.h"
#import "common/simple_string_dictionary.h"
#ifndef __EXCEPTIONS
#if !defined(__EXCEPTIONS) || (__clang__ && !__has_feature(cxx_exceptions))
// This file uses C++ try/catch (but shouldn't). Duplicate the macros from
// <c++/4.2.1/exception_defines.h> allowing this file to work properly with
// exceptions disabled even when other C++ libraries are used. #undef the try

View File

@ -44,8 +44,8 @@ void SeccompUnwinder::PopSeccompStackFrame(RawContextCPU* cpu,
uint64_t top = thread.stack.start_of_memory_range;
for (int i = 4; i--; ) {
if (bp < top ||
bp + sizeof(bp) > thread.stack.start_of_memory_range +
thread.stack.memory.data_size ||
bp > thread.stack.start_of_memory_range +
thread.stack.memory.data_size - sizeof(bp) ||
bp & 1) {
break;
}
@ -107,8 +107,8 @@ void SeccompUnwinder::PopSeccompStackFrame(RawContextCPU* cpu,
uint32_t top = thread.stack.start_of_memory_range;
for (int i = 4; i--; ) {
if (bp < top ||
bp + sizeof(bp) > thread.stack.start_of_memory_range +
thread.stack.memory.data_size ||
bp > thread.stack.start_of_memory_range +
thread.stack.memory.data_size - sizeof(bp) ||
bp & 1) {
break;
}

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

@ -36,7 +36,8 @@
namespace google_breakpad {
//static
const MinidumpDescriptor::MicrodumpOnConsole kMicrodumpOnConsole = {};
const MinidumpDescriptor::MicrodumpOnConsole
MinidumpDescriptor::kMicrodumpOnConsole = {};
MinidumpDescriptor::MinidumpDescriptor(const MinidumpDescriptor& descriptor)
: mode_(descriptor.mode_),

View File

@ -38,9 +38,9 @@
#include "client/linux/dump_writer_common/thread_info.h"
#include "client/linux/dump_writer_common/ucontext_reader.h"
#include "client/linux/handler/exception_handler.h"
#include "client/linux/log/log.h"
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
#include "common/linux/linux_libc_support.h"
#include "client/linux/log/log.h"
namespace {
@ -54,6 +54,8 @@ using google_breakpad::SeccompUnwinder;
using google_breakpad::ThreadInfo;
using google_breakpad::UContextReader;
const size_t kLineBufferSize = 2048;
class MicrodumpWriter {
public:
MicrodumpWriter(const ExceptionHandler::CrashContext* context,
@ -64,12 +66,21 @@ class MicrodumpWriter {
float_state_(context ? &context->float_state : NULL),
#endif
dumper_(dumper),
mapping_list_(mappings) { }
mapping_list_(mappings),
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();
}
@ -91,11 +102,14 @@ class MicrodumpWriter {
// Writes one line to the system log.
void LogLine(const char* msg) {
logger::write(msg, my_strlen(msg));
#if !defined(__ANDROID__)
logger::write("\n", 1); // Android logger appends the \n. Linux's doesn't.
#endif
}
// Stages the given string in the current line buffer.
void LogAppend(const char* str) {
my_strlcat(log_line_, str, sizeof(log_line_));
my_strlcat(log_line_, str, kLineBufferSize);
}
// As above (required to take precedence over template specialization below).
@ -125,14 +139,15 @@ class MicrodumpWriter {
// Writes out the current line buffer on the system log.
void LogCommitLine() {
logger::write(log_line_, my_strlen(log_line_));
my_strlcpy(log_line_, "", sizeof(log_line_));
LogLine(log_line_);
my_strlcpy(log_line_, "", kLineBufferSize);
}
bool DumpOSInformation() {
struct utsname uts;
if (uname(&uts))
return false;
const uint8_t n_cpus = static_cast<uint8_t>(sysconf(_SC_NPROCESSORS_CONF));
#if defined(__ANDROID__)
const char kOSId[] = "A";
@ -140,15 +155,34 @@ class MicrodumpWriter {
const char kOSId[] = "L";
#endif
// We cannot depend on uts.machine. On multiarch devices it always returns the
// primary arch, not the one that match the executable being run.
#if defined(__aarch64__)
const char kArch[] = "arm64";
#elif defined(__ARMEL__)
const char kArch[] = "arm";
#elif defined(__x86_64__)
const char kArch[] = "x86_64";
#elif defined(__i386__)
const char kArch[] = "x86";
#elif defined(__mips__)
const char kArch[] = "mips";
#else
#error "This code has not been ported to your platform yet"
#endif
LogAppend("O ");
LogAppend(kOSId);
LogAppend(" \"");
LogAppend(" ");
LogAppend(kArch);
LogAppend(" ");
LogAppend(n_cpus);
LogAppend(" ");
LogAppend(uts.machine);
LogAppend("\" \"");
LogAppend(" ");
LogAppend(uts.release);
LogAppend(" \"");
LogAppend(" ");
LogAppend(uts.version);
LogAppend("\"");
LogCommitLine();
return true;
}
@ -162,8 +196,9 @@ class MicrodumpWriter {
size_t stack_len;
if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
assert(false);
return false;
// The stack pointer might not be available. In this case we don't hard
// fail, just produce a (almost useless) microdump w/o a stack section.
return true;
}
LogAppend("S 0 ");
@ -296,7 +331,7 @@ class MicrodumpWriter {
LogAppend(module_identifier.data4[5]);
LogAppend(module_identifier.data4[6]);
LogAppend(module_identifier.data4[7]);
LogAppend(" ");
LogAppend("0 "); // Age is always 0 on Linux.
LogAppend(file_name);
LogCommitLine();
}
@ -306,15 +341,13 @@ class MicrodumpWriter {
// First write all the mappings from the dumper
for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
const MappingInfo& mapping = *dumper_->mappings()[i];
// Skip mappings which don't look like libraries.
if (!strstr(mapping.name, ".so") || // dump only libs (skip fonts, apks).
mapping.size < 4096) { // too small to get a signature for.
if (mapping.name[0] == 0 || // only want modules with filenames.
!mapping.exec || // only want executable mappings.
mapping.size < 4096 || // too small to get a signature for.
HaveMappingInfo(mapping)) {
continue;
}
if (HaveMappingInfo(mapping))
continue;
DumpModule(mapping, true, i, NULL);
}
// Next write all the mappings provided by the caller
@ -334,7 +367,7 @@ class MicrodumpWriter {
#endif
LinuxDumper* dumper_;
const MappingList& mapping_list_;
char log_line_[512];
char* log_line_;
};
} // namespace

View File

@ -0,0 +1,133 @@
// Copyright (c) 2014 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 <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include "breakpad_googletest_includes.h"
#include "client/linux/handler/exception_handler.h"
#include "client/linux/microdump_writer/microdump_writer.h"
#include "common/linux/eintr_wrapper.h"
#include "common/linux/ignore_ret.h"
#include "common/scoped_ptr.h"
#include "common/tests/auto_tempdir.h"
#include "common/using_std_string.h"
using namespace google_breakpad;
namespace {
typedef testing::Test MicrodumpWriterTest;
TEST(MicrodumpWriterTest, Setup) {
int fds[2];
ASSERT_NE(-1, pipe(fds));
AutoTempDir temp_dir;
string stderr_file = temp_dir.path() + "/stderr.log";
int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
ASSERT_NE(-1, err_fd);
const pid_t child = fork();
if (child == 0) {
close(fds[1]);
char b;
IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
close(fds[0]);
syscall(__NR_exit);
}
close(fds[0]);
ExceptionHandler::CrashContext context;
memset(&context, 0, sizeof(context));
// Set a non-zero tid to avoid tripping asserts.
context.tid = child;
// Push some extra mapping to check the MappingList logic.
const uint32_t memory_size = sysconf(_SC_PAGESIZE);
const char* kMemoryName = "libfoo.so";
const uint8_t kModuleGUID[sizeof(MDGUID)] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
MappingInfo info;
info.start_addr = memory_size;
info.size = memory_size;
info.offset = 42;
strcpy(info.name, kMemoryName);
MappingList mappings;
MappingEntry mapping;
mapping.first = info;
memcpy(mapping.second, kModuleGUID, sizeof(MDGUID));
mappings.push_back(mapping);
// Redirect temporarily stderr to the stderr.log file.
int save_err = dup(STDERR_FILENO);
ASSERT_NE(-1, save_err);
ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings));
// Revert stderr back to the console.
dup2(save_err, STDERR_FILENO);
close(save_err);
// Read back the stderr file and check for the microdump marker.
fsync(err_fd);
lseek(err_fd, 0, SEEK_SET);
const size_t kBufSize = 64 * 1024;
scoped_array<char> buf(new char[kBufSize]);
ASSERT_GT(read(err_fd, buf.get(), kBufSize), 0);
ASSERT_NE(static_cast<char*>(0), strstr(
buf.get(), "-----BEGIN BREAKPAD MICRODUMP-----"));
ASSERT_NE(static_cast<char*>(0), strstr(
buf.get(), "-----END BREAKPAD MICRODUMP-----"));
#ifdef __LP64__
ASSERT_NE(static_cast<char*>(0), strstr(
buf.get(), "M 0000000000001000 000000000000002A 0000000000001000 "
"33221100554477668899AABBCCDDEEFF0 libfoo.so"));
#else
ASSERT_NE(static_cast<char*>(0), strstr(
buf.get(), "M 00001000 0000002A 00001000 "
"33221100554477668899AABBCCDDEEFF0 libfoo.so"));
#endif
close(err_fd);
close(fds[1]);
}
} // namespace

View File

@ -74,7 +74,7 @@ bool LinuxCoreDumper::BuildProcPath(char* path, pid_t pid,
return true;
}
void LinuxCoreDumper::CopyFromProcess(void* dest, pid_t child,
bool LinuxCoreDumper::CopyFromProcess(void* dest, pid_t child,
const void* src, size_t length) {
ElfCoreDump::Addr virtual_address = reinterpret_cast<ElfCoreDump::Addr>(src);
// TODO(benchan): Investigate whether the data to be copied could span
@ -84,7 +84,9 @@ void LinuxCoreDumper::CopyFromProcess(void* dest, pid_t child,
// If the data segment is not found in the core dump, fill the result
// with marker characters.
memset(dest, 0xab, length);
return false;
}
return true;
}
bool LinuxCoreDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {

View File

@ -68,8 +68,9 @@ class LinuxCoreDumper : public LinuxDumper {
// Copies content of |length| bytes from a given process |child|,
// starting from |src|, into |dest|. This method extracts the content
// the core dump and fills |dest| with a sequence of marker bytes
// if the expected data is not found in the core dump.
virtual void CopyFromProcess(void* dest, pid_t child, const void* src,
// if the expected data is not found in the core dump. Returns true if
// the expected data is found in the core dump.
virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
size_t length);
// Implements LinuxDumper::GetThreadInfoByIndex().

View File

@ -100,8 +100,8 @@ class LinuxDumper {
PageAllocator* allocator() { return &allocator_; }
// Copy content of |length| bytes from a given process |child|,
// starting from |src|, into |dest|.
virtual void CopyFromProcess(void* dest, pid_t child, const void* src,
// starting from |src|, into |dest|. Returns true on success.
virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
size_t length) = 0;
// Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).

View File

@ -130,7 +130,7 @@ bool LinuxPtraceDumper::BuildProcPath(char* path, pid_t pid,
return true;
}
void LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
bool LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
const void* src, size_t length) {
unsigned long tmp = 55;
size_t done = 0;
@ -146,6 +146,7 @@ void LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
my_memcpy(local + done, &tmp, l);
done += l;
}
return true;
}
// Read thread info from /proc/$pid/status.
@ -282,8 +283,10 @@ bool LinuxPtraceDumper::ThreadsSuspend() {
// If the thread either disappeared before we could attach to it, or if
// it was part of the seccomp sandbox's trusted code, it is OK to
// silently drop it from the minidump.
my_memmove(&threads_[i], &threads_[i+1],
if (i < threads_.size() - 1) {
my_memmove(&threads_[i], &threads_[i + 1],
(threads_.size() - i - 1) * sizeof(threads_[i]));
}
threads_.resize(threads_.size() - 1);
--i;
}

View File

@ -55,8 +55,8 @@ class LinuxPtraceDumper : public LinuxDumper {
// Implements LinuxDumper::CopyFromProcess().
// Copies content of |length| bytes from a given process |child|,
// starting from |src|, into |dest|. This method uses ptrace to extract
// the content from the target process.
virtual void CopyFromProcess(void* dest, pid_t child, const void* src,
// the content from the target process. Always returns true.
virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
size_t length);
// Implements LinuxDumper::GetThreadInfoByIndex().

View File

@ -75,6 +75,7 @@
#include "client/linux/minidump_writer/proc_cpuinfo_reader.h"
#include "client/minidump_file_writer.h"
#include "common/linux/linux_libc_support.h"
#include "common/minidump_type_helper.h"
#include "google_breakpad/common/minidump_format.h"
#include "third_party/lss/linux_syscall_support.h"
@ -86,6 +87,7 @@ using google_breakpad::CpuSet;
using google_breakpad::LineReader;
using google_breakpad::LinuxDumper;
using google_breakpad::LinuxPtraceDumper;
using google_breakpad::MDTypeHelper;
using google_breakpad::MappingEntry;
using google_breakpad::MappingInfo;
using google_breakpad::MappingList;
@ -100,6 +102,8 @@ using google_breakpad::UContextReader;
using google_breakpad::UntypedMDRVA;
using google_breakpad::wasteful_vector;
typedef MDTypeHelper<sizeof(void*)>::MDRawDebug MDRawDebug;
typedef MDTypeHelper<sizeof(void*)>::MDRawLinkMap MDRawLinkMap;
class MinidumpWriter {
public:
@ -654,7 +658,9 @@ class MinidumpWriter {
ElfW(Addr) dyn_addr = 0;
for (; phnum >= 0; phnum--, phdr++) {
ElfW(Phdr) ph;
dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph));
if (!dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph)))
return false;
// Adjust base address with the virtual address of the PT_LOAD segment
// corresponding to offset 0
if (ph.p_type == PT_LOAD && ph.p_offset == 0) {
@ -675,11 +681,14 @@ class MinidumpWriter {
struct r_debug* r_debug = NULL;
uint32_t dynamic_length = 0;
for (int i = 0;;) {
for (int i = 0; ; ++i) {
ElfW(Dyn) dyn;
dynamic_length += sizeof(dyn);
dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic+i++,
sizeof(dyn));
if (!dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic + i,
sizeof(dyn))) {
return false;
}
if (dyn.d_tag == DT_DEBUG) {
r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
continue;
@ -699,11 +708,15 @@ class MinidumpWriter {
// Count the number of loaded DSOs
int dso_count = 0;
struct r_debug debug_entry;
dumper_->CopyFromProcess(&debug_entry, GetCrashThread(), r_debug,
sizeof(debug_entry));
if (!dumper_->CopyFromProcess(&debug_entry, GetCrashThread(), r_debug,
sizeof(debug_entry))) {
return false;
}
for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
struct link_map map;
dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map));
if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)))
return false;
ptr = map.l_next;
dso_count++;
}
@ -721,7 +734,9 @@ class MinidumpWriter {
// Iterate over DSOs and write their information to mini dump
for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
struct link_map map;
dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map));
if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)))
return false;
ptr = map.l_next;
char filename[257] = { 0 };
if (map.l_name) {
@ -733,8 +748,8 @@ class MinidumpWriter {
return false;
MDRawLinkMap entry;
entry.name = location.rva;
entry.addr = reinterpret_cast<void*>(map.l_addr);
entry.ld = reinterpret_cast<void*>(map.l_ld);
entry.addr = map.l_addr;
entry.ld = reinterpret_cast<uintptr_t>(map.l_ld);
linkmap.CopyIndex(idx++, &entry);
}
}
@ -750,9 +765,9 @@ class MinidumpWriter {
debug.get()->version = debug_entry.r_version;
debug.get()->map = linkmap_rva;
debug.get()->dso_count = dso_count;
debug.get()->brk = reinterpret_cast<void*>(debug_entry.r_brk);
debug.get()->ldbase = reinterpret_cast<void*>(debug_entry.r_ldbase);
debug.get()->dynamic = dynamic;
debug.get()->brk = debug_entry.r_brk;
debug.get()->ldbase = debug_entry.r_ldbase;
debug.get()->dynamic = reinterpret_cast<uintptr_t>(dynamic);
wasteful_vector<char> dso_debug_data(dumper_->allocator(), dynamic_length);
// The passed-in size to the constructor (above) is only a hint.

View File

@ -48,7 +48,7 @@
#import "common/mac/MachIPC.h"
#import "common/simple_string_dictionary.h"
#ifndef __EXCEPTIONS
#if !defined(__EXCEPTIONS) || (__clang__ && !__has_feature(cxx_exceptions))
// This file uses C++ try/catch (but shouldn't). Duplicate the macros from
// <c++/4.2.1/exception_defines.h> allowing this file to work properly with
// exceptions disabled even when other C++ libraries are used. #undef the try

View File

@ -174,6 +174,7 @@ void ExceptionHandler::Initialize(
assertion_ = NULL;
handler_return_value_ = false;
handle_debug_exceptions_ = false;
consume_invalid_handle_exceptions_ = false;
// Attempt to use out-of-process if user has specified a pipe or a
// crash generation client.
@ -481,6 +482,11 @@ LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS* exinfo) {
bool is_debug_exception = (code == EXCEPTION_BREAKPOINT) ||
(code == EXCEPTION_SINGLE_STEP);
if (code == EXCEPTION_INVALID_HANDLE &&
current_handler->consume_invalid_handle_exceptions_) {
return EXCEPTION_CONTINUE_EXECUTION;
}
bool success = false;
if (!is_debug_exception ||

View File

@ -263,6 +263,15 @@ class ExceptionHandler {
handle_debug_exceptions_ = handle_debug_exceptions;
}
// Controls behavior of EXCEPTION_INVALID_HANDLE.
bool get_consume_invalid_handle_exceptions() const {
return consume_invalid_handle_exceptions_;
}
void set_consume_invalid_handle_exceptions(
bool consume_invalid_handle_exceptions) {
consume_invalid_handle_exceptions_ = consume_invalid_handle_exceptions;
}
// Returns whether out-of-process dump generation is used or not.
bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; }
@ -472,6 +481,10 @@ class ExceptionHandler {
// to not interfere with debuggers.
bool handle_debug_exceptions_;
// If true, the handler will consume any EXCEPTION_INVALID_HANDLE exceptions.
// Leave this false (the default) to handle these exceptions as normal.
bool consume_invalid_handle_exceptions_;
// Callers can request additional memory regions to be included in
// the dump.
AppMemoryList app_memory_info_;

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

@ -183,14 +183,15 @@ const char* CompilationUnit::SkipAttribute(const char* start,
case DW_FORM_addr:
return start + reader_->AddressSize();
case DW_FORM_ref_addr:
// DWARF2 and 3 differ on whether ref_addr is address size or
// DWARF2 and 3/4 differ on whether ref_addr is address size or
// offset size.
assert(header_.version == 2 || header_.version == 3);
assert(header_.version >= 2);
if (header_.version == 2) {
return start + reader_->AddressSize();
} else if (header_.version == 3) {
} else if (header_.version >= 3) {
return start + reader_->OffsetSize();
}
break;
case DW_FORM_block1:
return start + 1 + reader_->ReadOneByte(start);
@ -390,14 +391,14 @@ const char* CompilationUnit::ProcessAttribute(
+ offset_from_section_start_);
return start + len;
case DW_FORM_ref_addr:
// DWARF2 and 3 differ on whether ref_addr is address size or
// DWARF2 and 3/4 differ on whether ref_addr is address size or
// offset size.
assert(header_.version == 2 || header_.version == 3);
assert(header_.version >= 2);
if (header_.version == 2) {
handler_->ProcessAttributeReference(dieoffset, attr, form,
reader_->ReadAddress(start));
return start + reader_->AddressSize();
} else if (header_.version == 3) {
} else if (header_.version >= 3) {
handler_->ProcessAttributeReference(dieoffset, attr, form,
reader_->ReadOffset(start));
return start + reader_->OffsetSize();

View File

@ -351,9 +351,15 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
break;
case dwarf2reader::DW_AT_MIPS_linkage_name: {
char* demangled = NULL;
#if !defined(__ANDROID__)
demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, NULL);
int status = -1;
#if !defined(__ANDROID__) // Android NDK doesn't provide abi::__cxa_demangle.
demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, &status);
#endif
if (status != 0) {
cu_context_->reporter->DemangleError(data, status);
demangled_name_ = "";
break;
}
if (demangled) {
demangled_name_ = AddStringToPool(demangled);
free(reinterpret_cast<void*>(demangled));
@ -396,6 +402,18 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
enclosing_name = &parent_context_->name;
}
// Prepare the return value before upcoming mutations possibly invalidate the
// existing pointers.
string return_value;
if (qualified_name) {
return_value = *qualified_name;
} else {
// Combine the enclosing name and unqualified name to produce our
// own fully-qualified name.
return_value = cu_context_->language->MakeQualifiedName(*enclosing_name,
*unqualified_name);
}
// If this DIE was marked as a declaration, record its names in the
// specification table.
if (declaration_) {
@ -409,13 +427,7 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
cu_context_->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,
*unqualified_name);
return return_value;
}
// A handler class for DW_TAG_subprogram DIEs.
@ -528,18 +540,19 @@ void DwarfCUToModule::FuncHandler::Finish() {
// functions that were never used), but all the ones we're
// interested in cover a non-empty range of bytes.
if (low_pc_ < high_pc_) {
// Create a Module::Function based on the data we've gathered, and
// add it to the functions_ list.
scoped_ptr<Module::Function> func(new Module::Function);
// Malformed DWARF may omit the name, but all Module::Functions must
// have names.
string name;
if (!name_.empty()) {
func->name = name_;
name = name_;
} else {
cu_context_->reporter->UnnamedFunction(offset_);
func->name = "<name omitted>";
name = "<name omitted>";
}
func->address = low_pc_;
// Create a Module::Function based on the data we've gathered, and
// add it to the functions_ list.
scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_));
func->size = high_pc_ - low_pc_;
func->parameter_size = 0;
if (func->address) {
@ -661,6 +674,13 @@ void DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) {
filename_.c_str(), offset);
}
void DwarfCUToModule::WarningReporter::DemangleError(
const string &input, int error) {
CUHeading();
fprintf(stderr, "%s: warning: failed to demangle %s with error %d\n",
filename_.c_str(), input.c_str(), error);
}
void DwarfCUToModule::WarningReporter::UnhandledInterCUReference(
uint64 offset, uint64 target) {
CUHeading();

View File

@ -199,6 +199,9 @@ class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
// link.
virtual void UnnamedFunction(uint64 offset);
// __cxa_demangle() failed to demangle INPUT.
virtual void DemangleError(const string &input, int error);
// The DW_FORM_ref_addr at OFFSET to TARGET was not handled because
// FilePrivate did not retain the inter-CU specification data.
virtual void UnhandledInterCUReference(uint64 offset, uint64 target);

View File

@ -81,6 +81,7 @@ class MockWarningReporter: public DwarfCUToModule::WarningReporter {
MOCK_METHOD1(UncoveredFunction, void(const Module::Function &function));
MOCK_METHOD1(UncoveredLine, void(const Module::Line &line));
MOCK_METHOD1(UnnamedFunction, void(uint64 offset));
MOCK_METHOD2(DemangleError, void(const string &input, int error));
MOCK_METHOD2(UnhandledInterCUReference, void(uint64 offset, uint64 target));
};
@ -1712,16 +1713,14 @@ TEST_F(CUErrors, BadCURootDIETag) {
// produce) output, so their results need to be checked by hand.
struct Reporter: public Test {
Reporter()
: reporter("filename", 0x123456789abcdef0ULL) {
: reporter("filename", 0x123456789abcdef0ULL),
function("function name", 0x19c45c30770c1eb0ULL),
file("source file name") {
reporter.SetCUName("compilation-unit-name");
function.name = "function name";
function.address = 0x19c45c30770c1eb0ULL;
function.size = 0x89808a5bdfa0a6a3ULL;
function.parameter_size = 0x6a329f18683dcd51ULL;
file.name = "source file name";
line.address = 0x3606ac6267aebeccULL;
line.size = 0x5de482229f32556aULL;
line.file = &file;

View File

@ -413,6 +413,15 @@ bool ElfEndianness(const typename ElfClass::Ehdr* elf_header,
return false;
}
// Given |left_abspath|, find the absolute path for |right_path| and see if the
// two absolute paths are the same.
bool IsSameFile(const char* left_abspath, const string& right_path) {
char right_abspath[PATH_MAX];
if (!realpath(right_path.c_str(), right_abspath))
return false;
return strcmp(left_abspath, right_abspath) == 0;
}
// Read the .gnu_debuglink and get the debug file name. If anything goes
// wrong, return an empty string.
string ReadDebugLink(const char* debuglink,
@ -430,14 +439,27 @@ string ReadDebugLink(const char* debuglink,
return string();
}
bool found = false;
int debuglink_fd = -1;
char obj_file_abspath[PATH_MAX];
if (!realpath(obj_file.c_str(), obj_file_abspath)) {
fprintf(stderr, "Cannot resolve absolute path for %s\n", obj_file.c_str());
return string();
}
std::vector<string> searched_paths;
string debuglink_path;
std::vector<string>::const_iterator it;
for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) {
const string& debug_dir = *it;
debuglink_path = debug_dir + "/" + debuglink;
debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
// There is the annoying case of /path/to/foo.so having foo.so as the
// debug link file name. Thus this may end up opening /path/to/foo.so again,
// and there is a small chance of the two files having the same CRC.
if (IsSameFile(obj_file_abspath, debuglink_path))
continue;
searched_paths.push_back(debug_dir);
int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
if (debuglink_fd < 0)
continue;
@ -469,21 +491,19 @@ string ReadDebugLink(const char* debuglink,
debuglink_path.c_str());
continue;
}
found = true;
break;
// Found debug file.
return debuglink_path;
}
if (!found) {
// Not found case.
fprintf(stderr, "Failed to find debug ELF file for '%s' after trying:\n",
obj_file.c_str());
for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) {
const string debug_dir = *it;
for (it = searched_paths.begin(); it < searched_paths.end(); ++it) {
const string& debug_dir = *it;
fprintf(stderr, " %s/%s\n", debug_dir.c_str(), debuglink);
}
return string();
}
return debuglink_path;
}
//
@ -628,6 +648,35 @@ bool LoadSymbols(const string& obj_file,
"DWARF debugging information\n", obj_file.c_str());
}
}
// See if there are export symbols available.
const Shdr* dynsym_section =
FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
sections, names, names_end,
elf_header->e_shnum);
const Shdr* dynstr_section =
FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
sections, names, names_end,
elf_header->e_shnum);
if (dynsym_section && dynstr_section) {
info->LoadedSection(".dynsym");
const uint8_t* dynsyms =
GetOffset<ElfClass, uint8_t>(elf_header,
dynsym_section->sh_offset);
const uint8_t* dynstrs =
GetOffset<ElfClass, uint8_t>(elf_header,
dynstr_section->sh_offset);
bool result =
ELFSymbolsToModule(dynsyms,
dynsym_section->sh_size,
dynstrs,
dynstr_section->sh_size,
big_endian,
ElfClass::kAddrSize,
module);
found_usable_info = found_usable_info || result;
}
}
if (options.symbol_data != NO_CFI) {
@ -689,8 +738,6 @@ bool LoadSymbols(const string& obj_file,
names_end, elf_header->e_shnum);
if (gnu_debuglink_section) {
if (!info->debug_dirs().empty()) {
found_debug_info_section = true;
const char* debuglink_contents =
GetOffset<ElfClass, char>(elf_header,
gnu_debuglink_section->sh_offset);
@ -709,45 +756,18 @@ bool LoadSymbols(const string& obj_file,
fprintf(stderr, "%s does not contain a .gnu_debuglink section.\n",
obj_file.c_str());
}
}
}
if (options.symbol_data != ONLY_CFI) {
const Shdr* dynsym_section =
FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
sections, names, names_end,
elf_header->e_shnum);
const Shdr* dynstr_section =
FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
sections, names, names_end,
elf_header->e_shnum);
if (dynsym_section && dynstr_section) {
info->LoadedSection(".dynsym");
const uint8_t* dynsyms =
GetOffset<ElfClass, uint8_t>(elf_header,
dynsym_section->sh_offset);
const uint8_t* dynstrs =
GetOffset<ElfClass, uint8_t>(elf_header,
dynstr_section->sh_offset);
bool result =
ELFSymbolsToModule(dynsyms,
dynsym_section->sh_size,
dynstrs,
dynstr_section->sh_size,
big_endian,
ElfClass::kAddrSize,
module);
found_usable_info = found_usable_info || result;
}
}
if (read_gnu_debug_link) {
return found_debug_info_section;
}
// Return true if some usable information was found
} else {
// Return true if some usable information was found, since the caller
// doesn't want to use .gnu_debuglink.
return found_usable_info;
}
// No debug info was found, let the user try again with .gnu_debuglink
// if present.
return false;
}
return true;
}
// Return the breakpad symbol file identifier for the architecture of
@ -800,6 +820,37 @@ string BaseFileName(const string &filename) {
return base;
}
template<typename ElfClass>
bool SanitizeDebugFile(const typename ElfClass::Ehdr* debug_elf_header,
const string& debuglink_file,
const string& obj_filename,
const char* obj_file_architecture,
const bool obj_file_is_big_endian) {
const char* debug_architecture =
ElfArchitecture<ElfClass>(debug_elf_header);
if (!debug_architecture) {
fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
debuglink_file.c_str(), debug_elf_header->e_machine);
return false;
}
if (strcmp(obj_file_architecture, debug_architecture)) {
fprintf(stderr, "%s with ELF machine architecture %s does not match "
"%s with ELF architecture %s\n",
debuglink_file.c_str(), debug_architecture,
obj_filename.c_str(), obj_file_architecture);
return false;
}
bool debug_big_endian;
if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian))
return false;
if (debug_big_endian != obj_file_is_big_endian) {
fprintf(stderr, "%s and %s does not match in endianness\n",
obj_filename.c_str(), debuglink_file.c_str());
return false;
}
return true;
}
template<typename ElfClass>
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
@ -849,34 +900,13 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
MmapWrapper debug_map_wrapper;
Ehdr* debug_elf_header = NULL;
if (!LoadELF(debuglink_file, &debug_map_wrapper,
reinterpret_cast<void**>(&debug_elf_header)))
return false;
// Sanity checks to make sure everything matches up.
const char *debug_architecture =
ElfArchitecture<ElfClass>(debug_elf_header);
if (!debug_architecture) {
fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
debuglink_file.c_str(), debug_elf_header->e_machine);
return false;
}
if (strcmp(architecture, debug_architecture)) {
fprintf(stderr, "%s with ELF machine architecture %s does not match "
"%s with ELF architecture %s\n",
debuglink_file.c_str(), debug_architecture,
obj_filename.c_str(), architecture);
reinterpret_cast<void**>(&debug_elf_header)) ||
!SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file,
obj_filename, architecture, big_endian)) {
return false;
}
bool debug_big_endian;
if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian))
return false;
if (debug_big_endian != big_endian) {
fprintf(stderr, "%s and %s does not match in endianness\n",
obj_filename.c_str(), debuglink_file.c_str());
return false;
}
if (!LoadSymbols<ElfClass>(debuglink_file, debug_big_endian,
if (!LoadSymbols<ElfClass>(debuglink_file, big_endian,
debug_elf_header, false, &info,
options, module.get())) {
return false;

View File

@ -32,6 +32,7 @@
#include "common/linux/elf_symbols_to_module.h"
#include <cxxabi.h>
#include <elf.h>
#include <string.h>
@ -155,9 +156,18 @@ bool ELFSymbolsToModule(const uint8_t *symtab_section,
while(!iterator->at_end) {
if (ELF32_ST_TYPE(iterator->info) == STT_FUNC &&
iterator->shndx != SHN_UNDEF) {
Module::Extern *ext = new Module::Extern;
Module::Extern *ext = new Module::Extern(iterator->value);
ext->name = SymbolString(iterator->name_offset, strings);
ext->address = iterator->value;
#if !defined(__ANDROID__) // Android NDK doesn't provide abi::__cxa_demangle.
int status = 0;
char* demangled =
abi::__cxa_demangle(ext->name.c_str(), NULL, NULL, &status);
if (demangled) {
if (status == 0)
ext->name = demangled;
free(demangled);
}
#endif
module->AddExtern(ext);
}
++iterator;

View File

@ -0,0 +1,56 @@
// Copyright (c) 2014, 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.
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_
#include <stdint.h>
#include "google_breakpad/common/minidump_format.h"
namespace google_breakpad {
template <size_t>
struct MDTypeHelper;
template <>
struct MDTypeHelper<sizeof(uint32_t)> {
typedef MDRawDebug32 MDRawDebug;
typedef MDRawLinkMap32 MDRawLinkMap;
};
template <>
struct MDTypeHelper<sizeof(uint64_t)> {
typedef MDRawDebug64 MDRawDebug;
typedef MDRawLinkMap64 MDRawLinkMap;
};
} // namespace google_breakpad
#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_

View File

@ -79,8 +79,34 @@ void Module::AddFunction(Function *function) {
// FUNC lines must not hold an empty name, so catch the problem early if
// callers try to add one.
assert(!function->name.empty());
// FUNCs are better than PUBLICs as they come with sizes, so remove an extern
// with the same address if present.
Extern ext(function->address);
ExternSet::iterator it_ext = externs_.find(&ext);
if (it_ext == externs_.end() &&
architecture_ == "arm" &&
(function->address & 0x1) == 0) {
// ARM THUMB functions have bit 0 set. ARM64 does not have THUMB.
Extern arm_thumb_ext(function->address | 0x1);
it_ext = externs_.find(&arm_thumb_ext);
}
if (it_ext != externs_.end()) {
delete *it_ext;
externs_.erase(it_ext);
}
#if _DEBUG
{
// There should be no other PUBLIC symbols that overlap with the function.
Extern debug_ext(function->address);
ExternSet::iterator it_debug = externs_.lower_bound(&ext);
assert(it_debug == externs_.end() ||
(*it_debug)->address >= function->address + function->size);
}
#endif
std::pair<FunctionSet::iterator,bool> ret = functions_.insert(function);
if (!ret.second) {
if (!ret.second && (*ret.first != function)) {
// Free the duplicate that was not inserted because this Module
// now owns it.
delete function;
@ -98,23 +124,12 @@ void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) {
}
void Module::AddExtern(Extern *ext) {
Function func;
func.name = ext->name;
func.address = ext->address;
// Since parsing debug section and public info are not necessarily
// mutually exclusive, check if the symbol has already been read
// as a function to avoid duplicates.
if (functions_.find(&func) == functions_.end()) {
std::pair<ExternSet::iterator,bool> ret = externs_.insert(ext);
if (!ret.second) {
// Free the duplicate that was not inserted because this Module
// now owns it.
delete ext;
}
} else {
delete ext;
}
}
void Module::GetFunctions(vector<Function *> *vec,
@ -141,8 +156,7 @@ Module::File *Module::FindFile(const string &name) {
FileByNameMap::iterator destiny = files_.lower_bound(&name);
if (destiny == files_.end()
|| *destiny->first != name) { // Repeated string comparison, boo hoo.
File *file = new File;
file->name = name;
File *file = new File(name);
file->source_id = -1;
destiny = files_.insert(destiny,
FileByNameMap::value_type(&file->name, file));

View File

@ -74,8 +74,10 @@ class Module {
// A source file.
struct File {
explicit File(const string &name_input) : name(name_input), source_id(0) {}
// The name of the source file.
string name;
const string name;
// The file's source id. The Write member function clears this
// field and assigns source ids a fresh, so any value placed here
@ -85,6 +87,9 @@ class Module {
// A function.
struct Function {
Function(const string &name_input, const Address &address_input) :
name(name_input), address(address_input), size(0), parameter_size(0) {}
// For sorting by address. (Not style-guide compliant, but it's
// stupid not to put this in the struct.)
static bool CompareByAddress(const Function *x, const Function *y) {
@ -92,10 +97,11 @@ class Module {
}
// The function's name.
string name;
const string name;
// The start address and length of the function's code.
Address address, size;
const Address address;
Address size;
// The function's parameter size.
Address parameter_size;
@ -120,7 +126,8 @@ class Module {
// An exported symbol.
struct Extern {
Address address;
explicit Extern(const Address &address_input) : address(address_input) {}
const Address address;
string name;
};

View File

@ -54,9 +54,7 @@ static Module::Function *generate_duplicate_function(const string &name) {
const Module::Address DUP_SIZE = 0x200b26e605f99071LL;
const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
Module::Function *function = new(Module::Function);
function->name = name;
function->address = DUP_ADDRESS;
Module::Function *function = new Module::Function(name, DUP_ADDRESS);
function->size = DUP_SIZE;
function->parameter_size = DUP_PARAMETER_SIZE;
return function;
@ -81,9 +79,8 @@ TEST(Write, OneLineFunc) {
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
Module::File *file = m.FindFile("file_name.cc");
Module::Function *function = new(Module::Function);
function->name = "function_name";
function->address = 0xe165bf8023b9d9abLL;
Module::Function *function = new Module::Function(
"function_name", 0xe165bf8023b9d9abLL);
function->size = 0x1e4bb0eb1cbf5b09LL;
function->parameter_size = 0x772beee89114358aLL;
Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL,
@ -110,9 +107,8 @@ TEST(Write, RelativeLoadAddress) {
Module::File *file2 = m.FindFile("filename-a.cc");
// A function.
Module::Function *function = new(Module::Function);
function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)";
function->address = 0xbec774ea5dd935f3LL;
Module::Function *function = new Module::Function(
"A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
function->size = 0x2922088f98d3f6fcLL;
function->parameter_size = 0xe5e9aa008bd5f0d0LL;
@ -168,9 +164,8 @@ TEST(Write, OmitUnusedFiles) {
Module::File *file3 = m.FindFile("filename3");
// Create a function.
Module::Function *function = new(Module::Function);
function->name = "function_name";
function->address = 0x9b926d464f0b9384LL;
Module::Function *function = new Module::Function(
"function_name", 0x9b926d464f0b9384LL);
function->size = 0x4f524a4ba795e6a6LL;
function->parameter_size = 0xbbe8133a6641c9b7LL;
@ -217,9 +212,8 @@ TEST(Write, NoCFI) {
Module::File *file1 = m.FindFile("filename.cc");
// A function.
Module::Function *function = new(Module::Function);
function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)";
function->address = 0xbec774ea5dd935f3LL;
Module::Function *function = new Module::Function(
"A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
function->size = 0x2922088f98d3f6fcLL;
function->parameter_size = 0xe5e9aa008bd5f0d0LL;
@ -260,15 +254,13 @@ TEST(Construct, AddFunctions) {
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
// Two functions.
Module::Function *function1 = new(Module::Function);
function1->name = "_without_form";
function1->address = 0xd35024aa7ca7da5cLL;
Module::Function *function1 = new Module::Function(
"_without_form", 0xd35024aa7ca7da5cLL);
function1->size = 0x200b26e605f99071LL;
function1->parameter_size = 0xf14ac4fed48c4a99LL;
Module::Function *function2 = new(Module::Function);
function2->name = "_and_void";
function2->address = 0x2987743d0b35b13fLL;
Module::Function *function2 = new Module::Function(
"_and_void", 0x2987743d0b35b13fLL);
function2->size = 0xb369db048deb3010LL;
function2->parameter_size = 0x938e556cb5a79988LL;
@ -443,11 +435,9 @@ TEST(Construct, Externs) {
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
// Two externs.
Module::Extern *extern1 = new(Module::Extern);
extern1->address = 0xffff;
Module::Extern *extern1 = new Module::Extern(0xffff);
extern1->name = "_abc";
Module::Extern *extern2 = new(Module::Extern);
extern2->address = 0xaaaa;
Module::Extern *extern2 = new Module::Extern(0xaaaa);
extern2->name = "_xyz";
m.AddExtern(extern1);
@ -470,11 +460,9 @@ TEST(Construct, DuplicateExterns) {
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
// Two externs.
Module::Extern *extern1 = new(Module::Extern);
extern1->address = 0xffff;
Module::Extern *extern1 = new Module::Extern(0xffff);
extern1->name = "_xyz";
Module::Extern *extern2 = new(Module::Extern);
extern2->address = 0xffff;
Module::Extern *extern2 = new Module::Extern(0xffff);
extern2->name = "_abc";
m.AddExtern(extern1);
@ -488,3 +476,71 @@ TEST(Construct, DuplicateExterns) {
"PUBLIC ffff 0 _xyz\n",
contents.c_str());
}
// If there exists an extern and a function at the same address, only write
// out the FUNC entry.
TEST(Construct, FunctionsAndExternsWithSameAddress) {
stringstream s;
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
// Two externs.
Module::Extern* extern1 = new Module::Extern(0xabc0);
extern1->name = "abc";
Module::Extern* extern2 = new Module::Extern(0xfff0);
extern2->name = "xyz";
m.AddExtern(extern1);
m.AddExtern(extern2);
Module::Function* function = new Module::Function("_xyz", 0xfff0);
function->size = 0x10;
function->parameter_size = 0;
m.AddFunction(function);
m.Write(s, ALL_SYMBOL_DATA);
string contents = s.str();
EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
MODULE_ID " " MODULE_NAME "\n"
"FUNC fff0 10 0 _xyz\n"
"PUBLIC abc0 0 abc\n",
contents.c_str());
}
// If there exists an extern and a function at the same address, only write
// out the FUNC entry. For ARM THUMB, the extern that comes from the ELF
// symbol section has bit 0 set.
TEST(Construct, FunctionsAndThumbExternsWithSameAddress) {
stringstream s;
Module m(MODULE_NAME, MODULE_OS, "arm", MODULE_ID);
// Two THUMB externs.
Module::Extern* thumb_extern1 = new Module::Extern(0xabc1);
thumb_extern1->name = "thumb_abc";
Module::Extern* thumb_extern2 = new Module::Extern(0xfff1);
thumb_extern2->name = "thumb_xyz";
Module::Extern* arm_extern1 = new Module::Extern(0xcc00);
arm_extern1->name = "arm_func";
m.AddExtern(thumb_extern1);
m.AddExtern(thumb_extern2);
m.AddExtern(arm_extern1);
// The corresponding function from the DWARF debug data have the actual
// address.
Module::Function* function = new Module::Function("_thumb_xyz", 0xfff0);
function->size = 0x10;
function->parameter_size = 0;
m.AddFunction(function);
m.Write(s, ALL_SYMBOL_DATA);
string contents = s.str();
EXPECT_STREQ("MODULE " MODULE_OS " arm "
MODULE_ID " " MODULE_NAME "\n"
"FUNC fff0 10 0 _thumb_xyz\n"
"PUBLIC abc1 0 thumb_abc\n"
"PUBLIC cc00 0 arm_func\n",
contents.c_str());
}

View File

@ -90,9 +90,7 @@ bool StabsToModule::EndCompilationUnit(uint64_t address) {
bool StabsToModule::StartFunction(const string &name,
uint64_t address) {
assert(!current_function_);
Module::Function *f = new Module::Function;
f->name = Demangle(name);
f->address = address;
Module::Function *f = new Module::Function(Demangle(name), address);
f->size = 0; // We compute this in StabsToModule::Finalize().
f->parameter_size = 0; // We don't provide this information.
current_function_ = f;
@ -133,7 +131,7 @@ bool StabsToModule::Line(uint64_t address, const char *name, int number) {
}
bool StabsToModule::Extern(const string &name, uint64_t address) {
Module::Extern *ext = new Module::Extern;
Module::Extern *ext = new Module::Extern(address);
// Older libstdc++ demangle implementations can crash on unexpected
// input, so be careful about what gets passed in.
if (name.compare(0, 3, "__Z") == 0) {
@ -143,7 +141,6 @@ bool StabsToModule::Extern(const string &name, uint64_t address) {
} else {
ext->name = name;
}
ext->address = address;
module_->AddExtern(ext);
return true;
}

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

@ -35,7 +35,7 @@
#include <atlcomcli.h>
#include <hash_map>
#include <unordered_map>
#include <string>
#include "common/windows/omap.h"
@ -47,7 +47,7 @@ struct IDiaSymbol;
namespace google_breakpad {
using std::wstring;
using stdext::hash_map;
using std::unordered_map;
// A structure that carries information that identifies a pdb file.
struct PDBModuleInfo {
@ -192,7 +192,7 @@ class PDBSourceLineWriter {
// Store this ID in the cache as a duplicate for this filename.
void StoreDuplicateFileID(const wstring &file, DWORD id) {
hash_map<wstring, DWORD>::iterator iter = unique_files_.find(file);
unordered_map<wstring, DWORD>::iterator iter = unique_files_.find(file);
if (iter != unique_files_.end()) {
// map this id to the previously seen one
file_ids_[id] = iter->second;
@ -204,7 +204,7 @@ class PDBSourceLineWriter {
// but different unique IDs. The cache attempts to coalesce these into
// one ID per unique filename.
DWORD GetRealFileID(DWORD id) {
hash_map<DWORD, DWORD>::iterator iter = file_ids_.find(id);
unordered_map<DWORD, DWORD>::iterator iter = file_ids_.find(id);
if (iter == file_ids_.end())
return id;
return iter->second;
@ -240,9 +240,9 @@ class PDBSourceLineWriter {
// There may be many duplicate filenames with different IDs.
// This maps from the DIA "unique ID" to a single ID per unique
// filename.
hash_map<DWORD, DWORD> file_ids_;
unordered_map<DWORD, DWORD> file_ids_;
// This maps unique filenames to file IDs.
hash_map<wstring, DWORD> unique_files_;
unordered_map<wstring, DWORD> unique_files_;
// This is used for calculating post-transform symbol addresses and lengths.
ImageMap image_map_;

View File

@ -342,7 +342,7 @@ typedef enum {
MD_LINUX_ENVIRON = 0x47670007, /* /proc/$x/environ */
MD_LINUX_AUXV = 0x47670008, /* /proc/$x/auxv */
MD_LINUX_MAPS = 0x47670009, /* /proc/$x/maps */
MD_LINUX_DSO_DEBUG = 0x4767000A /* MDRawDebug */
MD_LINUX_DSO_DEBUG = 0x4767000A /* MDRawDebug{32,64} */
} MDStreamType; /* MINIDUMP_STREAM_TYPE */
@ -930,21 +930,39 @@ typedef enum {
} MDAssertionInfoData;
/* These structs are used to store the DSO debug data in Linux minidumps,
* which is necessary for converting minidumps to usable coredumps. */
* which is necessary for converting minidumps to usable coredumps.
* Because of a historical accident, several fields are variably encoded
* according to client word size, so tools potentially need to support both. */
typedef struct {
void* addr;
uint32_t addr;
MDRVA name;
void* ld;
} MDRawLinkMap;
uint32_t ld;
} MDRawLinkMap32;
typedef struct {
uint32_t version;
MDRVA map;
MDRVA map; /* array of MDRawLinkMap32 */
uint32_t dso_count;
void* brk;
void* ldbase;
void* dynamic;
} MDRawDebug;
uint32_t brk;
uint32_t ldbase;
uint32_t dynamic;
} MDRawDebug32;
typedef struct {
uint64_t addr;
MDRVA name;
uint64_t ld;
} MDRawLinkMap64;
typedef struct {
uint32_t version;
MDRVA map; /* array of MDRawLinkMap64 */
uint32_t dso_count;
uint64_t brk;
uint64_t ldbase;
uint64_t dynamic;
} MDRawDebug64;
#if defined(_MSC_VER)
#pragma warning(pop)

View File

@ -0,0 +1,126 @@
// Copyright (c) 2014 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.
// microdump.h: A microdump reader. Microdump is a minified variant of a
// minidump (see minidump.h for documentation) which contains the minimum
// amount of information required to get a stack trace for the crashing thread.
// The information contained in a microdump is:
// - the crashing thread stack
// - system information (os type / version)
// - cpu context (state of the registers)
// - list of mmaps
#ifndef GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__
#define GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__
#include <string>
#include <vector>
#include "common/scoped_ptr.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/dump_context.h"
#include "google_breakpad/processor/memory_region.h"
#include "google_breakpad/processor/system_info.h"
#include "processor/basic_code_modules.h"
namespace google_breakpad {
// MicrodumpModuleList contains all of the loaded code modules for a process
// in the form of MicrodumpModules. It maintains a vector of these modules
// and provides access to a code module corresponding to a specific address.
class MicrodumpModules : public BasicCodeModules {
public:
// Takes over ownership of |module|.
void Add(const CodeModule* module);
};
// MicrodumpContext carries a CPU-specific context.
// See dump_context.h for documentation.
class MicrodumpContext : public DumpContext {
public:
virtual void SetContextARM(MDRawContextARM* arm);
virtual void SetContextARM64(MDRawContextARM64* arm64);
};
// This class provides access to microdump memory regions.
// See memory_region.h for documentation.
class MicrodumpMemoryRegion : public MemoryRegion {
public:
MicrodumpMemoryRegion();
virtual ~MicrodumpMemoryRegion() {}
// Set this region's address and contents. If we have placed an
// instance of this class in a test fixture class, individual tests
// can use this to provide the region's contents.
void Init(uint64_t base_address, const std::vector<uint8_t>& contents);
virtual uint64_t GetBase() const;
virtual uint32_t GetSize() const;
virtual bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const;
virtual bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const;
virtual bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const;
virtual bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const;
// Print a human-readable representation of the object to stdout.
virtual void Print() const;
private:
// Fetch a little-endian value from ADDRESS in contents_ whose size
// is BYTES, and store it in *VALUE. Returns true on success.
template<typename ValueType>
bool GetMemoryLittleEndian(uint64_t address, ValueType* value) const;
uint64_t base_address_;
std::vector<uint8_t> contents_;
};
// Microdump is the user's interface to a microdump file. It provides access to
// the microdump's context, memory regions and modules.
class Microdump {
public:
explicit Microdump(const string& contents);
virtual ~Microdump() {}
DumpContext* GetContext() { return context_.get(); }
MicrodumpMemoryRegion* GetMemory() { return stack_region_.get(); }
MicrodumpModules* GetModules() { return modules_.get(); }
SystemInfo* GetSystemInfo() { return system_info_.get(); }
private:
scoped_ptr<MicrodumpContext> context_;
scoped_ptr<MicrodumpMemoryRegion> stack_region_;
scoped_ptr<MicrodumpModules> modules_;
scoped_ptr<SystemInfo> system_info_;
};
} // namespace google_breakpad
#endif // GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__

View File

@ -27,6 +27,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The processor for microdump (a reduced dump containing only the state of the
// crashing thread). See crbug.com/410294 for more info and design docs.
#ifndef GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_PROCESSOR_H__
#define GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_PROCESSOR_H__

View File

@ -732,6 +732,7 @@ class MinidumpMiscInfo : public MinidumpStream {
private:
friend class Minidump;
friend class TestMinidumpMiscInfo;
static const uint32_t kStreamType = MD_MISC_INFO_STREAM;
@ -902,14 +903,14 @@ class Minidump {
// to avoid exposing an ugly API (GetStream needs to accept a garbage
// parameter).
virtual MinidumpThreadList* GetThreadList();
MinidumpModuleList* GetModuleList();
virtual MinidumpModuleList* GetModuleList();
virtual MinidumpMemoryList* GetMemoryList();
MinidumpException* GetException();
MinidumpAssertion* GetAssertion();
virtual MinidumpException* GetException();
virtual MinidumpAssertion* GetAssertion();
virtual MinidumpSystemInfo* GetSystemInfo();
MinidumpMiscInfo* GetMiscInfo();
MinidumpBreakpadInfo* GetBreakpadInfo();
MinidumpMemoryInfoList* GetMemoryInfoList();
virtual MinidumpMiscInfo* GetMiscInfo();
virtual MinidumpBreakpadInfo* GetBreakpadInfo();
virtual MinidumpMemoryInfoList* GetMemoryInfoList();
// The next set of methods are provided for users who wish to access
// data in minidump files directly, while leveraging the rest of

View File

@ -89,6 +89,12 @@ class MinidumpProcessor {
// the minidump.
static bool GetOSInfo(Minidump* dump, SystemInfo* info);
// Populates the |process_create_time| parameter with the create time of the
// crashed process. Returns false if this information is not available in
// the minidump |dump|.
static bool GetProcessCreateTime(Minidump* dump,
uint32_t* process_create_time);
// Returns a textual representation of the reason that a crash occurred,
// if the minidump in dump was produced as a result of a crash. Returns
// an empty string if this information cannot be determined. If address

View File

@ -97,6 +97,7 @@ class ProcessState {
// Accessors. See the data declarations below.
uint32_t time_date_stamp() const { return time_date_stamp_; }
uint32_t process_create_time() const { return process_create_time_; }
bool crashed() const { return crashed_; }
string crash_reason() const { return crash_reason_; }
uint64_t crash_address() const { return crash_address_; }
@ -117,12 +118,17 @@ class ProcessState {
ExploitabilityRating exploitability() const { return exploitability_; }
private:
// MinidumpProcessor is responsible for building ProcessState objects.
// MinidumpProcessor and MicrodumpProcessor are responsible for building
// ProcessState objects.
friend class MinidumpProcessor;
friend class MicrodumpProcessor;
// The time-date stamp of the minidump (time_t format)
uint32_t time_date_stamp_;
// The time-date stamp when the process was created (time_t format)
uint32_t process_create_time_;
// True if the process crashed, false if the dump was produced outside
// of an exception handler.
bool crashed_;

View File

@ -73,6 +73,11 @@ BasicCodeModules::BasicCodeModules(const CodeModules *that)
}
}
BasicCodeModules::BasicCodeModules()
: main_address_(0),
map_(new RangeMap<uint64_t, linked_ptr<const CodeModule> >()) {
}
BasicCodeModules::~BasicCodeModules() {
delete map_;
}

View File

@ -67,7 +67,9 @@ class BasicCodeModules : public CodeModules {
virtual const CodeModule* GetModuleAtIndex(unsigned int index) const;
virtual const CodeModules* Copy() const;
private:
protected:
BasicCodeModules();
// The base address of the main module.
uint64_t main_address_;
@ -75,6 +77,7 @@ class BasicCodeModules : public CodeModules {
// address range.
RangeMap<uint64_t, linked_ptr<const CodeModule> > *map_;
private:
// Disallow copy constructor and assignment operator.
BasicCodeModules(const BasicCodeModules &that);
void operator=(const BasicCodeModules &that);

View File

@ -43,7 +43,6 @@
#define snprintf _snprintf
#else // _WIN32
#include <unistd.h>
#define O_BINARY 0
#endif // _WIN32
#include "processor/logging.h"

306
src/processor/microdump.cc Normal file
View File

@ -0,0 +1,306 @@
// Copyright (c) 2014 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.
// microdump.cc: A microdump reader.
//
// See microdump.h for documentation.
#include "google_breakpad/processor/microdump.h"
#include <stdio.h>
#include <string.h>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "google_breakpad/common/minidump_cpu_arm.h"
#include "google_breakpad/processor/code_module.h"
#include "processor/basic_code_module.h"
#include "processor/linked_ptr.h"
#include "processor/logging.h"
#include "processor/range_map-inl.h"
namespace {
static const char kGoogleBreakpadKey[] = "/google-breakpad(";
static const char kMicrodumpBegin[] = "-----BEGIN BREAKPAD MICRODUMP-----";
static const char kMicrodumpEnd[] = "-----END BREAKPAD MICRODUMP-----";
static const char kOsKey[] = ": O ";
static const char kCpuKey[] = ": C ";
static const char kMmapKey[] = ": M ";
static const char kStackKey[] = ": S ";
static const char kStackFirstLineKey[] = ": S 0 ";
static const char kArmArchitecture[] = "arm";
static const char kArm64Architecture[] = "arm64";
template<typename T>
T HexStrToL(const string& str) {
uint64_t res = 0;
std::istringstream ss(str);
ss >> std::hex >> res;
return static_cast<T>(res);
}
std::vector<uint8_t> ParseHexBuf(const string& str) {
std::vector<uint8_t> buf;
for (size_t i = 0; i < str.length(); i += 2) {
buf.push_back(HexStrToL<uint8_t>(str.substr(i, 2)));
}
return buf;
}
} // namespace
namespace google_breakpad {
//
// MicrodumpModules
//
void MicrodumpModules::Add(const CodeModule* module) {
linked_ptr<const CodeModule> module_ptr(module);
if (!map_->StoreRange(module->base_address(), module->size(), module_ptr)) {
BPLOG(ERROR) << "Module " << module->code_file() <<
" could not be stored";
}
}
//
// MicrodumpContext
//
void MicrodumpContext::SetContextARM(MDRawContextARM* arm) {
DumpContext::SetContextFlags(MD_CONTEXT_ARM);
DumpContext::SetContextARM(arm);
valid_ = true;
}
void MicrodumpContext::SetContextARM64(MDRawContextARM64* arm64) {
DumpContext::SetContextFlags(MD_CONTEXT_ARM64);
DumpContext::SetContextARM64(arm64);
valid_ = true;
}
//
// MicrodumpMemoryRegion
//
MicrodumpMemoryRegion::MicrodumpMemoryRegion() : base_address_(0) { }
void MicrodumpMemoryRegion::Init(uint64_t base_address,
const std::vector<uint8_t>& contents) {
base_address_ = base_address;
contents_ = contents;
}
uint64_t MicrodumpMemoryRegion::GetBase() const { return base_address_; }
uint32_t MicrodumpMemoryRegion::GetSize() const { return contents_.size(); }
bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
uint8_t* value) const {
return GetMemoryLittleEndian(address, value);
}
bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
uint16_t* value) const {
return GetMemoryLittleEndian(address, value);
}
bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
uint32_t* value) const {
return GetMemoryLittleEndian(address, value);
}
bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
uint64_t* value) const {
return GetMemoryLittleEndian(address, value);
}
template<typename ValueType>
bool MicrodumpMemoryRegion::GetMemoryLittleEndian(uint64_t address,
ValueType* value) const {
if (address < base_address_ ||
address - base_address_ + sizeof(ValueType) > contents_.size())
return false;
ValueType v = 0;
uint64_t start = address - base_address_;
// The loop condition is odd, but it's correct for size_t.
for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--)
v = (v << 8) | static_cast<uint8_t>(contents_[start + i]);
*value = v;
return true;
}
void MicrodumpMemoryRegion::Print() const {
// Not reached, just needed to honor the base class contract.
assert(false);
}
//
// Microdump
//
Microdump::Microdump(const string& contents)
: context_(new MicrodumpContext()),
stack_region_(new MicrodumpMemoryRegion()),
modules_(new MicrodumpModules()),
system_info_(new SystemInfo()) {
assert(!contents.empty());
bool in_microdump = false;
string line;
uint64_t stack_start = 0;
std::vector<uint8_t> stack_content;
string arch;
std::istringstream stream(contents);
while (std::getline(stream, line)) {
if (line.find(kGoogleBreakpadKey) == string::npos) {
continue;
}
if (line.find(kMicrodumpBegin) != string::npos) {
in_microdump = true;
continue;
}
if (line.find(kMicrodumpEnd) != string::npos) {
break;
}
if (!in_microdump) {
continue;
}
size_t pos;
if ((pos = line.find(kOsKey)) != string::npos) {
string os_str(line, pos + strlen(kOsKey));
std::istringstream os_tokens(os_str);
string os_id;
string num_cpus;
string os_version;
// This reflect the actual HW arch and might not match the arch emulated
// for the execution (e.g., running a 32-bit binary on a 64-bit cpu).
string hw_arch;
os_tokens >> os_id;
os_tokens >> arch;
os_tokens >> num_cpus;
os_tokens >> hw_arch;
std::getline(os_tokens, os_version);
os_version.erase(0, 1); // remove leading space.
system_info_->cpu = hw_arch;
system_info_->cpu_count = HexStrToL<uint8_t>(num_cpus);
system_info_->os_version = os_version;
if (os_id == "L") {
system_info_->os = "Linux";
system_info_->os_short = "linux";
} else if (os_id == "A") {
system_info_->os = "Android";
system_info_->os_short = "android";
}
// OS line also contains release and version for future use.
} else if ((pos = line.find(kStackKey)) != string::npos) {
if (line.find(kStackFirstLineKey) != string::npos) {
// The first line of the stack (S 0 stack header) provides the value of
// the stack pointer, the start address of the stack being dumped and
// the length of the stack. We could use it in future to double check
// that we received all the stack as expected.
continue;
}
string stack_str(line, pos + strlen(kStackKey));
std::istringstream stack_tokens(stack_str);
string start_addr_str;
string raw_content;
stack_tokens >> start_addr_str;
stack_tokens >> raw_content;
uint64_t start_addr = HexStrToL<uint64_t>(start_addr_str);
if (stack_start != 0) {
// Verify that the stack chunks in the microdump are contiguous.
assert(start_addr == stack_start + stack_content.size());
} else {
stack_start = start_addr;
}
std::vector<uint8_t> chunk = ParseHexBuf(raw_content);
stack_content.insert(stack_content.end(), chunk.begin(), chunk.end());
} else if ((pos = line.find(kCpuKey)) != string::npos) {
string cpu_state_str(line, pos + strlen(kCpuKey));
std::vector<uint8_t> cpu_state_raw = ParseHexBuf(cpu_state_str);
if (strcmp(arch.c_str(), kArmArchitecture) == 0) {
if (cpu_state_raw.size() != sizeof(MDRawContextARM)) {
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
" bytes instead of " << sizeof(MDRawContextARM) << std::endl;
continue;
}
MDRawContextARM* arm = new MDRawContextARM();
memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
context_->SetContextARM(arm);
} else if (strcmp(arch.c_str(), kArm64Architecture) == 0) {
if (cpu_state_raw.size() != sizeof(MDRawContextARM64)) {
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
" bytes instead of " << sizeof(MDRawContextARM64) << std::endl;
continue;
}
MDRawContextARM64* arm = new MDRawContextARM64();
memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
context_->SetContextARM64(arm);
} else {
std::cerr << "Unsupported architecture: " << arch << std::endl;
}
} else if ((pos = line.find(kMmapKey)) != string::npos) {
string mmap_line(line, pos + strlen(kMmapKey));
std::istringstream mmap_tokens(mmap_line);
string addr, offset, size, identifier, filename;
mmap_tokens >> addr;
mmap_tokens >> offset;
mmap_tokens >> size;
mmap_tokens >> identifier;
mmap_tokens >> filename;
modules_->Add(new BasicCodeModule(
HexStrToL<uint64_t>(addr), // base_address
HexStrToL<uint64_t>(size), // size
filename, // code_file
identifier, // code_identifier
filename, // debug_file
identifier, // debug_identifier
"")); // version
}
}
stack_region_->Init(stack_start, stack_content);
}
} // namespace google_breakpad

View File

@ -27,6 +27,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// microdump_processor.cc: A microdump processor.
//
// See microdump_processor.h for documentation.
#include "google_breakpad/processor/microdump_processor.h"
#include <assert.h>
@ -35,8 +39,11 @@
#include "common/using_std_string.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/microdump.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/stackwalker.h"
#include "google_breakpad/processor/stack_frame_symbolizer.h"
#include "processor/logging.h"
namespace google_breakpad {
@ -51,7 +58,41 @@ ProcessResult MicrodumpProcessor::Process(const string &microdump_contents,
ProcessState* process_state) {
assert(process_state);
// TODO(mmandlis): Implement MicrodumpProcessor. See crbug.com/410294
process_state->Clear();
if (microdump_contents.empty()) {
BPLOG(ERROR) << "Microdump is empty.";
return PROCESS_ERROR_MINIDUMP_NOT_FOUND;
}
Microdump microdump(microdump_contents);
process_state->modules_ = microdump.GetModules()->Copy();
scoped_ptr<Stackwalker> stackwalker(
Stackwalker::StackwalkerForCPU(
&process_state->system_info_,
microdump.GetContext(),
microdump.GetMemory(),
process_state->modules_,
frame_symbolizer_));
scoped_ptr<CallStack> stack(new CallStack());
if (stackwalker.get()) {
if (!stackwalker->Walk(stack.get(),
&process_state->modules_without_symbols_,
&process_state->modules_with_corrupt_symbols_)) {
BPLOG(INFO) << "Processing was interrupted.";
return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED;
}
} else {
BPLOG(ERROR) << "No stackwalker found for microdump.";
return PROCESS_ERROR_NO_THREAD_LIST;
}
process_state->threads_.push_back(stack.release());
process_state->thread_memory_regions_.push_back(microdump.GetMemory());
process_state->crashed_ = true;
process_state->requesting_thread_ = 0;
process_state->system_info_ = *microdump.GetSystemInfo();
return PROCESS_OK;
}

View File

@ -29,18 +29,169 @@
// Unit test for MicrodumpProcessor.
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "breakpad_googletest_includes.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/microdump_processor.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/stack_frame.h"
#include "google_breakpad/processor/stack_frame_symbolizer.h"
#include "processor/simple_symbol_supplier.h"
#include "processor/stackwalker_unittest_utils.h"
namespace {
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::MicrodumpProcessor;
using google_breakpad::ProcessState;
using google_breakpad::SimpleSymbolSupplier;
using google_breakpad::StackFrameSymbolizer;
class MicrodumpProcessorTest : public ::testing::Test {
public:
MicrodumpProcessorTest()
: files_path_(string(getenv("srcdir") ? getenv("srcdir") : ".") +
"/src/processor/testdata/") {
}
void ReadFile(const string& file_name, string* file_contents) {
assert(file_contents);
std::ifstream file_stream(file_name.c_str(), std::ios::in);
ASSERT_TRUE(file_stream.good());
std::vector<char> bytes;
file_stream.seekg(0, std::ios_base::end);
ASSERT_TRUE(file_stream.good());
bytes.resize(file_stream.tellg());
file_stream.seekg(0, std::ios_base::beg);
ASSERT_TRUE(file_stream.good());
file_stream.read(&bytes[0], bytes.size());
ASSERT_TRUE(file_stream.good());
*file_contents = string(&bytes[0], bytes.size());
}
google_breakpad::ProcessResult ProcessMicrodump(
const string& symbols_file,
const string& microdump_contents,
ProcessState* state) {
SimpleSymbolSupplier supplier(symbols_file);
BasicSourceLineResolver resolver;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
MicrodumpProcessor processor(&frame_symbolizer);
return processor.Process(microdump_contents, state);
}
void AnalyzeDump(const string& microdump_file_name, ProcessState* state,
bool omit_symbols) {
string symbols_file = omit_symbols ? "" : files_path_ + "symbols/microdump";
string microdump_file_path = files_path_ + microdump_file_name;
string microdump_contents;
ReadFile(microdump_file_path, &microdump_contents);
google_breakpad::ProcessResult result =
ProcessMicrodump(symbols_file, microdump_contents, state);
ASSERT_EQ(google_breakpad::PROCESS_OK, result);
ASSERT_TRUE(state->crashed());
ASSERT_EQ(0, state->requesting_thread());
ASSERT_EQ(1U, state->threads()->size());
ASSERT_EQ(2, state->system_info()->cpu_count);
ASSERT_EQ("android", state->system_info()->os_short);
ASSERT_EQ("Android", state->system_info()->os);
}
string files_path_;
};
// TODO(mmandlis): Add MicrodumpProcessor tests. See crbug.com/410294
TEST_F(MicrodumpProcessorTest, TestProcess_Empty) {
ProcessState state;
google_breakpad::ProcessResult result =
ProcessMicrodump("", "", &state);
ASSERT_EQ(google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND, result);
}
TEST_F(MicrodumpProcessorTest, TestProcess_Invalid) {
ProcessState state;
google_breakpad::ProcessResult result =
ProcessMicrodump("", "This is not a valid microdump", &state);
ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
}
TEST_F(MicrodumpProcessorTest, TestProcess_MissingSymbols) {
ProcessState state;
AnalyzeDump("microdump-arm64.dmp", &state, true /* omit_symbols */);
ASSERT_EQ(8U, state.modules()->module_count());
ASSERT_EQ("aarch64", state.system_info()->cpu);
ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
ASSERT_EQ(1U, state.threads()->size());
ASSERT_EQ(12U, state.threads()->at(0)->frames()->size());
ASSERT_EQ("",
state.threads()->at(0)->frames()->at(0)->function_name);
ASSERT_EQ("",
state.threads()->at(0)->frames()->at(3)->function_name);
}
TEST_F(MicrodumpProcessorTest, TestProcess_UnsupportedArch) {
string microdump_contents =
"W/google-breakpad(26491): -----BEGIN BREAKPAD MICRODUMP-----\n"
"W/google-breakpad(26491): O A \"unsupported-arch\"\n"
"W/google-breakpad(26491): S 0 A48BD840 A48BD000 00002000\n";
ProcessState state;
google_breakpad::ProcessResult result =
ProcessMicrodump("", microdump_contents, &state);
ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result);
}
TEST_F(MicrodumpProcessorTest, TestProcessArm) {
ProcessState state;
AnalyzeDump("microdump-arm.dmp", &state, false /* omit_symbols */);
ASSERT_EQ(6U, state.modules()->module_count());
ASSERT_EQ("armv7l", state.system_info()->cpu);
ASSERT_EQ("OS VERSION INFO", state.system_info()->os_version);
ASSERT_EQ(8U, state.threads()->at(0)->frames()->size());
ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody",
state.threads()->at(0)->frames()->at(0)->function_name);
ASSERT_EQ("testing::Test::Run",
state.threads()->at(0)->frames()->at(1)->function_name);
ASSERT_EQ("main",
state.threads()->at(0)->frames()->at(6)->function_name);
ASSERT_EQ("breakpad_unittests",
state.threads()->at(0)->frames()->at(6)->module->code_file());
}
TEST_F(MicrodumpProcessorTest, TestProcessArm64) {
ProcessState state;
AnalyzeDump("microdump-arm64.dmp", &state, false /* omit_symbols */);
ASSERT_EQ(8U, state.modules()->module_count());
ASSERT_EQ("aarch64", state.system_info()->cpu);
ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version);
ASSERT_EQ(9U, state.threads()->at(0)->frames()->size());
ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody",
state.threads()->at(0)->frames()->at(0)->function_name);
ASSERT_EQ("testing::Test::Run",
state.threads()->at(0)->frames()->at(2)->function_name);
ASSERT_EQ("main",
state.threads()->at(0)->frames()->at(7)->function_name);
ASSERT_EQ("breakpad_unittests",
state.threads()->at(0)->frames()->at(7)->module->code_file());
}
} // namespace
int main(int argc, char *argv[]) {
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -0,0 +1,151 @@
// Copyright (c) 2014 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.
// microdump_stackwalk.cc: Process a microdump with MicrodumpProcessor, printing
// the results, including stack traces.
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <string>
#include <vector>
#include "common/scoped_ptr.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/microdump_processor.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/stack_frame_symbolizer.h"
#include "processor/logging.h"
#include "processor/simple_symbol_supplier.h"
#include "processor/stackwalk_common.h"
namespace {
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::MicrodumpProcessor;
using google_breakpad::ProcessResult;
using google_breakpad::ProcessState;
using google_breakpad::scoped_ptr;
using google_breakpad::SimpleSymbolSupplier;
using google_breakpad::StackFrameSymbolizer;
// Processes |microdump_file| using MicrodumpProcessor. |symbol_path|, if
// non-empty, is the base directory of a symbol storage area, laid out in
// the format required by SimpleSymbolSupplier. If such a storage area
// is specified, it is made available for use by the MicrodumpProcessor.
//
// Returns the value of MicrodumpProcessor::Process. If processing succeeds,
// prints identifying OS and CPU information from the microdump, crash
// information and call stacks for the crashing thread.
// All information is printed to stdout.
int PrintMicrodumpProcess(const char* microdump_file,
const std::vector<string>& symbol_paths,
bool machine_readable) {
std::ifstream file_stream(microdump_file);
std::vector<char> bytes;
file_stream.seekg(0, std::ios_base::end);
bytes.resize(file_stream.tellg());
file_stream.seekg(0, std::ios_base::beg);
file_stream.read(&bytes[0], bytes.size());
string microdump_content(&bytes[0], bytes.size());
scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
if (!symbol_paths.empty()) {
symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths));
}
BasicSourceLineResolver resolver;
StackFrameSymbolizer frame_symbolizer(symbol_supplier.get(), &resolver);
ProcessState process_state;
MicrodumpProcessor microdump_processor(&frame_symbolizer);
ProcessResult res = microdump_processor.Process(microdump_content,
&process_state);
if (res == google_breakpad::PROCESS_OK) {
if (machine_readable) {
PrintProcessStateMachineReadable(process_state);
} else {
PrintProcessState(process_state, false, &resolver);
}
return 0;
}
BPLOG(ERROR) << "MicrodumpProcessor::Process failed (code = " << res << ")";
return 1;
}
void usage(const char *program_name) {
fprintf(stderr, "usage: %s [-m] <microdump-file> [symbol-path ...]\n"
" -m : Output in machine-readable format\n",
program_name);
}
} // namespace
int main(int argc, char** argv) {
BPLOG_INIT(&argc, &argv);
if (argc < 2) {
usage(argv[0]);
return 1;
}
const char* microdump_file;
bool machine_readable;
int symbol_path_arg;
if (strcmp(argv[1], "-m") == 0) {
if (argc < 3) {
usage(argv[0]);
return 1;
}
machine_readable = true;
microdump_file = argv[2];
symbol_path_arg = 3;
} else {
machine_readable = false;
microdump_file = argv[1];
symbol_path_arg = 2;
}
// extra arguments are symbol paths
std::vector<string> symbol_paths;
if (argc > symbol_path_arg) {
for (int argi = symbol_path_arg; argi < argc; ++argi)
symbol_paths.push_back(argv[argi]);
}
return PrintMicrodumpProcess(microdump_file,
symbol_paths,
machine_readable);
}

View File

@ -0,0 +1,43 @@
#!/bin/sh
# Copyright (c) 2014, 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.
source "${0%/*}/microdump_stackwalk_test_vars" # for MICRODUMP_SUPPORTED_ARCHS.
testdata_dir=$srcdir/src/processor/testdata
set -e # Bail out with an error if any of the commands below fails.
for ARCH in $MICRODUMP_SUPPORTED_ARCHS; do
echo "Testing microdump_stackwalk -m for arch $ARCH"
./src/processor/microdump_stackwalk -m $testdata_dir/microdump-${ARCH}.dmp \
$testdata_dir/symbols/microdump | \
tr -d '\015' | \
diff -u $testdata_dir/microdump.stackwalk.machine_readable-${ARCH}.out -
done
exit 0

View File

@ -0,0 +1,43 @@
#!/bin/sh
# Copyright (c) 2014, 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.
source "${0%/*}/microdump_stackwalk_test_vars" # for MICRODUMP_SUPPORTED_ARCHS.
testdata_dir=$srcdir/src/processor/testdata
set -e # Bail out with an error if any of the commands below fails.
for ARCH in $MICRODUMP_SUPPORTED_ARCHS; do
echo "Testing microdump_stackwalk for arch $ARCH"
./src/processor/microdump_stackwalk $testdata_dir/microdump-${ARCH}.dmp \
$testdata_dir/symbols/microdump | \
tr -d '\015' | \
diff -u $testdata_dir/microdump.stackwalk-${ARCH}.out -
done
exit 0

View File

@ -0,0 +1 @@
MICRODUMP_SUPPORTED_ARCHS="arm arm64"

View File

@ -49,7 +49,6 @@
#define snprintf _snprintf
#else // _WIN32
#include <unistd.h>
#define O_BINARY 0
#endif // _WIN32
#include <fstream>
@ -2548,12 +2547,26 @@ bool MinidumpModuleList::Read(uint32_t expected_size) {
}
if (!range_map_->StoreRange(base_address, module_size, module_index)) {
// Android's shared memory implementation /dev/ashmem can contain
// duplicate entries for JITted code, so ignore these.
// TODO(wfh): Remove this code when Android is fixed.
// See https://crbug.com/439531
const string kDevAshmem("/dev/ashmem/");
if (module->code_file().compare(
0, kDevAshmem.length(), kDevAshmem) != 0) {
BPLOG(ERROR) << "MinidumpModuleList could not store module " <<
module_index << "/" << module_count << ", " <<
module->code_file() << ", " <<
HexString(base_address) << "+" <<
HexString(module_size);
return false;
} else {
BPLOG(INFO) << "MinidumpModuleList ignoring overlapping module " <<
module_index << "/" << module_count << ", " <<
module->code_file() << ", " <<
HexString(base_address) << "+" <<
HexString(module_size);
}
}
}

View File

@ -87,6 +87,9 @@ ProcessResult MinidumpProcessor::Process(
}
process_state->time_date_stamp_ = header->time_date_stamp;
bool has_process_create_time =
GetProcessCreateTime(dump, &process_state->process_create_time_);
bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_);
bool has_os_info = GetOSInfo(dump, &process_state->system_info_);
@ -141,8 +144,9 @@ ProcessResult MinidumpProcessor::Process(
(exception != NULL ? "" : "no ") << "exception, " <<
(module_list != NULL ? "" : "no ") << "module list, " <<
(threads != NULL ? "" : "no ") << "thread list, " <<
(has_dump_thread ? "" : "no ") << "dump thread, and " <<
(has_requesting_thread ? "" : "no ") << "requesting thread";
(has_dump_thread ? "" : "no ") << "dump thread, " <<
(has_requesting_thread ? "" : "no ") << "requesting thread, and " <<
(has_process_create_time ? "" : "no ") << "process create time";
bool interrupted = false;
bool found_requesting_thread = false;
@ -618,6 +622,32 @@ bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) {
return true;
}
// static
bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump,
uint32_t* process_create_time) {
assert(dump);
assert(process_create_time);
*process_create_time = 0;
MinidumpMiscInfo* minidump_misc_info = dump->GetMiscInfo();
if (!minidump_misc_info) {
return false;
}
const MDRawMiscInfo* md_raw_misc_info = minidump_misc_info->misc_info();
if (!md_raw_misc_info) {
return false;
}
if (!(md_raw_misc_info->flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES)) {
return false;
}
*process_create_time = md_raw_misc_info->process_create_time;
return true;
}
// static
string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
MinidumpException *exception = dump->GetException();

View File

@ -66,6 +66,7 @@ class MockMinidump : public Minidump {
MOCK_CONST_METHOD0(header, const MDRawHeader*());
MOCK_METHOD0(GetThreadList, MinidumpThreadList*());
MOCK_METHOD0(GetSystemInfo, MinidumpSystemInfo*());
MOCK_METHOD0(GetMiscInfo, MinidumpMiscInfo*());
MOCK_METHOD0(GetBreakpadInfo, MinidumpBreakpadInfo*());
MOCK_METHOD0(GetException, MinidumpException*());
MOCK_METHOD0(GetAssertion, MinidumpAssertion*());
@ -126,6 +127,17 @@ class MockMinidumpMemoryRegion : public MinidumpMemoryRegion {
MockMemoryRegion region_;
};
// A test miscelaneous info stream, just returns values from the
// MDRawMiscInfo fed to it.
class TestMinidumpMiscInfo : public MinidumpMiscInfo {
public:
explicit TestMinidumpMiscInfo(const MDRawMiscInfo& misc_info) :
MinidumpMiscInfo(NULL) {
valid_ = true;
misc_info_ = misc_info;
}
};
} // namespace google_breakpad
namespace {
@ -135,6 +147,7 @@ using google_breakpad::CallStack;
using google_breakpad::CodeModule;
using google_breakpad::MinidumpContext;
using google_breakpad::MinidumpMemoryRegion;
using google_breakpad::MinidumpMiscInfo;
using google_breakpad::MinidumpProcessor;
using google_breakpad::MinidumpSystemInfo;
using google_breakpad::MinidumpThreadList;
@ -402,6 +415,8 @@ TEST_F(MinidumpProcessorTest, TestBasicProcessing) {
ASSERT_EQ(state.crash_address(), 0x45U);
ASSERT_EQ(state.threads()->size(), size_t(1));
ASSERT_EQ(state.requesting_thread(), 0);
EXPECT_EQ(1171480435U, state.time_date_stamp());
EXPECT_EQ(1171480435U, state.process_create_time());
CallStack *stack = state.threads()->at(0);
ASSERT_TRUE(stack);
@ -529,6 +544,40 @@ TEST_F(MinidumpProcessorTest, TestThreadMissingMemory) {
ASSERT_EQ(kExpectedEIP, state.threads()->at(0)->frames()->at(0)->instruction);
}
TEST_F(MinidumpProcessorTest, GetProcessCreateTime) {
const uint32_t kProcessCreateTime = 2000;
const uint32_t kTimeDateStamp = 5000;
MockMinidump dump;
EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));
EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true));
// Set time of crash.
MDRawHeader fake_header;
fake_header.time_date_stamp = kTimeDateStamp;
EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header));
// Set process create time.
MDRawMiscInfo raw_misc_info;
memset(&raw_misc_info, 0, sizeof(raw_misc_info));
raw_misc_info.process_create_time = kProcessCreateTime;
raw_misc_info.flags1 |= MD_MISCINFO_FLAGS1_PROCESS_TIMES;
google_breakpad::TestMinidumpMiscInfo dump_misc_info(raw_misc_info);
EXPECT_CALL(dump, GetMiscInfo()).WillRepeatedly(Return(&dump_misc_info));
// No threads
MockMinidumpThreadList thread_list;
EXPECT_CALL(dump, GetThreadList()).WillOnce(Return(&thread_list));
EXPECT_CALL(thread_list, thread_count()).WillRepeatedly(Return(0));
MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL);
ProcessState state;
EXPECT_EQ(google_breakpad::PROCESS_OK, processor.Process(&dump, &state));
// Verify the time stamps.
ASSERT_EQ(kTimeDateStamp, state.time_date_stamp());
ASSERT_EQ(kProcessCreateTime, state.process_create_time());
}
TEST_F(MinidumpProcessorTest, TestThreadMissingContext) {
MockMinidump dump;
EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump"));

View File

@ -33,7 +33,6 @@
// Author: Mark Mentovai
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
@ -42,744 +41,22 @@
#include "common/scoped_ptr.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/code_modules.h"
#include "google_breakpad/processor/minidump.h"
#include "google_breakpad/processor/minidump_processor.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/logging.h"
#include "processor/pathname_stripper.h"
#include "processor/simple_symbol_supplier.h"
#include "processor/stackwalk_common.h"
namespace {
using std::vector;
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::CodeModule;
using google_breakpad::CodeModules;
using google_breakpad::MinidumpModule;
using google_breakpad::Minidump;
using google_breakpad::MinidumpProcessor;
using google_breakpad::PathnameStripper;
using google_breakpad::ProcessState;
using google_breakpad::scoped_ptr;
using google_breakpad::SimpleSymbolSupplier;
using google_breakpad::StackFrame;
using google_breakpad::StackFramePPC;
using google_breakpad::StackFrameSPARC;
using google_breakpad::StackFrameX86;
using google_breakpad::StackFrameAMD64;
using google_breakpad::StackFrameARM;
using google_breakpad::StackFrameARM64;
using google_breakpad::StackFrameMIPS;
// Separator character for machine readable output.
static const char kOutputSeparator = '|';
// PrintRegister prints a register's name and value to stdout. It will
// print four registers on a line. For the first register in a set,
// pass 0 for |start_col|. For registers in a set, pass the most recent
// return value of PrintRegister.
// The caller is responsible for printing the final newline after a set
// of registers is completely printed, regardless of the number of calls
// to PrintRegister.
static const int kMaxWidth = 80; // optimize for an 80-column terminal
static int PrintRegister(const char *name, uint32_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%08x", name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// PrintRegister64 does the same thing, but for 64-bit registers.
static int PrintRegister64(const char *name, uint64_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%016" PRIx64 , name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// StripSeparator takes a string |original| and returns a copy
// of the string with all occurences of |kOutputSeparator| removed.
static string StripSeparator(const string &original) {
string result = original;
string::size_type position = 0;
while ((position = result.find(kOutputSeparator, position)) != string::npos) {
result.erase(position, 1);
}
position = 0;
while ((position = result.find('\n', position)) != string::npos) {
result.erase(position, 1);
}
return result;
}
// 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
// source line, function, or module is printed, preferring them in that
// order. If no source line, function, or module information is available,
// an absolute code offset is printed.
//
// 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) {
int frame_count = stack->frames()->size();
if (frame_count == 0) {
printf(" <no frames>\n");
}
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%2d ", frame_index);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
printf("%s", PathnameStripper::File(frame->module->code_file()).c_str());
if (!frame->function_name.empty()) {
printf("!%s", frame->function_name.c_str());
if (!frame->source_file_name.empty()) {
string source_file = PathnameStripper::File(frame->source_file_name);
printf(" [%s : %d + 0x%" PRIx64 "]",
source_file.c_str(),
frame->source_line,
instruction_address - frame->source_line_base);
} else {
printf(" + 0x%" PRIx64, instruction_address - frame->function_base);
}
} else {
printf(" + 0x%" PRIx64,
instruction_address - frame->module->base_address());
}
} else {
printf("0x%" PRIx64, instruction_address);
}
printf("\n ");
int sequence = 0;
if (cpu == "x86") {
const StackFrameX86 *frame_x86 =
reinterpret_cast<const StackFrameX86*>(frame);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
}
} else if (cpu == "ppc") {
const StackFramePPC *frame_ppc =
reinterpret_cast<const StackFramePPC*>(frame);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
} else if (cpu == "amd64") {
const StackFrameAMD64 *frame_amd64 =
reinterpret_cast<const StackFrameAMD64*>(frame);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RAX)
sequence = PrintRegister64("rax", frame_amd64->context.rax, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDX)
sequence = PrintRegister64("rdx", frame_amd64->context.rdx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RCX)
sequence = PrintRegister64("rcx", frame_amd64->context.rcx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBX)
sequence = PrintRegister64("rbx", frame_amd64->context.rbx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSI)
sequence = PrintRegister64("rsi", frame_amd64->context.rsi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDI)
sequence = PrintRegister64("rdi", frame_amd64->context.rdi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP)
sequence = PrintRegister64("rbp", frame_amd64->context.rbp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP)
sequence = PrintRegister64("rsp", frame_amd64->context.rsp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R8)
sequence = PrintRegister64("r8", frame_amd64->context.r8, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R9)
sequence = PrintRegister64("r9", frame_amd64->context.r9, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R10)
sequence = PrintRegister64("r10", frame_amd64->context.r10, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R11)
sequence = PrintRegister64("r11", frame_amd64->context.r11, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R12)
sequence = PrintRegister64("r12", frame_amd64->context.r12, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R13)
sequence = PrintRegister64("r13", frame_amd64->context.r13, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R14)
sequence = PrintRegister64("r14", frame_amd64->context.r14, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R15)
sequence = PrintRegister64("r15", frame_amd64->context.r15, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP)
sequence = PrintRegister64("rip", frame_amd64->context.rip, sequence);
} else if (cpu == "sparc") {
const StackFrameSPARC *frame_sparc =
reinterpret_cast<const StackFrameSPARC*>(frame);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_sparc->context.g_r[30], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
} else if (cpu == "arm") {
const StackFrameARM *frame_arm =
reinterpret_cast<const StackFrameARM*>(frame);
// Argument registers (caller-saves), which will likely only be valid
// for the youngest frame.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R0)
sequence = PrintRegister("r0", frame_arm->context.iregs[0], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R1)
sequence = PrintRegister("r1", frame_arm->context.iregs[1], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R2)
sequence = PrintRegister("r2", frame_arm->context.iregs[2], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R3)
sequence = PrintRegister("r3", frame_arm->context.iregs[3], sequence);
// General-purpose callee-saves registers.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
sequence = PrintRegister("r4", frame_arm->context.iregs[4], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R5)
sequence = PrintRegister("r5", frame_arm->context.iregs[5], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R6)
sequence = PrintRegister("r6", frame_arm->context.iregs[6], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R7)
sequence = PrintRegister("r7", frame_arm->context.iregs[7], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R8)
sequence = PrintRegister("r8", frame_arm->context.iregs[8], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R9)
sequence = PrintRegister("r9", frame_arm->context.iregs[9], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R10)
sequence = PrintRegister("r10", frame_arm->context.iregs[10], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R12)
sequence = PrintRegister("r12", frame_arm->context.iregs[12], sequence);
// Registers with a dedicated or conventional purpose.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_arm->context.iregs[11], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_arm->context.iregs[13], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_LR)
sequence = PrintRegister("lr", frame_arm->context.iregs[14], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence);
} else if (cpu == "arm64") {
const StackFrameARM64 *frame_arm64 =
reinterpret_cast<const StackFrameARM64*>(frame);
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X0) {
sequence =
PrintRegister64("x0", frame_arm64->context.iregs[0], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X1) {
sequence =
PrintRegister64("x1", frame_arm64->context.iregs[1], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X2) {
sequence =
PrintRegister64("x2", frame_arm64->context.iregs[2], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X3) {
sequence =
PrintRegister64("x3", frame_arm64->context.iregs[3], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X4) {
sequence =
PrintRegister64("x4", frame_arm64->context.iregs[4], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X5) {
sequence =
PrintRegister64("x5", frame_arm64->context.iregs[5], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X6) {
sequence =
PrintRegister64("x6", frame_arm64->context.iregs[6], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X7) {
sequence =
PrintRegister64("x7", frame_arm64->context.iregs[7], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X8) {
sequence =
PrintRegister64("x8", frame_arm64->context.iregs[8], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X9) {
sequence =
PrintRegister64("x9", frame_arm64->context.iregs[9], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X10) {
sequence =
PrintRegister64("x10", frame_arm64->context.iregs[10], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X11) {
sequence =
PrintRegister64("x11", frame_arm64->context.iregs[11], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X12) {
sequence =
PrintRegister64("x12", frame_arm64->context.iregs[12], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X13) {
sequence =
PrintRegister64("x13", frame_arm64->context.iregs[13], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X14) {
sequence =
PrintRegister64("x14", frame_arm64->context.iregs[14], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X15) {
sequence =
PrintRegister64("x15", frame_arm64->context.iregs[15], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X16) {
sequence =
PrintRegister64("x16", frame_arm64->context.iregs[16], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X17) {
sequence =
PrintRegister64("x17", frame_arm64->context.iregs[17], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X18) {
sequence =
PrintRegister64("x18", frame_arm64->context.iregs[18], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X19) {
sequence =
PrintRegister64("x19", frame_arm64->context.iregs[19], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X20) {
sequence =
PrintRegister64("x20", frame_arm64->context.iregs[20], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X21) {
sequence =
PrintRegister64("x21", frame_arm64->context.iregs[21], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X22) {
sequence =
PrintRegister64("x22", frame_arm64->context.iregs[22], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X23) {
sequence =
PrintRegister64("x23", frame_arm64->context.iregs[23], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X24) {
sequence =
PrintRegister64("x24", frame_arm64->context.iregs[24], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X25) {
sequence =
PrintRegister64("x25", frame_arm64->context.iregs[25], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X26) {
sequence =
PrintRegister64("x26", frame_arm64->context.iregs[26], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X27) {
sequence =
PrintRegister64("x27", frame_arm64->context.iregs[27], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X28) {
sequence =
PrintRegister64("x28", frame_arm64->context.iregs[28], sequence);
}
// Registers with a dedicated or conventional purpose.
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_FP) {
sequence =
PrintRegister64("fp", frame_arm64->context.iregs[29], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_LR) {
sequence =
PrintRegister64("lr", frame_arm64->context.iregs[30], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) {
sequence =
PrintRegister64("sp", frame_arm64->context.iregs[31], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_PC) {
sequence =
PrintRegister64("pc", frame_arm64->context.iregs[32], sequence);
}
} else if (cpu == "mips") {
const StackFrameMIPS* frame_mips =
reinterpret_cast<const StackFrameMIPS*>(frame);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_GP)
sequence = PrintRegister64("gp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_GP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_SP)
sequence = PrintRegister64("sp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_SP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_FP)
sequence = PrintRegister64("fp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_FP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_RA)
sequence = PrintRegister64("ra",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_RA],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_PC)
sequence = PrintRegister64("pc", frame_mips->context.epc, sequence);
// Save registers s0-s7
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S0)
sequence = PrintRegister64("s0",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S0],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S1)
sequence = PrintRegister64("s1",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S1],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S2)
sequence = PrintRegister64("s2",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S2],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S3)
sequence = PrintRegister64("s3",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S3],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S4)
sequence = PrintRegister64("s4",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S4],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S5)
sequence = PrintRegister64("s5",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S5],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S6)
sequence = PrintRegister64("s6",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S6],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S7)
sequence = PrintRegister64("s7",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S7],
sequence);
}
printf("\n Found by: %s\n", frame->trust_description().c_str());
}
}
// PrintStackMachineReadable prints the call stack in |stack| to stdout,
// in the following machine readable pipe-delimited text format:
// thread number|frame number|module|function|source file|line|offset
//
// Module, function, source file, and source line may all be empty
// depending on availability. The code offset follows the same rules as
// PrintStack above.
static void PrintStackMachineReadable(int thread_num, const CallStack *stack) {
int frame_count = stack->frames()->size();
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index,
kOutputSeparator);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
assert(!frame->module->code_file().empty());
printf("%s", StripSeparator(PathnameStripper::File(
frame->module->code_file())).c_str());
if (!frame->function_name.empty()) {
printf("%c%s", kOutputSeparator,
StripSeparator(frame->function_name).c_str());
if (!frame->source_file_name.empty()) {
printf("%c%s%c%d%c0x%" PRIx64,
kOutputSeparator,
StripSeparator(frame->source_file_name).c_str(),
kOutputSeparator,
frame->source_line,
kOutputSeparator,
instruction_address - frame->source_line_base);
} else {
printf("%c%c%c0x%" PRIx64,
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->function_base);
}
} else {
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->module->base_address());
}
} else {
// the printf before this prints a trailing separator for module name
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address);
}
printf("\n");
}
}
// ContainsModule checks whether a given |module| is in the vector
// |modules_without_symbols|.
static bool ContainsModule(
const vector<const CodeModule*> *modules,
const CodeModule *module) {
assert(modules);
assert(module);
vector<const CodeModule*>::const_iterator iter;
for (iter = modules->begin(); iter != modules->end(); ++iter) {
if (module->debug_file().compare((*iter)->debug_file()) == 0 &&
module->debug_identifier().compare((*iter)->debug_identifier()) == 0) {
return true;
}
}
return false;
}
// PrintModule prints a single |module| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModule(
const CodeModule *module,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols,
uint64_t main_address) {
string symbol_issues;
if (ContainsModule(modules_without_symbols, module)) {
symbol_issues = " (WARNING: No symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
} else if (ContainsModule(modules_with_corrupt_symbols, module)) {
symbol_issues = " (WARNING: Corrupt symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
}
uint64_t base_address = module->base_address();
printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n",
base_address, base_address + module->size() - 1,
PathnameStripper::File(module->code_file()).c_str(),
module->version().empty() ? "???" : module->version().c_str(),
main_address != 0 && base_address == main_address ? " (main)" : "",
symbol_issues.c_str());
}
// PrintModules prints the list of all loaded |modules| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModules(
const CodeModules *modules,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols) {
if (!modules)
return;
printf("\n");
printf("Loaded modules:\n");
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
PrintModule(module, modules_without_symbols, modules_with_corrupt_symbols,
main_address);
}
}
// PrintModulesMachineReadable outputs a list of loaded modules,
// one per line, in the following machine-readable pipe-delimited
// text format:
// Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}|
// {Base Address}|{Max Address}|{Main}
static void PrintModulesMachineReadable(const CodeModules *modules) {
if (!modules)
return;
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
uint64_t base_address = module->base_address();
printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
kOutputSeparator, StripSeparator(module->version()).c_str(),
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->debug_file())).c_str(),
kOutputSeparator,
StripSeparator(module->debug_identifier()).c_str(),
kOutputSeparator, base_address,
kOutputSeparator, base_address + module->size() - 1,
kOutputSeparator,
main_module != NULL && base_address == main_address ? 1 : 0);
}
}
static void PrintProcessState(const ProcessState& process_state) {
// Print OS and CPU information.
string cpu = process_state.system_info()->cpu;
string cpu_info = process_state.system_info()->cpu_info;
printf("Operating system: %s\n", process_state.system_info()->os.c_str());
printf(" %s\n",
process_state.system_info()->os_version.c_str());
printf("CPU: %s\n", cpu.c_str());
if (!cpu_info.empty()) {
// This field is optional.
printf(" %s\n", cpu_info.c_str());
}
printf(" %d CPU%s\n",
process_state.system_info()->cpu_count,
process_state.system_info()->cpu_count != 1 ? "s" : "");
printf("\n");
// Print crash information.
if (process_state.crashed()) {
printf("Crash reason: %s\n", process_state.crash_reason().c_str());
printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address());
} else {
printf("No crash\n");
}
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("Assertion: %s\n", assertion.c_str());
}
// If the thread that requested the dump is known, print it first.
int requesting_thread = process_state.requesting_thread();
if (requesting_thread != -1) {
printf("\n");
printf("Thread %d (%s)\n",
requesting_thread,
process_state.crashed() ? "crashed" :
"requested dump, did not crash");
PrintStack(process_state.threads()->at(requesting_thread), cpu);
}
// Print all of the threads in the dump.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// 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);
}
}
PrintModules(process_state.modules(),
process_state.modules_without_symbols(),
process_state.modules_with_corrupt_symbols());
}
static void PrintProcessStateMachineReadable(const ProcessState& process_state)
{
// Print OS and CPU information.
// OS|{OS Name}|{OS Version}
// CPU|{CPU Name}|{CPU Info}|{Number of CPUs}
printf("OS%c%s%c%s\n", kOutputSeparator,
StripSeparator(process_state.system_info()->os).c_str(),
kOutputSeparator,
StripSeparator(process_state.system_info()->os_version).c_str());
printf("CPU%c%s%c%s%c%d\n", kOutputSeparator,
StripSeparator(process_state.system_info()->cpu).c_str(),
kOutputSeparator,
// this may be empty
StripSeparator(process_state.system_info()->cpu_info).c_str(),
kOutputSeparator,
process_state.system_info()->cpu_count);
int requesting_thread = process_state.requesting_thread();
// Print crash information.
// Crash|{Crash Reason}|{Crash Address}|{Crashed Thread}
printf("Crash%c", kOutputSeparator);
if (process_state.crashed()) {
printf("%s%c0x%" PRIx64 "%c",
StripSeparator(process_state.crash_reason()).c_str(),
kOutputSeparator, process_state.crash_address(), kOutputSeparator);
} else {
// print assertion info, if available, in place of crash reason,
// instead of the unhelpful "No crash"
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("%s%c%c", StripSeparator(assertion).c_str(),
kOutputSeparator, kOutputSeparator);
} else {
printf("No crash%c%c", kOutputSeparator, kOutputSeparator);
}
}
if (requesting_thread != -1) {
printf("%d\n", requesting_thread);
} else {
printf("\n");
}
PrintModulesMachineReadable(process_state.modules());
// blank line to indicate start of threads
printf("\n");
// If the thread that requested the dump is known, print it first.
if (requesting_thread != -1) {
PrintStackMachineReadable(requesting_thread,
process_state.threads()->at(requesting_thread));
}
// Print all of the threads in the dump.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// Don't print the crash thread again, it was already printed.
PrintStackMachineReadable(thread_index,
process_state.threads()->at(thread_index));
}
}
}
using google_breakpad::scoped_ptr;
// Processes |minidump_file| using MinidumpProcessor. |symbol_path|, if
// non-empty, is the base directory of a symbol storage area, laid out in
@ -791,9 +68,10 @@ static void PrintProcessStateMachineReadable(const ProcessState& process_state)
// information if the minidump was produced as a result of a crash, and
// call stacks for each thread contained in the minidump. All information
// is printed to stdout.
static bool PrintMinidumpProcess(const string &minidump_file,
const vector<string> &symbol_paths,
bool machine_readable) {
bool PrintMinidumpProcess(const string &minidump_file,
const std::vector<string> &symbol_paths,
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?
@ -804,8 +82,13 @@ static 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;
@ -814,20 +97,21 @@ static 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;
}
} // namespace
static void usage(const char *program_name) {
fprintf(stderr, "usage: %s [-m] <minidump-file> [symbol-path ...]\n"
" -m : Output in machine-readable format\n",
void usage(const char *program_name) {
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);
}
} // namespace
int main(int argc, char **argv) {
BPLOG_INIT(&argc, &argv);
@ -837,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) {
@ -849,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;
}
@ -864,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

@ -45,6 +45,7 @@ ProcessState::~ProcessState() {
void ProcessState::Clear() {
time_date_stamp_ = 0;
process_create_time_ = 0;
crashed_ = false;
crash_reason_.clear();
crash_address_ = 0;

View File

@ -46,11 +46,14 @@ package google_breakpad;
// A proto representation of a process, in a fully-digested state.
// See src/google_breakpad/processor/process_state.h
message ProcessStateProto {
// Next value: 13
// Next value: 14
// The time-date stamp of the original minidump (time_t format)
optional int64 time_date_stamp = 1;
// The time-date stamp when the process was created (time_t format)
optional int64 process_create_time = 13;
message Crash {
// The type of crash. OS- and possibly CPU- specific. For example,
// "EXCEPTION_ACCESS_VIOLATION" (Windows), "EXC_BAD_ACCESS /

View File

@ -0,0 +1,929 @@
// Copyright (c) 2010 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck
// executables to print the content of dumps (w/ stack traces) on the console.
//
// Author: Mark Mentovai
#include "processor/stackwalk_common.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#include "common/using_std_string.h"
#include "google_breakpad/processor/call_stack.h"
#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"
namespace google_breakpad {
namespace {
using std::vector;
// Separator character for machine readable output.
static const char kOutputSeparator = '|';
// PrintRegister prints a register's name and value to stdout. It will
// print four registers on a line. For the first register in a set,
// pass 0 for |start_col|. For registers in a set, pass the most recent
// return value of PrintRegister.
// The caller is responsible for printing the final newline after a set
// of registers is completely printed, regardless of the number of calls
// to PrintRegister.
static const int kMaxWidth = 80; // optimize for an 80-column terminal
static int PrintRegister(const char *name, uint32_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%08x", name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// PrintRegister64 does the same thing, but for 64-bit registers.
static int PrintRegister64(const char *name, uint64_t value, int start_col) {
char buffer[64];
snprintf(buffer, sizeof(buffer), " %5s = 0x%016" PRIx64 , name, value);
if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) {
start_col = 0;
printf("\n ");
}
fputs(buffer, stdout);
return start_col + strlen(buffer);
}
// StripSeparator takes a string |original| and returns a copy
// of the string with all occurences of |kOutputSeparator| removed.
static string StripSeparator(const string &original) {
string result = original;
string::size_type position = 0;
while ((position = result.find(kOutputSeparator, position)) != string::npos) {
result.erase(position, 1);
}
position = 0;
while ((position = result.find('\n', position)) != string::npos) {
result.erase(position, 1);
}
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
// source line, function, or module is printed, preferring them in that
// order. If no source line, function, or module information is available,
// an absolute code offset is printed.
//
// 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,
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");
}
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%2d ", frame_index);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
printf("%s", PathnameStripper::File(frame->module->code_file()).c_str());
if (!frame->function_name.empty()) {
printf("!%s", frame->function_name.c_str());
if (!frame->source_file_name.empty()) {
string source_file = PathnameStripper::File(frame->source_file_name);
printf(" [%s : %d + 0x%" PRIx64 "]",
source_file.c_str(),
frame->source_line,
instruction_address - frame->source_line_base);
} else {
printf(" + 0x%" PRIx64, instruction_address - frame->function_base);
}
} else {
printf(" + 0x%" PRIx64,
instruction_address - frame->module->base_address());
}
} else {
printf("0x%" PRIx64, instruction_address);
}
printf("\n ");
int sequence = 0;
if (cpu == "x86") {
const StackFrameX86 *frame_x86 =
reinterpret_cast<const StackFrameX86*>(frame);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
}
} else if (cpu == "ppc") {
const StackFramePPC *frame_ppc =
reinterpret_cast<const StackFramePPC*>(frame);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
} else if (cpu == "amd64") {
const StackFrameAMD64 *frame_amd64 =
reinterpret_cast<const StackFrameAMD64*>(frame);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RAX)
sequence = PrintRegister64("rax", frame_amd64->context.rax, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDX)
sequence = PrintRegister64("rdx", frame_amd64->context.rdx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RCX)
sequence = PrintRegister64("rcx", frame_amd64->context.rcx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBX)
sequence = PrintRegister64("rbx", frame_amd64->context.rbx, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSI)
sequence = PrintRegister64("rsi", frame_amd64->context.rsi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDI)
sequence = PrintRegister64("rdi", frame_amd64->context.rdi, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP)
sequence = PrintRegister64("rbp", frame_amd64->context.rbp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP)
sequence = PrintRegister64("rsp", frame_amd64->context.rsp, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R8)
sequence = PrintRegister64("r8", frame_amd64->context.r8, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R9)
sequence = PrintRegister64("r9", frame_amd64->context.r9, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R10)
sequence = PrintRegister64("r10", frame_amd64->context.r10, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R11)
sequence = PrintRegister64("r11", frame_amd64->context.r11, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R12)
sequence = PrintRegister64("r12", frame_amd64->context.r12, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R13)
sequence = PrintRegister64("r13", frame_amd64->context.r13, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R14)
sequence = PrintRegister64("r14", frame_amd64->context.r14, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R15)
sequence = PrintRegister64("r15", frame_amd64->context.r15, sequence);
if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP)
sequence = PrintRegister64("rip", frame_amd64->context.rip, sequence);
} else if (cpu == "sparc") {
const StackFrameSPARC *frame_sparc =
reinterpret_cast<const StackFrameSPARC*>(frame);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_sparc->context.g_r[30], sequence);
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
} else if (cpu == "arm") {
const StackFrameARM *frame_arm =
reinterpret_cast<const StackFrameARM*>(frame);
// Argument registers (caller-saves), which will likely only be valid
// for the youngest frame.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R0)
sequence = PrintRegister("r0", frame_arm->context.iregs[0], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R1)
sequence = PrintRegister("r1", frame_arm->context.iregs[1], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R2)
sequence = PrintRegister("r2", frame_arm->context.iregs[2], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R3)
sequence = PrintRegister("r3", frame_arm->context.iregs[3], sequence);
// General-purpose callee-saves registers.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
sequence = PrintRegister("r4", frame_arm->context.iregs[4], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R5)
sequence = PrintRegister("r5", frame_arm->context.iregs[5], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R6)
sequence = PrintRegister("r6", frame_arm->context.iregs[6], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R7)
sequence = PrintRegister("r7", frame_arm->context.iregs[7], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R8)
sequence = PrintRegister("r8", frame_arm->context.iregs[8], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R9)
sequence = PrintRegister("r9", frame_arm->context.iregs[9], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R10)
sequence = PrintRegister("r10", frame_arm->context.iregs[10], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R12)
sequence = PrintRegister("r12", frame_arm->context.iregs[12], sequence);
// Registers with a dedicated or conventional purpose.
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_FP)
sequence = PrintRegister("fp", frame_arm->context.iregs[11], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)
sequence = PrintRegister("sp", frame_arm->context.iregs[13], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_LR)
sequence = PrintRegister("lr", frame_arm->context.iregs[14], sequence);
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence);
} else if (cpu == "arm64") {
const StackFrameARM64 *frame_arm64 =
reinterpret_cast<const StackFrameARM64*>(frame);
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X0) {
sequence =
PrintRegister64("x0", frame_arm64->context.iregs[0], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X1) {
sequence =
PrintRegister64("x1", frame_arm64->context.iregs[1], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X2) {
sequence =
PrintRegister64("x2", frame_arm64->context.iregs[2], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X3) {
sequence =
PrintRegister64("x3", frame_arm64->context.iregs[3], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X4) {
sequence =
PrintRegister64("x4", frame_arm64->context.iregs[4], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X5) {
sequence =
PrintRegister64("x5", frame_arm64->context.iregs[5], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X6) {
sequence =
PrintRegister64("x6", frame_arm64->context.iregs[6], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X7) {
sequence =
PrintRegister64("x7", frame_arm64->context.iregs[7], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X8) {
sequence =
PrintRegister64("x8", frame_arm64->context.iregs[8], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X9) {
sequence =
PrintRegister64("x9", frame_arm64->context.iregs[9], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X10) {
sequence =
PrintRegister64("x10", frame_arm64->context.iregs[10], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X11) {
sequence =
PrintRegister64("x11", frame_arm64->context.iregs[11], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X12) {
sequence =
PrintRegister64("x12", frame_arm64->context.iregs[12], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X13) {
sequence =
PrintRegister64("x13", frame_arm64->context.iregs[13], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X14) {
sequence =
PrintRegister64("x14", frame_arm64->context.iregs[14], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X15) {
sequence =
PrintRegister64("x15", frame_arm64->context.iregs[15], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X16) {
sequence =
PrintRegister64("x16", frame_arm64->context.iregs[16], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X17) {
sequence =
PrintRegister64("x17", frame_arm64->context.iregs[17], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X18) {
sequence =
PrintRegister64("x18", frame_arm64->context.iregs[18], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X19) {
sequence =
PrintRegister64("x19", frame_arm64->context.iregs[19], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X20) {
sequence =
PrintRegister64("x20", frame_arm64->context.iregs[20], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X21) {
sequence =
PrintRegister64("x21", frame_arm64->context.iregs[21], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X22) {
sequence =
PrintRegister64("x22", frame_arm64->context.iregs[22], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X23) {
sequence =
PrintRegister64("x23", frame_arm64->context.iregs[23], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X24) {
sequence =
PrintRegister64("x24", frame_arm64->context.iregs[24], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X25) {
sequence =
PrintRegister64("x25", frame_arm64->context.iregs[25], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X26) {
sequence =
PrintRegister64("x26", frame_arm64->context.iregs[26], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X27) {
sequence =
PrintRegister64("x27", frame_arm64->context.iregs[27], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X28) {
sequence =
PrintRegister64("x28", frame_arm64->context.iregs[28], sequence);
}
// Registers with a dedicated or conventional purpose.
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_FP) {
sequence =
PrintRegister64("fp", frame_arm64->context.iregs[29], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_LR) {
sequence =
PrintRegister64("lr", frame_arm64->context.iregs[30], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) {
sequence =
PrintRegister64("sp", frame_arm64->context.iregs[31], sequence);
}
if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_PC) {
sequence =
PrintRegister64("pc", frame_arm64->context.iregs[32], sequence);
}
} else if (cpu == "mips") {
const StackFrameMIPS* frame_mips =
reinterpret_cast<const StackFrameMIPS*>(frame);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_GP)
sequence = PrintRegister64("gp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_GP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_SP)
sequence = PrintRegister64("sp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_SP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_FP)
sequence = PrintRegister64("fp",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_FP],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_RA)
sequence = PrintRegister64("ra",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_RA],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_PC)
sequence = PrintRegister64("pc", frame_mips->context.epc, sequence);
// Save registers s0-s7
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S0)
sequence = PrintRegister64("s0",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S0],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S1)
sequence = PrintRegister64("s1",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S1],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S2)
sequence = PrintRegister64("s2",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S2],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S3)
sequence = PrintRegister64("s3",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S3],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S4)
sequence = PrintRegister64("s4",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S4],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S5)
sequence = PrintRegister64("s5",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S5],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S6)
sequence = PrintRegister64("s6",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S6],
sequence);
if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S7)
sequence = PrintRegister64("s7",
frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S7],
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);
}
}
}
// PrintStackMachineReadable prints the call stack in |stack| to stdout,
// in the following machine readable pipe-delimited text format:
// thread number|frame number|module|function|source file|line|offset
//
// Module, function, source file, and source line may all be empty
// depending on availability. The code offset follows the same rules as
// PrintStack above.
static void PrintStackMachineReadable(int thread_num, const CallStack *stack) {
int frame_count = stack->frames()->size();
for (int frame_index = 0; frame_index < frame_count; ++frame_index) {
const StackFrame *frame = stack->frames()->at(frame_index);
printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index,
kOutputSeparator);
uint64_t instruction_address = frame->ReturnAddress();
if (frame->module) {
assert(!frame->module->code_file().empty());
printf("%s", StripSeparator(PathnameStripper::File(
frame->module->code_file())).c_str());
if (!frame->function_name.empty()) {
printf("%c%s", kOutputSeparator,
StripSeparator(frame->function_name).c_str());
if (!frame->source_file_name.empty()) {
printf("%c%s%c%d%c0x%" PRIx64,
kOutputSeparator,
StripSeparator(frame->source_file_name).c_str(),
kOutputSeparator,
frame->source_line,
kOutputSeparator,
instruction_address - frame->source_line_base);
} else {
printf("%c%c%c0x%" PRIx64,
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->function_base);
}
} else {
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address - frame->module->base_address());
}
} else {
// the printf before this prints a trailing separator for module name
printf("%c%c%c%c0x%" PRIx64,
kOutputSeparator, // empty function name
kOutputSeparator, // empty source file
kOutputSeparator, // empty source line
kOutputSeparator,
instruction_address);
}
printf("\n");
}
}
// ContainsModule checks whether a given |module| is in the vector
// |modules_without_symbols|.
static bool ContainsModule(
const vector<const CodeModule*> *modules,
const CodeModule *module) {
assert(modules);
assert(module);
vector<const CodeModule*>::const_iterator iter;
for (iter = modules->begin(); iter != modules->end(); ++iter) {
if (module->debug_file().compare((*iter)->debug_file()) == 0 &&
module->debug_identifier().compare((*iter)->debug_identifier()) == 0) {
return true;
}
}
return false;
}
// PrintModule prints a single |module| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModule(
const CodeModule *module,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols,
uint64_t main_address) {
string symbol_issues;
if (ContainsModule(modules_without_symbols, module)) {
symbol_issues = " (WARNING: No symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
} else if (ContainsModule(modules_with_corrupt_symbols, module)) {
symbol_issues = " (WARNING: Corrupt symbols, " +
PathnameStripper::File(module->debug_file()) + ", " +
module->debug_identifier() + ")";
}
uint64_t base_address = module->base_address();
printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n",
base_address, base_address + module->size() - 1,
PathnameStripper::File(module->code_file()).c_str(),
module->version().empty() ? "???" : module->version().c_str(),
main_address != 0 && base_address == main_address ? " (main)" : "",
symbol_issues.c_str());
}
// PrintModules prints the list of all loaded |modules| to stdout.
// |modules_without_symbols| should contain the list of modules that were
// confirmed to be missing their symbols during the stack walk.
static void PrintModules(
const CodeModules *modules,
const vector<const CodeModule*> *modules_without_symbols,
const vector<const CodeModule*> *modules_with_corrupt_symbols) {
if (!modules)
return;
printf("\n");
printf("Loaded modules:\n");
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
PrintModule(module, modules_without_symbols, modules_with_corrupt_symbols,
main_address);
}
}
// PrintModulesMachineReadable outputs a list of loaded modules,
// one per line, in the following machine-readable pipe-delimited
// text format:
// Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}|
// {Base Address}|{Max Address}|{Main}
static void PrintModulesMachineReadable(const CodeModules *modules) {
if (!modules)
return;
uint64_t main_address = 0;
const CodeModule *main_module = modules->GetMainModule();
if (main_module) {
main_address = main_module->base_address();
}
unsigned int module_count = modules->module_count();
for (unsigned int module_sequence = 0;
module_sequence < module_count;
++module_sequence) {
const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
uint64_t base_address = module->base_address();
printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n",
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->code_file())).c_str(),
kOutputSeparator, StripSeparator(module->version()).c_str(),
kOutputSeparator,
StripSeparator(PathnameStripper::File(module->debug_file())).c_str(),
kOutputSeparator,
StripSeparator(module->debug_identifier()).c_str(),
kOutputSeparator, base_address,
kOutputSeparator, base_address + module->size() - 1,
kOutputSeparator,
main_module != NULL && base_address == main_address ? 1 : 0);
}
}
} // namespace
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;
printf("Operating system: %s\n", process_state.system_info()->os.c_str());
printf(" %s\n",
process_state.system_info()->os_version.c_str());
printf("CPU: %s\n", cpu.c_str());
if (!cpu_info.empty()) {
// This field is optional.
printf(" %s\n", cpu_info.c_str());
}
printf(" %d CPU%s\n",
process_state.system_info()->cpu_count,
process_state.system_info()->cpu_count != 1 ? "s" : "");
printf("\n");
// Print crash information.
if (process_state.crashed()) {
printf("Crash reason: %s\n", process_state.crash_reason().c_str());
printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address());
} else {
printf("No crash\n");
}
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("Assertion: %s\n", assertion.c_str());
}
// Compute process uptime if the process creation and crash times are
// available in the dump.
if (process_state.time_date_stamp() != 0 &&
process_state.process_create_time() != 0 &&
process_state.time_date_stamp() >= process_state.process_create_time()) {
printf("Process uptime: %d seconds\n",
process_state.time_date_stamp() -
process_state.process_create_time());
} else {
printf("Process uptime: not available\n");
}
// If the thread that requested the dump is known, print it first.
int requesting_thread = process_state.requesting_thread();
if (requesting_thread != -1) {
printf("\n");
printf("Thread %d (%s)\n",
requesting_thread,
process_state.crashed() ? "crashed" :
"requested dump, did not crash");
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.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// 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,
output_stack_contents,
process_state.thread_memory_regions()->at(thread_index),
process_state.modules(), resolver);
}
}
PrintModules(process_state.modules(),
process_state.modules_without_symbols(),
process_state.modules_with_corrupt_symbols());
}
void PrintProcessStateMachineReadable(const ProcessState& process_state) {
// Print OS and CPU information.
// OS|{OS Name}|{OS Version}
// CPU|{CPU Name}|{CPU Info}|{Number of CPUs}
printf("OS%c%s%c%s\n", kOutputSeparator,
StripSeparator(process_state.system_info()->os).c_str(),
kOutputSeparator,
StripSeparator(process_state.system_info()->os_version).c_str());
printf("CPU%c%s%c%s%c%d\n", kOutputSeparator,
StripSeparator(process_state.system_info()->cpu).c_str(),
kOutputSeparator,
// this may be empty
StripSeparator(process_state.system_info()->cpu_info).c_str(),
kOutputSeparator,
process_state.system_info()->cpu_count);
int requesting_thread = process_state.requesting_thread();
// Print crash information.
// Crash|{Crash Reason}|{Crash Address}|{Crashed Thread}
printf("Crash%c", kOutputSeparator);
if (process_state.crashed()) {
printf("%s%c0x%" PRIx64 "%c",
StripSeparator(process_state.crash_reason()).c_str(),
kOutputSeparator, process_state.crash_address(), kOutputSeparator);
} else {
// print assertion info, if available, in place of crash reason,
// instead of the unhelpful "No crash"
string assertion = process_state.assertion();
if (!assertion.empty()) {
printf("%s%c%c", StripSeparator(assertion).c_str(),
kOutputSeparator, kOutputSeparator);
} else {
printf("No crash%c%c", kOutputSeparator, kOutputSeparator);
}
}
if (requesting_thread != -1) {
printf("%d\n", requesting_thread);
} else {
printf("\n");
}
PrintModulesMachineReadable(process_state.modules());
// blank line to indicate start of threads
printf("\n");
// If the thread that requested the dump is known, print it first.
if (requesting_thread != -1) {
PrintStackMachineReadable(requesting_thread,
process_state.threads()->at(requesting_thread));
}
// Print all of the threads in the dump.
int thread_count = process_state.threads()->size();
for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
if (thread_index != requesting_thread) {
// Don't print the crash thread again, it was already printed.
PrintStackMachineReadable(thread_index,
process_state.threads()->at(thread_index));
}
}
}
} // namespace google_breakpad

View File

@ -0,0 +1,49 @@
// Copyright (c) 2010 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck
// executables to print the content of dumps (w/ stack traces) on the console.
#ifndef PROCESSOR_STACKWALK_COMMON_H__
#define PROCESSOR_STACKWALK_COMMON_H__
namespace google_breakpad {
class ProcessState;
class SourceLineResolverInterface;
void PrintProcessStateMachineReadable(const ProcessState& process_state);
void PrintProcessState(const ProcessState& process_state,
bool output_stack_contents,
SourceLineResolverInterface* resolver);
} // namespace google_breakpad
#endif // PROCESSOR_STACKWALK_COMMON_H__

View File

@ -0,0 +1,33 @@
W/google-breakpad( 3745): -----BEGIN BREAKPAD MICRODUMP-----
W/google-breakpad( 3745): O A arm 02 armv7l OS VERSION INFO
W/google-breakpad( 3745): S 0 FFEA68C0 FFEA6000 00002000
W/google-breakpad( 3745): S FFEA6000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080020000A000002CA705F728000000000000000A000000000000000000000028000000
W/google-breakpad( 3745): S FFEA6180 2168EAFFC59104F77C67EAFF7C62EAFF4062EAFF1E71B3AA040000001E71B3AA4062EAFF020000007C62EAFFD062EAFFE867EAFFFAFFFFFF8263EAFFC9A404F700000000000000000000000000000000000000008363EAFF000000005462EAFFFFFFFFFF7C67EAFF1E71B3AA00000000000000003B62EAFF800000000600000000000000000000003C62EAFF06000000000000001B71B3AA000000005C62EAFF0000000000000000000000004462EAFF80000000D4ED06F7000000000000000000000000000000000000000000000000000000000000000000000000E467EAFF00000000000000000000000000000000000000000000000000000000C862EAFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008263EAFF06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA6300 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003430313631380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA6480 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA6600 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BAE0417D0000000000000000060000002168EAFFD4ED06F71869EAFFF867EAFF070000001B71B3AAA76805F70000000000000000E467EAFF000000000000000000000000000000000000000000000000FFFFFFFF004000002768EAFF
W/google-breakpad( 3745): S FFEA6780 0000000000000000285F20ABB467EAFF030000002768EAFF200000007702B3AA1869EAFF1F0000000868EAFF6347AEAA1869EAFF200000001869EAFF1F0000002768EAFF0868EAFF1869EAFF4548AEAA00000000800000000868EAFF2168EAFFD4ED06F7B549AEAA00000000000000000000000000000000010000000000000058585858585800002F646174612F6C6F63616C2F746D702F627265616B7061642E3430313631380000FD0000000000000000000031000000F941000002000000D0070000D0070000000000000000000000000000000000000010000000000000001000000000000080B220AB9468EAFFA0B220ABD53AAEAA3069EAFF914BAEAA3069EAFF4882B3AA083020ABF068EAFFA20E0000FFFFFFFF083020ABE99902F7C8DE08F7FF8102F700000000D0DE08F70069EAFFF068EAFFF868EAFFB3B2AEAAD068EAFF0000000000000000D4ED06F70500000000000000000000000000000003000000040000000000000000000000FFFFFFFF00000000FFFFFFFF00000000
W/google-breakpad( 3745): S FFEA6900 010000000000000000000000000000000000000000000000485F20AB000000000000000000000000475F20AB285F20ABB0B220AB05000000D1D320AB379304F7AAB220AB80B220ABF869EAFF3BBAB3AA040000003BBAB3AAF869EAFF03000000346AEAFF906AEAFF346FEAFFFBFFFFFF605420ABC9A404F74C6AEAFFA86AEAFF4C6FEAFFEDFFFFFF303D20AB046AEAFF6FCAB3AA0C6AEAFFFFFFFFFFF4D306F73BBAB3AA0000000000000000F369EAFF0000000019000000EC69EAFF00000000F469EAFF050000000000000036BAB3AA00000000146AEAFF0C6AEAFFF469EAFF00000000FC69EAFF00000000D4ED06F70000000000000000000000000000000000000000000000000000000000000000000000002C6FEAFF0000000000000000DC3CB4AA000000005C6AEAFF786AEAFF00000000806AEAFF0000000000000000DC3CB4AA906AEAFF00000000986AEAFF0000000000000000000000000000000000000000000000005D6BEAFF30A820ABA06BEAFF0000000028BAB3AA0D000000
W/google-breakpad( 3745): S FFEA6A80 38BAB3AA01000000605420AB05000000FAB9B3AA0D00000083C9B3AA06000000303D20AB13000000746FEAFF0B00000000A820ABF8A720AB904020AB78A820ABC52DAEAAC72DAEAA0A0000000A0000000000000046696C654944546573742F3100A820ABE06AEAFFFAB9B3AA0D0000004944546573742F3100000000F86AEAFFEC6AEAFF46696C6572000000874220ABCD6EEAFF6163B0AA6F000000864220ABCD6EEAFF6163B0AA65000000BDC620ABCD6EEAFF6163B0AA70000000BCC620ABCD6EEAFF6163B0AA79000000BBC620ABCD6EEAFF6163B0AA54000000BAC620ABCD6EEAFF6163B0AA65000000B9C620ABCD6EEAFF6163B0AA74000000B8C620ABCD6EEAFF6163B0AA61000000B7C620ABCD6EEAFF6163B0AA6C000000B6C620ABCD6EEAFF6163B0AA70000000B5C620ABCD6EEAFF6163B0AA6D000000B4C620ABCD6EEAFF6163B0AA65000000B3C620ABCD6EEAFF6163B0AA54000000B2C620ABCD6EEAFF6163B0AA68000000B1C620ABCD6EEAFF6163B0AA74000000B0C620AB
W/google-breakpad( 3745): S FFEA6C00 CD6EEAFF6163B0AA67000000A7B220ABCD6EEAFF6163B0AA6E000000A6B220ABCD6EEAFF6163B0AA69000000A5B220ABCD6EEAFF6163B0AA72000000A4B220ABCD6EEAFF6163B0AA74000000A3B220ABCD6EEAFF6163B0AA53000000A2B220ABCD6EEAFF6163B0AA44000000A1B220ABCD6EEAFF6163B0AA4D000000A0B220ABCD6EEAFF6163B0AA690000009FB220ABCD6EEAFF6163B0AA690000009EB220ABCD6EEAFF6163B0AA630000009DB220ABCD6EEAFF6163B0AA730000009CB220ABCD6EEAFF6163B0AA74000000435F20ABCD6EEAFF6163B0AA65000000425F20AB00000000C4D720AB310000007762AEAAC4D720AB7E6EEAFFC06EEAFF693BB2AAC4D720AB01CAB3AAC4D720AB01CAB3AAC4D720AB00000000C06EEAFF20000000C06EEAFF08100000088120ABFBACB2AA088120ABC4D720AB01CAB3AAC4D720AB016FEAFF6163B0AA6D0000003B5F20ABCD6EEAFF6163B0AA670000003A5F20ABCD6EEAFF6163B0AA69000000395F20ABCD6EEAFF6163B0AAB8E8B4AACC6DEAFF
W/google-breakpad( 3745): S FFEA6D80 15000000010000007D6EEAFF00D820ABC06EEAFF08100000088120AB01000000D83420ABC7AFB2AA01000000C4D720AB01CAB3AA0810000000000000200000002B0000002D000000B8E8B4AAB8E8B4AA00D820AB1C6EEAFF0000000000000000D06DEAFFD06DEAFF0A0000000A000000000000000000000000000000A35DB3AA01000000000000000A00000031000000000000007D6EEAFF7D6EEAFF005DB3AA286EEAFF5F24B2AAB8E8B4AA20D820AB12000000BCE8B4AAFC6EEAFFBB2CB2AAB8E8B4AA20D820ABB8D720AB02000000B0D720AB000000C0B8D720ABB8D720ABFC6EEAFF29F003F7B8D720ABC0D720ABB8D720ABA86EEAFFFC6EEAFF595D02F7B542AEAAC342AEAAA86EEAFF073BAEAAAC6EEAFFD19DAFAA00D820AB20000000576FEAFFD53AAEAA546FEAFF914BAEAA546FEAFF76C9B3AA546FEAFF146FEAFFBB00000048070000E0D720AB0300000018D820ABF4E3B4AA18D820AB0700000000000000485420ABD0D720AB8399B0AA23C8B3AAD0D720ABD0D720ABBAE0417D
W/google-breakpad( 3745): S FFEA6F00 23C8B3AADC31B4AAD0D720AB783420AB49010000883520ABD0D720AB606FEAFFD83420AB41A7B0AA08000000010000001000000001000000783420AB8399B0AA485420AB783420ABDD1CD2F675A8B0AA08000000010000005AC8B3AAC85420AB08000000010000000800000001000000C85420AB00000000DD1CD2F649010000783420AB883520AB01000000FDA8B0AA715FB0AA0000000000000000C78404F7D160B0AA783420AB883520AB000000000100000000000000F04720ABFDAAB0AAF4E8B4AA01000000DD1CD2F64901000040E4B4AA40E4B4AA2EBCB3AAE7C8B3AA1EC9B3AA33C9B3AA02000000B0B220AB2C70EAFF00000000783420AB02000000192CAEAA0000000000000000000000006C70EAFF619AB0AA2C70EAFF7470EAFF020000003B2CAEAA02000000010000008070EAFF7470EAFF8070EAFF9F5E02F75870EAFF00000000000000000000000000000000842DAEAA00B9B4AA98B8B4AA90B8B4AAF8B8B4AA00000000FF2608F7020000007F7BEAFF0000000000000000
W/google-breakpad( 3745): S FFEA7080 B97BEAFFDE7BEAFF0A7CEAFF1D7CEAFFD97DEAFF167EEAFF2F7EEAFF447EEAFF6E7EEAFF877EEAFF9E7EEAFFC87EEAFFE37EEAFFFD7EEAFF0A7FEAFF247FEAFF437FEAFFC27FEAFF0000000010000000D6B00700060000000010000011000000640000000300000034D0ACAA040000002000000005000000080000000700000000F007F7080000000000000009000000282DAEAA0B000000000000000C000000000000000D000000000000000E000000000000001700000000000000190000006C71EAFF1A0000001F0000001F000000D57FEAFF0F0000007C71EAFF00000000000000000000000000000000BAE0417DA395F6D9D5EFEE82959378DA76386C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA7200 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA7380 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA7500 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA7680 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA7800 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA7980 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): S FFEA7B00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F646174612F6C6F63616C2F746D702F627265616B7061645F756E69747465737473002D2D67746573745F66696C7465723D2A4D6963726F2A005F3D2F646174612F6C6F63616C2F746D702F627265616B7061645F756E6974746573747300454D554C415445445F53544F524147455F534F555243453D2F6D6E742F7368656C6C2F656D756C6174656400414E44524F49445F444154413D2F6461746100424F4F54434C415353504154483D2F73797374656D2F6672616D65776F726B2F636F72652D6C69626172742E6A61723A2F73797374656D2F6672616D65776F726B2F636F6E7363727970742E6A61723A2F73797374656D2F6672616D65776F726B2F6F
W/google-breakpad( 3745): S FFEA7C80 6B687474702E6A61723A2F73797374656D2F6672616D65776F726B2F636F72652D6A756E69742E6A61723A2F73797374656D2F6672616D65776F726B2F626F756E6379636173746C652E6A61723A2F73797374656D2F6672616D65776F726B2F6578742E6A61723A2F73797374656D2F6672616D65776F726B2F6672616D65776F726B2E6A61723A2F73797374656D2F6672616D65776F726B2F74656C6570686F6E792D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F766F69702D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F696D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F6D6D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F616E64726F69642E706F6C6963792E6A61723A2F73797374656D2F6672616D65776F726B2F6170616368652D786D6C2E6A617200504154483D2F7362696E3A2F76656E646F722F62696E3A2F73797374656D2F7362696E3A2F7379
W/google-breakpad( 3745): S FFEA7E00 7374656D2F62696E3A2F73797374656D2F7862696E004C4F4F505F4D4F554E54504F494E543D2F6D6E742F6F626200414E44524F49445F524F4F543D2F73797374656D00454D554C415445445F53544F524147455F5441524745543D2F73746F726167652F656D756C6174656400414E44524F49445F53544F524147453D2F73746F7261676500414E44524F49445F534F434B45545F616462643D31310045585445524E414C5F53544F524147453D2F73746F726167652F656D756C617465642F6C656761637900414E44524F49445F4153534554533D2F73797374656D2F617070004C445F5052454C4F41443D6C6962736967636861696E2E736F0052414E444F4D3D313131373200415345435F4D4F554E54504F494E543D2F6D6E742F6173656300414E44524F49445F50524F50455254595F574F524B53504143453D392C300053595354454D534552564552434C415353504154483D2F73797374656D2F6672616D65776F726B2F73657276696365732E6A61723A2F73797374656D2F
W/google-breakpad( 3745): S FFEA7F80 6672616D65776F726B2F65746865726E65742D736572766963652E6A61723A2F73797374656D2F6672616D65776F726B2F776966692D736572766963652E6A617200414E44524F49445F424F4F544C4F474F3D31002F646174612F6C6F63616C2F746D702F627265616B7061645F756E69747465737473000000000000000000
W/google-breakpad( 3745): C 06000040000000000000000000000000000000000069EAFFF068EAFFF868EAFF0469EAFFE068EAFF0069EAFF3069EAFFA20E000000000000C068EAFF07B3AEAA07B3AEAA000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3745): M AAACD000 00000000 0007C000 DA7778FB66018A4E9B4110ED06E730D00 breakpad_unittests
W/google-breakpad( 3745): M F6FCA000 00000000 00004000 56B149396A4DAF176E26B4A85DA87BF30 libnetd_client.so
W/google-breakpad( 3745): M F6FEE000 00000000 00004000 DFCD7772F3A5BD1E84A50C4DBFDE6F570 libstdc++.so
W/google-breakpad( 3745): M F6FF2000 00000000 00019000 AE3467401278371A956801500FC8187D0 libm.so
W/google-breakpad( 3745): M F700C000 00000000 00007000 0A492DEF82842051996A468D87F23F010 liblog.so
W/google-breakpad( 3745): M F7014000 00000000 0005A000 167F187B09A27F7444EF989603AAFD3D0 libc.so
W/google-breakpad( 3745): -----END BREAKPAD MICRODUMP-----

View File

@ -0,0 +1,45 @@
W/google-breakpad( 3728): -----BEGIN BREAKPAD MICRODUMP-----
W/google-breakpad( 3728): O A arm64 02 aarch64 OS 64 VERSION INFO
W/google-breakpad( 3728): S 0 0000007FE2BA6120 0000007FE2BA6000 0000000000003000
W/google-breakpad( 3728): S 0000007FE2BA6000 0700000000000000A060BAE27F0000007060BAE27F000000E4006A5F550000007060BAE27F000000FC006A5F550000001000000000000000D0006E5F550000002061BAE27F0000004C6E635F550000002061BAE27F0000002061BAE27F000000F060BAE27F000000D0FFFFFF80FFFFFFD060BAE27F00000020142B807F00000010E04E9555000000E065BAE27F000000A061BAE27F00000000406B5F55000000D060BAE27F00000058142B807F00000010E04E955500000000000000000000000104104001041040FFFFFFFFFFFFFFFFF060BAE27F00000048E62A807F000000E8C036807F00000040E62A807F0000002061BAE27F000000E86E635F55000000506ABAE27F000000E065BAE27F000000A061BAE27F000000FEFE2E7273636471507ABAE27F0000003C32665F55000000D02250955500000070E14E955500000070E14E955500000090E34E95550000004A62D1F64901000000F06D5F5500000001000000000000004962D1F6490100000100000000000000C9356B5F55000000
W/google-breakpad( 3728): S 0000007FE2BA6180 00000000000000009863BAE27F0000000000000005000000000000000000000003000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F646174612F6C6F63616C2F746D702F627265616B7061642E323839333833000F62BAE27F000000F061BAE27F000000D0F34E9555000000000000000000000000000000000000000000000000000000CAF34E9555000000A0F34E95550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6300 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6480 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6600 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004067BAE27F000000A04E2D807F0000004067BAE27F000000104E2D807F000000186E33807F0000002000000000000000006033807F000000007033807F00000090E64E9555000000000000000000000000000000000000000000000000000000A067BAE27F00000010C22A807F000000020000000000000000F06D5F550000002079BAE27F00000058F66D5F55000000D067BAE27F000000986A2D807F000000
W/google-breakpad( 3728): S 0000007FE2BA6780 80E64E9555000000006033807F00000090E64E955500000058F66D5F5500000020B5625F550000001CB5625F550000000068BAE27F000000C8C12A807F0000004868BAE27F0000008068BAE27F0000002079BAE27F00000058F66D5F5500000020B5625F550000008068BAE27F0000002079BAE27F00000058F66D5F550000001068BAE27F000000D0B9665F550000008078BAE27F000000987C665F550000002079BAE27F00000070E14E955500000060E04E9555000000000000000000000000000000000000002F000000000000000000000000000000000000000000000000000000000000004968BAE27F0000004868BAE27F0000002F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6900 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6A80 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6C00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6D80 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA6F00 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008070BAE27F000000DC4C2E807F0000002300000000000000000C509555000000702333807F0000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA7080 B070BAE27F000000B8672E807F000000C070BAE27F000000DC4C2E807F0000002E00000000000000000C5095550000001071BAE27F000000A4882E807F0000000073BAE27F000000B073BAE27F0000000D000000000000000D00000000000000DB336B5F55000000702333807F0000005071BAE27F000000A4882E807F0000004073BAE27F000000F073BAE27F0000007071BAE27F0000001C8A2E807F000000F472BAE27F000000F073BAE27F0000000073BAE27F000000E1336B5F55000000E1336B5F55000000702333807F0000000000000000000000050000000000000005000000000000004073BAE27F000000F078BAE27F000000F0BB2E807F000000702333807F00000090E34E955500000090384F955500000090E34E95550000004A62D1F64901000000F06D5F5500000001000000000000004962D1F6490100000100000000000000C9356B5F55000000000000000000000050E24E9555000000D3416B5F550000000A426B5F5500000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA7200 00000000000000000000000000000000000000000000000000000000000000002F73BAE27F0000005073BAE27F0000003F73BAE280FFFFFF2873BAE27F0000000000000000000000107ABAE27F0000000000000000000000207ABAE27F0000000000000000000000A772BAE27F0000007F73BAE280FFFFFFCDCCCCCCCCCCCCCC0000000000000000507ABAE27F000000E46E30807F000000607ABAE27F000000E872BAE27F000000E772BAE27F000000000000007F000000030000007F000000000000000000000003000000CCCCCCCC0000000000000000E07ABAE27F00000000000000000000006000655F550000008DEE4E95000000008100BAE27F000000000000000000000000000000000000000000000000000000507ABAE27F000000207ABAE27F000000D0FFFFFF80FFFFFF307ABAE27F000000D0FFFFFF80FFFFFFF073BAE27F0000000000000000000000507ABAE27F000000507ABAE27F000000107ABAE27F000000C8FFFFFF80FFFFFF207ABAE27F000000C8FFFFFF80FFFFFF
W/google-breakpad( 3728): S 0000007FE2BA7380 A073BAE27F00000060DC655F550000004074BAE27F0000000000000000000000E07ABAE27F000000E07ABAE27F000000CE336B5F550000000D00000000000000A0336B5F550000000D00000000000000C6F34E95550000008179BAE27F0000000074BAE27F00000060DC655F55000000DE336B5F550000000100000000000000C0384F95550000000500000000000000A8394F955500000013000000000000004074BAE27F00000060DC655F55000000C3F34E95550000008179BAE27F000000A0336B5F550000000D00000000000000C2F34E95550000008179BAE27F0000008074BAE27F00000060DC655F55000000C1F34E95550000008179BAE27F000000A074BAE27F00000060DC655F55000000C0F34E95550000008179BAE27F000000C074BAE27F00000060DC655F55000000BFF34E95550000008179BAE27F000000E074BAE27F00000060DC655F55000000BEF34E95550000008179BAE27F0000000075BAE27F00000060DC655F55000000BDF34E95550000008179BAE27F000000
W/google-breakpad( 3728): S 0000007FE2BA7500 2075BAE27F00000060DC655F55000000BCF34E95550000008179BAE27F0000004075BAE27F00000060DC655F550000006B79BAE27F0000008179BAE27F0000006075BAE27F00000060DC655F550000006A79BAE27F0000008179BAE27F0000008075BAE27F00000060DC655F550000006979BAE27F0000008179BAE27F000000A075BAE27F00000060DC655F550000006879BAE27F0000008179BAE27F000000C075BAE27F00000060DC655F550000006779BAE27F0000008179BAE27F000000E075BAE27F00000060DC655F550000006679BAE27F0000008179BAE27F0000000076BAE27F00000060DC655F550000006579BAE27F0000008179BAE27F0000002076BAE27F00000060DC655F550000006479BAE27F0000008179BAE27F0000004076BAE27F00000060DC655F550000006379BAE27F0000008179BAE27F0000006076BAE27F00000060DC655F550000006279BAE27F0000008179BAE27F0000008076BAE27F00000060DC655F550000006179BAE27F0000008179BAE27F000000
W/google-breakpad( 3728): S 0000007FE2BA7680 A076BAE27F00000060DC655F550000006079BAE27F0000008179BAE27F000000C076BAE27F00000060DC655F550000005F79BAE27F0000008179BAE27F000000E076BAE27F00000060DC655F550000005E79BAE27F0000008179BAE27F0000000077BAE27F00000060DC655F550000005D79BAE27F0000008179BAE27F0000002077BAE27F00000060DC655F55000000E077BAE27F000000AC74685F55000000F077BAE27F000000AC74685F550000004023509555000000A078BAE27F00000010235095550000009878BAE27F0000002078BAE27F000000AC74685F550000008077BAE27F000000C006635F5500000098225095550000003100000000000000B077BAE27F00000088BB695F5500000098225095550000005979BAE27F0000005A79BAE27F0000004488685F550000001078BAE27F00000054BF695F55000000B078BAE27F000000010000000000000050834F95550000008078BAE27F0000005979BAE27F000000982250955500000098225095550000000100000000000000
W/google-breakpad( 3728): S 0000007FE2BA7800 2D00000000000000C8FF6D5F55000000F078BAE27F00000068C4695F550000005A79BAE27F0000001023509555000000200000000000000098225095550000000100000000000000007ABAE27F000000B078BAE27F000000CCBB2E807F000000B078BAE27F000000FCBB2E807F000000702333807F0000000D00000000000000020000000000000090E34E9555000000F078BAE27F000000CCBB2E807F000000F078BAE27F000000FCBB2E807F000000702333807F000000190000000000000090384F955500000090E34E95550000004A62D1F649010000CE336B5F55000000507ABAE27F000000443272DD1F92C7154079BAE27F000000C0752E807F00000090384F955500000090E34E95550000005079BAE27F000000DC336B5F550000008079BAE27F000000A04E2D807F0000008079BAE27F000000104E2D807F000000186E33807F0000006001000000000000006033807F000000007033807F000000F022509555000000C8FFFFFF80FFFFFFC079BAE27F00000090DD625F55000000
W/google-breakpad( 3728): S 0000007FE2BA7980 60235095550000000700000000000000D7F66D5F55000000D0F66D5F55000000C079BAE27F00000068DD625F5500000010245095550000000000000000000000F079BAE27F000000C4F2655F55000000007ABAE27F000000F031665F55000000D022509555000000D022509555000000107ABAE27F00000060FE655F55000000107ABAE27F0000001441665F55000000407ABAE27F000000F031665F55000000D02250955500000070E14E9555000000607ABAE27F000000F031665F55000000507ABAE27F0000001832665F55000000807ABAE27F0000008C44665F55000000D02250955500000070E14E955500000020000000000000000100000000000000A07ABAE27F000000B845665F5500000090384F9555000000D022509555000000E07ABAE27F0000007446665F55000000A0394F955500000070E14E955500000090E34E955500000001000000000000004A62D1F6490100005EC60A0000000000207BBAE27F0000004C49665F5500000070E14E95550000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA7B00 90E34E955500000002000000000000000000000000000000D048665F55000000C07BBAE27F000000684B665F55000000000000000000000070E14E9555000000020000000000000060B3625F550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C07BBAE27F000000E0054F9555000000C07BBAE27F000000604B665F55000000F07BBAE27F00000098B3625F550000001C7CBAE27F000000887CBAE27F0000000200000000000000A0F34E9555000000207CBAE27F0000008CC32A807F000000A07CBAE27F0000000000000000000000887CBAE27F0000000010000001000000507CBAE27F00000004B5625F550000000000000000000000000000000000000000000000000000000000000000000000000000000000000050B635807F0000000000000000000000D07D6D5F55000000E07D6D5F55000000A07E6D5F55000000
W/google-breakpad( 3728): S 0000007FE2BA7C80 02000000000000007F8BBAE27F00000000000000000000000000000000000000B98BBAE27F000000DE8BBAE27F0000000A8CBAE27F0000001D8CBAE27F000000D98DBAE27F000000168EBAE27F0000002F8EBAE27F000000448EBAE27F0000006E8EBAE27F000000878EBAE27F0000009E8EBAE27F000000C88EBAE27F000000E38EBAE27F000000FD8EBAE27F0000000A8FBAE27F000000248FBAE27F000000438FBAE27F000000C28FBAE27F00000000000000000000002100000000000000008035807F0000001000000000000000FB00000000000000060000000000000000100000000000001100000000000000640000000000000003000000000000004080605F550000000400000000000000380000000000000005000000000000000800000000000000070000000000000000A035807F000000080000000000000000000000000000000900000000000000A4B4625F550000000B0000000000000000000000000000000C0000000000000000000000000000000D00000000000000
W/google-breakpad( 3728): S 0000007FE2BA7E00 00000000000000000E000000000000000000000000000000170000000000000000000000000000001900000000000000687EBAE27F0000001F00000000000000D58FBAE27F0000000F00000000000000787EBAE27F00000000000000000000000000000000000000443272DD1F92C715BDF280FA6D8DE039616172636836340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA7F80 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA8100 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA8280 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA8400 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA8580 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA8700 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA8880 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): S 0000007FE2BA8A00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002F
W/google-breakpad( 3728): S 0000007FE2BA8B80 646174612F6C6F63616C2F746D702F627265616B7061645F756E69747465737473002D2D67746573745F66696C7465723D2A4D6963726F2A005F3D2F646174612F6C6F63616C2F746D702F627265616B7061645F756E6974746573747300454D554C415445445F53544F524147455F534F555243453D2F6D6E742F7368656C6C2F656D756C6174656400414E44524F49445F444154413D2F6461746100424F4F54434C415353504154483D2F73797374656D2F6672616D65776F726B2F636F72652D6C69626172742E6A61723A2F73797374656D2F6672616D65776F726B2F636F6E7363727970742E6A61723A2F73797374656D2F6672616D65776F726B2F6F6B687474702E6A61723A2F73797374656D2F6672616D65776F726B2F636F72652D6A756E69742E6A61723A2F73797374656D2F6672616D65776F726B2F626F756E6379636173746C652E6A61723A2F73797374656D2F6672616D65776F726B2F6578742E6A61723A2F73797374656D2F6672616D65776F726B2F6672616D6577
W/google-breakpad( 3728): S 0000007FE2BA8D00 6F726B2E6A61723A2F73797374656D2F6672616D65776F726B2F74656C6570686F6E792D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F766F69702D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F696D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F6D6D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F616E64726F69642E706F6C6963792E6A61723A2F73797374656D2F6672616D65776F726B2F6170616368652D786D6C2E6A617200504154483D2F7362696E3A2F76656E646F722F62696E3A2F73797374656D2F7362696E3A2F73797374656D2F62696E3A2F73797374656D2F7862696E004C4F4F505F4D4F554E54504F494E543D2F6D6E742F6F626200414E44524F49445F524F4F543D2F73797374656D00454D554C415445445F53544F524147455F5441524745543D2F73746F726167652F656D756C6174656400414E44524F49445F53544F524147453D2F73
W/google-breakpad( 3728): S 0000007FE2BA8E80 746F7261676500414E44524F49445F534F434B45545F616462643D31310045585445524E414C5F53544F524147453D2F73746F726167652F656D756C617465642F6C656761637900414E44524F49445F4153534554533D2F73797374656D2F617070004C445F5052454C4F41443D6C6962736967636861696E2E736F0052414E444F4D3D313638323700415345435F4D4F554E54504F494E543D2F6D6E742F6173656300414E44524F49445F50524F50455254595F574F524B53504143453D392C300053595354454D534552564552434C415353504154483D2F73797374656D2F6672616D65776F726B2F73657276696365732E6A61723A2F73797374656D2F6672616D65776F726B2F65746865726E65742D736572766963652E6A61723A2F73797374656D2F6672616D65776F726B2F776966692D736572766963652E6A617200414E44524F49445F424F4F544C4F474F3D31002F646174612F6C6F63616C2F746D702F627265616B7061645F756E69747465737473000000000000000000
W/google-breakpad( 3728): C 06000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000506ABAE27F000000E065BAE27F000000E061BAE27F00000000406B5F550000008062BAE27F0000005062BAE27F000000514C6B5F55000000910E0000000000002062BAE27F000000F061BAE27F0000002061BAE27F0000006C6F635F550000002061BAE27F0000006C6F635F550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
W/google-breakpad( 3728): M 000000555F608000 0000000000000000 00000000000C0000 D6D1FEC9A15DE7F38A236898871A2E770 breakpad_unittests
W/google-breakpad( 3728): M 0000007F801F6000 0000000000000000 0000000000013000 7735F44BA6D7C27FD5C3636A43369B7C0 libnetd_client.so
W/google-breakpad( 3728): M 0000007F80229000 0000000000000000 0000000000014000 380C0B7CD8FA3F094BC3BA58A81CBAD00 libstdc++.so
W/google-breakpad( 3728): M 0000007F8023D000 0000000000000000 000000000003D000 F832D47D1E237E46D835991594DA6E890 libm.so
W/google-breakpad( 3728): M 0000007F8027B000 0000000000000000 0000000000019000 C407B93F87A835BE05451FC7B0B3E65E0 liblog.so
W/google-breakpad( 3728): M 0000007F80295000 0000000000000000 000000000009E000 479D5438753E27F019F2C9980DDBF4F30 libc.so
W/google-breakpad( 3728): M 0000007F80341000 0000000000000000 0000000000013000 9DA3FF8EF9CA0FDC481292EE530DF6EC0 libsigchain.so
W/google-breakpad( 3728): M 0000007F80358000 0000000000000000 0000000000002000 672B2CD6CF8AF6C43BD70F2AB02B3D0C0 linux-gate.so
W/google-breakpad( 3728): -----END BREAKPAD MICRODUMP-----

View File

@ -0,0 +1,42 @@
Operating system: Android
OS VERSION INFO
CPU: armv7l
2 CPUs
Crash reason:
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 breakpad_unittests!MicrodumpWriterTest_Setup_Test::TestBody [gtest.h : 1481 + 0x1]
Found by: given as instruction pointer in context
1 breakpad_unittests!testing::Test::Run [gtest.cc : 2435 + 0x17]
Found by: call frame info
2 breakpad_unittests!testing::TestInfo::Run [gtest.cc : 2610 + 0x5]
Found by: call frame info
3 breakpad_unittests!testing::TestCase::Run [gtest.cc : 2728 + 0x3]
Found by: call frame info
4 breakpad_unittests!testing::internal::UnitTestImpl::RunAllTests [gtest.cc : 4591 + 0x3]
Found by: call frame info
5 breakpad_unittests!testing::UnitTest::Run [gtest.cc : 2418 + 0x5]
Found by: call frame info
6 breakpad_unittests!main [gtest.h : 2326 + 0x3]
Found by: call frame info
7 libc.so + 0x11e9d
Found by: call frame info
Loaded modules:
0xaaacd000 - 0xaab48fff breakpad_unittests ???
0xf6fca000 - 0xf6fcdfff libnetd_client.so ???
0xf6fee000 - 0xf6ff1fff libstdc++.so ???
0xf6ff2000 - 0xf700afff libm.so ???
0xf700c000 - 0xf7012fff liblog.so ???
0xf7014000 - 0xf706dfff libc.so ??? (WARNING: No symbols, libc.so, 167F187B09A27F7444EF989603AAFD3D0)

View File

@ -0,0 +1,47 @@
Operating system: Android
OS 64 VERSION INFO
CPU: aarch64
2 CPUs
Crash reason:
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 breakpad_unittests!MicrodumpWriterTest_Setup_Test::TestBody [microdump_writer_unittest.cc : 77 + 0xc]
Found by: given as instruction pointer in context
1 breakpad_unittests!testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void> [gtest.cc : 2418 + 0x4]
Found by: call frame info
2 breakpad_unittests!testing::Test::Run [gtest.cc : 2435 + 0x14]
Found by: call frame info
3 breakpad_unittests!testing::TestInfo::Run [gtest.cc : 2610 + 0x4]
Found by: call frame info
4 breakpad_unittests!testing::TestCase::Run [gtest.cc : 2728 + 0x0]
Found by: call frame info
5 breakpad_unittests!testing::internal::UnitTestImpl::RunAllTests [gtest.cc : 4591 + 0x0]
Found by: call frame info
6 breakpad_unittests!testing::UnitTest::Run [gtest.cc : 2418 + 0x4]
Found by: call frame info
7 breakpad_unittests!main [gtest.h : 2326 + 0x0]
Found by: call frame info
8 libc.so + 0x17388
Found by: call frame info
Loaded modules:
0x555f608000 - 0x555f6c7fff breakpad_unittests ???
0x7f801f6000 - 0x7f80208fff libnetd_client.so ???
0x7f80229000 - 0x7f8023cfff libstdc++.so ???
0x7f8023d000 - 0x7f80279fff libm.so ???
0x7f8027b000 - 0x7f80293fff liblog.so ???
0x7f80295000 - 0x7f80332fff libc.so ??? (WARNING: No symbols, libc.so, 479D5438753E27F019F2C9980DDBF4F30)
0x7f80341000 - 0x7f80353fff libsigchain.so ???
0x7f80358000 - 0x7f80359fff linux-gate.so ???

View File

@ -0,0 +1,18 @@
OS|Android|OS VERSION INFO
CPU|armv7l||2
Crash||0x0|0
Module|breakpad_unittests||breakpad_unittests|DA7778FB66018A4E9B4110ED06E730D00|0xaaacd000|0xaab48fff|0
Module|libnetd_client.so||libnetd_client.so|56B149396A4DAF176E26B4A85DA87BF30|0xf6fca000|0xf6fcdfff|0
Module|libstdc++.so||libstdc++.so|DFCD7772F3A5BD1E84A50C4DBFDE6F570|0xf6fee000|0xf6ff1fff|0
Module|libm.so||libm.so|AE3467401278371A956801500FC8187D0|0xf6ff2000|0xf700afff|0
Module|liblog.so||liblog.so|0A492DEF82842051996A468D87F23F010|0xf700c000|0xf7012fff|0
Module|libc.so||libc.so|167F187B09A27F7444EF989603AAFD3D0|0xf7014000|0xf706dfff|0
0|0|breakpad_unittests|MicrodumpWriterTest_Setup_Test::TestBody|/s/clank/src/out_arm/Release/../../testing/gtest/include/gtest/gtest.h|1481|0x1
0|1|breakpad_unittests|testing::Test::Run|/s/clank/src/out_arm/Release/../../testing/gtest/src/gtest.cc|2435|0x17
0|2|breakpad_unittests|testing::TestInfo::Run|/s/clank/src/out_arm/Release/../../testing/gtest/src/gtest.cc|2610|0x5
0|3|breakpad_unittests|testing::TestCase::Run|/s/clank/src/out_arm/Release/../../testing/gtest/src/gtest.cc|2728|0x3
0|4|breakpad_unittests|testing::internal::UnitTestImpl::RunAllTests|/s/clank/src/out_arm/Release/../../testing/gtest/src/gtest.cc|4591|0x3
0|5|breakpad_unittests|testing::UnitTest::Run|/s/clank/src/out_arm/Release/../../testing/gtest/src/gtest.cc|2418|0x5
0|6|breakpad_unittests|main|/s/clank/src/out_arm/Release/../../testing/gtest/include/gtest/gtest.h|2326|0x3
0|7|libc.so||||0x11e9d

View File

@ -0,0 +1,21 @@
OS|Android|OS 64 VERSION INFO
CPU|aarch64||2
Crash||0x0|0
Module|breakpad_unittests||breakpad_unittests|D6D1FEC9A15DE7F38A236898871A2E770|0x555f608000|0x555f6c7fff|0
Module|libnetd_client.so||libnetd_client.so|7735F44BA6D7C27FD5C3636A43369B7C0|0x7f801f6000|0x7f80208fff|0
Module|libstdc++.so||libstdc++.so|380C0B7CD8FA3F094BC3BA58A81CBAD00|0x7f80229000|0x7f8023cfff|0
Module|libm.so||libm.so|F832D47D1E237E46D835991594DA6E890|0x7f8023d000|0x7f80279fff|0
Module|liblog.so||liblog.so|C407B93F87A835BE05451FC7B0B3E65E0|0x7f8027b000|0x7f80293fff|0
Module|libc.so||libc.so|479D5438753E27F019F2C9980DDBF4F30|0x7f80295000|0x7f80332fff|0
Module|libsigchain.so||libsigchain.so|9DA3FF8EF9CA0FDC481292EE530DF6EC0|0x7f80341000|0x7f80353fff|0
Module|linux-gate.so||linux-gate.so|672B2CD6CF8AF6C43BD70F2AB02B3D0C0|0x7f80358000|0x7f80359fff|0
0|0|breakpad_unittests|MicrodumpWriterTest_Setup_Test::TestBody|/s/clank/src/out/Release/../../breakpad/src/client/linux/microdump_writer/microdump_writer_unittest.cc|77|0xc
0|1|breakpad_unittests|testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>|/s/clank/src/out/Release/../../testing/gtest/src/gtest.cc|2418|0x4
0|2|breakpad_unittests|testing::Test::Run|/s/clank/src/out/Release/../../testing/gtest/src/gtest.cc|2435|0x14
0|3|breakpad_unittests|testing::TestInfo::Run|/s/clank/src/out/Release/../../testing/gtest/src/gtest.cc|2610|0x4
0|4|breakpad_unittests|testing::TestCase::Run|/s/clank/src/out/Release/../../testing/gtest/src/gtest.cc|2728|0x0
0|5|breakpad_unittests|testing::internal::UnitTestImpl::RunAllTests|/s/clank/src/out/Release/../../testing/gtest/src/gtest.cc|4591|0x0
0|6|breakpad_unittests|testing::UnitTest::Run|/s/clank/src/out/Release/../../testing/gtest/src/gtest.cc|2418|0x4
0|7|breakpad_unittests|main|/s/clank/src/out/Release/../../testing/gtest/include/gtest/gtest.h|2326|0x0
0|8|libc.so||||0x17388

View File

@ -6,6 +6,7 @@ CPU: x86
Crash reason: EXCEPTION_ACCESS_VIOLATION_WRITE
Crash address: 0x45
Process uptime: 0 seconds
Thread 0 (crashed)
0 test_app.exe!`anonymous namespace'::CrashFunction [test_app.cc : 58 + 0x3]

View File

@ -35,6 +35,7 @@
#include <elf.h>
#include <errno.h>
#include <inttypes.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
@ -47,6 +48,7 @@
#include <vector>
#include "common/linux/memory_mapped_file.h"
#include "common/minidump_type_helper.h"
#include "common/scoped_ptr.h"
#include "google_breakpad/common/minidump_format.h"
#include "third_party/lss/linux_syscall_support.h"
@ -81,9 +83,13 @@
typedef user_regs user_regs_struct;
#endif
using google_breakpad::MDTypeHelper;
using google_breakpad::MemoryMappedFile;
using google_breakpad::MinidumpMemoryRange;
typedef MDTypeHelper<sizeof(ElfW(Addr))>::MDRawDebug MDRawDebug;
typedef MDTypeHelper<sizeof(ElfW(Addr))>::MDRawLinkMap MDRawLinkMap;
static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1);
static bool verbose;
static std::string g_custom_so_basedir;
@ -691,14 +697,14 @@ ParseDSODebugInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range,
"MD_LINUX_DSO_DEBUG:\n"
"Version: %d\n"
"Number of DSOs: %d\n"
"Brk handler: %p\n"
"Dynamic loader at: %p\n"
"_DYNAMIC: %p\n",
"Brk handler: 0x%" PRIx64 "\n"
"Dynamic loader at: 0x%" PRIx64 "\n"
"_DYNAMIC: 0x%" PRIx64 "\n",
debug->version,
debug->dso_count,
debug->brk,
debug->ldbase,
debug->dynamic);
static_cast<uint64_t>(debug->brk),
static_cast<uint64_t>(debug->ldbase),
static_cast<uint64_t>(debug->dynamic));
}
crashinfo->debug = *debug;
if (range.length() > sizeof(MDRawDebug)) {
@ -713,8 +719,9 @@ ParseDSODebugInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range,
if (link_map) {
if (verbose) {
fprintf(stderr,
"#%03d: %p, %p, \"%s\"\n",
i, link_map->addr, link_map->ld,
"#%03d: %" PRIx64 ", %" PRIx64 ", \"%s\"\n",
i, static_cast<uint64_t>(link_map->addr),
static_cast<uint64_t>(link_map->ld),
full_file.GetAsciiMDString(link_map->name).c_str());
}
crashinfo->link_map.push_back(*link_map);

View File

@ -64,6 +64,7 @@
F44DDD8719C85CD50047280E /* dump_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8419C85CD50047280E /* dump_context.cc */; };
F44DDD8819C85CD50047280E /* dump_object.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8519C85CD50047280E /* dump_object.cc */; };
F44DDD8919C85CD50047280E /* microdump_processor.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8619C85CD50047280E /* microdump_processor.cc */; };
F4D43B2F1A38490700C290B2 /* microdump.cc in Sources */ = {isa = PBXBuildFile; fileRef = F4D43B2E1A38490700C290B2 /* microdump.cc */; };
F9C7ECE50E8ABCA600E953AD /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE20E8ABCA600E953AD /* bytereader.cc */; };
F9C7ECE60E8ABCA600E953AD /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */; };
F9C7ECE70E8ABCA600E953AD /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */; };
@ -179,6 +180,8 @@
F44DDD8B19C85CFB0047280E /* dump_object.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dump_object.h; path = ../../../google_breakpad/processor/dump_object.h; sourceTree = "<group>"; };
F44DDD8C19C85CFC0047280E /* microdump_processor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = microdump_processor.h; path = ../../../google_breakpad/processor/microdump_processor.h; sourceTree = "<group>"; };
F44DDD8D19C85CFC0047280E /* process_result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = process_result.h; path = ../../../google_breakpad/processor/process_result.h; sourceTree = "<group>"; };
F4D43B2E1A38490700C290B2 /* microdump.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = microdump.cc; path = ../../../processor/microdump.cc; sourceTree = "<group>"; };
F4D43B301A38492000C290B2 /* microdump.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = microdump.h; path = ../../../google_breakpad/processor/microdump.h; sourceTree = "<group>"; };
F9C7ECE20E8ABCA600E953AD /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
@ -224,6 +227,8 @@
F44DDD8A19C85CFB0047280E /* dump_context.h */,
F44DDD8519C85CD50047280E /* dump_object.cc */,
F44DDD8B19C85CFB0047280E /* dump_object.h */,
F4D43B2E1A38490700C290B2 /* microdump.cc */,
F4D43B301A38492000C290B2 /* microdump.h */,
F44DDD8619C85CD50047280E /* microdump_processor.cc */,
F44DDD8C19C85CFC0047280E /* microdump_processor.h */,
9BDF176C0B1B8CB100F8391B /* on_demand_symbol_supplier.mm */,
@ -482,6 +487,7 @@
D2A5DD4D1188651100081F03 /* cfi_frame_info.cc in Sources */,
D2A5DD631188658B00081F03 /* tokenize.cc in Sources */,
8B31FF2A11F0C62700FCF3E4 /* dwarf_cfi_to_module.cc in Sources */,
F4D43B2F1A38490700C290B2 /* microdump.cc in Sources */,
8B31FF2B11F0C62700FCF3E4 /* dwarf_cu_to_module.cc in Sources */,
F44DDD8819C85CD50047280E /* dump_object.cc in Sources */,
8B31FF2C11F0C62700FCF3E4 /* dwarf_line_to_module.cc in Sources */,