1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/sym_upload.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,226 @@ 1.4 +// Copyright (c) 2006, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +// symupload.cc: Upload a symbol file to a HTTP server. The upload is sent as 1.34 +// a multipart/form-data POST request with the following parameters: 1.35 +// code_file: the basename of the module, e.g. "app" 1.36 +// debug_file: the basename of the debugging file, e.g. "app" 1.37 +// debug_identifier: the debug file's identifier, usually consisting of 1.38 +// the guid and age embedded in the pdb, e.g. 1.39 +// "11111111BBBB3333DDDD555555555555F" 1.40 +// version: the file version of the module, e.g. "1.2.3.4" 1.41 +// os: the operating system that the module was built for 1.42 +// cpu: the CPU that the module was built for 1.43 +// symbol_file: the contents of the breakpad-format symbol file 1.44 + 1.45 +#include <assert.h> 1.46 +#include <stdio.h> 1.47 +#include <stdlib.h> 1.48 +#include <unistd.h> 1.49 + 1.50 +#include <functional> 1.51 +#include <iostream> 1.52 +#include <string> 1.53 +#include <vector> 1.54 + 1.55 +#include "common/linux/http_upload.h" 1.56 + 1.57 +using google_breakpad::HTTPUpload; 1.58 + 1.59 +typedef struct { 1.60 + std::string symbolsPath; 1.61 + std::string uploadURLStr; 1.62 + std::string proxy; 1.63 + std::string proxy_user_pwd; 1.64 + std::string version; 1.65 + bool success; 1.66 +} Options; 1.67 + 1.68 +static void TokenizeByChar(const std::string &source_string, 1.69 + int c, std::vector<std::string> *results) { 1.70 + assert(results); 1.71 + std::string::size_type cur_pos = 0, next_pos = 0; 1.72 + while ((next_pos = source_string.find(c, cur_pos)) != std::string::npos) { 1.73 + if (next_pos != cur_pos) 1.74 + results->push_back(source_string.substr(cur_pos, next_pos - cur_pos)); 1.75 + cur_pos = next_pos + 1; 1.76 + } 1.77 + if (cur_pos < source_string.size() && next_pos != cur_pos) 1.78 + results->push_back(source_string.substr(cur_pos)); 1.79 +} 1.80 + 1.81 +//============================================================================= 1.82 +// Parse out the module line which have 5 parts. 1.83 +// MODULE <os> <cpu> <uuid> <module-name> 1.84 +static bool ModuleDataForSymbolFile(const std::string &file, 1.85 + std::vector<std::string> *module_parts) { 1.86 + assert(module_parts); 1.87 + const size_t kModulePartNumber = 5; 1.88 + FILE *fp = fopen(file.c_str(), "r"); 1.89 + if (fp) { 1.90 + char buffer[1024]; 1.91 + if (fgets(buffer, sizeof(buffer), fp)) { 1.92 + std::string line(buffer); 1.93 + std::string::size_type line_break_pos = line.find_first_of('\n'); 1.94 + if (line_break_pos == std::string::npos) { 1.95 + assert(0 && "The file is invalid!"); 1.96 + fclose(fp); 1.97 + return false; 1.98 + } 1.99 + line.resize(line_break_pos); 1.100 + const char kDelimiter = ' '; 1.101 + TokenizeByChar(line, kDelimiter, module_parts); 1.102 + if (module_parts->size() != kModulePartNumber) 1.103 + module_parts->clear(); 1.104 + } 1.105 + fclose(fp); 1.106 + } 1.107 + 1.108 + return module_parts->size() == kModulePartNumber; 1.109 +} 1.110 + 1.111 +//============================================================================= 1.112 +static std::string CompactIdentifier(const std::string &uuid) { 1.113 + std::vector<std::string> components; 1.114 + TokenizeByChar(uuid, '-', &components); 1.115 + std::string result; 1.116 + for (size_t i = 0; i < components.size(); ++i) 1.117 + result += components[i]; 1.118 + return result; 1.119 +} 1.120 + 1.121 +//============================================================================= 1.122 +static void Start(Options *options) { 1.123 + std::map<std::string, std::string> parameters; 1.124 + options->success = false; 1.125 + std::vector<std::string> module_parts; 1.126 + if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { 1.127 + fprintf(stderr, "Failed to parse symbol file!\n"); 1.128 + return; 1.129 + } 1.130 + 1.131 + std::string compacted_id = CompactIdentifier(module_parts[3]); 1.132 + 1.133 + // Add parameters 1.134 + if (!options->version.empty()) 1.135 + parameters["version"] = options->version; 1.136 + 1.137 + // MODULE <os> <cpu> <uuid> <module-name> 1.138 + // 0 1 2 3 4 1.139 + parameters["os"] = module_parts[1]; 1.140 + parameters["cpu"] = module_parts[2]; 1.141 + parameters["debug_file"] = module_parts[4]; 1.142 + parameters["code_file"] = module_parts[4]; 1.143 + parameters["debug_identifier"] = compacted_id; 1.144 + std::string response, error; 1.145 + long response_code; 1.146 + bool success = HTTPUpload::SendRequest(options->uploadURLStr, 1.147 + parameters, 1.148 + options->symbolsPath, 1.149 + "symbol_file", 1.150 + options->proxy, 1.151 + options->proxy_user_pwd, 1.152 + "", 1.153 + &response, 1.154 + &response_code, 1.155 + &error); 1.156 + 1.157 + if (!success) { 1.158 + printf("Failed to send symbol file: %s\n", error.c_str()); 1.159 + printf("Response:\n"); 1.160 + printf("%s\n", response.c_str()); 1.161 + } else if (response_code == 0) { 1.162 + printf("Failed to send symbol file: No response code\n"); 1.163 + } else if (response_code != 200) { 1.164 + printf("Failed to send symbol file: Response code %ld\n", response_code); 1.165 + printf("Response:\n"); 1.166 + printf("%s\n", response.c_str()); 1.167 + } else { 1.168 + printf("Successfully sent the symbol file.\n"); 1.169 + } 1.170 + options->success = success; 1.171 +} 1.172 + 1.173 +//============================================================================= 1.174 +static void 1.175 +Usage(int argc, const char *argv[]) { 1.176 + fprintf(stderr, "Submit symbol information.\n"); 1.177 + fprintf(stderr, "Usage: %s [options...] <symbols> <upload-URL>\n", argv[0]); 1.178 + fprintf(stderr, "Options:\n"); 1.179 + fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n"); 1.180 + fprintf(stderr, "<upload-URL> is the destination for the upload\n"); 1.181 + fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n"); 1.182 + fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n"); 1.183 + fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n"); 1.184 + fprintf(stderr, "-h:\t Usage\n"); 1.185 + fprintf(stderr, "-?:\t Usage\n"); 1.186 +} 1.187 + 1.188 +//============================================================================= 1.189 +static void 1.190 +SetupOptions(int argc, const char *argv[], Options *options) { 1.191 + extern int optind; 1.192 + char ch; 1.193 + 1.194 + while ((ch = getopt(argc, (char * const *)argv, "u:v:x:h?")) != -1) { 1.195 + switch (ch) { 1.196 + case 'u': 1.197 + options->proxy_user_pwd = optarg; 1.198 + break; 1.199 + case 'v': 1.200 + options->version = optarg; 1.201 + break; 1.202 + case 'x': 1.203 + options->proxy = optarg; 1.204 + break; 1.205 + 1.206 + default: 1.207 + Usage(argc, argv); 1.208 + exit(0); 1.209 + break; 1.210 + } 1.211 + } 1.212 + 1.213 + if ((argc - optind) != 2) { 1.214 + fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); 1.215 + Usage(argc, argv); 1.216 + exit(1); 1.217 + } 1.218 + 1.219 + options->symbolsPath = argv[optind]; 1.220 + options->uploadURLStr = argv[optind + 1]; 1.221 +} 1.222 + 1.223 +//============================================================================= 1.224 +int main (int argc, const char * argv[]) { 1.225 + Options options; 1.226 + SetupOptions(argc, argv, &options); 1.227 + Start(&options); 1.228 + return options.success ? 0 : 1; 1.229 +}