// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2005 University of California
//
// This 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 2.1 of the License, or (at your option) any later version.
//
// This software 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.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
/*
 *  mac_backtrace.h
 *
 */
 
/* This is a rudimentary backtrace generator for boinc project applications.  
*
* It is adapted from Apple Developer Technical Support Sample Code 
*   MoreisBetter / MoreDebugging / MoreBacktraceTest
*  The symbols it displays are not always clean.  
*
* This code handles Mac OS X 10.3.x through 10.4.2.  It may require some 
* adjustment for future OS versions; see the discussion of _sigtramp and 
* PowerPC Signal Stack Frames below.
*
*  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).
*
*  Flags in backtrace:
*    F this frame pointer is bad
*    P this PC is bad
*    S this frame is a signal handler
*
*/
 
#ifndef _BOINC_BACKTRACE_
#define _BOINC_BACKTRACE_


#ifdef __cplusplus
extern "C" {
#endif

#include <mach/mach.h>

/*	Overview
	--------
	This module implements a number of PowerPC backtrace routines. 
	All of the routines are implemented in terms of a common core. 
	The code is structured in a very generic way.  For example, if 
	you were running on a version of Mach that support inter-machine 
	messaging, it would be feasible to do a backtrace of a PowerPC 
	program from program executing a completely different instruction 
	set architecture (ISA).
	
	Backtraces are inherently processor-specific.  As Mac OS X only 
	runs on PowerPC, I haven't attempted to make this code ISA 
	independent.  Even if I did this work, there would be no way 
	to test it, and I don't believe it shipping untested code.  
	Similarly, I don't have any way to test this with 64-bit PowerPC 
	code.
	
	If you're curious about how PowerPC stack frames work, check out 
	the comments in the implementation file.  The comments in the 
	header focus on how you use these routines.
*/

// These definitions isolate the backtrace algorithm from the specifics 
// of the instruction set architecture that it's being compiled for. 

typedef unsigned long MacBTPPCInst;
typedef unsigned long MacBTPPCAddr;

// The end result of a backtrace is an array of MacBTPPCFrame 
// structures.

struct MacBTPPCFrame {
	MacBTPPCAddr	sp;		// frame pointer for this function invocation
	MacBTPPCAddr	pc;		// PC for this function invocation
	unsigned long  	flags;		// various flags, see below
};
typedef struct MacBTPPCFrame MacBTPPCFrame;

enum {
	kMacBTFrameBadMask      = 0x0001,	// this frame pointer is bad
	kMacBTPCBadMask         = 0x0002,	// this PC is bad
	kMacBTSignalHandlerMask = 0x0004	// this frame is a signal handler
};

/*	Common Parameters
	-----------------
	All of the backtrace routines accept certain common parameters.
	
	  o pc and sp -- For non "Self" routines, these parameters supply 
		the initial program counter and stack pointer for the backtrace.
		
	  o stackBottom and stackTop -- These define the extent of the stack 
		which you are tracing.  If this information isn't handy, supply 
		0 for both.  Supplying meaningful values can reduce the number 
		of bogus frames reported if the stack is corrupt.
	
	  o frameArray and frameArrayCount -- These define an array of stack 
		frames that the routines fill out.  You can supply NULL and 0 
		(respectively) if you're not interested in getting the actual 
		frame data (typically you do this to get the count of the number 
		of frames via frameCount).  The routines do not fail if this 
		buffer is exhausted.  Instead they simply return as many frames 
		as they can and continue tracing, returning an accurate value 
		for frameCount.
		
	  o frameCount -- You can use this to get back an accurate count of 
		the number of frames in the stack.  If you're not interested 
		in this information, you can pass NULL.
*/

void PrintBacktrace(void);
int MacBacktracePPCMachSelf(MacBTPPCAddr stackBottom, MacBTPPCAddr stackTop,
                                MacBTPPCFrame *frameArray, unsigned long frameArrayCount, 
                                unsigned long *frameCount, char OSMinorVersion);

#if defined(__cplusplus)
}
#endif


typedef const void *MacAToSAddr;

enum {
	kMacAToSNoSymbol = 0,
	kMacAToSDyldPubliSymbol,			// supported
	kMacAToSDyldPrivateSymbol,			// supported
	kMacAToSCFMSymbol,				// not yet implemented
	kMacAToSTracebackTableSymbol			// not yet implemented
};
typedef signed long MacAToSSymbolType;

struct MacAToSSymInfo {
	MacAToSSymbolType	symbolType;
	char			symbolName[63];
	unsigned long		symbolOffset;
};
typedef struct MacAToSSymInfo MacAToSSymInfo;

#endif      // _BOINC_BACKTRACE_