Breakpad fails to create minidump on target when I

2019-07-18 08:20发布

问题:

I've found that my test application does not generate a correct dump file when I use threads. I am using a cross-compiler to build the Breadpad library which is then linked with my cross-compiler to run on the target.

I'll start by explaining my set up:

Building on: Ubuntu 12.04, i686

Host/Target: Vortex86DX which is an i586 cpu, fully custom Linux system

Build tools: Buildroot, crosstool-ng, gcc 4.4.6, glibc 2.9

To build Breakpad I do this:

$ ./configure CC=/opt/br/output/host/usr/bin/i486-unknown-linux-gnu-gcc CXX=/opt/br/output/host/usr/bin/i486-unknown-linux-gnu-g++ --host=i486-unknown-linux-gnu
$ make

My cross-compiler is integrated into Buildroot, and I want to build binaries that run on --host=i486-unknown-linux-gnu

I cross-compile my test app like so:

$ /opt/br/output/host/usr/bin/i486-unknown-linux-gnu-g++ -g mytest.cpp client/linux/libbreakpad_client.a -I. -lrt -lpthread -lboost_thread -o mytest

The test app is:

#include <boost/thread/thread.hpp>
#include "./client/linux/handler/exception_handler.h"
#include <unistd.h>

static bool dumpCallback( const google_breakpad::MinidumpDescriptor &md,
                            void *context, bool succeeded)
{
    printf( "dump path: %s\n", md.path());
    return succeeded;
}

void crash1()
{
    volatile int* a = (int*)(NULL);
    *a = 1;
}

void crash2()
{
    volatile int x, y;
    y = 0;
    x/=y;
}

void t1()
{
    sleep(1);
    crash1();
}

void t2()
{
    while(1) sleep(10);
}


int main()
{
    google_breakpad::MinidumpDescriptor md("/tmp");
    google_breakpad::ExceptionHandler eh(md, NULL, dumpCallback, NULL, true, -1);

    // comment out to select between thread crash, main crash, main crash with non-crashing thread
    boost::thread thread1(t2);
    sleep(1);
    crash1();
    sleep(3);

    return 0;
}

I simply create variations between crashing from main() and crashing from a thread.

Observations when I cross compile and run my app on the target:

(1) the test app, with no threads, will create a correct dump file on the target. PASS

(2) the test app, with a thread that crashes, will create a very small and incorrect dump file (mostly zeroes) on the target. FAIL

(3) the test app, with a thread that doesn't crash, and a main that crashes, will create a medium sized and incorrect dump file on the target. FAIL

EDIT: In case (1), the callback returns succeeded=true. In cases (2) and (3), succeeded=false. So the library knows that it did not succeed. I guess it's my job to find out why it fails on my target.

If I compile the same test app to run on my build computer, it runs and creates a correct dump file in all circumstances. i.e. I have successfully run the cross-compiled Crashpad library on my build computer and it works as it should. Since both build and host are x86, this is possible.

e.g. I build using the non cross compile g++

g++ -g  mytest.cpp client/linux/libbreakpad_client.a -I. -lrt -lpthread -lboost_thread -o mytest

My questions are:

  • is the problem with Breakpad?

  • is the problem with my cross compilation libraries?

  • does the kernel make a difference? Do I need to enable any particular functionality?

  • how can this be made to work? i.e. a multi-threaded app, running on my target, produces a correct minidump file

回答1:

Google Breakpad will fail to create a minidump on a pre-Pentium III x86 processor.

Pentium III and above contain 8 extra floating point registers that are requested by a sys_ptrace call in Breakpad.

src/client/linux/minidump_writer/linux_ptrace_dumper.cc:
if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1)
    return false;

On a pre-Pentium III processor this call will fail and this causes the entire minidump to fail.