mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
Add the run_with_crashpad tool.
run_with_crashpad runs a program with a Crashpad exception handler. It allows a Crashpad exception-handling server to be started and to direct crashes to it from programs that are not themselves clients of the Crashpad client library. R=rsesek@chromium.org Review URL: https://codereview.chromium.org/810423004
This commit is contained in:
parent
2602e9d5d0
commit
f4ec7ba590
99
tools/mac/run_with_crashpad.ad
Normal file
99
tools/mac/run_with_crashpad.ad
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright 2014 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
|
||||
|
||||
= run_with_crashpad(1)
|
||||
|
||||
== Name
|
||||
|
||||
run_with_crashpad - Run a program with a Crashpad exception handler
|
||||
|
||||
== Synopsis
|
||||
|
||||
[verse]
|
||||
*run_with_crashpad* ['OPTION…'] 'COMMAND' ['ARG…']
|
||||
|
||||
== Description
|
||||
|
||||
Starts a Crashpad exception handler server such as crashpad_handler(8) and
|
||||
becomes its client, setting an exception port referencing the handler. Then,
|
||||
executes 'COMMAND' along with any arguments specified ('ARG…') with the new
|
||||
exception port in effect.
|
||||
|
||||
The exception port is configured to receive exceptions of type +EXC_CRASH+,
|
||||
+EXC_RESOURCE+, and +EXC_GUARD+. The exception behavior is configured as
|
||||
+EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES+. The thread state flavor is
|
||||
set to +MACHINE_THREAD_STATE+.
|
||||
|
||||
Programs that use the Crashpad client library directly will not normally use
|
||||
this tool. This tool exists to allow programs that are unaware of Crashpad to be
|
||||
run with a Crashpad exception handler.
|
||||
|
||||
== Options
|
||||
*-h*, *--handler*='HANDLER'::
|
||||
Invoke 'HANDLER' as the Crashpad handler program instead of the default,
|
||||
*crashpad_handler*.
|
||||
|
||||
*-a*, *--handler-argument*='ARGUMENT'::
|
||||
Invokes the Crashpad handler program with 'ARGUMENT' as one of its arguments.
|
||||
This option may appear zero, one, or more times. Regardless of this option’s
|
||||
presence, the handler will always be invoked with the necessary arguments to
|
||||
perform a handshake.
|
||||
|
||||
*--help*::
|
||||
Display help and exit.
|
||||
|
||||
*--version*::
|
||||
Output version information and exit.
|
||||
|
||||
== Examples
|
||||
|
||||
Starts a Crashpad exception handler server by its default name,
|
||||
*crashpad_handler*, and runs a program with this handler in effect.
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ *run_with_crashpad crash*
|
||||
Illegal instruction: 4
|
||||
----
|
||||
|
||||
Starts a Crashpad exception handler server at a nonstandard path, and runs
|
||||
exception_port_tool(1) to show the task-level exception ports.
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ *run_with_crashpad --handler=/tmp/crashpad_handler exception_port_tool*
|
||||
task exception port 0, mask 0x1c00 (CRASH|RESOURCE|GUARD), port 0x30b, behavior
|
||||
0x80000003 (STATE_IDENTITY|MACH), flavor 7 (THREAD)
|
||||
----
|
||||
|
||||
== Exit Status
|
||||
|
||||
*0*::
|
||||
Success.
|
||||
|
||||
*125*::
|
||||
Failure, with a message printed to the standard error stream.
|
||||
|
||||
*126*::
|
||||
The program specified by 'COMMAND' was found, but could not be invoked.
|
||||
|
||||
*127*::
|
||||
The program specified by 'COMMAND' could not be found.
|
||||
|
||||
== See Also
|
||||
|
||||
crashpad_handler(8),
|
||||
exception_port_tool(1)
|
||||
|
||||
include::../man_footer.ad[]
|
144
tools/mac/run_with_crashpad.cc
Normal file
144
tools/mac/run_with_crashpad.cc
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright 2014 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 <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/logging.h"
|
||||
#include "client/crashpad_client.h"
|
||||
#include "tools/tool_support.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace {
|
||||
|
||||
void Usage(const std::string& me) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s [OPTION]... COMMAND [ARG]...\n"
|
||||
"Start a Crashpad handler and have it handle crashes from COMMAND.\n"
|
||||
"\n"
|
||||
" -h, --handler=HANDLER invoke HANDLER instead of crashpad_handler\n"
|
||||
" -a, --handler-argument=ARGUMENT invoke the handler with ARGUMENT\n"
|
||||
" --help display this help and exit\n"
|
||||
" --version output version information and exit\n",
|
||||
me.c_str());
|
||||
ToolSupport::UsageTail(me);
|
||||
}
|
||||
|
||||
int RunWithCrashpadMain(int argc, char* argv[]) {
|
||||
const std::string me(basename(argv[0]));
|
||||
|
||||
enum ExitCode {
|
||||
kExitSuccess = EXIT_SUCCESS,
|
||||
|
||||
// To differentiate this tool’s errors from errors in the programs it execs,
|
||||
// use a high exit code for ordinary failures instead of EXIT_FAILURE. This
|
||||
// is the same rationale for using the distinct exit codes for exec
|
||||
// failures.
|
||||
kExitFailure = 125,
|
||||
|
||||
// Like env, use exit code 126 if the program was found but could not be
|
||||
// invoked, and 127 if it could not be found.
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/env.html
|
||||
kExitExecFailure = 126,
|
||||
kExitExecENOENT = 127,
|
||||
};
|
||||
|
||||
enum OptionFlags {
|
||||
// “Short” (single-character) options.
|
||||
kOptionHandler = 'h',
|
||||
kOptionHandlerArgument = 'a',
|
||||
|
||||
// Long options without short equivalents.
|
||||
kOptionLastChar = 255,
|
||||
|
||||
// Standard options.
|
||||
kOptionHelp = -2,
|
||||
kOptionVersion = -3,
|
||||
};
|
||||
|
||||
const struct option long_options[] = {
|
||||
{"handler", required_argument, nullptr, kOptionHandler},
|
||||
{"handler-argument", required_argument, nullptr, kOptionHandlerArgument},
|
||||
{"help", no_argument, nullptr, kOptionHelp},
|
||||
{"version", no_argument, nullptr, kOptionVersion},
|
||||
{nullptr, 0, nullptr, 0},
|
||||
};
|
||||
|
||||
struct {
|
||||
std::string handler;
|
||||
std::vector<std::string> handler_arguments;
|
||||
} options = {};
|
||||
options.handler = "crashpad_handler";
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, "+a:h:", long_options, nullptr)) !=
|
||||
-1) {
|
||||
switch (opt) {
|
||||
case kOptionHandler:
|
||||
options.handler = optarg;
|
||||
break;
|
||||
case kOptionHandlerArgument:
|
||||
options.handler_arguments.push_back(optarg);
|
||||
break;
|
||||
case kOptionHelp:
|
||||
Usage(me);
|
||||
return kExitSuccess;
|
||||
case kOptionVersion:
|
||||
ToolSupport::Version(me);
|
||||
return kExitSuccess;
|
||||
default:
|
||||
ToolSupport::UsageHint(me, nullptr);
|
||||
return kExitFailure;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!argc) {
|
||||
ToolSupport::UsageHint(me, "COMMAND is required");
|
||||
return kExitFailure;
|
||||
}
|
||||
|
||||
// Start the handler process and direct exceptions to it.
|
||||
CrashpadClient crashpad_client;
|
||||
if (!crashpad_client.StartHandler(base::FilePath(options.handler),
|
||||
options.handler_arguments)) {
|
||||
return kExitFailure;
|
||||
}
|
||||
|
||||
if (!crashpad_client.UseHandler()) {
|
||||
return kExitFailure;
|
||||
}
|
||||
|
||||
// Using the remaining arguments, start a new program with the new exception
|
||||
// port in effect.
|
||||
execvp(argv[0], argv);
|
||||
PLOG(ERROR) << "execvp " << argv[0];
|
||||
return errno == ENOENT ? kExitExecENOENT : kExitExecFailure;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace crashpad
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return crashpad::RunWithCrashpadMain(argc, argv);
|
||||
}
|
@ -102,6 +102,22 @@
|
||||
'mac/on_demand_service_tool.mm',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'run_with_crashpad',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'tool_support',
|
||||
'../client/client.gyp:client',
|
||||
'../compat/compat.gyp:compat',
|
||||
'../third_party/mini_chromium/mini_chromium/base/base.gyp:base',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'mac/run_with_crashpad.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}, {
|
||||
'targets': [],
|
||||
|
Loading…
x
Reference in New Issue
Block a user