diff options
author | luly81 <luly81@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2007-03-12 01:53:18 +0000 |
---|---|---|
committer | luly81 <luly81@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2007-03-12 01:53:18 +0000 |
commit | bcd46f007919b5063164c8c5c6c2bd4dfb62681e (patch) | |
tree | bdf12a91fb24c51c99a1092c2374851b2e31370f /src/tools | |
parent | fixes for issue 129 : reviewed by Waylonis (diff) | |
download | breakpad-bcd46f007919b5063164c8c5c6c2bd4dfb62681e.tar.xz |
Add Linux exception handler.
Add Linux stab symbol dumper.
Add minidump & symbol uploader for Linux.
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@126 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/linux/dump_syms/Makefile | 28 | ||||
-rw-r--r-- | src/tools/linux/dump_syms/dump_syms.cc | 56 | ||||
-rw-r--r-- | src/tools/linux/symupload/Makefile | 24 | ||||
-rw-r--r-- | src/tools/linux/symupload/minidump_upload.cc | 143 | ||||
-rw-r--r-- | src/tools/linux/symupload/sym_upload.cc | 219 |
5 files changed, 470 insertions, 0 deletions
diff --git a/src/tools/linux/dump_syms/Makefile b/src/tools/linux/dump_syms/Makefile new file mode 100644 index 00000000..87491996 --- /dev/null +++ b/src/tools/linux/dump_syms/Makefile @@ -0,0 +1,28 @@ +CPP=g++ +CC=gcc + +CPPFLAGS=-gstabs -I../../.. -Wall -D_REENTRANT +LDFLAGS=-lssl + +.PHONY:all clean + +BIN=dump_syms + +all:$(BIN) + +DUMP_OBJ=dump_symbols.o guid_creator.o dump_syms.o file_id.o + +dump_syms:$(DUMP_OBJ) + $(CPP) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ + +dump_symbols.o:../../../common/linux/dump_symbols.cc + $(CPP) $(CPPFLAGS) -c $^ + +guid_creator.o:../../../common/linux/guid_creator.cc + $(CPP) $(CPPFLAGS) -c $^ + +file_id.o:../../../common/linux/file_id.cc + $(CPP) $(CPPFLAGS) -c $^ + +clean: + rm -f $(BIN) $(DUMP_OBJ) diff --git a/src/tools/linux/dump_syms/dump_syms.cc b/src/tools/linux/dump_syms/dump_syms.cc new file mode 100644 index 00000000..3eca3745 --- /dev/null +++ b/src/tools/linux/dump_syms/dump_syms.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <string> + +#include "common/linux/dump_symbols.h" + +using namespace google_breakpad; + +int main(int argc, char **argv) { + if (argc < 2 || argc > 3) { + fprintf(stderr, + "Usage: %s <binary-with-stab-symbol> [output-symbol-file]\n", + argv[0]); + return 1; + } + + const char *binary = argv[1]; + std::string symbol_file(binary); + symbol_file += ".sym"; + if (argc == 3) + symbol_file = argv[2]; + + DumpSymbols dumper; + if (dumper.WriteSymbolFile(binary, symbol_file)) + printf("Symbol file successfully written: %s\n", symbol_file.c_str()); + else + printf("Failed to write symbol file.\n"); + return 0; +} diff --git a/src/tools/linux/symupload/Makefile b/src/tools/linux/symupload/Makefile new file mode 100644 index 00000000..7d4257d8 --- /dev/null +++ b/src/tools/linux/symupload/Makefile @@ -0,0 +1,24 @@ +CC=g++ + +CPPFLAGS=-gstabs -I../../.. -Wall -D_REENTRANT + +.PHONY:all clean + +BIN=minidump_upload sym_upload + +all:$(BIN) + +DUMP_UPLOAD_OBJ=minidump_upload.o http_upload.o +SYM_UPLOAD_OBJ=sym_upload.o http_upload.o + +minidump_upload:$(DUMP_UPLOAD_OBJ) + $(CC) $(CPPFLAGS) `curl-config --libs` -o $@ $^ + +sym_upload:$(SYM_UPLOAD_OBJ) + $(CC) $(CPPFLAGS) `curl-config --libs` -o $@ $^ + +http_upload.o:../../../common/linux/http_upload.cc + $(CC) $(CPPFLAGS) `curl-config --cflags` -c $^ + +clean: + rm *.o $(BIN) diff --git a/src/tools/linux/symupload/minidump_upload.cc b/src/tools/linux/symupload/minidump_upload.cc new file mode 100644 index 00000000..de9f7092 --- /dev/null +++ b/src/tools/linux/symupload/minidump_upload.cc @@ -0,0 +1,143 @@ +// Copyright (c) 2006, 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. + +// minidump_upload.m: Upload a minidump to a HTTP server. The upload is sent as +// a multipart/form-data POST request with the following parameters: +// prod: the product name +// ver: the product version +// symbol_file: the breakpad format symbol file + +#include <unistd.h> + +#include <string> + +#include "common/linux/http_upload.h" + +using google_breakpad::HTTPUpload; + +struct Options { + std::string minidumpPath; + std::string uploadURLStr; + std::string product; + std::string version; + std::string proxy; + std::string proxy_user_pwd; + bool success; +}; + +//============================================================================= +static void Start(Options *options) { + std::map<std::string, std::string> parameters; + // Add parameters + parameters["prod"] = options->product; + parameters["ver"] = options->version; + + // Send it + std::string response; + bool success = HTTPUpload::SendRequest(options->uploadURLStr, + parameters, + options->minidumpPath, + "upload_file_minidump", + options->proxy, + options->proxy_user_pwd, + &response); + + if (success) { + printf("Successfully sent the minidump file.\n"); + } else { + printf("Failed to send minidump\n"); + printf("Response:\n"); + printf("%s\n", response.c_str()); + } + options->success = success; +} + +//============================================================================= +static void +Usage(int argc, const char *argv[]) { + fprintf(stderr, "Submit minidump information.\n"); + fprintf(stderr, "Usage: %s [options...] -p <product> -v <version> <minidump> " + "<upload-URL>\n", argv[0]); + fprintf(stderr, "Options:\n"); + fprintf(stderr, "<minidump> should be a minidump.\n"); + fprintf(stderr, "<upload-URL> is the destination for the upload\n"); + + fprintf(stderr, "-p:\t <product> Product name\n"); + fprintf(stderr, "-v:\t <version> Product version\n"); + fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n"); + fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n"); + fprintf(stderr, "-h:\t Usage\n"); + fprintf(stderr, "-?:\t Usage\n"); +} + +//============================================================================= +static void +SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + char ch; + + while ((ch = getopt(argc, (char * const *)argv, "p:u:v:x:h?")) != -1) { + switch (ch) { + case 'p': + options->product = optarg; + break; + case 'u': + options->proxy_user_pwd = optarg; + break; + case 'v': + options->version = optarg; + break; + case 'x': + options->proxy = optarg; + break; + + default: + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 2) { + fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); + Usage(argc, argv); + exit(1); + } + + options->minidumpPath = argv[optind]; + options->uploadURLStr = argv[optind + 1]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + Options options; + SetupOptions(argc, argv, &options); + Start(&options); + return options.success ? 0 : 1; +} diff --git a/src/tools/linux/symupload/sym_upload.cc b/src/tools/linux/symupload/sym_upload.cc new file mode 100644 index 00000000..eb1e71d1 --- /dev/null +++ b/src/tools/linux/symupload/sym_upload.cc @@ -0,0 +1,219 @@ +// Copyright (c) 2006, 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. + +// symupload.cc: Upload a symbol file to a HTTP server. The upload is sent as +// a multipart/form-data POST request with the following parameters: +// code_file: the basename of the module, e.g. "app" +// debug_file: the basename of the debugging file, e.g. "app" +// debug_identifier: the debug file's identifier, usually consisting of +// the guid and age embedded in the pdb, e.g. +// "11111111BBBB3333DDDD555555555555F" +// version: the file version of the module, e.g. "1.2.3.4" +// os: the operating system that the module was built for +// cpu: the CPU that the module was built for +// symbol_file: the contents of the breakpad-format symbol file + +#include <unistd.h> + +#include <cstdio> +#include <cassert> +#include <functional> +#include <iostream> +#include <string> +#include <vector> + +#include "common/linux/http_upload.h" + +using google_breakpad::HTTPUpload; + +typedef struct { + std::string symbolsPath; + std::string uploadURLStr; + std::string proxy; + std::string proxy_user_pwd; + std::string version; + bool success; +} Options; + +static void TokenizeByChar(const std::string &source_string, + int c, std::vector<std::string> *results) { + assert(results); + std::string::size_type cur_pos = 0, next_pos = 0; + while ((next_pos = source_string.find(c, cur_pos)) != std::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 6 parts. +// MODULE <os> <cpu> <uuid> <age> <module-name> +static bool ModuleDataForSymbolFile(const std::string &file, + std::vector<std::string> *module_parts) { + assert(module_parts); + const size_t kModulePartNumber = 6; + FILE *fp = fopen(file.c_str(), "r"); + if (fp) { + char buffer[1024]; + if (fgets(buffer, sizeof(buffer), fp)) { + std::string line(buffer); + std::string::size_type line_break_pos = line.find_first_of('\n'); + if (line_break_pos == std::string::npos) { + assert(!"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 std::string CompactIdentifier(const std::string &uuid, + const std::string &age) { + std::vector<std::string> components; + TokenizeByChar(uuid, '-', &components); + std::string result; + for (size_t i = 0; i < components.size(); ++i) + result += components[i]; + result += age; + return result; +} + +//============================================================================= +static void Start(Options *options) { + std::map<std::string, std::string> parameters; + options->success = false; + std::vector<std::string> module_parts; + if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { + fprintf(stderr, "Failed to parse symbol file!\n"); + return; + } + + std::string compacted_id = CompactIdentifier(module_parts[3], + module_parts[4]); + + // Add parameters + if (!options->version.empty()) + parameters["version"] = options->version; + + // MODULE <os> <cpu> <uuid> <age> <module-name> + // 0 1 2 3 4 5 + parameters["age"] = "1"; + parameters["os"] = module_parts[1]; + parameters["cpu"] = module_parts[2]; + parameters["debug_file"] = module_parts[5]; + parameters["code_file"] = module_parts[5]; + parameters["debug_identifier"] = compacted_id; + std::string response; + bool success = HTTPUpload::SendRequest(options->uploadURLStr, + parameters, + options->symbolsPath, + "symbol_file", + options->proxy, + options->proxy_user_pwd, + &response); + + if (success) { + printf("Successfully sent the symbol file.\n"); + } else { + printf("Failed to send symbol file.\n"); + printf("Response:\n"); + printf("%s\n", response.c_str()); + } + options->success = success; +} + +//============================================================================= +static void +Usage(int argc, const char *argv[]) { + fprintf(stderr, "Submit symbol information.\n"); + fprintf(stderr, "Usage: %s [options...] <symbols> <upload-URL>\n", argv[0]); + fprintf(stderr, "Options:\n"); + fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n"); + fprintf(stderr, "<upload-URL> is the destination for the upload\n"); + fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n"); + fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n"); + fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n"); + fprintf(stderr, "-h:\t Usage\n"); + fprintf(stderr, "-?:\t Usage\n"); +} + +//============================================================================= +static void +SetupOptions(int argc, const char *argv[], Options *options) { + extern int optind; + char ch; + + while ((ch = getopt(argc, (char * const *)argv, "u:v:x:h?")) != -1) { + switch (ch) { + case 'u': + options->proxy_user_pwd = optarg; + break; + case 'v': + options->version = optarg; + break; + case 'x': + options->proxy = optarg; + break; + + default: + Usage(argc, argv); + exit(0); + break; + } + } + + if ((argc - optind) != 2) { + fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); + Usage(argc, argv); + exit(1); + } + + options->symbolsPath = argv[optind]; + options->uploadURLStr = argv[optind + 1]; +} + +//============================================================================= +int main (int argc, const char * argv[]) { + Options options; + SetupOptions(argc, argv, &options); + Start(&options); + return options.success ? 0 : 1; +} |