diff --git a/test/AMBuilder b/test/AMBuilder index 0b25880..db2e5c7 100644 --- a/test/AMBuilder +++ b/test/AMBuilder @@ -11,22 +11,47 @@ def BuildEverything(): compiler = SM.DefaultCompiler() - compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src')) - if AMBuild.target['platform'] in ['linux']: + compiler['POSTLINKFLAGS'].append('-lm') compiler['POSTLINKFLAGS'].append('-lstdc++') compiler['POSTLINKFLAGS'].append('-pthread') + + compiler['CDEFINES'].append('HAVE_CONFIG_H') + compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'breakpad', 'build', 'src')) elif compiler.cc.name == 'msvc': compiler['POSTLINKFLAGS'].remove('/SUBSYSTEM:WINDOWS') compiler['POSTLINKFLAGS'].append('/SUBSYSTEM:CONSOLE') + compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src')) + name = 'test-crash-dump-generation' extension = AMBuild.AddJob(name) binary = Cpp.ExecutableBuilder(name, AMBuild, extension, compiler) - binary.AddSourceFiles('test', [ - 'test.cpp', - ]) + sourceFiles = [ + 'test.cpp', + ] + + if AMBuild.target['platform'] in ['linux']: + sourceFiles.extend([ + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'dwarf_cfi_to_module.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'dwarf_cu_to_module.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'dwarf_line_to_module.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'language.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'module.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'path_helper.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'stabs_reader.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'stabs_to_module.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'dwarf', 'bytereader.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'dwarf', 'dwarf2diehandler.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'dwarf', 'dwarf2reader.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'dwarf', 'elf_reader.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'linux', 'crc32.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'linux', 'dump_symbols.cc'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'common', 'linux', 'elf_symbols_to_module.cc'), + ]) + + binary.AddSourceFiles('test', sourceFiles); if AMBuild.target['platform'] in ['linux']: libs = [ diff --git a/test/test.cpp b/test/test.cpp index 828dd3d..64d2d9b 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -2,16 +2,22 @@ #include "client/linux/handler/exception_handler.h" #include "common/linux/linux_libc_support.h" #include "third_party/lss/linux_syscall_support.h" +#include "common/linux/dump_symbols.h" +#include "common/path_helper.h" + +#include #include #include #include +#include #define my_jmp_buf sigjmp_buf #define my_setjmp(x) sigsetjmp(x, 0) #define my_longjmp siglongjmp using google_breakpad::MinidumpDescriptor; +using google_breakpad::WriteSymbolFile; #elif defined _WINDOWS #define _STDINT // ~.~ @@ -174,6 +180,54 @@ int main(int argc, char *argv[]) } printf("\n"); + +#if defined _LINUX + for (unsigned int moduleIndex = 0; moduleIndex < moduleCount; ++moduleIndex) { + auto module = processState.modules()->GetModuleAtIndex(moduleIndex); + + auto debugFile = module->debug_file(); + if (debugFile[0] != '/') { + continue; + } + + printf("%s\n", debugFile.c_str()); + + auto debugFileDir = google_breakpad::DirName(debugFile); + std::vector debug_dirs{ + debugFileDir, + }; + + FILE *saved_stderr = fdopen(dup(fileno(stderr)), "w"); + if (freopen(_PATH_DEVNULL, "w", stderr)) { + // If it fails, not a lot we can (or should) do. + // Add this brace section to silence gcc warnings. + } + + std::ostringstream outputStream; + google_breakpad::DumpOptions options(ALL_SYMBOL_DATA, true); + if (!WriteSymbolFile(debugFile, debug_dirs, options, outputStream)) { + outputStream.str(""); + outputStream.clear(); + + // Try again without debug dirs. + if (!WriteSymbolFile(debugFile, {}, options, outputStream)) { + // TODO: Something. + } + } + + fflush(stderr); + dup2(fileno(saved_stderr), fileno(stderr)); + fclose(saved_stderr); + + + // WriteSymbolFileHeaderOnly would do this for us, but this is just for testing. + auto output = outputStream.str(); + output = output.substr(0, output.find("\n")); + fprintf(stdout, "%s\n", output.c_str()); + + // break; + } +#endif } if (generateCrash) {