diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/linux/http_upload.cc | 15 | ||||
-rw-r--r-- | src/common/linux/http_upload.h | 3 | ||||
-rw-r--r-- | src/common/linux/symbol_upload.cc | 155 | ||||
-rw-r--r-- | src/common/linux/symbol_upload.h | 59 | ||||
-rw-r--r-- | src/tools/linux/symupload/sym_upload.cc | 131 |
5 files changed, 234 insertions, 129 deletions
diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc index 4492fe84..702526af 100644 --- a/src/common/linux/http_upload.cc +++ b/src/common/linux/http_upload.cc @@ -72,7 +72,9 @@ bool HTTPUpload::SendRequest(const string &url, // We may have been linked statically; if curl_easy_init is in the // current binary, no need to search for a dynamic version. void* curl_lib = dlopen(NULL, RTLD_NOW); - if (!curl_lib || dlsym(curl_lib, "curl_easy_init") == NULL) { + if (!CheckCurlLib(curl_lib)) { + fprintf(stderr, + "Failed to open curl lib from binary, use libcurl.so instead\n"); dlerror(); // Clear dlerror before attempting to open libraries. dlclose(curl_lib); curl_lib = NULL; @@ -113,6 +115,10 @@ bool HTTPUpload::SendRequest(const string &url, *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt"); (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str()); (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent); + // Support multithread by disabling timeout handling, would get SIGSEGV with + // Curl_resolv_timeout in stack trace otherwise. + // See https://curl.haxx.se/libcurl/c/threadsafe.html + (*curl_easy_setopt)(curl, CURLOPT_NOSIGNAL, 1); // Set proxy information if necessary. if (!proxy.empty()) (*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str()); @@ -198,6 +204,13 @@ bool HTTPUpload::SendRequest(const string &url, } // static +bool HTTPUpload::CheckCurlLib(void* curl_lib) { + return curl_lib && + dlsym(curl_lib, "curl_easy_init") && + dlsym(curl_lib, "curl_easy_setopt"); +} + +// static bool HTTPUpload::CheckParameters(const map<string, string> ¶meters) { for (map<string, string>::const_iterator pos = parameters.begin(); pos != parameters.end(); ++pos) { diff --git a/src/common/linux/http_upload.h b/src/common/linux/http_upload.h index 4f0e452f..bc1d5d57 100644 --- a/src/common/linux/http_upload.h +++ b/src/common/linux/http_upload.h @@ -74,6 +74,9 @@ class HTTPUpload { // any quote (") characters. Returns true if so. static bool CheckParameters(const map<string, string> ¶meters); + // Checks the curl_lib parameter points to a valid curl lib. + static bool CheckCurlLib(void* curl_lib); + // No instances of this class should be created. // Disallow all constructors, destructors, and operator=. HTTPUpload(); diff --git a/src/common/linux/symbol_upload.cc b/src/common/linux/symbol_upload.cc new file mode 100644 index 00000000..bbd3181e --- /dev/null +++ b/src/common/linux/symbol_upload.cc @@ -0,0 +1,155 @@ +// Copyright (c) 2011 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. + +// symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper +// function for linux symbol upload tool. + +#include "common/linux/http_upload.h" +#include "common/linux/symbol_upload.h" + +#include <assert.h> +#include <stdio.h> + +#include <functional> +#include <vector> + +namespace google_breakpad { +namespace sym_upload { + +void TokenizeByChar(const string &source_string, int c, + std::vector<string> *results) { + assert(results); + string::size_type cur_pos = 0, next_pos = 0; + while ((next_pos = source_string.find(c, cur_pos)) != 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 5 parts. +// MODULE <os> <cpu> <uuid> <module-name> +bool ModuleDataForSymbolFile(const string &file, + std::vector<string> *module_parts) { + assert(module_parts); + const size_t kModulePartNumber = 5; + FILE* fp = fopen(file.c_str(), "r"); + if (fp) { + char buffer[1024]; + if (fgets(buffer, sizeof(buffer), fp)) { + string line(buffer); + string::size_type line_break_pos = line.find_first_of('\n'); + if (line_break_pos == string::npos) { + assert(0 && "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; +} + +//============================================================================= +string CompactIdentifier(const string &uuid) { + std::vector<string> components; + TokenizeByChar(uuid, '-', &components); + string result; + for (size_t i = 0; i < components.size(); ++i) + result += components[i]; + return result; +} + +//============================================================================= +void Start(Options *options) { + std::map<string, string> parameters; + options->success = false; + std::vector<string> module_parts; + if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { + fprintf(stderr, "Failed to parse symbol file!\n"); + return; + } + + string compacted_id = CompactIdentifier(module_parts[3]); + + // Add parameters + if (!options->version.empty()) + parameters["version"] = options->version; + + // MODULE <os> <cpu> <uuid> <module-name> + // 0 1 2 3 4 + parameters["os"] = module_parts[1]; + parameters["cpu"] = module_parts[2]; + parameters["debug_file"] = module_parts[4]; + parameters["code_file"] = module_parts[4]; + parameters["debug_identifier"] = compacted_id; + + std::map<string, string> files; + files["symbol_file"] = options->symbolsPath; + + string response, error; + long response_code; + bool success = HTTPUpload::SendRequest(options->uploadURLStr, + parameters, + files, + options->proxy, + options->proxy_user_pwd, + "", + &response, + &response_code, + &error); + + if (!success) { + printf("Failed to send symbol file: %s\n", error.c_str()); + printf("Response code: %ld\n", response_code); + printf("Response:\n"); + printf("%s\n", response.c_str()); + } else if (response_code == 0) { + printf("Failed to send symbol file: No response code\n"); + } else if (response_code != 200) { + printf("Failed to send symbol file: Response code %ld\n", response_code); + printf("Response:\n"); + printf("%s\n", response.c_str()); + } else { + printf("Successfully sent the symbol file.\n"); + } + options->success = success; +} + +} // namespace sym_upload +} // namespace google_breakpad diff --git a/src/common/linux/symbol_upload.h b/src/common/linux/symbol_upload.h new file mode 100644 index 00000000..0a469692 --- /dev/null +++ b/src/common/linux/symbol_upload.h @@ -0,0 +1,59 @@ +// -*- mode: c++ -*- + +// Copyright (c) 2011 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. + +// symbol_upload.h: helper functions for linux symbol upload tool. + +#ifndef COMMON_LINUX_SYMBOL_UPLOAD_H_ +#define COMMON_LINUX_SYMBOL_UPLOAD_H_ + +#include <string> + +#include "common/using_std_string.h" + +namespace google_breakpad { +namespace sym_upload { + +typedef struct { + string symbolsPath; + string uploadURLStr; + string proxy; + string proxy_user_pwd; + string version; + bool success; +} Options; + +// Starts upload to symbol server with options. +void Start(Options* options); + +} // namespace sym_upload +} // namespace google_breakpad + +#endif // COMMON_LINUX_SYMBOL_UPLOAD_H_ diff --git a/src/tools/linux/symupload/sym_upload.cc b/src/tools/linux/symupload/sym_upload.cc index 2f9a73c3..9eeb2d44 100644 --- a/src/tools/linux/symupload/sym_upload.cc +++ b/src/tools/linux/symupload/sym_upload.cc @@ -39,138 +39,13 @@ // cpu: the CPU that the module was built for // symbol_file: the contents of the breakpad-format symbol file -#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <functional> -#include <iostream> -#include <string> -#include <vector> +#include "common/linux/symbol_upload.h" -#include "common/linux/http_upload.h" -#include "common/using_std_string.h" - -using google_breakpad::HTTPUpload; - -typedef struct { - string symbolsPath; - string uploadURLStr; - string proxy; - string proxy_user_pwd; - string version; - bool success; -} Options; - -static void TokenizeByChar(const string &source_string, - int c, std::vector<string> *results) { - assert(results); - string::size_type cur_pos = 0, next_pos = 0; - while ((next_pos = source_string.find(c, cur_pos)) != 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 5 parts. -// MODULE <os> <cpu> <uuid> <module-name> -static bool ModuleDataForSymbolFile(const string &file, - std::vector<string> *module_parts) { - assert(module_parts); - const size_t kModulePartNumber = 5; - FILE* fp = fopen(file.c_str(), "r"); - if (fp) { - char buffer[1024]; - if (fgets(buffer, sizeof(buffer), fp)) { - string line(buffer); - string::size_type line_break_pos = line.find_first_of('\n'); - if (line_break_pos == string::npos) { - assert(0 && "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 string CompactIdentifier(const string &uuid) { - std::vector<string> components; - TokenizeByChar(uuid, '-', &components); - string result; - for (size_t i = 0; i < components.size(); ++i) - result += components[i]; - return result; -} - -//============================================================================= -static void Start(Options *options) { - std::map<string, string> parameters; - options->success = false; - std::vector<string> module_parts; - if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { - fprintf(stderr, "Failed to parse symbol file!\n"); - return; - } - - string compacted_id = CompactIdentifier(module_parts[3]); - - // Add parameters - if (!options->version.empty()) - parameters["version"] = options->version; - - // MODULE <os> <cpu> <uuid> <module-name> - // 0 1 2 3 4 - parameters["os"] = module_parts[1]; - parameters["cpu"] = module_parts[2]; - parameters["debug_file"] = module_parts[4]; - parameters["code_file"] = module_parts[4]; - parameters["debug_identifier"] = compacted_id; - - std::map<string, string> files; - files["symbol_file"] = options->symbolsPath; - - string response, error; - long response_code; - bool success = HTTPUpload::SendRequest(options->uploadURLStr, - parameters, - files, - options->proxy, - options->proxy_user_pwd, - "", - &response, - &response_code, - &error); - - if (!success) { - printf("Failed to send symbol file: %s\n", error.c_str()); - printf("Response code: %ld\n", response_code); - printf("Response:\n"); - printf("%s\n", response.c_str()); - } else if (response_code == 0) { - printf("Failed to send symbol file: No response code\n"); - } else if (response_code != 200) { - printf("Failed to send symbol file: Response code %ld\n", response_code); - printf("Response:\n"); - printf("%s\n", response.c_str()); - } else { - printf("Successfully sent the symbol file.\n"); - } - options->success = success; -} +using google_breakpad::sym_upload::Options; //============================================================================= static void @@ -232,6 +107,6 @@ SetupOptions(int argc, const char *argv[], Options *options) { int main(int argc, const char* argv[]) { Options options; SetupOptions(argc, argv, &options); - Start(&options); + google_breakpad::sym_upload::Start(&options); return options.success ? 0 : 1; } |