toolkit/crashreporter/google-breakpad/src/tools/linux/symupload/sym_upload.cc

changeset 0
6474c204b198
     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 +}

mercurial