| OLD | NEW |
| 1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, 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 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 // code_file: the basename of the module, e.g. "app" | 32 // code_file: the basename of the module, e.g. "app" |
| 33 // debug_file: the basename of the debugging file, e.g. "app" | 33 // debug_file: the basename of the debugging file, e.g. "app" |
| 34 // debug_identifier: the debug file's identifier, usually consisting of | 34 // debug_identifier: the debug file's identifier, usually consisting of |
| 35 // the guid and age embedded in the pdb, e.g. | 35 // the guid and age embedded in the pdb, e.g. |
| 36 // "11111111BBBB3333DDDD555555555555F" | 36 // "11111111BBBB3333DDDD555555555555F" |
| 37 // version: the file version of the module, e.g. "1.2.3.4" | 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 | 38 // os: the operating system that the module was built for |
| 39 // cpu: the CPU 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 | 40 // symbol_file: the contents of the breakpad-format symbol file |
| 41 | 41 |
| 42 #include <assert.h> | |
| 43 #include <stdio.h> | 42 #include <stdio.h> |
| 44 #include <stdlib.h> | 43 #include <stdlib.h> |
| 45 #include <unistd.h> | 44 #include <unistd.h> |
| 46 | 45 |
| 47 #include <functional> | 46 #include "common/linux/symbol_upload.h" |
| 48 #include <iostream> | |
| 49 #include <string> | |
| 50 #include <vector> | |
| 51 | 47 |
| 52 #include "common/linux/http_upload.h" | 48 using google_breakpad::sym_upload::Options; |
| 53 #include "common/using_std_string.h" | |
| 54 | |
| 55 using google_breakpad::HTTPUpload; | |
| 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) { | |
| 68 assert(results); | |
| 69 string::size_type cur_pos = 0, next_pos = 0; | |
| 70 while ((next_pos = source_string.find(c, cur_pos)) != string::npos) { | |
| 71 if (next_pos != cur_pos) | |
| 72 results->push_back(source_string.substr(cur_pos, next_pos - cur_pos)); | |
| 73 cur_pos = next_pos + 1; | |
| 74 } | |
| 75 if (cur_pos < source_string.size() && next_pos != cur_pos) | |
| 76 results->push_back(source_string.substr(cur_pos)); | |
| 77 } | |
| 78 | |
| 79 //============================================================================= | |
| 80 // Parse out the module line which have 5 parts. | |
| 81 // MODULE <os> <cpu> <uuid> <module-name> | |
| 82 static bool ModuleDataForSymbolFile(const string &file, | |
| 83 std::vector<string> *module_parts) { | |
| 84 assert(module_parts); | |
| 85 const size_t kModulePartNumber = 5; | |
| 86 FILE* fp = fopen(file.c_str(), "r"); | |
| 87 if (fp) { | |
| 88 char buffer[1024]; | |
| 89 if (fgets(buffer, sizeof(buffer), fp)) { | |
| 90 string line(buffer); | |
| 91 string::size_type line_break_pos = line.find_first_of('\n'); | |
| 92 if (line_break_pos == string::npos) { | |
| 93 assert(0 && "The file is invalid!"); | |
| 94 fclose(fp); | |
| 95 return false; | |
| 96 } | |
| 97 line.resize(line_break_pos); | |
| 98 const char kDelimiter = ' '; | |
| 99 TokenizeByChar(line, kDelimiter, module_parts); | |
| 100 if (module_parts->size() != kModulePartNumber) | |
| 101 module_parts->clear(); | |
| 102 } | |
| 103 fclose(fp); | |
| 104 } | |
| 105 | |
| 106 return module_parts->size() == kModulePartNumber; | |
| 107 } | |
| 108 | |
| 109 //============================================================================= | |
| 110 static string CompactIdentifier(const string &uuid) { | |
| 111 std::vector<string> components; | |
| 112 TokenizeByChar(uuid, '-', &components); | |
| 113 string result; | |
| 114 for (size_t i = 0; i < components.size(); ++i) | |
| 115 result += components[i]; | |
| 116 return result; | |
| 117 } | |
| 118 | |
| 119 //============================================================================= | |
| 120 static void Start(Options *options) { | |
| 121 std::map<string, string> parameters; | |
| 122 options->success = false; | |
| 123 std::vector<string> module_parts; | |
| 124 if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { | |
| 125 fprintf(stderr, "Failed to parse symbol file!\n"); | |
| 126 return; | |
| 127 } | |
| 128 | |
| 129 string compacted_id = CompactIdentifier(module_parts[3]); | |
| 130 | |
| 131 // Add parameters | |
| 132 if (!options->version.empty()) | |
| 133 parameters["version"] = options->version; | |
| 134 | |
| 135 // MODULE <os> <cpu> <uuid> <module-name> | |
| 136 // 0 1 2 3 4 | |
| 137 parameters["os"] = module_parts[1]; | |
| 138 parameters["cpu"] = module_parts[2]; | |
| 139 parameters["debug_file"] = module_parts[4]; | |
| 140 parameters["code_file"] = module_parts[4]; | |
| 141 parameters["debug_identifier"] = compacted_id; | |
| 142 | |
| 143 std::map<string, string> files; | |
| 144 files["symbol_file"] = options->symbolsPath; | |
| 145 | |
| 146 string response, error; | |
| 147 long response_code; | |
| 148 bool success = HTTPUpload::SendRequest(options->uploadURLStr, | |
| 149 parameters, | |
| 150 files, | |
| 151 options->proxy, | |
| 152 options->proxy_user_pwd, | |
| 153 "", | |
| 154 &response, | |
| 155 &response_code, | |
| 156 &error); | |
| 157 | |
| 158 if (!success) { | |
| 159 printf("Failed to send symbol file: %s\n", error.c_str()); | |
| 160 printf("Response code: %ld\n", response_code); | |
| 161 printf("Response:\n"); | |
| 162 printf("%s\n", response.c_str()); | |
| 163 } else if (response_code == 0) { | |
| 164 printf("Failed to send symbol file: No response code\n"); | |
| 165 } else if (response_code != 200) { | |
| 166 printf("Failed to send symbol file: Response code %ld\n", response_code); | |
| 167 printf("Response:\n"); | |
| 168 printf("%s\n", response.c_str()); | |
| 169 } else { | |
| 170 printf("Successfully sent the symbol file.\n"); | |
| 171 } | |
| 172 options->success = success; | |
| 173 } | |
| 174 | 49 |
| 175 //============================================================================= | 50 //============================================================================= |
| 176 static void | 51 static void |
| 177 Usage(int argc, const char *argv[]) { | 52 Usage(int argc, const char *argv[]) { |
| 178 fprintf(stderr, "Submit symbol information.\n"); | 53 fprintf(stderr, "Submit symbol information.\n"); |
| 179 fprintf(stderr, "Usage: %s [options...] <symbols> <upload-URL>\n", argv[0]); | 54 fprintf(stderr, "Usage: %s [options...] <symbols> <upload-URL>\n", argv[0]); |
| 180 fprintf(stderr, "Options:\n"); | 55 fprintf(stderr, "Options:\n"); |
| 181 fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n"); | 56 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"); | 57 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"); | 58 fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n"); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 } | 100 } |
| 226 | 101 |
| 227 options->symbolsPath = argv[optind]; | 102 options->symbolsPath = argv[optind]; |
| 228 options->uploadURLStr = argv[optind + 1]; | 103 options->uploadURLStr = argv[optind + 1]; |
| 229 } | 104 } |
| 230 | 105 |
| 231 //============================================================================= | 106 //============================================================================= |
| 232 int main(int argc, const char* argv[]) { | 107 int main(int argc, const char* argv[]) { |
| 233 Options options; | 108 Options options; |
| 234 SetupOptions(argc, argv, &options); | 109 SetupOptions(argc, argv, &options); |
| 235 Start(&options); | 110 google_breakpad::sym_upload::Start(&options); |
| 236 return options.success ? 0 : 1; | 111 return options.success ? 0 : 1; |
| 237 } | 112 } |
| OLD | NEW |