Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2011 Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| 11 // copyright notice, this list of conditions and the following disclaimer | 11 // copyright notice, this list of conditions and the following disclaimer |
| 12 // in the documentation and/or other materials provided with the | 12 // in the documentation and/or other materials provided with the |
| 13 // distribution. | 13 // distribution. |
| 14 // * Neither the name of Google Inc. nor the names of its | 14 // * Neither the name of Google Inc. nor the names of its |
| 15 // contributors may be used to endorse or promote products derived from | 15 // contributors may be used to endorse or promote products derived from |
| 16 // this software without specific prior written permission. | 16 // this software without specific prior written permission. |
| 17 // | 17 // |
| 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 // symupload.cc: Upload a symbol file to a HTTP server. The upload is sent as | 30 // symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper |
| 31 // a multipart/form-data POST request with the following parameters: | 31 // function for linux symbol upload tool. |
| 32 // code_file: the basename of the module, e.g. "app" | 32 |
| 33 // debug_file: the basename of the debugging file, e.g. "app" | 33 #include "common/linux/http_upload.h" |
| 34 // debug_identifier: the debug file's identifier, usually consisting of | 34 #include "common/linux/symbol_upload.h" |
| 35 // the guid and age embedded in the pdb, e.g. | |
| 36 // "11111111BBBB3333DDDD555555555555F" | |
| 37 // version: the file version of the module, e.g. "1.2.3.4" | |
| 38 // os: the operating system that the module was built for | |
| 39 // cpu: the CPU that the module was built for | |
| 40 // symbol_file: the contents of the breakpad-format symbol file | |
| 41 | 35 |
| 42 #include <assert.h> | 36 #include <assert.h> |
| 43 #include <stdio.h> | 37 #include <stdio.h> |
| 44 #include <stdlib.h> | |
| 45 #include <unistd.h> | |
| 46 | 38 |
| 47 #include <functional> | 39 #include <functional> |
| 48 #include <iostream> | |
| 49 #include <string> | |
| 50 #include <vector> | 40 #include <vector> |
| 51 | 41 |
| 52 #include "common/linux/http_upload.h" | 42 namespace google_breakpad { |
| 53 #include "common/using_std_string.h" | 43 namespace sym_upload { |
| 54 | 44 |
| 55 using google_breakpad::HTTPUpload; | 45 void TokenizeByChar(const string &source_string, |
| 56 | |
| 57 typedef struct { | |
| 58 string symbolsPath; | |
| 59 string uploadURLStr; | |
| 60 string proxy; | |
| 61 string proxy_user_pwd; | |
| 62 string version; | |
| 63 bool success; | |
| 64 } Options; | |
| 65 | |
| 66 static void TokenizeByChar(const string &source_string, | |
| 67 int c, std::vector<string> *results) { | 46 int c, std::vector<string> *results) { |
|
mmandlis
2016/03/30 18:34:40
nit, please, fix indentation.
| |
| 68 assert(results); | 47 assert(results); |
| 69 string::size_type cur_pos = 0, next_pos = 0; | 48 string::size_type cur_pos = 0, next_pos = 0; |
| 70 while ((next_pos = source_string.find(c, cur_pos)) != string::npos) { | 49 while ((next_pos = source_string.find(c, cur_pos)) != string::npos) { |
| 71 if (next_pos != cur_pos) | 50 if (next_pos != cur_pos) |
| 72 results->push_back(source_string.substr(cur_pos, next_pos - cur_pos)); | 51 results->push_back(source_string.substr(cur_pos, next_pos - cur_pos)); |
| 73 cur_pos = next_pos + 1; | 52 cur_pos = next_pos + 1; |
| 74 } | 53 } |
| 75 if (cur_pos < source_string.size() && next_pos != cur_pos) | 54 if (cur_pos < source_string.size() && next_pos != cur_pos) |
| 76 results->push_back(source_string.substr(cur_pos)); | 55 results->push_back(source_string.substr(cur_pos)); |
| 77 } | 56 } |
| 78 | 57 |
| 79 //============================================================================= | 58 //============================================================================= |
| 80 // Parse out the module line which have 5 parts. | 59 // Parse out the module line which have 5 parts. |
| 81 // MODULE <os> <cpu> <uuid> <module-name> | 60 // MODULE <os> <cpu> <uuid> <module-name> |
| 82 static bool ModuleDataForSymbolFile(const string &file, | 61 bool ModuleDataForSymbolFile(const string &file, |
| 83 std::vector<string> *module_parts) { | 62 std::vector<string> *module_parts) { |
|
mmandlis
2016/03/30 18:34:40
nit, please, fix indentation.
| |
| 84 assert(module_parts); | 63 assert(module_parts); |
| 85 const size_t kModulePartNumber = 5; | 64 const size_t kModulePartNumber = 5; |
| 86 FILE* fp = fopen(file.c_str(), "r"); | 65 FILE* fp = fopen(file.c_str(), "r"); |
| 87 if (fp) { | 66 if (fp) { |
| 88 char buffer[1024]; | 67 char buffer[1024]; |
| 89 if (fgets(buffer, sizeof(buffer), fp)) { | 68 if (fgets(buffer, sizeof(buffer), fp)) { |
| 90 string line(buffer); | 69 string line(buffer); |
| 91 string::size_type line_break_pos = line.find_first_of('\n'); | 70 string::size_type line_break_pos = line.find_first_of('\n'); |
| 92 if (line_break_pos == string::npos) { | 71 if (line_break_pos == string::npos) { |
| 93 assert(0 && "The file is invalid!"); | 72 assert(0 && "The file is invalid!"); |
| 94 fclose(fp); | 73 fclose(fp); |
| 95 return false; | 74 return false; |
| 96 } | 75 } |
| 97 line.resize(line_break_pos); | 76 line.resize(line_break_pos); |
| 98 const char kDelimiter = ' '; | 77 const char kDelimiter = ' '; |
| 99 TokenizeByChar(line, kDelimiter, module_parts); | 78 TokenizeByChar(line, kDelimiter, module_parts); |
| 100 if (module_parts->size() != kModulePartNumber) | 79 if (module_parts->size() != kModulePartNumber) |
| 101 module_parts->clear(); | 80 module_parts->clear(); |
| 102 } | 81 } |
| 103 fclose(fp); | 82 fclose(fp); |
| 104 } | 83 } |
| 105 | 84 |
| 106 return module_parts->size() == kModulePartNumber; | 85 return module_parts->size() == kModulePartNumber; |
| 107 } | 86 } |
| 108 | 87 |
| 109 //============================================================================= | 88 //============================================================================= |
| 110 static string CompactIdentifier(const string &uuid) { | 89 string CompactIdentifier(const string &uuid) { |
| 111 std::vector<string> components; | 90 std::vector<string> components; |
| 112 TokenizeByChar(uuid, '-', &components); | 91 TokenizeByChar(uuid, '-', &components); |
| 113 string result; | 92 string result; |
| 114 for (size_t i = 0; i < components.size(); ++i) | 93 for (size_t i = 0; i < components.size(); ++i) |
| 115 result += components[i]; | 94 result += components[i]; |
| 116 return result; | 95 return result; |
| 117 } | 96 } |
| 118 | 97 |
| 119 //============================================================================= | 98 //============================================================================= |
| 120 static void Start(Options *options) { | 99 void Start(Options *options) { |
| 121 std::map<string, string> parameters; | 100 std::map<string, string> parameters; |
| 122 options->success = false; | 101 options->success = false; |
| 123 std::vector<string> module_parts; | 102 std::vector<string> module_parts; |
| 124 if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { | 103 if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { |
| 125 fprintf(stderr, "Failed to parse symbol file!\n"); | 104 fprintf(stderr, "Failed to parse symbol file!\n"); |
| 126 return; | 105 return; |
| 127 } | 106 } |
| 128 | 107 |
| 129 string compacted_id = CompactIdentifier(module_parts[3]); | 108 string compacted_id = CompactIdentifier(module_parts[3]); |
| 130 | 109 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 } else if (response_code != 200) { | 144 } else if (response_code != 200) { |
| 166 printf("Failed to send symbol file: Response code %ld\n", response_code); | 145 printf("Failed to send symbol file: Response code %ld\n", response_code); |
| 167 printf("Response:\n"); | 146 printf("Response:\n"); |
| 168 printf("%s\n", response.c_str()); | 147 printf("%s\n", response.c_str()); |
| 169 } else { | 148 } else { |
| 170 printf("Successfully sent the symbol file.\n"); | 149 printf("Successfully sent the symbol file.\n"); |
| 171 } | 150 } |
| 172 options->success = success; | 151 options->success = success; |
| 173 } | 152 } |
| 174 | 153 |
| 175 //============================================================================= | 154 } // namespace sym_upload |
| 176 static void | 155 } // namespace google_breakpad |
| 177 Usage(int argc, const char *argv[]) { | |
| 178 fprintf(stderr, "Submit symbol information.\n"); | |
| 179 fprintf(stderr, "Usage: %s [options...] <symbols> <upload-URL>\n", argv[0]); | |
| 180 fprintf(stderr, "Options:\n"); | |
| 181 fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n"); | |
| 182 fprintf(stderr, "<upload-URL> is the destination for the upload\n"); | |
| 183 fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n"); | |
| 184 fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n"); | |
| 185 fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n"); | |
| 186 fprintf(stderr, "-h:\t Usage\n"); | |
| 187 fprintf(stderr, "-?:\t Usage\n"); | |
| 188 } | |
| 189 | |
| 190 //============================================================================= | |
| 191 static void | |
| 192 SetupOptions(int argc, const char *argv[], Options *options) { | |
| 193 extern int optind; | |
| 194 int ch; | |
| 195 | |
| 196 while ((ch = getopt(argc, (char * const *)argv, "u:v:x:h?")) != -1) { | |
| 197 switch (ch) { | |
| 198 case 'h': | |
| 199 case '?': | |
| 200 Usage(argc, argv); | |
| 201 exit(0); | |
| 202 break; | |
| 203 case 'u': | |
| 204 options->proxy_user_pwd = optarg; | |
| 205 break; | |
| 206 case 'v': | |
| 207 options->version = optarg; | |
| 208 break; | |
| 209 case 'x': | |
| 210 options->proxy = optarg; | |
| 211 break; | |
| 212 | |
| 213 default: | |
| 214 fprintf(stderr, "Invalid option '%c'\n", ch); | |
| 215 Usage(argc, argv); | |
| 216 exit(1); | |
| 217 break; | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 if ((argc - optind) != 2) { | |
| 222 fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]); | |
| 223 Usage(argc, argv); | |
| 224 exit(1); | |
| 225 } | |
| 226 | |
| 227 options->symbolsPath = argv[optind]; | |
| 228 options->uploadURLStr = argv[optind + 1]; | |
| 229 } | |
| 230 | |
| 231 //============================================================================= | |
| 232 int main(int argc, const char* argv[]) { | |
| 233 Options options; | |
| 234 SetupOptions(argc, argv, &options); | |
| 235 Start(&options); | |
| 236 return options.success ? 0 : 1; | |
| 237 } | |
| OLD | NEW |