From 6f4e6aacc88562dbc144e76251792da742d4120f Mon Sep 17 00:00:00 2001 From: Mark Mentovai Date: Thu, 19 Mar 2015 18:41:01 -0400 Subject: [PATCH] Add crashpad_database_util and its man page. R=rsesek@chromium.org Review URL: https://codereview.chromium.org/1022663002 --- client/crash_report_database_mac.mm | 10 +- client/crash_report_database_test.cc | 7 +- handler/mac/crashpad_handler.ad | 1 + handler/mac/main.cc | 2 +- tools/crashpad_database_util.ad | 151 ++++++++ tools/crashpad_database_util.cc | 516 +++++++++++++++++++++++++++ tools/generate_dump.cc | 2 +- tools/mac/catch_exception_tool.cc | 2 +- tools/mac/exception_port_tool.cc | 2 +- tools/mac/on_demand_service_tool.mm | 2 +- tools/mac/run_with_crashpad.cc | 2 +- tools/tools.gyp | 17 + 12 files changed, 702 insertions(+), 12 deletions(-) create mode 100644 tools/crashpad_database_util.ad create mode 100644 tools/crashpad_database_util.cc diff --git a/client/crash_report_database_mac.mm b/client/crash_report_database_mac.mm index d588f765..f451efb0 100644 --- a/client/crash_report_database_mac.mm +++ b/client/crash_report_database_mac.mm @@ -573,15 +573,15 @@ CrashReportDatabase::OperationStatus CrashReportDatabaseMac::ReportsInDirectory( reports->reserve([paths count]); for (NSString* entry in paths) { - base::FilePath report_path = path.Append([entry fileSystemRepresentation]); - base::ScopedFD lock(ObtainReportLock(report_path)); + Report report; + report.file_path = path.Append([entry fileSystemRepresentation]); + base::ScopedFD lock(ObtainReportLock(report.file_path)); if (!lock.is_valid()) continue; - Report report; - if (!ReadReportMetadataLocked(report_path, &report)) { + if (!ReadReportMetadataLocked(report.file_path, &report)) { LOG(WARNING) << "Failed to read report metadata for " - << report_path.value(); + << report.file_path.value(); continue; } reports->push_back(report); diff --git a/client/crash_report_database_test.cc b/client/crash_report_database_test.cc index ff29b080..f065dd69 100644 --- a/client/crash_report_database_test.cc +++ b/client/crash_report_database_test.cc @@ -372,8 +372,10 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) { EXPECT_EQ(4u, pending.size()); ASSERT_EQ(1u, completed.size()); - for (const auto& report : pending) + for (const auto& report : pending) { EXPECT_NE(report_1_uuid, report.uuid); + EXPECT_FALSE(report.file_path.empty()); + } EXPECT_EQ(report_1_uuid, completed[0].uuid); EXPECT_EQ("report1", completed[0].id); EXPECT_EQ(true, completed[0].uploaded); @@ -400,6 +402,7 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) { EXPECT_FALSE(report.uploaded); EXPECT_TRUE(report.id.empty()); } + EXPECT_FALSE(report.file_path.empty()); } // Upload a second report. @@ -431,6 +434,7 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) { for (const auto& report : pending) { EXPECT_TRUE(report.uuid == report_0_uuid || report.uuid == report_3_uuid); + EXPECT_FALSE(report.file_path.empty()); } // Skip upload for one report. @@ -459,6 +463,7 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) { EXPECT_GT(report.upload_attempts, 0); EXPECT_GT(report.last_upload_attempt_time, 0); } + EXPECT_FALSE(report.file_path.empty()); } } diff --git a/handler/mac/crashpad_handler.ad b/handler/mac/crashpad_handler.ad index e337b3c7..85780b89 100644 --- a/handler/mac/crashpad_handler.ad +++ b/handler/mac/crashpad_handler.ad @@ -101,6 +101,7 @@ Failure, with a message printed to the standard error stream. == See Also man_link:catch_exception_tool[1], +man_link:crashpad_database_util[1], man_link:generate_dump[1], man_link:run_with_crashpad[1] diff --git a/handler/mac/main.cc b/handler/mac/main.cc index a67364bd..1df183f9 100644 --- a/handler/mac/main.cc +++ b/handler/mac/main.cc @@ -77,7 +77,7 @@ int HandlerMain(int argc, char* argv[]) { } options = {}; options.handshake_fd = -1; - const struct option long_options[] = { + const option long_options[] = { {"annotation", required_argument, nullptr, kOptionAnnotation}, {"database", required_argument, nullptr, kOptionDatabase}, {"handshake-fd", required_argument, nullptr, kOptionHandshakeFD}, diff --git a/tools/crashpad_database_util.ad b/tools/crashpad_database_util.ad new file mode 100644 index 00000000..36b7447d --- /dev/null +++ b/tools/crashpad_database_util.ad @@ -0,0 +1,151 @@ +// Copyright 2015 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +:doctype: manpage + += crashpad_database_util(1) + +== Name + +crashpad_database_util - Operate on Crashpad crash report databases + +== Synopsis + +[verse] +*crashpad_database_util* ['OPTION…'] + +== Description + +Operates on Crashpad crash report databases. The database’s settings can be +queried and modified, and information about crash reports stored in the +database can be displayed. + +When this program is requested to both show and set information in a single +invocation, all “show” operations will be completed prior to beginning any “set” +operation. + +Programs that use the Crashpad client library directly will not normally use +this tool, but may use the database through the programmatic interfaces in the +client library. This tool exists to allow developers to manipulate a Crashpad +database. + +== Options +*-d*, *--database*='PATH':: +Use 'PATH' as the path to the Crashpad crash report database. This option is +required. If the database does not exist, it will be created, provided that the +parent directory of 'PATH' exists. + +*--show-client-id*:: +Show the client ID stored in the database’s settings. The client ID is formatted +as a UUID. The client ID is set when the database is created. + +*--show-uploads-enabled*:: +Show the status of the uploads-enabled bit stored in the database’s settings. +man_link:crashpad_handler[8] does not upload reports when this bit is false. +This bit is false when a database is created, and is under an application’s +control via the Crashpad client library interface. ++ +See also *--set-uploads-enabled*. + +*--show-last-upload-attempt-time*:: +Show the last-upload-attempt time stored in the database’s settings. This value +is +0+, meaning “never,” when the database is created. +man_link:crashpad_handler[8] consults this value before attempting an upload to +implement its rate-limiting behavior. The database updates this value whenever +an upload is attempted. ++ +See also *--set-last-upload-attempt-time*. + +*--show-pending-reports*:: +Show reports eligible for upload. + +*--show-completed-reports*:: +Show reports not eligible for upload. A report is moved from the “pending” state +to the “completed” state by man_link:crashpad_handler[8]. This may happen when a +report is successfully uploaded, when a report is not uploaded because uploads +are disabled, or when a report upload attempt fails and will not be retried. + +*--show-all-report-info*:: +With *--show-pending-reports* or *--show-completed-reports*, show all metadata +for each report displayed. Without this option, only report IDs will be shown. + +*--show-report*='UUID':: +Show a report from the database looked up by its identifier, 'UUID', which must +be formatted in string representation per RFC 4122 §3. All metadata for each +report found via a *--show-report* option will be shown. If 'UUID' is not found, +the string +"not found"+ will be printed. If this program is only requested to +show a single report and it is not found, it will treat this as a failure for +the purposes of determining its exit status. + +*--set-report-uploads-enabled*='BOOL':: +Enable or disable report upload in the database’s settings. 'BOOL' is a string +representation of a boolean value, such as +"0"+ or +"true"+. ++ +See also *--show-uploads-enabled*. + +*--set-last-upload-attempt-time*='TIME':: +Set the last-upload-attempt time in the database’s settings. 'TIME' is a string +representation of a time, which may be in 'yyyy-mm-dd hh:mm:ss' format, a +numeric +time_t+ value, or the special string +"never"+. ++ +See also *--show-last-upload-attempt-time*. + +*--utc*:: +When showing times, do so in UTC as opposed to the local time zone. When setting +times, interpret ambiguous time strings in UTC as opposed to the local time +zone. + +*--help*:: +Display help and exit. + +*--version*:: +Output version information and exit. + +== Examples + +Shows all crash reports in a crash report database that are in the “completed” +state. +[subs="quotes"] +---- +$ *crashpad_database_util --database /tmp/crashpad_database \ + --show-completed-reports* +23f9512b-63e1-4ead-9dcd-e2e21fbccc68 +4bfca440-039f-4bc6-bbd4-6933cef5efd4 +56caeff8-b61a-43b2-832d-9e796e6e4a50 +---- + +Disables report upload in a crash report database’s settings, and then verifies +that the change was made. +[subs="quotes"] +---- +$ *crashpad_database_util --database /tmp/crashpad_database \ + --set-uploads-enabled false* +$ *crashpad_database_util --database /tmp/crashpad_database \ + --show-uploads-enabled* +false +---- + +== Exit Status + +*0*:: +Success. + +*1*:: +Failure, with a message printed to the standard error stream. + +== See Also + +man_link:crashpad_handler[8] + +include::../../doc/man_footer.ad[] diff --git a/tools/crashpad_database_util.cc b/tools/crashpad_database_util.cc new file mode 100644 index 00000000..264be8c9 --- /dev/null +++ b/tools/crashpad_database_util.cc @@ -0,0 +1,516 @@ +// Copyright 2015 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_conversions.h" +#include "client/crash_report_database.h" +#include "client/settings.h" +#include "tools/tool_support.h" +#include "util/misc/uuid.h" + +namespace crashpad { +namespace { + +void Usage(const std::string& me) { + fprintf(stderr, +"Usage: %s [OPTION]... PID\n" +"Operate on Crashpad crash report databases.\n" +"\n" +" -d, --database=PATH operate on the crash report database at PATH\n" +" --show-client-id show the client ID\n" +" --show-uploads-enabled show whether uploads are enabled\n" +" --show-last-upload-attempt-time\n" +" show the last-upload-attempt time\n" +" --show-pending-reports show reports eligible for upload\n" +" --show-completed-reports show reports not eligible for upload\n" +" --show-all-report-info with --show-*-reports, show more information\n" +" --show-report=UUID show report stored under UUID\n" +" --set-uploads-enabled=BOOL enable or disable uploads\n" +" --set-last-upload-attempt-time=TIME\n" +" set the last-upload-attempt time to TIME\n" +" --utc show and set UTC times instead of local\n" +" --help display this help and exit\n" +" --version output version information and exit\n", + me.c_str()); + ToolSupport::UsageTail(me); +} + +struct Options { + std::vector show_reports; + const char* database; + const char* set_last_upload_attempt_time_string; + time_t set_last_upload_attempt_time; + bool show_client_id; + bool show_uploads_enabled; + bool show_last_upload_attempt_time; + bool show_pending_reports; + bool show_completed_reports; + bool show_all_report_info; + bool set_uploads_enabled; + bool has_set_uploads_enabled; + bool utc; +}; + +// Converts |string| to |boolean|, returning true if a conversion could be +// performed, and false without setting |boolean| if no conversion could be +// performed. Various string representations of a boolean are recognized +// case-insensitively. +bool StringToBool(const char* string, bool* boolean) { + const char* const kFalseWords[] = { + "0", + "false", + "no", + "off", + "disabled", + "clear", + }; + const char* const kTrueWords[] = { + "1", + "true", + "yes", + "on", + "enabled", + "set", + }; + + for (size_t index = 0; index < arraysize(kFalseWords); ++index) { + if (strcasecmp(string, kFalseWords[index]) == 0) { + *boolean = false; + return true; + } + } + + for (size_t index = 0; index < arraysize(kTrueWords); ++index) { + if (strcasecmp(string, kTrueWords[index]) == 0) { + *boolean = true; + return true; + } + } + + return false; +} + +// Converts |boolean| to a string, either "true" or "false". +std::string BoolToString(bool boolean) { + return std::string(boolean ? "true" : "false"); +} + +// Converts |string| to |time|, returning true if a conversion could be +// performed, and false without setting |boolean| if no conversion could be +// performed. Various time formats are recognized, including several string +// representations and a numeric time_t representation. The special string +// "never" is recognized as |string| and converts to a |time| value of 0. |utc|, +// when true, causes |string| to be interpreted as a UTC time rather than a +// local time when the time zone is ambiguous. +bool StringToTime(const char* string, time_t* time, bool utc) { + if (strcasecmp(string, "never") == 0) { + *time = 0; + return true; + } + + const char* end = string + strlen(string); + + const char* const kFormats[] = { + "%Y-%m-%d %H:%M:%S %Z", + "%Y-%m-%d %H:%M:%S", + "%+", + }; + + for (size_t index = 0; index < arraysize(kFormats); ++index) { + tm time_tm; + const char* strptime_result = strptime(string, kFormats[index], &time_tm); + if (strptime_result == end) { + if (utc) { + *time = timegm(&time_tm); + } else { + *time = timelocal(&time_tm); + } + + return true; + } + } + + char* end_result; + errno = 0; + long long strtoll_result = strtoll(string, &end_result, 0); + if (end_result == end && errno == 0 && + base::IsValueInRangeForNumericType(strtoll_result)) { + *time = strtoll_result; + return true; + } + + return false; +} + +// Converst |time_tt| to a string, and returns it. |utc| determines whether the +// converted time will reference local time or UTC. If |time_tt| is 0, the +// string "never" will be returned as a special case. +std::string TimeToString(time_t time_tt, bool utc) { + if (time_tt == 0) { + return std::string("never"); + } + + tm time_tm; + if (utc) { + gmtime_r(&time_tt, &time_tm); + } else { + localtime_r(&time_tt, &time_tm); + } + + char string[64]; + CHECK_NE( + strftime(string, arraysize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm), + 0u); + + return std::string(string); +} + +// Shows information about a single |report|. |space_count| is the number of +// spaces to print before each line that is printed. |utc| determines whether +// times should be shown in UTC or the local time zone. +void ShowReport(const CrashReportDatabase::Report& report, + size_t space_count, + bool utc) { + std::string spaces(space_count, ' '); + + printf("%sPath: %s\n", spaces.c_str(), report.file_path.value().c_str()); + if (!report.id.empty()) { + printf("%sRemote ID: %s\n", spaces.c_str(), report.id.c_str()); + } + printf("%sCreation time: %s\n", + spaces.c_str(), + TimeToString(report.creation_time, utc).c_str()); + printf("%sUploaded: %s\n", + spaces.c_str(), + BoolToString(report.uploaded).c_str()); + printf("%sLast upload attempt time: %s\n", + spaces.c_str(), + TimeToString(report.last_upload_attempt_time, utc).c_str()); + printf("%sUpload attempts: %d\n", spaces.c_str(), report.upload_attempts); +} + +// Shows information about a vector of |reports|. |space_count| is the number of +// spaces to print before each line that is printed. |options| will be consulted +// to determine whether to show expanded information +// (options.show_all_report_info) and what time zone to use when showing +// expanded information (options.utc). +void ShowReports(const std::vector& reports, + size_t space_count, + const Options& options) { + std::string spaces(space_count, ' '); + const char* colon = options.show_all_report_info ? ":" : ""; + + for (const CrashReportDatabase::Report& report : reports) { + printf("%s%s%s\n", spaces.c_str(), report.uuid.ToString().c_str(), colon); + if (options.show_all_report_info) { + ShowReport(report, space_count + 2, options.utc); + } + } +} + +int DatabaseUtilMain(int argc, char* argv[]) { + const std::string me(basename(argv[0])); + + enum OptionFlags { + // “Short” (single-character) options. + kOptionDatabase = 'd', + + // Long options without short equivalents. + kOptionLastChar = 255, + kOptionShowClientID, + kOptionShowUploadsEnabled, + kOptionShowLastUploadAttemptTime, + kOptionShowPendingReports, + kOptionShowCompletedReports, + kOptionShowAllReportInfo, + kOptionShowReport, + kOptionSetUploadsEnabled, + kOptionSetLastUploadAttemptTime, + kOptionUTC, + + // Standard options. + kOptionHelp = -2, + kOptionVersion = -3, + }; + + const option long_options[] = { + {"database", required_argument, nullptr, kOptionDatabase}, + {"show-client-id", no_argument, nullptr, kOptionShowClientID}, + {"show-uploads-enabled", no_argument, nullptr, kOptionShowUploadsEnabled}, + {"show-last-upload-attempt-time", + no_argument, + nullptr, + kOptionShowLastUploadAttemptTime}, + {"show-pending-reports", no_argument, nullptr, kOptionShowPendingReports}, + {"show-completed-reports", + no_argument, + nullptr, + kOptionShowCompletedReports}, + {"show-all-report-info", no_argument, nullptr, kOptionShowAllReportInfo}, + {"show-report", required_argument, nullptr, kOptionShowReport}, + {"set-uploads-enabled", + required_argument, + nullptr, + kOptionSetUploadsEnabled}, + {"set-last-upload-attempt-time", + required_argument, + nullptr, + kOptionSetLastUploadAttemptTime}, + {"utc", no_argument, nullptr, kOptionUTC}, + {"help", no_argument, nullptr, kOptionHelp}, + {"version", no_argument, nullptr, kOptionVersion}, + {nullptr, 0, nullptr, 0}, + }; + + Options options = {}; + + int opt; + while ((opt = getopt_long(argc, argv, "d:", long_options, nullptr)) != -1) { + switch (opt) { + case kOptionDatabase: { + options.database = optarg; + break; + } + case kOptionShowClientID: { + options.show_client_id = true; + break; + } + case kOptionShowUploadsEnabled: { + options.show_uploads_enabled = true; + break; + } + case kOptionShowLastUploadAttemptTime: { + options.show_last_upload_attempt_time = true; + break; + } + case kOptionShowPendingReports: { + options.show_pending_reports = true; + break; + } + case kOptionShowCompletedReports: { + options.show_completed_reports = true; + break; + } + case kOptionShowAllReportInfo: { + options.show_all_report_info = true; + break; + } + case kOptionShowReport: { + UUID uuid; + if (!uuid.InitializeFromString(optarg)) { + ToolSupport::UsageHint(me, "--show-report requires a UUID"); + return EXIT_FAILURE; + } + options.show_reports.push_back(uuid); + break; + } + case kOptionSetUploadsEnabled: { + if (!StringToBool(optarg, &options.set_uploads_enabled)) { + ToolSupport::UsageHint(me, "--set-uploads-enabled requires a BOOL"); + return EXIT_FAILURE; + } + options.has_set_uploads_enabled = true; + break; + } + case kOptionSetLastUploadAttemptTime: { + options.set_last_upload_attempt_time_string = optarg; + break; + } + case kOptionUTC: { + options.utc = true; + break; + } + case kOptionHelp: { + Usage(me); + return EXIT_SUCCESS; + } + case kOptionVersion: { + ToolSupport::Version(me); + return EXIT_SUCCESS; + } + default: { + ToolSupport::UsageHint(me, nullptr); + return EXIT_FAILURE; + } + } + } + argc -= optind; + argv += optind; + + if (!options.database) { + ToolSupport::UsageHint(me, "--database is required"); + return EXIT_FAILURE; + } + + // This conversion couldn’t happen in the option-processing loop above because + // it depends on options.utc, which may have been set after + // options.set_last_upload_attempt_time_string. + if (options.set_last_upload_attempt_time_string) { + if (!StringToTime(options.set_last_upload_attempt_time_string, + &options.set_last_upload_attempt_time, + options.utc)) { + ToolSupport::UsageHint(me, + "--set-last-upload-attempt-time requires a TIME"); + return EXIT_FAILURE; + } + } + + const size_t show_operations = options.show_client_id + + options.show_uploads_enabled + + options.show_last_upload_attempt_time + + options.show_pending_reports + + options.show_completed_reports + + options.show_reports.size(); + const size_t set_operations = + options.has_set_uploads_enabled + + (options.set_last_upload_attempt_time_string != nullptr); + + if (show_operations + set_operations == 0) { + ToolSupport::UsageHint(me, "nothing to do"); + return EXIT_FAILURE; + } + + scoped_ptr database( + CrashReportDatabase::Initialize(base::FilePath(options.database))); + if (!database) { + return EXIT_FAILURE; + } + + Settings* settings = database->GetSettings(); + + // Handle the “show” options before the “set” options so that when they’re + // specified together, the “show” option reflects the initial state. + + if (options.show_client_id) { + UUID client_id; + if (!settings->GetClientID(&client_id)) { + return EXIT_FAILURE; + } + + const char* prefix = (show_operations > 1) ? "Client ID: " : ""; + + printf("%s%s\n", prefix, client_id.ToString().c_str()); + } + + if (options.show_uploads_enabled) { + bool uploads_enabled; + if (!settings->GetUploadsEnabled(&uploads_enabled)) { + return EXIT_FAILURE; + } + + const char* prefix = (show_operations > 1) ? "Uploads enabled: " : ""; + + printf("%s%s\n", prefix, BoolToString(uploads_enabled).c_str()); + } + + if (options.show_last_upload_attempt_time) { + time_t last_upload_attempt_time; + if (!settings->GetLastUploadAttemptTime(&last_upload_attempt_time)) { + return EXIT_FAILURE; + } + + const char* prefix = + (show_operations > 1) ? "Last upload attempt time: " : ""; + + printf("%s%s (%ld)\n", + prefix, + TimeToString(last_upload_attempt_time, options.utc).c_str(), + implicit_cast(last_upload_attempt_time)); + } + + if (options.show_pending_reports) { + std::vector pending_reports; + if (database->GetPendingReports(&pending_reports) != + CrashReportDatabase::kNoError) { + return EXIT_FAILURE; + } + + if (show_operations > 1) { + printf("Pending reports:\n"); + } + + ShowReports(pending_reports, show_operations > 1 ? 2 : 0, options); + } + + if (options.show_completed_reports) { + std::vector completed_reports; + if (database->GetCompletedReports(&completed_reports) != + CrashReportDatabase::kNoError) { + return EXIT_FAILURE; + } + + if (show_operations > 1) { + printf("Completed reports:\n"); + } + + ShowReports(completed_reports, show_operations > 1 ? 2 : 0, options); + } + + for (const UUID& uuid : options.show_reports) { + CrashReportDatabase::Report report; + CrashReportDatabase::OperationStatus status = + database->LookUpCrashReport(uuid, &report); + if (status == CrashReportDatabase::kNoError) { + if (show_operations > 1) { + printf("Report %s:\n", uuid.ToString().c_str()); + } + ShowReport(report, show_operations > 1 ? 2 : 0, options.utc); + } else if (status == CrashReportDatabase::kReportNotFound) { + // If only asked to do one thing, a failure to find the single requested + // report should result in a failure exit status. + if (show_operations + set_operations == 1) { + fprintf(stderr, "%s: Report not found\n", me.c_str()); + return EXIT_FAILURE; + } + printf("Report %s not found\n", uuid.ToString().c_str()); + } else { + return EXIT_FAILURE; + } + } + + if (options.has_set_uploads_enabled && + !settings->SetUploadsEnabled(options.set_uploads_enabled)) { + return EXIT_FAILURE; + } + + if (options.set_last_upload_attempt_time_string && + !settings->SetLastUploadAttemptTime( + options.set_last_upload_attempt_time)) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +} // namespace +} // namespace crashpad + +int main(int argc, char* argv[]) { + return crashpad::DatabaseUtilMain(argc, argv); +} diff --git a/tools/generate_dump.cc b/tools/generate_dump.cc index e1bbbfa7..ecb1bda0 100644 --- a/tools/generate_dump.cc +++ b/tools/generate_dump.cc @@ -76,7 +76,7 @@ int GenerateDumpMain(int argc, char* argv[]) { Options options = {}; options.suspend = true; - const struct option long_options[] = { + const option long_options[] = { {"no-suspend", no_argument, nullptr, kOptionNoSuspend}, {"output", required_argument, nullptr, kOptionOutput}, {"help", no_argument, nullptr, kOptionHelp}, diff --git a/tools/mac/catch_exception_tool.cc b/tools/mac/catch_exception_tool.cc index 59af49a2..016ff4c3 100644 --- a/tools/mac/catch_exception_tool.cc +++ b/tools/mac/catch_exception_tool.cc @@ -200,7 +200,7 @@ int CatchExceptionToolMain(int argc, char* argv[]) { Options options = {}; - const struct option long_options[] = { + const option long_options[] = { {"file", required_argument, nullptr, kOptionFile}, {"mach-service", required_argument, nullptr, kOptionMachService}, {"persistent", no_argument, nullptr, kOptionPersistent}, diff --git a/tools/mac/exception_port_tool.cc b/tools/mac/exception_port_tool.cc index ad0e4dc1..3bb96524 100644 --- a/tools/mac/exception_port_tool.cc +++ b/tools/mac/exception_port_tool.cc @@ -401,7 +401,7 @@ int ExceptionPortToolMain(int argc, char* argv[]) { bool numeric; } options = {}; - const struct option long_options[] = { + const option long_options[] = { {"set-handler", required_argument, nullptr, kOptionSetPort}, {"show-bootstrap", required_argument, nullptr, kOptionShowBootstrap}, {"pid", required_argument, nullptr, kOptionPid}, diff --git a/tools/mac/on_demand_service_tool.mm b/tools/mac/on_demand_service_tool.mm index 0b22cbd1..c6b69520 100644 --- a/tools/mac/on_demand_service_tool.mm +++ b/tools/mac/on_demand_service_tool.mm @@ -81,7 +81,7 @@ int OnDemandServiceToolMain(int argc, char* argv[]) { std::vector mach_services; } options = {}; - const struct option long_options[] = { + const option long_options[] = { {"load", no_argument, nullptr, kOptionLoadJob}, {"unload", no_argument, nullptr, kOptionUnloadJob}, {"label", required_argument, nullptr, kOptionJobLabel}, diff --git a/tools/mac/run_with_crashpad.cc b/tools/mac/run_with_crashpad.cc index 291913e9..9d6679cf 100644 --- a/tools/mac/run_with_crashpad.cc +++ b/tools/mac/run_with_crashpad.cc @@ -83,7 +83,7 @@ int RunWithCrashpadMain(int argc, char* argv[]) { kOptionVersion = -3, }; - const struct option long_options[] = { + const option long_options[] = { {"handler", required_argument, nullptr, kOptionHandler}, {"annotation", required_argument, nullptr, kOptionAnnotation}, {"database", required_argument, nullptr, kOptionDatabase}, diff --git a/tools/tools.gyp b/tools/tools.gyp index 22eccedf..2c4ad2ab 100644 --- a/tools/tools.gyp +++ b/tools/tools.gyp @@ -59,6 +59,23 @@ 'tool_support.h', ], }, + { + 'target_name': 'crashpad_database_util', + 'type': 'executable', + 'dependencies': [ + 'crashpad_tool_support', + '../client/client.gyp:crashpad_client', + '../compat/compat.gyp:crashpad_compat', + '../third_party/mini_chromium/mini_chromium.gyp:base', + '../util/util.gyp:crashpad_util', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'crashpad_database_util.cc', + ], + }, { 'target_name': 'catch_exception_tool', 'type': 'executable',