mirror of https://github.com/BOINC/boinc.git
427 lines
17 KiB
C
427 lines
17 KiB
C
// This file is part of BOINC.
|
|
// http://boinc.berkeley.edu
|
|
// Copyright (C) 2008 University of California
|
|
//
|
|
// 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.
|
|
//
|
|
// BOINC is distributed in the hope that it will be useful,
|
|
// 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.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
|
/*
|
|
* QTaskMemory.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: QTaskMemory.h
|
|
|
|
Contains: Task memory access abstraction.
|
|
|
|
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: QTaskMemory.h,v $
|
|
Revision 1.1 2007/03/02 12:20:40
|
|
First checked in.
|
|
|
|
|
|
*/
|
|
|
|
#ifndef _QTASKMEMORY_H
|
|
#define _QTASKMEMORY_H
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
#include <stdbool.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
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*!
|
|
@header QTaskMemory.h
|
|
|
|
@abstract Abstraction layer for reading another process's memory.
|
|
|
|
@discussion This module lets you read memory from another task. It's implemented
|
|
using Mach APIs that are designed for that very job. The purpose of
|
|
this module is to make those routines easier to call, handling the
|
|
various nasty compatibility problems that arise. See the comments
|
|
inside "QTaskMemory.c" for the gory details.
|
|
|
|
When using this module, keep in mind that addresses within a remote
|
|
task are represented by an unsigned 64-bit integer (QTMAddr). This
|
|
is necessary because it lets a 32-bit tool examine a 64-bit task.
|
|
-- Changed for BOINC: See comments in QTaskMemory.c
|
|
|
|
Because of oddities in the underlying infrastructure (specifically,
|
|
mach_vm_read does odd things if you ask for a size of zero -- it
|
|
returns KERN_SUCCESS, addrLocal == 0, bytesRead == 0), we don't
|
|
allow clients to request a size of zero.
|
|
*/
|
|
|
|
/*!
|
|
@functiongroup Main Interface
|
|
*/
|
|
/////////////////////////////////////////////////////////////////
|
|
#pragma mark ***** Main Interface
|
|
|
|
/*!
|
|
@typedef QTMAddr
|
|
|
|
@abstract Represents an address within a task.
|
|
|
|
@discussion This type represents an address within a task. We can't just
|
|
use use (void *) because we need to be able to represent 64-bit
|
|
addresses, even if we're built 32-bit.
|
|
*/
|
|
#if TARGET_CPU_X86 || TARGET_CPU_X86_64
|
|
typedef mach_vm_address_t QTMAddr;
|
|
#else
|
|
typedef uint64_t QTMAddr;
|
|
#endif
|
|
|
|
/*!
|
|
@typedef QTMOffset
|
|
|
|
@abstract Represents a byte offset between two QTMAddrs.
|
|
|
|
@discussion This type represents a byte offset between two QTMAddrs. We
|
|
can't just use use ptrdiff_t or size_t because we need to be
|
|
able to represent a 64-bit offset, even if we're built 32-bit.
|
|
*/
|
|
#if TARGET_CPU_X86 || TARGET_CPU_X86_64
|
|
typedef mach_vm_offset_t QTMOffset;
|
|
#else
|
|
typedef uint64_t QTMOffset;
|
|
#endif
|
|
|
|
/*!
|
|
@function QTMRead
|
|
|
|
@abstract Reads memory from a task.
|
|
|
|
@discussion Read size bytes from addrWithinTask of the task to the buffer
|
|
specified by addrLocal. There are no partial results; you
|
|
either get size bytes of data or an error.
|
|
|
|
@param task Must be the name of a valid send right for the task control
|
|
port of the task whose memory you want to read; mach_task_self
|
|
is just fine.
|
|
|
|
@param addrWithinTask
|
|
The address within that task of the memory you want to read.
|
|
|
|
@param size The number of bytes that you want to read; there must be this
|
|
many bytes available in the buffer pointed to by addrLocal.
|
|
It must not be zero.
|
|
|
|
@param addrLocal
|
|
The address of the buffer into which you want to read the bytes.
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
*/
|
|
extern int QTMRead(task_t task, QTMAddr addrWithinTask, size_t size, void *addrLocal);
|
|
|
|
/*!
|
|
@function QTMReadAllocated
|
|
|
|
@abstract Allocates a buffer and reads memory from a task into it.
|
|
|
|
@discussion Read size bytes from addrWithinTask of the task to a newly
|
|
allocated buffer, and return a pointer to that buffer in *bufPtr.
|
|
The client is responsible for freeing the buffer by calling QTMFree.
|
|
|
|
@param task Must be the name of a valid send right for the task control
|
|
port of the task whose memory you want to read; mach_task_self
|
|
is just fine.
|
|
|
|
@param addrWithinTask
|
|
The address within that task of the memory you want to read.
|
|
|
|
@param size The number of bytes that you want to read. It must not be zero.
|
|
|
|
@param bufPtr On entry, bufPtr must not be NULL and *bufPtr must be NULL.
|
|
On success, *bufPtr will point to a buffer of at least size bytes.
|
|
You must free the buffer by calling QTMFree.
|
|
On failure, *bufPtr will be NULL.
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
*/
|
|
extern int QTMReadAllocated(task_t task, QTMAddr addrWithinTask, size_t size, const void **bufPtr);
|
|
|
|
/*!
|
|
@function QTMRemap
|
|
|
|
@abstract Maps memory from a task into your address space.
|
|
|
|
@discussion Maps size bytes of memory from addrWithinTask to the current
|
|
task and returns the address of the newly mapped data in *bufPtr.
|
|
The client is responsible for freeing the buffer by calling
|
|
QTMFree.
|
|
|
|
@param task Must be the name of a valid send right for the task control
|
|
port of the task whose memory you want to map; mach_task_self
|
|
is just fine.
|
|
|
|
@param addrWithinTask
|
|
The address within that task of the memory you want to map.
|
|
|
|
@param size The number of bytes that you want to map. It must not be zero.
|
|
|
|
@param bufPtr On entry, bufPtr must not be NULL and *bufPtr must be NULL.
|
|
On success, *bufPtr will point to a buffer of at least size bytes.
|
|
You must free the buffer by calling QTMFree.
|
|
On failure, *bufPtr will be NULL.
|
|
|
|
@result An errno-style error code per QTMErrnoFromMachError.
|
|
|
|
*/
|
|
extern int QTMRemap(task_t task, QTMAddr addrWithinTask, size_t size, const void **bufPtr);
|
|
|
|
/*!
|
|
@function QTMFree
|
|
|
|
@abstract Free data returned by QTMReadAllocated or QTMRemap.
|
|
|
|
@discussion Free data returned by QTMReadAllocated or QTMRemap.
|
|
|
|
@param buf The buffer to free. This may be NULL, in which case the routine
|
|
does nothing.
|
|
|
|
@param size The size of the buffer to free. If buf is NULL, this value
|
|
is ignored. If buf is not NULL, this must bee the same value
|
|
as passed to the routine that allocated the memory (and hence
|
|
must not be 0).
|
|
*/
|
|
extern void QTMFree(const void *buf, size_t size);
|
|
|
|
/*!
|
|
@functiongroup Utilities
|
|
*/
|
|
/////////////////////////////////////////////////////////////////
|
|
#pragma mark ***** Utilities
|
|
|
|
/*!
|
|
@function QTMErrnoFromMachError
|
|
|
|
@abstract Converts a Mach error code to a errno-style error code.
|
|
|
|
@discussion Various other modules call Mach directly for various reasons,
|
|
and these need to translate Mach-style errors into errno-style
|
|
errors. This module already has a helper routine to do that
|
|
job, so I export it.
|
|
|
|
IMPORTANT:
|
|
This routine can still return errors outside of the errno range.
|
|
What it does is as follows:
|
|
|
|
1. If the Mach error is something obvious that we recognise,
|
|
map it to a specific errno-style error.
|
|
|
|
2. Failing that, if the Mach error is outside of the errno
|
|
range (and thus it's not ambiguous as to whether the error
|
|
is a Mach error or an errno error), just return it.
|
|
|
|
3. For unrecognised Mach errors within the errno range, just
|
|
return EINVAL.
|
|
|
|
The upshot is that if an error is outside of the errno range
|
|
[0..ELAST], you should treat it as a Mach error.
|
|
|
|
@param kr A Mach error code.
|
|
|
|
@result An errno-style error code.
|
|
*/
|
|
extern int QTMErrnoFromMachError(kern_return_t kr);
|
|
|
|
/*!
|
|
@enum QTMDarwinOSMajor
|
|
|
|
@abstract Constants for Darwin OS release major values.
|
|
|
|
@constant kQTMDarwinOSMajorForMacOSX102
|
|
The Darwin OS release major value for Mac OS X 10.2.x.
|
|
|
|
@constant kQTMDarwinOSMajorForMacOSX103
|
|
The Darwin OS release major value for Mac OS X 10.3.x.
|
|
|
|
@constant kQTMDarwinOSMajorForMacOSX104
|
|
The Darwin OS release major value for Mac OS X 10.4.x.
|
|
*/
|
|
enum QTMDarwinOSMajor {
|
|
kQTMDarwinOSMajorForMacOSX102 = 6,
|
|
kQTMDarwinOSMajorForMacOSX103 = 7,
|
|
kQTMDarwinOSMajorForMacOSX104 = 8
|
|
};
|
|
|
|
/*!
|
|
@function QTMGetDarwinOSRelease
|
|
|
|
@abstract Returns the Darwin OS release numbers.
|
|
|
|
@discussion Returns the Darwin OS release numbers for the current
|
|
system. It gets these values by calling uname and parsing
|
|
the results. For example, the major/minor/bug values for
|
|
Mac OS X 10.4.8 will be 8/8/x (where x is dependent on the
|
|
particular release).
|
|
|
|
This is useful in environments, like a 64-bit process running
|
|
on Mac OS X 10.4.x, where you can't get gestaltSystemVersion.
|
|
|
|
@param majorPtr May be NULL, in which case no value is return. Otherwise,
|
|
on entry, *majorPtr is ignored and, on success, *majorPtr
|
|
will be set to the Darwin OS release major component.
|
|
|
|
@param minorPtr May be NULL, in which case no value is return. Otherwise,
|
|
on entry, *minorPtr is ignored and, on success, *minorPtr
|
|
will be set to the Darwin OS release minor component.
|
|
|
|
@param bugPtr May be NULL, in which case no value is return. Otherwise,
|
|
on entry, *bugPtr is ignored and, on success, *bugPtr
|
|
will be set to the Darwin OS release bug fix component.
|
|
|
|
@result An errno-style error number.
|
|
*/
|
|
extern int QTMGetDarwinOSRelease(int *majorPtr, int *minorPtr, int *bugPtr);
|
|
// Get the Darwin OS release using uname. I can't use gestaltSystemVersion
|
|
// because it's part of CoreServices, and CoreServices is not available
|
|
// to 64-bit programs on Mac OS X 10.4.x.
|
|
|
|
/*!
|
|
@function QTMTaskIs64Bit
|
|
|
|
@abstract Determines whether a task is 64-bit.
|
|
|
|
@discussion Returns true if the specified task is 64-bit.
|
|
|
|
@param task Must be the name of a valid send right for the task control
|
|
port of the task; mach_task_self should work just fine.
|
|
|
|
@result Returns true if the task is 64-bit and false otherwise.
|
|
|
|
If something goes wrong, you get the default value of false.
|
|
*/
|
|
extern bool QTMTaskIs64Bit(task_t task);
|
|
|
|
/*!
|
|
@function QTMTaskIsNative
|
|
|
|
@abstract Determines whether a task is native.
|
|
|
|
@discussion Returns false if the specified task is being run using Rosetta.
|
|
|
|
@param task Must be the name of a valid send right for the task control
|
|
port of the task; mach_task_self should work just fine.
|
|
|
|
@result Returns false if the task is being run by Rosetta and false
|
|
otherwise.
|
|
|
|
If something goes wrong, you get the default value of true.
|
|
*/
|
|
extern bool QTMTaskIsNative(task_t task);
|
|
|
|
// I'm not ever going to try to explain how this works (-:
|
|
//
|
|
// Apple doesn't generally recommend, and hence doesn't officially document,
|
|
// the Mach API. If you search the web for "vm_region", you'll find our
|
|
// unofficial documentation.
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|