Compare commits

..

223 Commits

Author SHA1 Message Date
Nicholas Nethercote
7fc25b8962 Fix a trivial parsing bug caught by static analysis
R=ted
2016-06-10 09:51:14 -04:00
Ralph Giles
c65ed6573e Update symbol file documentation links.
These locations have changed since the move from Google Code.

R=ted.mielczarek@gmail.com
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1275630
2016-06-10 06:29:06 -04:00
Primiano Tucci
a34c929f6f linux/android: add SIGTRAP to the list of signals handled by the client
__builtin_trap() causes a SIGTRAP on arm64 (at least with GCC 4.9).
SIGTRAP is not handled by breakpad, causing crashes induced by
__builtin_trap() to be missed.
Note that on x86 and arm, instead, __builtin_trap() raises a SIGILL,
which is already handled by breakapd.

BUG=chromium:614865
R=vapier@chromium.org

Review URL: https://codereview.chromium.org/2042853002 .
2016-06-08 17:04:49 +01:00
Primiano Tucci
72e94c4ddb [Android] Roll back to r10e.
BUG=599327
R=primiano@chromium.org
TBR=mark@chromium.org

Review URL: https://codereview.chromium.org/2042873003 .
2016-06-06 20:43:36 +01:00
Primiano Tucci
7933830cb7 [Android] Revert x86 workaround changes for NDK r11c.
BUG=599327
R=primiano@chromium.org
TBR=mark@chromium.org

Review URL: https://codereview.chromium.org/2035343002 .
2016-06-06 14:35:51 +01:00
Ivan Penkov
240ed57ee1 Adding support for overlapping ranges to RangeMap.
When enabled, adding of a new range that overlaps with an existing one can be a successful operation.  The range which ends at the higher address will be shrunk down by moving its start position to a higher address so that it does not overlap anymore.

This change is required to fix http://crbug/611824.  The actual fix will come in a separate CL.

R=mmandlis@chromium.org

Review URL: https://codereview.chromium.org/2029953003 .
2016-06-05 22:41:10 -07:00
Ted Mielczarek
8b7b28663f Make the getting started section in the README better
Some of my colleagues have commented in the past few months that the
Breakpad README is not very clear on how to get and build the code
nowadays. This change moves some of the docs from the "request
change review" section up to the "getting started" section, and adds
a few more things to clarify.

R=vapier@chromium.org
BUG=

Review URL: https://codereview.chromium.org/2035103002 .
2016-06-03 13:32:14 -04:00
Primiano Tucci
d269bd0f29 [Android] Update breakpad to NDK r11c.
BUG=599327
R=mark@chromium.org, primiano@chromium.org

Review URL: https://codereview.chromium.org/2025923003 .
2016-06-02 17:07:07 +01:00
Mike Frysinger
bad9e55ea5 fix signed warning errors in unittests
A bunch of gtest assert statements fail due to signed warnings as
unadorned constants are treated as signed integers.  Mark them all
unsigned to avoid that.

One example (focus on the "[with ...]" blocks that show the types):
In file included from src/breakpad_googletest_includes.h:33:0,
                 from src/common/memory_unittest.cc:30:
src/testing/gtest/include/gtest/gtest.h: In instantiation of 'testing::AssertionResult testing::internal::CmpHelperEQ(const char*, const char*, const T1&, const T2&) [with T1 = int; T2 = long unsigned int]':
src/testing/gtest/include/gtest/gtest.h:1524:23: required from 'static testing::AssertionResult testing::internal::EqHelper<true>::Compare(const char*, const char*, const T1&, const T2&, typename testing::internal::EnableIf<(! testing::internal::is_pointer<T2>::value)>::type*) [with T1 = int; T2 = long unsigned int; typename testing::internal::EnableIf<(! testing::internal::is_pointer<T2>::value)>::type = void]'
src/common/memory_unittest.cc:41:246: required from here
src/testing/gtest/include/gtest/gtest.h:1448:16: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
   if (expected == actual) {
                ^
cc1plus: some warnings being treated as errors
Makefile:5180: recipe for target 'src/common/src_client_linux_linux_client_unittest_shlib-memory_unittest.o' failed
make[2]: *** [src/common/src_client_linux_linux_client_unittest_shlib-memory_unittest.o] Error 1

R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/2013893003 .
2016-05-26 10:09:46 -04:00
Mike Frysinger
6368037ef2 elf_reader: drop unused zlib include
This breaks building for targets that don't include zlib.

BUG=chromium:604440
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/2010803003 .
2016-05-25 16:38:04 -04:00
Mike Frysinger
983d04d36e travis: verify out-of-tree builds & dist targets
Required updating a lot of dist files in the process.

R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1946293002 .
2016-05-25 14:36:37 -04:00
Veljko Mihailovic
71a5ee37a5 [MIPS] Rename variable mips to mips32
Renaming variable mips to mips32 since mips is already defined
by the toolchain.

BUG=Compile error in Chromium
R=mark@chromium.org

Review URL: https://codereview.chromium.org/2006393004 .

Patch from Veljko Mihailovic <veljko.mihailovic@imgtec.com>.
2016-05-25 10:13:18 -04:00
Ivan Penkov
79901bb99d Fixing an unused-variable warning in microdump_writer.cc
BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=699
R=mark@chromium.org, primiano@chromium.org

Review URL: https://codereview.chromium.org/2006333002 .
2016-05-24 12:08:25 -07:00
Lars Volker
f25a411200 Fix stack collection with size limit
src/client/linux/minidump_writer/minidump_writer.cc:273 obtains the
stack info by calling GetStackInfo(). That method will return the
stack base address, aligned to the bottom of the memory page that
'stack_pointer' is in. After that it will cap the size of the memory
area to be copied into the minidump to 'max_stack_len', starting from
the base address, if the caller requested so. This will be the case
when collecting reduced stacks, as introduced by this change:
https://breakpad.appspot.com/487002/

In such cases the caller will request 2048 bytes of memory. However
GetStackInfo() will have aligned the base address to the page
boundary, by default 4096 bytes. If the stack, which grows towards the
base address from the top ends before the 2048 bytes of the first
block, then we will not collect any useful part of the stack.

As a fix we skip chunks of 'max_stack_len' bytes starting from
the base address until the stack_pointer is actually contained in the
chunk, which we will add to the minidump file.

BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=695
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1959643004 .

Patch from Lars Volker <lv@cloudera.com>.
2016-05-24 11:49:35 -07:00
Tobias Sargeant
faeb1f9b2b Functions only called by DumpFreeSpace need to be conditionally compiled.
BUG=525938
R=mark@chromium.org

Review URL: https://codereview.chromium.org/2008553002 .
2016-05-23 18:58:48 +01:00
Primiano Tucci
adca10c8ff Add statistics about free space to microdump format.
When a crash occurs as a result of an allocation failure, it is useful
to know approximately what regions of the virtual address space remain
available, so that we know whether the crash should be attributed to
memory fragmentation, or some other cause.

BUG=525938
R=primiano@chromium.org

Review URL: https://codereview.chromium.org/1796803003 .
2016-05-23 16:06:26 +01:00
Yunlian Jiang
e35167de75 use another elf.h inside the package for common/dwarf/elf_reader
We tried to use common/android/include/elf.h, however it contains
'#include-next elf.h' so it still breaks MAC build. So we use
third_party/musl/include/elf.h instead.

BUG=none
TEST=make; make test passes. There is no '#include-next elf.h' in
     the new elf.h

R=michaelbai@chromium.org

Review URL: https://codereview.chromium.org/1994633003 .
2016-05-18 15:06:38 -07:00
Yunlian Jiang
9eb2c6fe6c Use elf.h inside the package.
MAC does not have elf.h, so use the elf.h inside the package instead
of the one in the system.
One failure example is
https://codereview.chromium.org/1978803003/

TEST=make; make check
BUG=
R=michaelbai@chromium.org

Review URL: https://codereview.chromium.org/1984713002 .
2016-05-18 12:56:22 -07:00
Ted Mielczarek
67d5567177 Don't let PDBSourceLineWriter::GetSymbolFunctionName return empty function names
It's possible for `IDiaSymbol::get_name` to return S_OK and provide
and empty string. I haven't figured out the exact root cause yet
(the symbols in question are coming from the Rust standard library),
but FUNC lines with missing function names break the processor and
so we should never do it. This change makes it output "<name omitted>"
which matches the behavior of the DWARF dumping code.

R=mark@chromium.org
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1272278

Review URL: https://codereview.chromium.org/1985643004 .
2016-05-16 12:30:59 -04:00
Tao Bai
a875991e73 Revert "Write adjusted range back to module"
This is no right fix, we shouldn't allow module overlap.

This reverts commit 4f417c8c0f.

BUG=606972
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1976683004 .

Patch from Tao Bai <michaelbai@chromium.org>.
2016-05-13 12:45:44 -04:00
Dave MacLachlan
a84d4fc426 Replaced glibc version of elf.h with musl version of elf.h.
Updated dump_syms xcode project and ran tests.

BUG=
R=vapier@chromium.org

Review URL: https://codereview.chromium.org/1973113002 .
2016-05-12 14:22:59 -07:00
Dave MacLachlan
3d225e288c Fixes up dump_syms build on OS X so it works with ELF.
Adds elf.h header from glibc.
Updates dwarf2reader.cc so it isn't comparing a unique_ptr against NULL.
Moves from MacOS10.5 SDK to latest SDK for Xcode project.
Moves from using gcc to clang for dump_syms tests.
Disables warning about 'Missing Field In Structure Initializers' to temporarily work around https://bugs.chromium.org/p/google-breakpad/issues/detail?id=697.

With this patch all tests form dump_syms pass again using Xcode 7.3 on Mac OS X 10.11.

BUG= https://bugs.chromium.org/p/google-breakpad/issues/detail?id=696, https://bugs.chromium.org/p/google-breakpad/issues/detail?id=697
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1970903002 .
2016-05-12 11:38:09 -07:00
Dave MacLachlan
1bbe2f29c9 Update to handle dsym files that end with a header.
dsym files generated by Xcode for swift (Xcode 7.3) end with a header, and the
code did not handle that case.

BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=689
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1971793002 .
2016-05-11 14:10:23 -07:00
Yunlian Jiang
638066b82e breakpad: fix unittest errors
This fixes the unittest error caused by
https://codereview.chromium.org/1884283002/

TEST=unittest passes on falco board in ChromeOS.
BUG=
R=vapier@chromium.org

Review URL: https://codereview.chromium.org/1952083002 .
2016-05-04 16:48:00 -07:00
Yunlian Jiang
764c21f752 Add debug fission support.
This added debug fission support.
It tries to find the dwp file from the debug dir /usr/lib/debug/*/debug
and read symbols from them.

Most of this patch comes from
https://critique.corp.google.com/#review/52048295
and some fixes after that.
The elf_reader.cc comes from TOT google code. I just
removed some google dependency.

Current problems from this patch
1: Some type mismatch: from uint8_t * to char *.
2: Some hack to find the .dwp file. (replace .debug with .dwp)

BUG=chromium:604440
R=dehao@google.com, ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1884283002 .
2016-05-04 11:09:44 -07:00
Mike Frysinger
b5712766f6 macho: fix printf type mismatches
The %ld expects a long signed integer, but we're passing in a size_t.
Use %zu which is an unsigned size_t type.

R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1951603002 .
2016-05-04 13:20:27 -04:00
Tao Bai
4f417c8c0f Write adjusted range back to module
In Android, the mmap could be overlapped by /dev/ashmem, we adjusted
the range in https://breakpad.appspot.com/9744002/, but adjusted
range isn't written back to module, this caused the corresponding
module be dropped in BasicCodeModules copy constructor.

This also fix a lot of 'unable to store module' warnings
when dumping Android's minidump.

BUG=606972
R=mark@chromium.org, wfh@chromium.org

Review URL: https://codereview.chromium.org/1939333002 .

Patch from Tao Bai <michaelbai@chromium.org>.
2016-05-03 18:14:28 -04:00
Primiano Tucci
fcb844ee32 Add parentheses to silence clang warning
crrev.com/1887033002 introuced a clang warning (see below).
This fixes it, so that breakpad can be rolled in chrome, where
warnings are always fatal.

From: https://build.chromium.org/p/tryserver.chromium.android/builders/android_chromium_gn_compile_dbg/builds/59031/steps/compile%20%28with%20patch%29/logs/stdio

FAILED: clang_x64/obj/breakpad/dump_syms/dwarf_cu_to_module.o
../../breakpad/src/common/dwarf_cu_to_module.cc:420:20: error: '&&' within '||' [-Werror,-Wlogical-op-parentheses]
if (declaration_ && qualified_name || (unqualified_name && enclosing_name)) {
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~ ~~
../../breakpad/src/common/dwarf_cu_to_module.cc:420:20: note: place parentheses around the '&&' expression to silence this warning
if (declaration_ && qualified_name || (unqualified_name && enclosing_name)) {
                 ^
   (                             )

R=mark@chromium.org, petrcermak@chromium.org

Review URL: https://codereview.chromium.org/1928363002 .
2016-05-03 16:56:06 +02:00
Primiano Tucci
17ad0c18b1 Revert of Extend mapping merge to include reserved but unused mappings. (https://breakpad.appspot.com/7714003)
Reason for revert:
It is causing breakpad crash reports to be invalid (see the associated
bug).

Merging empty holes in r-x mappings was originally introduced in
https://breakpad.appspot.com/7714003 to deal with the first generation
of relro packing, which could introduce holes within a .so mapping:

  [libchrome.so]
  [guard region]
  [libchrome.so]

However, the logic is broken for the case of two *different* adjacent
.so mappings with a guard region in the middle:

  [libfoo.so]
  [guard region]
  [libchrome.so]

In this case the guard region is mistakenly associated with libfoo.so,
but that is not the right thing to do. In fact, the second generation of
rerlo packing added the guard region to prevent mmaps from overlapping
and to give room for the non-zero vaddr of relro-packed libraries, which
require an anticipated load bias.

As the first generation of relro packing is not used anymore, there is
no reason to keep this buggy code, which causes failures in decoding
crashes where an arbitrary library is mapped immediately before a rerlo
packed library.

Original issue's description:
> Extend mapping merge to include reserved but unused mappings.
>
> When parsing /proc/pid/maps, current code merges adjacent entries that
> refer to the same library and where the start of the second is equal to
> the end of the first, for example:
>
>   40022000-40025000 r-xp 00000000 b3:11 827        /system/lib/liblog.so
>   40025000-40026000 r--p 00002000 b3:11 827        /system/lib/liblog.so
>   40026000-40027000 rw-p 00003000 b3:11 827        /system/lib/liblog.so
>
> When the system linker loads a library it first reserves all the address
> space required, from the smallest start to the largest end address, using
> an anonymous mapping, and then maps loaded segments inside that reservation.
> If the loaded segments do not fully occupy the reservation this leaves
> gaps, and these gaps prevent merges that should occur from occurring:
>
>   40417000-4044a000 r-xp 00000000 b3:11 820        /system/lib/libjpeg.so
> > 4044a000-4044b000 ---p 00000000 00:00 0
>   4044b000-4044c000 r--p 00033000 b3:11 820        /system/lib/libjpeg.so
>   4044c000-4044d000 rw-p 00034000 b3:11 820        /system/lib/libjpeg.so
>
> Where the segments that follow this gap do not contain executable code
> the failure to merge does not affect breakpad operation.  However, where
> they do then the merge needs to occur.  Packing relocations in a large
> library splits the executable segment into two, resulting in:
>
>   73b0c000-73b21000 r-xp 00000000 b3:19 786460
> /data/.../libchrome.2160.0.so
> > 73b21000-73d12000 ---p 00000000 00:00 0
>   73d12000-75a90000 r-xp 00014000 b3:19 786460
> /data/.../libchrome.2160.0.so
>   75a90000-75c0d000 rw-p 01d91000 b3:19 786460
> /data/.../libchrome.2160.0.so
>
> Here the mapping at 73d12000-75a90000 must be merged into 73b0c000-73b21000
> so that breakpad correctly calculates the base address for text.
>
> This change enables the full merge by also merging anonymous maps which
> result from unused reservation, identified as '---p' with offset 0, and
> which follow on from an executable mapping, into that executable mapping.
>
> BUG=chromium:394703

BUG=chromium:499747
R=primiano@chromium.org, rmcilroy@chromium.org

Review URL: https://codereview.chromium.org/1923383002 .
2016-04-28 16:49:44 +01:00
Dave MacLachlan
8762c82297 Remove GTM_ENABLE_LEAKS and GTMGarbageCollection
Removes some archaic Google Toolbox For Mac features.

BUG=
R=ivanpe@chromium.org, mark@chromium.org

Review URL: https://codereview.chromium.org/1912473002 .
2016-04-21 13:20:17 -07:00
Ted Mielczarek
ea2e22b352 Make x86-64 frame pointer unwinding stricter
The x86-64 frame pointer-based unwind method will accept values
that aren't valid for the frame pointer register and the return address.
This fixes it to reject non-8-byte-aligned frame pointers, as
well as non-canonical addresses for the return address it finds.

A colleague of mine asked me why Breakpad gave a bad stack
for a crash in our crash-stats system:
https://crash-stats.mozilla.com/report/index/a472c842-2c7b-4ca7-a267-478cf2160405

Digging in, it turns out that the function in frame 0 is a leaf function,
so MSVC doesn't generate an entry in the unwind table for it, so
dump_syms doesn't produce a STACK CFI entry for it in the symbol file.
The stackwalker tries frame pointer unwinding, and %rbp is set to a
value that sort-of works, so it produces a garbage frame 1 and then
is lost. Either of the two checks in this patch would have stopped
the stackwalker from using the frame pointer.

It's possible we could do something smarter on the dump_syms side,
like enumerating all functions and outputing some default STACK CFI rule
for those that don't have unwind info, but that wouldn't fix crashes
from existing builds without re-dumping symbols for them. In any event,
these checks should always pass for valid frame pointer-using functions.

R=mark@chromium.org
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1263001

Review URL: https://codereview.chromium.org/1902783002 .
2016-04-19 15:20:09 -04:00
Ted Mielczarek
d48fa9d3a4 Pass VERBOSE=1 to make check in travis to get failing test output
R=vapier@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1900133002 .
2016-04-19 15:19:32 -04:00
Mike Frysinger
622bc036d6 README: link to Travis CI build status
BUG=
R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1885413003 .
2016-04-15 13:18:32 -04:00
Ted Mielczarek
b39ab626ab Bump MinidumpMemoryRegion::max_bytes to 2MB
BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=694
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1883253002 .
2016-04-14 16:27:25 -04:00
Sebastien Marchand
d986b9d311 Add a missing const to an accessor.
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1882833004 .
2016-04-14 14:45:04 -04:00
Ted Mielczarek
2e266396ee Fix DWARF handling of inlined functions in namespaces
Currently an inlined function in a namespace in DWARF will
be given a name comprised of just `namespace::`. This is due
to a logic error in ComputeQualifiedName, where it doesn't
handle an empty `unqualified_name` properly.

We apparently have a fair number of these in our Mac builds,
an example of the DWARF that's being mishandled looks like:
0x117eda40:     TAG_namespace [5] *
                 AT_name( "js" )
                 AT_decl_file( "../../dist/include/js/Utility.h" )
                 AT_decl_line( 35 )

0x11808500:         TAG_subprogram [251] *
                     AT_low_pc( 0x0000000002f12110 )
                     AT_high_pc( 0x0000000002f1216b )
                     AT_APPLE_omit_frame_ptr( 0x01 )
                     AT_frame_base( rsp )
                     AT_abstract_origin( {0x0000000011800a4f}"_ZN2js40TraceManuallyBarrieredGenericPointerEdgeEP8JSTracerPPNS_2gc4CellEPKc" )
                      AT_MIPS_linkage_name( "_ZN2js40TraceManuallyBarrieredGenericPointerEdgeEP8JSTracerPPNS_2gc4CellEPKc" )
                      AT_name( "TraceManuallyBarrieredGenericPointerEdge" )
                      AT_decl_file( "/builds/slave/rel-m-rel-m64_bld-000000000000/build/js/src/gc/Marking.cpp" )
                      AT_decl_line( 547 )
                      AT_external( 0x01 )
                      AT_APPLE_optimized( 0x01 )
                      AT_inline( DW_INL_inlined )

This turned a few instances of this in the file I was testing on into
`<name omitted>`, which seems to just be a symptom of the
"DW_AT_abstract_origin comes later in the file" issue. (Which is probably
also worth fixing given that it occurs some 29k times when dumping
symbols from Firefox's XUL binary, but it's a separate issue.)

R=mark@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1887033002 .
2016-04-14 10:32:20 -04:00
Ted Mielczarek
fee47f4638 Add some new stream types to MDStreamType
I ran minidump_dump on a dump from Firefox on my Windows 10 machine
and noticed some streams that Breakpad didn't have names for.
Looking in minidumpapiset.h in the Windows 10 SDK finds these values
in MINIDUMP_STREAM_TYPE. There are also struct definitions for the
stream data for some of them (all but JavaScriptData), but I don't have
a particular need for those currently.

R=mark@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1884943002 .
2016-04-13 12:15:15 -04:00
Ted Mielczarek
0203b0cbdd Add travis CI config
This will let us setup travis-ci on the Breakpad GitHub mirror.

R=vapier@chromium.org, mark@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1873133003 .
2016-04-12 14:55:52 -04:00
Ted Mielczarek
205b5ac6ed Fix a dependency issue in automake
Doing a `make -jN check` from a fresh build breaks (and has probably been
broken for a while). linux_client_unittest_shlib is missing $(TEST_LIBS)
from its _DEPENDENCIES. The automake manual says if _DEPENDENCIES are not
specified they'll be computed from _LDADD, but we are specifying it and just
leaving out $(TEST_LIBS).

R=vapier@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1870733005 .
2016-04-12 14:55:18 -04:00
Mike Frysinger
2f1b7adcd3 tweak IGNORE_RET behavior a bit
GCC will still warn about unused return value with the form:
	if (write(...));

Instead, change the semi-colon to an empty set of braces.

BUG=chromium:428478
TEST=build+test still works
2016-04-11 13:05:44 -04:00
David Yen
b0e5f26233 Added an option (-i) to have dump_syms output header information only.
It is often helpful to check if a particular symbol file dumped by
dump_syms actually matches a version of a binary file we have. The
symbol output contains an ID which can be used to see if it matches
the binary file. Unfortunately, this ID is internally calculated
and not a standard hash of the binary file. Being able to output the
header information only will allow users to determine whether their
symbol file is up to date or not.

R=jochen@chromium.org
BUG=561447

Review URL: https://codereview.chromium.org/1864823002 .

Patch from David Yen <dyen@chromium.org>.
2016-04-08 04:37:45 +02:00
Yunxiao Ma
32901f6d4c Remove unreferenced local variable which breaks build.
Depending on compiler's setting, the unreferenced local variable may
cause build break.

modified:   src/processor/minidump.cc

R=mark@chromium.org

Review URL: https://codereview.chromium.org/1866533002 .

Patch from Yunxiao Ma <yxma@google.com>.
2016-04-05 19:37:13 -04:00
Yunxiao Ma
46359276c8 Rename stdio.h wrapper file to stdio_wrapper.h.
Some projects will get build break because the comipler is confused when
searches for the standard stdio.h. Rename the wrapper file to avoid that.

renamed:    src/common/stdio.h -> src/common/stdio_wrapper.h
modified:   src/processor/minidump.cc
modified:   src/processor/dump_context.cc
modified:   src/processor/logging.cc
modified:   src/processor/minidump.cc
modified:   src/processor/minidump_processor.cc
modified:   src/processor/stackwalk_common.cc
modified:   src/processor/symbolic_constants_win.cc

R=mark@chromium.org, labath@google.com

Review URL: https://codereview.chromium.org/1864603002 .

Patch from Yunxiao Ma <yxma@google.com>.
2016-04-05 15:45:30 -04:00
Ted Mielczarek
6c8f80aa8b Switch the Linux minidump writer to use MDCVInfoELF for CV data.
This preserves full build ids in minidumps, which are useful for
tracking down the right version of system libraries from Linux
distributions.

The default build id produced by GNU binutils' ld is a 160-bit SHA-1
hash of some parts of the binary, which is exactly 20 bytes:
https://sourceware.org/binutils/docs-2.26/ld/Options.html#index-g_t_002d_002dbuild_002did-292

The bulk of the changes here are to change the signatures of the
FileID methods to use a wasteful_vector instead of raw pointers, since
build ids can be of arbitrary length.

The previous change that added support for this in the processor code
preserved the return value of `Minidump::debug_identifier()` as the
current `GUID+age` treatment for backwards-compatibility, and exposed
the full build id from `Minidump::code_identifier()`, which was
previously stubbed out for Linux dumps. This change keeps the debug ID
in the `dump_syms` output the same to match.

R=mark@chromium.org, thestig@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1688743002 .
2016-04-05 09:34:20 -04:00
Patrick Linehan
c1848484e1 sample_app: enable C++11 for Android builds
Also add the -D__STDC_LIMIT_MACROS definition as we rely on UINTPTR_MAX.

Review URL: https://codereview.chromium.org/1801913002/
2016-04-04 21:35:26 -04:00
Veljko Mihailovic
6ce752d741 Support processing microdump for mips architecture
Based on changes for ARM, ARM64 and X86, the support for
MIPS and MIPS64 is added in microdump.

TEST=microdump_stackwalk  ~/microdump-mips32.dmp symbols/
BUG=microdump_stackwalk failing for mips architectures

Review URL: https://codereview.chromium.org/1731923002/
2016-04-01 18:50:46 -04:00
Sebastien Marchand
d9c532217e Add the TID to the CallStack.
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1849933002 .
2016-04-01 10:11:10 -04:00
Li Yan
c77c51fae6 Refactor sym_upload in tools to extract code into common/linux, and minor fixes
to code calling libcurl. This change may be used to build a tool to dump and
upload symbols with multi-thread.

BUG=

R=mmandlis@chromium.org
CC=google-breakpad-dev@googlegroups.com

Review URL: https://codereview.chromium.org/1842113002 .
2016-03-30 13:46:21 -07:00
Ted Mielczarek
d091e5103f Make EXC_BAD_ACCESS / EXC_I386_GPFLT print nicely in the processor
Currently EXC_BAD_ACCESS doesn't support EXC_I386_GPFLT as
exception_flags for pretty-printing in the processor, but this happens
for a lot of things:
http://opensource.apple.com/source/xnu/xnu-2050.24.15/osfmk/i386/trap.c
(search for EXC_I386_GPFLT).

And we get a lot of these in the wild:
https://crash-stats.mozilla.com/search/?reason=%3DEXC_BAD_ACCESS+%2F+0x0000000d&cpu_name=amd64&_facets=signature&_facets=address&_columns=date&_columns=signature&_columns=product&_columns=version&_columns=build_id&_columns=platform&_columns=address#crash-reports

This patch makes them show up with a nice name instead of the current
"EXC_BAD_ACCESS / 0x0000000d".

Additionally, this patch fixes some other cases where x86-64 wasn't being handled in the same way as x86, and fixes some x86-specific exception flags to be stringified with I386 in the output.

R=mark@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1833123002 .
2016-03-29 15:32:47 -04:00
David Yen
512cac3a1b Have dump_syms output the full symbol table.
Some of the symbols in the stack trace are not found in the .dynsym
section but were located in the full symbol table .symtab section
instead. This was causing some of our stack traces to be incomplete or
point to incorrect function names.

Since we only output function names, there are actually not that many
more symbols located in .symtab that aren't in .dynsym. It is better to
simply output all symbols found so our stack traces are complete.

R=mark@chromium.org, thestig@chromium.org
BUG=561447

Review URL: https://codereview.chromium.org/1824063002 .

Patch from David Yen <dyen@chromium.org>.
2016-03-23 13:17:41 -04:00
Ted Mielczarek
85b27e4a69 Fix the Linux Starter Guide docs
The auto-conversion from googlecode wiki format apparently wasn't perfect.
This also fixes up some of the links to point to the new Breakpad repo.

R=vapier@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1823583002 .
2016-03-22 14:03:09 -04:00
Ivan Penkov
ebba1800e4 Explicitly call non-sized delete on dynamically sized memory for correct behavior under sized-delete.
The code as it stands allocates a chunk of memory of arbitrary size and places an object into it. It stores a pointer to that object and memory into a list telling the compiler that it is a pointer to a char.  When the compiler deletes the objects in the list it thinks that the list contains pointers to chars - not pointers to arbitrarily sized regions of memory.

This is fixing an issue that will reproduces when the following optimization (C++ sized dealocation) is enabled: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3536.html

The fix is to explicitly call the non-sized delete operator, and the library code that supports malloc/free/new/delete will figure out the size of the block of memory from the pointer being passed in.

Patch provided by Darryl Gove.

R=mark@chromium.org

Review URL: https://codereview.chromium.org/1788473002 .
2016-03-11 16:37:46 -08:00
Jon Turney
139693446b Fix format warning in omap.cc
omap.cc(212): warning C4473: 'fprintf' : not enough arguments passed for format string

BUG=None
Review URL: https://codereview.chromium.org/1776613004
2016-03-10 08:51:20 -05:00
Patrick Linehan
11e17136db Include necessary source files in Android build config.
BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=639
Review URL: https://codereview.chromium.org/1722333002
2016-03-09 18:16:29 -05:00
Primiano Tucci
8915f7be39 Don't merge the mappings if their exec bit are different.
BUG=585534
R=primiano@chromium.org

Review URL: https://codereview.chromium.org/1750033002 .
2016-03-08 08:46:00 +00:00
Dominik Laskowski
4d69050717 Add an optional root prefix to Linux dumpers
The Linux dumpers use absolute paths for shared libraries referenced by
dumps, so they fail to locate them if the crash originated in a chroot.
This CL enables callers to specify a root prefix, which is prepended to
mapping paths before opening them.

BUG=chromium:591792
TEST=make check
Review URL: https://codereview.chromium.org/1761023002/
2016-03-07 21:35:43 -05:00
Maria Mandlis
f3d28e9c4a Handle multiple microdumps in system log.
Properly handle microdump processing, when the system_log file contains an incomplete microdump section at the top. The processor will process the first complete microdump section.

R=primiano@chromium.org

Review URL: https://codereview.chromium.org/1742843002 .
2016-02-26 18:50:50 -08:00
Maria Mandlis
f97e47e55e Support processing microdumps for x86 architecture.
BUG=587536
R=primiano@chromium.org

Review URL: https://codereview.chromium.org/1704243002 .
2016-02-18 06:13:56 -08:00
Birunthan Mohanathas
25f913e981 Try loading msdiaNNN.dll if CoCreateInstance(CLSID_DiaSource) fails
Because tools/windows/symupload/symupload.cc uses `nullptr` (which
requires VS2010), the CLSID comparison is only performed for msdia100.dll
and later. When compiling with an older (or future) CLSID_DiaSource, we
retain the existing behaviour (i.e. fail if CoCreateInstance fails).

R=ivanpe@chromium.org
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1236343
2016-02-17 11:36:19 -05:00
Ted Mielczarek
7b25f70813 Fix buffer overrun in MinidumpModule::debug_identifier with MDCVInfoELF 2016-02-17 06:20:58 -05:00
Mike Frysinger
358c3b449c linux_dumper_unittest_helper: move to a check-only binary
There's no need for this binary outside of local tests, so stop
building/installing it by default.

BUG=chromium:579384
TEST=`make check` passe
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1632933002 .
2016-02-17 00:48:38 -05:00
Ivan Penkov
dee15c2547 Fixing a flaky Linux exploitability unittest.
BUG=https://code.google.com/p/chromium/issues/detail?id=584174
R=mmandlis@chromium.org

Review URL: https://codereview.chromium.org/1697963002 .
2016-02-16 11:46:04 -08:00
Ted Mielczarek
e132514d80 Ensure Linux minidump writer flushes minidump header early.
If the Linux minidump writer crashes while writing a dump, the dump
might contain some useful information, but the header will be empty
because TypedMDRVA's destructor flushes the data, and the header var
doesn't go out of scope until the end of the `Dump` method. This
fixes that problem by putting the header in a shorter block scope.

We've seen this problem in some Android dumps in the wild, like:
https://crash-stats.mozilla.com/report/index/cef5b777-02d1-43c2-bf40-133ab2160209

R=thestig@chromium.org
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1247978

Review URL: https://codereview.chromium.org/1696573003 .
2016-02-12 15:50:16 -05:00
Veljko Mihailovic
d7c0bd0624 Fix for linux make check build failure
Linux make check is failing for mips, mips64, arm, arm64
with error:
"fatal error: mach/arm/vm_types.h: No such file or directory" in case of arm,
"../src/third_party/mac_headers/mach/machine/vm_types.h:37:2: error: #error architecture not supported" in case of mips/mips64

This was partially fixed in https://codereview.chromium.org/1645673002/.

Here excluding src/common/mac/macho_reader_unittest for hosts other than x86/x86-64.

BUG=make check failure for linux mips
TEST=make check pass

Review URL: https://codereview.chromium.org/1692933002 .
2016-02-12 15:17:11 -05:00
Maria Mandlis
df280bb631 Parse additional line introduced in the microdump format and containing the GPU infromation in the following format:
G GL_VERSION|GL_VENDOR|GL_RENDERER.

The GPU version, vendor and renderer are extracted during microdump parsing and populated in the appropriate fields in the SystemInfo struct.

This is to match the changes introduced in crrev.com/1343713002 and crrev.com/1334473003

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

Review URL: https://codereview.chromium.org/1678463002 .
2016-02-11 10:04:04 -08:00
Lei Zhang
a8f79b0fde Revert "Added a switch to dump minidump modules in minidump_stackwalk."
This reverts commit cb936a0243.

A=dyen@chromium.org
Original Review: https://codereview.chromium.org/1672773002/

R=dyen@chromium.org

Review URL: https://codereview.chromium.org/1688493003 .
2016-02-10 13:11:20 -08:00
Ted Mielczarek
4912669df1 Change MDCVInfoELF into something usable.
This patch changes MDCVInfoELF (which is currently unused, apparently
a vestigal bit of code landed as part of Solaris support) into a supported
CodeView format that simply contains a build id as raw bytes.

Modern ELF toolchains support build ids nicely:
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Developer_Guide/compiling-build-id.html

It would be useful to have the original build ids of loaded modules in
Linux minidumps, since tools like Fedora's darkserver allow querying by build
id and the current Breakpad code truncates the build id to the size of a GUID,
which loses information:
https://darkserver.fedoraproject.org/

A follow-up patch will change the Linux minidump generation code to produce
MDCVInfoELF in minidumps instead of MDCVInfoPDB70. This patch should be landed
first to ensure that crash processors are able to handle this format before
dumps are generated containing it.

The full build id is exposed as the return value of Minidump::code_identifier(),
which currently just returns "id" for modules in Linux dumps. For
backwards-compatibility, Minidump::debug_identifier() continues to treat
the build id as a GUID, so debug identifiers for existing modules will not
change.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1675413002 .
2016-02-10 09:00:02 -05:00
Sylvain Defresne
afa2539de4 Fix usage of deprecated method sendSynchronousRequest:returningResponse:error:.
The method -[NSURLConnection sendSynchronousRequest:returningResponse:error:]
has been deprecated in 10.11 OS X SDK and 9.0 iOS SDK without replacement. So
emulate a synchronous request by using an asynchronous request and waiting on
a semaphore for the request completion.

BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=675
BUG=569158
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1675243002 .
2016-02-08 17:39:44 +01:00
Sylvain Defresne
c4c887c34a Fix usage of deprecated method stringByAddingPercentEscapesUsingEncoding:.
The method -[NSString stringByAddingPercentEscapesUsingEncoding:] has been
deprecated with 10.11 OS X SDK and 9.0 iOS SDK. The recommended method is
-[NSString stringByAddingPercentEncodingWithAllowedCharacters:] available
since 10.9 OS X SDK and 7.0 iOS SDK.

Use the new method when available using URLQueryAllowedCharacterSet to get
the same encoded string.

BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=675
BUG=569158
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1680663002 .
2016-02-08 17:39:26 +01:00
Sylvain Defresne
f4012f5cd9 Fix usage of deprecated function CFPropertyListCreateFromXMLData.
The function CFPropertyListCreateFromXMLData is deprecated in favor of
the function CFPropertyListCreateWithData that is available since the
10.6 OS X SDK and 4.0 iOS SDK.

BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=675
BUG=569158
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1678063002 .
2016-02-08 17:38:33 +01:00
Mike Frysinger
76c51742c9 [mips64] Support for mips n64
Adding remaining mips n64 support including stackwalker.

BUG=None
TEST=manually tested on Linux/Android
R=vapier@chromium.org

Review URL: https://codereview.chromium.org/1418453011 .
2016-02-06 18:58:39 -05:00
Ivan Penkov
c199f5b122 Remove use of deprecated CFURLCreateDataAndPropertiesFromResource function.
Original change (https://codereview.chromium.org/1527363003/) was failing
in CFReadStreamGetBuffer() call, so changed to CFReadStreamRead() to be
more conservative.

Patch provided by Scott Hancher.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1637433003 .
2016-01-31 18:17:42 -08:00
Lei Zhang
815d51c343 Added a switch to dump minidump modules in minidump_stackwalk.
In order to figure out what symbols we need associated to a minidump,
it is useful to be able to dump all the modules the minidump contains.

A=dyen@chromium.org
Original Review: https://codereview.chromium.org/1651593002/
BUG=563716
R=dyen@chromium.org

Review URL: https://codereview.chromium.org/1650713002 .
2016-01-29 13:59:17 -08:00
Pavel Labath
442b45266d Improvements to GYP build
This updates the GYP build for the processor component (on windows).
- adds/removes references to files which were added or removed from the
  repository
- includes build/common.gypi in the gyp files: needed to correctly
  detect the OS (I think, the generated MSVC solutions were broken
  without it)
- conditionally compiles code platform-specific code for the given
  platform

After this minidump processor nearly compiles with VS2013: the generated
project is correct, but some files still have compilation errors.

Disclaimer: I have not tested the GYP changes on non-windows platform,
as there does not seem to be anyone using it there.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1643633004 .
2016-01-29 11:43:21 +00:00
Mike Frysinger
3f736ce086 only build dump_syms_mac for x86 hosts
The dump_syms_mac tool only works for the system it is being built for
(it doesn't support running on ELFs for a diff target), and it builds
only for x86 currently.

If you look at the mac header:
	src/third_party/mac_headers/mach/machine/vm_types.h
it will #error for non x86/arm systems, and the arm header is not in
our source tree.

Tweak the build so it's only compiled when targetting x86 systems.

BUG=chromium:579384
TEST=`make check` pass
R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1645673002 .
2016-01-27 16:45:21 -05:00
Mike Frysinger
bc44efdc27 convert to uint8_t* for binary data to fix -Wnarrowing build errors
Newer gcc versions default to -Werror=narrowing when using newer C++
standards (which we do).  This causes issues when we try to stuff a
value like 0xea into a char -- the value is out of range for signed
char bytes.  That's when gcc throws an error:
.../bytereader_unittest.cc: In member function 'virtual void Reader_DW_EH_PE_absptr4_Test::TestBody()':
.../bytereader_unittest.cc:400:55: error: narrowing conversion of '234' from 'int' to 'char' inside { } [-Wnarrowing]

BUG=chromium:579384
TEST=`make check` passes
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1605153004 .
2016-01-26 15:38:19 -05:00
Mike Frysinger
b16c640e09 autotools: regen w/latest versions
Should have no real impact on the build.  Just pulling in the latest
versions from the latest autoconf/automake versions.

BUG=chromium:579384
TEST=`make && make install` still works
2016-01-25 19:29:06 -05:00
Mike Frysinger
f820ead901 test: allow use of system gmock/gtest libs
Some systems provide prebuilt copies of gmock/gtest (such as Chromium
OS).  Add a configure flag so they can take advantage of that.  This
allows for a smaller checkout as they don't need to include the full
testing/ tree.

BUG=chromium:579384
TEST=`make check` passes w/--enable-system-test-libs
TEST=`make check` passes w/--disable-system-test-libs
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1638653002 .
2016-01-25 19:27:56 -05:00
Mike Frysinger
4b5dcd0e69 build: clean up .dwo files
When building with -gsplit-dwarf, the generated dwo files are left behind
even when you `make clean`.  Fix that up.

BUG=chromium:579384
TEST=`./configure CXXFLAGS='-O -gsplit-dwarf' && make && make clean` removes dwo files now
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1633893002 .
2016-01-25 18:40:56 -05:00
Mike Frysinger
83523e066b test: stop building tons of copies of gtest/gmock objects
The current makefile ends up building ~17 copies of the gtest/gmock
objects -- every test that refers to the cc files directly will have
its own copy.  This is because the build doesn't know if CFLAGS and
such have changed between each target (and in some cases, they are).

Create a new libtesting.a target to hold a single copy of these files
and update all of the unittests to link that in.  This speeds up the
build a bit especially when you aren't using ccache.

This does mean we can no longer build gtest/gmock with unique flags,
but we haven't wanted that so far, so clearly no one wants that.

BUG=chromium:579384
TEST=`make check` passes
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1633903002 .
2016-01-25 17:41:53 -05:00
Mike Frysinger
e4cf26b851 linux_client_unittest_shlib: fix cleaning
The EXTRA_PROGRAMS knob does not automatically trigger clean up of
targets listed in it.  Use CLEANFILES so we make sure `make clean`
will delete the linux_client_unittest_shlib lib.

BUG=chromium:579384
TEST=`make check` passes
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1618593002 .
2016-01-25 16:53:16 -05:00
Mike Frysinger
92280b3c67 tests: unify duplicate build settings
Rather than copy & paste the same set of -I flags many times over,
create a single varible to hold it.

BUG=chromium:579384
TEST=`make check` passes
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1613763002 .
2016-01-25 15:12:03 -05:00
Mike Frysinger
aa5ceea25b DEPS: roll test libs up to the latest release
BUG=chromium:579384
TEST=`make check` passes
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1607413003 .
2016-01-25 15:10:38 -05:00
Olivier Robin
658eb44f3f Revert "Fix deprecatation warning when building for recent SDKs on iOS/OS X."
This reverts CL https://codereview.chromium.org/1563223004/
This reverts commit 7cc0d8562b.

CL 1563223004 introduces two bugs on iOS.
- Encoding the minidump name with extra percent causing crash server to fail
  processing the file.
- Using a released pointer causing random crashes on upload. The
  data, resp, err pointers returned in the NSURLSession completion
  handler is released at the end of the block. When used later (to get
  the crash ID), it causes a crash.

BUG=569158
R=blundell@chromium.org, mark@chromium.org

Review URL: https://codereview.chromium.org/1619603002 .

Patch from Olivier Robin <olivierrobin@chromium.org>.
2016-01-21 11:34:12 -05:00
Mike Frysinger
8baa236daa exploitability_unittest: fix warnings
The std::getline function always returns its first arg (which is an
iostream object) and cannot return anything else.  Thus, testing its
value is pointless, and even leads to build errors w/at least gcc-5
due to gtest ASSERT_TRUE funcs only taking bool types:

.../exploitability_unittest.cc: In member function 'virtual void {anonymous}::ExploitabilityLinuxUtilsTest_DisassembleBytesTest_Test::TestBody()':
.../exploitability_unittest.cc:200:136: error: no matching function for call to 'testing::AssertionResult::AssertionResult(std::basic_istream<char>&)'
In file included from .../breakpad_googletest_includes.h:33:0,
                 from .../exploitability_unittest.cc:35:
.../gtest.h:262:12: note: candidate: testing::AssertionResult::AssertionResult(bool)

Since we know this never fails, simply drop the ASSERT_TRUE usage.
The next line already checks the content of the buffer we read.

Further on in the file, we hit some signed warnings:
In file included from .../breakpad_googletest_includes.h:33:0,
                 from .../exploitability_unittest.cc:35:
.../gtest.h: In instantiation of 'testing::AssertionResult testing::internal::CmpHelperEQ(const char*, const char*, const T1&, const T2&) [with T1 = long unsigned int; T2 = int]':
.../gtest.h:1484:23:   required from 'static testing::AssertionResult testing::internal::EqHelper<lhs_is_null_literal>::Compare(const char*, const char*, const T1&, const T2&) [with T1 = long unsigned int; T2 = int; bool lhs_is_null_literal = false]'
.../exploitability_unittest.cc:241:289:   required from here
.../gtest.h:1448:16: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
   if (expected == actual) {

This is because we compare the register value (a uint64_t) directly to
an integer constant, and those are signed by default.  Stick a U suffix
on them to fix things up.

BUG=chromium:579384
TEST=`make check` passes
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1611763002 .
2016-01-21 00:50:28 -05:00
Pavel Labath
48673cdb8c Fix usage of snprintf for MSVC
Older versions of MSVC don't have a snprintf functions. Some files
were already working around that, but not all of them. Instead of
copying the logic into every file, I centralize it into a new
stdio.h wrapper file and make other files include that.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1602563003 .

Patch from Pavel Labath <labath@google.com>.
2016-01-19 21:28:44 -05:00
Mike Frysinger
126a938fef breakpad: fix unittest failure when building with clang.
In C/C++, the result of signed integer overflow is undefined.

The expression "base + size - 1" is parsed as "(base + size) - 1", and
"base + size" can overflow even if "base + (size - 1)" <= INT_MAX.

See http://g/c-compiler-chrome/461JohPKakE/JI3rEBg6FwAJ for more.

BUG=None
TEST='CC=clang CXX=clang++ ./configure && make check'
R=vapier@chromium.org

Review URL: https://codereview.chromium.org/1591793002 .
2016-01-15 13:29:32 -05:00
Mike Frysinger
081cbd64d7 README: add more links to breakpad sites
R=andybons@chromium.org

Review URL: https://codereview.chromium.org/1583163003 .
2016-01-14 13:32:20 -05:00
Mike Frysinger
ac69c577d8 Move core2md objects to libbreakpad_client.a
This CL exports LinuxCoreDumper and ElfCoreDump in the client library. The ARC collector, which is an alternative to core2md optimized for large core dumps, needs these symbols for core dump parsing and conversion to minidump.

BUG=http://b/25773929
TEST=nm src/client/linux/libbreakpad_client.a | grep LinuxCoreDumper

Review URL: https://codereview.chromium.org/1576053002 .
2016-01-13 15:30:21 -05:00
Pavel Labath
4f512397f5 libdisasm: Remove inclusion of windows.h
windows.h defines exception_code as a macro, which conflicts with our
use of the identifier in exception records. It appears that this
particular include of windows.h is not needed, so instead of undefining
the macro, I simply delete the include. Build tested with MSVC 2013.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1579623004 .

Patch from Pavel Labath <labath@google.com>.
2016-01-12 10:43:06 -05:00
Pavel Labath
a1784ae81f Define intptr and uintptr in a more generic way
MSVC does not have the __PTRDIFF_TYPE__ macro defined, so I use the
standard [u]intptr_t types instead. Compilation tested on windows, linux
and mac.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1571293003 .

Patch from Pavel Labath <labath@google.com>.
2016-01-11 12:38:28 -05:00
Pavel Labath
2dda5fefdc libdisasm: Don't depend on sizeof(void)
Due to operator precedence, the address was first cast to void*
and then incremented, which resulted in an error on windows, as
sizeof(void) is undefined and MSVC takes this seriously. Changing
the precedence to perform the addition first.

R=mark@chromium.org

Review URL: https://codereview.chromium.org/1570843002 .

Patch from Pavel Labath <labath@google.com>.
2016-01-08 12:52:04 -05:00
Pavel Labath
68039850bc disassembler_x86: Remove unused include
This file is not present on windows, and it's causing build errors
there. As far as I can tell, nothing in this file actually uses
that include, so I just remove it.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1475353002 .

Patch from Pavel Labath <labath@google.com>.
2016-01-08 10:07:04 -05:00
Sylvain Defresne
7b0d7a976e Fix compilation of breakpad on Linux.
Fix some copy/paste errors from commit 41440eaa.

BUG=None
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1564293002 .
2016-01-08 09:34:27 +01:00
Lei Zhang
728bcdff61 Check for C++11 support in the configure script.
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1570013002 .
2016-01-08 00:27:48 -08:00
Sylvain Defresne
98bea93a3e Fix deprecatation warning when building for recent SDKs on iOS/OS X.
Fixes the following compilation warning when using recent version of
the iOS or OS X SDK by using the recommended new API:

../../breakpad/src/common/mac/HTTPMultipartUpload.m:56:10: error: 'stringByAddingPercentEscapesUsingEncoding:' is deprecated: first deprecated in iOS 9.0 - Use -stringByAddingPercentEncodingWithAllowedCharacters: instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent since each URL component or subcomponent has different rules for what characters are valid. [-Werror,-Wdeprecated-declarations]
    [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
         ^
CFURLCreateStringByAddingPercentEscapes

../../breakpad/src/common/mac/HTTPMultipartUpload.m:207:29: error: 'sendSynchronousRequest:returningResponse:error:' is deprecated: first deprecated in iOS 9.0 - Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h [-Werror,-Wdeprecated-declarations]
    data = [NSURLConnection sendSynchronousRequest:req
                            ^

../../breakpad/src/client/mac/handler/minidump_generator.cc:158:6: error: 'CFPropertyListCreateFromXMLData' is deprecated: first deprecated in iOS 8.0 - Use CFPropertyListCreateWithData instead. [-Werror,-Wdeprecated-declarations]
    (CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable,
     ^

BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=675
BUG=569158
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1563223004 .
2016-01-07 19:48:21 +01:00
Lei Zhang
bcf4cc2f9a Use range-based for loops in linux/minidump_writer/minidump_writer.cc.
Also fix lint errors.

R=mark@chromium.org

Review URL: https://codereview.chromium.org/1562273002 .
2016-01-07 00:53:06 -08:00
Mike Frysinger
b1d3cdba8b switch to git for external projects
Now that all the projects we care about use git and have repos available,
switch to them and away from the old googlecode svn repos.

TEST=`gclient sync` migrated svn->git fine
TEST=`make check` still passes
TEST=manual `diff -ur` on the new/old repos shows same content
BUG=
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1560913002 .
2016-01-06 19:44:41 -05:00
Lei Zhang
8c49d62005 Avoid comparing size_t to be < 0 on AArch64.
cpu_features_entries is empty on AArch64 and causes tautological-compare
warning when compiling with Clang.

A=dskiba@google.com
Original Review: https://codereview.chromium.org/1562223002/

BUG=chromium:539781

Review URL: https://codereview.chromium.org/1566893002 .
2016-01-06 16:16:01 -08:00
Lei Zhang
ee4d8ffed4 Make minidump-2-core.cc build with -Wformat.
A=thakis@chromium.org
BUG=chromium:574817
Original Review: https://codereview.chromium.org/1562983002/

R=thakis@chromium.org

Review URL: https://codereview.chromium.org/1563043002 .
2016-01-06 14:17:16 -08:00
Lei Zhang
f9b60452e1 Fix -Wunused-function warnings in ASAN builds.
A=thakis@chromium.org
BUG=chromium:573250
Original Review: https://codereview.chromium.org/1551963002/

Review URL: https://codereview.chromium.org/1551983002 .
2015-12-30 15:44:02 -08:00
Lei Zhang
257123ca70 Let breakpad build with -Wall on OS X and Linux.
A=thakis@chromium.org
Original Review: https://codereview.chromium.org/1550933002/

R=thakis@chromium.org

Review URL: https://codereview.chromium.org/1554613002 .
2015-12-29 13:42:49 -08:00
Ivan Penkov
1be3027941 Remove use of deprecated CFURLCreateDataAndPropertiesFromResource function.
Patch by Scott Hancher

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1527363003 .
2015-12-18 10:26:21 -08:00
Ted Mielczarek
524508ff2f Fix ExploitabilityLinuxUtilsTest::DisassembleBytesTest to not fail when temp file ends with 0
R=ivanpe@chromium.org
BUG=https://bugs.chromium.org/p/google-breakpad/issues/detail?id=668

Review URL: https://codereview.chromium.org/1482363003 .
2015-11-30 14:05:08 -05:00
Ted Mielczarek
a22992081f Rename src/tools/mac/dump_syms binary to dump_syms_mac in autotools build to fix make install
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1474673004 .
2015-11-25 14:27:53 -05:00
Mike Frysinger
dc16e41747 dump_syms: add a -v flag
dump_syms generates a lot of warnings.
This CL puts logging behind a command line flag

URL=https://android-review.googlesource.com/181558
BUG=b:25460551
BUG=google-breakpad:441
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1437763002 .
2015-11-11 13:52:03 -05:00
Mike Frysinger
f217ae431f build: detect the right ar tool
Use automake's AM_PROG_AR helper instead of the default of hardcoding
`ar` all the time.  When cross-compiling, this can often be the wrong
one to use.

BUG=google-breakpad:519
R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1435813002 .
2015-11-11 13:43:14 -05:00
Mike Frysinger
39e372dab6 gitignore: add mac/dump_syms
BUG=google-breakpad:670
2015-11-11 01:47:33 -05:00
Mike Frysinger
fc62e72539 autotools: refresh config.{sub,guess} 2015-11-11 01:38:23 -05:00
Mike Frysinger
2d1b97a1ff Don't include libdisasm.a in libbreakpad.a
libbreakpad.a pointlessly contains libdisasm.a

This looks like a left-over from when libtool was used

Since this has no useful effect (as the linker doesn't recursively search
archive members which aren't objects), anything which requires the objects in
libdisasm.a must already be linking with it, so simply remove it.

BUG=https://code.google.com/p/google-breakpad/issues/detail?id=484

Review URL: https://codereview.chromium.org/1399003002 .
2015-11-11 01:17:45 -05:00
Mike Frysinger
ac2a3e466f Fix file descriptor leaks in linux CrashGenerationServer
R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1137423004 .
2015-11-11 01:12:20 -05:00
Mike Frysinger
ee69060bfd Install headers under client/linux/dump_writer_common
Automake did not install headers under c/l/dwc, which caused
compile errors when building against an installed breakpad, since
other headers (e.g. client/linux/handler/exception_handler.h)
depended on it. This commit adds these headers to the list of
automake installed files.

R=vapier@chromium.org

Review URL: https://codereview.chromium.org/1127393006 .
2015-11-11 01:11:00 -05:00
Boris Vidolov
beee5c2e71 Make dump_syms buildable under newer versions of Xcode.
R=mark@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1438483002 .
2015-11-10 13:23:38 -08:00
Lei Zhang
aa5ff205cb Android: Workaround for ftruncate() issues.
This works around a bug in M that prevents Breakpad from using
ftruncate() in the renderer process.

To do this, skip the calls to ftruncate() when allocating bigger
minidump files and strictly depends on write() to append to the end.

It might be less efficient but this is probably less of an issue on
SD cards. It is much better than not getting crash reports.

BUG=542840

Original CL: https://codereview.appspot.com/273880044/
Original CL Author: acleung@chromium.org

Review URL: https://codereview.chromium.org/1407233016 .
2015-11-05 15:45:01 -08:00
Ivan Penkov
b458f36762 Issue in StackwalkerAMD64::GetCallerByFramePointerRecovery.
There is an issue in StackwalkerAMD64::GetCallerByFramePointerRecovery.
Occasionally it produces invalid frames (instruction pointer == 0) which
prevents the AMD64 stack walker from proceeding to do stack scanning and
instead leads to premature termination of the stack walking process.

For more details: http://crbug/537444

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1408973002 .
2015-10-15 20:47:15 -07:00
Benjamin Lerman
ef7575d35a Only release current_breakpad_ if it is defined.
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1402453006 .
2015-10-14 17:35:47 +02:00
Mike Frysinger
a31f601d90 Revert "[Docs] Add wiki content to Markdown docs"
This reverts commit 7ed2476eea.

This was supposed to be committed to the linux-syscall-support
project.  The two CLs landing at the sametime confused me.

Note: LSS has been updated via commit 08056836f2b4a5747daff75435d10d6.

Review URL: https://codereview.chromium.org/1395743002 .
2015-10-07 17:04:43 -04:00
Ted Mielczarek
4ee6f3cd1c Fix Windows crash_generation_server for debug builds without -D_DEBUG
Debug Gecko builds don't build with -D_DEBUG, so the ifdef in
crash_generation_server doesn't work right. The MSDN documentation for
assert says that it's enabled based on the absence of the NDEBUG define,
so using that seems sensible.

R=thestig@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1398453002 .
2015-10-07 14:19:23 -04:00
David Major
7685dfc567 Support for multiple upload files in CrashReportSender/HTTPUpload
A=David Major <dmajor@mozilla.com>
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=1048091
R=ted@mielczarek.org

Review URL: https://bugzilla.mozilla.org/show_bug.cgi?id=1048091 .
2015-10-06 11:05:12 -04:00
Ted Mielczarek
dbf56c53a0 Fix MSVC build (including on 2015), drop some workarounds for MSVC older than 2013.
The Windows client gyp files were missing proc_maps_linux.cc for the
unittest build. Adding that revealed some build errors due to it
unconditionally including <inttypes.h>. Removing the workarounds in
breakpad_types.h (and a few other places) made that build, which means
that Visual C++ 2013 is now our minimum supported version of MSVC.

Additionally I tried building with VC++ 2015 and fixed a few warnings
(which were failing the build because we have /WX enabled) to ensure
that that builds as well.

BUG=https://code.google.com/p/google-breakpad/issues/detail?id=669
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1353893002 .
2015-10-06 08:03:57 -04:00
Ivan Penkov
f948d8d623 Increasing the Breakpad stack walker max scan limit from 30 to 40.
Chrome started hitting some crashes in v8 jitted code which happens to be
non ABI compliant and debuggers (including WinDBG) are unable to produce
meaningful stack traces.

The Breakpad stack walker has some builtin heuristics to deal with such cases.
More specifically, when unable to find a good parent frame, it scans the raw
stack to find a suitable parent frame.  The max scan size was set at 30
pointers which was (apparently) not enough to recover in this case.

I'm increasing it to 40 pointers.  I confirmed that at 34 pointers it was able
to recover however I'm setting it to 40 in order to it some slack.

I needed to update two unittests which were expecting the previous scan limit.

BUG=
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1379433005 .
2015-10-05 11:35:09 -07:00
Pavel Labath
01c8f7cf46 [mac] Teach dump_syms to handle additional zerofill sections
This patch allows dump_syms to handle S_THREAD_LOCAL_ZEROFILL
and S_GB_ZEROFILL section in the same way as the more common
S_ZEROFILL section.  Previously, dump_syms would fail to dump
a binary containing a __DATA,__thread_bss section, because it
tried to look up its data (and failed).

R=mark@chromium.org

Review URL: https://codereview.chromium.org/1369233003 .

Patch from Pavel Labath <labath@google.com>.
2015-09-30 08:20:42 -04:00
Primiano Tucci
679d70f50b Fix automake files after README.md -> README rename
Minor followup to crrev.com/1357773004 and
crrev.com/1361993002 which moved the README and forgot
to update the automake files.
This is to make "./configure && make" work.

TBR=mark@chromium.org

Review URL: https://codereview.chromium.org/1368363002 .
2015-09-28 14:02:08 +01:00
Primiano Tucci
0d53bdd43d Add GPU fingerprint information to breakpad microdumps.
Although strictly the GPU fingerprint is defined by the build fingerprint,
there is not currently a straightforward mapping from build fingerprint
to useful GPU / GL driver information.

In order to aid debugging of WebView crashes that occur in GL drivers,
and to better understand the range of drivers and versions for feature
blacklisting purposes, it is useful to have GPU fingerprints in breakpad
microdumps.

Landing this patch on behalf of Tobias Sargeant<tobiasjs@chromium.org>

BUG=chromium:536769
R=primiano@chromium.org, thestig@chromium.org

Review URL: https://codereview.chromium.org/1334473003 .
2015-09-28 13:52:54 +01:00
Mike Frysinger
08a727d8f0 [Docs] Add wiki content to Markdown docs
BUG=none
R=vapier@chromium.org, mseaborn@chromium.org

Review URL: https://codereview.chromium.org/1356253003 .
2015-09-24 11:32:37 -04:00
Mark Mentovai
f74c85df88 Update configure to look for README.md instead of README
This is required after daed3a4383. configure won't run as-is, reported
in https://codereview.chromium.org/1357773004/.

R=andybons@chromium.org

Review URL: https://codereview.chromium.org/1361993002 .
2015-09-23 10:46:55 -04:00
Andy Bonventre
0ff15b41ed [Docs] add markdown docs (converted from Wiki)
BUG=none
R=mark
CC=google-breakpad-dev@googlegroups.com

Review URL: https://codereview.chromium.org/1357773004 .

Patch from Andy Bonventre <andybons@chromium.org>.
2015-09-22 17:29:52 -04:00
Primiano Tucci
4d06db5a1f Linux ExceptionHandler: don't allocate the CrashContext on the stack
On Android the size of the alternate stack can be very small (8k).
Even if breakpad uses sigaltstack to increase the size of the alternate
stack during initialization, that call affects only the main thread.
On Android, the libc's pthread initializer reset the sigaltstack to 8k.
When entering a signal handler, the kernel typically pushes the context
on the alternate stack. On arm64, sizeof(CrashContext) is ~5k, which
leaves 3k of usable stack for breakpad.
On top of that, breakpad allocates another struct CrashContext on the
stack. In the case of Android arm64, then, breakpad ends up using
5k + 5k > 8k of stack, which causes a stack overflow.
This got unnoticed in Android L, as the alternate stack didn't have
red-zones between them, so breakpad was often happily overflowing onto
the next thread's stack. This is not the case anymore [1].
This CL moves the CrashContext into a global variable. It should be
safe as the ExceptionHandlers are serialized on a mutex.

[1] 595752f623

BUG=374
R=mark@chromium.org

Review URL: https://codereview.chromium.org/1354923002 .
2015-09-22 09:11:24 +01:00
Ted Mielczarek
3520fc314b Fixup a bad strcmp call landed in previous commit 2015-09-16 19:25:35 -04:00
Ted Mielczarek
8079ae192d Fix Mac Breakpad host tools to build in Linux cross-compile
We're working on building our Firefox Mac builds as a Linux cross-compile
(https://bugzilla.mozilla.org/show_bug.cgi?id=921040) and we need symbol
dumping to work. This change ports the Mac dump_syms tool to build and work
on Linux. I've tested it and it produces identical output to running the
tool on Mac.

The bulk of the work here was converting src/common/mac/dump_syms.mm and
src/tools/mac/dump_syms/dump_syms_tool.mm from ObjC++ to C++ and removing
their use of Foundation classes in favor of standard C/C++.

This won't compile out-of-the-box on Linux, it requires some Mac system
headers that are not included in this patch. I have those tentatively in
a separate patch to land in Gecko
(http://hg.mozilla.org/users/tmielczarek_mozilla.com/mc/rev/5fb8da23c83c),
but I wasn't sure if you'd be interested in having them in the Breakpad tree.
We could almost certainly pare down the set of headers included there, I
didn't spend too much time trying to minimize them (we primarily just need
the Mach-O structs and a few associated bits).

I just realized that this patch is missing updating the XCode project files
(ugh). I'll fix that up in a bit.

R=mark@chromium.org
BUG=https://bugzilla.mozilla.org/show_bug.cgi?id=543111

Review URL: https://codereview.chromium.org/1340543002 .
2015-09-16 06:46:55 -04:00
Ted Mielczarek
d28bebcd16 Update gitignore to ignore more GYP things
Now that we're using gclient everywhere, the hook to run gyp on the Windows
projects gets run on Linux, so we get Makefiles strewn around the tree.

R=vapier@chromium.org

Review URL: https://codereview.chromium.org/1339653002 .
2015-09-11 14:20:15 -04:00
Mike Frysinger
1dcec01445 solaris: fix spurious ;
As reported in the issue tracker, building on Solaris 8 fails:
.../src/common/solaris/guid_creator.cc:69: error: extra `;'

BUG=google-breakpad:251
R=ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1333243002 .
2015-09-11 12:59:53 -04:00
Mike Frysinger
a057bc5d3e README: update dev documents w/new git flow
BUG=chromium:502355
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1335483002 .
2015-09-11 01:38:20 -04:00
Mike Frysinger
e8dbddf291 deps: switch lss to git
BUG=524777
TEST=`gclient sync` switches lss to git
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1331783002 .
2015-09-11 01:37:29 -04:00
Will Harris
2d450f312b Fix regression on x86 for "Fix compile error with Windows clang"
R=thakis@chromium.org

Review URL: https://codereview.chromium.org/1318013002 .
2015-09-03 16:38:57 -07:00
Vadim Shtayura
26ce7a2a89 Change codereview.settings to point to new repo URL.
It changes "Committed: <URL>" in CLs to point to Git repo browser.

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

Review URL: https://codereview.chromium.org/1319083007 .
2015-09-01 17:13:51 -07:00
mmandlis@chromium.org
3f4d090d70 The "CPU architecture" field is being filled from the wrong part of
the microdump. The microdump OS/arch line looks like:
O A arm 04 armv7l 3.4.0-perf-g4d6e88e #1 SMP PREEMPT Mon Mar 30 19:09:30 2015
and currently the field that says "armv7l" or "aarch64" is being used
to fill in the CPU arch field in crash. The problem is that on a
64-bit device this field *always* says "aarch64" even when running in
a 32-bit process, and so currently the crash reports for aarch64 are
a mix of 32-bit and 64-bit crashes. We should be using the first field
instead, which just says "arm" or "arm64" and reflects the actual
version of webview (32-bit or 64-bit) which is running.

BUG=
R=primiano@chromium.org

Review URL: https://codereview.chromium.org/1306983003 .

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1498 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-26 16:18:52 +00:00
Liu.andrew.x@gmail.com
f073540795 Add check for Linux minidump ending on bad write for exploitability rating.
If a crash occurred as a result to a write to unwritable memory, it is reason
to suggest exploitability. The processor checks for a bad write by
disassembling the command that caused the crash by piping the raw bytes near
the instruction pointer through objdump. This allows the processor to see if
the instruction that caused the crash is a write to memory and where the
target of the address is located.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1273823004

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1497 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-21 16:22:19 +00:00
ted.mielczarek@gmail.com
ee2d76fe90 Don't use strtok_s for mingw builds
R=ivanpe at https://codereview.chromium.org/1292503005/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1496 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-20 15:09:16 +00:00
rmcilroy@chromium.org
8e8be001cb Add user_regs_struct and user_fpsimd_struct for aarch64 on Android.
Android's sys/user.h is missing user_regs_struct and user_fpsimd_struct.
Add them to the Android specific user.h used by breakpad to workaround
Android / glibc compatibility issues.

A bug has been filed on the Android NDK team to add the missing structures to
the NDK, at which point this hack can be removed.

Also remove the mxcsr_mask hack on x64, which is no longer required since
we have moved to the r10d NDK which fixes this issue.

R=primiano@chromium.org

Review URL: https://codereview.chromium.org/1291983003 .

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1495 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-20 14:30:38 +00:00
wfh@chromium.org
9178d8fa03 Fix compile error with Windows clang.
This change fixes the following errors shown during compile with
Windows clang:

error: cannot pass non-trivial object of type 'ATL::CComBSTR' to variadic function; expected type from format string was 'wchar_t *' [-Wnon-pod-varargs]

Original CL: https://codereview.chromium.org/1252913009/

BUG=https://code.google.com/p/google-breakpad/issues/detail?id=662

Review URL: https://codereview.chromium.org/1307463003

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1494 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-19 22:28:17 +00:00
primiano@chromium.org
3bc3dad8f8 Fix inttypes format macros in src/processor/proc_maps_linux.cc
crrev.com/1298443002 has introduced a build failure by re-defining
__STDC_FORMAT_MACROS. Fixing it.

BUG=
R=mark@chromium.org, ted.mielczarek@gmail.com

Review URL: https://codereview.chromium.org/1303493003 .

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1493 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-19 07:24:21 +00:00
primiano@chromium.org
3365fe7986 Remove obsolete seccomp_unwinder for legacy (pre-BPF) sandbox
The PopSeccompStackFrame was introduced to deal with stack frames
originated in the legacy seccomp sandbox. The only user of that
sandbox was Google Chrome, but the legacy sandbox has been
deprecated in 2013 (crrev.com/1290643003) in favor of the new
bpf sandbox.
Removing this dead code as it has some small bound checking bug
which causes occasional crashes in WebView (which are totally
unrelated to the sandbox).

Note: this will require a corresponding change in the chromium
GYP/GN build files to roll.

BUG=665,chromium:477444
R=jln@chromium.org, mark@chromium.org, torne@chromium.org

Review URL: https://codereview.chromium.org/1299593003 .

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1492 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-18 08:38:14 +00:00
ted.mielczarek@gmail.com
dc5c38675c Fix proc_maps_linux compile for non-Linux
R=ivanpe at https://codereview.chromium.org/1298443002/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1491 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-17 11:55:15 +00:00
primiano@chromium.org
6ea9219d80 [microdump] Move microdump writes to the crash ring-buffer log
So far the microdump_writer dumped the log in logcat using the default
system log. This is simple to achieve but has some drawbacks:
 1. Creates spam in the system log, pushing back other eventual useful
    messages.
 2. There is a high chance that the microdump gets lost if some log
    spam storm happens immediately after a crash and before the log
    is collected by the feedback client.
 3. Since Android L, the logger is smartly throttling messages (to
    reduce logcat spam). Throttling brekpad logs defeats the all
    point of microdumps.

This change is conceptually very simple. Replace the use of
__android_log_write() with __android_log_buf_write(), which takes
an extra bufID argument. The main drawback is that the
__android_log_buf_write is not exported in the NDK and needs to be
dynamically looked up via dlsym.
This choice has been discussed and advocated by Android owners.
See the internal bug b/21753476.

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

Review URL: https://codereview.chromium.org/1286063003 .

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1490 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-17 10:32:26 +00:00
primiano@chromium.org
a3e9c02647 [microdump] Fix hw architecture indication in build fingerprint line
r1456 introduced the possibility to customize the OS-line of the
microdump, enabling to replace, in the case of android, the generic
uname() info with the Android build fingerprint.
While doing that, it mistakenly removed the HW architecture indication
from the format.
See crbug.com/520075 for more details.

BUG=chromium:520075
R=mmandlis@chromium.org, torne@chromium.org

Review URL: https://codereview.chromium.org/1288313002 .

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1489 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-17 08:02:16 +00:00
Liu.andrew.x@gmail.com
e3687f92c2 Add check for executable stack/heap when rating Linux exploitability.
This CL also consequentially adds a public method to get the number of
mappings in a Linux minidump.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1291603002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1488 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-15 00:37:14 +00:00
Liu.andrew.x@gmail.com
ab5ffb8b6c Add check to see if stack pointer is off the stack according to the memory
mappings when rating Linux exploitability.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1286033002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1487 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-15 00:27:27 +00:00
Liu.andrew.x@gmail.com
8794e39888 Fix format specifier in proc maps to support 32-bit architectures.
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1288323003

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1486 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-13 20:13:55 +00:00
ted.mielczarek@gmail.com
cde8616abf Actually remove removed files
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1485 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-13 19:49:44 +00:00
ted.mielczarek@gmail.com
591ba326b3 Remove some old unused code, add a missing include
R=lei at https://codereview.chromium.org/1211963002



git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1484 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-13 16:38:19 +00:00
Liu.andrew.x@gmail.com
ffa293221f Fix format specifier in proc maps to support 32-bit architectures.
R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1280853003

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1483 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-12 00:53:39 +00:00
Liu.andrew.x@gmail.com
c4e643dfb4 Allow Print() to be called by const instances of MinidumpLinuxMaps and
MinidumpLinuxMapsList.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1287803002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1482 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-12 00:21:44 +00:00
Liu.andrew.x@gmail.com
6a1a906773 Change Print method of MinidumpLinuxMaps and MinidumpLinuxMapsList to print
contents of /proc/<pid>/maps instead of just the files mapped to memory.

Review URL: https://codereview.chromium.org/1273123002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1481 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-11 16:05:48 +00:00
ivanpe@chromium.org
47527e48e5 Workaround for range map overlaps caused by Android package relocation.
If there is a range overlap, the cause may be the client correction applied for Android packed relocations.  If this is the case, back out the client correction and retry.

Patch from Simon Baldwin <simonb@chromium.org>.

https://code.google.com/p/chromium/issues/detail?id=509110

R=simonb@chromium.org

Review URL: https://codereview.chromium.org/1275173005

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1480 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-10 17:03:29 +00:00
cjhopman@chromium.org
64c0d9c66d Fix breakpad for arm on arm64
On arm64 devices, GETFPREGS fails with errno==EIO. Ignore those failures
on Android arm builds.

BUG=508324
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1268023003 .

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1479 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-08-05 22:48:48 +00:00
Liu.andrew.x@gmail.com
0dbae0cf3f Fix potential null pointer dereference.
If a MinidumpLinuxMapsList was created and destroyed without its Read method,
the program would have a segmentation fault because the destructor did not
check for a null maps_ field. Additional changes include additional
supplementary null checks, a potential memory leak fix, and some comment
removal.

Review URL: https://codereview.chromium.org/1271543002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1478 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-31 15:26:39 +00:00
Liu.andrew.x@gmail.com
4634d88f2e Remove unnecessary dependencies.
Review URL: https://codereview.chromium.org/1266493002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1477 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-29 00:09:22 +00:00
Liu.andrew.x@gmail.com
2997f45907 Add support for Linux memory mapping stream and remove ELF header usage
when checking exploitability rating.

Linux minidumps do not support MD_MEMORY_INFO_LIST_STREAM, meaning the
processor cannot retrieve its memory mappings. However, it has its own
stream, MD_LINUX_MAPS, which contains memory mappings specific to Linux
(it contains the contents of /proc/self/maps). This CL allows the minidump
to gather information from the memory mappings for Linux minidumps.

In addition, exploitability rating for Linux dumps now use memory mappings
instead of checking the ELF headers of binaries. The basis for the change
is that checking the ELF headers requires the minidumps to store the memory
from the ELF headers, while the memory mapping data is already present,
meaning the size of a minidump will be unchanged.

As a result, of removing ELF header analysis, two unit tests have been removed.
Arguably, the cases that those unit tests check do not merit a high
exploitability rating and do not warrant a solid conclusion that was given
earlier.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1251593007

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1476 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-28 00:53:44 +00:00
Liu.andrew.x@gmail.com
4959c18e98 Fix incorrect comment.
The exploitability rating for a dump is EXPLOITABILITY_NOT_ANALYZED if the
exploitability engine in not enabled, not EXPLOITABILITY_NONE.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1254333002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1475 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-27 18:04:54 +00:00
vapier@chromium.org
0b7c158932 add aarch64 support to minidump-2-core
The thread info expects the struct names as they expect in asm/ptrace.h,
but the header doesn't include that, it includes sys/user.h.  Rename the
reg structs to match that header.

Rename the elf_siginfo to _elf_siginfo to avoid conflicting with the one
in the sys/procfs.h.  It is only used locally in one place, so we don't
need to update any callers.

Otherwise, drop in aarch64 support into the minidump-2-core file.

BUG=chromium:334368


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1474 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-20 10:21:27 +00:00
vapier@chromium.org
85e4cf8029 tests: InstructionPointerMemoryNullPointer: make it work under llvm
When LLVM sees an attempt to dereference a NULL pointer, it will generate
invalid opcodes (undefined behavior) which leads to SIGILL which breaks
this unittest.  Upstream's recommendation in this case is to add volatile
markings to get the actual dereference to happen.

This is documented in the blog post under "Dereferencing a NULL Pointer":
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1473 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-20 06:19:49 +00:00
Liu.andrew.x@gmail.com
a840e1b710 Add ELF header analysis when checking for instruction pointer in code.
If the minidump module containing the instruction pointer has memory
containing the ELF header and program header table, when checking the
exploitability rating, the processor will use the ELF header data to determine
if the instruction pointer lies in an executable region of the module, rather
than just checking if it lies in a module.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1233973002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1472 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-16 20:42:29 +00:00
wfh@chromium.org
0c426387b8 Fix -Wreorder warnings in the Windows code.
This makes the order of fields in constructor initializer lists match
the order in which the fields are declared in (which is the order
they're initialized in). No intended behavior change.

This change was originally reviewed at
https://codereview.chromium.org/1230923005/

BUG=chromium:505304
TBR=thakis@chromium.org

Review URL: https://codereview.chromium.org/1234653002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1471 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-10 20:24:33 +00:00
changluo@google.com
28c9c9b82c Default nil or empty version string to CFBundleVersion
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1470 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-10 01:29:50 +00:00
Liu.andrew.x@gmail.com
fed2e33bd1 Set exception whitelist check as earlier check instead of last check.
When I first added the exception whitelist, I meant to put the check before
checking the location of the instruction pointer. (I didn't notice that it
was after the other check until now.) The whitelist check is to quickly rule
out minidumps, and if checking the instruction pointer provided any useful
information, it would be pretty indicative that the exception causing the
dump is interesting.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1211253009

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1469 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-07-07 21:30:06 +00:00
Liu.andrew.x@gmail.com
e2eb4505d0 Use general instruction/stack pointer convenience method instead of manually
finding the instruction/stack pointer for exploitability rating.

There was already a method that found the instruction pointer, so the files
for exploitability ratings had repeated code. Also a method for finding the
stack pointer is implemented in this CL.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1210943005

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1468 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-30 23:22:09 +00:00
Liu.andrew.x@gmail.com
12213a5e15 Checking for benign exceptions that trigger a minidump.
If the exception reponsible for the crash is benign, such as a floating point
exception, we can rule out the possibility that the code is exploitable. This
CL checks for such exceptions and marks the dump as not exploitable if such an
exception is found.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1212383004

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1467 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-30 20:34:39 +00:00
Liu.andrew.x@gmail.com
440c1f79ef This CL adds support for ARM and ARM64 architectures when calculating
exploitability ratings.

The stackwalker will now grab the instruction pointers for ARM and ARM64
architectures, so checking exploitability on ARM and ARM64 will no longer
return EXPLOITABILITY_ERR_PROCESSING.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1216063004

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1466 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-30 18:17:23 +00:00
rmcilroy@chromium.org
cd744acecc Adjust breakpad module size to match adjusted start_addr.
When changing a module's start_addr to account for Android packed
relocations, also adjust its size field so that the apparent module
end addr calculated by the breakpad processor does not alter.

Ensures that the mapping entry from a packed library is consistent
with that which an unpacked one would produce.

BUG=499747
R=primiano@chromium.org, rmcilroy@chromium.org

Review URL: https://codereview.chromium.org/1211863002.

Patch from Simon Baldwin <simonb@chromium.org>.

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1465 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-30 13:30:22 +00:00
Liu.andrew.x@gmail.com
cca153368a Checking location of the instruction pointer to see if it is
in valid code for Linux exploitability rating.

This CL adds to the Linux exploitability checker by verifying that the
instruction pointer is in valid code. Verification is done by obtaining a
memory mapping of the crash and checking if the instruction pointer lies in
an executable region. If there is no memory mapping, the instruction pointer
is checked to determine if it lies within a known module.

R=ivanpe@chromium.org

Review URL: https://codereview.chromium.org/1210493003

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1464 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-25 23:05:16 +00:00
rsesek@chromium.org
ed3bf1c825 Update the upload.py code review server.
This is follow-up to r1455.

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1463 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-24 16:27:36 +00:00
ivanpe@chromium.org
3c3c6680d3 Reconfigured options for sym_upload to not treat h and ? flags as invalid options.
I'm submitting this on behalf of Andrew Liu.

R=mmandlis@chromium.org

Review URL: https://codereview.chromium.org/1196733004

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1462 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-22 21:21:40 +00:00
primiano@chromium.org
11004944ad 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.

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1461 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-22 11:50:00 +00:00
ivanpe@chromium.org
893e93a41f Use local variable for out parameter rather than direct use of ivar
- Resolves spurious static analyzer warning about response_ being potentially leaked due to the retain in Xcode 6.3 and later.

I'm submitting this on behalf of Brian Moore.

R=qsr@chromium.org

Review URL: https://codereview.chromium.org/1171693007

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1460 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-20 00:32:37 +00:00
rmcilroy@chromium.org
8785c0cb8f Update breakpad for Android packed relocations.
Shared libraries containing Android packed relocations have a load
bias that differs from the start address in /proc/$$/maps. Current
breakpad assumes that the load bias and mapping start address are
the same.

Fixed by changing the client to detect the presence of Android packed
relocations in the address space of a loaded library, and adjusting the
stored mapping start address of any that are packed so that it contains
the linker's load bias.

For this to work properly, it is important that the non-packed library
is symbolized for breakpad. Either packed or non-packed libraries may
be run on the device; the client detects which has been loaded by the
linker.

BUG=499747
R=primiano@chromium.org, rmcilroy@chromium.org

Review URL: https://codereview.chromium.org/1189823002.

Patch from Simon Baldwin <simonb@chromium.org>.

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1459 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-06-19 16:30:42 +00:00
vapier@chromium.org
66295d1352 update more ignore files
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1458 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-05-28 06:16:15 +00:00
primiano@chromium.org
90cbb27528 [microdump] Add build fingerprint and product info metadata.
This is to add build fingerprint and product name/version to
microdumps. Conversely to what happens in the case of minidumps
with MIME fields, due to the nature of minidumps, extra metadata
cannot be reliably injected after the dump is completed.
This CL adds the plumbing to inject two optional fields plus the
corresponding tests.

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

Review URL: https://codereview.chromium.org/1125153008

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1456 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-05-15 08:43:01 +00:00
mark@chromium.org
f1ca06a079 Switch code review server to codereview.chromium.org.
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1455 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-05-06 17:52:38 +00:00
primiano@chromium.org
69b745aa74 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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1454 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-30 09:12:54 +00:00
erikchen@chromium.org
aa75fa5d4e Support object files larger than 2**32.
Reviewed at https://breakpad.appspot.com/7834002/#ps340001


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1453 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-22 20:14:24 +00:00
rmcilroy@chromium.org
0f27af628f [MIPS]: Use mcontext_t structure for MIPS
This change removes user_regs_struct and
user_fpregs_struct structures for mips
and uses mcontext_t instead.

R=fdegans@chromium.org, mark@chromium.org, rmcilroy@chromium.org

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

Patch from Gordana Cmiljanovic <Gordana.Cmiljanovic@imgtec.com>.

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1452 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-21 21:34:14 +00:00
vapier@chromium.org
9c6af3e29c update svn:ignores
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1451 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-18 03:27:45 +00:00
vapier@chromium.org
50b2a7e647 synx with latest upstream gnuconfig
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1450 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-18 03:25:50 +00:00
cjhopman@chromium.org
751453c357 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


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1447 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-15 22:57:24 +00:00
mark@chromium.org
d88401cca9 MIPS64: Initial MIPS64 related change.
With this change Breakpad can be compiled for MIPS64,
but it is not yet functional.

Patch by Gordana Cmiljanovic <Gordana.Cmiljanovic@imgtec.com>
Review URL: https://breakpad.appspot.com/6824002/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1446 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-15 19:28:11 +00:00
mark@chromium.org
18fc88ddc2 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/trunk@1443 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-13 23:59:06 +00:00
primiano@chromium.org
353e4cd585 Microdump processor: be more tolerant for different logcat formats
The current processor implementation is grepping for /google-breakpad(
in the logcat lines, to filter out microdump lines, which by default
look like this:
W/google-breakpad( 3728): -----BEGIN BREAKPAD MICRODUMP-----

Turns out that logcat format can vary, when passing optional arguments,
and produce something like the following:

04-13 12:30:35.563  6531  6531 W google-breakpad: -----BEGIN ...

In the latter case, the "/google-breakpad(" filter is too aggressive.
This change is relaxing it, so it is compatible also with non-default
logcat arguments.

BUG=640
R=mmandlis@chromium.org

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

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1442 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-13 17:45:17 +00:00
mark@chromium.org
cd6f90524a Add address and reason for IN_PAGE_ERROR.
ACCESS_VIOLATION and IN_PAGE_ERROR both specify
read/write/dep flags and address. ACCESS_VIOLATION currently
reports these, but IN_PAGE_ERROR does not. This change makes
IN_PAGE_ERROR report this information as well, and also the
additional NTSTATUS value for the underlying cause.

Patch by bungeman@chromium.org
Review URL: https://breakpad.appspot.com/1794002/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1441 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-10 22:05:29 +00:00
mark@chromium.org
cfdf7cf8a9 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/trunk@1438 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-04-10 17:57:24 +00:00
ted.mielczarek@gmail.com
48b9a40539 Fix compilation with gcc --std=c++11
Patch by Jon Turney <jon.turney.1111@gmail.com>
R=ted at https://breakpad.appspot.com/7824002/



git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1435 4c0a9323-5329-0410-9bdc-e9ce6186880e
2015-03-24 11:25:14 +00:00
primiano@chromium.org
9b2d7192a4 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
ee25f6794b 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
9208fbc224 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
bbd478ae73 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
eb08c16300 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
f2e6c177e4 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
14bbefbd96 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
b79454627e 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
94f863af2c 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
3b7262b0ee 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
c63cf36a13 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
89947e7d86 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
854b9f74a0 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
9f00bce09a 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
4c01a9c389 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
8aa26b79f9 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
924a8a2974 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
cef1bee150 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
cfaf27c37e 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
7bebb27fb4 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
efa0310455 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
c332a1dcba 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
30d41ec243 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
ba16fd3ffc 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
d10c8c18ae 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
bbbe29de11 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
10baadae40 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
0b6cc95246 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
63919583ba 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
57e5b074f6 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
be21ad8190 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
6354cffeb0 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
95 changed files with 8338 additions and 1149 deletions

26
.travis.yml Normal file
View File

@ -0,0 +1,26 @@
# Travis build integration.
# https://docs.travis-ci.com/
language: cpp
# TODO: add a clang build as well.
compiler:
- gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- g++-4.8
# Travis sets CC/CXX to the system toolchain based on the `compiler`
# selection. If clang is added, this should move to be set inside the
# matrix.
env:
- USE_CC=gcc-4.8 USE_CXX=g++-4.8
before_install: ./scripts/travis-checkout.sh
script: ./scripts/travis-build.sh
# TODO: add mac support
os:
- linux
notifications:
email:
- google-breakpad-dev@googlegroups.com

View File

@ -116,6 +116,7 @@ pkgconfig_DATA =
if SYSTEM_TEST_LIBS
TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS)
TEST_LIBS = $(GTEST_LIBS) -lgtest_main $(GMOCK_LIBS)
TEST_DEPS =
else
TEST_CFLAGS = \
-I$(top_srcdir)/src/testing/include \
@ -123,6 +124,7 @@ TEST_CFLAGS = \
-I$(top_srcdir)/src/testing/gtest \
-I$(top_srcdir)/src/testing
TEST_LIBS = src/testing/libtesting.a
TEST_DEPS = $(TEST_LIBS)
endif
## Libraries
@ -138,6 +140,7 @@ check_LIBRARIES += src/testing/libtesting.a
if !SYSTEM_TEST_LIBS
src_testing_libtesting_a_SOURCES = \
src/breakpad_googletest_includes.h \
src/testing/gtest/src/gtest-all.cc \
src/testing/gtest/src/gtest_main.cc \
src/testing/src/gmock-all.cc
@ -161,21 +164,33 @@ src_client_linux_libbreakpad_client_a_SOURCES = \
src/client/linux/dump_writer_common/thread_info.cc \
src/client/linux/dump_writer_common/ucontext_reader.cc \
src/client/linux/handler/exception_handler.cc \
src/client/linux/handler/exception_handler.h \
src/client/linux/handler/minidump_descriptor.cc \
src/client/linux/handler/minidump_descriptor.h \
src/client/linux/log/log.cc \
src/client/linux/log/log.h \
src/client/linux/microdump_writer/microdump_writer.cc \
src/client/linux/microdump_writer/microdump_writer.h \
src/client/linux/minidump_writer/linux_core_dumper.cc \
src/client/linux/minidump_writer/linux_dumper.cc \
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
src/client/linux/minidump_writer/minidump_writer.cc \
src/client/minidump_file_writer-inl.h \
src/client/minidump_file_writer.cc \
src/client/minidump_file_writer.h \
src/common/convert_UTF.c \
src/common/convert_UTF.h \
src/common/md5.cc \
src/common/md5.h \
src/common/string_conversion.cc \
src/common/string_conversion.h \
src/common/linux/elf_core_dump.cc \
src/common/linux/elfutils.cc \
src/common/linux/elfutils.h \
src/common/linux/file_id.cc \
src/common/linux/file_id.h \
src/common/linux/guid_creator.cc \
src/common/linux/guid_creator.h \
src/common/linux/linux_libc_support.cc \
src/common/linux/memory_mapped_file.cc \
src/common/linux/safe_readlink.cc
@ -380,6 +395,7 @@ check_PROGRAMS += \
src/processor/pathname_stripper_unittest \
src/processor/postfix_evaluator_unittest \
src/processor/proc_maps_linux_unittest \
src/processor/range_map_shrink_down_unittest \
src/processor/range_map_unittest \
src/processor/stackwalker_amd64_unittest \
src/processor/stackwalker_arm_unittest \
@ -467,9 +483,12 @@ src_client_linux_linux_client_unittest_shlib_SOURCES = \
src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
src/common/linux/elf_core_dump.cc \
src/common/linux/linux_libc_support_unittest.cc \
src/common/linux/tests/auto_testfile.h \
src/common/linux/tests/crash_generator.cc \
src/common/memory_unittest.cc \
src/common/tests/auto_tempdir.h \
src/common/tests/file_utils.cc \
src/common/tests/file_utils.h \
src/processor/basic_code_modules.cc \
src/processor/dump_context.cc \
src/processor/dump_object.cc \
@ -524,11 +543,14 @@ endif
src_client_linux_linux_client_unittest_shlib_DEPENDENCIES = \
src/client/linux/linux_dumper_unittest_helper \
src/client/linux/libbreakpad_client.a \
$(TEST_DEPS) \
src/libbreakpad.a
src_client_linux_linux_client_unittest_SOURCES =
# The extra-long build id is for a test in minidump_writer_unittest.cc.
src_client_linux_linux_client_unittest_LDFLAGS = \
-Wl,-rpath,'$$ORIGIN'
-Wl,-rpath,'$$ORIGIN' \
-Wl,--build-id=0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
if ANDROID_HOST
src_client_linux_linux_client_unittest_LDFLAGS += \
-llog
@ -559,9 +581,12 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/linux/crc32.cc \
src/common/linux/dump_symbols.cc \
src/common/linux/dump_symbols.h \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/elf_symbols_to_module.h \
src/common/linux/elfutils.cc \
src/common/linux/file_id.cc \
src/common/linux/linux_libc_support.cc \
@ -571,7 +596,8 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
src_tools_linux_md2core_minidump_2_core_SOURCES = \
src/common/linux/memory_mapped_file.cc \
src/tools/linux/md2core/minidump-2-core.cc
src/tools/linux/md2core/minidump-2-core.cc \
src/tools/linux/md2core/minidump_memory_range.h
src_tools_linux_symupload_minidump_upload_SOURCES = \
src/common/linux/http_upload.cc \
@ -580,6 +606,9 @@ src_tools_linux_symupload_minidump_upload_LDADD = -ldl
src_tools_linux_symupload_sym_upload_SOURCES = \
src/common/linux/http_upload.cc \
src/common/linux/http_upload.h \
src/common/linux/symbol_upload.cc \
src/common/linux/symbol_upload.h \
src/tools/linux/symupload/sym_upload.cc
src_tools_linux_symupload_sym_upload_LDADD = -ldl
@ -595,13 +624,20 @@ src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc \
src/common/mac/dump_syms.cc \
src/common/mac/dump_syms.h \
src/common/mac/file_id.cc \
src/common/mac/file_id.h \
src/common/mac/macho_id.cc \
src/common/mac/macho_id.h \
src/common/mac/macho_reader.cc \
src/common/mac/macho_reader.h \
src/common/mac/macho_utilities.cc \
src/common/mac/macho_utilities.h \
src/common/mac/macho_walker.cc \
src/common/mac/macho_walker.h \
src/tools/mac/dump_syms/dump_syms_tool.cc
src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS= \
-I$(top_srcdir)/src/third_party/mac_headers \
@ -625,13 +661,20 @@ src_common_dumper_unittest_SOURCES = \
src/common/stabs_to_module_unittest.cc \
src/common/test_assembler.cc \
src/common/dwarf/bytereader.cc \
src/common/dwarf/bytereader.h \
src/common/dwarf/bytereader-inl.h \
src/common/dwarf/bytereader_unittest.cc \
src/common/dwarf/cfi_assembler.cc \
src/common/dwarf/cfi_assembler.h \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2diehandler_unittest.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/dwarf2reader.h \
src/common/dwarf/elf_reader.cc \
src/common/dwarf/elf_reader.h \
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
src/common/dwarf/dwarf2reader_die_unittest.cc \
src/common/dwarf/dwarf2reader_test_common.h \
src/common/linux/crc32.cc \
src/common/linux/dump_symbols.cc \
src/common/linux/dump_symbols_unittest.cc \
@ -650,6 +693,8 @@ src_common_dumper_unittest_SOURCES = \
src/common/linux/synth_elf.cc \
src/common/linux/synth_elf_unittest.cc \
src/common/linux/tests/crash_generator.cc \
src/common/linux/tests/crash_generator.h \
src/common/testdata/func-line-pairing.h \
src/common/tests/file_utils.cc
src_common_dumper_unittest_CPPFLAGS = \
$(AM_CPPFLAGS) $(TEST_CFLAGS) \
@ -672,6 +717,7 @@ src_common_mac_macho_reader_unittest_SOURCES = \
src/common/dwarf/cfi_assembler.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc \
src/common/mac/file_id.cc \
src/common/mac/macho_id.cc \
@ -971,6 +1017,16 @@ src_processor_postfix_evaluator_unittest_LDADD = \
src/processor/pathname_stripper.o \
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
src_processor_range_map_shrink_down_unittest_SOURCES = \
src/processor/range_map_shrink_down_unittest.cc
src_processor_range_map_shrink_down_unittest_LDADD = \
src/processor/logging.o \
src/processor/pathname_stripper.o \
$(TEST_LIBS) \
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
src_processor_range_map_shrink_down_unittest_CPPFLAGS = \
$(AM_CPPFLAGS) $(TEST_CFLAGS)
src_processor_range_map_unittest_SOURCES = \
src/processor/range_map_unittest.cc
src_processor_range_map_unittest_LDADD = \
@ -1195,33 +1251,32 @@ endif !DISABLE_PROCESSOR
## sed -e s/'^\(.*\)$'/'\t\1 \\'/
EXTRA_DIST = \
$(SCRIPTS) \
src/processor/stackwalk_selftest_sol.s \
src/client/linux/handler/Makefile \
src/client/linux/handler/exception_handler.cc \
src/client/linux/handler/exception_handler.h \
src/client/linux/handler/minidump_descriptor.cc \
src/client/linux/handler/minidump_descriptor.h \
src/client/linux/handler/exception_handler_test.cc \
src/client/linux/handler/linux_thread.cc \
src/client/linux/handler/linux_thread.h \
src/client/linux/handler/linux_thread_test.cc \
src/client/linux/handler/minidump_generator.cc \
src/client/linux/handler/minidump_generator.h \
src/client/linux/handler/minidump_test.cc \
src/client/linux/data/linux-gate-amd.sym \
src/client/linux/data/linux-gate-intel.sym \
src/client/mac/handler/breakpad_nlist_64.cc \
src/client/mac/handler/breakpad_nlist_64.h \
src/client/mac/handler/dynamic_images.cc \
src/client/mac/handler/dynamic_images.h \
src/client/mac/handler/exception_handler.cc \
src/client/mac/handler/exception_handler.h \
src/client/mac/handler/exception_handler_test.cc \
src/client/mac/handler/mach_vm_compat.h \
src/client/mac/handler/minidump_generator.cc \
src/client/mac/handler/minidump_generator.h \
src/client/mac/handler/minidump_generator_test.cc \
src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
src/client/mac/handler/minidump_tests32-Info.plist \
src/client/mac/handler/minidump_tests64-Info.plist \
src/client/mac/handler/obj-cTestCases-Info.plist \
src/client/mac/handler/protected_memory_allocator.cc \
src/client/mac/handler/protected_memory_allocator.h \
src/client/minidump_file_writer-inl.h \
src/client/minidump_file_writer.cc \
src/client/minidump_file_writer.h \
src/client/mac/handler/ucontext_compat.h \
src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym \
src/client/mac/tests/BreakpadFramework_Test.mm \
src/client/mac/tests/crash_generation_server_test.cc \
src/client/mac/tests/exception_handler_test.cc \
src/client/mac/tests/minidump_generator_test.cc \
src/client/mac/tests/minidump_generator_test_helper.cc \
src/client/mac/tests/spawn_child_process.h \
src/client/mac/tests/testlogging.h \
src/client/minidump_file_writer_unittest.cc \
src/client/solaris/handler/Makefile \
src/client/solaris/handler/exception_handler.cc \
@ -1232,44 +1287,24 @@ EXTRA_DIST = \
src/client/solaris/handler/minidump_test.cc \
src/client/solaris/handler/solaris_lwp.cc \
src/client/solaris/handler/solaris_lwp.h \
src/client/windows/breakpad_client.sln \
src/client/windows/breakpad_client.gyp \
src/client/windows/handler/exception_handler.cc \
src/client/windows/handler/exception_handler.h \
src/client/windows/handler/exception_handler.vcproj \
src/client/windows/handler/exception_handler.gyp \
src/client/windows/sender/crash_report_sender.cc \
src/client/windows/sender/crash_report_sender.h \
src/client/windows/sender/crash_report_sender.vcproj \
src/common/convert_UTF.c \
src/common/convert_UTF.h \
src/common/linux/crc32.cc \
src/common/linux/dump_symbols.cc \
src/common/linux/dump_symbols.h \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/elf_symbols_to_module.h \
src/common/linux/elfutils.cc \
src/common/linux/elfutils.h \
src/common/linux/file_id.cc \
src/common/linux/file_id.h \
src/common/linux/guid_creator.cc \
src/common/linux/guid_creator.h \
src/common/linux/http_upload.cc \
src/common/linux/http_upload.h \
src/client/windows/sender/crash_report_sender.gyp \
src/common/dwarf/dwarf2diehandler.h \
src/common/dwarf/dwarf2enums.h \
src/common/dwarf/line_state_machine.h \
src/common/dwarf/types.h \
src/common/mac/arch_utilities.h \
src/common/mac/byteswap.h \
src/common/mac/HTTPMultipartUpload.h \
src/common/mac/HTTPMultipartUpload.m \
src/common/mac/dump_syms.h \
src/common/mac/dump_syms.cc \
src/common/mac/file_id.cc \
src/common/mac/file_id.h \
src/common/mac/macho_id.cc \
src/common/mac/macho_id.h \
src/common/mac/macho_utilities.cc \
src/common/mac/macho_utilities.h \
src/common/mac/macho_walker.cc \
src/common/mac/macho_walker.h \
src/common/mac/string_utilities.cc \
src/common/mac/string_utilities.h \
src/common/md5.cc \
src/common/md5.h \
src/common/mac/super_fat_arch.h \
src/common/scoped_ptr.h \
src/common/solaris/dump_symbols.cc \
src/common/solaris/dump_symbols.h \
@ -1278,8 +1313,6 @@ EXTRA_DIST = \
src/common/solaris/guid_creator.cc \
src/common/solaris/guid_creator.h \
src/common/solaris/message_output.h \
src/common/string_conversion.cc \
src/common/string_conversion.h \
src/common/windows/guid_string.cc \
src/common/windows/guid_string.h \
src/common/windows/http_upload.cc \
@ -1288,22 +1321,158 @@ EXTRA_DIST = \
src/common/windows/pdb_source_line_writer.h \
src/common/windows/string_utils-inl.h \
src/common/windows/string_utils.cc \
src/processor/stackwalk_common.cc \
src/processor/stackwalk_common.h \
src/processor/stackwalker_selftest_sol.s \
src/processor/testdata/ascii_read_av_block_write.dmp \
src/processor/testdata/ascii_read_av_clobber_write.dmp \
src/processor/testdata/ascii_read_av_conditional.dmp \
src/processor/testdata/ascii_read_av.dmp \
src/processor/testdata/ascii_read_av_then_jmp.dmp \
src/processor/testdata/ascii_read_av_xchg_write.dmp \
src/processor/testdata/ascii_write_av_arg_to_call.dmp \
src/processor/testdata/ascii_write_av.dmp \
src/processor/testdata/exec_av_on_stack.dmp \
src/processor/testdata/linux_divide_by_zero.dmp \
src/processor/testdata/linux_executable_heap.dmp \
src/processor/testdata/linux_executable_stack.dmp \
src/processor/testdata/linux_inside_module_exe_region1.dmp \
src/processor/testdata/linux_inside_module_exe_region2.dmp \
src/processor/testdata/linux_jmp_to_0.dmp \
src/processor/testdata/linux_jmp_to_module_not_exe_region.dmp \
src/processor/testdata/linux_null_dereference.dmp \
src/processor/testdata/linux_null_read_av.dmp \
src/processor/testdata/linux_outside_module.dmp \
src/processor/testdata/linux_overflow.dmp \
src/processor/testdata/linux_raise_sigabrt.dmp \
src/processor/testdata/linux_stack_pointer_in_module.dmp \
src/processor/testdata/linux_stack_pointer_in_stack.dmp \
src/processor/testdata/linux_stacksmash.dmp \
src/processor/testdata/linux_write_to_nonwritable_module.dmp \
src/processor/testdata/linux_write_to_nonwritable_region_math.dmp \
src/processor/testdata/linux_write_to_outside_module.dmp \
src/processor/testdata/linux_write_to_outside_module_via_math.dmp \
src/processor/testdata/linux_write_to_under_4k.dmp \
src/processor/testdata/microdump-arm64.dmp \
src/processor/testdata/microdump-arm.dmp \
src/processor/testdata/microdump-mips32.dmp \
src/processor/testdata/microdump-mips64.dmp \
src/processor/testdata/microdump-multiple.dmp \
src/processor/testdata/microdump.stackwalk-arm64.out \
src/processor/testdata/microdump.stackwalk-arm.out \
src/processor/testdata/microdump.stackwalk.machine_readable-arm64.out \
src/processor/testdata/microdump.stackwalk.machine_readable-arm.out \
src/processor/testdata/microdump-x86.dmp \
src/processor/testdata/minidump2.dmp \
src/processor/testdata/minidump2.dump.out \
src/processor/testdata/minidump2.stackwalk.machine_readable.out \
src/processor/testdata/minidump2.stackwalk.out \
src/processor/testdata/module0.out \
src/processor/testdata/module1.out \
src/processor/testdata/module2.out \
src/processor/testdata/module3_bad.out \
src/processor/testdata/module4_bad.out \
src/processor/testdata/null_read_av.dmp \
src/processor/testdata/null_write_av.dmp \
src/processor/testdata/read_av_clobber_write.dmp \
src/processor/testdata/read_av_conditional.dmp \
src/processor/testdata/read_av_non_null.dmp \
src/processor/testdata/stack_exhaustion.dmp \
src/processor/testdata/write_av_non_null.dmp \
src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
src/processor/testdata/symbols/ld-2.13.so/C32AD7E235EA6112E02A5B9D6219C4850/ld-2.13.so.sym \
src/processor/testdata/symbols/libc-2.13.so/F4F8DFCD5A5FB5A7CE64717E9E6AE3890/libc-2.13.so.sym \
src/processor/testdata/symbols/libgcc_s.so.1/18B180F90887D8F8B5C35D185444AF4C0/libgcc_s.so.1.sym \
src/processor/testdata/symbols/microdump/breakpad_unittests/D6D1FEC9A15DE7F38A236898871A2E770/breakpad_unittests.sym \
src/processor/testdata/symbols/microdump/breakpad_unittests/DA7778FB66018A4E9B4110ED06E730D00/breakpad_unittests.sym \
src/processor/testdata/symbols/microdump/crash_example/6E72E2F1A5F59AB3D51356FDFE394D490/crash_example.sym \
src/processor/testdata/symbols/microdump/crash_example/8F36148CC4647A8116CAF2A25F591F570/crash_example.sym \
src/processor/testdata/symbols/null_read_av/7B7D1968FF0D47AE4366E9C3A7E1B6750/null_read_av.sym \
src/processor/testdata/symbols/overflow/B0E1FC01EF48E39CAF5C881D2DF0C3840/overflow.sym \
src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
src/processor/testdata/test_app.cc \
src/tools/linux/dump_syms/Makefile \
src/tools/linux/dump_syms/dump_syms.cc \
src/tools/linux/symupload/Makefile \
src/tools/linux/symupload/minidump_upload.cc \
src/tools/linux/symupload/sym_upload.cc \
src/testing/gtest/include/gtest/gtest.h \
src/testing/gtest/include/gtest/gtest-death-test.h \
src/testing/gtest/include/gtest/gtest-message.h \
src/testing/gtest/include/gtest/gtest-param-test.h \
src/testing/gtest/include/gtest/gtest-printers.h \
src/testing/gtest/include/gtest/gtest-spi.h \
src/testing/gtest/include/gtest/gtest-test-part.h \
src/testing/gtest/include/gtest/gtest-typed-test.h \
src/testing/gtest/include/gtest/gtest_pred_impl.h \
src/testing/gtest/include/gtest/gtest_prod.h \
src/testing/gtest/include/gtest/internal/gtest-death-test-internal.h \
src/testing/gtest/include/gtest/internal/gtest-filepath.h \
src/testing/gtest/include/gtest/internal/gtest-internal.h \
src/testing/gtest/include/gtest/internal/gtest-linked_ptr.h \
src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h \
src/testing/gtest/include/gtest/internal/gtest-param-util.h \
src/testing/gtest/include/gtest/internal/gtest-port.h \
src/testing/gtest/include/gtest/internal/gtest-string.h \
src/testing/gtest/include/gtest/internal/gtest-tuple.h \
src/testing/gtest/include/gtest/internal/gtest-type-util.h \
src/testing/gtest/src/gtest.cc \
src/testing/gtest/src/gtest-death-test.cc \
src/testing/gtest/src/gtest-filepath.cc \
src/testing/gtest/src/gtest-internal-inl.h \
src/testing/gtest/src/gtest-port.cc \
src/testing/gtest/src/gtest-printers.cc \
src/testing/gtest/src/gtest-test-part.cc \
src/testing/gtest/src/gtest-typed-test.cc \
src/testing/include/gmock/gmock.h \
src/testing/include/gmock/gmock-actions.h \
src/testing/include/gmock/gmock-cardinalities.h \
src/testing/include/gmock/gmock-generated-actions.h \
src/testing/include/gmock/gmock-generated-function-mockers.h \
src/testing/include/gmock/gmock-generated-matchers.h \
src/testing/include/gmock/gmock-generated-nice-strict.h \
src/testing/include/gmock/gmock-matchers.h \
src/testing/include/gmock/gmock-more-actions.h \
src/testing/include/gmock/gmock-more-matchers.h \
src/testing/include/gmock/gmock-spec-builders.h \
src/testing/include/gmock/internal/gmock-generated-internal-utils.h \
src/testing/include/gmock/internal/gmock-internal-utils.h \
src/testing/include/gmock/internal/gmock-port.h \
src/testing/src/gmock.cc \
src/testing/src/gmock-cardinalities.cc \
src/testing/src/gmock-internal-utils.cc \
src/testing/src/gmock-matchers.cc \
src/testing/src/gmock-spec-builders.cc \
src/testing/src/gmock_main.cc \
src/third_party/curl/COPYING \
src/third_party/curl/curlbuild.h \
src/third_party/curl/curl.h \
src/third_party/curl/curlrules.h \
src/third_party/curl/curlver.h \
src/third_party/curl/easy.h \
src/third_party/curl/mprintf.h \
src/third_party/curl/multi.h \
src/third_party/curl/stdcheaders.h \
src/third_party/curl/typecheck-gcc.h \
src/third_party/curl/types.h \
src/third_party/mac_headers/architecture/byte_order.h \
src/third_party/mac_headers/i386/_types.h \
src/third_party/mac_headers/mach/boolean.h \
src/third_party/mac_headers/mach/i386/boolean.h \
src/third_party/mac_headers/mach/i386/vm_param.h \
src/third_party/mac_headers/mach/i386/vm_types.h \
src/third_party/mac_headers/mach/machine/boolean.h \
src/third_party/mac_headers/mach/machine.h \
src/third_party/mac_headers/mach/machine/thread_state.h \
src/third_party/mac_headers/mach/machine/thread_status.h \
src/third_party/mac_headers/mach/machine/vm_types.h \
src/third_party/mac_headers/mach-o/arch.h \
src/third_party/mac_headers/mach-o/fat.h \
src/third_party/mac_headers/mach-o/loader.h \
src/third_party/mac_headers/mach-o/nlist.h \
src/third_party/mac_headers/mach/thread_status.h \
src/third_party/mac_headers/mach/vm_prot.h \
src/third_party/mac_headers/README \
src/third_party/musl/README \
src/third_party/musl/COPYRIGHT \
src/third_party/musl/README.breakpad \
src/third_party/musl/VERSION \
src/third_party/musl/include/elf.h \
src/tools/mac/crash_report/crash_report.mm \
src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
src/tools/mac/crash_report/on_demand_symbol_supplier.h \
@ -1322,15 +1491,20 @@ EXTRA_DIST = \
src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym \
src/tools/windows/converter/ms_symbol_server_converter.cc \
src/tools/windows/converter/ms_symbol_server_converter.h \
src/tools/windows/converter/ms_symbol_server_converter.vcproj \
src/tools/windows/converter/ms_symbol_server_converter.gyp \
src/tools/windows/dump_syms/dump_syms.cc \
src/tools/windows/dump_syms/dump_syms.vcproj \
src/tools/windows/dump_syms/dump_syms.gyp \
src/tools/windows/dump_syms/run_regtest.sh \
src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
src/tools/windows/dump_syms/testdata/dump_syms_regtest64.sym \
src/tools/windows/dump_syms/testdata/omap_reorder_bbs.sym \
src/tools/windows/dump_syms/testdata/omap_reorder_funcs.sym \
src/tools/windows/dump_syms/testdata/omap_stretched.sym \
src/tools/windows/dump_syms/testdata/omap_stretched_filled.sym \
src/tools/windows/symupload/symupload.cc \
src/tools/windows/symupload/symupload.vcproj
src/tools/windows/symupload/symupload.gyp
mostlyclean-local:
-find src -name '*.dwo' -exec rm -f {} +

View File

@ -194,6 +194,7 @@ EXTRA_PROGRAMS = $(am__EXEEXT_1)
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64_unittest \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm_unittest \
@ -298,17 +299,25 @@ am__src_client_linux_libbreakpad_client_a_SOURCES_DIST = \
src/client/linux/dump_writer_common/thread_info.cc \
src/client/linux/dump_writer_common/ucontext_reader.cc \
src/client/linux/handler/exception_handler.cc \
src/client/linux/handler/exception_handler.h \
src/client/linux/handler/minidump_descriptor.cc \
src/client/linux/log/log.cc \
src/client/linux/handler/minidump_descriptor.h \
src/client/linux/log/log.cc src/client/linux/log/log.h \
src/client/linux/microdump_writer/microdump_writer.cc \
src/client/linux/microdump_writer/microdump_writer.h \
src/client/linux/minidump_writer/linux_core_dumper.cc \
src/client/linux/minidump_writer/linux_dumper.cc \
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
src/client/linux/minidump_writer/minidump_writer.cc \
src/client/minidump_file_writer.cc src/common/convert_UTF.c \
src/common/md5.cc src/common/string_conversion.cc \
src/client/minidump_file_writer-inl.h \
src/client/minidump_file_writer.cc \
src/client/minidump_file_writer.h src/common/convert_UTF.c \
src/common/convert_UTF.h src/common/md5.cc src/common/md5.h \
src/common/string_conversion.cc src/common/string_conversion.h \
src/common/linux/elf_core_dump.cc src/common/linux/elfutils.cc \
src/common/linux/file_id.cc src/common/linux/guid_creator.cc \
src/common/linux/elfutils.h src/common/linux/file_id.cc \
src/common/linux/file_id.h src/common/linux/guid_creator.cc \
src/common/linux/guid_creator.h \
src/common/linux/linux_libc_support.cc \
src/common/linux/memory_mapped_file.cc \
src/common/linux/safe_readlink.cc \
@ -488,6 +497,7 @@ src_libbreakpad_a_OBJECTS = $(am_src_libbreakpad_a_OBJECTS)
src_testing_libtesting_a_AR = $(AR) $(ARFLAGS)
src_testing_libtesting_a_LIBADD =
am__src_testing_libtesting_a_SOURCES_DIST = \
src/breakpad_googletest_includes.h \
src/testing/gtest/src/gtest-all.cc \
src/testing/gtest/src/gtest_main.cc \
src/testing/src/gmock-all.cc
@ -571,6 +581,7 @@ src_third_party_libdisasm_libdisasm_a_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/postfix_evaluator_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/proc_maps_linux_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_amd64_unittest$(EXEEXT) \
@DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_arm_unittest$(EXEEXT) \
@ -597,6 +608,7 @@ src_client_linux_linux_client_unittest_LINK = $(CCLD) $(AM_CFLAGS) \
$(CFLAGS) $(src_client_linux_linux_client_unittest_LDFLAGS) \
$(LDFLAGS) -o $@
am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \
src/breakpad_googletest_includes.h \
src/testing/gtest/src/gtest-all.cc \
src/testing/gtest/src/gtest_main.cc \
src/testing/src/gmock-all.cc \
@ -612,8 +624,10 @@ am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \
src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
src/common/linux/elf_core_dump.cc \
src/common/linux/linux_libc_support_unittest.cc \
src/common/linux/tests/auto_testfile.h \
src/common/linux/tests/crash_generator.cc \
src/common/memory_unittest.cc src/common/tests/file_utils.cc \
src/common/memory_unittest.cc src/common/tests/auto_tempdir.h \
src/common/tests/file_utils.cc src/common/tests/file_utils.h \
src/processor/basic_code_modules.cc \
src/processor/dump_context.cc src/processor/dump_object.cc \
src/processor/logging.cc src/processor/minidump.cc \
@ -684,13 +698,19 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
src/common/stabs_to_module.cc \
src/common/stabs_to_module_unittest.cc \
src/common/test_assembler.cc src/common/dwarf/bytereader.cc \
src/common/dwarf/bytereader.h \
src/common/dwarf/bytereader-inl.h \
src/common/dwarf/bytereader_unittest.cc \
src/common/dwarf/cfi_assembler.cc \
src/common/dwarf/cfi_assembler.h \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2diehandler_unittest.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/dwarf2reader.h src/common/dwarf/elf_reader.cc \
src/common/dwarf/elf_reader.h \
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
src/common/dwarf/dwarf2reader_die_unittest.cc \
src/common/dwarf/dwarf2reader_test_common.h \
src/common/linux/crc32.cc src/common/linux/dump_symbols.cc \
src/common/linux/dump_symbols_unittest.cc \
src/common/linux/elf_core_dump.cc \
@ -707,6 +727,8 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
src/common/linux/synth_elf.cc \
src/common/linux/synth_elf_unittest.cc \
src/common/linux/tests/crash_generator.cc \
src/common/linux/tests/crash_generator.h \
src/common/testdata/func-line-pairing.h \
src/common/tests/file_utils.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_common_dumper_unittest_OBJECTS = src/common/src_common_dumper_unittest-byte_cursor_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_cfi_to_module.$(OBJEXT) \
@ -730,6 +752,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT) \
@ -767,6 +790,7 @@ am__src_common_mac_macho_reader_unittest_SOURCES_DIST = \
src/common/dwarf/cfi_assembler.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc src/common/mac/file_id.cc \
src/common/mac/macho_id.cc src/common/mac/macho_reader.cc \
src/common/mac/macho_reader_unittest.cc \
@ -785,6 +809,7 @@ am__src_common_mac_macho_reader_unittest_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-cfi_assembler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-file_id.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_common_mac_macho_reader_unittest-macho_id.$(OBJEXT) \
@ -1147,6 +1172,17 @@ src_processor_proc_maps_linux_unittest_OBJECTS = \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
am__src_processor_range_map_shrink_down_unittest_SOURCES_DIST = \
src/processor/range_map_shrink_down_unittest.cc
@DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_shrink_down_unittest_OBJECTS = src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.$(OBJEXT)
src_processor_range_map_shrink_down_unittest_OBJECTS = \
$(am_src_processor_range_map_shrink_down_unittest_OBJECTS)
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_DEPENDENCIES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_2) \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1) \
@DISABLE_PROCESSOR_FALSE@ $(am__DEPENDENCIES_1)
am__src_processor_range_map_unittest_SOURCES_DIST = \
src/processor/range_map_unittest.cc
@DISABLE_PROCESSOR_FALSE@am_src_processor_range_map_unittest_OBJECTS = src/processor/range_map_unittest.$(OBJEXT)
@ -1343,9 +1379,12 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
src/common/module.cc src/common/stabs_reader.cc \
src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc src/common/linux/crc32.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc src/common/linux/crc32.cc \
src/common/linux/dump_symbols.cc \
src/common/linux/dump_symbols.h \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/elf_symbols_to_module.h \
src/common/linux/elfutils.cc src/common/linux/file_id.cc \
src/common/linux/linux_libc_support.cc \
src/common/linux/memory_mapped_file.cc \
@ -1361,6 +1400,7 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.$(OBJEXT) \
@ -1375,7 +1415,8 @@ src_tools_linux_dump_syms_dump_syms_OBJECTS = \
src_tools_linux_dump_syms_dump_syms_LDADD = $(LDADD)
am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST = \
src/common/linux/memory_mapped_file.cc \
src/tools/linux/md2core/minidump-2-core.cc
src/tools/linux/md2core/minidump-2-core.cc \
src/tools/linux/md2core/minidump_memory_range.h
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_OBJECTS = src/common/linux/memory_mapped_file.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.$(OBJEXT)
src_tools_linux_md2core_minidump_2_core_OBJECTS = \
@ -1397,9 +1438,12 @@ src_tools_linux_symupload_minidump_upload_OBJECTS = \
$(am_src_tools_linux_symupload_minidump_upload_OBJECTS)
src_tools_linux_symupload_minidump_upload_DEPENDENCIES =
am__src_tools_linux_symupload_sym_upload_SOURCES_DIST = \
src/common/linux/http_upload.cc \
src/common/linux/http_upload.cc src/common/linux/http_upload.h \
src/common/linux/symbol_upload.cc \
src/common/linux/symbol_upload.h \
src/tools/linux/symupload/sym_upload.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_symupload_sym_upload_OBJECTS = src/common/linux/http_upload.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload.$(OBJEXT)
src_tools_linux_symupload_sym_upload_OBJECTS = \
$(am_src_tools_linux_symupload_sym_upload_OBJECTS)
@ -1413,11 +1457,15 @@ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
src/common/dwarf/bytereader.cc \
src/common/dwarf/dwarf2diehandler.cc \
src/common/dwarf/dwarf2reader.cc \
src/common/dwarf/elf_reader.cc \
src/common/mac/arch_utilities.cc src/common/mac/dump_syms.cc \
src/common/mac/file_id.cc src/common/mac/macho_id.cc \
src/common/mac/macho_reader.cc \
src/common/mac/dump_syms.h src/common/mac/file_id.cc \
src/common/mac/file_id.h src/common/mac/macho_id.cc \
src/common/mac/macho_id.h src/common/mac/macho_reader.cc \
src/common/mac/macho_reader.h \
src/common/mac/macho_utilities.cc \
src/common/mac/macho_walker.cc \
src/common/mac/macho_utilities.h \
src/common/mac/macho_walker.cc src/common/mac/macho_walker.h \
src/tools/mac/dump_syms/dump_syms_tool.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_mac_dump_syms_dump_syms_mac_OBJECTS = src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cfi_to_module.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_tools_mac_dump_syms_dump_syms_mac-dwarf_cu_to_module.$(OBJEXT) \
@ -1430,6 +1478,7 @@ am__src_tools_mac_dump_syms_dump_syms_mac_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-bytereader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-dump_syms.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-file_id.$(OBJEXT) \
@ -1523,6 +1572,7 @@ SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \
$(src_processor_pathname_stripper_unittest_SOURCES) \
$(src_processor_postfix_evaluator_unittest_SOURCES) \
$(src_processor_proc_maps_linux_unittest_SOURCES) \
$(src_processor_range_map_shrink_down_unittest_SOURCES) \
$(src_processor_range_map_unittest_SOURCES) \
$(src_processor_stackwalker_address_list_unittest_SOURCES) \
$(src_processor_stackwalker_amd64_unittest_SOURCES) \
@ -1572,6 +1622,7 @@ DIST_SOURCES = \
$(am__src_processor_pathname_stripper_unittest_SOURCES_DIST) \
$(am__src_processor_postfix_evaluator_unittest_SOURCES_DIST) \
$(am__src_processor_proc_maps_linux_unittest_SOURCES_DIST) \
$(am__src_processor_range_map_shrink_down_unittest_SOURCES_DIST) \
$(am__src_processor_range_map_unittest_SOURCES_DIST) \
$(am__src_processor_stackwalker_address_list_unittest_SOURCES_DIST) \
$(am__src_processor_stackwalker_amd64_unittest_SOURCES_DIST) \
@ -2005,11 +2056,14 @@ pkgconfig_DATA = $(am__append_6) $(am__append_9)
@SYSTEM_TEST_LIBS_TRUE@TEST_CFLAGS = $(GTEST_CFLAGS) $(GMOCK_CFLAGS)
@SYSTEM_TEST_LIBS_FALSE@TEST_LIBS = src/testing/libtesting.a
@SYSTEM_TEST_LIBS_TRUE@TEST_LIBS = $(GTEST_LIBS) -lgtest_main $(GMOCK_LIBS)
@SYSTEM_TEST_LIBS_FALSE@TEST_DEPS = $(TEST_LIBS)
@SYSTEM_TEST_LIBS_TRUE@TEST_DEPS =
check_LIBRARIES = src/testing/libtesting.a
noinst_LIBRARIES = $(am__append_7)
lib_LIBRARIES = $(am__append_5) $(am__append_8)
CLEANFILES = $(am__append_13)
@SYSTEM_TEST_LIBS_FALSE@src_testing_libtesting_a_SOURCES = \
@SYSTEM_TEST_LIBS_FALSE@ src/breakpad_googletest_includes.h \
@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/gtest-all.cc \
@SYSTEM_TEST_LIBS_FALSE@ src/testing/gtest/src/gtest_main.cc \
@SYSTEM_TEST_LIBS_FALSE@ src/testing/src/gmock-all.cc
@ -2022,20 +2076,32 @@ CLEANFILES = $(am__append_13)
@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/thread_info.cc \
@LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/ucontext_reader.cc \
@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.cc \
@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.h \
@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.cc \
@LINUX_HOST_TRUE@ src/client/linux/handler/minidump_descriptor.h \
@LINUX_HOST_TRUE@ src/client/linux/log/log.cc \
@LINUX_HOST_TRUE@ src/client/linux/log/log.h \
@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.cc \
@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer.h \
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_core_dumper.cc \
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_dumper.cc \
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/minidump_writer.cc \
@LINUX_HOST_TRUE@ src/client/minidump_file_writer-inl.h \
@LINUX_HOST_TRUE@ src/client/minidump_file_writer.cc \
@LINUX_HOST_TRUE@ src/common/convert_UTF.c src/common/md5.cc \
@LINUX_HOST_TRUE@ src/client/minidump_file_writer.h \
@LINUX_HOST_TRUE@ src/common/convert_UTF.c \
@LINUX_HOST_TRUE@ src/common/convert_UTF.h src/common/md5.cc \
@LINUX_HOST_TRUE@ src/common/md5.h \
@LINUX_HOST_TRUE@ src/common/string_conversion.cc \
@LINUX_HOST_TRUE@ src/common/string_conversion.h \
@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \
@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \
@LINUX_HOST_TRUE@ src/common/linux/elfutils.h \
@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
@LINUX_HOST_TRUE@ src/common/linux/file_id.h \
@LINUX_HOST_TRUE@ src/common/linux/guid_creator.cc \
@LINUX_HOST_TRUE@ src/common/linux/guid_creator.h \
@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \
@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
@LINUX_HOST_TRUE@ src/common/linux/safe_readlink.cc \
@ -2223,9 +2289,12 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@LINUX_HOST_TRUE@ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \
@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support_unittest.cc \
@LINUX_HOST_TRUE@ src/common/linux/tests/auto_testfile.h \
@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.cc \
@LINUX_HOST_TRUE@ src/common/memory_unittest.cc \
@LINUX_HOST_TRUE@ src/common/tests/auto_tempdir.h \
@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc \
@LINUX_HOST_TRUE@ src/common/tests/file_utils.h \
@LINUX_HOST_TRUE@ src/processor/basic_code_modules.cc \
@LINUX_HOST_TRUE@ src/processor/dump_context.cc \
@LINUX_HOST_TRUE@ src/processor/dump_object.cc \
@ -2269,11 +2338,15 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_DEPENDENCIES = \
@LINUX_HOST_TRUE@ src/client/linux/linux_dumper_unittest_helper \
@LINUX_HOST_TRUE@ src/client/linux/libbreakpad_client.a \
@LINUX_HOST_TRUE@ $(TEST_DEPS) \
@LINUX_HOST_TRUE@ src/libbreakpad.a
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_SOURCES =
# The extra-long build id is for a test in minidump_writer_unittest.cc.
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDFLAGS = \
@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' $(am__append_24)
@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' \
@LINUX_HOST_TRUE@ -Wl,--build-id=0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f \
@LINUX_HOST_TRUE@ $(am__append_24)
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDADD = \
@LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib \
@LINUX_HOST_TRUE@ $(TEST_LIBS)
@ -2298,9 +2371,12 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elfutils.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/linux_libc_support.cc \
@ -2310,7 +2386,8 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_SOURCES = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump_memory_range.h
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_SOURCES = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.cc \
@ -2319,6 +2396,9 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_LDADD = -ldl
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_SOURCES = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/http_upload.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/symbol_upload.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/symupload/sym_upload.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_sym_upload_LDADD = -ldl
@ -2334,13 +2414,20 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/dump_syms.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/dump_syms.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_reader.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_utilities.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_utilities.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_walker.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_walker.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/mac/dump_syms/dump_syms_tool.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS = \
@ -2365,13 +2452,20 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_to_module_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/test_assembler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader-inl.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_cfi_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_die_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_test_common.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols_unittest.cc \
@ -2390,6 +2484,8 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/tests/crash_generator.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/testdata/func-line-pairing.h \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/tests/file_utils.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_common_dumper_unittest_CPPFLAGS = \
@ -2414,6 +2510,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/cfi_assembler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/elf_reader.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/arch_utilities.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/file_id.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/mac/macho_id.cc \
@ -2745,6 +2842,18 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_shrink_down_unittest.cc
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_LDADD = \
@DISABLE_PROCESSOR_FALSE@ src/processor/logging.o \
@DISABLE_PROCESSOR_FALSE@ src/processor/pathname_stripper.o \
@DISABLE_PROCESSOR_FALSE@ $(TEST_LIBS) \
@DISABLE_PROCESSOR_FALSE@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_shrink_down_unittest_CPPFLAGS = \
@DISABLE_PROCESSOR_FALSE@ $(AM_CPPFLAGS) $(TEST_CFLAGS)
@DISABLE_PROCESSOR_FALSE@src_processor_range_map_unittest_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/processor/range_map_unittest.cc
@ -2982,33 +3091,32 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
EXTRA_DIST = \
$(SCRIPTS) \
src/processor/stackwalk_selftest_sol.s \
src/client/linux/handler/Makefile \
src/client/linux/handler/exception_handler.cc \
src/client/linux/handler/exception_handler.h \
src/client/linux/handler/minidump_descriptor.cc \
src/client/linux/handler/minidump_descriptor.h \
src/client/linux/handler/exception_handler_test.cc \
src/client/linux/handler/linux_thread.cc \
src/client/linux/handler/linux_thread.h \
src/client/linux/handler/linux_thread_test.cc \
src/client/linux/handler/minidump_generator.cc \
src/client/linux/handler/minidump_generator.h \
src/client/linux/handler/minidump_test.cc \
src/client/linux/data/linux-gate-amd.sym \
src/client/linux/data/linux-gate-intel.sym \
src/client/mac/handler/breakpad_nlist_64.cc \
src/client/mac/handler/breakpad_nlist_64.h \
src/client/mac/handler/dynamic_images.cc \
src/client/mac/handler/dynamic_images.h \
src/client/mac/handler/exception_handler.cc \
src/client/mac/handler/exception_handler.h \
src/client/mac/handler/exception_handler_test.cc \
src/client/mac/handler/mach_vm_compat.h \
src/client/mac/handler/minidump_generator.cc \
src/client/mac/handler/minidump_generator.h \
src/client/mac/handler/minidump_generator_test.cc \
src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj \
src/client/mac/handler/minidump_tests32-Info.plist \
src/client/mac/handler/minidump_tests64-Info.plist \
src/client/mac/handler/obj-cTestCases-Info.plist \
src/client/mac/handler/protected_memory_allocator.cc \
src/client/mac/handler/protected_memory_allocator.h \
src/client/minidump_file_writer-inl.h \
src/client/minidump_file_writer.cc \
src/client/minidump_file_writer.h \
src/client/mac/handler/ucontext_compat.h \
src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym \
src/client/mac/tests/BreakpadFramework_Test.mm \
src/client/mac/tests/crash_generation_server_test.cc \
src/client/mac/tests/exception_handler_test.cc \
src/client/mac/tests/minidump_generator_test.cc \
src/client/mac/tests/minidump_generator_test_helper.cc \
src/client/mac/tests/spawn_child_process.h \
src/client/mac/tests/testlogging.h \
src/client/minidump_file_writer_unittest.cc \
src/client/solaris/handler/Makefile \
src/client/solaris/handler/exception_handler.cc \
@ -3019,44 +3127,24 @@ EXTRA_DIST = \
src/client/solaris/handler/minidump_test.cc \
src/client/solaris/handler/solaris_lwp.cc \
src/client/solaris/handler/solaris_lwp.h \
src/client/windows/breakpad_client.sln \
src/client/windows/breakpad_client.gyp \
src/client/windows/handler/exception_handler.cc \
src/client/windows/handler/exception_handler.h \
src/client/windows/handler/exception_handler.vcproj \
src/client/windows/handler/exception_handler.gyp \
src/client/windows/sender/crash_report_sender.cc \
src/client/windows/sender/crash_report_sender.h \
src/client/windows/sender/crash_report_sender.vcproj \
src/common/convert_UTF.c \
src/common/convert_UTF.h \
src/common/linux/crc32.cc \
src/common/linux/dump_symbols.cc \
src/common/linux/dump_symbols.h \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/elf_symbols_to_module.h \
src/common/linux/elfutils.cc \
src/common/linux/elfutils.h \
src/common/linux/file_id.cc \
src/common/linux/file_id.h \
src/common/linux/guid_creator.cc \
src/common/linux/guid_creator.h \
src/common/linux/http_upload.cc \
src/common/linux/http_upload.h \
src/client/windows/sender/crash_report_sender.gyp \
src/common/dwarf/dwarf2diehandler.h \
src/common/dwarf/dwarf2enums.h \
src/common/dwarf/line_state_machine.h \
src/common/dwarf/types.h \
src/common/mac/arch_utilities.h \
src/common/mac/byteswap.h \
src/common/mac/HTTPMultipartUpload.h \
src/common/mac/HTTPMultipartUpload.m \
src/common/mac/dump_syms.h \
src/common/mac/dump_syms.cc \
src/common/mac/file_id.cc \
src/common/mac/file_id.h \
src/common/mac/macho_id.cc \
src/common/mac/macho_id.h \
src/common/mac/macho_utilities.cc \
src/common/mac/macho_utilities.h \
src/common/mac/macho_walker.cc \
src/common/mac/macho_walker.h \
src/common/mac/string_utilities.cc \
src/common/mac/string_utilities.h \
src/common/md5.cc \
src/common/md5.h \
src/common/mac/super_fat_arch.h \
src/common/scoped_ptr.h \
src/common/solaris/dump_symbols.cc \
src/common/solaris/dump_symbols.h \
@ -3065,8 +3153,6 @@ EXTRA_DIST = \
src/common/solaris/guid_creator.cc \
src/common/solaris/guid_creator.h \
src/common/solaris/message_output.h \
src/common/string_conversion.cc \
src/common/string_conversion.h \
src/common/windows/guid_string.cc \
src/common/windows/guid_string.h \
src/common/windows/http_upload.cc \
@ -3075,22 +3161,158 @@ EXTRA_DIST = \
src/common/windows/pdb_source_line_writer.h \
src/common/windows/string_utils-inl.h \
src/common/windows/string_utils.cc \
src/processor/stackwalk_common.cc \
src/processor/stackwalk_common.h \
src/processor/stackwalker_selftest_sol.s \
src/processor/testdata/ascii_read_av_block_write.dmp \
src/processor/testdata/ascii_read_av_clobber_write.dmp \
src/processor/testdata/ascii_read_av_conditional.dmp \
src/processor/testdata/ascii_read_av.dmp \
src/processor/testdata/ascii_read_av_then_jmp.dmp \
src/processor/testdata/ascii_read_av_xchg_write.dmp \
src/processor/testdata/ascii_write_av_arg_to_call.dmp \
src/processor/testdata/ascii_write_av.dmp \
src/processor/testdata/exec_av_on_stack.dmp \
src/processor/testdata/linux_divide_by_zero.dmp \
src/processor/testdata/linux_executable_heap.dmp \
src/processor/testdata/linux_executable_stack.dmp \
src/processor/testdata/linux_inside_module_exe_region1.dmp \
src/processor/testdata/linux_inside_module_exe_region2.dmp \
src/processor/testdata/linux_jmp_to_0.dmp \
src/processor/testdata/linux_jmp_to_module_not_exe_region.dmp \
src/processor/testdata/linux_null_dereference.dmp \
src/processor/testdata/linux_null_read_av.dmp \
src/processor/testdata/linux_outside_module.dmp \
src/processor/testdata/linux_overflow.dmp \
src/processor/testdata/linux_raise_sigabrt.dmp \
src/processor/testdata/linux_stack_pointer_in_module.dmp \
src/processor/testdata/linux_stack_pointer_in_stack.dmp \
src/processor/testdata/linux_stacksmash.dmp \
src/processor/testdata/linux_write_to_nonwritable_module.dmp \
src/processor/testdata/linux_write_to_nonwritable_region_math.dmp \
src/processor/testdata/linux_write_to_outside_module.dmp \
src/processor/testdata/linux_write_to_outside_module_via_math.dmp \
src/processor/testdata/linux_write_to_under_4k.dmp \
src/processor/testdata/microdump-arm64.dmp \
src/processor/testdata/microdump-arm.dmp \
src/processor/testdata/microdump-mips32.dmp \
src/processor/testdata/microdump-mips64.dmp \
src/processor/testdata/microdump-multiple.dmp \
src/processor/testdata/microdump.stackwalk-arm64.out \
src/processor/testdata/microdump.stackwalk-arm.out \
src/processor/testdata/microdump.stackwalk.machine_readable-arm64.out \
src/processor/testdata/microdump.stackwalk.machine_readable-arm.out \
src/processor/testdata/microdump-x86.dmp \
src/processor/testdata/minidump2.dmp \
src/processor/testdata/minidump2.dump.out \
src/processor/testdata/minidump2.stackwalk.machine_readable.out \
src/processor/testdata/minidump2.stackwalk.out \
src/processor/testdata/module0.out \
src/processor/testdata/module1.out \
src/processor/testdata/module2.out \
src/processor/testdata/module3_bad.out \
src/processor/testdata/module4_bad.out \
src/processor/testdata/null_read_av.dmp \
src/processor/testdata/null_write_av.dmp \
src/processor/testdata/read_av_clobber_write.dmp \
src/processor/testdata/read_av_conditional.dmp \
src/processor/testdata/read_av_non_null.dmp \
src/processor/testdata/stack_exhaustion.dmp \
src/processor/testdata/write_av_non_null.dmp \
src/processor/testdata/symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym \
src/processor/testdata/symbols/ld-2.13.so/C32AD7E235EA6112E02A5B9D6219C4850/ld-2.13.so.sym \
src/processor/testdata/symbols/libc-2.13.so/F4F8DFCD5A5FB5A7CE64717E9E6AE3890/libc-2.13.so.sym \
src/processor/testdata/symbols/libgcc_s.so.1/18B180F90887D8F8B5C35D185444AF4C0/libgcc_s.so.1.sym \
src/processor/testdata/symbols/microdump/breakpad_unittests/D6D1FEC9A15DE7F38A236898871A2E770/breakpad_unittests.sym \
src/processor/testdata/symbols/microdump/breakpad_unittests/DA7778FB66018A4E9B4110ED06E730D00/breakpad_unittests.sym \
src/processor/testdata/symbols/microdump/crash_example/6E72E2F1A5F59AB3D51356FDFE394D490/crash_example.sym \
src/processor/testdata/symbols/microdump/crash_example/8F36148CC4647A8116CAF2A25F591F570/crash_example.sym \
src/processor/testdata/symbols/null_read_av/7B7D1968FF0D47AE4366E9C3A7E1B6750/null_read_av.sym \
src/processor/testdata/symbols/overflow/B0E1FC01EF48E39CAF5C881D2DF0C3840/overflow.sym \
src/processor/testdata/symbols/test_app.pdb/5A9832E5287241C1838ED98914E9B7FF1/test_app.sym \
src/processor/testdata/test_app.cc \
src/tools/linux/dump_syms/Makefile \
src/tools/linux/dump_syms/dump_syms.cc \
src/tools/linux/symupload/Makefile \
src/tools/linux/symupload/minidump_upload.cc \
src/tools/linux/symupload/sym_upload.cc \
src/testing/gtest/include/gtest/gtest.h \
src/testing/gtest/include/gtest/gtest-death-test.h \
src/testing/gtest/include/gtest/gtest-message.h \
src/testing/gtest/include/gtest/gtest-param-test.h \
src/testing/gtest/include/gtest/gtest-printers.h \
src/testing/gtest/include/gtest/gtest-spi.h \
src/testing/gtest/include/gtest/gtest-test-part.h \
src/testing/gtest/include/gtest/gtest-typed-test.h \
src/testing/gtest/include/gtest/gtest_pred_impl.h \
src/testing/gtest/include/gtest/gtest_prod.h \
src/testing/gtest/include/gtest/internal/gtest-death-test-internal.h \
src/testing/gtest/include/gtest/internal/gtest-filepath.h \
src/testing/gtest/include/gtest/internal/gtest-internal.h \
src/testing/gtest/include/gtest/internal/gtest-linked_ptr.h \
src/testing/gtest/include/gtest/internal/gtest-param-util-generated.h \
src/testing/gtest/include/gtest/internal/gtest-param-util.h \
src/testing/gtest/include/gtest/internal/gtest-port.h \
src/testing/gtest/include/gtest/internal/gtest-string.h \
src/testing/gtest/include/gtest/internal/gtest-tuple.h \
src/testing/gtest/include/gtest/internal/gtest-type-util.h \
src/testing/gtest/src/gtest.cc \
src/testing/gtest/src/gtest-death-test.cc \
src/testing/gtest/src/gtest-filepath.cc \
src/testing/gtest/src/gtest-internal-inl.h \
src/testing/gtest/src/gtest-port.cc \
src/testing/gtest/src/gtest-printers.cc \
src/testing/gtest/src/gtest-test-part.cc \
src/testing/gtest/src/gtest-typed-test.cc \
src/testing/include/gmock/gmock.h \
src/testing/include/gmock/gmock-actions.h \
src/testing/include/gmock/gmock-cardinalities.h \
src/testing/include/gmock/gmock-generated-actions.h \
src/testing/include/gmock/gmock-generated-function-mockers.h \
src/testing/include/gmock/gmock-generated-matchers.h \
src/testing/include/gmock/gmock-generated-nice-strict.h \
src/testing/include/gmock/gmock-matchers.h \
src/testing/include/gmock/gmock-more-actions.h \
src/testing/include/gmock/gmock-more-matchers.h \
src/testing/include/gmock/gmock-spec-builders.h \
src/testing/include/gmock/internal/gmock-generated-internal-utils.h \
src/testing/include/gmock/internal/gmock-internal-utils.h \
src/testing/include/gmock/internal/gmock-port.h \
src/testing/src/gmock.cc \
src/testing/src/gmock-cardinalities.cc \
src/testing/src/gmock-internal-utils.cc \
src/testing/src/gmock-matchers.cc \
src/testing/src/gmock-spec-builders.cc \
src/testing/src/gmock_main.cc \
src/third_party/curl/COPYING \
src/third_party/curl/curlbuild.h \
src/third_party/curl/curl.h \
src/third_party/curl/curlrules.h \
src/third_party/curl/curlver.h \
src/third_party/curl/easy.h \
src/third_party/curl/mprintf.h \
src/third_party/curl/multi.h \
src/third_party/curl/stdcheaders.h \
src/third_party/curl/typecheck-gcc.h \
src/third_party/curl/types.h \
src/third_party/mac_headers/architecture/byte_order.h \
src/third_party/mac_headers/i386/_types.h \
src/third_party/mac_headers/mach/boolean.h \
src/third_party/mac_headers/mach/i386/boolean.h \
src/third_party/mac_headers/mach/i386/vm_param.h \
src/third_party/mac_headers/mach/i386/vm_types.h \
src/third_party/mac_headers/mach/machine/boolean.h \
src/third_party/mac_headers/mach/machine.h \
src/third_party/mac_headers/mach/machine/thread_state.h \
src/third_party/mac_headers/mach/machine/thread_status.h \
src/third_party/mac_headers/mach/machine/vm_types.h \
src/third_party/mac_headers/mach-o/arch.h \
src/third_party/mac_headers/mach-o/fat.h \
src/third_party/mac_headers/mach-o/loader.h \
src/third_party/mac_headers/mach-o/nlist.h \
src/third_party/mac_headers/mach/thread_status.h \
src/third_party/mac_headers/mach/vm_prot.h \
src/third_party/mac_headers/README \
src/third_party/musl/README \
src/third_party/musl/COPYRIGHT \
src/third_party/musl/README.breakpad \
src/third_party/musl/VERSION \
src/third_party/musl/include/elf.h \
src/tools/mac/crash_report/crash_report.mm \
src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj \
src/tools/mac/crash_report/on_demand_symbol_supplier.h \
@ -3109,15 +3331,20 @@ EXTRA_DIST = \
src/tools/solaris/dump_syms/testdata/dump_syms_regtest.sym \
src/tools/windows/converter/ms_symbol_server_converter.cc \
src/tools/windows/converter/ms_symbol_server_converter.h \
src/tools/windows/converter/ms_symbol_server_converter.vcproj \
src/tools/windows/converter/ms_symbol_server_converter.gyp \
src/tools/windows/dump_syms/dump_syms.cc \
src/tools/windows/dump_syms/dump_syms.vcproj \
src/tools/windows/dump_syms/dump_syms.gyp \
src/tools/windows/dump_syms/run_regtest.sh \
src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc \
src/tools/windows/dump_syms/testdata/dump_syms_regtest.pdb \
src/tools/windows/dump_syms/testdata/dump_syms_regtest.sym \
src/tools/windows/dump_syms/testdata/dump_syms_regtest64.sym \
src/tools/windows/dump_syms/testdata/omap_reorder_bbs.sym \
src/tools/windows/dump_syms/testdata/omap_reorder_funcs.sym \
src/tools/windows/dump_syms/testdata/omap_stretched.sym \
src/tools/windows/dump_syms/testdata/omap_stretched_filled.sym \
src/tools/windows/symupload/symupload.cc \
src/tools/windows/symupload/symupload.vcproj
src/tools/windows/symupload/symupload.gyp
all: all-am
@ -3773,6 +4000,9 @@ src/common/dwarf/src_common_dumper_unittest-dwarf2diehandler_unittest.$(OBJEXT):
src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/src_common_dumper_unittest-elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
@ -3879,6 +4109,9 @@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2diehandler.$(OBJEXT)
src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/mac/$(am__dirstamp):
@$(MKDIR_P) src/common/mac
@: > src/common/mac/$(am__dirstamp)
@ -4050,6 +4283,13 @@ src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.$(
src/processor/proc_maps_linux_unittest$(EXEEXT): $(src_processor_proc_maps_linux_unittest_OBJECTS) $(src_processor_proc_maps_linux_unittest_DEPENDENCIES) $(EXTRA_src_processor_proc_maps_linux_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/proc_maps_linux_unittest$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_proc_maps_linux_unittest_OBJECTS) $(src_processor_proc_maps_linux_unittest_LDADD) $(LIBS)
src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
src/processor/range_map_shrink_down_unittest$(EXEEXT): $(src_processor_range_map_shrink_down_unittest_OBJECTS) $(src_processor_range_map_shrink_down_unittest_DEPENDENCIES) $(EXTRA_src_processor_range_map_shrink_down_unittest_DEPENDENCIES) src/processor/$(am__dirstamp)
@rm -f src/processor/range_map_shrink_down_unittest$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(src_processor_range_map_shrink_down_unittest_OBJECTS) $(src_processor_range_map_shrink_down_unittest_LDADD) $(LIBS)
src/processor/range_map_unittest.$(OBJEXT): \
src/processor/$(am__dirstamp) \
src/processor/$(DEPDIR)/$(am__dirstamp)
@ -4211,6 +4451,9 @@ src/common/dwarf/dwarf2diehandler.$(OBJEXT): \
src/common/dwarf/dwarf2reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/linux/crc32.$(OBJEXT): src/common/linux/$(am__dirstamp) \
src/common/linux/$(DEPDIR)/$(am__dirstamp)
src/common/linux/dump_symbols.$(OBJEXT): \
@ -4268,6 +4511,9 @@ src/tools/linux/symupload/minidump_upload.$(OBJEXT): \
src/tools/linux/symupload/minidump_upload$(EXEEXT): $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_DEPENDENCIES) $(EXTRA_src_tools_linux_symupload_minidump_upload_DEPENDENCIES) src/tools/linux/symupload/$(am__dirstamp)
@rm -f src/tools/linux/symupload/minidump_upload$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(src_tools_linux_symupload_minidump_upload_OBJECTS) $(src_tools_linux_symupload_minidump_upload_LDADD) $(LIBS)
src/common/linux/symbol_upload.$(OBJEXT): \
src/common/linux/$(am__dirstamp) \
src/common/linux/$(DEPDIR)/$(am__dirstamp)
src/tools/linux/symupload/sym_upload.$(OBJEXT): \
src/tools/linux/symupload/$(am__dirstamp) \
src/tools/linux/symupload/$(DEPDIR)/$(am__dirstamp)
@ -4308,6 +4554,9 @@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.$(OBJEXT
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.$(OBJEXT): \
src/common/dwarf/$(am__dirstamp) \
src/common/dwarf/$(DEPDIR)/$(am__dirstamp)
src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.$(OBJEXT): \
src/common/mac/$(am__dirstamp) \
src/common/mac/$(DEPDIR)/$(am__dirstamp)
@ -4458,6 +4707,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2diehandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-bytereader_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-cfi_assembler.Po@am__quote@
@ -4466,13 +4716,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-cfi_assembler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2diehandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-bytereader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2diehandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/crc32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dump_symbols.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_core_dump.Po@am__quote@
@ -4503,6 +4756,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-safe_readlink_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/symbol_upload.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/tests/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-crash_generator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/tests/$(DEPDIR)/src_common_dumper_unittest-crash_generator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Po@am__quote@
@ -4572,6 +4826,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-stackwalker_address_list_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_amd64_unittest-stackwalker_amd64_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_stackwalker_arm64_unittest-stackwalker_arm64_unittest.Po@am__quote@
@ -5432,6 +5687,20 @@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj: src/common/dwarf/d
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
src/common/dwarf/src_common_dumper_unittest-elf_reader.o: src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_dumper_unittest-elf_reader.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_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
src/common/dwarf/src_common_dumper_unittest-elf_reader.obj: src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_dumper_unittest-elf_reader.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_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o: src/common/dwarf/dwarf2reader_cfi_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.o `test -f 'src/common/dwarf/dwarf2reader_cfi_unittest.cc' || echo '$(srcdir)/'`src/common/dwarf/dwarf2reader_cfi_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Tpo src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po
@ -5908,6 +6177,20 @@ src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj: src/comm
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o: src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.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_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj: src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_common_mac_macho_reader_unittest-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.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_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_mac_macho_reader_unittest-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o: src/common/mac/arch_utilities.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_mac_macho_reader_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo -c -o src/common/mac/src_common_mac_macho_reader_unittest-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_common_mac_macho_reader_unittest-arch_utilities.Po
@ -6230,6 +6513,20 @@ src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.ob
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_proc_maps_linux_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_proc_maps_linux_unittest-proc_maps_linux_unittest.obj `if test -f 'src/processor/proc_maps_linux_unittest.cc'; then $(CYGPATH_W) 'src/processor/proc_maps_linux_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/proc_maps_linux_unittest.cc'; fi`
src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o: src/processor/range_map_shrink_down_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o `test -f 'src/processor/range_map_shrink_down_unittest.cc' || echo '$(srcdir)/'`src/processor/range_map_shrink_down_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/range_map_shrink_down_unittest.cc' object='src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_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_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.o `test -f 'src/processor/range_map_shrink_down_unittest.cc' || echo '$(srcdir)/'`src/processor/range_map_shrink_down_unittest.cc
src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj: src/processor/range_map_shrink_down_unittest.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj `if test -f 'src/processor/range_map_shrink_down_unittest.cc'; then $(CYGPATH_W) 'src/processor/range_map_shrink_down_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/range_map_shrink_down_unittest.cc'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Tpo src/processor/$(DEPDIR)/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/processor/range_map_shrink_down_unittest.cc' object='src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_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_processor_range_map_shrink_down_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_range_map_shrink_down_unittest-range_map_shrink_down_unittest.obj `if test -f 'src/processor/range_map_shrink_down_unittest.cc'; then $(CYGPATH_W) 'src/processor/range_map_shrink_down_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/range_map_shrink_down_unittest.cc'; fi`
src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o: src/common/test_assembler.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_stackwalker_address_list_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o -MD -MP -MF src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo -c -o src/common/src_processor_stackwalker_address_list_unittest-test_assembler.o `test -f 'src/common/test_assembler.cc' || echo '$(srcdir)/'`src/common/test_assembler.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Tpo src/common/$(DEPDIR)/src_processor_stackwalker_address_list_unittest-test_assembler.Po
@ -6692,6 +6989,20 @@ src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj: src/com
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-dwarf2reader.obj `if test -f 'src/common/dwarf/dwarf2reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader.cc'; fi`
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o: src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.o `test -f 'src/common/dwarf/elf_reader.cc' || echo '$(srcdir)/'`src/common/dwarf/elf_reader.cc
src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj: src/common/dwarf/elf_reader.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj -MD -MP -MF src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Tpo src/common/dwarf/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/dwarf/elf_reader.cc' object='src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.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) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_tools_mac_dump_syms_dump_syms_mac-elf_reader.obj `if test -f 'src/common/dwarf/elf_reader.cc'; then $(CYGPATH_W) 'src/common/dwarf/elf_reader.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/elf_reader.cc'; fi`
src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o: src/common/mac/arch_utilities.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_tools_mac_dump_syms_dump_syms_mac_CXXFLAGS) $(CXXFLAGS) -MT src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o -MD -MP -MF src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo -c -o src/common/mac/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.o `test -f 'src/common/mac/arch_utilities.cc' || echo '$(srcdir)/'`src/common/mac/arch_utilities.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Tpo src/common/mac/$(DEPDIR)/src_tools_mac_dump_syms_dump_syms_mac-arch_utilities.Po
@ -7368,6 +7679,13 @@ src/processor/proc_maps_linux_unittest.log: src/processor/proc_maps_linux_unitte
--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/range_map_shrink_down_unittest.log: src/processor/range_map_shrink_down_unittest$(EXEEXT)
@p='src/processor/range_map_shrink_down_unittest$(EXEEXT)'; \
b='src/processor/range_map_shrink_down_unittest'; \
$(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/range_map_unittest.log: src/processor/range_map_unittest$(EXEEXT)
@p='src/processor/range_map_unittest$(EXEEXT)'; \
b='src/processor/range_map_unittest'; \

View File

@ -6,7 +6,7 @@ on Android, and later generate valid stack traces from the minidumps
it generates.
This release supports ARM, x86 and MIPS based Android systems.
This release requires NDK release r10c or higher.
This release requires NDK release r11c or higher.
I. Building the client library:
===============================
@ -58,7 +58,7 @@ II. Using the client library in Android:
========================================
The usage instructions are very similar to the Linux ones that are
found at http://code.google.com/p/google-breakpad/wiki/LinuxStarterGuide
found at https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/linux_starter_guide.md
1/ You need to include "client/linux/handler/exception_handler.h" from a C++
source file.

View File

@ -8,42 +8,73 @@ crash-reporting system.
* [Bugs](https://bugs.chromium.org/p/google-breakpad/)
* Discussion/Questions: [google-breakpad-discuss@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-discuss)
* Developer/Reviews: [google-breakpad-dev@googlegroups.com](https://groups.google.com/d/forum/google-breakpad-dev)
* Tests: [![Build Status](https://travis-ci.org/google/breakpad.svg?branch=master)](https://travis-ci.org/google/breakpad)
## Getting started in 32-bit mode (from trunk)
## Getting started (from master)
```sh
# Configure
CXXFLAGS=-m32 CFLAGS=-m32 CPPFLAGS=-m32 ./configure
# Build
make
# Test
make check
# Install
make install
```
1. First, [download depot_tools](http://dev.chromium.org/developers/how-tos/install-depot-tools)
and ensure that they're in your `PATH`.
2. Create a new directory for checking out the source code (it must be named
breakpad).
```sh
mkdir breakpad && cd breakpad
```
3. Run the `fetch` tool from depot_tools to download all the source repos.
```sh
fetch breakpad
cd src
```
4. Build the source.
```sh
./configure && make
```
You can also cd to another directory and run configure from there to build
outside the source tree.
This will build the processor tools (`src/processor/minidump_stackwalk`,
`src/processor/minidump_dump`, etc), and when building on Linux it will
also build the client libraries and some tools
(`src/tools/linux/dump_syms/dump_syms`,
`src/tools/linux/md2core/minidump-2-core`, etc).
5. Optionally, run tests.
```sh
make check
```
6. Optionally, install the built libraries
```sh
make install
```
If you need to reconfigure your build be sure to run `make distclean` first.
## To request change review:
To update an existing checkout to a newer revision, you can
`git pull` as usual, but then you should run `gclient sync` to ensure that the
dependent repos are up-to-date.
1. Get a copy of depot_tools repo.
http://dev.chromium.org/developers/how-tos/install-depot-tools
## To request change review
2. Create a new directory for checking out the source code.
mkdir breakpad && cd breakpad
1. Follow the steps above to get the source and build it.
3. Run the `fetch` tool from depot_tools to download all the source repos.
`fetch breakpad`
4. Make changes. Build and test your changes.
2. Make changes. Build and test your changes.
For core code like processor use methods above.
For linux/mac/windows, there are test targets in each project file.
5. Commit your changes to your local repo and upload them to the server.
3. Commit your changes to your local repo and upload them to the server.
http://dev.chromium.org/developers/contributing-code
e.g. `git commit ... && git cl upload ...`
You will be prompted for credential and a description.
6. At https://codereview.chromium.org/ you'll find your issue listed; click on
4. At https://codereview.chromium.org/ you'll find your issue listed; click on
it, and select Publish+Mail, and enter in the code reviewer and CC
google-breakpad-dev@googlegroups.com

View File

@ -71,9 +71,12 @@ LOCAL_ARM_MODE := arm
# List of client source files, directly taken from Makefile.am
LOCAL_SRC_FILES := \
src/client/linux/crash_generation/crash_generation_client.cc \
src/client/linux/dump_writer_common/thread_info.cc \
src/client/linux/dump_writer_common/ucontext_reader.cc \
src/client/linux/handler/exception_handler.cc \
src/client/linux/handler/minidump_descriptor.cc \
src/client/linux/log/log.cc \
src/client/linux/microdump_writer/microdump_writer.cc \
src/client/linux/minidump_writer/linux_dumper.cc \
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
src/client/linux/minidump_writer/minidump_writer.cc \

View File

@ -29,3 +29,4 @@
APP_STL := stlport_static
APP_ABI := all
APP_CXXFLAGS := -std=c++11 -D__STDC_LIMIT_MACROS

View File

@ -14,76 +14,85 @@ necessary to produce minidumps from an application.
First, configure your build process to link **libbreakpad\_client.a** into your
binary, and set your include paths to include the **src** directory in the
**google-breakpad** source tree. Next, include the exception handler header: ```
# include "client/linux/handler/exception_handler.h"
**google-breakpad** source tree. Next, include the exception handler header:
```cpp
#include "client/linux/handler/exception_handler.h"
```
Now you can instantiate an `ExceptionHandler` object. Exception handling is active for the lifetime of the `ExceptionHandler` object, so you should instantiate it as early as possible in your application's startup process, and keep it alive for as close to shutdown as possible. To do anything useful, the `ExceptionHandler` constructor requires a path where it can write minidumps, as well as a callback function to receive information about minidumps that were written:
```
```cpp
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* context, bool succeeded) { printf("Dump path: %s\n", descriptor.path());
return succeeded; }
void* context, bool succeeded) {
printf("Dump path: %s\n", descriptor.path());
return succeeded;
}
void crash() { volatile int* a = (int*)(NULL); *a = 1; }
int main(int argc, char* argv[]) { google_breakpad::MinidumpDescriptor
descriptor("/tmp"); google_breakpad::ExceptionHandler eh(descriptor, NULL,
dumpCallback, NULL, true, -1); crash(); return 0; } ```
int main(int argc, char* argv[]) {
google_breakpad::MinidumpDescriptor descriptor("/tmp");
google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);
crash();
return 0;
}
```
Compiling and running this example should produce a minidump file in /tmp, and
it should print the minidump filename before exiting. You can read more about
the other parameters to the `ExceptionHandler` constructor <a
href='http://code.google.com/p/google-breakpad/source/browse/trunk/src/client/linux/handler/exception_handler.h'>in
the exception_handler.h source file</a>.
the other parameters to the `ExceptionHandler` constructor [in the exception_handler.h source file][1].
[1]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/client/linux/handler/exception_handler.h
**Note**: You should do as little work as possible in the callback function.
Your application is in an unsafe state. It may not be safe to allocate memory or
call functions from other shared libraries. The safest thing to do is `fork` and
`exec` a new process to do any work you need to do. If you must do some work in
the callback, the Breakpad source contains <a
href='http://code.google.com/p/google-breakpad/source/browse/trunk/src/common/linux/linux_libc_support.h'>some
simple reimplementations of libc functions</a>, to avoid calling directly into
libc, as well as <a href='http://code.google.com/p/linux-syscall-support/'>a
header file for making Linux system calls</a> (in **src/third\_party/lss**) to
avoid calling into other shared libraries.
the callback, the Breakpad source contains [some simple reimplementations of libc functions][2], to avoid calling directly into
libc, as well as [a header file for making Linux system calls][3] (in **src/third\_party/lss**) to avoid calling into other shared libraries.
[2]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/common/linux/linux_libc_support.h
[3]: https://chromium.googlesource.com/linux-syscall-support/+/master
## Sending the minidump file
In a real application, you would want to handle the minidump in some way, likely
by sending it to a server for analysis. The Breakpad source tree contains <a
href='http://code.google.com/p/google-breakpad/source/browse/#svn/trunk/src/common/linux'>some
HTTP upload source</a> that you might find useful, as well as <a
href='http://code.google.com/p/google-breakpad/source/browse/#svn/trunk/src/tools/linux/symupload'>a
minidump upload tool</a>.
by sending it to a server for analysis. The Breakpad source tree contains [some
HTTP upload source][4] that you might find useful, as well as [a minidump upload tool][5].
[4]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/common/linux/http_upload.h
[5]: https://chromium.googlesource.com/breakpad/breakpad/+/master/src/tools/linux/symupload/minidump_upload.cc
## Producing symbols for your application
To produce useful stack traces, Breakpad requires you to convert the debugging
symbols in your binaries to <a
href='http://code.google.com/p/google-breakpad/wiki/SymbolFiles'>text-format
symbol files</a>. First, ensure that you've compiled your binaries with `-g` to
symbols in your binaries to [text-format symbol files][6]. First, ensure that you've compiled your binaries with `-g` to
include debugging symbols. Next, compile the `dump_syms` tool by running
`configure && make` in the Breakpad source directory. Next, run `dump_syms` on
your binaries to produce the text-format symbols. For example, if your main
binary was named `test`: `$ google-breakpad/src/tools/linux/dump_syms/dump_syms
./test > test.sym
`
binary was named `test`:
[6]: https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
```
$ google-breakpad/src/tools/linux/dump_syms/dump_syms ./test > test.sym
```
In order to use these symbols with the `minidump_stackwalk` tool, you will need
to place them in a specific directory structure. The first line of the symbol
file contains the information you need to produce this directory structure, for
example (your output will vary): `$ head -n1 test.sym MODULE Linux x86_64
6EDC6ACDB282125843FD59DA9C81BD830 test $ mkdir -p
./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830 $ mv test.sym
./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
`
example (your output will vary):
You may also find the <a
href='http://mxr.mozilla.org/mozilla-central/source/toolkit/crashreporter/tools/symbolstore.py'>symbolstore.py</a>
script in the Mozilla repository useful, as it encapsulates these steps.
```
$ head -n1 test.sym MODULE Linux x86_64 6EDC6ACDB282125843FD59DA9C81BD830 test
$ mkdir -p ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
$ mv test.sym ./symbols/test/6EDC6ACDB282125843FD59DA9C81BD830
```
You may also find the [symbolstore.py][7] script in the Mozilla repository useful, as it encapsulates these steps.
[7]: https://dxr.mozilla.org/mozilla-central/source/toolkit/crashreporter/tools/symbolstore.py
## Processing the minidump to produce a stack trace
@ -92,6 +101,10 @@ plus its corresponding text-format symbols and produce a symbolized stacktrace.
It should be in the **google-breakpad/src/processor** directory if you compiled
the Breakpad source using the directions above. Simply pass it the minidump and
the symbol path as commandline parameters:
`google-breakpad/src/processor/minidump_stackwalk minidump.dmp ./symbols
` It produces verbose output on stderr, and the stacktrace on stdout, so you may
```
$ google-breakpad/src/processor/minidump_stackwalk minidump.dmp ./symbols
```
It produces verbose output on stderr, and the stacktrace on stdout, so you may
want to redirect stderr.

43
scripts/travis-build.sh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/sh
set -ex
setup_env() {
# Travis sets CC/CXX to the system toolchain, so our .travis.yml
# exports USE_{CC,CXX} for this script to use.
if [ -n "$USE_CC" ]; then
export CC=$USE_CC
fi
if [ -n "$USE_CXX" ]; then
export CXX=$USE_CXX
fi
# Use -jN for faster builds. Travis build machines under Docker
# have a lot of cores, but are memory-limited, so the kernel
# will OOM if we try to use them all, so use at most 4.
# See https://github.com/travis-ci/travis-ci/issues/1972
export NCPUS=$(getconf _NPROCESSORS_ONLN)
export JOBS=$(( $NCPUS < 4 ? $NCPUS : 4 ))
}
# Do an in-tree build and make sure tests pass.
build() {
./configure
make -j${JOBS} check VERBOSE=1
make distclean
}
# Do an out-of-tree build and make sure we can create a release tarball.
build_out_of_tree() {
mkdir -p build/native
cd build/native
../../configure
make -j${JOBS} distcheck VERBOSE=1
}
main() {
setup_env
build
build_out_of_tree
}
main "$@"

24
scripts/travis-checkout.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh
set -ex
get_depot_tools() {
cd
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
PATH="$HOME/depot_tools:$PATH"
}
gclient_sync() {
# Rename the source dir to match what gclient expects.
srcdir=$(basename "$TRAVIS_BUILD_DIR")
cd "${TRAVIS_BUILD_DIR}"/..
mv "${srcdir}" src
gclient config --unmanaged https://github.com/google/breakpad.git
gclient sync
}
main() {
get_depot_tools
gclient_sync
}
main "$@"

View File

@ -118,7 +118,7 @@ namespace {
// all these signals must be Core (see man 7 signal) because we rethrow the
// signal after handling it and expect that it'll be fatal.
const int kExceptionSignals[] = {
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP
};
const int kNumHandledSignals =
sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]);

View File

@ -45,7 +45,6 @@
#include "client/linux/handler/exception_handler.h"
#include "client/linux/minidump_writer/minidump_writer.h"
#include "common/linux/eintr_wrapper.h"
#include "common/linux/file_id.h"
#include "common/linux/ignore_ret.h"
#include "common/linux/linux_libc_support.h"
#include "common/tests/auto_tempdir.h"
@ -94,10 +93,6 @@ void FlushInstructionCache(const char* memory, uint32_t memory_size) {
#endif
}
// Length of a formatted GUID string =
// sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator)
const int kGUIDStringSize = 37;
void sigchld_handler(int signo) { }
int CreateTMPFile(const string& dir, string* path) {
@ -817,19 +812,7 @@ TEST(ExceptionHandlerTest, ModuleInfo) {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
char module_identifier_buffer[kGUIDStringSize];
FileID::ConvertIdentifierToString(kModuleGUID,
module_identifier_buffer,
sizeof(module_identifier_buffer));
string module_identifier(module_identifier_buffer);
// Strip out dashes
size_t pos;
while ((pos = module_identifier.find('-')) != string::npos) {
module_identifier.erase(pos, 1);
}
// And append a zero, because module IDs include an "age" field
// which is always zero on Linux.
module_identifier += "0";
const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
// Get some memory.
char* memory =

View File

@ -32,6 +32,8 @@
#include "client/linux/microdump_writer/microdump_writer.h"
#include <limits>
#include <sys/utsname.h>
#include "client/linux/dump_writer_common/thread_info.h"
@ -40,11 +42,15 @@
#include "client/linux/handler/microdump_extra_info.h"
#include "client/linux/log/log.h"
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
#include "common/linux/file_id.h"
#include "common/linux/linux_libc_support.h"
#include "common/memory.h"
namespace {
using google_breakpad::auto_wasteful_vector;
using google_breakpad::ExceptionHandler;
using google_breakpad::kDefaultBuildIdSize;
using google_breakpad::LinuxDumper;
using google_breakpad::LinuxPtraceDumper;
using google_breakpad::MappingInfo;
@ -56,6 +62,72 @@ using google_breakpad::UContextReader;
const size_t kLineBufferSize = 2048;
#if !defined(__LP64__)
// The following are only used by DumpFreeSpace, so need to be compiled
// in conditionally in the same way.
template <typename Dst, typename Src>
Dst saturated_cast(Src src) {
if (src >= std::numeric_limits<Dst>::max())
return std::numeric_limits<Dst>::max();
if (src <= std::numeric_limits<Dst>::min())
return std::numeric_limits<Dst>::min();
return static_cast<Dst>(src);
}
int Log2Floor(uint64_t n) {
// Copied from chromium src/base/bits.h
if (n == 0)
return -1;
int log = 0;
uint64_t value = n;
for (int i = 5; i >= 0; --i) {
int shift = (1 << i);
uint64_t x = value >> shift;
if (x != 0) {
value = x;
log += shift;
}
}
assert(value == 1u);
return log;
}
bool MappingsAreAdjacent(const MappingInfo& a, const MappingInfo& b) {
// Because of load biasing, we can end up with a situation where two
// mappings actually overlap. So we will define adjacency to also include a
// b start address that lies within a's address range (including starting
// immediately after a).
// Because load biasing only ever moves the start address backwards, the end
// address should still increase.
return a.start_addr <= b.start_addr && a.start_addr + a.size >= b.start_addr;
}
bool MappingLessThan(const MappingInfo* a, const MappingInfo* b) {
// Return true if mapping a is before mapping b.
// For the same reason (load biasing) we compare end addresses, which - unlike
// start addresses - will not have been modified.
return a->start_addr + a->size < b->start_addr + b->size;
}
size_t NextOrderedMapping(
const google_breakpad::wasteful_vector<MappingInfo*>& mappings,
size_t curr) {
// Find the mapping that directly follows mappings[curr].
// If no such mapping exists, return |invalid| to indicate this.
const size_t invalid = std::numeric_limits<size_t>::max();
size_t best = invalid;
for (size_t next = 0; next < mappings.size(); ++next) {
if (MappingLessThan(mappings[curr], mappings[next]) &&
(best == invalid || MappingLessThan(mappings[next], mappings[best]))) {
best = next;
}
}
return best;
}
#endif // !__LP64__
class MicrodumpWriter {
public:
MicrodumpWriter(const ExceptionHandler::CrashContext* context,
@ -93,6 +165,9 @@ class MicrodumpWriter {
DumpProductInformation();
DumpOSInformation();
DumpGPUInformation();
#if !defined(__LP64__)
DumpFreeSpace();
#endif
success = DumpCrashingThread();
if (success)
success = DumpMappings();
@ -336,21 +411,31 @@ class MicrodumpWriter {
bool member,
unsigned int mapping_id,
const uint8_t* identifier) {
MDGUID module_identifier;
auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier_bytes(
dumper_->allocator());
if (identifier) {
// GUID was provided by caller.
my_memcpy(&module_identifier, identifier, sizeof(MDGUID));
identifier_bytes.insert(identifier_bytes.end(),
identifier,
identifier + sizeof(MDGUID));
} else {
dumper_->ElfFileIdentifierForMapping(
mapping,
member,
mapping_id,
reinterpret_cast<uint8_t*>(&module_identifier));
identifier_bytes);
}
// Copy as many bytes of |identifier| as will fit into a MDGUID
MDGUID module_identifier = {0};
memcpy(&module_identifier, &identifier_bytes[0],
std::min(sizeof(MDGUID), identifier_bytes.size()));
char file_name[NAME_MAX];
char file_path[NAME_MAX];
LinuxDumper::GetMappingEffectiveNameAndPath(
dumper_->GetMappingEffectiveNameAndPath(
mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
LogAppend("M ");
@ -376,6 +461,80 @@ class MicrodumpWriter {
LogCommitLine();
}
#if !defined(__LP64__)
void DumpFreeSpace() {
const google_breakpad::wasteful_vector<MappingInfo*>& mappings =
dumper_->mappings();
if (mappings.size() == 0) return;
// This is complicated by the fact that mappings is not in order. It should
// be mostly in order, however the mapping that contains the entry point for
// the process is always at the front of the vector.
static const int HBITS = sizeof(size_t) * 8;
size_t hole_histogram[HBITS];
my_memset(hole_histogram, 0, sizeof(hole_histogram));
// Find the lowest address mapping.
size_t curr = 0;
for (size_t i = 1; i < mappings.size(); ++i) {
if (mappings[i]->start_addr < mappings[curr]->start_addr) curr = i;
}
uintptr_t lo_addr = mappings[curr]->start_addr;
size_t hole_cnt = 0;
size_t hole_max = 0;
size_t hole_sum = 0;
while (true) {
// Skip to the end of an adjacent run of mappings. This is an optimization
// for the fact that mappings is mostly sorted.
while (curr != mappings.size() - 1 &&
MappingsAreAdjacent(*mappings[curr], *mappings[curr + 1])) {
++curr;
}
size_t next = NextOrderedMapping(mappings, curr);
if (next == std::numeric_limits<size_t>::max())
break;
uintptr_t hole_lo = mappings[curr]->start_addr + mappings[curr]->size;
uintptr_t hole_hi = mappings[next]->start_addr;
if (hole_hi > hole_lo) {
size_t hole_sz = hole_hi - hole_lo;
hole_sum += hole_sz;
hole_max = std::max(hole_sz, hole_max);
++hole_cnt;
++hole_histogram[Log2Floor(hole_sz)];
}
curr = next;
}
uintptr_t hi_addr = mappings[curr]->start_addr + mappings[curr]->size;
LogAppend("H ");
LogAppend(lo_addr);
LogAppend(" ");
LogAppend(hi_addr);
LogAppend(" ");
LogAppend(saturated_cast<uint16_t>(hole_cnt));
LogAppend(" ");
LogAppend(hole_max);
LogAppend(" ");
LogAppend(hole_sum);
for (unsigned int i = 0; i < HBITS; ++i) {
if (!hole_histogram[i]) continue;
LogAppend(" ");
LogAppend(saturated_cast<uint8_t>(i));
LogAppend(":");
LogAppend(saturated_cast<uint8_t>(hole_histogram[i]));
}
LogCommitLine();
}
#endif
// Write information about the mappings in effect.
bool DumpMappings() {
// First write all the mappings from the dumper

View File

@ -49,8 +49,9 @@ namespace google_breakpad {
LinuxCoreDumper::LinuxCoreDumper(pid_t pid,
const char* core_path,
const char* procfs_path)
: LinuxDumper(pid),
const char* procfs_path,
const char* root_prefix)
: LinuxDumper(pid, root_prefix),
core_path_(core_path),
procfs_path_(procfs_path),
thread_infos_(&allocator_, 8) {

View File

@ -47,7 +47,9 @@ class LinuxCoreDumper : public LinuxDumper {
// its proc files at |procfs_path|. If |procfs_path| is a copy of
// /proc/<pid>, it should contain the following files:
// auxv, cmdline, environ, exe, maps, status
LinuxCoreDumper(pid_t pid, const char* core_path, const char* procfs_path);
// See LinuxDumper for the purpose of |root_prefix|.
LinuxCoreDumper(pid_t pid, const char* core_path, const char* procfs_path,
const char* root_prefix = "");
// Implements LinuxDumper::BuildProcPath().
// Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).

View File

@ -39,6 +39,16 @@
using namespace google_breakpad;
TEST(LinuxCoreDumperTest, GetMappingAbsolutePath) {
const LinuxCoreDumper dumper(getpid(), "core", "/tmp", "/mnt/root");
const MappingInfo mapping = { 0, 0, 0, false, "/usr/lib/libc.so" };
char path[PATH_MAX];
dumper.GetMappingAbsolutePath(mapping, path);
EXPECT_STREQ("/mnt/root/usr/lib/libc.so", path);
}
TEST(LinuxCoreDumperTest, BuildProcPath) {
const pid_t pid = getpid();
const char procfs_path[] = "/procfs_copy";

View File

@ -70,7 +70,6 @@ static const int DT_ANDROID_RELA = DT_LOOS + 4;
static const char kMappedFileUnsafePrefix[] = "/dev/";
static const char kDeletedSuffix[] = " (deleted)";
static const char kReservedFlags[] = " ---p";
inline static bool IsMappedFileOpenUnsafe(
const google_breakpad::MappingInfo& mapping) {
@ -88,14 +87,16 @@ namespace google_breakpad {
// All interesting auvx entry types are below AT_SYSINFO_EHDR
#define AT_MAX AT_SYSINFO_EHDR
LinuxDumper::LinuxDumper(pid_t pid)
LinuxDumper::LinuxDumper(pid_t pid, const char* root_prefix)
: pid_(pid),
root_prefix_(root_prefix),
crash_address_(0),
crash_signal_(0),
crash_thread_(pid),
threads_(&allocator_, 8),
mappings_(&allocator_),
auxv_(&allocator_, AT_MAX + 1) {
assert(root_prefix_ && my_strlen(root_prefix_) < PATH_MAX);
// The passed-in size to the constructor (above) is only a hint.
// Must call .resize() to do actual initialization of the elements.
auxv_.resize(AT_MAX + 1);
@ -119,9 +120,8 @@ bool
LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
bool member,
unsigned int mapping_id,
uint8_t identifier[sizeof(MDGUID)]) {
wasteful_vector<uint8_t>& identifier) {
assert(!member || mapping_id < mappings_.size());
my_memset(identifier, 0, sizeof(MDGUID));
if (IsMappedFileOpenUnsafe(mapping))
return false;
@ -139,14 +139,9 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
return FileID::ElfFileIdentifierFromMappedFile(linux_gate, identifier);
}
char filename[NAME_MAX];
size_t filename_len = my_strlen(mapping.name);
if (filename_len >= NAME_MAX) {
assert(false);
char filename[PATH_MAX];
if (!GetMappingAbsolutePath(mapping, filename))
return false;
}
my_memcpy(filename, mapping.name, filename_len);
filename[filename_len] = '\0';
bool filename_modified = HandleDeletedFileInMapping(filename);
MemoryMappedFile mapped_file(filename, mapping.offset);
@ -156,13 +151,19 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
bool success =
FileID::ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
if (success && member && filename_modified) {
mappings_[mapping_id]->name[filename_len -
mappings_[mapping_id]->name[my_strlen(mapping.name) -
sizeof(kDeletedSuffix) + 1] = '\0';
}
return success;
}
bool LinuxDumper::GetMappingAbsolutePath(const MappingInfo& mapping,
char path[PATH_MAX]) const {
return my_strlcpy(path, root_prefix_, PATH_MAX) < PATH_MAX &&
my_strlcat(path, mapping.name, PATH_MAX) < PATH_MAX;
}
namespace {
bool ElfFileSoNameFromMappedFile(
const void* elf_base, char* soname, size_t soname_size) {
@ -212,23 +213,16 @@ bool ElfFileSoNameFromMappedFile(
// for |mapping|. If the SONAME is found copy it into the passed buffer
// |soname| and return true. The size of the buffer is |soname_size|.
// The SONAME will be truncated if it is too long to fit in the buffer.
bool ElfFileSoName(
bool ElfFileSoName(const LinuxDumper& dumper,
const MappingInfo& mapping, char* soname, size_t soname_size) {
if (IsMappedFileOpenUnsafe(mapping)) {
// Not safe
return false;
}
char filename[NAME_MAX];
size_t filename_len = my_strlen(mapping.name);
if (filename_len >= NAME_MAX) {
assert(false);
// name too long
char filename[PATH_MAX];
if (!dumper.GetMappingAbsolutePath(mapping, filename))
return false;
}
my_memcpy(filename, mapping.name, filename_len);
filename[filename_len] = '\0';
MemoryMappedFile mapped_file(filename, mapping.offset);
if (!mapped_file.data() || mapped_file.size() < SELFMAG) {
@ -242,7 +236,6 @@ bool ElfFileSoName(
} // namespace
// static
void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
char* file_path,
size_t file_path_size,
@ -255,8 +248,10 @@ void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
// apk on Android). We try to find the name of the shared object (SONAME) by
// looking in the file for ELF sections.
bool mapped_from_archive = false;
if (mapping.exec && mapping.offset != 0)
mapped_from_archive = ElfFileSoName(mapping, file_name, file_name_size);
if (mapping.exec && mapping.offset != 0) {
mapped_from_archive =
ElfFileSoName(*this, mapping, file_name, file_name_size);
}
if (mapped_from_archive) {
// Some tools (e.g., stackwalk) extract the basename from the pathname. In
@ -354,24 +349,8 @@ bool LinuxDumper::EnumerateMappings() {
MappingInfo* module = mappings_.back();
if ((start_addr == module->start_addr + module->size) &&
(my_strlen(name) == my_strlen(module->name)) &&
(my_strncmp(name, module->name, my_strlen(name)) == 0)) {
module->size = end_addr - module->start_addr;
line_reader->PopLine(line_len);
continue;
}
}
// Also merge mappings that result from address ranges that the
// linker reserved but which a loaded library did not use. These
// appear as an anonymous private mapping with no access flags set
// and which directly follow an executable mapping.
if (!name && !mappings_.empty()) {
MappingInfo* module = mappings_.back();
if ((start_addr == module->start_addr + module->size) &&
module->exec &&
module->name[0] == '/' &&
offset == 0 && my_strncmp(i2,
kReservedFlags,
sizeof(kReservedFlags) - 1) == 0) {
(my_strncmp(name, module->name, my_strlen(name)) == 0) &&
(exec == module->exec)) {
module->size = end_addr - module->start_addr;
line_reader->PopLine(line_len);
continue;
@ -580,10 +559,13 @@ bool LinuxDumper::HandleDeletedFileInMapping(char* path) const {
// Check |path| against the /proc/pid/exe 'symlink'.
char exe_link[NAME_MAX];
char new_path[NAME_MAX];
if (!BuildProcPath(exe_link, pid_, "exe"))
return false;
if (!SafeReadLink(exe_link, new_path))
MappingInfo new_mapping = {0};
if (!SafeReadLink(exe_link, new_mapping.name))
return false;
char new_path[PATH_MAX];
if (!GetMappingAbsolutePath(new_mapping, new_path))
return false;
if (my_strcmp(path, new_path) != 0)
return false;

View File

@ -49,6 +49,7 @@
#include "client/linux/dump_writer_common/mapping_info.h"
#include "client/linux/dump_writer_common/thread_info.h"
#include "common/linux/file_id.h"
#include "common/memory.h"
#include "google_breakpad/common/minidump_format.h"
@ -72,7 +73,9 @@ const char kLinuxGateLibraryName[] = "linux-gate.so";
class LinuxDumper {
public:
explicit LinuxDumper(pid_t pid);
// The |root_prefix| is prepended to mapping paths before opening them, which
// is useful if the crash originates from a chroot.
explicit LinuxDumper(pid_t pid, const char* root_prefix = "");
virtual ~LinuxDumper();
@ -127,7 +130,7 @@ class LinuxDumper {
bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
bool member,
unsigned int mapping_id,
uint8_t identifier[sizeof(MDGUID)]);
wasteful_vector<uint8_t>& identifier);
uintptr_t crash_address() const { return crash_address_; }
void set_crash_address(uintptr_t crash_address) {
@ -140,16 +143,21 @@ class LinuxDumper {
pid_t crash_thread() const { return crash_thread_; }
void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
// Concatenates the |root_prefix_| and |mapping| path. Writes into |path| and
// returns true unless the string is too long.
bool GetMappingAbsolutePath(const MappingInfo& mapping,
char path[PATH_MAX]) const;
// Extracts the effective path and file name of from |mapping|. In most cases
// the effective name/path are just the mapping's path and basename. In some
// other cases, however, a library can be mapped from an archive (e.g., when
// loading .so libs from an apk on Android) and this method is able to
// reconstruct the original file name.
static void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
char* file_path,
size_t file_path_size,
char* file_name,
size_t file_name_size);
void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
char* file_path,
size_t file_path_size,
char* file_name,
size_t file_name_size);
protected:
bool ReadAuxv();
@ -172,6 +180,9 @@ class LinuxDumper {
// ID of the crashed process.
const pid_t pid_;
// Path of the root directory to which mapping paths are relative.
const char* const root_prefix_;
// Virtual address at which the process crashed.
uintptr_t crash_address_;

View File

@ -66,6 +66,7 @@ using namespace google_breakpad;
namespace {
typedef wasteful_vector<uint8_t> id_vector;
typedef testing::Test LinuxPtraceDumperTest;
/* Fixture for running tests in a child process. */
@ -105,11 +106,17 @@ class LinuxPtraceDumperChildTest : public testing::Test {
* This is achieved by defining a TestBody macro further below.
*/
virtual void RealTestBody() = 0;
id_vector make_vector() {
return id_vector(&allocator, kDefaultBuildIdSize);
}
private:
static const int kFatalFailure = 1;
static const int kNonFatalFailure = 2;
pid_t child_pid_;
PageAllocator allocator;
};
} // namespace
@ -310,14 +317,15 @@ TEST_F(LinuxPtraceDumperChildTest, LinuxGateMappingID) {
// Need to suspend the child so ptrace actually works.
ASSERT_TRUE(dumper.ThreadsSuspend());
uint8_t identifier[sizeof(MDGUID)];
id_vector identifier(make_vector());
ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index],
true,
index,
identifier));
uint8_t empty_identifier[sizeof(MDGUID)];
memset(empty_identifier, 0, sizeof(empty_identifier));
EXPECT_NE(0, memcmp(empty_identifier, identifier, sizeof(identifier)));
id_vector empty_identifier(make_vector());
empty_identifier.resize(kDefaultBuildIdSize, 0);
EXPECT_NE(empty_identifier, identifier);
EXPECT_TRUE(dumper.ThreadsResume());
}
#endif
@ -343,19 +351,18 @@ TEST_F(LinuxPtraceDumperChildTest, FileIDsMatch) {
}
ASSERT_TRUE(found_exe);
uint8_t identifier1[sizeof(MDGUID)];
uint8_t identifier2[sizeof(MDGUID)];
id_vector identifier1(make_vector());
id_vector identifier2(make_vector());
EXPECT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[i], true, i,
identifier1));
FileID fileid(exe_name);
EXPECT_TRUE(fileid.ElfFileIdentifier(identifier2));
char identifier_string1[37];
char identifier_string2[37];
FileID::ConvertIdentifierToString(identifier1, identifier_string1,
37);
FileID::ConvertIdentifierToString(identifier2, identifier_string2,
37);
EXPECT_STREQ(identifier_string1, identifier_string2);
string identifier_string1 =
FileID::ConvertIdentifierToUUIDString(identifier1);
string identifier_string2 =
FileID::ConvertIdentifierToUUIDString(identifier2);
EXPECT_EQ(identifier_string1, identifier_string2);
}
/* Get back to normal behavior of TEST*() macros wrt TestBody. */

View File

@ -73,6 +73,7 @@
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
#include "client/linux/minidump_writer/proc_cpuinfo_reader.h"
#include "client/minidump_file_writer.h"
#include "common/linux/file_id.h"
#include "common/linux/linux_libc_support.h"
#include "common/minidump_type_helper.h"
#include "google_breakpad/common/minidump_format.h"
@ -81,8 +82,10 @@
namespace {
using google_breakpad::AppMemoryList;
using google_breakpad::auto_wasteful_vector;
using google_breakpad::ExceptionHandler;
using google_breakpad::CpuSet;
using google_breakpad::kDefaultBuildIdSize;
using google_breakpad::LineReader;
using google_breakpad::LinuxDumper;
using google_breakpad::LinuxPtraceDumper;
@ -272,6 +275,14 @@ class MinidumpWriter {
if (max_stack_len >= 0 &&
stack_len > static_cast<unsigned int>(max_stack_len)) {
stack_len = max_stack_len;
// Skip empty chunks of length max_stack_len.
uintptr_t int_stack = reinterpret_cast<uintptr_t>(stack);
if (max_stack_len > 0) {
while (int_stack + max_stack_len < stack_pointer) {
int_stack += max_stack_len;
}
}
stack = reinterpret_cast<const void*>(int_stack);
}
if (!memory.Allocate(stack_len))
return false;
@ -546,41 +557,40 @@ class MinidumpWriter {
mod->base_of_image = mapping.start_addr;
mod->size_of_image = mapping.size;
uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX];
uint8_t* cv_ptr = cv_buf;
auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier_bytes(
dumper_->allocator());
const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE;
my_memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
cv_ptr += sizeof(cv_signature);
uint8_t* signature = cv_ptr;
cv_ptr += sizeof(MDGUID);
if (identifier) {
// GUID was provided by caller.
my_memcpy(signature, identifier, sizeof(MDGUID));
identifier_bytes.insert(identifier_bytes.end(),
identifier,
identifier + sizeof(MDGUID));
} else {
// Note: ElfFileIdentifierForMapping() can manipulate the |mapping.name|.
dumper_->ElfFileIdentifierForMapping(mapping, member,
mapping_id, signature);
dumper_->ElfFileIdentifierForMapping(mapping,
member,
mapping_id,
identifier_bytes);
}
if (!identifier_bytes.empty()) {
UntypedMDRVA cv(&minidump_writer_);
if (!cv.Allocate(MDCVInfoELF_minsize + identifier_bytes.size()))
return false;
const uint32_t cv_signature = MD_CVINFOELF_SIGNATURE;
cv.Copy(&cv_signature, sizeof(cv_signature));
cv.Copy(cv.position() + sizeof(cv_signature), &identifier_bytes[0],
identifier_bytes.size());
mod->cv_record = cv.location();
}
my_memset(cv_ptr, 0, sizeof(uint32_t)); // Set age to 0 on Linux.
cv_ptr += sizeof(uint32_t);
char file_name[NAME_MAX];
char file_path[NAME_MAX];
LinuxDumper::GetMappingEffectiveNameAndPath(
dumper_->GetMappingEffectiveNameAndPath(
mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
const size_t file_name_len = my_strlen(file_name);
UntypedMDRVA cv(&minidump_writer_);
if (!cv.Allocate(MDCVInfoPDB70_minsize + file_name_len + 1))
return false;
// Write pdb_file_name
my_memcpy(cv_ptr, file_name, file_name_len + 1);
cv.Copy(cv_buf, MDCVInfoPDB70_minsize + file_name_len + 1);
mod->cv_record = cv.location();
MDLocationDescriptor ld;
if (!minidump_writer_.WriteString(file_path, my_strlen(file_path), &ld))
return false;

View File

@ -54,10 +54,6 @@
using namespace google_breakpad;
// Length of a formatted GUID string =
// sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator)
const int kGUIDStringSize = 37;
namespace {
typedef testing::Test MinidumpWriterTest;
@ -137,19 +133,7 @@ TEST(MinidumpWriterTest, MappingInfo) {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
char module_identifier_buffer[kGUIDStringSize];
FileID::ConvertIdentifierToString(kModuleGUID,
module_identifier_buffer,
sizeof(module_identifier_buffer));
string module_identifier(module_identifier_buffer);
// Strip out dashes
size_t pos;
while ((pos = module_identifier.find('-')) != string::npos) {
module_identifier.erase(pos, 1);
}
// And append a zero, because module IDs include an "age" field
// which is always zero on Linux.
module_identifier += "0";
const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
// Get some memory.
char* memory =
@ -230,6 +214,53 @@ TEST(MinidumpWriterTest, MappingInfo) {
close(fds[1]);
}
// Test that a binary with a longer-than-usual build id note
// makes its way all the way through to the minidump unscathed.
// The linux_client_unittest is linked with an explicit --build-id
// in Makefile.am.
TEST(MinidumpWriterTest, BuildIDLong) {
int fds[2];
ASSERT_NE(-1, pipe(fds));
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));
ASSERT_EQ(0, getcontext(&context.context));
context.tid = child;
AutoTempDir temp_dir;
const string dump_path = temp_dir.path() + kMDWriterUnitTestFileName;
EXPECT_TRUE(WriteMinidump(dump_path.c_str(),
child, &context, sizeof(context)));
close(fds[1]);
// Read the minidump. Load the module list, and ensure that
// the main module has the correct debug id and code id.
Minidump minidump(dump_path);
ASSERT_TRUE(minidump.Read());
MinidumpModuleList* module_list = minidump.GetModuleList();
ASSERT_TRUE(module_list);
const MinidumpModule* module = module_list->GetMainModule();
ASSERT_TRUE(module);
const string module_identifier = "030201000504070608090A0B0C0D0E0F0";
// This is passed explicitly to the linker in Makefile.am
const string build_id =
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
EXPECT_EQ(module_identifier, module->debug_identifier());
EXPECT_EQ(build_id, module->code_identifier());
}
// Test that mapping info can be specified, and that it overrides
// existing mappings that are wholly contained within the specified
// range.
@ -245,19 +276,7 @@ TEST(MinidumpWriterTest, MappingInfoContained) {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
char module_identifier_buffer[kGUIDStringSize];
FileID::ConvertIdentifierToString(kModuleGUID,
module_identifier_buffer,
sizeof(module_identifier_buffer));
string module_identifier(module_identifier_buffer);
// Strip out dashes
size_t pos;
while ((pos = module_identifier.find('-')) != string::npos) {
module_identifier.erase(pos, 1);
}
// And append a zero, because module IDs include an "age" field
// which is always zero on Linux.
module_identifier += "0";
const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
// mmap a file
AutoTempDir temp_dir;
@ -410,12 +429,10 @@ TEST(MinidumpWriterTest, DeletedBinary) {
EXPECT_STREQ(binpath.c_str(), module->code_file().c_str());
// Check that the file ID is correct.
FileID fileid(helper_path.c_str());
uint8_t identifier[sizeof(MDGUID)];
PageAllocator allocator;
wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize);
EXPECT_TRUE(fileid.ElfFileIdentifier(identifier));
char identifier_string[kGUIDStringSize];
FileID::ConvertIdentifierToString(identifier,
identifier_string,
kGUIDStringSize);
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
string module_identifier(identifier_string);
// Strip out dashes
size_t pos;

View File

@ -583,7 +583,6 @@
4DBE4769134A4F080072546A /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
8B31007011F0CD3C00FCF3E4 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMDefines.h; path = ../../common/mac/GTMDefines.h; sourceTree = SOURCE_ROOT; };
8B3101E911F0CDE300FCF3E4 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
8B31022211F0CE1000FCF3E4 /* GTMGarbageCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMGarbageCollection.h; path = ../../common/mac/GTMGarbageCollection.h; sourceTree = SOURCE_ROOT; };
8B31027711F0D3AF00FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
8B31027811F0D3AF00FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
8B31FFF611F0C90500FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
@ -955,7 +954,6 @@
children = (
162F64F0161C577500CD68D5 /* arch_utilities.cc */,
162F64F1161C577500CD68D5 /* arch_utilities.h */,
8B31022211F0CE1000FCF3E4 /* GTMGarbageCollection.h */,
8B31007011F0CD3C00FCF3E4 /* GTMDefines.h */,
F9C77E0F0F7DDF650045F7DB /* testing */,
F9C44EE70EF0A3C1003AEBAA /* GTMLogger.h */,

View File

@ -75,6 +75,8 @@
'dwarf/dwarf2reader.cc',
'dwarf/dwarf2reader.h',
'dwarf/dwarf2reader_test_common.h',
'dwarf/elf_reader.cc',
'dwarf/elf_reader.h',
'dwarf/functioninfo.cc',
'dwarf/functioninfo.h',
'dwarf/line_state_machine.h',

View File

@ -243,4 +243,8 @@ uint64 ByteReader::ReadEncodedPointer(const uint8_t *buffer,
return pointer;
}
Endianness ByteReader::GetEndianness() const {
return endian_;
}
} // namespace dwarf2reader

View File

@ -280,6 +280,7 @@ class ByteReader {
DwarfPointerEncoding encoding,
size_t *len) const;
Endianness GetEndianness() const;
private:
// Function pointer type for our address and offset readers.

View File

@ -149,7 +149,10 @@ enum DwarfForm {
DW_FORM_sec_offset = 0x17,
DW_FORM_exprloc = 0x18,
DW_FORM_flag_present = 0x19,
DW_FORM_ref_sig8 = 0x20
DW_FORM_ref_sig8 = 0x20,
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
DW_FORM_GNU_addr_index = 0x1f01,
DW_FORM_GNU_str_index = 0x1f02
};
// Attribute names and codes
@ -264,6 +267,13 @@ enum DwarfAttribute {
DW_AT_body_begin = 0x2105,
DW_AT_body_end = 0x2106,
DW_AT_GNU_vector = 0x2107,
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
DW_AT_GNU_dwo_name = 0x2130,
DW_AT_GNU_dwo_id = 0x2131,
DW_AT_GNU_ranges_base = 0x2132,
DW_AT_GNU_addr_base = 0x2133,
DW_AT_GNU_pubnames = 0x2134,
DW_AT_GNU_pubtypes = 0x2135,
// VMS extensions.
DW_AT_VMS_rtnbeg_pd_address = 0x2201,
// UPC extension.
@ -491,7 +501,22 @@ enum DwarfOpcode {
DW_OP_lo_user =0xe0,
DW_OP_hi_user =0xff,
// GNU extensions
DW_OP_GNU_push_tls_address =0xe0
DW_OP_GNU_push_tls_address =0xe0,
// Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
DW_OP_GNU_addr_index =0xfb,
DW_OP_GNU_const_index =0xfc
};
// Section identifiers for DWP files
enum DwarfSectionId {
DW_SECT_INFO = 1,
DW_SECT_TYPES = 2,
DW_SECT_ABBREV = 3,
DW_SECT_LINE = 4,
DW_SECT_LOC = 5,
DW_SECT_STR_OFFSETS = 6,
DW_SECT_MACINFO = 7,
DW_SECT_MACRO = 8
};
// Source languages. These are values for DW_AT_language.

View File

@ -44,6 +44,8 @@
#include <string>
#include <utility>
#include <sys/stat.h>
#include "common/dwarf/bytereader-inl.h"
#include "common/dwarf/bytereader.h"
#include "common/dwarf/line_state_machine.h"
@ -51,11 +53,38 @@
namespace dwarf2reader {
CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset,
CompilationUnit::CompilationUnit(const string& path,
const SectionMap& sections, uint64 offset,
ByteReader* reader, Dwarf2Handler* handler)
: offset_from_section_start_(offset), reader_(reader),
sections_(sections), handler_(handler), abbrevs_(NULL),
string_buffer_(NULL), string_buffer_length_(0) {}
: path_(path), offset_from_section_start_(offset), reader_(reader),
sections_(sections), handler_(handler), abbrevs_(),
string_buffer_(NULL), string_buffer_length_(0),
str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
addr_buffer_(NULL), addr_buffer_length_(0),
is_split_dwarf_(false), dwo_id_(0), dwo_name_(),
skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0),
have_checked_for_dwp_(false), dwp_path_(),
dwp_byte_reader_(), dwp_reader_() {}
// Initialize a compilation unit from a .dwo or .dwp file.
// In this case, we need the .debug_addr section from the
// executable file that contains the corresponding skeleton
// compilation unit. We also inherit the Dwarf2Handler from
// the executable file, and call it as if we were still
// processing the original compilation unit.
void CompilationUnit::SetSplitDwarf(const uint8_t* addr_buffer,
uint64 addr_buffer_length,
uint64 addr_base,
uint64 ranges_base,
uint64 dwo_id) {
is_split_dwarf_ = true;
addr_buffer_ = addr_buffer;
addr_buffer_length_ = addr_buffer_length;
addr_base_ = addr_base;
ranges_base_ = ranges_base;
skeleton_dwo_id_ = dwo_id;
}
// Read a DWARF2/3 abbreviation section.
// Each abbrev consists of a abbreviation number, a tag, a byte
@ -174,6 +203,8 @@ const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
return start + strlen(reinterpret_cast<const char *>(start)) + 1;
case DW_FORM_udata:
case DW_FORM_ref_udata:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_addr_index:
reader_->ReadUnsignedLEB128(start, &len);
return start + len;
@ -235,7 +266,9 @@ void CompilationUnit::ReadHeader() {
header_.abbrev_offset = reader_->ReadOffset(headerptr);
headerptr += reader_->OffsetSize();
assert(headerptr + 1 < buffer_ + buffer_length_);
// Compare against less than or equal because this may be the last
// section in the file.
assert(headerptr + 1 <= buffer_ + buffer_length_);
header_.address_size = reader_->ReadOneByte(headerptr);
reader_->SetAddressSize(header_.address_size);
headerptr += 1;
@ -296,9 +329,31 @@ uint64 CompilationUnit::Start() {
string_buffer_length_ = iter->second.second;
}
// Set the string offsets section if we have one.
iter = sections_.find(".debug_str_offsets");
if (iter != sections_.end()) {
str_offsets_buffer_ = iter->second.first;
str_offsets_buffer_length_ = iter->second.second;
}
// Set the address section if we have one.
iter = sections_.find(".debug_addr");
if (iter != sections_.end()) {
addr_buffer_ = iter->second.first;
addr_buffer_length_ = iter->second.second;
}
// Now that we have our abbreviations, start processing DIE's.
ProcessDIEs();
// If this is a skeleton compilation unit generated with split DWARF,
// and the client needs the full debug info, we need to find the full
// compilation unit in a .dwo or .dwp file.
if (!is_split_dwarf_
&& dwo_name_ != NULL
&& handler_->NeedSplitDebugInfo())
ProcessSplitDwarf();
return ourlength;
}
@ -320,48 +375,46 @@ const uint8_t *CompilationUnit::ProcessAttribute(
return ProcessAttribute(dieoffset, start, attr, form);
case DW_FORM_flag_present:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form, 1);
ProcessAttributeUnsigned(dieoffset, attr, form, 1);
return start;
case DW_FORM_data1:
case DW_FORM_flag:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadOneByte(start));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadOneByte(start));
return start + 1;
case DW_FORM_data2:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadTwoBytes(start));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadTwoBytes(start));
return start + 2;
case DW_FORM_data4:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadFourBytes(start));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadFourBytes(start));
return start + 4;
case DW_FORM_data8:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadEightBytes(start));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadEightBytes(start));
return start + 8;
case DW_FORM_string: {
const char *str = reinterpret_cast<const char *>(start);
handler_->ProcessAttributeString(dieoffset, attr, form,
str);
ProcessAttributeString(dieoffset, attr, form, str);
return start + strlen(str) + 1;
}
case DW_FORM_udata:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadUnsignedLEB128(start,
&len));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadUnsignedLEB128(start, &len));
return start + len;
case DW_FORM_sdata:
handler_->ProcessAttributeSigned(dieoffset, attr, form,
reader_->ReadSignedLEB128(start, &len));
ProcessAttributeSigned(dieoffset, attr, form,
reader_->ReadSignedLEB128(start, &len));
return start + len;
case DW_FORM_addr:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadAddress(start));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadAddress(start));
return start + reader_->AddressSize();
case DW_FORM_sec_offset:
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadOffset(start));
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadOffset(start));
return start + reader_->OffsetSize();
case DW_FORM_ref1:
@ -441,10 +494,32 @@ const uint8_t *CompilationUnit::ProcessAttribute(
assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_);
const char *str = reinterpret_cast<const char *>(string_buffer_ + offset);
handler_->ProcessAttributeString(dieoffset, attr, form,
str);
ProcessAttributeString(dieoffset, attr, form, str);
return start + reader_->OffsetSize();
}
case DW_FORM_GNU_str_index: {
uint64 str_index = reader_->ReadUnsignedLEB128(start, &len);
const uint8_t* offset_ptr =
str_offsets_buffer_ + str_index * reader_->OffsetSize();
const uint64 offset = reader_->ReadOffset(offset_ptr);
if (offset >= string_buffer_length_) {
return NULL;
}
const char* str = reinterpret_cast<const char *>(string_buffer_) + offset;
ProcessAttributeString(dieoffset, attr, form, str);
return start + len;
break;
}
case DW_FORM_GNU_addr_index: {
uint64 addr_index = reader_->ReadUnsignedLEB128(start, &len);
const uint8_t* addr_ptr =
addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
ProcessAttributeUnsigned(dieoffset, attr, form,
reader_->ReadAddress(addr_ptr));
return start + len;
}
}
fprintf(stderr, "Unhandled form type\n");
return NULL;
@ -458,6 +533,16 @@ const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset,
i++) {
start = ProcessAttribute(dieoffset, start, i->first, i->second);
}
// If this is a compilation unit in a split DWARF object, verify that
// the dwo_id matches. If it does not match, we will ignore this
// compilation unit.
if (abbrev.tag == DW_TAG_compile_unit
&& is_split_dwarf_
&& dwo_id_ != skeleton_dwo_id_) {
return NULL;
}
return start;
}
@ -515,6 +600,307 @@ void CompilationUnit::ProcessDIEs() {
}
}
// Check for a valid ELF file and return the Address size.
// Returns 0 if not a valid ELF file.
inline int GetElfWidth(const ElfReader& elf) {
if (elf.IsElf32File())
return 4;
if (elf.IsElf64File())
return 8;
return 0;
}
void CompilationUnit::ProcessSplitDwarf() {
struct stat statbuf;
if (!have_checked_for_dwp_) {
// Look for a .dwp file in the same directory as the executable.
have_checked_for_dwp_ = true;
string dwp_suffix(".dwp");
dwp_path_ = path_ + dwp_suffix;
if (stat(dwp_path_.c_str(), &statbuf) != 0) {
// Fall back to a split .debug file in the same directory.
string debug_suffix(".debug");
dwp_path_ = path_;
size_t found = path_.rfind(debug_suffix);
if (found + debug_suffix.length() == path_.length())
dwp_path_ = dwp_path_.replace(found, debug_suffix.length(), dwp_suffix);
}
if (stat(dwp_path_.c_str(), &statbuf) == 0) {
ElfReader* elf = new ElfReader(dwp_path_);
int width = GetElfWidth(*elf);
if (width != 0) {
dwp_byte_reader_.reset(new ByteReader(reader_->GetEndianness()));
dwp_byte_reader_->SetAddressSize(width);
dwp_reader_.reset(new DwpReader(*dwp_byte_reader_, elf));
dwp_reader_->Initialize();
} else {
delete elf;
}
}
}
bool found_in_dwp = false;
if (dwp_reader_) {
// If we have a .dwp file, read the debug sections for the requested CU.
SectionMap sections;
dwp_reader_->ReadDebugSectionsForCU(dwo_id_, &sections);
if (!sections.empty()) {
found_in_dwp = true;
CompilationUnit dwp_comp_unit(dwp_path_, sections, 0,
dwp_byte_reader_.get(), handler_);
dwp_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, addr_base_,
ranges_base_, dwo_id_);
dwp_comp_unit.Start();
}
}
if (!found_in_dwp) {
// If no .dwp file, try to open the .dwo file.
if (stat(dwo_name_, &statbuf) == 0) {
ElfReader elf(dwo_name_);
int width = GetElfWidth(elf);
if (width != 0) {
ByteReader reader(ENDIANNESS_LITTLE);
reader.SetAddressSize(width);
SectionMap sections;
ReadDebugSectionsFromDwo(&elf, &sections);
CompilationUnit dwo_comp_unit(dwo_name_, sections, 0, &reader,
handler_);
dwo_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_,
addr_base_, ranges_base_, dwo_id_);
dwo_comp_unit.Start();
}
}
}
}
void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader,
SectionMap* sections) {
static const char* const section_names[] = {
".debug_abbrev",
".debug_info",
".debug_str_offsets",
".debug_str"
};
for (unsigned int i = 0u;
i < sizeof(section_names)/sizeof(*(section_names)); ++i) {
string base_name = section_names[i];
string dwo_name = base_name + ".dwo";
size_t section_size;
const char* section_data = elf_reader->GetSectionByName(dwo_name,
&section_size);
if (section_data != NULL)
sections->insert(std::make_pair(
base_name, std::make_pair(
reinterpret_cast<const uint8_t *>(section_data),
section_size)));
}
}
DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader)
: elf_reader_(elf_reader), byte_reader_(byte_reader),
cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL),
string_buffer_size_(0), version_(0), ncolumns_(0), nunits_(0),
nslots_(0), phash_(NULL), pindex_(NULL), shndx_pool_(NULL),
offset_table_(NULL), size_table_(NULL), abbrev_data_(NULL),
abbrev_size_(0), info_data_(NULL), info_size_(0),
str_offsets_data_(NULL), str_offsets_size_(0) {}
DwpReader::~DwpReader() {
if (elf_reader_) delete elf_reader_;
}
void DwpReader::Initialize() {
cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index",
&cu_index_size_);
if (cu_index_ == NULL) {
return;
}
// The .debug_str.dwo section is shared by all CUs in the file.
string_buffer_ = elf_reader_->GetSectionByName(".debug_str.dwo",
&string_buffer_size_);
version_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_));
if (version_ == 1) {
nslots_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_)
+ 3 * sizeof(uint32));
phash_ = cu_index_ + 4 * sizeof(uint32);
pindex_ = phash_ + nslots_ * sizeof(uint64);
shndx_pool_ = pindex_ + nslots_ * sizeof(uint32);
if (shndx_pool_ >= cu_index_ + cu_index_size_) {
version_ = 0;
}
} else if (version_ == 2) {
ncolumns_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_) + sizeof(uint32));
nunits_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_) + 2 * sizeof(uint32));
nslots_ = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(cu_index_) + 3 * sizeof(uint32));
phash_ = cu_index_ + 4 * sizeof(uint32);
pindex_ = phash_ + nslots_ * sizeof(uint64);
offset_table_ = pindex_ + nslots_ * sizeof(uint32);
size_table_ = offset_table_ + ncolumns_ * (nunits_ + 1) * sizeof(uint32);
abbrev_data_ = elf_reader_->GetSectionByName(".debug_abbrev.dwo",
&abbrev_size_);
info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_);
str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo",
&str_offsets_size_);
if (size_table_ >= cu_index_ + cu_index_size_) {
version_ = 0;
}
}
}
void DwpReader::ReadDebugSectionsForCU(uint64 dwo_id,
SectionMap* sections) {
if (version_ == 1) {
int slot = LookupCU(dwo_id);
if (slot == -1) {
return;
}
// The index table points to the section index pool, where we
// can read a list of section indexes for the debug sections
// for the CU whose dwo_id we are looking for.
int index = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(pindex_)
+ slot * sizeof(uint32));
const char* shndx_list = shndx_pool_ + index * sizeof(uint32);
for (;;) {
if (shndx_list >= cu_index_ + cu_index_size_) {
version_ = 0;
return;
}
unsigned int shndx = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(shndx_list));
shndx_list += sizeof(uint32);
if (shndx == 0)
break;
const char* section_name = elf_reader_->GetSectionName(shndx);
size_t section_size;
const char* section_data;
// We're only interested in these four debug sections.
// The section names in the .dwo file end with ".dwo", but we
// add them to the sections table with their normal names.
if (!strncmp(section_name, ".debug_abbrev", strlen(".debug_abbrev"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_abbrev",
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
section_size)));
} else if (!strncmp(section_name, ".debug_info", strlen(".debug_info"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_info",
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
section_size)));
} else if (!strncmp(section_name, ".debug_str_offsets",
strlen(".debug_str_offsets"))) {
section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
sections->insert(std::make_pair(
".debug_str_offsets",
std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
section_size)));
}
}
sections->insert(std::make_pair(
".debug_str",
std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
string_buffer_size_)));
} else if (version_ == 2) {
uint32 index = LookupCUv2(dwo_id);
if (index == 0) {
return;
}
// The index points to a row in each of the section offsets table
// and the section size table, where we can read the offsets and sizes
// of the contributions to each debug section from the CU whose dwo_id
// we are looking for. Row 0 of the section offsets table has the
// section ids for each column of the table. The size table begins
// with row 1.
const char* id_row = offset_table_;
const char* offset_row = offset_table_
+ index * ncolumns_ * sizeof(uint32);
const char* size_row =
size_table_ + (index - 1) * ncolumns_ * sizeof(uint32);
if (size_row + ncolumns_ * sizeof(uint32) > cu_index_ + cu_index_size_) {
version_ = 0;
return;
}
for (unsigned int col = 0u; col < ncolumns_; ++col) {
uint32 section_id =
byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(id_row)
+ col * sizeof(uint32));
uint32 offset = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(offset_row)
+ col * sizeof(uint32));
uint32 size = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(size_row) + col * sizeof(uint32));
if (section_id == DW_SECT_ABBREV) {
sections->insert(std::make_pair(
".debug_abbrev",
std::make_pair(reinterpret_cast<const uint8_t *> (abbrev_data_)
+ offset, size)));
} else if (section_id == DW_SECT_INFO) {
sections->insert(std::make_pair(
".debug_info",
std::make_pair(reinterpret_cast<const uint8_t *> (info_data_)
+ offset, size)));
} else if (section_id == DW_SECT_STR_OFFSETS) {
sections->insert(std::make_pair(
".debug_str_offsets",
std::make_pair(reinterpret_cast<const uint8_t *> (str_offsets_data_)
+ offset, size)));
}
}
sections->insert(std::make_pair(
".debug_str",
std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
string_buffer_size_)));
}
}
int DwpReader::LookupCU(uint64 dwo_id) {
uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
uint64 probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
if (probe != 0 && probe != dwo_id) {
uint32 secondary_hash =
(static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
do {
slot = (slot + secondary_hash) & (nslots_ - 1);
probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
} while (probe != 0 && probe != dwo_id);
}
if (probe == 0)
return -1;
return slot;
}
uint32 DwpReader::LookupCUv2(uint64 dwo_id) {
uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
uint64 probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
uint32 index = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
if (index != 0 && probe != dwo_id) {
uint32 secondary_hash =
(static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
do {
slot = (slot + secondary_hash) & (nslots_ - 1);
probe = byte_reader_.ReadEightBytes(
reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
index = byte_reader_.ReadFourBytes(
reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
} while (index != 0 && probe != dwo_id);
}
return index;
}
LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length,
ByteReader* reader, LineInfoHandler* handler):
handler_(handler), reader_(reader), buffer_(buffer) {

View File

@ -47,16 +47,19 @@
#include <string>
#include <utility>
#include <vector>
#include <memory>
#include "common/dwarf/bytereader.h"
#include "common/dwarf/dwarf2enums.h"
#include "common/dwarf/types.h"
#include "common/using_std_string.h"
#include "common/dwarf/elf_reader.h"
namespace dwarf2reader {
struct LineStateMachine;
class Dwarf2Handler;
class LineInfoHandler;
class DwpReader;
// This maps from a string naming a section to a pair containing a
// the data for the section, and the size of the section.
@ -184,151 +187,10 @@ class LineInfoHandler {
uint32 file_num, uint32 line_num, uint32 column_num) { }
};
// The base of DWARF2/3 debug info is a DIE (Debugging Information
// Entry.
// DWARF groups DIE's into a tree and calls the root of this tree a
// "compilation unit". Most of the time, there is one compilation
// unit in the .debug_info section for each file that had debug info
// generated.
// Each DIE consists of
// 1. a tag specifying a thing that is being described (ie
// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
// 2. attributes (such as DW_AT_location for location in memory,
// DW_AT_name for name), and data for each attribute.
// 3. A flag saying whether the DIE has children or not
// In order to gain some amount of compression, the format of
// each DIE (tag name, attributes and data forms for the attributes)
// are stored in a separate table called the "abbreviation table".
// This is done because a large number of DIEs have the exact same tag
// and list of attributes, but different data for those attributes.
// As a result, the .debug_info section is just a stream of data, and
// requires reading of the .debug_abbrev section to say what the data
// means.
// As a warning to the user, it should be noted that the reason for
// using absolute offsets from the beginning of .debug_info is that
// DWARF2/3 supports referencing DIE's from other DIE's by their offset
// from either the current compilation unit start, *or* the beginning
// of the .debug_info section. This means it is possible to reference
// a DIE in one compilation unit from a DIE in another compilation
// unit. This style of reference is usually used to eliminate
// duplicated information that occurs across compilation
// units, such as base types, etc. GCC 3.4+ support this with
// -feliminate-dwarf2-dups. Other toolchains will sometimes do
// duplicate elimination in the linker.
class CompilationUnit {
public:
// Initialize a compilation unit. This requires a map of sections,
// the offset of this compilation unit in the .debug_info section, a
// ByteReader, and a Dwarf2Handler class to call callbacks in.
CompilationUnit(const SectionMap& sections, uint64 offset,
ByteReader* reader, Dwarf2Handler* handler);
virtual ~CompilationUnit() {
if (abbrevs_) delete abbrevs_;
}
// Begin reading a Dwarf2 compilation unit, and calling the
// callbacks in the Dwarf2Handler
// Return the full length of the compilation unit, including
// headers. This plus the starting offset passed to the constructor
// is the offset of the end of the compilation unit --- and the
// start of the next compilation unit, if there is one.
uint64 Start();
private:
// This struct represents a single DWARF2/3 abbreviation
// The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
// tag and a list of attributes, as well as the data form of each attribute.
struct Abbrev {
uint64 number;
enum DwarfTag tag;
bool has_children;
AttributeList attributes;
};
// A DWARF2/3 compilation unit header. This is not the same size as
// in the actual file, as the one in the file may have a 32 bit or
// 64 bit length.
struct CompilationUnitHeader {
uint64 length;
uint16 version;
uint64 abbrev_offset;
uint8 address_size;
} header_;
// Reads the DWARF2/3 header for this compilation unit.
void ReadHeader();
// Reads the DWARF2/3 abbreviations for this compilation unit
void ReadAbbrevs();
// Processes a single DIE for this compilation unit and return a new
// pointer just past the end of it
const uint8_t *ProcessDIE(uint64 dieoffset,
const uint8_t *start,
const Abbrev& abbrev);
// Processes a single attribute and return a new pointer just past the
// end of it
const uint8_t *ProcessAttribute(uint64 dieoffset,
const uint8_t *start,
enum DwarfAttribute attr,
enum DwarfForm form);
// Processes all DIEs for this compilation unit
void ProcessDIEs();
// Skips the die with attributes specified in ABBREV starting at
// START, and return the new place to position the stream to.
const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
// Skips the attribute starting at START, with FORM, and return the
// new place to position the stream to.
const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
// Offset from section start is the offset of this compilation unit
// from the beginning of the .debug_info section.
uint64 offset_from_section_start_;
// buffer is the buffer for our CU, starting at .debug_info + offset
// passed in from constructor.
// after_header points to right after the compilation unit header.
const uint8_t *buffer_;
uint64 buffer_length_;
const uint8_t *after_header_;
// The associated ByteReader that handles endianness issues for us
ByteReader* reader_;
// The map of sections in our file to buffers containing their data
const SectionMap& sections_;
// The associated handler to call processing functions in
Dwarf2Handler* handler_;
// Set of DWARF2/3 abbreviations for this compilation unit. Indexed
// by abbreviation number, which means that abbrevs_[0] is not
// valid.
std::vector<Abbrev>* abbrevs_;
// String section buffer and length, if we have a string section.
// This is here to avoid doing a section lookup for strings in
// ProcessAttribute, which is in the hot path for DWARF2 reading.
const uint8_t *string_buffer_;
uint64 string_buffer_length_;
};
// This class is the main interface between the reader and the
// client. The virtual functions inside this get called for
// interesting events that happen during DWARF2 reading.
// The default implementation skips everything.
class Dwarf2Handler {
public:
Dwarf2Handler() { }
@ -342,6 +204,19 @@ class Dwarf2Handler {
uint8 offset_size, uint64 cu_length,
uint8 dwarf_version) { return false; }
// When processing a skeleton compilation unit, resulting from a split
// DWARF compilation, once the skeleton debug info has been read,
// the reader will call this function to ask the client if it needs
// the full debug info from the .dwo or .dwp file. Return true if
// you need it, or false to skip processing the split debug info.
virtual bool NeedSplitDebugInfo() { return true; }
// Start to process a split compilation unit at OFFSET from the beginning of
// the debug_info section in the .dwp/.dwo file. Return false if you would
// like to skip this compilation unit.
virtual bool StartSplitCompilationUnit(uint64 offset,
uint64 cu_length) { return false; }
// Start to process a DIE at OFFSET from the beginning of the .debug_info
// section. Return false if you would like to skip this DIE.
virtual bool StartDIE(uint64 offset, enum DwarfTag tag) { return false; }
@ -412,6 +287,367 @@ class Dwarf2Handler {
};
// The base of DWARF2/3 debug info is a DIE (Debugging Information
// Entry.
// DWARF groups DIE's into a tree and calls the root of this tree a
// "compilation unit". Most of the time, there is one compilation
// unit in the .debug_info section for each file that had debug info
// generated.
// Each DIE consists of
// 1. a tag specifying a thing that is being described (ie
// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
// 2. attributes (such as DW_AT_location for location in memory,
// DW_AT_name for name), and data for each attribute.
// 3. A flag saying whether the DIE has children or not
// In order to gain some amount of compression, the format of
// each DIE (tag name, attributes and data forms for the attributes)
// are stored in a separate table called the "abbreviation table".
// This is done because a large number of DIEs have the exact same tag
// and list of attributes, but different data for those attributes.
// As a result, the .debug_info section is just a stream of data, and
// requires reading of the .debug_abbrev section to say what the data
// means.
// As a warning to the user, it should be noted that the reason for
// using absolute offsets from the beginning of .debug_info is that
// DWARF2/3 supports referencing DIE's from other DIE's by their offset
// from either the current compilation unit start, *or* the beginning
// of the .debug_info section. This means it is possible to reference
// a DIE in one compilation unit from a DIE in another compilation
// unit. This style of reference is usually used to eliminate
// duplicated information that occurs across compilation
// units, such as base types, etc. GCC 3.4+ support this with
// -feliminate-dwarf2-dups. Other toolchains will sometimes do
// duplicate elimination in the linker.
class CompilationUnit {
public:
// Initialize a compilation unit. This requires a map of sections,
// the offset of this compilation unit in the .debug_info section, a
// ByteReader, and a Dwarf2Handler class to call callbacks in.
CompilationUnit(const string& path, const SectionMap& sections, uint64 offset,
ByteReader* reader, Dwarf2Handler* handler);
virtual ~CompilationUnit() {
if (abbrevs_) delete abbrevs_;
}
// Initialize a compilation unit from a .dwo or .dwp file.
// In this case, we need the .debug_addr section from the
// executable file that contains the corresponding skeleton
// compilation unit. We also inherit the Dwarf2Handler from
// the executable file, and call it as if we were still
// processing the original compilation unit.
void SetSplitDwarf(const uint8_t* addr_buffer, uint64 addr_buffer_length,
uint64 addr_base, uint64 ranges_base, uint64 dwo_id);
// Begin reading a Dwarf2 compilation unit, and calling the
// callbacks in the Dwarf2Handler
// Return the full length of the compilation unit, including
// headers. This plus the starting offset passed to the constructor
// is the offset of the end of the compilation unit --- and the
// start of the next compilation unit, if there is one.
uint64 Start();
private:
// This struct represents a single DWARF2/3 abbreviation
// The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
// tag and a list of attributes, as well as the data form of each attribute.
struct Abbrev {
uint64 number;
enum DwarfTag tag;
bool has_children;
AttributeList attributes;
};
// A DWARF2/3 compilation unit header. This is not the same size as
// in the actual file, as the one in the file may have a 32 bit or
// 64 bit length.
struct CompilationUnitHeader {
uint64 length;
uint16 version;
uint64 abbrev_offset;
uint8 address_size;
} header_;
// Reads the DWARF2/3 header for this compilation unit.
void ReadHeader();
// Reads the DWARF2/3 abbreviations for this compilation unit
void ReadAbbrevs();
// Processes a single DIE for this compilation unit and return a new
// pointer just past the end of it
const uint8_t *ProcessDIE(uint64 dieoffset,
const uint8_t *start,
const Abbrev& abbrev);
// Processes a single attribute and return a new pointer just past the
// end of it
const uint8_t *ProcessAttribute(uint64 dieoffset,
const uint8_t *start,
enum DwarfAttribute attr,
enum DwarfForm form);
// Called when we have an attribute with unsigned data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA.
// If we see a DW_AT_GNU_dwo_id attribute, save the value so that
// we can find the debug info in a .dwo or .dwp file.
void ProcessAttributeUnsigned(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
uint64 data) {
if (attr == DW_AT_GNU_dwo_id) {
dwo_id_ = data;
}
else if (attr == DW_AT_GNU_addr_base) {
addr_base_ = data;
}
else if (attr == DW_AT_GNU_ranges_base) {
ranges_base_ = data;
}
// TODO(yunlian): When we add DW_AT_ranges_base from DWARF-5,
// that base will apply to DW_AT_ranges attributes in the
// skeleton CU as well as in the .dwo/.dwp files.
else if (attr == DW_AT_ranges && is_split_dwarf_) {
data += ranges_base_;
}
handler_->ProcessAttributeUnsigned(offset, attr, form, data);
}
// Called when we have an attribute with signed data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA.
void ProcessAttributeSigned(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
int64 data) {
handler_->ProcessAttributeSigned(offset, attr, form, data);
}
// Called when we have an attribute with a buffer of data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA, and the
// length of the buffer is LENGTH.
void ProcessAttributeBuffer(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
const uint8_t* data,
uint64 len) {
handler_->ProcessAttributeBuffer(offset, attr, form, data, len);
}
// Called when we have an attribute with string data to give to
// our handler. The attribute is for the DIE at OFFSET from the
// beginning of compilation unit, has a name of ATTR, a form of
// FORM, and the actual data of the attribute is in DATA.
// If we see a DW_AT_GNU_dwo_name attribute, save the value so
// that we can find the debug info in a .dwo or .dwp file.
void ProcessAttributeString(uint64 offset,
enum DwarfAttribute attr,
enum DwarfForm form,
const char* data) {
if (attr == DW_AT_GNU_dwo_name)
dwo_name_ = data;
handler_->ProcessAttributeString(offset, attr, form, data);
}
// Processes all DIEs for this compilation unit
void ProcessDIEs();
// Skips the die with attributes specified in ABBREV starting at
// START, and return the new place to position the stream to.
const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
// Skips the attribute starting at START, with FORM, and return the
// new place to position the stream to.
const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
// Process the actual debug information in a split DWARF file.
void ProcessSplitDwarf();
// Read the debug sections from a .dwo file.
void ReadDebugSectionsFromDwo(ElfReader* elf_reader,
SectionMap* sections);
// Path of the file containing the debug information.
const string path_;
// Offset from section start is the offset of this compilation unit
// from the beginning of the .debug_info section.
uint64 offset_from_section_start_;
// buffer is the buffer for our CU, starting at .debug_info + offset
// passed in from constructor.
// after_header points to right after the compilation unit header.
const uint8_t *buffer_;
uint64 buffer_length_;
const uint8_t *after_header_;
// The associated ByteReader that handles endianness issues for us
ByteReader* reader_;
// The map of sections in our file to buffers containing their data
const SectionMap& sections_;
// The associated handler to call processing functions in
Dwarf2Handler* handler_;
// Set of DWARF2/3 abbreviations for this compilation unit. Indexed
// by abbreviation number, which means that abbrevs_[0] is not
// valid.
std::vector<Abbrev>* abbrevs_;
// String section buffer and length, if we have a string section.
// This is here to avoid doing a section lookup for strings in
// ProcessAttribute, which is in the hot path for DWARF2 reading.
const uint8_t *string_buffer_;
uint64 string_buffer_length_;
// String offsets section buffer and length, if we have a string offsets
// section (.debug_str_offsets or .debug_str_offsets.dwo).
const uint8_t* str_offsets_buffer_;
uint64 str_offsets_buffer_length_;
// Address section buffer and length, if we have an address section
// (.debug_addr).
const uint8_t* addr_buffer_;
uint64 addr_buffer_length_;
// Flag indicating whether this compilation unit is part of a .dwo
// or .dwp file. If true, we are reading this unit because a
// skeleton compilation unit in an executable file had a
// DW_AT_GNU_dwo_name or DW_AT_GNU_dwo_id attribute.
// In a .dwo file, we expect the string offsets section to
// have a ".dwo" suffix, and we will use the ".debug_addr" section
// associated with the skeleton compilation unit.
bool is_split_dwarf_;
// The value of the DW_AT_GNU_dwo_id attribute, if any.
uint64 dwo_id_;
// The value of the DW_AT_GNU_dwo_name attribute, if any.
const char* dwo_name_;
// If this is a split DWARF CU, the value of the DW_AT_GNU_dwo_id attribute
// from the skeleton CU.
uint64 skeleton_dwo_id_;
// The value of the DW_AT_GNU_ranges_base attribute, if any.
uint64 ranges_base_;
// The value of the DW_AT_GNU_addr_base attribute, if any.
uint64 addr_base_;
// True if we have already looked for a .dwp file.
bool have_checked_for_dwp_;
// Path to the .dwp file.
string dwp_path_;
// ByteReader for the DWP file.
std::unique_ptr<ByteReader> dwp_byte_reader_;
// DWP reader.
std::unique_ptr<DwpReader> dwp_reader_;
};
// A Reader for a .dwp file. Supports the fetching of DWARF debug
// info for a given dwo_id.
//
// There are two versions of .dwp files. In both versions, the
// .dwp file is an ELF file containing only debug sections.
// In Version 1, the file contains many copies of each debug
// section, one for each .dwo file that is packaged in the .dwp
// file, and the .debug_cu_index section maps from the dwo_id
// to a set of section indexes. In Version 2, the file contains
// one of each debug section, and the .debug_cu_index section
// maps from the dwo_id to a set of offsets and lengths that
// identify each .dwo file's contribution to the larger sections.
class DwpReader {
public:
DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader);
~DwpReader();
// Read the CU index and initialize data members.
void Initialize();
// Read the debug sections for the given dwo_id.
void ReadDebugSectionsForCU(uint64 dwo_id, SectionMap* sections);
private:
// Search a v1 hash table for "dwo_id". Returns the slot index
// where the dwo_id was found, or -1 if it was not found.
int LookupCU(uint64 dwo_id);
// Search a v2 hash table for "dwo_id". Returns the row index
// in the offsets and sizes tables, or 0 if it was not found.
uint32 LookupCUv2(uint64 dwo_id);
// The ELF reader for the .dwp file.
ElfReader* elf_reader_;
// The ByteReader for the .dwp file.
const ByteReader& byte_reader_;
// Pointer to the .debug_cu_index section.
const char* cu_index_;
// Size of the .debug_cu_index section.
size_t cu_index_size_;
// Pointer to the .debug_str.dwo section.
const char* string_buffer_;
// Size of the .debug_str.dwo section.
size_t string_buffer_size_;
// Version of the .dwp file. We support versions 1 and 2 currently.
int version_;
// Number of columns in the section tables (version 2).
unsigned int ncolumns_;
// Number of units in the section tables (version 2).
unsigned int nunits_;
// Number of slots in the hash table.
unsigned int nslots_;
// Pointer to the beginning of the hash table.
const char* phash_;
// Pointer to the beginning of the index table.
const char* pindex_;
// Pointer to the beginning of the section index pool (version 1).
const char* shndx_pool_;
// Pointer to the beginning of the section offset table (version 2).
const char* offset_table_;
// Pointer to the beginning of the section size table (version 2).
const char* size_table_;
// Contents of the sections of interest (version 2).
const char* abbrev_data_;
size_t abbrev_size_;
const char* info_data_;
size_t info_size_;
const char* str_offsets_data_;
size_t str_offsets_size_;
};
// This class is a reader for DWARF's Call Frame Information. CFI
// describes how to unwind stack frames --- even for functions that do
// not follow fixed conventions for saving registers, whose frame size

View File

@ -199,7 +199,7 @@ TEST_P(DwarfHeader, Header) {
ByteReader byte_reader(GetParam().endianness == kLittleEndian ?
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
CompilationUnit parser(MakeSectionMap(), 0, &byte_reader, &handler);
CompilationUnit parser("", MakeSectionMap(), 0, &byte_reader, &handler);
EXPECT_EQ(parser.Start(), info_contents.size());
}
@ -277,7 +277,7 @@ struct DwarfFormsFixture: public DIEFixture {
void ParseCompilationUnit(const DwarfHeaderParams &params, uint64 offset=0) {
ByteReader byte_reader(params.endianness == kLittleEndian ?
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
CompilationUnit parser(MakeSectionMap(), offset, &byte_reader, &handler);
CompilationUnit parser("", MakeSectionMap(), offset, &byte_reader, &handler);
EXPECT_EQ(offset + parser.Start(), info_contents.size());
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,166 @@
// Copyright 2005 Google Inc. All Rights Reserved.
// Author: chatham@google.com (Andrew Chatham)
// Author: satorux@google.com (Satoru Takabayashi)
//
// ElfReader handles reading in ELF. It can extract symbols from the
// current process, which may be used to symbolize stack traces
// without having to make a potentially dangerous call to fork().
//
// ElfReader dynamically allocates memory, so it is not appropriate to
// use once the address space might be corrupted, such as during
// process death.
//
// ElfReader supports both 32-bit and 64-bit ELF binaries.
#ifndef COMMON_DWARF_ELF_READER_H__
#define COMMON_DWARF_ELF_READER_H__
#include <string>
#include <vector>
#include "common/dwarf/types.h"
using std::string;
using std::vector;
using std::pair;
namespace dwarf2reader {
class SymbolMap;
class Elf32;
class Elf64;
template<typename ElfArch>
class ElfReaderImpl;
class ElfReader {
public:
explicit ElfReader(const string &path);
~ElfReader();
// Parse the ELF prologue of this file and return whether it was
// successfully parsed and matches the word size and byte order of
// the current process.
bool IsNativeElfFile() const;
// Similar to IsNativeElfFile but checks if it's a 32-bit ELF file.
bool IsElf32File() const;
// Similar to IsNativeElfFile but checks if it's a 64-bit ELF file.
bool IsElf64File() const;
// Checks if it's an ELF file of type ET_DYN (shared object file).
bool IsDynamicSharedObject();
// Add symbols in the given ELF file into the provided SymbolMap,
// assuming that the file has been loaded into the specified
// offset.
//
// The remaining arguments are typically taken from a
// ProcMapsIterator (base/sysinfo.h) and describe which portions of
// the ELF file are mapped into which parts of memory:
//
// mem_offset - position at which the segment is mapped into memory
// file_offset - offset in the file where the mapping begins
// length - length of the mapped segment
void AddSymbols(SymbolMap *symbols,
uint64 mem_offset, uint64 file_offset,
uint64 length);
class SymbolSink {
public:
virtual ~SymbolSink() {}
virtual void AddSymbol(const char *name, uint64 address, uint64 size) = 0;
};
// Like AddSymbols above, but with no address correction.
// Processes any SHT_SYMTAB section, followed by any SHT_DYNSYM section.
void VisitSymbols(SymbolSink *sink);
// Like VisitSymbols above, but for a specific symbol binding/type.
// A negative value for the binding and type parameters means any
// binding or type.
void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type);
// Like VisitSymbols above but can optionally export raw symbol values instead
// of adjusted ones.
void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type,
bool get_raw_symbol_values);
// p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD
// segments are present. This is the address an ELF image was linked
// (by static linker) to be loaded at. Usually (but not always) 0 for
// shared libraries and position-independent executables.
uint64 VaddrOfFirstLoadSegment();
// Return the name of section "shndx". Returns NULL if the section
// is not found.
const char *GetSectionName(int shndx);
// Return the number of sections in the given ELF file.
uint64 GetNumSections();
// Get section "shndx" from the given ELF file. On success, return
// the pointer to the section and store the size in "size".
// On error, return NULL. The returned section data is only valid
// until the ElfReader gets destroyed.
const char *GetSectionByIndex(int shndx, size_t *size);
// Get section with "section_name" (ex. ".text", ".symtab") in the
// given ELF file. On success, return the pointer to the section
// and store the size in "size". On error, return NULL. The
// returned section data is only valid until the ElfReader gets
// destroyed.
const char *GetSectionByName(const string &section_name, size_t *size);
// This is like GetSectionByName() but it returns a lot of extra information
// about the section. The SectionInfo structure is almost identical to
// the typedef struct Elf64_Shdr defined in <elf.h>, but is redefined
// here so that the many short macro names in <elf.h> don't have to be
// added to our already cluttered namespace.
struct SectionInfo {
uint32 type; // Section type (SHT_xxx constant from elf.h).
uint64 flags; // Section flags (SHF_xxx constants from elf.h).
uint64 addr; // Section virtual address at execution.
uint64 offset; // Section file offset.
uint64 size; // Section size in bytes.
uint32 link; // Link to another section.
uint32 info; // Additional section information.
uint64 addralign; // Section alignment.
uint64 entsize; // Entry size if section holds a table.
};
const char *GetSectionInfoByName(const string &section_name,
SectionInfo *info);
// Check if "path" is an ELF binary that has not been stripped of symbol
// tables. This function supports both 32-bit and 64-bit ELF binaries.
static bool IsNonStrippedELFBinary(const string &path);
// Check if "path" is an ELF binary that has not been stripped of debug
// info. Unlike IsNonStrippedELFBinary, this function will return
// false for binaries passed through "strip -S".
static bool IsNonDebugStrippedELFBinary(const string &path);
// Match a requested section name with the section name as it
// appears in the elf-file, adjusting for compressed debug section
// names. For example, returns true if name == ".debug_abbrev" and
// sh_name == ".zdebug_abbrev"
static bool SectionNamesMatch(const string &name, const string &sh_name);
private:
// Lazily initialize impl32_ and return it.
ElfReaderImpl<Elf32> *GetImpl32();
// Ditto for impl64_.
ElfReaderImpl<Elf64> *GetImpl64();
// Path of the file we're reading.
const string path_;
// Read-only file descriptor for the file. May be -1 if there was an
// error during open.
int fd_;
ElfReaderImpl<Elf32> *impl32_;
ElfReaderImpl<Elf64> *impl64_;
};
} // namespace dwarf2reader
#endif // COMMON_DWARF_ELF_READER_H__

View File

@ -384,17 +384,17 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
qualified_name = &specification_->qualified_name;
}
const string *unqualified_name;
const string *unqualified_name = NULL;
const string *enclosing_name;
if (!qualified_name) {
// Find our unqualified name. If the DIE has its own DW_AT_name
// attribute, then use that; otherwise, check our specification.
if (name_attribute_.empty() && specification_)
unqualified_name = &specification_->unqualified_name;
else
// Find the unqualified name. If the DIE has its own DW_AT_name
// attribute, then use that; otherwise, check the specification.
if (!name_attribute_.empty())
unqualified_name = &name_attribute_;
else if (specification_)
unqualified_name = &specification_->unqualified_name;
// Find the name of our enclosing context. If we have a
// Find the name of the enclosing context. If this DIE has a
// specification, it's the specification's enclosing context that
// counts; otherwise, use this DIE's context.
if (specification_)
@ -408,7 +408,7 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
string return_value;
if (qualified_name) {
return_value = *qualified_name;
} else {
} else if (unqualified_name && enclosing_name) {
// Combine the enclosing name and unqualified name to produce our
// own fully-qualified name.
return_value = cu_context_->language->MakeQualifiedName(*enclosing_name,
@ -417,7 +417,8 @@ string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
// If this DIE was marked as a declaration, record its names in the
// specification table.
if (declaration_) {
if ((declaration_ && qualified_name) ||
(unqualified_name && enclosing_name)) {
Specification spec;
if (qualified_name) {
spec.qualified_name = *qualified_name;

View File

@ -1323,6 +1323,29 @@ TEST_F(Specifications, InlineFunction) {
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
}
// An inline function in a namespace should correctly derive its
// name from its abstract origin, and not just the namespace name.
TEST_F(Specifications, InlineFunctionInNamespace) {
PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
StartCU();
DIEHandler* space_handler
= StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
"Namespace");
ASSERT_TRUE(space_handler != NULL);
AbstractInstanceDIE(space_handler, 0x1e8dac5d507ed7abULL,
dwarf2reader::DW_INL_inlined, 0LL, "func-name");
DefineInlineInstanceDIE(space_handler, "", 0x1e8dac5d507ed7abULL,
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
space_handler->Finish();
delete space_handler;
root_handler_.Finish();
TestFunctionCount(1);
TestFunction(0, "Namespace::func-name",
0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
}
// Check name construction for a long chain containing each combination of:
// - struct, union, class, namespace
// - direct and definition

View File

@ -64,6 +64,7 @@
#include "common/linux/elfutils-inl.h"
#include "common/linux/elf_symbols_to_module.h"
#include "common/linux/file_id.h"
#include "common/memory.h"
#include "common/module.h"
#include "common/scoped_ptr.h"
#ifndef NO_STABS_SUPPORT
@ -82,14 +83,18 @@ using google_breakpad::DwarfLineToModule;
using google_breakpad::ElfClass;
using google_breakpad::ElfClass32;
using google_breakpad::ElfClass64;
using google_breakpad::FileID;
using google_breakpad::FindElfSectionByName;
using google_breakpad::GetOffset;
using google_breakpad::IsValidElf;
using google_breakpad::kDefaultBuildIdSize;
using google_breakpad::Module;
using google_breakpad::PageAllocator;
#ifndef NO_STABS_SUPPORT
using google_breakpad::StabsToModule;
#endif
using google_breakpad::scoped_ptr;
using google_breakpad::wasteful_vector;
// Define AARCH64 ELF architecture if host machine does not include this define.
#ifndef EM_AARCH64
@ -283,7 +288,8 @@ bool LoadDwarf(const string& dwarf_filename,
// Make a Dwarf2Handler that drives the DIEHandler.
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
// Make a DWARF parser for the compilation unit at OFFSET.
dwarf2reader::CompilationUnit reader(file_context.section_map(),
dwarf2reader::CompilationUnit reader(dwarf_filename,
file_context.section_map(),
offset,
&byte_reader,
&die_dispatcher);
@ -684,32 +690,61 @@ bool LoadSymbols(const string& obj_file,
}
// 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 Shdr* symtab_section =
FindElfSectionByName<ElfClass>(".symtab", SHT_SYMTAB,
sections, names, names_end,
elf_header->e_shnum);
const Shdr* strtab_section =
FindElfSectionByName<ElfClass>(".strtab", SHT_STRTAB,
sections, names, names_end,
elf_header->e_shnum);
if (symtab_section && strtab_section) {
info->LoadedSection(".symtab");
const uint8_t* dynsyms =
const uint8_t* symtab =
GetOffset<ElfClass, uint8_t>(elf_header,
dynsym_section->sh_offset);
const uint8_t* dynstrs =
symtab_section->sh_offset);
const uint8_t* strtab =
GetOffset<ElfClass, uint8_t>(elf_header,
dynstr_section->sh_offset);
strtab_section->sh_offset);
bool result =
ELFSymbolsToModule(dynsyms,
dynsym_section->sh_size,
dynstrs,
dynstr_section->sh_size,
ELFSymbolsToModule(symtab,
symtab_section->sh_size,
strtab,
strtab_section->sh_size,
big_endian,
ElfClass::kAddrSize,
module);
found_usable_info = found_usable_info || result;
} else {
// Look in dynsym only if full symbol table was not 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;
}
}
}
@ -825,25 +860,6 @@ const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) {
}
}
// Format the Elf file identifier in IDENTIFIER as a UUID with the
// dashes removed.
string FormatIdentifier(unsigned char identifier[16]) {
char identifier_str[40];
google_breakpad::FileID::ConvertIdentifierToString(
identifier,
identifier_str,
sizeof(identifier_str));
string id_no_dash;
for (int i = 0; identifier_str[i] != '\0'; ++i)
if (identifier_str[i] != '-')
id_no_dash += identifier_str[i];
// Add an extra "0" by the end. PDB files on Windows have an 'age'
// number appended to the end of the file identifier; this isn't
// really used or necessary on other platforms, but be consistent.
id_no_dash += '0';
return id_no_dash;
}
// Return the non-directory portion of FILENAME: the portion after the
// last slash, or the whole filename if there are no slashes.
string BaseFileName(const string &filename) {
@ -886,18 +902,12 @@ bool SanitizeDebugFile(const typename ElfClass::Ehdr* debug_elf_header,
}
template<typename ElfClass>
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
Module** out_module) {
typedef typename ElfClass::Ehdr Ehdr;
*out_module = NULL;
unsigned char identifier[16];
if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header,
identifier)) {
bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
scoped_ptr<Module>& module) {
PageAllocator allocator;
wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize);
if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) {
fprintf(stderr, "%s: unable to generate file identifier\n",
obj_filename.c_str());
return false;
@ -910,17 +920,39 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
return false;
}
string name = BaseFileName(obj_filename);
string os = "Linux";
// Add an extra "0" at the end. PDB files on Windows have an 'age'
// number appended to the end of the file identifier; this isn't
// really used or necessary on other platforms, but be consistent.
string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0";
module.reset(new Module(name, os, architecture, id));
return true;
}
template<typename ElfClass>
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
Module** out_module) {
typedef typename ElfClass::Ehdr Ehdr;
*out_module = NULL;
scoped_ptr<Module> module;
if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, module)) {
return false;
}
// Figure out what endianness this file is.
bool big_endian;
if (!ElfEndianness<ElfClass>(elf_header, &big_endian))
return false;
string name = BaseFileName(obj_filename);
string os = "Linux";
string id = FormatIdentifier(identifier);
LoadSymbolsInfo<ElfClass> info(debug_dirs);
scoped_ptr<Module> module(new Module(name, os, architecture, id));
if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
!debug_dirs.empty(), &info,
options, module.get())) {
@ -935,7 +967,9 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
if (!LoadELF(debuglink_file, &debug_map_wrapper,
reinterpret_cast<void**>(&debug_elf_header)) ||
!SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file,
obj_filename, architecture, big_endian)) {
obj_filename,
module->architecture().c_str(),
big_endian)) {
return false;
}
@ -993,6 +1027,45 @@ bool WriteSymbolFile(const string &obj_file,
return result;
}
// Read the selected object file's debugging information, and write out the
// header only to |stream|. Return true on success; if an error occurs, report
// it and return false.
bool WriteSymbolFileHeader(const string& obj_file,
std::ostream &sym_stream) {
MmapWrapper map_wrapper;
void* elf_header = NULL;
if (!LoadELF(obj_file, &map_wrapper, &elf_header)) {
fprintf(stderr, "Could not load ELF file: %s\n", obj_file.c_str());
return false;
}
if (!IsValidElf(elf_header)) {
fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str());
return false;
}
int elfclass = ElfClass(elf_header);
scoped_ptr<Module> module;
if (elfclass == ELFCLASS32) {
if (!InitModuleForElfClass<ElfClass32>(
reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, module)) {
fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
return false;
}
} else if (elfclass == ELFCLASS64) {
if (!InitModuleForElfClass<ElfClass64>(
reinterpret_cast<const Elf64_Ehdr*>(elf_header), obj_file, module)) {
fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
return false;
}
} else {
fprintf(stderr, "Unsupported module file: %s\n", obj_file.c_str());
return false;
}
return module->Write(sym_stream, ALL_SYMBOL_DATA);
}
bool ReadSymbolData(const string& obj_file,
const std::vector<string>& debug_dirs,
const DumpOptions& options,

View File

@ -67,6 +67,12 @@ bool WriteSymbolFile(const string &obj_file,
const DumpOptions& options,
std::ostream &sym_stream);
// Read the selected object file's debugging information, and write out the
// header only to |stream|. Return true on success; if an error occurs, report
// it and return false.
bool WriteSymbolFileHeader(const string& obj_file,
std::ostream &sym_stream);
// As above, but simply return the debugging information in MODULE
// instead of writing it to a stream. The caller owns the resulting
// Module object and must delete it when finished.

View File

@ -39,6 +39,7 @@
#include <string.h>
#include <algorithm>
#include <string>
#include "common/linux/elf_gnu_compat.h"
#include "common/linux/elfutils.h"
@ -46,8 +47,13 @@
#include "common/linux/memory_mapped_file.h"
#include "third_party/lss/linux_syscall_support.h"
using std::string;
namespace google_breakpad {
// Used in a few places for backwards-compatibility.
const size_t kMDGUIDSize = sizeof(MDGUID);
FileID::FileID(const char* path) : path_(path) {}
// ELF note name and desc are 32-bits word padded.
@ -58,7 +64,7 @@ FileID::FileID(const char* path) : path_(path) {}
template<typename ElfClass>
static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
uint8_t identifier[kMDGUIDSize]) {
wasteful_vector<uint8_t>& identifier) {
typedef typename ElfClass::Nhdr Nhdr;
const void* section_end = reinterpret_cast<const char*>(section) + length;
@ -76,21 +82,19 @@ static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
return false;
}
const char* build_id = reinterpret_cast<const char*>(note_header) +
const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) +
sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz);
// Copy as many bits of the build ID as will fit
// into the GUID space.
my_memset(identifier, 0, kMDGUIDSize);
memcpy(identifier, build_id,
std::min(kMDGUIDSize, (size_t)note_header->n_descsz));
identifier.insert(identifier.end(),
build_id,
build_id + note_header->n_descsz);
return true;
}
// Attempt to locate a .note.gnu.build-id section in an ELF binary
// and copy as many bytes of it as will fit into |identifier|.
static bool FindElfBuildIDNote(const void *elf_mapped_base,
uint8_t identifier[kMDGUIDSize]) {
// and copy it into |identifier|.
static bool FindElfBuildIDNote(const void* elf_mapped_base,
wasteful_vector<uint8_t>& identifier) {
void* note_section;
size_t note_size;
int elfclass;
@ -116,8 +120,10 @@ static bool FindElfBuildIDNote(const void *elf_mapped_base,
// Attempt to locate the .text section of an ELF binary and generate
// a simple hash by XORing the first page worth of bytes into |identifier|.
static bool HashElfTextSection(const void *elf_mapped_base,
uint8_t identifier[kMDGUIDSize]) {
static bool HashElfTextSection(const void* elf_mapped_base,
wasteful_vector<uint8_t>& identifier) {
identifier.resize(kMDGUIDSize);
void* text_section;
size_t text_size;
if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
@ -126,7 +132,9 @@ static bool HashElfTextSection(const void *elf_mapped_base,
return false;
}
my_memset(identifier, 0, kMDGUIDSize);
// Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
// function backwards-compatible.
my_memset(&identifier[0], 0, kMDGUIDSize);
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096));
while (ptr < ptr_end) {
@ -139,7 +147,7 @@ static bool HashElfTextSection(const void *elf_mapped_base,
// static
bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
uint8_t identifier[kMDGUIDSize]) {
wasteful_vector<uint8_t>& identifier) {
// Look for a build id note first.
if (FindElfBuildIDNote(base, identifier))
return true;
@ -148,7 +156,7 @@ bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
return HashElfTextSection(base, identifier);
}
bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) {
bool FileID::ElfFileIdentifier(wasteful_vector<uint8_t>& identifier) {
MemoryMappedFile mapped_file(path_.c_str(), 0);
if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
return false;
@ -156,13 +164,16 @@ bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) {
return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
}
// This function is not ever called in an unsafe context, so it's OK
// to allocate memory and use libc.
// static
void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
char* buffer, int buffer_length) {
uint8_t identifier_swapped[kMDGUIDSize];
string FileID::ConvertIdentifierToUUIDString(
const wasteful_vector<uint8_t>& identifier) {
uint8_t identifier_swapped[kMDGUIDSize] = { 0 };
// Endian-ness swap to match dump processor expectation.
memcpy(identifier_swapped, identifier, kMDGUIDSize);
memcpy(identifier_swapped, &identifier[0],
std::min(kMDGUIDSize, identifier.size()));
uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
*data1 = htonl(*data1);
uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
@ -170,22 +181,13 @@ void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
*data3 = htons(*data3);
int buffer_idx = 0;
for (unsigned int idx = 0;
(buffer_idx < buffer_length) && (idx < kMDGUIDSize);
++idx) {
int hi = (identifier_swapped[idx] >> 4) & 0x0F;
int lo = (identifier_swapped[idx]) & 0x0F;
if (idx == 4 || idx == 6 || idx == 8 || idx == 10)
buffer[buffer_idx++] = '-';
buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
string result;
for (unsigned int idx = 0; idx < kMDGUIDSize; ++idx) {
char buf[3];
snprintf(buf, sizeof(buf), "%02X", identifier_swapped[idx]);
result.append(buf);
}
// NULL terminate
buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0;
return result;
}
} // namespace google_breakpad

View File

@ -37,10 +37,15 @@
#include <string>
#include "common/linux/guid_creator.h"
#include "common/memory.h"
namespace google_breakpad {
static const size_t kMDGUIDSize = sizeof(MDGUID);
// GNU binutils' ld defaults to 'sha1', which is 160 bits == 20 bytes,
// so this is enough to fit that, which most binaries will use.
// This is just a sensible default for auto_wasteful_vector so most
// callers can get away with stack allocation.
static const size_t kDefaultBuildIdSize = 20;
class FileID {
public:
@ -48,25 +53,25 @@ class FileID {
~FileID() {}
// Load the identifier for the elf file path specified in the constructor into
// |identifier|. Return false if the identifier could not be created for the
// file.
// |identifier|.
//
// The current implementation will look for a .note.gnu.build-id
// section and use that as the file id, otherwise it falls back to
// XORing the first 4096 bytes of the .text section to generate an identifier.
bool ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]);
bool ElfFileIdentifier(wasteful_vector<uint8_t>& identifier);
// Load the identifier for the elf file mapped into memory at |base| into
// |identifier|. Return false if the identifier could not be created for the
// |identifier|. Return false if the identifier could not be created for this
// file.
static bool ElfFileIdentifierFromMappedFile(const void* base,
uint8_t identifier[kMDGUIDSize]);
static bool ElfFileIdentifierFromMappedFile(
const void* base,
wasteful_vector<uint8_t>& identifier);
// Convert the |identifier| data to a NULL terminated string. The string will
// be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE).
// The |buffer| should be at least 37 bytes long to receive all of the data
// and termination. Shorter buffers will contain truncated data.
static void ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
char* buffer, int buffer_length);
// Convert the |identifier| data to a string. The string will
// be formatted as a UUID in all uppercase without dashes.
// (e.g., 22F065BBFC9C49F780FE26A7CEBD7BCE).
static std::string ConvertIdentifierToUUIDString(
const wasteful_vector<uint8_t>& identifier);
private:
// Storage for the path specified

View File

@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string>
#include <vector>
#include "common/linux/elf_gnu_compat.h"
#include "common/linux/elfutils.h"
@ -45,13 +46,11 @@
#include "breakpad_googletest_includes.h"
using namespace google_breakpad;
using google_breakpad::ElfClass32;
using google_breakpad::ElfClass64;
using google_breakpad::SafeReadLink;
using google_breakpad::synth_elf::ELF;
using google_breakpad::synth_elf::Notes;
using google_breakpad::test_assembler::kLittleEndian;
using google_breakpad::test_assembler::Section;
using std::vector;
using ::testing::Types;
namespace {
@ -64,6 +63,8 @@ void PopulateSection(Section* section, int size, int prime_number) {
section->Append(1, (i % prime_number) % 256);
}
typedef wasteful_vector<uint8_t> id_vector;
} // namespace
#ifndef __ANDROID__
@ -87,19 +88,20 @@ TEST(FileIDStripTest, StripSelf) {
sprintf(cmdline, "strip \"%s\"", templ.c_str());
ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
uint8_t identifier1[sizeof(MDGUID)];
uint8_t identifier2[sizeof(MDGUID)];
PageAllocator allocator;
id_vector identifier1(&allocator, kDefaultBuildIdSize);
id_vector identifier2(&allocator, kDefaultBuildIdSize);
FileID fileid1(exe_name);
EXPECT_TRUE(fileid1.ElfFileIdentifier(identifier1));
FileID fileid2(templ.c_str());
EXPECT_TRUE(fileid2.ElfFileIdentifier(identifier2));
char identifier_string1[37];
char identifier_string2[37];
FileID::ConvertIdentifierToString(identifier1, identifier_string1,
37);
FileID::ConvertIdentifierToString(identifier2, identifier_string2,
37);
EXPECT_STREQ(identifier_string1, identifier_string2);
string identifier_string1 =
FileID::ConvertIdentifierToUUIDString(identifier1);
string identifier_string2 =
FileID::ConvertIdentifierToUUIDString(identifier2);
EXPECT_EQ(identifier_string1, identifier_string2);
}
#endif // !__ANDROID__
@ -116,8 +118,22 @@ public:
elfdata = &elfdata_v[0];
}
id_vector make_vector() {
return id_vector(&allocator, kDefaultBuildIdSize);
}
template<size_t N>
string get_file_id(const uint8_t (&data)[N]) {
id_vector expected_identifier(make_vector());
expected_identifier.insert(expected_identifier.end(),
&data[0],
data + N);
return FileID::ConvertIdentifierToUUIDString(expected_identifier);
}
vector<uint8_t> elfdata_v;
uint8_t* elfdata;
PageAllocator allocator;
};
typedef Types<ElfClass32, ElfClass64> ElfClasses;
@ -125,10 +141,8 @@ typedef Types<ElfClass32, ElfClass64> ElfClasses;
TYPED_TEST_CASE(FileIDTest, ElfClasses);
TYPED_TEST(FileIDTest, ElfClass) {
uint8_t identifier[sizeof(MDGUID)];
const char expected_identifier_string[] =
"80808080-8080-0000-0000-008080808080";
char identifier_string[sizeof(expected_identifier_string)];
"80808080808000000000008080808080";
const size_t kTextSectionSize = 128;
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
@ -140,58 +154,106 @@ TYPED_TEST(FileIDTest, ElfClass) {
elf.Finish();
this->GetElfContents(elf);
id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
FileID::ConvertIdentifierToString(identifier, identifier_string,
sizeof(identifier_string));
EXPECT_STREQ(expected_identifier_string, identifier_string);
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
EXPECT_EQ(expected_identifier_string, identifier_string);
}
TYPED_TEST(FileIDTest, BuildID) {
const uint8_t kExpectedIdentifier[sizeof(MDGUID)] =
const uint8_t kExpectedIdentifierBytes[] =
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
char expected_identifier_string[] =
"00000000-0000-0000-0000-000000000000";
FileID::ConvertIdentifierToString(kExpectedIdentifier,
expected_identifier_string,
sizeof(expected_identifier_string));
uint8_t identifier[sizeof(MDGUID)];
char identifier_string[sizeof(expected_identifier_string)];
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13};
const string expected_identifier_string =
this->get_file_id(kExpectedIdentifierBytes);
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
Section text(kLittleEndian);
text.Append(4096, 0);
elf.AddSection(".text", text, SHT_PROGBITS);
Notes notes(kLittleEndian);
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifier,
sizeof(kExpectedIdentifier));
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
sizeof(kExpectedIdentifierBytes));
elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
elf.Finish();
this->GetElfContents(elf);
id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
FileID::ConvertIdentifierToString(identifier, identifier_string,
sizeof(identifier_string));
EXPECT_STREQ(expected_identifier_string, identifier_string);
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
EXPECT_EQ(expected_identifier_string, identifier_string);
}
// Test that a build id note with fewer bytes than usual is handled.
TYPED_TEST(FileIDTest, BuildIDShort) {
const uint8_t kExpectedIdentifierBytes[] =
{0x00, 0x01, 0x02, 0x03};
const string expected_identifier_string =
this->get_file_id(kExpectedIdentifierBytes);
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
Section text(kLittleEndian);
text.Append(4096, 0);
elf.AddSection(".text", text, SHT_PROGBITS);
Notes notes(kLittleEndian);
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
sizeof(kExpectedIdentifierBytes));
elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
elf.Finish();
this->GetElfContents(elf);
id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
EXPECT_EQ(expected_identifier_string, identifier_string);
}
// Test that a build id note with more bytes than usual is handled.
TYPED_TEST(FileIDTest, BuildIDLong) {
const uint8_t kExpectedIdentifierBytes[] =
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
const string expected_identifier_string =
this->get_file_id(kExpectedIdentifierBytes);
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
Section text(kLittleEndian);
text.Append(4096, 0);
elf.AddSection(".text", text, SHT_PROGBITS);
Notes notes(kLittleEndian);
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
sizeof(kExpectedIdentifierBytes));
elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
elf.Finish();
this->GetElfContents(elf);
id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
EXPECT_EQ(expected_identifier_string, identifier_string);
}
TYPED_TEST(FileIDTest, BuildIDPH) {
const uint8_t kExpectedIdentifier[sizeof(MDGUID)] =
const uint8_t kExpectedIdentifierBytes[] =
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
char expected_identifier_string[] =
"00000000-0000-0000-0000-000000000000";
FileID::ConvertIdentifierToString(kExpectedIdentifier,
expected_identifier_string,
sizeof(expected_identifier_string));
uint8_t identifier[sizeof(MDGUID)];
char identifier_string[sizeof(expected_identifier_string)];
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13};
const string expected_identifier_string =
this->get_file_id(kExpectedIdentifierBytes);
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
Section text(kLittleEndian);
@ -200,31 +262,25 @@ TYPED_TEST(FileIDTest, BuildIDPH) {
Notes notes(kLittleEndian);
notes.AddNote(0, "Linux",
reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4);
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifier,
sizeof(kExpectedIdentifier));
notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
sizeof(kExpectedIdentifierBytes));
int note_idx = elf.AddSection(".note", notes, SHT_NOTE);
elf.AddSegment(note_idx, note_idx, PT_NOTE);
elf.Finish();
this->GetElfContents(elf);
id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
FileID::ConvertIdentifierToString(identifier, identifier_string,
sizeof(identifier_string));
EXPECT_STREQ(expected_identifier_string, identifier_string);
string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
EXPECT_EQ(expected_identifier_string, identifier_string);
}
// Test to make sure two files with different text sections produce
// different hashes when not using a build id.
TYPED_TEST(FileIDTest, UniqueHashes) {
char identifier_string_1[] =
"00000000-0000-0000-0000-000000000000";
char identifier_string_2[] =
"00000000-0000-0000-0000-000000000000";
uint8_t identifier_1[sizeof(MDGUID)];
uint8_t identifier_2[sizeof(MDGUID)];
{
ELF elf1(EM_386, TypeParam::kClass, kLittleEndian);
Section foo_1(kLittleEndian);
@ -237,10 +293,11 @@ TYPED_TEST(FileIDTest, UniqueHashes) {
this->GetElfContents(elf1);
}
id_vector identifier_1(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier_1));
FileID::ConvertIdentifierToString(identifier_1, identifier_string_1,
sizeof(identifier_string_1));
string identifier_string_1 =
FileID::ConvertIdentifierToUUIDString(identifier_1);
{
ELF elf2(EM_386, TypeParam::kClass, kLittleEndian);
@ -254,10 +311,11 @@ TYPED_TEST(FileIDTest, UniqueHashes) {
this->GetElfContents(elf2);
}
id_vector identifier_2(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier_2));
FileID::ConvertIdentifierToString(identifier_2, identifier_string_2,
sizeof(identifier_string_2));
string identifier_string_2 =
FileID::ConvertIdentifierToUUIDString(identifier_2);
EXPECT_STRNE(identifier_string_1, identifier_string_2);
EXPECT_NE(identifier_string_1, identifier_string_2);
}

View File

@ -72,7 +72,9 @@ bool HTTPUpload::SendRequest(const string &url,
// We may have been linked statically; if curl_easy_init is in the
// current binary, no need to search for a dynamic version.
void* curl_lib = dlopen(NULL, RTLD_NOW);
if (!curl_lib || dlsym(curl_lib, "curl_easy_init") == NULL) {
if (!CheckCurlLib(curl_lib)) {
fprintf(stderr,
"Failed to open curl lib from binary, use libcurl.so instead\n");
dlerror(); // Clear dlerror before attempting to open libraries.
dlclose(curl_lib);
curl_lib = NULL;
@ -113,6 +115,10 @@ bool HTTPUpload::SendRequest(const string &url,
*(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt");
(*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str());
(*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent);
// Support multithread by disabling timeout handling, would get SIGSEGV with
// Curl_resolv_timeout in stack trace otherwise.
// See https://curl.haxx.se/libcurl/c/threadsafe.html
(*curl_easy_setopt)(curl, CURLOPT_NOSIGNAL, 1);
// Set proxy information if necessary.
if (!proxy.empty())
(*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str());
@ -197,6 +203,13 @@ bool HTTPUpload::SendRequest(const string &url,
return err_code == CURLE_OK;
}
// static
bool HTTPUpload::CheckCurlLib(void* curl_lib) {
return curl_lib &&
dlsym(curl_lib, "curl_easy_init") &&
dlsym(curl_lib, "curl_easy_setopt");
}
// static
bool HTTPUpload::CheckParameters(const map<string, string> &parameters) {
for (map<string, string>::const_iterator pos = parameters.begin();

View File

@ -74,6 +74,9 @@ class HTTPUpload {
// any quote (") characters. Returns true if so.
static bool CheckParameters(const map<string, string> &parameters);
// Checks the curl_lib parameter points to a valid curl lib.
static bool CheckCurlLib(void* curl_lib);
// No instances of this class should be created.
// Disallow all constructors, destructors, and operator=.
HTTPUpload();

View File

@ -35,6 +35,6 @@
// the call fails, IGNORE_RET() can be used to mark the return code as ignored.
// This avoids spurious compiler warnings.
#define IGNORE_RET(x) do { if (x); } while (0)
#define IGNORE_RET(x) do { if (x) {} } while (0)
#endif // COMMON_LINUX_IGNORE_RET_H_

View File

@ -0,0 +1,155 @@
// Copyright (c) 2011 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.
// symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper
// function for linux symbol upload tool.
#include "common/linux/http_upload.h"
#include "common/linux/symbol_upload.h"
#include <assert.h>
#include <stdio.h>
#include <functional>
#include <vector>
namespace google_breakpad {
namespace sym_upload {
void TokenizeByChar(const string &source_string, int c,
std::vector<string> *results) {
assert(results);
string::size_type cur_pos = 0, next_pos = 0;
while ((next_pos = source_string.find(c, cur_pos)) != string::npos) {
if (next_pos != cur_pos)
results->push_back(source_string.substr(cur_pos, next_pos - cur_pos));
cur_pos = next_pos + 1;
}
if (cur_pos < source_string.size() && next_pos != cur_pos)
results->push_back(source_string.substr(cur_pos));
}
//=============================================================================
// Parse out the module line which have 5 parts.
// MODULE <os> <cpu> <uuid> <module-name>
bool ModuleDataForSymbolFile(const string &file,
std::vector<string> *module_parts) {
assert(module_parts);
const size_t kModulePartNumber = 5;
FILE* fp = fopen(file.c_str(), "r");
if (fp) {
char buffer[1024];
if (fgets(buffer, sizeof(buffer), fp)) {
string line(buffer);
string::size_type line_break_pos = line.find_first_of('\n');
if (line_break_pos == string::npos) {
assert(0 && "The file is invalid!");
fclose(fp);
return false;
}
line.resize(line_break_pos);
const char kDelimiter = ' ';
TokenizeByChar(line, kDelimiter, module_parts);
if (module_parts->size() != kModulePartNumber)
module_parts->clear();
}
fclose(fp);
}
return module_parts->size() == kModulePartNumber;
}
//=============================================================================
string CompactIdentifier(const string &uuid) {
std::vector<string> components;
TokenizeByChar(uuid, '-', &components);
string result;
for (size_t i = 0; i < components.size(); ++i)
result += components[i];
return result;
}
//=============================================================================
void Start(Options *options) {
std::map<string, string> parameters;
options->success = false;
std::vector<string> module_parts;
if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
fprintf(stderr, "Failed to parse symbol file!\n");
return;
}
string compacted_id = CompactIdentifier(module_parts[3]);
// Add parameters
if (!options->version.empty())
parameters["version"] = options->version;
// MODULE <os> <cpu> <uuid> <module-name>
// 0 1 2 3 4
parameters["os"] = module_parts[1];
parameters["cpu"] = module_parts[2];
parameters["debug_file"] = module_parts[4];
parameters["code_file"] = module_parts[4];
parameters["debug_identifier"] = compacted_id;
std::map<string, string> files;
files["symbol_file"] = options->symbolsPath;
string response, error;
long response_code;
bool success = HTTPUpload::SendRequest(options->uploadURLStr,
parameters,
files,
options->proxy,
options->proxy_user_pwd,
"",
&response,
&response_code,
&error);
if (!success) {
printf("Failed to send symbol file: %s\n", error.c_str());
printf("Response code: %ld\n", response_code);
printf("Response:\n");
printf("%s\n", response.c_str());
} else if (response_code == 0) {
printf("Failed to send symbol file: No response code\n");
} else if (response_code != 200) {
printf("Failed to send symbol file: Response code %ld\n", response_code);
printf("Response:\n");
printf("%s\n", response.c_str());
} else {
printf("Successfully sent the symbol file.\n");
}
options->success = success;
}
} // namespace sym_upload
} // namespace google_breakpad

View File

@ -0,0 +1,59 @@
// -*- mode: c++ -*-
// Copyright (c) 2011 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.
// symbol_upload.h: helper functions for linux symbol upload tool.
#ifndef COMMON_LINUX_SYMBOL_UPLOAD_H_
#define COMMON_LINUX_SYMBOL_UPLOAD_H_
#include <string>
#include "common/using_std_string.h"
namespace google_breakpad {
namespace sym_upload {
typedef struct {
string symbolsPath;
string uploadURLStr;
string proxy;
string proxy_user_pwd;
string version;
bool success;
} Options;
// Starts upload to symbol server with options.
void Start(Options* options);
} // namespace sym_upload
} // namespace google_breakpad
#endif // COMMON_LINUX_SYMBOL_UPLOAD_H_

View File

@ -27,12 +27,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ARCHS = $(ARCHS_STANDARD_32_64_BIT)
SDKROOT = macosx10.5
GCC_VERSION = 4.2
GCC_VERSION[sdk=macosx10.4][arch=*] = 4.0
GCC_C_LANGUAGE_STANDARD = c99
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES
@ -41,7 +35,10 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = NO
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
GCC_WARN_ABOUT_RETURN_TYPE = YES
GCC_WARN_MISSING_PARENTHESES = YES
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
// Once https://bugs.chromium.org/p/google-breakpad/issues/detail?id=697
// is fixed this should be reenabled.
//GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
GCC_WARN_ABOUT_MISSING_NEWLINE = YES
GCC_WARN_SIGN_COMPARE = YES
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES
@ -51,6 +48,5 @@ GCC_WARN_UNUSED_VARIABLE = YES
GCC_TREAT_WARNINGS_AS_ERRORS = YES
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
DEBUG_INFORMATION_FORMAT[sdk=macosx10.4][arch=*] = stabs
ALWAYS_SEARCH_USER_PATHS = NO

View File

@ -328,6 +328,65 @@ class DumpSymbols::DumperLineToModule:
dwarf2reader::ByteReader *byte_reader_; // WEAK
};
bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
// Select an object file, if SetArchitecture hasn't been called to set one
// explicitly.
if (!selected_object_file_) {
// If there's only one architecture, that's the one.
if (object_files_.size() == 1)
selected_object_file_ = &object_files_[0];
else {
// Look for an object file whose architecture matches our own.
const NXArchInfo *local_arch = NXGetLocalArchInfo();
if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) {
fprintf(stderr, "%s: object file contains more than one"
" architecture, none of which match the current"
" architecture; specify an architecture explicitly"
" with '-a ARCH' to resolve the ambiguity\n",
object_filename_.c_str());
return false;
}
}
}
assert(selected_object_file_);
// Find the name of the selected file's architecture, to appear in
// the MODULE record and in error messages.
const NXArchInfo *selected_arch_info =
google_breakpad::BreakpadGetArchInfoFromCpuType(
selected_object_file_->cputype, selected_object_file_->cpusubtype);
const char *selected_arch_name = selected_arch_info->name;
if (strcmp(selected_arch_name, "i386") == 0)
selected_arch_name = "x86";
// Produce a name to use in error messages that includes the
// filename, and the architecture, if there is more than one.
selected_object_name_ = object_filename_;
if (object_files_.size() > 1) {
selected_object_name_ += ", architecture ";
selected_object_name_ + selected_arch_name;
}
// Compute a module name, to appear in the MODULE record.
string module_name = object_filename_;
module_name = basename(&module_name[0]);
// Choose an identifier string, to appear in the MODULE record.
string identifier = Identifier();
if (identifier.empty())
return false;
identifier += "0";
// Create a module to hold the debugging information.
module.reset(new Module(module_name,
"mac",
selected_arch_name,
identifier));
return true;
}
bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
const mach_o::Reader &macho_reader,
const mach_o::SectionMap &dwarf_sections,
@ -378,7 +437,8 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
// Make a Dwarf2Handler that drives our DIEHandler.
dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
// Make a DWARF parser for the compilation unit at OFFSET.
dwarf2reader::CompilationUnit dwarf_reader(file_context.section_map(),
dwarf2reader::CompilationUnit dwarf_reader(selected_object_name_,
file_context.section_map(),
offset,
&byte_reader,
&die_dispatcher);
@ -535,61 +595,9 @@ bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer &entries,
}
bool DumpSymbols::ReadSymbolData(Module** out_module) {
// Select an object file, if SetArchitecture hasn't been called to set one
// explicitly.
if (!selected_object_file_) {
// If there's only one architecture, that's the one.
if (object_files_.size() == 1)
selected_object_file_ = &object_files_[0];
else {
// Look for an object file whose architecture matches our own.
const NXArchInfo *local_arch = NXGetLocalArchInfo();
if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) {
fprintf(stderr, "%s: object file contains more than one"
" architecture, none of which match the current"
" architecture; specify an architecture explicitly"
" with '-a ARCH' to resolve the ambiguity\n",
object_filename_.c_str());
return false;
}
}
}
assert(selected_object_file_);
// Find the name of the selected file's architecture, to appear in
// the MODULE record and in error messages.
const NXArchInfo *selected_arch_info =
google_breakpad::BreakpadGetArchInfoFromCpuType(
selected_object_file_->cputype, selected_object_file_->cpusubtype);
const char *selected_arch_name = selected_arch_info->name;
if (strcmp(selected_arch_name, "i386") == 0)
selected_arch_name = "x86";
// Produce a name to use in error messages that includes the
// filename, and the architecture, if there is more than one.
selected_object_name_ = object_filename_;
if (object_files_.size() > 1) {
selected_object_name_ += ", architecture ";
selected_object_name_ + selected_arch_name;
}
// Compute a module name, to appear in the MODULE record.
string module_name = object_filename_;
module_name = basename(&module_name[0]);
// Choose an identifier string, to appear in the MODULE record.
string identifier = Identifier();
if (identifier.empty())
scoped_ptr<Module> module;
if (!CreateEmptyModule(module))
return false;
identifier += "0";
// Create a module to hold the debugging information.
scoped_ptr<Module> module(new Module(module_name,
"mac",
selected_arch_name,
identifier));
// Parse the selected object file.
mach_o::Reader::Reporter reporter(selected_object_name_);
@ -624,4 +632,15 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
return false;
}
// Read the selected object file's debugging information, and write out the
// header only to |stream|. Return true on success; if an error occurs, report
// it and return false.
bool DumpSymbols::WriteSymbolFileHeader(std::ostream &stream) {
scoped_ptr<Module> module;
if (!CreateEmptyModule(module))
return false;
return module->Write(stream, symbol_data_);
}
} // namespace google_breakpad

View File

@ -112,6 +112,11 @@ class DumpSymbols {
// return false.
bool WriteSymbolFile(std::ostream &stream);
// Read the selected object file's debugging information, and write out the
// header only to |stream|. Return true on success; if an error occurs, report
// it and return false.
bool WriteSymbolFileHeader(std::ostream &stream);
// As above, but simply return the debugging information in module
// instead of writing it to a stream. The caller owns the resulting
// module object and must delete it when finished.
@ -130,6 +135,10 @@ class DumpSymbols {
// Return an identifier string for the file this DumpSymbols is dumping.
std::string Identifier();
// Creates an empty module object.
bool CreateEmptyModule(scoped_ptr<Module>& module);
// Read debugging information from |dwarf_sections|, which was taken from
// |macho_reader|, and add it to |module|. On success, return true;
// on failure, report the problem and return false.

View File

@ -181,15 +181,15 @@ void Reader::Reporter::LoadCommandRegionTruncated() {
void Reader::Reporter::LoadCommandsOverrun(size_t claimed, size_t i,
LoadCommandType type) {
fprintf(stderr, "%s: file's header claims there are %ld"
" load commands, but load command #%ld",
fprintf(stderr, "%s: file's header claims there are %zu"
" load commands, but load command #%zu",
filename_.c_str(), claimed, i);
if (type) fprintf(stderr, ", of type %d,", type);
fprintf(stderr, " extends beyond the end of the load command region\n");
}
void Reader::Reporter::LoadCommandTooShort(size_t i, LoadCommandType type) {
fprintf(stderr, "%s: the contents of load command #%ld, of type %d,"
fprintf(stderr, "%s: the contents of load command #%zu, of type %d,"
" extend beyond the size given in the load command's header\n",
filename_.c_str(), i, type);
}

View File

@ -26,10 +26,6 @@
#import "GTMObjC2Runtime.h"
#import "GTMUnitTestDevLog.h"
#if !GTM_IPHONE_SDK
#import "GTMGarbageCollection.h"
#endif // !GTM_IPHONE_SDK
#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
#import <stdarg.h>
@ -430,71 +426,3 @@ static int MethodSort(id a, id b, void *context) {
}
@end
// Leak detection
#if !GTM_IPHONE_DEVICE && !GTM_SUPPRESS_RUN_LEAKS_HOOK
// Don't want to get leaks on the iPhone Device as the device doesn't
// have 'leaks'. The simulator does though.
// COV_NF_START
// We don't have leak checking on by default, so this won't be hit.
static void _GTMRunLeaks(void) {
// This is an atexit handler. It runs leaks for us to check if we are
// leaking anything in our tests.
const char* cExclusionsEnv = getenv("GTM_LEAKS_SYMBOLS_TO_IGNORE");
NSMutableString *exclusions = [NSMutableString string];
if (cExclusionsEnv) {
NSString *exclusionsEnv = [NSString stringWithUTF8String:cExclusionsEnv];
NSArray *exclusionsArray = [exclusionsEnv componentsSeparatedByString:@","];
NSString *exclusion;
NSCharacterSet *wcSet = [NSCharacterSet whitespaceCharacterSet];
GTM_FOREACH_OBJECT(exclusion, exclusionsArray) {
exclusion = [exclusion stringByTrimmingCharactersInSet:wcSet];
[exclusions appendFormat:@"-exclude \"%@\" ", exclusion];
}
}
// Clearing out DYLD_ROOT_PATH because iPhone Simulator framework libraries
// are different from regular OS X libraries and leaks will fail to run
// because of missing symbols. Also capturing the output of leaks and then
// pipe rather than a direct pipe, because otherwise if leaks failed,
// the system() call will still be successful. Bug:
// http://code.google.com/p/google-toolbox-for-mac/issues/detail?id=56
NSString *string
= [NSString stringWithFormat:
@"LeakOut=`DYLD_ROOT_PATH='' /usr/bin/leaks %@%d` &&"
@"echo \"$LeakOut\"|/usr/bin/sed -e 's/Leak: /Leaks:0: warning: Leak /'",
exclusions, getpid()];
int ret = system([string UTF8String]);
if (ret) {
fprintf(stderr,
"%s:%d: Error: Unable to run leaks. 'system' returned: %d\n",
__FILE__, __LINE__, ret);
fflush(stderr);
}
}
// COV_NF_END
static __attribute__((constructor)) void _GTMInstallLeaks(void) {
BOOL checkLeaks = YES;
#if !GTM_IPHONE_SDK
checkLeaks = GTMIsGarbageCollectionEnabled() ? NO : YES;
#endif // !GTM_IPHONE_SDK
if (checkLeaks) {
checkLeaks = getenv("GTM_ENABLE_LEAKS") ? YES : NO;
if (checkLeaks) {
// COV_NF_START
// We don't have leak checking on by default, so this won't be hit.
fprintf(stderr, "Leak Checking Enabled\n");
fflush(stderr);
int ret = atexit(&_GTMRunLeaks);
// To avoid unused variable warning when _GTMDevAssert is stripped.
(void)ret;
_GTMDevAssert(ret == 0,
@"Unable to install _GTMRunLeaks as an atexit handler (%d)",
errno);
// COV_NF_END
}
}
}
#endif // !GTM_IPHONE_DEVICE && !GTM_SUPPRESS_RUN_LEAKS_HOOK

View File

@ -64,7 +64,8 @@ class PageAllocator {
: page_size_(getpagesize()),
last_(NULL),
current_page_(NULL),
page_offset_(0) {
page_offset_(0),
pages_allocated_(0) {
}
~PageAllocator() {
@ -112,6 +113,8 @@ class PageAllocator {
return false;
}
unsigned long pages_allocated() { return pages_allocated_; }
private:
uint8_t *GetNPages(size_t num_pages) {
#if defined(__x86_64__) || defined(__aarch64__) || defined(__aarch64__) || \
@ -136,6 +139,8 @@ class PageAllocator {
header->num_pages = num_pages;
last_ = header;
pages_allocated_ += num_pages;
return reinterpret_cast<uint8_t*>(a);
}
@ -157,6 +162,7 @@ class PageAllocator {
PageHeader *last_;
uint8_t *current_page_;
size_t page_offset_;
unsigned long pages_allocated_;
};
// Wrapper to use with STL containers
@ -165,12 +171,30 @@ struct PageStdAllocator : public std::allocator<T> {
typedef typename std::allocator<T>::pointer pointer;
typedef typename std::allocator<T>::size_type size_type;
explicit PageStdAllocator(PageAllocator& allocator): allocator_(allocator) {}
explicit PageStdAllocator(PageAllocator& allocator) : allocator_(allocator),
stackdata_(NULL),
stackdata_size_(0)
{}
template <class Other> PageStdAllocator(const PageStdAllocator<Other>& other)
: allocator_(other.allocator_) {}
: allocator_(other.allocator_),
stackdata_(nullptr),
stackdata_size_(0)
{}
explicit PageStdAllocator(PageAllocator& allocator,
pointer stackdata,
size_type stackdata_size) : allocator_(allocator),
stackdata_(stackdata),
stackdata_size_(stackdata_size)
{}
inline pointer allocate(size_type n, const void* = 0) {
return static_cast<pointer>(allocator_.Alloc(sizeof(T) * n));
const size_type size = sizeof(T) * n;
if (size <= stackdata_size_) {
return stackdata_;
}
return static_cast<pointer>(allocator_.Alloc(size));
}
inline void deallocate(pointer, size_type) {
@ -188,6 +212,8 @@ struct PageStdAllocator : public std::allocator<T> {
template<typename Other> friend struct PageStdAllocator;
PageAllocator& allocator_;
pointer stackdata_;
size_type stackdata_size_;
};
// A wasteful vector is a std::vector, except that it allocates memory from a
@ -200,6 +226,24 @@ class wasteful_vector : public std::vector<T, PageStdAllocator<T> > {
: std::vector<T, PageStdAllocator<T> >(PageStdAllocator<T>(*allocator)) {
std::vector<T, PageStdAllocator<T> >::reserve(size_hint);
}
protected:
wasteful_vector(PageStdAllocator<T> allocator)
: std::vector<T, PageStdAllocator<T> >(allocator) {}
};
// auto_wasteful_vector allocates space on the stack for N entries to avoid
// using the PageAllocator for small data, while still allowing for larger data.
template<class T, unsigned int N>
class auto_wasteful_vector : public wasteful_vector<T> {
T stackdata_[N];
public:
auto_wasteful_vector(PageAllocator* allocator)
: wasteful_vector<T>(
PageStdAllocator<T>(*allocator,
&stackdata_[0],
sizeof(stackdata_))) {
std::vector<T, PageStdAllocator<T> >::reserve(N);
}
};
} // namespace google_breakpad

View File

@ -38,11 +38,13 @@ typedef testing::Test PageAllocatorTest;
TEST(PageAllocatorTest, Setup) {
PageAllocator allocator;
EXPECT_EQ(0U, allocator.pages_allocated());
}
TEST(PageAllocatorTest, SmallObjects) {
PageAllocator allocator;
EXPECT_EQ(0U, allocator.pages_allocated());
for (unsigned i = 1; i < 1024; ++i) {
uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
ASSERT_FALSE(p == NULL);
@ -53,8 +55,10 @@ TEST(PageAllocatorTest, SmallObjects) {
TEST(PageAllocatorTest, LargeObject) {
PageAllocator allocator;
EXPECT_EQ(0U, allocator.pages_allocated());
uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(10000));
ASSERT_FALSE(p == NULL);
EXPECT_EQ(3U, allocator.pages_allocated());
for (unsigned i = 1; i < 10; ++i) {
uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
ASSERT_FALSE(p == NULL);
@ -75,6 +79,7 @@ TEST(WastefulVectorTest, Setup) {
TEST(WastefulVectorTest, Simple) {
PageAllocator allocator_;
EXPECT_EQ(0U, allocator_.pages_allocated());
wasteful_vector<unsigned> v(&allocator_);
for (unsigned i = 0; i < 256; ++i) {
@ -84,6 +89,7 @@ TEST(WastefulVectorTest, Simple) {
}
ASSERT_FALSE(v.empty());
ASSERT_EQ(v.size(), 256u);
EXPECT_EQ(1U, allocator_.pages_allocated());
for (unsigned i = 0; i < 256; ++i)
ASSERT_EQ(v[i], i);
}
@ -91,7 +97,28 @@ TEST(WastefulVectorTest, Simple) {
TEST(WastefulVectorTest, UsesPageAllocator) {
PageAllocator allocator_;
wasteful_vector<unsigned> v(&allocator_);
EXPECT_EQ(1U, allocator_.pages_allocated());
v.push_back(1);
ASSERT_TRUE(allocator_.OwnsPointer(&v[0]));
}
TEST(WastefulVectorTest, AutoWastefulVector) {
PageAllocator allocator_;
EXPECT_EQ(0U, allocator_.pages_allocated());
auto_wasteful_vector<unsigned, 4> v(&allocator_);
EXPECT_EQ(0U, allocator_.pages_allocated());
v.push_back(1);
EXPECT_EQ(0U, allocator_.pages_allocated());
EXPECT_FALSE(allocator_.OwnsPointer(&v[0]));
v.resize(4);
EXPECT_EQ(0U, allocator_.pages_allocated());
EXPECT_FALSE(allocator_.OwnsPointer(&v[0]));
v.resize(10);
EXPECT_EQ(1U, allocator_.pages_allocated());
EXPECT_TRUE(allocator_.OwnsPointer(&v[0]));
}

View File

@ -27,8 +27,8 @@
// (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_STDIO_H
#define GOOGLE_BREAKPAD_COMMON_STDIO_H
#ifndef GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H
#define GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H
#include <stdio.h>
@ -40,4 +40,4 @@ typedef SSIZE_T ssize_t;
#endif
#endif // GOOGLE_BREAKPAD_COMMON_STDIO_H
#endif // GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H

View File

@ -210,7 +210,7 @@ bool FindAndLoadOmapTable(const wchar_t* name,
reinterpret_cast<BYTE*>(&table->at(0)),
&count_read))) {
fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
"data from stream \"%ws\"\n");
"data from stream \"%ws\"\n", name);
return false;
}

View File

@ -975,6 +975,16 @@ bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function,
fprintf(stderr, "failed to get function name\n");
return false;
}
// It's possible for get_name to return an empty string, so
// special-case that.
if (wcscmp(*name, L"") == 0) {
SysFreeString(*name);
// dwarf_cu_to_module.cc uses "<name omitted>", so match that.
*name = SysAllocString(L"<name omitted>");
return true;
}
// If a name comes from get_name because no undecorated form existed,
// it's already formatted properly to be used as output. Don't do any
// additional processing.

View File

@ -3,6 +3,9 @@
/* Define to 1 if you have the <a.out.h> header file. */
#undef HAVE_A_OUT_H
/* define if the compiler supports basic C++11 syntax */
#undef HAVE_CXX11
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

View File

@ -328,6 +328,10 @@ typedef enum {
MD_MEMORY_INFO_LIST_STREAM = 16, /* MDRawMemoryInfoList */
MD_THREAD_INFO_LIST_STREAM = 17,
MD_HANDLE_OPERATION_LIST_STREAM = 18,
MD_TOKEN_STREAM = 19,
MD_JAVASCRIPT_DATA_STREAM = 20,
MD_SYSTEM_MEMORY_INFO_STREAM = 21,
MD_PROCESS_VM_COUNTERS_STREAM = 22,
MD_LAST_RESERVED_STREAM = 0x0000ffff,
/* Breakpad extension types. 0x4767 = "Gg" */

View File

@ -45,6 +45,7 @@
#ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
#define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
#include <cstdint>
#include <vector>
namespace google_breakpad {
@ -61,15 +62,24 @@ class CallStack {
// Resets the CallStack to its initial empty state
void Clear();
const vector<StackFrame*>* frames() const { return &frames_; }
// Set the TID associated with this call stack.
void set_tid(uint32_t tid) { tid_ = tid; }
uint32_t tid() const { return tid_; }
private:
// Stackwalker is responsible for building the frames_ vector.
friend class Stackwalker;
// Storage for pushed frames.
vector<StackFrame*> frames_;
// The TID associated with this call stack. Default to 0 if it's not
// available.
uint32_t tid_;
};
} // namespace google_breakpad

View File

@ -67,6 +67,8 @@ class MicrodumpContext : public DumpContext {
virtual void SetContextARM(MDRawContextARM* arm);
virtual void SetContextARM64(MDRawContextARM64* arm64);
virtual void SetContextX86(MDRawContextX86* x86);
virtual void SetContextMIPS(MDRawContextMIPS* mips32);
virtual void SetContextMIPS64(MDRawContextMIPS* mips64);
};
// This class provides access to microdump memory regions.

View File

@ -46,8 +46,7 @@
namespace google_breakpad {
BasicCodeModules::BasicCodeModules(const CodeModules *that)
: main_address_(0),
map_(new RangeMap<uint64_t, linked_ptr<const CodeModule> >()) {
: main_address_(0), map_() {
BPLOG_IF(ERROR, !that) << "BasicCodeModules::BasicCodeModules requires "
"|that|";
assert(that);
@ -66,30 +65,27 @@ BasicCodeModules::BasicCodeModules(const CodeModules *that)
// GetModuleAtSequence.
linked_ptr<const CodeModule> module(
that->GetModuleAtIndex(module_sequence)->Copy());
if (!map_->StoreRange(module->base_address(), module->size(), module)) {
if (!map_.StoreRange(module->base_address(), module->size(), module)) {
BPLOG(ERROR) << "Module " << module->code_file() <<
" could not be stored";
}
}
}
BasicCodeModules::BasicCodeModules()
: main_address_(0),
map_(new RangeMap<uint64_t, linked_ptr<const CodeModule> >()) {
}
BasicCodeModules::BasicCodeModules() : main_address_(0), map_() { }
BasicCodeModules::~BasicCodeModules() {
delete map_;
}
unsigned int BasicCodeModules::module_count() const {
return map_->GetCount();
return map_.GetCount();
}
const CodeModule* BasicCodeModules::GetModuleForAddress(
uint64_t address) const {
linked_ptr<const CodeModule> module;
if (!map_->RetrieveRange(address, &module, NULL, NULL)) {
if (!map_.RetrieveRange(address, &module, NULL /* base */, NULL /* delta */,
NULL /* size */)) {
BPLOG(INFO) << "No module at " << HexString(address);
return NULL;
}
@ -104,7 +100,8 @@ const CodeModule* BasicCodeModules::GetMainModule() const {
const CodeModule* BasicCodeModules::GetModuleAtSequence(
unsigned int sequence) const {
linked_ptr<const CodeModule> module;
if (!map_->RetrieveRangeAtIndex(sequence, &module, NULL, NULL)) {
if (!map_.RetrieveRangeAtIndex(sequence, &module, NULL /* base */,
NULL /* delta */, NULL /* size */)) {
BPLOG(ERROR) << "RetrieveRangeAtIndex failed for sequence " << sequence;
return NULL;
}

View File

@ -41,13 +41,14 @@
#ifndef PROCESSOR_BASIC_CODE_MODULES_H__
#define PROCESSOR_BASIC_CODE_MODULES_H__
#include <stddef.h>
#include "google_breakpad/processor/code_modules.h"
#include "processor/linked_ptr.h"
#include "processor/range_map.h"
namespace google_breakpad {
template<typename T> class linked_ptr;
template<typename AddressType, typename EntryType> class RangeMap;
class BasicCodeModules : public CodeModules {
public:
// Creates a new BasicCodeModules object given any existing CodeModules
@ -75,7 +76,7 @@ class BasicCodeModules : public CodeModules {
// The map used to contain each CodeModule, keyed by each CodeModule's
// address range.
RangeMap<uint64_t, linked_ptr<const CodeModule> > *map_;
RangeMap<uint64_t, linked_ptr<const CodeModule> > map_;
private:
// Disallow copy constructor and assignment operator.

View File

@ -203,15 +203,16 @@ void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const {
MemAddr function_base;
MemAddr function_size;
MemAddr public_address;
if (functions_.RetrieveNearestRange(address, &func,
&function_base, &function_size) &&
if (functions_.RetrieveNearestRange(address, &func, &function_base,
NULL /* delta */, &function_size) &&
address >= function_base && address - function_base < function_size) {
frame->function_name = func->name;
frame->function_base = frame->module->base_address() + function_base;
linked_ptr<Line> line;
MemAddr line_base;
if (func->lines.RetrieveRange(address, &line, &line_base, NULL)) {
if (func->lines.RetrieveRange(address, &line, &line_base, NULL /* delta */,
NULL /* size */)) {
FileMap::const_iterator it = files_.find(line->source_file_id);
if (it != files_.end()) {
frame->source_file_name = files_.find(line->source_file_id)->second;
@ -256,8 +257,8 @@ WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo(
// comparison in an overflow-friendly way.
linked_ptr<Function> function;
MemAddr function_base, function_size;
if (functions_.RetrieveNearestRange(address, &function,
&function_base, &function_size) &&
if (functions_.RetrieveNearestRange(address, &function, &function_base,
NULL /* delta */, &function_size) &&
address >= function_base && address - function_base < function_size) {
result->parameter_size = function->parameter_size;
result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE;
@ -286,8 +287,8 @@ CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo(
// provides an initial set of register recovery rules. Then, walk
// forward from the initial rule's starting address to frame's
// instruction address, applying delta rules.
if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules,
&initial_base, &initial_size)) {
if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules, &initial_base,
NULL /* delta */, &initial_size)) {
return NULL;
}
@ -482,7 +483,7 @@ bool SymbolParseHelper::ParseFile(char *file_line, long *index,
}
*filename = tokens[1];
if (!filename) {
if (!*filename) {
return false;
}
@ -595,7 +596,7 @@ bool SymbolParseHelper::ParsePublicSymbol(char *public_line,
*stack_param_size < 0) {
return false;
}
*name = tokens[2];
*name = tokens[2];
return true;
}

View File

@ -48,6 +48,7 @@ void CallStack::Clear() {
++iterator) {
delete *iterator;
}
tid_ = 0;
}
} // namespace google_breakpad

View File

@ -54,7 +54,7 @@ class MemoryRegion;
// values, when the PC is at a given address in the current frame's
// function. See the description of 'STACK CFI' records at:
//
// http://code.google.com/p/google-breakpad/wiki/SymbolFiles
// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
//
// To prepare an instance of CFIFrameInfo for use at a given
// instruction, first populate it with the rules from the 'STACK CFI

View File

@ -41,7 +41,7 @@
#include <unistd.h>
#endif // _WIN32
#include "common/stdio.h"
#include "common/stdio_wrapper.h"
#include "processor/logging.h"
namespace google_breakpad {

View File

@ -40,7 +40,7 @@
#include <string>
#include "common/stdio.h"
#include "common/stdio_wrapper.h"
#include "common/using_std_string.h"
#include "processor/logging.h"
#include "processor/pathname_stripper.h"

View File

@ -61,6 +61,8 @@ static const char kStackFirstLineKey[] = ": S 0 ";
static const char kArmArchitecture[] = "arm";
static const char kArm64Architecture[] = "arm64";
static const char kX86Architecture[] = "x86";
static const char kMipsArchitecture[] = "mips";
static const char kMips64Architecture[] = "mips64";
static const char kGpuUnknown[] = "UNKNOWN";
template<typename T>
@ -102,7 +104,7 @@ namespace google_breakpad {
void MicrodumpModules::Add(const CodeModule* module) {
linked_ptr<const CodeModule> module_ptr(module);
if (!map_->StoreRange(module->base_address(), module->size(), module_ptr)) {
if (!map_.StoreRange(module->base_address(), module->size(), module_ptr)) {
BPLOG(ERROR) << "Module " << module->code_file() <<
" could not be stored";
}
@ -131,6 +133,18 @@ void MicrodumpContext::SetContextX86(MDRawContextX86* x86) {
valid_ = true;
}
void MicrodumpContext::SetContextMIPS(MDRawContextMIPS* mips32) {
DumpContext::SetContextFlags(MD_CONTEXT_MIPS);
DumpContext::SetContextMIPS(mips32);
valid_ = true;
}
void MicrodumpContext::SetContextMIPS64(MDRawContextMIPS* mips64) {
DumpContext::SetContextFlags(MD_CONTEXT_MIPS64);
DumpContext::SetContextMIPS(mips64);
valid_ = true;
}
//
// MicrodumpMemoryRegion
@ -281,8 +295,9 @@ Microdump::Microdump(const string& contents)
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;
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
<< " bytes instead of " << sizeof(MDRawContextARM)
<< std::endl;
continue;
}
MDRawContextARM* arm = new MDRawContextARM();
@ -290,8 +305,9 @@ Microdump::Microdump(const string& contents)
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;
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
<< " bytes instead of " << sizeof(MDRawContextARM64)
<< std::endl;
continue;
}
MDRawContextARM64* arm = new MDRawContextARM64();
@ -299,13 +315,34 @@ Microdump::Microdump(const string& contents)
context_->SetContextARM64(arm);
} else if (strcmp(arch.c_str(), kX86Architecture) == 0) {
if (cpu_state_raw.size() != sizeof(MDRawContextX86)) {
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() <<
" bytes instead of " << sizeof(MDRawContextX86) << std::endl;
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
<< " bytes instead of " << sizeof(MDRawContextX86)
<< std::endl;
continue;
}
MDRawContextX86* x86 = new MDRawContextX86();
memcpy(x86, &cpu_state_raw[0], cpu_state_raw.size());
context_->SetContextX86(x86);
} else if (strcmp(arch.c_str(), kMipsArchitecture) == 0) {
if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
<< " bytes instead of " << sizeof(MDRawContextMIPS)
<< std::endl;
continue;
}
MDRawContextMIPS* mips32 = new MDRawContextMIPS();
memcpy(mips32, &cpu_state_raw[0], cpu_state_raw.size());
context_->SetContextMIPS(mips32);
} else if (strcmp(arch.c_str(), kMips64Architecture) == 0) {
if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
<< " bytes instead of " << sizeof(MDRawContextMIPS)
<< std::endl;
continue;
}
MDRawContextMIPS* mips64 = new MDRawContextMIPS();
memcpy(mips64, &cpu_state_raw[0], cpu_state_raw.size());
context_->SetContextMIPS64(mips64);
} else {
std::cerr << "Unsupported architecture: " << arch << std::endl;
}

View File

@ -223,6 +223,48 @@ TEST_F(MicrodumpProcessorTest, TestProcessMultiple) {
ASSERT_EQ(2U, state.threads()->at(0)->frames()->size());
}
TEST_F(MicrodumpProcessorTest, TestProcessMips) {
ProcessState state;
AnalyzeDump("microdump-mips32.dmp", false /* omit_symbols */,
2 /* expected_cpu_count */, &state);
ASSERT_EQ(7U, state.modules()->module_count());
ASSERT_EQ("mips", state.system_info()->cpu);
ASSERT_EQ("3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015",
state.system_info()->os_version);
ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
ASSERT_EQ("blaTest",
state.threads()->at(0)->frames()->at(0)->function_name);
ASSERT_EQ("Crash",
state.threads()->at(0)->frames()->at(1)->function_name);
ASSERT_EQ("main",
state.threads()->at(0)->frames()->at(2)->function_name);
ASSERT_EQ("crash_example",
state.threads()->at(0)->frames()->at(0)->module->debug_file());
}
TEST_F(MicrodumpProcessorTest, TestProcessMips64) {
ProcessState state;
AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */,
1 /* expected_cpu_count */, &state);
ASSERT_EQ(7U, state.modules()->module_count());
ASSERT_EQ("mips64", state.system_info()->cpu);
ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015",
state.system_info()->os_version);
ASSERT_EQ(4U, state.threads()->at(0)->frames()->size());
ASSERT_EQ("blaTest",
state.threads()->at(0)->frames()->at(0)->function_name);
ASSERT_EQ("Crash",
state.threads()->at(0)->frames()->at(1)->function_name);
ASSERT_EQ("main",
state.threads()->at(0)->frames()->at(2)->function_name);
ASSERT_EQ("crash_example",
state.threads()->at(0)->frames()->at(0)->module->debug_file());
}
} // namespace
int main(int argc, char* argv[]) {

View File

@ -57,7 +57,7 @@
#include "processor/range_map-inl.h"
#include "common/scoped_ptr.h"
#include "common/stdio.h"
#include "common/stdio_wrapper.h"
#include "google_breakpad/processor/dump_context.h"
#include "processor/basic_code_module.h"
#include "processor/basic_code_modules.h"
@ -1180,7 +1180,7 @@ bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) {
//
uint32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024; // 1MB
uint32_t MinidumpMemoryRegion::max_bytes_ = 2 * 1024 * 1024; // 2MB
MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump)
@ -1930,9 +1930,8 @@ string MinidumpModule::debug_file() const {
file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name);
} else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) {
// It's actually an MDCVInfoELF structure.
const MDCVInfoELF* cv_record_elf =
reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]);
assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE);
assert(reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])->
cv_signature == MD_CVINFOELF_SIGNATURE);
// For MDCVInfoELF, the debug file is the code file.
file = *name_;
@ -2673,7 +2672,8 @@ const MinidumpModule* MinidumpModuleList::GetModuleForAddress(
}
unsigned int module_index;
if (!range_map_->RetrieveRange(address, &module_index, NULL, NULL)) {
if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */,
NULL /* delta */, NULL /* size */)) {
BPLOG(INFO) << "MinidumpModuleList has no module at " <<
HexString(address);
return NULL;
@ -2709,7 +2709,9 @@ const MinidumpModule* MinidumpModuleList::GetModuleAtSequence(
}
unsigned int module_index;
if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, NULL, NULL)) {
if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index,
NULL /* base */, NULL /* delta */,
NULL /* size */)) {
BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence;
return NULL;
}
@ -2924,7 +2926,8 @@ MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress(
}
unsigned int region_index;
if (!range_map_->RetrieveRange(address, &region_index, NULL, NULL)) {
if (!range_map_->RetrieveRange(address, &region_index, NULL /* base */,
NULL /* delta */, NULL /* size */)) {
BPLOG(INFO) << "MinidumpMemoryList has no memory region at " <<
HexString(address);
return NULL;
@ -4028,7 +4031,8 @@ const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress(
}
unsigned int info_index;
if (!range_map_->RetrieveRange(address, &info_index, NULL, NULL)) {
if (!range_map_->RetrieveRange(address, &info_index, NULL /* base */,
NULL /* delta */, NULL /* size */)) {
BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " <<
HexString(address);
return NULL;
@ -4568,6 +4572,14 @@ static const char* get_stream_name(uint32_t stream_type) {
return "MD_THREAD_INFO_LIST_STREAM";
case MD_HANDLE_OPERATION_LIST_STREAM:
return "MD_HANDLE_OPERATION_LIST_STREAM";
case MD_TOKEN_STREAM:
return "MD_TOKEN_STREAM";
case MD_JAVASCRIPT_DATA_STREAM:
return "MD_JAVASCRIPT_DATA_STREAM";
case MD_SYSTEM_MEMORY_INFO_STREAM:
return "MD_SYSTEM_MEMORY_INFO_STREAM";
case MD_PROCESS_VM_COUNTERS_STREAM:
return "MD_PROCESS_VM_COUNTERS_STREAM";
case MD_LAST_RESERVED_STREAM:
return "MD_LAST_RESERVED_STREAM";
case MD_BREAKPAD_INFO_STREAM:

View File

@ -34,7 +34,7 @@
#include <string>
#include "common/scoped_ptr.h"
#include "common/stdio.h"
#include "common/stdio_wrapper.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/minidump.h"
@ -267,6 +267,7 @@ ProcessResult MinidumpProcessor::Process(
// one bad thread.
BPLOG(ERROR) << "No stackwalker for " << thread_string;
}
stack->set_tid(thread_id);
process_state->threads_.push_back(stack.release());
process_state->thread_memory_regions_.push_back(thread_memory);
}
@ -745,6 +746,19 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
BPLOG(INFO) << "Unknown exception reason " << reason;
break;
}
} else if (raw_system_info->processor_architecture ==
MD_CPU_ARCHITECTURE_X86 ||
raw_system_info->processor_architecture ==
MD_CPU_ARCHITECTURE_AMD64) {
switch (exception_flags) {
case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
reason.append("EXC_I386_GPFLT");
break;
default:
reason.append(flags_string);
BPLOG(INFO) << "Unknown exception reason " << reason;
break;
}
} else {
reason.append(flags_string);
BPLOG(INFO) << "Unknown exception reason " << reason;
@ -795,25 +809,26 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
}
break;
}
case MD_CPU_ARCHITECTURE_AMD64:
case MD_CPU_ARCHITECTURE_X86: {
switch (exception_flags) {
case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION:
reason.append("EXC_I386_INVOP");
break;
case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT:
reason.append("EXC_INVTSSFLT");
reason.append("EXC_I386_INVTSSFLT");
break;
case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT:
reason.append("EXC_SEGNPFLT");
reason.append("EXC_I386_SEGNPFLT");
break;
case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT:
reason.append("EXC_STKFLT");
reason.append("EXC_I386_STKFLT");
break;
case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT:
reason.append("EXC_GPFLT");
reason.append("EXC_I386_GPFLT");
break;
case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT:
reason.append("EXC_ALIGNFLT");
reason.append("EXC_I386_ALIGNFLT");
break;
default:
reason.append(flags_string);
@ -866,6 +881,7 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
}
break;
}
case MD_CPU_ARCHITECTURE_AMD64:
case MD_CPU_ARCHITECTURE_X86: {
switch (exception_flags) {
case MD_EXCEPTION_CODE_MAC_X86_DIV:
@ -966,6 +982,7 @@ string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) {
}
break;
}
case MD_CPU_ARCHITECTURE_AMD64:
case MD_CPU_ARCHITECTURE_X86: {
switch (exception_flags) {
case MD_EXCEPTION_CODE_MAC_X86_SGL:

View File

@ -414,6 +414,7 @@ TEST_F(MinidumpProcessorTest, TestBasicProcessing) {
ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION_WRITE");
ASSERT_EQ(state.crash_address(), 0x45U);
ASSERT_EQ(state.threads()->size(), size_t(1));
EXPECT_EQ((*state.threads())[0]->tid(), 3060U);
ASSERT_EQ(state.requesting_thread(), 0);
EXPECT_EQ(1171480435U, state.time_date_stamp());
EXPECT_EQ(1171480435U, state.process_create_time());

View File

@ -625,6 +625,80 @@ TEST(Dump, CVELFShort) {
ASSERT_EQ("B4CDA95F0000000000000000000000000", md_module->debug_identifier());
}
// Test that a build_id that's very long is handled properly.
TEST(Dump, CVELFLong) {
Dump dump(0, kLittleEndian);
String module_name(dump, "elf module");
Section cv_info(dump);
cv_info
.D32(MD_CVINFOELF_SIGNATURE) // signature
// build_id, lots of bytes
.Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf"
"\x37\x38\xce\xa3\x4a\x87\x01\x02\x03\x04\x05\x06\x07\x08"
"\x09\x0a\x0b\x0c\x0d\x0e\x0f");
const MDRawSystemInfo linux_x86 = {
MD_CPU_ARCHITECTURE_X86, // processor_architecture
6, // processor_level
0xd08, // processor_revision
1, // number_of_processors
0, // product_type
0, // major_version
0, // minor_version
0, // build_number
MD_OS_LINUX, // platform_id
0xdeadbeef, // csd_version_rva
0x100, // suite_mask
0, // reserved2
{ // cpu
{ // x86_cpu_info
{ 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id
0x6d8, // version_information
0xafe9fbff, // feature_information
0xffffffff // amd_extended_cpu_features
}
}
};
String csd_version(dump, "Literally Linux");
SystemInfo system_info(dump, linux_x86, csd_version);
Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd,
module_name,
0xb1054d2a,
0x34571371,
fixed_file_info, // from synth_minidump_unittest_data.h
&cv_info, nullptr);
dump.Add(&module);
dump.Add(&module_name);
dump.Add(&cv_info);
dump.Add(&system_info);
dump.Add(&csd_version);
dump.Finish();
string contents;
ASSERT_TRUE(dump.GetContents(&contents));
istringstream minidump_stream(contents);
Minidump minidump(minidump_stream);
ASSERT_TRUE(minidump.Read());
ASSERT_EQ(2U, minidump.GetDirectoryEntryCount());
MinidumpModuleList *md_module_list = minidump.GetModuleList();
ASSERT_TRUE(md_module_list != NULL);
ASSERT_EQ(1U, md_module_list->module_count());
const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0);
ASSERT_TRUE(md_module != NULL);
// just the build_id, directly
ASSERT_EQ(
"5fa9cdb41053df1b86fab733b4df3738cea34a870102030405060708090a0b0c0d0e0f",
md_module->code_identifier());
// build_id truncated to GUID length and treated as such, with zero
// age appended.
ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier());
}
TEST(Dump, OneSystemInfo) {
Dump dump(0, kLittleEndian);
String csd_version(dump, "Petulant Pierogi");

View File

@ -77,7 +77,7 @@
'pathname_stripper.h',
'postfix_evaluator-inl.h',
'postfix_evaluator.h',
'proc_maps_linux.cc',
'proc_maps_linux.cc',
'process_state.cc',
'range_map-inl.h',
'range_map.h',
@ -154,6 +154,7 @@
'minidump_unittest.cc',
'pathname_stripper_unittest.cc',
'postfix_evaluator_unittest.cc',
'range_map_shrink_down_unittest.cc',
'range_map_unittest.cc',
'stackwalker_address_list_unittest.cc',
'stackwalker_amd64_unittest.cc',

View File

@ -40,16 +40,29 @@
#include <assert.h>
#include "processor/range_map.h"
#include "processor/linked_ptr.h"
#include "processor/logging.h"
namespace google_breakpad {
template<typename AddressType, typename EntryType>
void RangeMap<AddressType, EntryType>::SetEnableShrinkDown(
bool enable_shrink_down) {
enable_shrink_down_ = enable_shrink_down;
}
template<typename AddressType, typename EntryType>
bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
const AddressType &size,
const EntryType &entry) {
return StoreRangeInternal(base, 0 /* delta */, size, entry);
}
template<typename AddressType, typename EntryType>
bool RangeMap<AddressType, EntryType>::StoreRangeInternal(
const AddressType &base, const AddressType &delta,
const AddressType &size, const EntryType &entry) {
AddressType high = base + (size - 1);
// Check for undersize or overflow.
@ -57,9 +70,10 @@ bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
// The processor will hit this case too frequently with common symbol
// files in the size == 0 case, which is more suited to a DEBUG channel.
// Filter those out since there's no DEBUG channel at the moment.
BPLOG_IF(INFO, size != 0) << "StoreRange failed, " << HexString(base) <<
"+" << HexString(size) << ", " <<
HexString(high);
BPLOG_IF(INFO, size != 0) << "StoreRangeInternal failed, "
<< HexString(base) << "+" << HexString(size)
<< ", " << HexString(high)
<< ", delta: " << HexString(delta);
return false;
}
@ -71,53 +85,80 @@ bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
if (iterator_base != iterator_high) {
// Some other range begins in the space used by this range. It may be
// contained within the space used by this range, or it may extend lower.
// Regardless, it is an error.
// The processor hits this case too frequently with common symbol files.
// This is most appropriate for a DEBUG channel, but since none exists now
// simply comment out this logging.
//
// AddressType other_base = iterator_base->second.base();
// AddressType other_size = iterator_base->first - other_base + 1;
// BPLOG(INFO) << "StoreRange failed, an existing range is contained by or "
// "extends lower than the new range: new " <<
// HexString(base) << "+" << HexString(size) <<
// ", existing " << HexString(other_base) << "+" <<
// HexString(other_size);
return false;
// If enable_shrink_down_ is true, shrink the current range down, otherwise
// this is an error.
if (enable_shrink_down_) {
AddressType additional_delta = iterator_base->first - base + 1;
return StoreRangeInternal(base + additional_delta,
delta + additional_delta,
size - additional_delta, entry);
} else {
// The processor hits this case too frequently with common symbol files.
// This is most appropriate for a DEBUG channel, but since none exists
// now simply comment out this logging.
// AddressType other_base = iterator_base->second.base();
// AddressType other_size = iterator_base->first - other_base + 1;
// BPLOG(INFO) << "StoreRangeInternal failed, an existing range is "
// << "overlapping with the new range: new "
// << HexString(base) << "+" << HexString(size)
// << ", existing " << HexString(other_base) << "+"
// << HexString(other_size);
return false;
}
}
if (iterator_high != map_.end()) {
if (iterator_high->second.base() <= high) {
// The range above this one overlaps with this one. It may fully
// contain this range, or it may begin within this range and extend
// higher. Regardless, it's an error.
// The processor hits this case too frequently with common symbol files.
// This is most appropriate for a DEBUG channel, but since none exists now
// simply comment out this logging.
//
// AddressType other_base = iterator_high->second.base();
// AddressType other_size = iterator_high->first - other_base + 1;
// BPLOG(INFO) << "StoreRange failed, an existing range contains or "
// "extends higher than the new range: new " <<
// HexString(base) << "+" << HexString(size) <<
// ", existing " << HexString(other_base) << "+" <<
// HexString(other_size);
return false;
// higher. If enable_shrink_down_ is true, shrink the other range down,
// otherwise this is an error.
if (enable_shrink_down_ && iterator_high->first > high) {
// Shrink the other range down.
AddressType other_high = iterator_high->first;
AddressType additional_delta =
high - iterator_high->second.base() + 1;
EntryType other_entry;
AddressType other_base = AddressType();
AddressType other_size = AddressType();
AddressType other_delta = AddressType();
RetrieveRange(other_high, &other_entry, &other_base, &other_delta,
&other_size);
map_.erase(iterator_high);
map_.insert(MapValue(other_high,
Range(other_base + additional_delta,
other_delta + additional_delta,
other_entry)));
// Retry to store this range.
return StoreRangeInternal(base, delta, size, entry);
} else {
// The processor hits this case too frequently with common symbol files.
// This is most appropriate for a DEBUG channel, but since none exists
// now simply comment out this logging.
//
// AddressType other_base = iterator_high->second.base();
// AddressType other_size = iterator_high->first - other_base + 1;
// BPLOG(INFO) << "StoreRangeInternal failed, an existing range "
// << "contains or extends higher than the new range: new "
// << HexString(base) << "+" << HexString(size)
// << ", existing " << HexString(other_base) << "+"
// << HexString(other_size);
return false;
}
}
}
// Store the range in the map by its high address, so that lower_bound can
// be used to quickly locate a range by address.
map_.insert(MapValue(high, Range(base, entry)));
map_.insert(MapValue(high, Range(base, delta, entry)));
return true;
}
template<typename AddressType, typename EntryType>
bool RangeMap<AddressType, EntryType>::RetrieveRange(
const AddressType &address, EntryType *entry,
AddressType *entry_base, AddressType *entry_size) const {
const AddressType &address, EntryType *entry, AddressType *entry_base,
AddressType *entry_delta, AddressType *entry_size) const {
BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|";
assert(entry);
@ -136,6 +177,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveRange(
*entry = iterator->second.entry();
if (entry_base)
*entry_base = iterator->second.base();
if (entry_delta)
*entry_delta = iterator->second.delta();
if (entry_size)
*entry_size = iterator->first - iterator->second.base() + 1;
@ -145,13 +188,13 @@ bool RangeMap<AddressType, EntryType>::RetrieveRange(
template<typename AddressType, typename EntryType>
bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
const AddressType &address, EntryType *entry,
AddressType *entry_base, AddressType *entry_size) const {
const AddressType &address, EntryType *entry, AddressType *entry_base,
AddressType *entry_delta, AddressType *entry_size) const {
BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|";
assert(entry);
// If address is within a range, RetrieveRange can handle it.
if (RetrieveRange(address, entry, entry_base, entry_size))
if (RetrieveRange(address, entry, entry_base, entry_delta, entry_size))
return true;
// upper_bound gives the first element whose key is greater than address,
@ -167,6 +210,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
*entry = iterator->second.entry();
if (entry_base)
*entry_base = iterator->second.base();
if (entry_delta)
*entry_delta = iterator->second.delta();
if (entry_size)
*entry_size = iterator->first - iterator->second.base() + 1;
@ -176,8 +221,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveNearestRange(
template<typename AddressType, typename EntryType>
bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
int index, EntryType *entry,
AddressType *entry_base, AddressType *entry_size) const {
int index, EntryType *entry, AddressType *entry_base,
AddressType *entry_delta, AddressType *entry_size) const {
BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|";
assert(entry);
@ -195,6 +240,8 @@ bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex(
*entry = iterator->second.entry();
if (entry_base)
*entry_base = iterator->second.base();
if (entry_delta)
*entry_delta = iterator->second.delta();
if (entry_size)
*entry_size = iterator->first - iterator->second.base() + 1;

View File

@ -52,40 +52,55 @@ template<class, class> class RangeMapSerializer;
template<typename AddressType, typename EntryType>
class RangeMap {
public:
RangeMap() : map_() {}
RangeMap() : enable_shrink_down_(false), map_() {}
// |enable_shrink_down| tells whether overlapping ranges can be shrunk down.
// If true, then adding a new range that overlaps with an existing one can
// be a successful operation. The range which ends at the higher address
// will be shrunk down by moving its start position to a higher address so
// that it does not overlap anymore.
void SetEnableShrinkDown(bool enable_shrink_down);
// Inserts a range into the map. Returns false for a parameter error,
// or if the location of the range would conflict with a range already
// stored in the map.
bool StoreRange(const AddressType &base,
const AddressType &size,
// stored in the map. If enable_shrink_down is true and there is an overlap
// between the current range and some other range (already in the map),
// shrink down the range which ends at a higher address.
bool StoreRange(const AddressType &base, const AddressType &size,
const EntryType &entry);
// Locates the range encompassing the supplied address. If there is
// no such range, returns false. entry_base and entry_size, if non-NULL,
// are set to the base and size of the entry's range.
// Locates the range encompassing the supplied address. If there is no such
// range, returns false. entry_base, entry_delta, and entry_size, if
// non-NULL, are set to the base, delta, and size of the entry's range.
// A positive entry delta (> 0) indicates that there was an overlap and the
// entry was shrunk down (original start address was increased by delta).
bool RetrieveRange(const AddressType &address, EntryType *entry,
AddressType *entry_base, AddressType *entry_size) const;
AddressType *entry_base, AddressType *entry_delta,
AddressType *entry_size) const;
// Locates the range encompassing the supplied address, if one exists.
// If no range encompasses the supplied address, locates the nearest range
// to the supplied address that is lower than the address. Returns false
// if no range meets these criteria. entry_base and entry_size, if
// non-NULL, are set to the base and size of the entry's range.
// if no range meets these criteria. entry_base, entry_delta, and entry_size,
// if non-NULL, are set to the base, delta, and size of the entry's range.
// A positive entry delta (> 0) indicates that there was an overlap and the
// entry was shrunk down (original start address was increased by delta).
bool RetrieveNearestRange(const AddressType &address, EntryType *entry,
AddressType *entry_base, AddressType *entry_size)
const;
AddressType *entry_base, AddressType *entry_delta,
AddressType *entry_size) const;
// Treating all ranges as a list ordered by the address spaces that they
// occupy, locates the range at the index specified by index. Returns
// false if index is larger than the number of ranges stored. entry_base
// and entry_size, if non-NULL, are set to the base and size of the entry's
// range.
// false if index is larger than the number of ranges stored. entry_base,
// entry_delta, and entry_size, if non-NULL, are set to the base, delta, and
// size of the entry's range.
// A positive entry delta (> 0) indicates that there was an overlap and the
// entry was shrunk down (original start address was increased by delta).
//
// RetrieveRangeAtIndex is not optimized for speedy operation.
bool RetrieveRangeAtIndex(int index, EntryType *entry,
AddressType *entry_base, AddressType *entry_size)
const;
AddressType *entry_base, AddressType *entry_delta,
AddressType *entry_size) const;
// Returns the number of ranges stored in the RangeMap.
int GetCount() const;
@ -99,12 +114,19 @@ class RangeMap {
friend class ModuleComparer;
friend class RangeMapSerializer<AddressType, EntryType>;
// Same a StoreRange() with the only exception that the |delta| can be
// passed in.
bool StoreRangeInternal(const AddressType &base, const AddressType &delta,
const AddressType &size, const EntryType &entry);
class Range {
public:
Range(const AddressType &base, const EntryType &entry)
: base_(base), entry_(entry) {}
Range(const AddressType &base, const AddressType &delta,
const EntryType &entry)
: base_(base), delta_(delta), entry_(entry) {}
AddressType base() const { return base_; }
AddressType delta() const { return delta_; }
EntryType entry() const { return entry_; }
private:
@ -112,6 +134,9 @@ class RangeMap {
// be stored, because RangeMap uses it as the key to the map.
const AddressType base_;
// The delta when the range is shrunk down.
const AddressType delta_;
// The entry corresponding to a range.
const EntryType entry_;
};
@ -121,6 +146,9 @@ class RangeMap {
typedef typename AddressToRangeMap::const_iterator MapConstIterator;
typedef typename AddressToRangeMap::value_type MapValue;
// Whether overlapping ranges can be shrunk down.
bool enable_shrink_down_;
// Maps the high address of each range to a EntryType.
AddressToRangeMap map_;
};

View File

@ -0,0 +1,355 @@
// Copyright (c) 2016, 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
// range_map_shrink_down_unittest.cc: Unit tests for RangeMap that specifically
// test shrink down when ranges overlap.
//
// Author: Ivan Penkov
#include <limits.h>
#include <stdio.h>
#include "processor/range_map-inl.h"
#include "breakpad_googletest_includes.h"
#include "common/scoped_ptr.h"
#include "processor/linked_ptr.h"
#include "processor/logging.h"
namespace {
using google_breakpad::linked_ptr;
using google_breakpad::scoped_ptr;
using google_breakpad::RangeMap;
// A CountedObject holds an int. A global (not thread safe!) count of
// allocated CountedObjects is maintained to help test memory management.
class CountedObject {
public:
explicit CountedObject(int id) : id_(id) { ++count_; }
~CountedObject() { --count_; }
static int count() { return count_; }
int id() const { return id_; }
private:
static int count_;
int id_;
};
int CountedObject::count_;
typedef int AddressType;
typedef RangeMap<AddressType, linked_ptr<CountedObject>> TestMap;
// Same range cannot be stored wice.
TEST(RangeMap, TestShinkDown_SameRange) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
object_1));
// Same range cannot be stored wice.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_FALSE(range_map.StoreRange(0 /* base address */, 100 /* size */,
object_2));
}
// If a range is completely contained by another range, then the larger range
// should be shrinked down.
TEST(RangeMap, TestShinkDown_CompletelyContained) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
// Larger range is added first.
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
object_1));
// Smaller (contained) range is added second.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */,
object_2));
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_delta = AddressType();
AddressType retrieved_size = AddressType();
// The first range contains the second, so the first range should have been
// shrunk to [90, 99]. Range [0, 9] should be free.
EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(1, object->id());
EXPECT_EQ(90, retrieved_base);
EXPECT_EQ(90, retrieved_delta);
EXPECT_EQ(10, retrieved_size);
// Validate the properties of the smaller range (should be untouched).
EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(2, object->id());
EXPECT_EQ(10, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(80, retrieved_size);
}
// Same as the previous test, however the larger range is added second.
TEST(RangeMap, TestShinkDown_CompletelyContained_LargerAddedSecond) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
// Smaller (contained) range is added first.
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */,
object_1));
// Larger range is added second.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
object_2));
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_delta = AddressType();
AddressType retrieved_size = AddressType();
// The second range contains the first, so the second range should have been
// shrunk to [90, 99]. Range [0, 9] should be free.
EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(2, object->id());
EXPECT_EQ(90, retrieved_base);
EXPECT_EQ(90, retrieved_delta);
EXPECT_EQ(10, retrieved_size);
// Validate the properties of the smaller range (should be untouched).
EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(1, object->id());
EXPECT_EQ(10, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(80, retrieved_size);
}
TEST(RangeMap, TestShinkDown_PartialOverlap_AtBeginning) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
object_1));
// Partial overlap at the beginning of the new range.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_TRUE(range_map.StoreRange(90 /* base address */, 110 /* size */,
object_2));
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_delta = AddressType();
AddressType retrieved_size = AddressType();
// The second range is supposed to be shrunk down so the following address
// should resize in the first range.
EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(1, object->id());
EXPECT_EQ(0, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(100, retrieved_size);
// Validate the properties of the shrunk down range.
EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(2, object->id());
EXPECT_EQ(100, retrieved_base);
EXPECT_EQ(10, retrieved_delta);
EXPECT_EQ(100, retrieved_size);
}
TEST(RangeMap, TestShinkDown_PartialOverlap_AtEnd) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 50 /* size */,
object_1));
// Partial overlap at the end of the new range.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 70 /* size */,
object_2));
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_delta = AddressType();
AddressType retrieved_size = AddressType();
// The first range is supposed to be shrunk down so the following address
// should resize in the first range.
EXPECT_TRUE(range_map.RetrieveRange(69, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(2, object->id());
EXPECT_EQ(0, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(70, retrieved_size);
// Validate the properties of the shrunk down range.
EXPECT_TRUE(range_map.RetrieveRange(70, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(1, object->id());
EXPECT_EQ(70, retrieved_base);
EXPECT_EQ(20, retrieved_delta);
EXPECT_EQ(30, retrieved_size);
}
// A new range is overlapped at both ends. The new range and the range
// that overlaps at the end should be shrink. The range that overlaps at the
// beginning should be left untouched.
TEST(RangeMap, TestShinkDown_OverlapAtBothEnds) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
// This should overlap object_3 at the beginning.
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */,
object_1));
// This should overlap object_3 at the end.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */,
object_2));
// This should be overlapped on both ends by object_1 and object_2.
linked_ptr<CountedObject> object_3(new CountedObject(3));
EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 100 /* size */,
object_3));
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_delta = AddressType();
AddressType retrieved_size = AddressType();
// The first range should be intact.
EXPECT_TRUE(range_map.RetrieveRange(0, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(1, object->id());
EXPECT_EQ(0, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(100, retrieved_size);
// The second range should be shrunk down by 50.
EXPECT_TRUE(range_map.RetrieveRange(150, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(2, object->id());
EXPECT_EQ(150, retrieved_base);
EXPECT_EQ(50, retrieved_delta);
EXPECT_EQ(50, retrieved_size);
// The third range (in the middle) should be shrunk down by 50.
EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(3, object->id());
EXPECT_EQ(100, retrieved_base);
EXPECT_EQ(50, retrieved_delta);
EXPECT_EQ(50, retrieved_size);
}
TEST(RangeMap, TestShinkDown_MultipleConflicts) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
// This should overlap with object_3.
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */,
object_1));
// This should also overlap with object_3 but after object_1.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */,
object_2));
// This should be overlapped on both object_1 and object_2. Since
// object_3 ends with the higher address it must be shrunk.
linked_ptr<CountedObject> object_3(new CountedObject(3));
EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 300 /* size */,
object_3));
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_delta = AddressType();
AddressType retrieved_size = AddressType();
// The first range should be intact.
EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(1, object->id());
EXPECT_EQ(10, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(90, retrieved_size);
// The second range should be intact.
EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(2, object->id());
EXPECT_EQ(100, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(100, retrieved_size);
// The third range should be shrunk down by 200.
EXPECT_TRUE(range_map.RetrieveRange(299, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(3, object->id());
EXPECT_EQ(200, retrieved_base);
EXPECT_EQ(200, retrieved_delta);
EXPECT_EQ(100, retrieved_size);
}
// Adding two ranges without overlap should succeed and the ranges should
// be left intact.
TEST(RangeMap, TestShinkDown_NoConflicts) {
TestMap range_map;
range_map.SetEnableShrinkDown(true);
// Adding range 1.
linked_ptr<CountedObject> object_1(new CountedObject(1));
EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */,
object_1));
// Adding range 2 - no overlap with range 1.
linked_ptr<CountedObject> object_2(new CountedObject(2));
EXPECT_TRUE(range_map.StoreRange(110 /* base address */, 90 /* size */,
object_2));
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_delta = AddressType();
AddressType retrieved_size = AddressType();
// The first range should be intact.
EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(1, object->id());
EXPECT_EQ(10, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(90, retrieved_size);
// The second range should be intact.
EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base,
&retrieved_delta, &retrieved_size));
EXPECT_EQ(2, object->id());
EXPECT_EQ(110, retrieved_base);
EXPECT_EQ(0, retrieved_delta);
EXPECT_EQ(90, retrieved_size);
}
} // namespace

View File

@ -166,8 +166,10 @@ static bool RetrieveTest(TestMap *range_map, const RangeTest *range_test) {
linked_ptr<CountedObject> object;
AddressType retrieved_base = AddressType();
AddressType retrieved_size = AddressType();
AddressType retrieved_delta = AddressType();
bool retrieved = range_map->RetrieveRange(address, &object,
&retrieved_base,
&retrieved_delta,
&retrieved_size);
bool observed_result = retrieved && object->id() == range_test->id;
@ -209,10 +211,12 @@ static bool RetrieveTest(TestMap *range_map, const RangeTest *range_test) {
linked_ptr<CountedObject> nearest_object;
AddressType nearest_base = AddressType();
AddressType nearest_delta = AddressType();
AddressType nearest_size = AddressType();
bool retrieved_nearest = range_map->RetrieveNearestRange(address,
&nearest_object,
&nearest_base,
&nearest_delta,
&nearest_size);
// When checking one greater than the high side, RetrieveNearestRange
@ -274,7 +278,8 @@ static bool RetrieveIndexTest(TestMap *range_map, int set) {
int object_count = range_map->GetCount();
for (int object_index = 0; object_index < object_count; ++object_index) {
AddressType base;
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, NULL)) {
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base,
NULL /* delta */, NULL /* size */)) {
fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, "
"expected success, observed failure\n",
set, object_index);
@ -314,7 +319,8 @@ static bool RetrieveIndexTest(TestMap *range_map, int set) {
// Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that
// are too high.
if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL, NULL)) {
if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL /* base */,
NULL /* delta */, NULL /* size */)) {
fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d (too large), "
"expected failure, observed success\n",
set, object_count);
@ -343,7 +349,8 @@ static bool RetriveAtIndexTest2() {
int object_count = range_map->GetCount();
for (int object_index = 0; object_index < object_count; ++object_index) {
AddressType base;
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, NULL)) {
if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base,
NULL /* delta */, NULL /* size */)) {
fprintf(stderr, "FAILED: RetrieveAtIndexTest2 index %d, "
"expected success, observed failure\n", object_index);
return false;

View File

@ -41,7 +41,7 @@
#include <string>
#include <vector>
#include "common/stdio.h"
#include "common/stdio_wrapper.h"
#include "common/using_std_string.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_module.h"

View File

@ -164,6 +164,12 @@ bool StackwalkerAMD64::IsEndOfStack(uint64_t caller_rip, uint64_t caller_rsp,
return false;
}
// Returns true if `ptr` is not in x86-64 canonical form.
// https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
static bool is_non_canonical(uint64_t ptr) {
return ptr > 0x7FFFFFFFFFFF && ptr < 0xFFFF800000000000;
}
StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery(
const vector<StackFrame*>& frames) {
StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
@ -186,11 +192,22 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery(
// %caller_rip = *(%callee_rbp + 8)
// %caller_rbp = *(%callee_rbp)
// If rbp is not 8-byte aligned it can't be a frame pointer.
if (last_rbp % 8 != 0) {
return NULL;
}
uint64_t caller_rip, caller_rbp;
if (memory_->GetMemoryAtAddress(last_rbp + 8, &caller_rip) &&
memory_->GetMemoryAtAddress(last_rbp, &caller_rbp)) {
uint64_t caller_rsp = last_rbp + 16;
// If the recovered rip is not a canonical address it can't be
// the return address, so rbp must not have been a frame pointer.
if (is_non_canonical(caller_rip)) {
return NULL;
}
// Simple sanity check that the stack is growing downwards as expected.
if (IsEndOfStack(caller_rip, caller_rsp, last_rsp) ||
caller_rbp < last_rbp) {

View File

@ -72,8 +72,8 @@ class StackwalkerAMD64Fixture {
: stack_section(kLittleEndian),
// Give the two modules reasonable standard locations and names
// for tests to play with.
module1(0x40000000c0000000ULL, 0x10000, "module1", "version1"),
module2(0x50000000b0000000ULL, 0x10000, "module2", "version2") {
module1(0x00007400c0000000ULL, 0x10000, "module1", "version1"),
module2(0x00007500b0000000ULL, 0x10000, "module2", "version2") {
// Identify the system as a Linux system.
system_info.os = "Linux";
system_info.os_short = "linux";
@ -149,7 +149,7 @@ TEST_F(SanityCheck, NoResolver) {
// provide any call frame information, so trying to reconstruct the
// context frame's caller should fail. So there's no need for us to
// provide stack contents.
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = 0x8000000080000000ULL;
StackFrameSymbolizer frame_symbolizer(NULL, NULL);
@ -176,7 +176,7 @@ TEST_F(GetContextFrame, Simple) {
// provide any call frame information, so trying to reconstruct the
// context frame's caller should fail. So there's no need for us to
// provide stack contents.
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = 0x8000000080000000ULL;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
@ -200,7 +200,7 @@ TEST_F(GetContextFrame, Simple) {
// The stackwalker should be able to produce the context frame even
// without stack memory present.
TEST_F(GetContextFrame, NoStackMemory) {
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = 0x8000000080000000ULL;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
@ -230,23 +230,23 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
// Force scanning through three frames to ensure that the
// stack pointer is set properly in scan-recovered frames.
stack_section.start() = 0x8000000080000000ULL;
uint64_t return_address1 = 0x50000000b0000100ULL;
uint64_t return_address2 = 0x50000000b0000900ULL;
uint64_t return_address1 = 0x00007500b0000100ULL;
uint64_t return_address2 = 0x00007500b0000900ULL;
Label frame1_sp, frame2_sp, frame1_rbp;
stack_section
// frame 0
.Append(16, 0) // space
.D64(0x40000000b0000000ULL) // junk that's not
.D64(0x50000000d0000000ULL) // a return address
.D64(0x00007400b0000000ULL) // junk that's not
.D64(0x00007500d0000000ULL) // a return address
.D64(return_address1) // actual return address
// frame 1
.Mark(&frame1_sp)
.Append(16, 0) // space
.D64(0x40000000b0000000ULL) // more junk
.D64(0x50000000d0000000ULL)
.D64(0x00007400b0000000ULL) // more junk
.D64(0x00007500d0000000ULL)
.Mark(&frame1_rbp)
.D64(stack_section.start()) // This is in the right place to be
@ -260,7 +260,7 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
RegionFromSection();
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = frame1_rbp.Value();
raw_context.rsp = stack_section.start().Value();
@ -308,18 +308,18 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
// it is only considered a valid return address if it
// lies within a function's bounds.
stack_section.start() = 0x8000000080000000ULL;
uint64_t return_address = 0x50000000b0000110ULL;
uint64_t return_address = 0x00007500b0000110ULL;
Label frame1_sp, frame1_rbp;
stack_section
// frame 0
.Append(16, 0) // space
.D64(0x40000000b0000000ULL) // junk that's not
.D64(0x50000000b0000000ULL) // a return address
.D64(0x00007400b0000000ULL) // junk that's not
.D64(0x00007500b0000000ULL) // a return address
.D64(0x40000000c0001000ULL) // a couple of plausible addresses
.D64(0x50000000b000aaaaULL) // that are not within functions
.D64(0x00007400c0001000ULL) // a couple of plausible addresses
.D64(0x00007500b000aaaaULL) // that are not within functions
.D64(return_address) // actual return address
// frame 1
@ -328,7 +328,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
.Mark(&frame1_rbp);
RegionFromSection();
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = frame1_rbp.Value();
raw_context.rsp = stack_section.start().Value();
@ -355,7 +355,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
EXPECT_EQ("platypus", frame0->function_name);
EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base);
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
@ -367,7 +367,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
EXPECT_EQ("echidna", frame1->function_name);
EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
}
// StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an
@ -502,6 +502,107 @@ TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) {
}
}
// Don't use frame pointer recovery if %rbp is not 8-byte aligned, which
// indicates that it's not being used as a frame pointer.
TEST_F(GetCallerFrame, FramePointerNotAligned) {
stack_section.start() = 0x8000000080000000ULL;
uint64_t return_address1 = 0x00007500b0000100ULL;
Label frame0_rbp, not_frame1_rbp, frame1_sp;
stack_section
// frame 0
.Align(8, 0)
.Append(2, 0) // mis-align the frame pointer
.Mark(&frame0_rbp)
.D64(not_frame1_rbp) // not the previous frame pointer
.D64(0x00007500b0000a00ULL) // plausible but wrong return address
.Align(8, 0)
.D64(return_address1) // return address
// frame 1
.Mark(&frame1_sp)
.Mark(&not_frame1_rbp)
.Append(32, 0); // end of stack
RegionFromSection();
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = frame0_rbp.Value();
raw_context.rsp = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
vector<const CodeModule*> modules_without_symbols;
vector<const CodeModule*> modules_with_corrupt_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
&modules_with_corrupt_symbols));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
StackFrameAMD64::CONTEXT_VALID_RSP),
frame1->context_validity);
EXPECT_EQ(return_address1, frame1->context.rip);
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
}
// Don't use frame pointer recovery if the recovered %rip is not
// a canonical x86-64 address.
TEST_F(GetCallerFrame, NonCanonicalInstructionPointerFromFramePointer) {
stack_section.start() = 0x8000000080000000ULL;
uint64_t return_address1 = 0x00007500b0000100ULL;
Label frame0_rbp, frame1_sp, not_frame1_bp;
stack_section
// frame 0
.Align(8, 0)
.Mark(&frame0_rbp)
.D64(not_frame1_bp) // some junk on the stack
.D64(0xDADADADADADADADA) // not the return address
.D64(return_address1) // return address
// frame 1
.Mark(&frame1_sp)
.Append(16, 0)
.Mark(&not_frame1_bp)
.Append(32, 0); // end of stack
RegionFromSection();
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = frame0_rbp.Value();
raw_context.rsp = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&frame_symbolizer);
vector<const CodeModule*> modules_without_symbols;
vector<const CodeModule*> modules_with_corrupt_symbols;
ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols,
&modules_with_corrupt_symbols));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
StackFrameAMD64::CONTEXT_VALID_RSP),
frame1->context_validity);
EXPECT_EQ(return_address1, frame1->context.rip);
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
}
// Test that set_max_frames_scanned prevents using stack scanning
// to find caller frames.
TEST_F(GetCallerFrame, ScanningNotAllowed) {
@ -509,23 +610,23 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) {
// only addresses located within loaded modules are
// considered valid return addresses.
stack_section.start() = 0x8000000080000000ULL;
uint64_t return_address1 = 0x50000000b0000100ULL;
uint64_t return_address2 = 0x50000000b0000900ULL;
uint64_t return_address1 = 0x00007500b0000100ULL;
uint64_t return_address2 = 0x00007500b0000900ULL;
Label frame1_sp, frame2_sp, frame1_rbp;
stack_section
// frame 0
.Append(16, 0) // space
.D64(0x40000000b0000000ULL) // junk that's not
.D64(0x50000000d0000000ULL) // a return address
.D64(0x00007400b0000000ULL) // junk that's not
.D64(0x00007500d0000000ULL) // a return address
.D64(return_address1) // actual return address
// frame 1
.Mark(&frame1_sp)
.Append(16, 0) // space
.D64(0x40000000b0000000ULL) // more junk
.D64(0x50000000d0000000ULL)
.D64(0x00007400b0000000ULL) // more junk
.D64(0x00007500d0000000ULL)
.Mark(&frame1_rbp)
.D64(stack_section.start()) // This is in the right place to be
@ -539,7 +640,7 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) {
RegionFromSection();
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = frame1_rbp.Value();
raw_context.rsp = stack_section.start().Value();
@ -570,18 +671,18 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
// %rbp directly below the return address, assume that it is indeed the
// next frame's %rbp.
stack_section.start() = 0x8000000080000000ULL;
uint64_t return_address = 0x50000000b0000110ULL;
uint64_t return_address = 0x00007500b0000110ULL;
Label frame0_rbp, frame1_sp, frame1_rbp;
stack_section
// frame 0
.Append(16, 0) // space
.D64(0x40000000b0000000ULL) // junk that's not
.D64(0x50000000b0000000ULL) // a return address
.D64(0x00007400b0000000ULL) // junk that's not
.D64(0x00007500b0000000ULL) // a return address
.D64(0x40000000c0001000ULL) // a couple of plausible addresses
.D64(0x50000000b000aaaaULL) // that are not within functions
.D64(0x00007400c0001000ULL) // a couple of plausible addresses
.D64(0x00007500b000aaaaULL) // that are not within functions
.Mark(&frame0_rbp)
.D64(frame1_rbp) // caller-pushed %rbp
@ -592,7 +693,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
.Mark(&frame1_rbp); // end of stack
RegionFromSection();
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rip = 0x00007400c0000200ULL;
raw_context.rbp = frame0_rbp.Value();
raw_context.rsp = stack_section.start().Value();
@ -620,7 +721,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp);
EXPECT_EQ("sasquatch", frame0->function_name);
EXPECT_EQ(0x40000000c0000100ULL, frame0->function_base);
EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base);
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
@ -632,7 +733,7 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp);
EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp);
EXPECT_EQ("yeti", frame1->function_name);
EXPECT_EQ(0x50000000b0000100ULL, frame1->function_base);
EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base);
}
struct CFIFixture: public StackwalkerAMD64Fixture {
@ -663,7 +764,7 @@ struct CFIFixture: public StackwalkerAMD64Fixture {
// Provide some distinctive values for the caller's registers.
expected.rsp = 0x8000000080000000ULL;
expected.rip = 0x40000000c0005510ULL;
expected.rip = 0x00007400c0005510ULL;
expected.rbp = 0x68995b1de4700266ULL;
expected.rbx = 0x5a5beeb38de23be8ULL;
expected.r12 = 0xed1b02e8cc0fc79cULL;
@ -700,7 +801,7 @@ struct CFIFixture: public StackwalkerAMD64Fixture {
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
EXPECT_EQ("enchiridion", frame0->function_name);
EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base);
EXPECT_EQ(0x00007400c0004000ULL, frame0->function_base);
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
@ -733,9 +834,9 @@ class CFI: public CFIFixture, public Test { };
TEST_F(CFI, At4000) {
Label frame1_rsp = expected.rsp;
stack_section
.D64(0x40000000c0005510ULL) // return address
.D64(0x00007400c0005510ULL) // return address
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
raw_context.rip = 0x40000000c0004000ULL;
raw_context.rip = 0x00007400c0004000ULL;
CheckWalk();
}
@ -743,9 +844,9 @@ TEST_F(CFI, At4001) {
Label frame1_rsp = expected.rsp;
stack_section
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
.D64(0x40000000c0005510ULL) // return address
.D64(0x00007400c0005510ULL) // return address
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
raw_context.rip = 0x40000000c0004001ULL;
raw_context.rip = 0x00007400c0004001ULL;
raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value
CheckWalk();
}
@ -754,9 +855,9 @@ TEST_F(CFI, At4002) {
Label frame1_rsp = expected.rsp;
stack_section
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
.D64(0x40000000c0005510ULL) // return address
.D64(0x00007400c0005510ULL) // return address
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
raw_context.rip = 0x40000000c0004002ULL;
raw_context.rip = 0x00007400c0004002ULL;
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value
CheckWalk();
@ -769,9 +870,9 @@ TEST_F(CFI, At4003) {
.D64(0x1d20ad8acacbe930ULL) // saved %r13
.D64(0x319e68b49e3ace0fULL) // garbage
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
.D64(0x40000000c0005510ULL) // return address
.D64(0x00007400c0005510ULL) // return address
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
raw_context.rip = 0x40000000c0004003ULL;
raw_context.rip = 0x00007400c0004003ULL;
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
@ -786,9 +887,9 @@ TEST_F(CFI, At4004) {
.D64(0x1d20ad8acacbe930ULL) // saved %r13
.D64(0x319e68b49e3ace0fULL) // garbage
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
.D64(0x40000000c0005510ULL) // return address
.D64(0x00007400c0005510ULL) // return address
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
raw_context.rip = 0x40000000c0004004ULL;
raw_context.rip = 0x00007400c0004004ULL;
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12
raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13
@ -804,10 +905,10 @@ TEST_F(CFI, At4005) {
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
.D64(0xaa95fa054aedfbaeULL) // garbage
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
raw_context.rip = 0x40000000c0004005ULL;
raw_context.rip = 0x00007400c0004005ULL;
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12
raw_context.r13 = 0x40000000c0005510ULL; // return address
raw_context.r13 = 0x00007400c0005510ULL; // return address
CheckWalk();
}
@ -822,10 +923,10 @@ TEST_F(CFI, At4006) {
.D64(0x5a5beeb38de23be8ULL) // saved %rbx
.D64(0xf015ee516ad89eabULL) // garbage
.Mark(&frame1_rsp); // This effectively sets stack_section.start().
raw_context.rip = 0x40000000c0004006ULL;
raw_context.rip = 0x00007400c0004006ULL;
raw_context.rbp = frame0_rbp.Value();
raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12
raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12
raw_context.r13 = 0x40000000c0005510ULL; // return address
raw_context.r13 = 0x00007400c0005510ULL; // return address
CheckWalk();
}

View File

@ -180,7 +180,7 @@ class TestValidMap : public ::testing::Test {
void TearDown() {
for (int i = 0;i < kNumberTestCases; ++i)
delete map_data[i];
::operator delete(map_data[i]);
}

View File

@ -35,7 +35,7 @@
#include <string>
#include "common/stdio.h"
#include "common/stdio_wrapper.h"
#include "google_breakpad/common/breakpad_types.h"
#include "google_breakpad/common/minidump_exception_win32.h"
#include "processor/symbolic_constants_win.h"

View File

@ -0,0 +1,37 @@
F/google-breakpad(11976): -----BEGIN BREAKPAD MICRODUMP-----
F/google-breakpad(11976): V UNKNOWN:0.0.0.0
F/google-breakpad(11976): O A mips 02 mips 3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015
F/google-breakpad(11976): G UNKNOWN
F/google-breakpad(11976): S 0 7F92FC38 7F92F000 00002000
F/google-breakpad(11976): S 7F92F000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F92F180 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F92F300 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C801007701000000880140770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094020077010000008801407700000000880200770100000088014077000000005043BD770000000099999999000000000500000000000000030000000945BA7791F4927F0000000090F8927F90F4927F5043BD7700F8927F000000005432B67790F4927F00000000
F/google-breakpad(11976): S 7F92F480 18000077000000005043BD77000000003100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF000000005043BD77000000009402B877FFFFFFFF0000400000004000000040000456B2774041C177000000005043BD7700000000FFFFFFFF9402B87700000000000000005043BD77C000407700000077700FB877000040006805B877E02FBA7700000000C8C6BA77000000005043BD77000000009402B877EC0EB877D02F007723000000C0004077FC0300000030B7770487B7775043BD77044BBF779402B8770000000000000000010000005043BD7700000000020000000000000000000077040000005043BD7754D2BC771E000000E00C4077
F/google-breakpad(11976): S 7F92F600 D02F007701000000C0004077FC0300000030B7770487B777C0004077FC0300000030B7770487B77700000000010000005043BD770030B777000000000000000000000077370000000100000054D2BC770200000060024077C8004077888BB77717000000400A4077C8004077888BB7770100000054D2BC775043BD77A00140771000000000700377007003000030B777C00040772865BD775043BD77FC8CB777C0004077020000000070037780000000C00040772865BD77286AB77760024077C80040774CA4B777286AB777400A4077C80040774CA4B7775043BD7794D2BC770010000060300077C0004077020000005043BD77000000008001407702000000180000000000000028700377DCB0B77700000000000000000000000024AAB7775043BD7780D2BC7750300077180000000004000080D2BC77B8F7927F8C37BD7778D2BC77A0F8927F5043BD773C7EB9775043BD77B8F7927F9837BD779C37BD77B8F7927F8C37BD7778D2BC77A0F8927FE87BBC77307DB9770300000000000000
F/google-breakpad(11976): S 7F92F780 5043BD77FF00000028700377000400005043BD77B8F7927F8C37BD77E03ABD7798A4BA770000000070A7BA7784A6BA7700000000A8A8BA77E87BBC776090B67702000000A0F8927FE03ABD770445BA77A4F9927FA0F9927F7CD2BC77E87BBC7728A6BF7778F5B5778004000000040000A4F9927FF4E0B5775043BD77F844BA77A0F8927F070000005043BD770400BC77A0F8927F070000005043BD77E03ABD775043BD77D0F4B577E03ABD7788EEB5775043BD77E03ABD7700000000E03ABD775043BD7700000000A002007701000000880140770445BA77A4F9927F64DCB3775043BD770000000002000000A0F8927F5043BD770445BA77A4F9927F02000000A0F8927F5426B2779402B877FFFFFFFFA0F9927FA4F9927F5043BD770456B277736F667469727100313736373431313720302032363138303938203020313436D002007701000000880140773431383020313136383631335043BD772031333136373332504E00775043BD77C000000000000000040000000000000000000000
F/google-breakpad(11976): S 7F92F900 0000000024AAB777302030203020302030203020302032335043BD7720302030203020382865BD774000000000010000800000000030BD77504E00771800000050000000004E007702000000100000007CD2BC77E87BBC7728A6BF772C60B9772030203020302030020000000030BD7700000000000000005043BD776CD2BC7740000000DCDEB877203020302030203020302030203020305043BD7720302000010000008CD2BC775043BD77010000005043BD77000000005043BD770030BD77008D4077400000000030BD770030BD770030BD77E4F9B777A8C8B877F0C2B1775043BD770030BD775043BD77010000005043BD770000000000000000C000407768D2BC7770D2BC7702000000C4CFB877FCD185095043BD775043BD77FCD185095043BD7758F1B177C0004077144FB177D02F007701000000C0004077FC0300000030B7770487B77707000000AC50B17700000000B452C07700000000010000005043BD77B866B177040000000000000000000077380000000100000054D2BC77
F/google-breakpad(11976): S 7F92FA80 0100000000024077C8004077888BB7770300000060CDC0775043BD7788C2BE770100000003000000D02F007704000000C0004077FC0300000030B7770487B777C00040772865BD775043BD77FC8CB77700000000010000005043BD77400000005043BD770400000000400000204E00775043BD7700000000000000000400000000000000000000000000000024AAB7770010000030D9BE7704000000040000005043BD7700024077009003772865BD7700000000000000000000000000000000204E00770800000020000000004E00770000000000000000EC17C87700E0C77700E0C7772C60B9774489B7770100000000000000588AB77700000000000000005043BD770800000000000000DCDEB8775043BD7701000000400D4077004000005043BD77009003770000000048B7B7775043BD770450C0775043BD77DCDEB877080000080020C177A80600002090C877040000000100000054FC927F0400000000E0C77784CBC177B00DC177C011BF772090C877000000000800000830800377
F/google-breakpad(11976): S 7F92FC00 000000003828C17700000000000000002472C376E4FC927F5043BD775014C177E4FC927F004000005014C17700E0C77700E0C7778C2BC177C4FC927FC4FC927FC4FC927FC4FC927F2090C877C4FC927FC4FC927FEC10C17700000000E4FD927F010000006C11C1772090C8772472C3760100000000000000E86A98771012C177B0FC927FA821C77700000000000000000000000001000000FFFFFFFF080000002090C8770090BE7700500200E4FD927F03000000FFFFFFFF00000000000000000000000000000000000000000000000014000000FFFFFFFF000000000000000000000000000000006C0FC177000000000000000003000000FFFFFFFF00000000000000000000000000000000000000000000000000000000FFFFFFFF00000000000000000000000000000000030000000400000034FD927F34FD927F0000000040FD927F40FD927F0000000013AD8CAFECFD927F6465B177010000000000000000000000000000005043BD778B0000000100000060C7C077FFFFFFFFE86A9877
F/google-breakpad(11976): S 7F92FD80 00E09677500EC1771C40C07700000000F0FB927F0090C0772090C877CCEDBE77480DC877500DC877580DC877600DC877680DC87700E0967701000000DC0DC1770100000000000000E86A987764B1BE7700000000000000000000000000000000010000007E0B937F000000008E0B937FA00B937FB30B937FD60B937FE10B937FFC0B937F070C937F1E0C937F370C937F4B0C937F640C937FE30C937FFD0C937FB90E937FCE0E937FE10E937F0D0F937F370F937F470F937F510F937F8E0F937FAD0F937FC20F937F000000001000000000000000060000000010000011000000640000000300000034E0C0770400000020000000050000000B000000070000000090BE77080000000000000009000000B00DC1770B000000000000000C000000000000000D000000000000000E00000000000000170000000000000019000000D8FE927F1F000000EC0F937F00000000000000000000000013AD8CAF8ABDF68B3A80A7E02317024E000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F92FF00 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930080 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930200 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930380 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930500 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930680 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930800 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930980 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): S 7F930B00 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E2F63726173685F6578616D706C65005F3D2E2F63726173685F6578616D706C6500414E44524F49445F444154413D2F64617461005345434F4E444152595F53544F524147453D2F73746F726167652F7364636172643100484F4D453D2F6461746100414E44524F49445F4153534554533D2F73797374656D2F617070005445524D3D767431303000414E44524F49445F534F434B45545F616462643D313000414E44524F49445F53544F524147453D2F73746F72616765004D4B53483D2F73797374656D2F62696E2F7368004C4F4F505F4D4F554E54504F494E543D2F6D6E742F6F62620053595354454D534552564552434C415353504154483D2F7379737465
F/google-breakpad(11976): S 7F930C80 6D2F6672616D65776F726B2F73657276696365732E6A61723A2F73797374656D2F6672616D65776F726B2F65746865726E65742D736572766963652E6A61723A2F73797374656D2F6672616D65776F726B2F776966692D736572766963652E6A617200415345435F4D4F554E54504F494E543D2F6D6E742F6173656300424F4F54434C415353504154483D2F73797374656D2F6672616D65776F726B2F636F72652D6C69626172742E6A61723A2F73797374656D2F6672616D65776F726B2F636F6E7363727970742E6A61723A2F73797374656D2F6672616D65776F726B2F6F6B687474702E6A61723A2F73797374656D2F6672616D65776F726B2F636F72652D6A756E69742E6A61723A2F73797374656D2F6672616D65776F726B2F626F756E6379636173746C652E6A61723A2F73797374656D2F6672616D65776F726B2F6578742E6A61723A2F73797374656D2F6672616D65776F726B2F6672616D65776F726B2E6A61723A2F73797374656D2F6672616D65776F726B2F74656C657068
F/google-breakpad(11976): S 7F930E00 6F6E792D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F766F69702D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F696D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F6D6D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F616E64726F69642E706F6C6963792E6A61723A2F73797374656D2F6672616D65776F726B2F6170616368652D786D6C2E6A6172005348454C4C3D2F73797374656D2F62696E2F736800414E44524F49445F424F4F544C4F474F3D3100454D554C415445445F53544F524147455F534F555243453D2F6D6E742F7368656C6C2F656D756C6174656400454D554C415445445F53544F524147455F5441524745543D2F73746F726167652F656D756C6174656400484F53544E414D453D6E706D38303100555345523D726F6F7400504154483D2F7362696E3A2F76656E646F722F62696E3A2F73797374656D2F7362696E3A2F73797374656D2F62696E
F/google-breakpad(11976): S 7F930F80 3A2F73797374656D2F7862696E00414E44524F49445F50524F50455254595F574F524B53504143453D382C3000414E44524F49445F524F4F543D2F73797374656D0045585445524E414C5F53544F524147453D2F73746F726167652F656D756C617465642F6C6567616379002E2F63726173685F6578616D706C650000000000
F/google-breakpad(11976): C 0E0004000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006830007700000000683000770000000068300077000000002865BD770000000000000000000000002870037700000000284400000000000000000000000000003044000000000000ECFD927F00000000E4FD927F0000000001000000000000006C11C1770000000001000000000000002472C376000000000100000000000000000000000000000001000000000000005810C17700000000000000000000000000000000000000002090C8770000000038FC927F00000000E86A987700000000EC10C177000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000007C10C1770000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
F/google-breakpad(11976): M 77C0E000 00000000 0006D000 8F36148CC4647A8116CAF2A25F591F570 crash_example
F/google-breakpad(11976): M 77A9B000 00000000 00012000 3A1A14AAD5B1EB3BC54F2E1C36CE3ACB0 libnetd_client.so
F/google-breakpad(11976): M 77ACD000 00000000 00012000 E8FC3CD6F45E059AD5849A4BEE176D0F0 libstdc++.so
F/google-breakpad(11976): M 77ADF000 00000000 00024000 07C6570597295683DE36D8FE97E6AEC30 libm.so
F/google-breakpad(11976): M 77B03000 00000000 000CB000 D1E0DFA8390BAADD25564F8B0E139FF90 libc.so
F/google-breakpad(11976): M 77BD7000 00000000 00012000 EC0B4DDBEFC52282C34AF60EEEB8EAAA0 liblog.so
F/google-breakpad(11976): M 77BE9000 00000000 00014000 8C70B1BF8FBAC1170EB21E350AB2E7580 linker
F/google-breakpad(11976): -----END BREAKPAD MICRODUMP-----

View File

@ -0,0 +1,26 @@
02-23 15:49:14.700 1740 1739 F google-breakpad: -----BEGIN BREAKPAD MICRODUMP-----
02-23 15:49:14.700 1740 1739 F google-breakpad: V UNKNOWN:0.0.0.0
02-23 15:49:14.702 1740 1739 F google-breakpad: O A mips64 01 mips64 3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015
02-23 15:49:14.702 1740 1739 F google-breakpad: G UNKNOWN
02-23 15:49:14.702 1740 1739 F google-breakpad: S 0 000000FFFFCCF650 000000FFFFCCF000 0000000000001000
02-23 15:49:14.707 1740 1739 F google-breakpad: S 000000FFFFCCF000 FF0000000000000000301DF1FF00000040701DF1FF0000008C7216F1FF000000704F1DF1FF00000000301DF1FF000000604F1DF1FF000000E0511DF1FF00000040701DF1FF0000001C2E16F1FF00000080501DF1FF000000A04F1DF1FF00000090501DF1FF000000E0511DF1FF000000C08416F1FF0000000000000000000000B0501DF1FF000000C08416F1FF0000000000000000000000C0501DF1FF000000C08416F1FF000000000000000000000008521DF1FF000000C08416F1FF0000000000000000000000F8511DF1FF000000C08416F1FF000000000000000000000000000000000000001000F5F0FF0000001000F5F0FF0000001000F5F0FF0000000800F5F0FF0000000010F5F0FF00000001000000000000000010F5F0FF0000000010F5F0FF0000000800F5F0FF0000000010F5F0FF0000000800F5F0FF0000000010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000800F5F0FF0000000010F5F0FF000000
02-23 15:49:14.708 1740 1739 F google-breakpad: S 000000FFFFCCF180 0010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000800F5F0FF000000306042F1FF00000018F4CCFFFF00000018F4CCFFFF0000001010F5F0FF000000306042F1FF000000000000000000000018F4CCFFFF00000018F4CCFFFF000000000000000000000018F4CCFFFF0000000000000000000000000000000000000020F4CCFFFF00000000000000000000000010F5F0FF00000020F4CCFFFF0000000010F5F0FF00000020F4CCFFFF0000000810F5F0FF00000028F4CCFFFF0000000810F5F0FF00000028F4CCFFFF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF00000018F4CCFFFF00000030F4CCFFFF00000030F4CCFFFF0000001010F5F0FF00000030F4CCFFFF0000001010F5F0FF00000030F4CCFFFF0000000010F5F0FF0000000010F5F0FF000000306042F1FF00000060DF38F1FF000000A8F4CCFFFF0000000010F5F0FF0000000040000000000000880000000000000078462EF1FF000000D06B28F1FF000000
02-23 15:49:14.710 1740 1739 F google-breakpad: S 000000FFFFCCF300 01000000000000001010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000010F5F0FF000000FFFFFFFFFFFFFF1F0010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF000000000000000000000018F4CCFFFF00000000F3CCFFFF00000018F4CCFFFF00000000F3CCFFFF0000000010F5F0FF0000000800F5F0FF000000A8F4CCFFFF0000001010F5F0FF0000000800F5F0FF000000A8F4CCFFFF000000A8F4CCFFFF0000001010F5F0FF0000000800F5F0FF000000A8F4CCFFFF000000A8F4CCFFFF0000001010F5F0FF0000000800F5F0FF000000A8F4CCFFFF000000A8F4CCFFFF00000008000000000000000800F5F0FF00000000000000000000000000000000000000000000000000000000000000000000001010F5F0FF00000078F8CCFFFF00000088F8CCFFFF000000306042F1FF00000024BB38F1FF000000FFFFFFFF0100000000000000000000005CA138F1FF0000000000000000000000
02-23 15:49:14.711 1740 1739 F google-breakpad: S 000000FFFFCCF480 A8F6CCFFFF00000008F7CCFFFF000000404538F1FF000000344E33F1FF0000004B3838F1FF00000008F7CCFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF00000098F7CCFFFF000000A8F7CCFFFF000000A8F7CCFFFF000000A8F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000B0F7CCFFFF000000C0F7CCFFFF000000C0F7CCFFFF000000C0F7CCFFFF0000000010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF0000001010F5F0FF0000000010F5F0FF0000000010F5F0FF0000001010F5F0FF0000001010F5F0FF000000389732F1FF000000E09432F1FF00000011000000000000001900000000000000389432F1FF0000007C9432F1FF000000
02-23 15:49:14.713 1740 1739 F google-breakpad: S 000000FFFFCCF600 50C537F1FF000000C8F6CCFFFF0000000000000000000000C8F6CCFFFF000000D100000003000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF000000C8F6CCFFFF0000000000000000000000306042F1FF000000B0A238F1FF00000078F8CCFFFF0000000000000000000000306042F1FF000000B0A338F1FF00000078F8CCFFFF0000000000000001000000000000000000000003000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000000000000000000005CA138F1FF0000000000000000000000000000000000000003000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000
02-23 15:49:14.715 1740 1739 F google-breakpad: S 000000FFFFCCF780 00000000000000000000000000000000030000000400000098F7CCFFFF00000098F7CCFFFF0000000000000000000000B0F7CCFFFF000000B0F7CCFFFF0000000000000000000000EF89807E722BAE6F0820BAECFF00000078F8CCFFFF00000080462EF1FF000000ACBB1FF1FF00000008D537F1FF000000FFFFFFFFFFFFFFFF06261800000000000020B8ECFF000000306042F1FF0000003CA038F1FF000000D8DC41F1FF000000E8DC41F1FF000000F8DC41F1FF00000048C472ECFF000000306042F1FF000000D09F38F1FF0000000626180000000000443333F1FF000000404538F1FF000000000000000000000001000000000000000AFCCCFFFF00000000000000000000001AFCCCFFFF0000002CFCCCFFFF0000003FFCCCFFFF00000053FCCCFFFF0000005EFCCCFFFF00000068FCCCFFFF0000007DFCCCFFFF00000088FCCCFFFF0000009DFCCCFFFF000000B0FCCCFFFF000000C7FCCCFFFF000000E2FCCCFFFF0000008AFECCFFFF000000A4FECCFFFF000000BBFECCFFFF000000
02-23 15:49:14.716 1740 1739 F google-breakpad: S 000000FFFFCCF900 D3FECCFFFF000000F4FECCFFFF0000000DFFCCFFFF0000004AFFCCFFFF000000C9FFCCFFFF00000000000000000000001000000000000000030000000000000006000000000000000010000000000000110000000000000064000000000000000300000000000000402038F1FF0000000400000000000000380000000000000005000000000000000B000000000000000700000000000000009032F1FF000000080000000000000000000000000000000900000000000000A09F38F1FF0000000B0000000000000000000000000000000C0000000000000000000000000000000D0000000000000000000000000000000E00000000000000000000000000000017000000000000000000000000000000190000000000000040FACCFFFF0000001F00000000000000E8FFCCFFFF00000000000000000000000000000000000000EF89807E722BAE6F9B236B56712BD221000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02-23 15:49:14.717 1740 1739 F google-breakpad: S 000000FFFFCCFA80 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
02-23 15:49:14.719 1740 1739 F google-breakpad: S 000000FFFFCCFC00 000000000000000000002E2F63726173685F6578616D706C65005F3D2E2F63726173685F6578616D706C6500414E44524F49445F444154413D2F64617461004D4B53483D2F73797374656D2F62696E2F736800484F4D453D2F6461746100555345523D726F6F7400414E44524F49445F524F4F543D2F73797374656D005445524D3D787465726D005348454C4C3D2F73797374656D2F62696E2F736800414E44524F49445F424F4F544C4F474F3D3100544D504449523D2F646174612F6C6F63616C2F746D7000414E44524F49445F4153534554533D2F73797374656D2F61707000424F4F54434C415353504154483D2F73797374656D2F6672616D65776F726B2F636F72652D6C69626172742E6A61723A2F73797374656D2F6672616D65776F726B2F636F6E7363727970742E6A61723A2F73797374656D2F6672616D65776F726B2F6F6B687474702E6A61723A2F73797374656D2F6672616D65776F726B2F636F72652D6A756E69742E6A61723A2F73797374656D2F6672616D65776F72
02-23 15:49:14.720 1740 1739 F google-breakpad: S 000000FFFFCCFD80 6B2F626F756E6379636173746C652E6A61723A2F73797374656D2F6672616D65776F726B2F6578742E6A61723A2F73797374656D2F6672616D65776F726B2F6672616D65776F726B2E6A61723A2F73797374656D2F6672616D65776F726B2F74656C6570686F6E792D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F766F69702D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F696D732D636F6D6D6F6E2E6A61723A2F73797374656D2F6672616D65776F726B2F6170616368652D786D6C2E6A61723A2F73797374656D2F6672616D65776F726B2F6F72672E6170616368652E687474702E6C65676163792E626F6F742E6A617200415345435F4D4F554E54504F494E543D2F6D6E742F6173656300414E44524F49445F534F434B45545F616462643D313000484F53544E414D453D67656E657269635F6D69707336340045585445524E414C5F53544F524147453D2F73746F726167652F73646361726400414E44524F49445F53544F52
02-23 15:49:14.720 1740 1739 F google-breakpad: S 000000FFFFCCFF00 4147453D2F73746F7261676500504154483D2F7362696E3A2F76656E646F722F62696E3A2F73797374656D2F7362696E3A2F73797374656D2F62696E3A2F73797374656D2F7862696E0053595354454D534552564552434C415353504154483D2F73797374656D2F6672616D65776F726B2F73657276696365732E6A61723A2F73797374656D2F6672616D65776F726B2F65746865726E65742D736572766963652E6A61723A2F73797374656D2F6672616D65776F726B2F776966692D736572766963652E6A617200414E44524F49445F50524F50455254595F574F524B53504143453D392C30002E2F63726173685F6578616D706C65000000000000000000
02-23 15:49:14.723 1740 1739 F google-breakpad: C 0E000800000000000000000000000000010000000000000000000000000000000100000000000000000000000000000038F241F1FF0000000000FFFFFFFFFFFF0000000000000000FFFF000000000000FCFFFFFFFFFFFFFF00000000000000000100000000000000010000000000000000000000000000000100000000000000010000000000000078F8CCFFFF00000088F8CCFFFF00000001000000000000001CA338F1FF00000000001000000000000820BAECFF00000048C472ECFF0000000000000000000000000000000000000028A238F1FF00000010000000000000000000000000000000306042F1FF00000050F6CCFFFF0000000626180000000000B0A238F1FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004CA238F1FF00000000000000000000000000000000000000FFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7FFFFFFFFFFFFFFF7F0000000000000000
02-23 15:49:14.725 1740 1739 F google-breakpad: M 000000FFF1382000 0000000000000000 0000000000081000 6E72E2F1A5F59AB3D51356FDFE394D490 crash_example
02-23 15:49:14.725 1740 1739 F google-breakpad: M 000000FFF0FE2000 0000000000000000 0000000000014000 3C1F908C8C62D8A2EBFC12D8AF285F670 libnetd_client.so
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1016000 0000000000000000 000000000005D000 F53A8A43C039FF5DB65F78E97ADAAE000 libm.so
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1073000 0000000000000000 0000000000014000 906759235C65BD24385BA1376F1C4A0D0 libstdc++.so
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1083000 0000000000000000 0000000000150000 FF1D9D1DA2F0B636817320E78C3E2AF20 libc++.so
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF11D6000 0000000000000000 0000000000109000 3A55BF92DE1E4C51F6F6140479CFA5080 libc.so
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF12ED000 0000000000000000 000000000001C000 44F1FB3127301036FA2EFE040F09CF6C0 liblog.so
02-23 15:49:14.726 1740 1739 F google-breakpad: M 000000FFF1329000 0000000000000000 000000000003A000 519DF595D6558C61E962693B460A31C80 linker64
02-23 15:49:14.726 1740 1739 F google-breakpad: -----END BREAKPAD MICRODUMP-----

View File

@ -0,0 +1,56 @@
MODULE Linux mips 6E72E2F1A5F59AB3D51356FDFE394D490 crash_example
FILE 0 /s/breakpad/src/tools/linux/crash_example.cc
FUNC 80a8 9c 0 google_breakpad::MinidumpDescriptor::MinidumpDescriptor
80a8 20 75 8
80c8 38 78 8
8100 10 78 8
8110 14 78 8
8124 10 78 8
8134 10 78 8
FUNC 815c a0 0 DumpCallback
815c 2c 13 37
8188 1c 14 37
81a4 14 15 37
81b8 1c 15 37
81d4 14 17 37
81e8 4 18 37
81ec 10 19 37
FUNC 81fc 2c 0 Leaf
81fc 10 21 37
820c 8 22 37
8214 8 23 37
821c 4 25 37
8220 8 26 37
FUNC 8228 58 0 blaTest
8228 1c 28 37
8244 c 29 37
8250 20 30 37
8270 10 31 37
FUNC 8280 40 0 Crash
8280 18 33 37
8298 4 34 37
829c 14 35 37
82b0 10 36 37
FUNC 831c f4 0 main
831c 2c 40 37
8348 c 40 37
8354 18 41 37
836c 34 43 37
83a0 10 44 37
83b0 4 45 37
83b4 14 43 37
83c8 18 45 37
83e0 30 46 37
PUBLIC 831c 0 main
STACK CFI INIT 8228 58 .cfa: $sp 0 + .ra: $ra
STACK CFI 822c .cfa: $sp 32 +
STACK CFI 8234 $gp: .cfa -16 + ^ .ra: .cfa -8 + ^
STACK CFI 827c $gp: $gp .cfa: $sp 0 + .ra: .ra
STACK CFI INIT 8280 40 .cfa: $sp 0 + .ra: $ra
STACK CFI 8284 .cfa: $sp 32 +
STACK CFI 828c $gp: .cfa -16 + ^ .ra: .cfa -8 + ^
STACK CFI 82bc $gp: $gp .cfa: $sp 0 + .ra: .ra
STACK CFI INIT 831c f4 .cfa: $sp 0 + .ra: $ra
STACK CFI 8320 .cfa: $sp 352 +
STACK CFI 832c $gp: .cfa -16 + ^ $s0: .cfa -24 + ^ .ra: .cfa -8 + ^
STACK CFI 840c $gp: $gp $s0: $s0 .cfa: $sp 0 + .ra: .ra

View File

@ -0,0 +1,48 @@
MODULE Linux mips 8F36148CC4647A8116CAF2A25F591F570 crash_example
FILE 0 /home/rtrk/chromium_mips/chromium/src/out-android-mips/Debug/../../breakpad/src/tools/linux/crash_example.cc
FUNC 2ea4 b4 0 google_breakpad::MinidumpDescriptor::MinidumpDescriptor
2ea4 20 75 6
2ec4 40 78 6
2f04 18 78 6
2f1c 14 78 6
2f30 18 78 6
2f48 10 78 6
FUNC 2f6c c4 0 DumpCallback
2f6c 28 13 33
2f94 28 14 33
2fbc 1c 15 33
2fd8 28 15 33
3000 1c 17 33
301c 4 18 33
3020 10 19 33
FUNC 3030 28 0 Leaf
3030 4 21 33
3034 c 22 33
3040 c 23 33
304c 4 25 33
3050 8 26 33
FUNC 3058 60 0 blaTest
3058 1c 28 33
3074 c 29 33
3080 28 30 33
30a8 10 31 33
FUNC 30b8 48 0 Crash
30b8 18 33 33
30d0 4 34 33
30d4 1c 35 33
30f0 10 36 33
FUNC 316c 120 0 main
316c 24 40 33
3190 c 40 33
319c 20 41 33
31bc 40 43 33
31fc 18 44 33
3214 4 45 33
3218 1c 43 33
3234 20 45 33
3254 38 46 33
PUBLIC 316c 0 main
STACK CFI INIT 30b8 48 .cfa: $sp 39792944 + .ra: $ra
STACK CFI 30c8 .cfa: $sp 40 +
STACK CFI 30d0 .ra: .cfa -4 + ^
STACK CFI 30f8 .cfa: $sp 0 + .ra: .ra

View File

@ -118,7 +118,7 @@ struct WindowsFrameInfo {
uint64_t &code_size) {
// The format of a STACK WIN record is documented at:
//
// http://code.google.com/p/google-breakpad/wiki/SymbolFiles
// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
std::vector<char> buffer;
StringToVector(string, buffer);

163
src/third_party/musl/COPYRIGHT vendored Normal file
View File

@ -0,0 +1,163 @@
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS 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.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
Authors/contributors include:
Alex Dowad
Alexander Monakov
Anthony G. Basile
Arvid Picciani
Bobby Bingham
Boris Brezillon
Brent Cook
Chris Spiegel
Clément Vasseur
Daniel Micay
Denys Vlasenko
Emil Renner Berthing
Felix Fietkau
Felix Janda
Gianluca Anzolin
Hauke Mehrtens
Hiltjo Posthuma
Isaac Dunham
Jaydeep Patil
Jens Gustedt
Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
Josiah Worcester
Justin Cormack
Khem Raj
Kylie McClain
Luca Barbato
Luka Perkov
M Farkas-Dyck (Strake)
Mahesh Bodapati
Michael Forney
Natanael Copa
Nicholas J. Kain
orc
Pascal Cuoq
Petr Hosek
Pierre Carrier
Rich Felker
Richard Pennington
Shiz
sin
Solar Designer
Stefan Kristiansson
Szabolcs Nagy
Timo Teräs
Trutz Behn
Valentin Ochs
William Haddon
Portions of this software are derived from third-party works licensed
under terms compatible with the above MIT license:
The TRE regular expression implementation (src/regex/reg* and
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
under a 2-clause BSD license (license text in the source files). The
included version has been heavily modified by Rich Felker in 2012, in
the interests of size, simplicity, and namespace cleanliness.
Much of the math library code (src/math/* and src/complex/*) is
Copyright © 1993,2004 Sun Microsystems or
Copyright © 2003-2011 David Schultz or
Copyright © 2003-2009 Steven G. Kargl or
Copyright © 2003-2009 Bruce D. Evans or
Copyright © 2008 Stephen L. Moshier
and labelled as such in comments in the individual source files. All
have been licensed under extremely permissive terms.
The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008
The Android Open Source Project and is licensed under a two-clause BSD
license. It was taken from Bionic libc, used on Android.
The implementation of DES for crypt (src/crypt/crypt_des.c) is
Copyright © 1994 David Burren. It is licensed under a BSD license.
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
originally written by Solar Designer and placed into the public
domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
Valentin Ochs and is licensed under an MIT-style license.
The BSD PRNG implementation (src/prng/random.c) and XSI search API
(src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and
licensed under following terms: "Permission to use, copy, modify,
and/or distribute this code for any purpose with or without fee is
hereby granted. There is no warranty."
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
The mips and microblaze ports were originally written by Richard
Pennington for use in the ellcc project. The original code was adapted
by Rich Felker for build system and code conventions during upstream
integration. It is licensed under the standard MIT terms.
The mips64 port was contributed by Imagination Technologies and is
licensed under the standard MIT terms.
The powerpc port was also originally written by Richard Pennington,
and later supplemented and integrated by John Spencer. It is licensed
under the standard MIT terms.
All other files which have no copyright comments are original works
produced specifically for use as part of this library, written either
by Rich Felker, the main author of the library, or by one or more
contibutors listed above. Details on authorship of individual files
can be found in the git version control history of the project. The
omission of copyright and license comments in each file is in the
interest of source tree size.
In addition, permission is hereby granted for all public header files
(include/* and arch/*/bits/*) and crt files intended to be linked into
applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
the copyright notice and permission notice otherwise required by the
license, and to use these files without any requirement of
attribution. These files include substantial contributions from:
Bobby Bingham
John Spencer
Nicholas J. Kain
Rich Felker
Richard Pennington
Stefan Kristiansson
Szabolcs Nagy
all of whom have explicitly granted such permission.
This file previously contained text expressing a belief that most of
the files covered by the above exception were sufficiently trivial not
to be subject to copyright, resulting in confusion over whether it
negated the permissions granted in the license. In the spirit of
permissive licensing, and of not having licensing issues being an
obstacle to adoption, that text has been removed.

23
src/third_party/musl/README vendored Normal file
View File

@ -0,0 +1,23 @@
musl libc
musl, pronounced like the word "mussel", is an MIT-licensed
implementation of the standard C library targetting the Linux syscall
API, suitable for use in a wide range of deployment environments. musl
offers efficient static and dynamic linking support, lightweight code
and low runtime overhead, strong fail-safe guarantees under correct
usage, and correctness in the sense of standards conformance and
safety. musl is built on the principle that these goals are best
achieved through simple code that is easy to understand and maintain.
The 1.1 release series for musl features coverage for all interfaces
defined in ISO C99 and POSIX 2008 base, along with a number of
non-standardized interfaces for compatibility with Linux, BSD, and
glibc functionality.
For basic installation instructions, see the included INSTALL file.
Information on full musl-targeted compiler toolchains, system
bootstrapping, and Linux distributions built on musl can be found on
the project website:
http://www.musl-libc.org/

3
src/third_party/musl/README.breakpad vendored Normal file
View File

@ -0,0 +1,3 @@
This directory contains the elf header from
https://git.musl-libc.org/cgit/musl/tree/
that is required to get ELF working in dump_syms on Mac OS X.

1
src/third_party/musl/VERSION vendored Normal file
View File

@ -0,0 +1 @@
1.1.14

2827
src/third_party/musl/include/elf.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -39,11 +39,13 @@
#include "common/linux/dump_symbols.h"
using google_breakpad::WriteSymbolFile;
using google_breakpad::WriteSymbolFileHeader;
int usage(const char* self) {
fprintf(stderr, "Usage: %s [OPTION] <binary-with-debugging-info> "
"[directories-for-debug-file]\n\n", self);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -i: Output module header information only.\n");
fprintf(stderr, " -c Do not generate CFI section\n");
fprintf(stderr, " -r Do not handle inter-compilation unit references\n");
fprintf(stderr, " -v Print all warnings to stderr\n");
@ -53,27 +55,29 @@ int usage(const char* self) {
int main(int argc, char **argv) {
if (argc < 2)
return usage(argv[0]);
bool header_only = false;
bool cfi = true;
bool handle_inter_cu_refs = true;
bool log_to_stderr = false;
int arg_index = 1;
while (arg_index < argc && strlen(argv[arg_index]) > 0 &&
argv[arg_index][0] == '-') {
if (strcmp("-c", argv[arg_index]) == 0) {
if (strcmp("-i", argv[arg_index]) == 0) {
header_only = true;
} else if (strcmp("-c", argv[arg_index]) == 0) {
cfi = false;
} else if (strcmp("-r", argv[arg_index]) == 0) {
handle_inter_cu_refs = false;
} else if (strcmp("-v", argv[arg_index]) == 0) {
log_to_stderr = true;
} else {
printf("2.4 %s\n", argv[arg_index]);
return usage(argv[0]);
}
++arg_index;
}
if (arg_index == argc)
return usage(argv[0]);
// Save stderr so it can be used below.
FILE* saved_stderr = fdopen(dup(fileno(stderr)), "w");
if (!log_to_stderr) {
@ -82,7 +86,6 @@ int main(int argc, char **argv) {
// Add this brace section to silence gcc warnings.
}
}
const char* binary;
std::vector<string> debug_dirs;
binary = argv[arg_index];
@ -92,11 +95,18 @@ int main(int argc, char **argv) {
debug_dirs.push_back(argv[debug_dir_index]);
}
SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI;
google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs);
if (!WriteSymbolFile(binary, debug_dirs, options, std::cout)) {
fprintf(saved_stderr, "Failed to write symbol file.\n");
return 1;
if (header_only) {
if (!WriteSymbolFileHeader(binary, std::cout)) {
fprintf(saved_stderr, "Failed to process file.\n");
return 1;
}
} else {
SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI;
google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs);
if (!WriteSymbolFile(binary, debug_dirs, options, std::cout)) {
fprintf(saved_stderr, "Failed to write symbol file.\n");
return 1;
}
}
return 0;

View File

@ -39,138 +39,13 @@
// cpu: the CPU that the module was built for
// symbol_file: the contents of the breakpad-format symbol file
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include "common/linux/symbol_upload.h"
#include "common/linux/http_upload.h"
#include "common/using_std_string.h"
using google_breakpad::HTTPUpload;
typedef struct {
string symbolsPath;
string uploadURLStr;
string proxy;
string proxy_user_pwd;
string version;
bool success;
} Options;
static void TokenizeByChar(const string &source_string,
int c, std::vector<string> *results) {
assert(results);
string::size_type cur_pos = 0, next_pos = 0;
while ((next_pos = source_string.find(c, cur_pos)) != string::npos) {
if (next_pos != cur_pos)
results->push_back(source_string.substr(cur_pos, next_pos - cur_pos));
cur_pos = next_pos + 1;
}
if (cur_pos < source_string.size() && next_pos != cur_pos)
results->push_back(source_string.substr(cur_pos));
}
//=============================================================================
// Parse out the module line which have 5 parts.
// MODULE <os> <cpu> <uuid> <module-name>
static bool ModuleDataForSymbolFile(const string &file,
std::vector<string> *module_parts) {
assert(module_parts);
const size_t kModulePartNumber = 5;
FILE* fp = fopen(file.c_str(), "r");
if (fp) {
char buffer[1024];
if (fgets(buffer, sizeof(buffer), fp)) {
string line(buffer);
string::size_type line_break_pos = line.find_first_of('\n');
if (line_break_pos == string::npos) {
assert(0 && "The file is invalid!");
fclose(fp);
return false;
}
line.resize(line_break_pos);
const char kDelimiter = ' ';
TokenizeByChar(line, kDelimiter, module_parts);
if (module_parts->size() != kModulePartNumber)
module_parts->clear();
}
fclose(fp);
}
return module_parts->size() == kModulePartNumber;
}
//=============================================================================
static string CompactIdentifier(const string &uuid) {
std::vector<string> components;
TokenizeByChar(uuid, '-', &components);
string result;
for (size_t i = 0; i < components.size(); ++i)
result += components[i];
return result;
}
//=============================================================================
static void Start(Options *options) {
std::map<string, string> parameters;
options->success = false;
std::vector<string> module_parts;
if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
fprintf(stderr, "Failed to parse symbol file!\n");
return;
}
string compacted_id = CompactIdentifier(module_parts[3]);
// Add parameters
if (!options->version.empty())
parameters["version"] = options->version;
// MODULE <os> <cpu> <uuid> <module-name>
// 0 1 2 3 4
parameters["os"] = module_parts[1];
parameters["cpu"] = module_parts[2];
parameters["debug_file"] = module_parts[4];
parameters["code_file"] = module_parts[4];
parameters["debug_identifier"] = compacted_id;
std::map<string, string> files;
files["symbol_file"] = options->symbolsPath;
string response, error;
long response_code;
bool success = HTTPUpload::SendRequest(options->uploadURLStr,
parameters,
files,
options->proxy,
options->proxy_user_pwd,
"",
&response,
&response_code,
&error);
if (!success) {
printf("Failed to send symbol file: %s\n", error.c_str());
printf("Response code: %ld\n", response_code);
printf("Response:\n");
printf("%s\n", response.c_str());
} else if (response_code == 0) {
printf("Failed to send symbol file: No response code\n");
} else if (response_code != 200) {
printf("Failed to send symbol file: Response code %ld\n", response_code);
printf("Response:\n");
printf("%s\n", response.c_str());
} else {
printf("Successfully sent the symbol file.\n");
}
options->success = success;
}
using google_breakpad::sym_upload::Options;
//=============================================================================
static void
@ -232,6 +107,6 @@ SetupOptions(int argc, const char *argv[], Options *options) {
int main(int argc, const char* argv[]) {
Options options;
SetupOptions(argc, argv, &options);
Start(&options);
google_breakpad::sym_upload::Start(&options);
return options.success ? 0 : 1;
}

View File

@ -36,6 +36,8 @@
162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
162F6500161C5F2200CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64F8161C591500CD68D5 /* arch_utilities.cc */; };
4D72CAF513DFBAC2006CABE3 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D72CAF413DFBAC2006CABE3 /* md5.cc */; };
8BCAAA4C1CE3A7980046090B /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */; };
8BCAAA4D1CE3B1260046090B /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8BCAAA4A1CE3A7980046090B /* elf_reader.cc */; };
B84A91F8116CF78F006C210E /* libgtestmockall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88FB024116BDFFF00407530 /* libgtestmockall.a */; };
B84A91FB116CF7AF006C210E /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE241166603300407530 /* module.cc */; };
B84A91FC116CF7AF006C210E /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = B88FAE3C11666C8900407530 /* stabs_to_module.cc */; };
@ -280,6 +282,8 @@
8B31023E11F0CF1C00FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
8BCAAA4A1CE3A7980046090B /* elf_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = elf_reader.cc; path = ../../../common/dwarf/elf_reader.cc; sourceTree = "<group>"; };
8BCAAA4B1CE3A7980046090B /* elf_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = elf_reader.h; path = ../../../common/dwarf/elf_reader.h; sourceTree = "<group>"; };
9BDF186D0B1BB43700F8391B /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = "<group>"; };
9BDF186E0B1BB43700F8391B /* dump_syms_tool.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dump_syms_tool.cc; sourceTree = "<group>"; };
9BE650410B52F6D800611104 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
@ -613,6 +617,8 @@
B88FAE1711665FE400407530 /* dwarf2diehandler.cc */,
B88FAE1811665FE400407530 /* dwarf2diehandler.h */,
B88FB0DB116CEC5800407530 /* dwarf2diehandler_unittest.cc */,
8BCAAA4A1CE3A7980046090B /* elf_reader.cc */,
8BCAAA4B1CE3A7980046090B /* elf_reader.h */,
);
name = DWARF;
sourceTree = "<group>";
@ -887,6 +893,8 @@
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
};
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "dump_syms" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
@ -954,6 +962,7 @@
files = (
B88FAF38116A595400407530 /* dwarf2reader_cfi_unittest.cc in Sources */,
B88FAF3F116A5A2E00407530 /* dwarf2reader.cc in Sources */,
8BCAAA4D1CE3B1260046090B /* elf_reader.cc in Sources */,
B88FAF40116A5A2E00407530 /* bytereader.cc in Sources */,
B88FAF37116A595400407530 /* cfi_assembler.cc in Sources */,
);
@ -1071,6 +1080,7 @@
files = (
162F64FA161C591500CD68D5 /* arch_utilities.cc in Sources */,
B88FAE2C1166606200407530 /* macho_reader.cc in Sources */,
8BCAAA4C1CE3A7980046090B /* elf_reader.cc in Sources */,
B8C5B5171166534700D34F4E /* dwarf2reader.cc in Sources */,
B8C5B5181166534700D34F4E /* bytereader.cc in Sources */,
B8C5B5191166534700D34F4E /* macho_utilities.cc in Sources */,
@ -1225,7 +1235,11 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */;
buildSettings = {
HEADER_SEARCH_PATHS = ../../..;
HEADER_SEARCH_PATHS = (
../../..,
../../../common/mac/include/,
../../../third_party/musl/include/,
);
};
name = Debug;
};
@ -1233,7 +1247,11 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */;
buildSettings = {
HEADER_SEARCH_PATHS = ../../..;
HEADER_SEARCH_PATHS = (
../../..,
../../../common/mac/include/,
../../../third_party/musl/include/,
);
};
name = Release;
};
@ -1619,7 +1637,6 @@
GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
GCC_VERSION = "";
PRODUCT_NAME = dump_syms;
SDKROOT = macosx;
};
name = Debug;
};
@ -1629,7 +1646,6 @@
GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
GCC_VERSION = "";
PRODUCT_NAME = dump_syms;
SDKROOT = macosx;
};
name = Release;
};

View File

@ -51,11 +51,13 @@ using std::vector;
struct Options {
Options()
: srcPath(), dsymPath(), arch(), cfi(true), handle_inter_cu_refs(true) {}
: srcPath(), dsymPath(), arch(), header_only(false),
cfi(true), handle_inter_cu_refs(true) {}
string srcPath;
string dsymPath;
const NXArchInfo *arch;
bool header_only;
bool cfi;
bool handle_inter_cu_refs;
};
@ -151,6 +153,9 @@ static bool Start(const Options &options) {
}
}
if (options.header_only)
return dump_symbols.WriteSymbolFileHeader(std::cout);
// Read the primary file into a Breakpad Module.
Module* module = NULL;
if (!dump_symbols.ReadSymbolData(&module))
@ -189,6 +194,7 @@ static void Usage(int argc, const char *argv[]) {
fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n");
fprintf(stderr, "Usage: %s [-a ARCHITECTURE] [-c] [-g dSYM path] "
"<Mach-o file>\n", argv[0]);
fprintf(stderr, "\t-i: Output module header information only.\n");
fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n");
fprintf(stderr, "\t in the file, if it contains only one architecture]\n");
fprintf(stderr, "\t-g: Debug symbol file (dSYM) to dump in addition to the "
@ -204,8 +210,11 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
extern int optind;
signed char ch;
while ((ch = getopt(argc, (char * const *)argv, "a:g:chr?")) != -1) {
while ((ch = getopt(argc, (char * const *)argv, "ia:g:chr?")) != -1) {
switch (ch) {
case 'i':
options->header_only = true;
break;
case 'a': {
const NXArchInfo *arch_info =
google_breakpad::BreakpadGetArchInfoFromName(optarg);

View File

@ -54,7 +54,7 @@ class SymbolFileParser(object):
"""Parser for Breakpad symbol files.
The format of these files is documented at
https://code.google.com/p/google-breakpad/wiki/SymbolFiles
https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md
"""
def __init__(self, input_stream, output_stream, ignored_prefixes=None,