2008-08-06 18:36:30 +00:00
|
|
|
// This file is part of BOINC.
|
2007-04-17 02:27:09 +00:00
|
|
|
// http://boinc.berkeley.edu
|
2008-08-06 18:36:30 +00:00
|
|
|
// Copyright (C) 2008 University of California
|
2007-04-17 02:27:09 +00:00
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// BOINC is free software; you can redistribute it and/or modify it
|
|
|
|
// under the terms of the GNU Lesser General Public License
|
|
|
|
// as published by the Free Software Foundation,
|
|
|
|
// either version 3 of the License, or (at your option) any later version.
|
2007-04-17 02:27:09 +00:00
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// BOINC is distributed in the hope that it will be useful,
|
2007-04-17 02:27:09 +00:00
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
// See the GNU Lesser General Public License for more details.
|
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
2007-04-17 02:27:09 +00:00
|
|
|
/*
|
|
|
|
* QCrashReport.h
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* This is part of a backtrace generator for boinc project applications.
|
|
|
|
*
|
|
|
|
* Adapted from Apple Developer Technical Support Sample Code QCrashReport
|
|
|
|
*
|
|
|
|
* This code handles Mac OS X 10.3.x through 10.4.9. It may require some
|
|
|
|
* adjustment for future OS versions; see the discussion of _sigtramp and
|
|
|
|
* PowerPC Signal Stack Frames in file QBacktrace.c.
|
|
|
|
*
|
|
|
|
* For useful tips on using backtrace information, see Apple Tech Note 2123:
|
|
|
|
* http://developer.apple.com/technotes/tn2004/tn2123.html#SECNOSYMBOLS
|
|
|
|
*
|
|
|
|
* To convert addresses to correct symbols, use the atos command-line tool:
|
|
|
|
* atos -o path/to/executable/with/symbols address
|
|
|
|
* Note: if address 1a23 is hex, use 0x1a23.
|
|
|
|
*
|
|
|
|
* To demangle mangled C++ symbols, use the c++filt command-line tool.
|
|
|
|
* You may need to prefix C++ symbols with an additonal underscore before
|
|
|
|
* passing them to c++filt (so they begin with two underscore characters).
|
|
|
|
*
|
|
|
|
* A very useful shell script to add symbols to a crash dump can be found at:
|
|
|
|
* http://developer.apple.com/tools/xcode/symbolizingcrashdumps.html
|
|
|
|
* Pipe the output of the shell script through c++filt to demangle C++ symbols.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
File: QCrashReport.h
|
|
|
|
|
|
|
|
Contains: Code for generating crash reports.
|
|
|
|
|
|
|
|
Written by: DTS
|
|
|
|
|
|
|
|
Copyright: Copyright (c) 2007 Apple Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
|
|
|
|
("Apple") in consideration of your agreement to the following
|
|
|
|
terms, and your use, installation, modification or
|
|
|
|
redistribution of this Apple software constitutes acceptance of
|
|
|
|
these terms. If you do not agree with these terms, please do
|
|
|
|
not use, install, modify or redistribute this Apple software.
|
|
|
|
|
|
|
|
In consideration of your agreement to abide by the following
|
|
|
|
terms, and subject to these terms, Apple grants you a personal,
|
|
|
|
non-exclusive license, under Apple's copyrights in this
|
|
|
|
original Apple software (the "Apple Software"), to use,
|
|
|
|
reproduce, modify and redistribute the Apple Software, with or
|
|
|
|
without modifications, in source and/or binary forms; provided
|
|
|
|
that if you redistribute the Apple Software in its entirety and
|
|
|
|
without modifications, you must retain this notice and the
|
|
|
|
following text and disclaimers in all such redistributions of
|
|
|
|
the Apple Software. Neither the name, trademarks, service marks
|
|
|
|
or logos of Apple Inc. may be used to endorse or promote
|
|
|
|
products derived from the Apple Software without specific prior
|
|
|
|
written permission from Apple. Except as expressly stated in
|
|
|
|
this notice, no other rights or licenses, express or implied,
|
|
|
|
are granted by Apple herein, including but not limited to any
|
|
|
|
patent rights that may be infringed by your derivative works or
|
|
|
|
by other works in which the Apple Software may be incorporated.
|
|
|
|
|
|
|
|
The Apple Software is provided by Apple on an "AS IS" basis.
|
|
|
|
APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
|
|
|
WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
|
|
|
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
|
|
|
|
THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
|
|
|
COMBINATION WITH YOUR PRODUCTS.
|
|
|
|
|
|
|
|
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
|
|
|
INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
|
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
|
|
|
|
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
|
|
|
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
|
|
|
|
OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
|
|
|
|
OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
|
|
SUCH DAMAGE.
|
|
|
|
|
|
|
|
Change History (most recent first):
|
|
|
|
|
|
|
|
$Log: QCrashReport.h,v $
|
|
|
|
Revision 1.1 2007/03/02 12:20:01
|
|
|
|
First checked in.
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _QCRASHREPORT_H
|
|
|
|
#define _QCRASHREPORT_H
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
// Put <mach/mach.h> inside extern "C" guards for the C++ build
|
|
|
|
// because the Mach header files don't always have them.
|
|
|
|
|
|
|
|
#if defined(__cplusplus)
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <mach/mach.h>
|
|
|
|
|
|
|
|
#if defined(__cplusplus)
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-03 21:31:20 +00:00
|
|
|
#include "QMachOImage.h"
|
2007-04-17 02:27:09 +00:00
|
|
|
#include "QBacktrace.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@functiongroup Crash Report Object
|
|
|
|
*/
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
#pragma mark ***** Crash Report Object
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@header QCrashReport.h
|
|
|
|
|
|
|
|
@abstract High-level crash report object.
|
|
|
|
|
|
|
|
@discussion This module provides a high-level interface for creating and
|
|
|
|
recording crash report information. It encapsulates all of
|
|
|
|
the complexity of many lower-level modules, providing you with
|
|
|
|
a nice, clean interface for creating crash reports.
|
|
|
|
|
|
|
|
To create a create report object, just call QCRCreateFromTask or
|
|
|
|
QCRCreateFromSelf. Use QCRDestroy to destroy the resulting
|
|
|
|
object. Use QCRGetThreadCount and QCRGetThreadAtIndex to
|
|
|
|
iterate the threads of the crash report, and
|
|
|
|
QCRGetBacktraceAtIndex to interate the backtraces for those
|
|
|
|
threads. Call QCRGetSymbols and QCRGetImages to get at the
|
|
|
|
underlying symbols object and image objects. Finally,
|
|
|
|
QCRPrintBacktraces, QCRPrintThreadState and QCRPrintImages
|
|
|
|
provide a standard way to render crash reports to text.
|
|
|
|
|
|
|
|
This module assumes that the state of the process you're
|
|
|
|
investigating is stable. That is, when you create a crash report
|
|
|
|
object for a process, you need to guarantee that the state
|
|
|
|
of the process does not change while that object exists.
|
|
|
|
The best way to prevent this from happening is to suspend the
|
|
|
|
process while you're accessing it. You can automatically
|
|
|
|
suspend the task for the lifetime of the crash report object by
|
|
|
|
pass true to the suspend parameter of QCRCreateFromTask.
|
|
|
|
|
|
|
|
One special case of this applies to crash report objects that
|
|
|
|
target the current process (mach_task_self). In this case,
|
|
|
|
it's not feasible to suspend the task, a fact that makes for
|
|
|
|
some interesting challenges. This module copes with that
|
|
|
|
in two ways:
|
|
|
|
|
|
|
|
o When you get a backtrace for a thread, it implicitly gets
|
|
|
|
the thread's state. It then caches that state and the
|
|
|
|
associated backtrace. From that point on, you get
|
|
|
|
a consistent backtrace, although it may not be correlated
|
|
|
|
with the current state of the thread.
|
|
|
|
|
|
|
|
o An exception to this is for the current thread
|
|
|
|
(mach_thread_self). Unless you explicitly set its state
|
|
|
|
(using QCRSetThreadStateAtIndex), the act of calling
|
|
|
|
QCRGetBacktraceAtIndex causes the module to throw away
|
|
|
|
the cached backtrace for the thread and generate a new one
|
|
|
|
based on the thread's current state.
|
|
|
|
|
|
|
|
This has some interesting consequences on the life time of
|
|
|
|
certain memory blocks returned by the module. Specifically:
|
|
|
|
|
|
|
|
o thread state returned by QCRGetThreadStateAtIndex
|
|
|
|
|
|
|
|
o backtrace frames returned by QCRGetBacktraceAtIndex
|
|
|
|
|
|
|
|
In both cases, this memory persists until one of the following
|
|
|
|
happens:
|
|
|
|
|
|
|
|
- you destroy the crash report object
|
|
|
|
- you explicitly set the thread state using QCRSetThreadStateAtIndex
|
|
|
|
- it's associated with the current thread and you generate
|
|
|
|
a new backtrace for the thread by calling QCRGetBacktraceAtIndex
|
|
|
|
|
|
|
|
In addition, this module provides some helper routines for
|
|
|
|
launching a crash report tool (QCRExecuteCrashReportTool) and
|
|
|
|
for giving that tool access to the task control port for the
|
|
|
|
crashed task (QCRGetParentTask).
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@typedef QCrashReportRef
|
|
|
|
|
|
|
|
@abstract A reference to the crash report object.
|
|
|
|
|
|
|
|
@discussion This type is opaque; to create, destroy, or access it, you must
|
|
|
|
use the routines in this module.
|
|
|
|
*/
|
|
|
|
typedef struct QCrashReport *QCrashReportRef;
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@functiongroup Create and Destroy
|
|
|
|
*/
|
|
|
|
#pragma mark ***** Create and Destroy
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRCreateFromTask
|
|
|
|
|
|
|
|
@abstract Creates a crash report object for an arbitrary process.
|
|
|
|
|
|
|
|
@discussion Creates a crash report object for the specified process.
|
|
|
|
|
|
|
|
@param task Must be the name of a valid send right for the task control
|
|
|
|
port of the process to inspect; mach_task_self is just fine.
|
|
|
|
|
|
|
|
If you do pass in mach_task_self, this routine automatically
|
|
|
|
enables some nice optimisations.
|
|
|
|
|
|
|
|
@param suspend If true, the target task is suspended while the crash report
|
|
|
|
object exists.
|
|
|
|
|
|
|
|
Must not be true if task is mach_task_self.
|
|
|
|
|
|
|
|
@param crashedThread
|
|
|
|
The name of a valid send right for the thread control port of
|
|
|
|
the thread that crashed, or MACH_PORT_NULL if you don't have
|
|
|
|
this information handy. If you pass in MACH_PORT_NULL, you
|
|
|
|
can also set the crashed thread later by calling
|
|
|
|
QCRSetCrashedThreadIndex.
|
|
|
|
|
|
|
|
It is accepatble to pass mach_thread_self to this parameter,
|
|
|
|
but it may not do what you expect. See the discussion
|
|
|
|
above for details.
|
|
|
|
|
|
|
|
This value primarily affects the text rendering routines;
|
|
|
|
see the discussion in QCRSetCrashedThreadIndex for details.
|
|
|
|
|
|
|
|
@param cputype The CPU type for which you are creating a crash report.
|
|
|
|
Typically you would pass CPU_TYPE_ANY to use the CPU type of
|
|
|
|
the first dynamic linker that's discovered. See
|
|
|
|
QMOImageCreateFromTaskDyld for a detailed discussion of this
|
|
|
|
value.
|
|
|
|
|
|
|
|
@param crRefPtr On entry, crRefPtr must not be NULL and *crRefPtr must
|
|
|
|
be NULL. On success, *crRefPtr will be a reference to the
|
|
|
|
crash report object that's been created. On error, *crRefPtr
|
|
|
|
will be NULL.
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
*/
|
|
|
|
extern int QCRCreateFromTask(
|
|
|
|
task_t task,
|
|
|
|
bool suspend,
|
|
|
|
thread_t crashedThread,
|
|
|
|
cpu_type_t cputype,
|
|
|
|
QCrashReportRef * crRefPtr
|
|
|
|
);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRCreateFromSelf
|
|
|
|
|
|
|
|
@abstract Creates a crash report object for the current process.
|
|
|
|
|
|
|
|
@discussion This is equivalent to calling QCRCreateFromTask with
|
|
|
|
mach_task_self, false, mach_thread_self, and QMOGetLocalCPUType
|
|
|
|
for the first four parameters.
|
|
|
|
|
|
|
|
@param crRefPtr On entry, crRefPtr must not be NULL and *crRefPtr must
|
|
|
|
be NULL. On success, *crRefPtr will be a reference to the
|
|
|
|
crash report object that's been created. On error, *crRefPtr
|
|
|
|
will be NULL.
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
*/
|
|
|
|
extern int QCRCreateFromSelf(QCrashReportRef *crRefPtr);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRDestroy
|
|
|
|
|
|
|
|
@abstract Destroys a crash report object.
|
|
|
|
|
|
|
|
@discussion Destroys the supplied crash report object.
|
|
|
|
|
|
|
|
@param qmoImage The crash report object to destroy. If this is NULL, the routine
|
|
|
|
does nothing.
|
|
|
|
*/
|
|
|
|
extern void QCRDestroy(QCrashReportRef crRef);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@functiongroup Accessors
|
|
|
|
*/
|
|
|
|
#pragma mark ***** Accessors
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetSymbols
|
|
|
|
|
|
|
|
@abstract Gets the symbols for this crash report.
|
|
|
|
|
|
|
|
@discussion Gets the symbols object for this crash report object.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@result A reference to the symbols object. This will never be
|
|
|
|
NULL (it is created when the crash report object is created,
|
|
|
|
and any failures would have caused creation to fail). It
|
|
|
|
exists until you destroy the crash report object.
|
|
|
|
*/
|
|
|
|
extern QSymbolsRef QCRGetSymbols(QCrashReportRef crRef);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetImages
|
|
|
|
|
|
|
|
@abstract Gets the images for this crash report.
|
|
|
|
|
|
|
|
@discussion Gets the array of image objects for this crash report object.
|
|
|
|
|
|
|
|
This routine can never fail; the image array is created when
|
|
|
|
the crash report object is created, and any failures would
|
|
|
|
have caused creation to fail.
|
|
|
|
|
|
|
|
IMPORTANT: Do not free the array that this returns, or indeed
|
|
|
|
any of the image objects contained in the array. These all
|
|
|
|
belongs to the crash report object and will be destroyed when
|
|
|
|
the crash report object is destroyed.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param imageArrayPtr
|
|
|
|
A pointer to an image object array pointer. On entry,
|
|
|
|
imageArrayPtr must not be NULL and *imageArrayPtr is
|
|
|
|
ignored. On return, *imageArrayPtr will be a pointer
|
|
|
|
to *imageCountPtr QMOImageRef objects.
|
|
|
|
|
|
|
|
@param imageCountPtr
|
|
|
|
A pointer to an image object count. On entry, imageCountPtr
|
|
|
|
must not be NULL and *imageCountPtr is ignored. On return,
|
|
|
|
*imageCountPtr is the size of the image array whose pointer
|
|
|
|
is returned in *imageArrayPtr.
|
|
|
|
*/
|
|
|
|
extern void QCRGetImages(
|
|
|
|
QCrashReportRef crRef,
|
|
|
|
QMOImageRef ** imageArrayPtr,
|
|
|
|
size_t * imageCountPtr
|
|
|
|
);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetThreadCount
|
|
|
|
|
|
|
|
@abstract Returns the number of threads in this crash report.
|
|
|
|
|
|
|
|
@discussion Return the number of threads running in the process for which
|
|
|
|
this crash report was created.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@result A count of the number of threads.
|
|
|
|
*/
|
|
|
|
extern size_t QCRGetThreadCount(QCrashReportRef crRef);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetThreadAtIndex
|
|
|
|
|
|
|
|
@abstract Returns the specified thread for a crash report.
|
|
|
|
|
|
|
|
@discussion Returns the thread specified by threadIndex for the crash
|
|
|
|
report.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param threadIndex
|
|
|
|
A zero-based index into the array of threads.
|
|
|
|
|
|
|
|
@result Returns the name of a send right for the thread control
|
|
|
|
port. This right is owned by the crash report object;
|
|
|
|
you must not release it and it goes away when you destroy
|
|
|
|
the crash report object (although you may have other
|
|
|
|
references to the right).
|
|
|
|
*/
|
|
|
|
extern thread_t QCRGetThreadAtIndex(QCrashReportRef crRef, size_t threadIndex);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetThreadStateAtIndex
|
|
|
|
|
|
|
|
@abstract Gets the thread state of the specified thread.
|
|
|
|
|
|
|
|
@discussion Returns the state of the specified thread in the crash
|
|
|
|
report object. The first time you call this function
|
|
|
|
(either explicitly, or implicitly by calling functions that
|
|
|
|
need the thread state), it takes a snapshot of the thread
|
|
|
|
state. By the time the function returns, this snapshot is
|
|
|
|
valid only if the thread (or the entire task) is suspend.
|
|
|
|
Also, the lifetime of this snapshot is controlled by a number
|
|
|
|
of factors; see the detailed discussion of this topic,
|
|
|
|
above.
|
|
|
|
|
|
|
|
If you have explicitly set the thread state (by calling
|
|
|
|
QCRSetThreadStateAtIndex) you will get back the values you
|
|
|
|
set most recently.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param threadIndex
|
|
|
|
A zero-based index into the array of threads.
|
|
|
|
|
|
|
|
If this specifies the current thread (that is, QCRGetThreadAtIndex
|
|
|
|
for this index returns mach_thread_self), you probably won't
|
|
|
|
get useful results. See the discussion above for details.
|
|
|
|
|
|
|
|
@param cpuTypePtr
|
|
|
|
If NULL, this parameter is ignored. Otherwise,
|
|
|
|
on entry, the value of *cpuTypePtr is ignored. On success,
|
|
|
|
*cpuTypePtr will be the CPU type of the process that contains
|
|
|
|
the thread (for example, CPU_TYPE_X86). This will be the same
|
|
|
|
for all threads within the process. On error, the value in
|
|
|
|
*cpuTypePtr is undefined.
|
|
|
|
|
|
|
|
@param threadStateFlavorPtr
|
|
|
|
If NULL, this parameter is ignored. Otherwise,
|
|
|
|
on entry, the value of *threadStateFlavorPtr is ignored.
|
|
|
|
On success, *threadStateFlavorPtr will be the thread state
|
|
|
|
flavor of the thread's state (for example, x86_THREAD_STATE32).
|
|
|
|
On error, the value in *threadStateFlavorPtr is undefined.
|
|
|
|
|
|
|
|
@param threadStatePtr
|
|
|
|
If NULL, this parameter is ignored. Otherwise,
|
|
|
|
on entry, the value of *threadStatePtr is ignored.
|
|
|
|
On success, *threadStatePtr will contain a pointer to the
|
|
|
|
thread's state (for example, you could treat this as a pointer
|
|
|
|
to a x86_thread_state32_t structure). On error, the value in
|
|
|
|
*threadStatePtr is undefined.
|
|
|
|
|
|
|
|
IMPORTANT: The lifetime of this pointer is controlled by
|
|
|
|
a number of factors. See the detailed discussion of this
|
|
|
|
topic, above.
|
|
|
|
|
|
|
|
@param threadStateSizePtr
|
|
|
|
If NULL, this parameter is ignored. Otherwise,
|
|
|
|
on entry, the value of *threadStateSizePtr is ignored.
|
|
|
|
On success, *threadStateSizePtr will be the size, in bytes,
|
|
|
|
of thread's state (for example, sizeof(x86_thread_state32_t)).
|
|
|
|
On error, the value in *threadStateSizePtr is undefined.
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
If threadIndex is out of range, this will be EINVAL.
|
|
|
|
*/
|
|
|
|
extern int QCRGetThreadStateAtIndex(
|
|
|
|
QCrashReportRef crRef,
|
|
|
|
size_t threadIndex,
|
|
|
|
cpu_type_t * cpuTypePtr,
|
|
|
|
thread_state_flavor_t * threadStateFlavorPtr,
|
|
|
|
const void ** threadStatePtr,
|
|
|
|
size_t * threadStateSizePtr
|
|
|
|
);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRSetThreadStateAtIndex
|
|
|
|
|
|
|
|
@abstract Set the thread state for the specified thread.
|
|
|
|
|
|
|
|
@discussion Sets the thread state of the specified thread within the
|
|
|
|
the crash report. This is useful if you have a better idea
|
|
|
|
of the thread's state than the default mechanism for getting
|
|
|
|
the thread state used by QCRGetThreadStateAtIndex (which gets
|
|
|
|
it by calling the Mach routine thread_get_state). For example,
|
|
|
|
if you're running in a signal handler, you can extract the
|
|
|
|
interrupted thread's state from the signal handlers parameters.
|
|
|
|
|
|
|
|
If you set a thread's state by calling this routine, it
|
|
|
|
persists for the lifetime of the crash report object (unless
|
|
|
|
you override it by calling this routine again).
|
|
|
|
|
|
|
|
The memory buffer specified by threadState and threadStateSize
|
|
|
|
is copied by this routine; you do not need to maintain it
|
|
|
|
once the routine has returned.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param threadIndex
|
|
|
|
A zero-based index into the array of threads.
|
|
|
|
|
|
|
|
It is both acceptable and useful to specify the current
|
|
|
|
thread here (that is, pass in a value for which QCRGetThreadAtIndex
|
|
|
|
would return mach_thread_self).
|
|
|
|
|
|
|
|
@param threadStateFlavor
|
|
|
|
Must be the thread state flavor of the new thread state
|
|
|
|
(for example, x86_THREAD_STATE32).
|
|
|
|
|
|
|
|
@param threadState
|
|
|
|
Must be a pointer to the new thread state (for example, a
|
|
|
|
pointer to a x86_thread_state32_t structure). NULL is not
|
|
|
|
acceptable.
|
|
|
|
|
|
|
|
@param threadStateSize
|
|
|
|
The size, in bytes, of the new thread state pointed to by
|
|
|
|
threadState (for example, sizeof(x86_thread_state32_t)). Due
|
|
|
|
to the nature of Mach thread states, this must not be zero and
|
|
|
|
must be an even multiple of sizeof(integer_t).
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
If threadIndex is out of range, this will be EINVAL.
|
|
|
|
*/
|
|
|
|
extern int QCRSetThreadStateAtIndex(
|
|
|
|
QCrashReportRef crRef,
|
|
|
|
size_t threadIndex,
|
|
|
|
thread_state_flavor_t threadStateFlavor,
|
|
|
|
const void * threadState,
|
|
|
|
size_t threadStateSize
|
|
|
|
);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetBacktraceAtIndex
|
|
|
|
|
|
|
|
@abstract Returns a backtrace for the specified thread.
|
|
|
|
|
|
|
|
@discussion Returns a backtrace for the specified thread. The first time
|
|
|
|
you call this function (except when specifying the current
|
|
|
|
thread, see below), it takes a snapshot of the thread's
|
|
|
|
backtrace. For each subsequent call, you get back the
|
|
|
|
same backtrace. This lifetime of this backtrace is
|
|
|
|
controlled by a number of factors; see the detailed
|
|
|
|
discussion of this topic, above.
|
|
|
|
|
|
|
|
This routine has a special case so that you can easily get a
|
|
|
|
meaningful backtrace for the current thread. If you specify
|
|
|
|
the current thread (that is, you pass in a value for which
|
|
|
|
QCRGetThreadAtIndex would return mach_thread_self) and you
|
|
|
|
have not explicitly set the thread state (by calling
|
|
|
|
QCRSetThreadStateByIndex), this routine will return a backtrace
|
|
|
|
for the current thread at the current time. This backtrace
|
|
|
|
will persist until you call this function again (or until any
|
|
|
|
of the other events that can clear the backtrace occurs; see
|
|
|
|
the detailed discussion above).
|
|
|
|
|
|
|
|
If you call this for anything except the current thread,
|
|
|
|
it implicitly snapshots the current thread state; this ensures
|
|
|
|
that the current thread state and the backtrace are in sync.
|
|
|
|
|
|
|
|
IMPORTANT: The lifetime of the array returned by this routine
|
|
|
|
is controlled by a number of factors. See the detailed
|
|
|
|
discussion of this topic, above.
|
|
|
|
|
|
|
|
IMPORTANT: Do not free the array that this returns, or indeed
|
|
|
|
any of the items in the array. These all belongs to the crash
|
|
|
|
report object and will be destroyed when the crash report
|
|
|
|
object is destroyed.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param threadIndex
|
|
|
|
A zero-based index into the array of threads.
|
|
|
|
|
|
|
|
@param frameArrayPtr
|
|
|
|
Must not be NULL. On entry, the value of *frameArrayPtr is ignored.
|
|
|
|
On success, *frameArrayPtr will contain a pointer to an array
|
|
|
|
of *frameCountPtr QBTFrame objects. On error, the value in
|
|
|
|
*frameArrayPtr is undefined.
|
|
|
|
|
|
|
|
@param frameCountPtr
|
|
|
|
Must not be NULL. On entry, the value of *frameCountPtr is
|
|
|
|
ignored. On success, *frameCountPtr will be the number of
|
|
|
|
valid elements in the array pointed to be *frameArrayPtr.
|
|
|
|
On error, the value in *frameCountPtr is undefined.
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
If threadIndex is out of range, this will be EINVAL.
|
|
|
|
*/
|
|
|
|
extern int QCRGetBacktraceAtIndex(
|
|
|
|
QCrashReportRef crRef,
|
|
|
|
size_t threadIndex,
|
|
|
|
const QBTFrame ** frameArrayPtr,
|
|
|
|
size_t * frameCountPtr
|
|
|
|
);
|
|
|
|
|
|
|
|
enum {
|
|
|
|
kQCRNoThread = (size_t) -1
|
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetCrashedThreadIndex
|
|
|
|
|
|
|
|
@abstract Returns the crashed thread.
|
|
|
|
|
|
|
|
@discussion Returns the index of the crashed thread. Unless you've
|
|
|
|
explicitly set this (using QCRSetCrashedThreadIndex), this
|
|
|
|
value is determined as follows:
|
|
|
|
|
|
|
|
1. If you specified MACH_PORT_NULL when you created the crash
|
|
|
|
report object, the result will be kQCRNoThread.
|
|
|
|
|
|
|
|
2. Otherwise, the result will be the index of the thread that
|
|
|
|
matches the thread that you specified.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@result The index of the crashed thread, or kQCRNoThread if none
|
|
|
|
was specified.
|
|
|
|
*/
|
|
|
|
extern size_t QCRGetCrashedThreadIndex(QCrashReportRef crRef);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRSetCrashedThreadIndex
|
|
|
|
|
|
|
|
@abstract Sets the crashed thread.
|
|
|
|
|
|
|
|
@discussion Sets the index of the crashed thread. This value can be
|
|
|
|
specified initially by passing a value to the crashedThread
|
|
|
|
parameter of QCRCreateFromTask. However, you can use this
|
|
|
|
function to override this value at any time.
|
|
|
|
|
|
|
|
The information primarily affects the text rendering routines.
|
|
|
|
The crashed thread will be highlighted by QCRPrintBacktraces.
|
|
|
|
Also, QCRPrintThreadState prints the thread state of the
|
|
|
|
crashed thread.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param threadIndex
|
|
|
|
A zero-based index into the array of threads.
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
If threadIndex is out of range, this will be EINVAL.
|
|
|
|
*/
|
|
|
|
extern int QCRSetCrashedThreadIndex(QCrashReportRef crRef, size_t threadIndex);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@functiongroup Text Rendering
|
|
|
|
*/
|
|
|
|
#pragma mark ***** Text Rendering
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRPrintBacktraces
|
|
|
|
|
|
|
|
@abstract Prints backtraces of each thread in the crash report.
|
|
|
|
|
|
|
|
@discussion This function is designed to ape the backtraces section of
|
|
|
|
a CrashReporter crash log as much as possible.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param f The file to print to. If you want to print to something
|
|
|
|
other than a file, create a custom (FILE *) object using
|
|
|
|
<x-man-page://3/funopen>.
|
|
|
|
*/
|
|
|
|
extern void QCRPrintBacktraces(QCrashReportRef crRef, FILE *f);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRPrintThreadState
|
|
|
|
|
|
|
|
@abstract Prints the thread state of the crashed thread.
|
|
|
|
|
|
|
|
@discussion This function is designed to ape the thread state section of
|
|
|
|
a CrashReporter crash log as much as possible.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param f The file to print to. If you want to print to something
|
|
|
|
other than a file, create a custom (FILE *) object using
|
|
|
|
<x-man-page://3/funopen>.
|
|
|
|
*/
|
|
|
|
extern void QCRPrintThreadState(QCrashReportRef crRef, FILE *f);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRPrintImages
|
|
|
|
|
|
|
|
@abstract Prints the dyld images of the crashed thread.
|
|
|
|
|
|
|
|
@discussion This function is designed to ape the "Binary Images Description"
|
|
|
|
section of a CrashReporter crash log as much as possible.
|
|
|
|
|
|
|
|
@param crRef A valid crash report object.
|
|
|
|
|
|
|
|
@param f The file to print to. If you want to print to something
|
|
|
|
other than a file, create a custom (FILE *) object using
|
|
|
|
<x-man-page://3/funopen>.
|
|
|
|
*/
|
|
|
|
extern void QCRPrintImages(QCrashReportRef crRef, FILE *f);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@functiongroup Tool Helpers
|
|
|
|
*/
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
#pragma mark ***** Tool Helpers
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRExecuteCrashReportTool
|
|
|
|
|
|
|
|
@abstract Runs a crash report tool, giving it access to our task.
|
|
|
|
|
|
|
|
@discussion This function runs a crash report tool against the current
|
|
|
|
task in such a way that the crash report tool can get a
|
|
|
|
send right to the current process's task control port by
|
|
|
|
calling QCRGetParentTask.
|
|
|
|
|
|
|
|
IMPORTANT: This routine isn't thread safe. To do its work
|
|
|
|
it must switch the current task's bootstrap port, fork/exec
|
|
|
|
the tool, and then switch the port back. This can't be
|
|
|
|
done in a thread-safe way on current versions of Mac OS X.
|
|
|
|
|
|
|
|
@param toolArgs An array of arguments for the tool. The array must be
|
|
|
|
terminated by a NULL entry. The first entry must contain
|
|
|
|
the path to the tool.
|
|
|
|
|
|
|
|
@param pidPtr If NULL, the tool runs synchronously. That is, the routine
|
|
|
|
waits for the tool to exit before returning. In that case,
|
|
|
|
toolStatusPtr must not be NULL.
|
|
|
|
|
|
|
|
If non-NULL, the tools runs asynchronously and the routine
|
|
|
|
returns the process ID of the tool so that you can wait
|
|
|
|
for it to complete. On entry, *pidPtr must be -1. On
|
|
|
|
success, *pidPtr will be the process ID of the running tool
|
|
|
|
(that is, not -1). On error, *pidPtr will be -1.
|
|
|
|
|
|
|
|
@param toolStatusPtr
|
|
|
|
If the tool is run synchronously, the routine returns the
|
|
|
|
tool's exit status here. This is the value returned from
|
|
|
|
its main function (typically EXIT_SUCCESS or EXIT_FAILURE).
|
|
|
|
|
|
|
|
In the synchronous case, toolStatusPtr must not be NULL.
|
|
|
|
On entry, *toolStatusPtr is ignore. On success,
|
|
|
|
*toolStatusPtr contains the tool's exit status. On error,
|
|
|
|
the value of *toolStatusPtr is undefined.
|
|
|
|
|
|
|
|
In the asynchronous case, toolStatusPtr must be NULL.
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
*/
|
|
|
|
extern int QCRExecuteCrashReportTool(const char *toolArgs[], pid_t *pidPtr, int *toolStatusPtr);
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@function QCRGetParentTask
|
|
|
|
|
|
|
|
@abstract Returns the task control port for the parent task.
|
|
|
|
|
|
|
|
@discussion For a crash report tool executed by QCRExecuteCrashReportTool,
|
|
|
|
this routine returns the name of a send right for the parent
|
|
|
|
process's task control port. This allows you to interrogate
|
|
|
|
the parent process using routines like QCRCreateFromTask.
|
|
|
|
|
|
|
|
@param taskPtr Must not be NULL. On entry, *taskPtr must be MACH_PORT_NULL.
|
|
|
|
On success, *taskPtr will be the name of a send right for the
|
|
|
|
parent process's task control port. On error, *taskPtr will
|
|
|
|
be MACH_PORT_NULL.
|
|
|
|
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
*/
|
|
|
|
extern int QCRGetParentTask(task_t *taskPtr);
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|