1
1

* Make the backtrace printing functionality a framework

* Copy Linux and Solaris backtrace support from util/stacktrace.c
* Added backtrace support for Mac OS X.

This commit was SVN r11023.
Этот коммит содержится в:
Brian Barrett 2006-07-27 02:56:02 +00:00
родитель 7ea33eac02
Коммит aaf31c6ade
49 изменённых файлов: 5876 добавлений и 33 удалений

1
NEWS
Просмотреть файл

@ -25,6 +25,7 @@ version 1.0.
1.2
---
- Added stacktrace support for Solaris and Mac OS X.
- Update event library to libevent-1.1a
- Fixed standards conformance issues with MPI_ERR_TRUNCATED and
setting MPI_ERROR during MPI_TEST/MPI_WAIT.

Просмотреть файл

@ -17,7 +17,7 @@ dnl
dnl $HEADER$
dnl
# OMPI_CHECK_FUNC_LIB(func, lib)
# OMPI_CHECK_FUNC_LIB(func, lib, [action-if-found], [action-if-not-found])
# ------------------------------
# Try to find function func, first with the present LIBS, second with
# lib added to LIBS. If func is found with the libraries listed in
@ -42,6 +42,6 @@ AC_DEFUN([OMPI_CHECK_FUNC_LIB],[
# see if we actually have $1. Use AC_CHECK_FUNCS so that it
# does the glibc "not implemented" check. Will use the current LIBS,
# so will check in -l$2 if we decided we needed it above
AC_CHECK_FUNCS([$1])
AC_CHECK_FUNCS([$1], $3, $4)
AS_VAR_POPDEF([ompi_var])dnl
])

Просмотреть файл

@ -570,8 +570,7 @@ AC_CHECK_HEADERS([alloca.h aio.h arpa/inet.h dirent.h \
sys/resource.h sys/select.h sys/socket.h sys/sockio.h \
stdarg.h sys/stat.h sys/statvfs.h sys/time.h sys/tree.h \
sys/types.h sys/uio.h sys/utsname.h sys/wait.h syslog.h \
time.h termios.h ulimit.h unistd.h util.h utmp.h malloc.h \
ucontext.h])
time.h termios.h ulimit.h unistd.h util.h utmp.h malloc.h])
# Needed to work around Darwin requiring sys/socket.h for
# net/if.h
@ -689,16 +688,13 @@ AC_CHECK_LIB([socket], [socket])
# Solaris has sched_yeild in -lrt, usually in libc
OMPI_CHECK_FUNC_LIB([sched_yield], [rt])
# FreeBSD has backtrace in -lexecinfo, usually in libc
OMPI_CHECK_FUNC_LIB([backtrace], [execinfo])
# IRIX has dirname in -lgen, usually in libc
OMPI_CHECK_FUNC_LIB([dirname], [gen])
# Darwin doesn't need -lm, as it's a symlink to libSystem.dylib
OMPI_CHECK_FUNC_LIB([ceil], [m])
AC_CHECK_FUNCS([asprintf snprintf vasprintf vsnprintf openpty isatty htonl ntohl htons ntohs getpwuid fork waitpid execve pipe ptsname setsid mmap mallopt tcgetpgrp printstack])
AC_CHECK_FUNCS([asprintf snprintf vasprintf vsnprintf openpty isatty htonl ntohl htons ntohs getpwuid fork waitpid execve pipe ptsname setsid mmap mallopt tcgetpgrp])
#
# Make sure we can copy va_lists (need check declared, not linkable)

41
opal/mca/backtrace/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,41 @@
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
# main library setup
noinst_LTLIBRARIES = libmca_backtrace.la
libmca_backtrace_la_SOURCES =
# header setup
nobase_opal_HEADERS =
# local files
headers = backtrace.h
libmca_backtrace_la_SOURCES += $(headers)
# Conditionally install the header files
if WANT_INSTALL_HEADERS
nobase_opal_HEADERS += $(headers)
opaldir = $(includedir)/openmpi/opal/mca/backtrace
else
opaldir = $(includedir)
endif
include base/Makefile.am
distclean-local:
rm -f base/static-components.h

75
opal/mca/backtrace/backtrace.h Обычный файл
Просмотреть файл

@ -0,0 +1,75 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OPAL_MCA_BACKTRACE_BACKTRACE_H
#define OPAL_MCA_BACKTRACE_BACKTRACE_H
#include "opal_config.h"
#include "opal/mca/mca.h"
#include "opal/mca/base/base.h"
/*
* Most of this file is just for ompi_info. There are two interface
* functions, both of which are called directly. The joy of link-time
* components.
*/
/*
* print back trace to FILE file
*
* \note some attempts made to be signal safe.
*/
void opal_backtrace_print(FILE *file);
/*
* Return back trace in buffer. buffer will be allocated by the
* backtrace component, but should be free'ed by the caller.
*
* \note Probably bad to call this from a signal handler.
*
*/
int opal_backtrace_buffer(char*** messages, int *len);
/**
* Structure for backtrace v1.0.0 components.
* Chained to MCA v1.0.0
*/
struct opal_backtrace_base_component_1_0_0_t {
/** MCA base component */
mca_base_component_t backtracec_version;
/** MCA base data */
mca_base_component_data_1_0_0_t backtracec_data;
};
/**
* Convenience typedef
*/
typedef struct opal_backtrace_base_component_1_0_0_t opal_backtrace_base_component_1_0_0_t;
/*
* Macro for use in components that are of type backtrace v1.0.0
*/
#define OPAL_BACKTRACE_BASE_VERSION_1_0_0 \
/* backtrace v1.0 is chained to MCA v1.0 */ \
MCA_BASE_VERSION_1_0_0, \
/* backtrace v1.0 */ \
"backtrace", 1, 0, 0
#endif /* OPAL_MCA_BACKTRACE_BACKTRACE_H */

23
opal/mca/backtrace/base/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,23 @@
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
headers += \
base/base.h
libmca_backtrace_la_SOURCES += \
base/backtrace_component.c

Просмотреть файл

@ -0,0 +1,74 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include "opal/constants.h"
#include "opal/util/output.h"
#include "opal/mca/mca.h"
#include "opal/mca/base/base.h"
#include "opal/mca/base/mca_base_param.h"
#include "opal/mca/backtrace/backtrace.h"
#include "opal/mca/backtrace/base/base.h"
/*
* The following file was created by configure. It contains extern
* statements and the definition of an array of pointers to each
* component's public mca_base_component_t struct.
*/
#include "opal/mca/backtrace/base/static-components.h"
/*
* Globals
*/
opal_list_t opal_backtrace_base_components_opened;
int
opal_backtrace_base_open(void)
{
/* Open up all available components */
if (OPAL_SUCCESS !=
mca_base_components_open("backtrace", 0,
mca_backtrace_base_static_components,
&opal_backtrace_base_components_opened,
true)) {
return OPAL_ERROR;
}
/* All done */
return OPAL_SUCCESS;
}
int
opal_backtrace_base_close(void)
{
/* Close all components that are still open (this should only
happen during laminfo). */
mca_base_components_close(0,
&opal_backtrace_base_components_opened,
NULL);
OBJ_DESTRUCT(&opal_backtrace_base_components_opened);
/* All done */
return OPAL_SUCCESS;
}

77
opal/mca/backtrace/base/base.h Обычный файл
Просмотреть файл

@ -0,0 +1,77 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*
*/
#ifndef OPAL_BACKTRACE_BASE_H
#define OPAL_BACKTRACE_BASE_H
#include "opal_config.h"
#include "opal/mca/backtrace/backtrace.h"
/*
* Global functions for MCA overall backtrace open and close
*/
#if defined(c_plusplus) || defined(__cplusplus)
extern "C" {
#endif
/**
* Initialize the backtrace MCA framework
*
* @retval OPAL_SUCCESS Upon success
* @retval OPAL_ERROR Upon failure
*
* This must be the first function invoked in the backtrace MCA
* framework. It initializes the backtrace MCA framework, finds
* and opens backtrace components, etc.
*
* This function is invoked during opal_init() and during the
* initialization of the special case of the laminfo command.
*
* This function fills in the internal global variable
* opal_backtrace_base_components_opened, which is a list of all
* backtrace components that were successfully opened. This
* variable should \em only be used by other backtrace base
* functions -- it is not considered a public interface member --
* and is only mentioned here for completeness.
*/
OMPI_DECLSPEC int opal_backtrace_base_open(void);
/**
* Shut down the backtrace MCA framework.
*
* @retval OPAL_SUCCESS Always
*
* This function shuts down everything in the backtrace MCA
* framework, and is called during opal_finalize() and the
* special case of the laminfo command.
*
* It must be the last function invoked on the backtrace MCA framework.
*/
OMPI_DECLSPEC int opal_backtrace_base_close(void);
extern opal_list_t opal_backtrace_base_components_opened;
#if defined(c_plusplus) || defined(__cplusplus)
}
#endif
#endif /* OPAL_BASE_BACKTRACE_H */

21
opal/mca/backtrace/configure.m4 Обычный файл
Просмотреть файл

@ -0,0 +1,21 @@
dnl -*- shell-script -*-
dnl
dnl Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
dnl University Research and Technology
dnl Corporation. All rights reserved.
dnl Copyright (c) 2004-2005 The University of Tennessee and The University
dnl of Tennessee Research Foundation. All rights
dnl reserved.
dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
dnl University of Stuttgart. All rights reserved.
dnl Copyright (c) 2004-2006 The Regents of the University of California.
dnl All rights reserved.
dnl $COPYRIGHT$
dnl
dnl Additional copyrights may follow
dnl
dnl $HEADER$
dnl
dnl we only want one :)
m4_define(MCA_backtrace_CONFIGURE_MODE, STOP_AT_FIRST)

30
opal/mca/backtrace/darwin/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,30 @@
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
AM_CPPFLAGS = -I$(srcdir)/MoreBacktrace
noinst_LTLIBRARIES = libmca_backtrace_darwin.la
libmca_backtrace_darwin_la_SOURCES = \
backtrace_darwin.c \
backtrace_darwin_component.c \
MoreBacktrace/MoreSetup.h \
MoreBacktrace/MoreDebugging/MoreAddrToSym.c \
MoreBacktrace/MoreDebugging/MoreAddrToSym.h \
MoreBacktrace/MoreDebugging/MoreBacktrace.c \
MoreBacktrace/MoreDebugging/MoreBacktrace.h

Просмотреть файл

@ -0,0 +1,339 @@
/*
File: MoreAddrToSym.c
Contains: Code for mapping addresses to their symbolic names.
Written by: DTS
Copyright: Copyright (c) 2006 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Apples
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 Computer, 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: MoreAddrToSym.c,v $
Revision 1.2 2006/01/22 22:47:13 eskimo1
Significant rewrite to account for changes in MoreBacktrace. Still not as functional as I'd like.
Revision 1.1 2003/04/04 15:02:57 eskimo1
First checked in. This code still has bugs, but I've written enough code that checking in is a good idea.
*/
/////////////////////////////////////////////////////////////////
// Our Prototypes
#include "MoreAddrToSym.h"
// Mac OS Interfaces
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <stdlib.h>
#include <mach-o/dyld.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
#include <mach-o/stab.h>
// MIB Prototypes
/////////////////////////////////////////////////////////////////
extern int MoreAToSCreate(size_t count, MoreAToSSymInfo *symbols[])
// See comments in header.
{
int err;
assert(symbols != NULL);
assert(*symbols == NULL);
err = 0;
*symbols = calloc(count, sizeof(MoreAToSSymInfo));
if (*symbols == NULL) {
err = ENOMEM;
}
assert( (err == 0) == (*symbols != NULL) );
return err;
}
extern void MoreAToSDestroy(size_t count, MoreAToSSymInfo symbols[])
// See comments in header.
{
size_t index;
if (symbols != NULL) {
for (index = 0; index < count; index++) {
free( (void *) symbols[index].symbolName );
}
free(symbols);
}
}
static int ReplaceSymbolIfBetter(
MoreAToSSymInfo * existingSymbol,
MoreAToSSymbolType symbolType,
const char * symbolName,
MoreAToSOffset symbolOffset
)
// Check to see whether the symbolic information defined by symbolType,
// symbolName, and symbolOffset is 'better' than the symbolic information
// in existingSymbol. If so, replace the old information with the new.
// In this case, 'better' is defined as being having a smaller
// symbolOffset, that is, we've found a symbol that's closer to the
// requested address.
//
// The idea behind this code is that one day I'll come up with multiple
// ways to get at symbolic information, and then I'll only keep the best
// result. However, I don't really use this functionality yet.
{
int err;
bool replace;
assert(existingSymbol != NULL);
assert(symbolType != kMoreAToSNoSymbol);
assert(symbolName != NULL);
assert( (existingSymbol->symbolType == kMoreAToSNoSymbol) == (existingSymbol->symbolName == NULL) );
err = 0;
if (existingSymbol->symbolType == kMoreAToSNoSymbol) {
replace = true;
} else {
replace = (symbolOffset < existingSymbol->symbolOffset);
}
if (replace) {
char * tmp;
tmp = strdup(symbolName);
if (tmp == NULL) {
err = ENOMEM;
} else {
free( (void *) existingSymbol->symbolName );
existingSymbol->symbolType = symbolType;
existingSymbol->symbolName = tmp;
existingSymbol->symbolOffset = symbolOffset;
}
}
return err;
}
// FindOwnerOfPC and GetFunctionName countesy of Ed Wynne. Don't ask me
// how it works, or I'll start to whimper. Actually, I have a fairly good idea
// how it works, and a fairly good idea how to fix its more serious problems,
// but I just don't have time at the moment.
static const struct mach_header *FindOwnerOfPC(unsigned int pc)
{
unsigned int count,index,offset,cmdex;
struct segment_command * seg;
struct load_command * cmd;
const struct mach_header * header;
count = _dyld_image_count();
for (index = 0;index < count;index += 1)
{
header = _dyld_get_image_header(index);
offset = _dyld_get_image_vmaddr_slide(index);
cmd = (struct load_command*)((char*)header + sizeof(struct mach_header));
for (cmdex = 0;cmdex < header->ncmds;cmdex += 1,cmd = (struct load_command*)((char*)cmd + cmd->cmdsize))
{
switch(cmd->cmd)
{
case LC_SEGMENT:
seg = (struct segment_command*)cmd;
if ((pc >= (seg->vmaddr + offset)) && (pc < (seg->vmaddr + offset + seg->vmsize)))
return header;
break;
}
}
}
return NULL;
}
static const char *GetFunctionName(unsigned int pc,unsigned int *offset, bool *publicSymbol)
{
struct segment_command *seg_linkedit = NULL;
struct segment_command *seg_text = NULL;
struct symtab_command *symtab = NULL;
struct load_command *cmd;
const struct mach_header*header;
unsigned int vm_slide,file_slide;
struct nlist *sym,*symbase;
char *strings,*name;
unsigned int base,index;
header = FindOwnerOfPC(pc);
if (header != NULL)
{
cmd = (struct load_command*)((char*)header + sizeof(struct mach_header));
for (index = 0;index < header->ncmds;index += 1,cmd = (struct load_command*)((char*)cmd + cmd->cmdsize))
{
switch(cmd->cmd)
{
case LC_SEGMENT:
if (!strcmp(((struct segment_command*)cmd)->segname,SEG_TEXT))
seg_text = (struct segment_command*)cmd;
else if (!strcmp(((struct segment_command*)cmd)->segname,SEG_LINKEDIT))
seg_linkedit = (struct segment_command*)cmd;
break;
case LC_SYMTAB:
symtab = (struct symtab_command*)cmd;
break;
}
}
if ((seg_text == NULL) || (seg_linkedit == NULL) || (symtab == NULL))
{
*offset = 0;
return NULL;
}
vm_slide = (unsigned long)header - (unsigned long)seg_text->vmaddr;
file_slide = ((unsigned long)seg_linkedit->vmaddr - (unsigned long)seg_text->vmaddr) - seg_linkedit->fileoff;
symbase = (struct nlist*)((unsigned long)header + (symtab->symoff + file_slide));
strings = (char*)((unsigned long)header + (symtab->stroff + file_slide));
// Look for a global symbol.
for (index = 0,sym = symbase;index < symtab->nsyms;index += 1,sym += 1)
{
if (sym->n_type != N_FUN)
continue;
name = sym->n_un.n_strx ? (strings + sym->n_un.n_strx) : NULL;
base = sym->n_value + vm_slide;
for (index += 1,sym += 1;index < symtab->nsyms;index += 1,sym += 1)
if (sym->n_type == N_FUN)
break;
if ((pc >= base) && (pc <= (base + sym->n_value)) && (name != NULL) && (strlen(name) > 0))
{
*offset = pc - base;
*publicSymbol = true;
return strdup(name);
}
}
// Look for a reasonably close private symbol.
for (name = NULL,base = 0xFFFFFFFF,index = 0,sym = symbase;index < symtab->nsyms;index += 1,sym += 1)
{
if ((sym->n_type & 0x0E) != 0x0E)
continue;
if ((sym->n_value + vm_slide) > pc)
continue;
if ((base != 0xFFFFFFFF) && ((pc - (sym->n_value + vm_slide)) >= (pc - base)))
continue;
name = sym->n_un.n_strx ? (strings + sym->n_un.n_strx) : NULL;
base = sym->n_value + vm_slide;
}
*offset = pc - base;
*publicSymbol = false;
return (name != NULL) ? strdup(name) : NULL;
}
*offset = 0;
return NULL;
}
extern int MoreAToSCopySymbolNamesUsingDyld(
size_t count,
MoreAToSAddr addresses[],
MoreAToSSymInfo symbols[]
)
// See comments in header.
{
int err;
size_t index;
assert(addresses != NULL);
assert(symbols != NULL);
err = 0;
for (index = 0; index < count; index++) {
const char * thisSymbol;
const char * cleanSymbol;
unsigned int thisSymbolOffset;
bool thisSymbolPublic;
MoreAToSSymbolType thisSymbolType;
thisSymbol = NULL;
if (addresses[index] != 0) { // NULL is never a useful symbol
thisSymbol = GetFunctionName( (unsigned int) addresses[index], &thisSymbolOffset, &thisSymbolPublic);
}
if (thisSymbol != NULL) {
// Mach-O symbols virtually always start with '_'. If there's one there,
// let's strip it.
if (thisSymbol[0] == '_') {
cleanSymbol = &thisSymbol[1];
} else {
cleanSymbol = thisSymbol;
}
if (thisSymbolPublic) {
thisSymbolType = kMoreAToSDyldPubliSymbol;
} else {
thisSymbolType = kMoreAToSDyldPrivateSymbol;
}
err = ReplaceSymbolIfBetter(&symbols[index], thisSymbolType, cleanSymbol, thisSymbolOffset);
}
free( (void *) thisSymbol);
if (err != 0) {
break;
}
}
return err;
}

Просмотреть файл

@ -0,0 +1,143 @@
/*
File: MoreAddrToSym.h
Contains: Code for mapping addresses to their symbolic names.
Written by: DTS
Copyright: Copyright (c) 2006 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Apples
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 Computer, 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: MoreAddrToSym.h,v $
Revision 1.2 2006/01/22 22:47:15 eskimo1
Significant rewrite to account for changes in MoreBacktrace. Still not as functional as I'd like.
Revision 1.1 2003/04/04 15:03:00 eskimo1
First checked in. This code still has bugs, but I've written enough code that checking in is a good idea.
*/
#pragma once
/////////////////////////////////////////////////////////////////
// MoreIsBetter Setup
#include "MoreSetup.h"
// Mac OS Interfaces
#include <stdint.h>
#include <stdlib.h>
/////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
// IMPORTANT:
// This code is currently broken in two ways:
//
// o If the binary has debugging symbols, you often get a debugging
// symbol rather than a real symbol. I believe this is caused by
// handling of N_FUN in the GetFunctionName routine. Furthermore,
// I believe that it did work previous but something changed in the
// Mach-O headers to break it. This warrants serious investigation.
//
// You can work around this problem by removing the debug symbols
// using:
//
// $ strip -S YourBinaryName
//
// o It doesn't handle 64-bit Mach-O binaries. This is a simple
// limitation of the code, and it should be relatively easy to fix.
//
// I intend to fix both of these problems with a future rewrite.
// Until then, I've decided to live with them.
typedef uint64_t MoreAToSAddr;
typedef uint64_t MoreAToSOffset;
enum MoreAToSSymbolType {
kMoreAToSNoSymbol = 0,
kMoreAToSDyldPubliSymbol,
kMoreAToSDyldPrivateSymbol
};
typedef enum MoreAToSSymbolType MoreAToSSymbolType;
struct MoreAToSSymInfo {
MoreAToSSymbolType symbolType;
const char * symbolName;
MoreAToSOffset symbolOffset;
};
typedef struct MoreAToSSymInfo MoreAToSSymInfo;
extern int MoreAToSCreate(size_t count, MoreAToSSymInfo *symbols[]);
// Creates a blank MoreAToSSymInfo array with count entries.
// You must dispose of it using MoreAToSDestroy.
//
// symbols must not be NULL
// *symbols must be NULL
// Returns 0 on success, an errno-style error code otherwise
// On success, *symbols will not be NULL
// On error, *symbols will be NULL
extern void MoreAToSDestroy(size_t count, MoreAToSSymInfo symbols[]);
// Destroys a MoreAToSDestroy array (blank or filled in) of
// count entries.
extern int MoreAToSCopySymbolNamesUsingDyld(
size_t count,
MoreAToSAddr addresses[],
MoreAToSSymInfo symbols[]
);
// Given count values in the addresses array, works out the symbolic
// information for those values and returns it in the symbols array.
//
// Returns 0 on success, an errno-style error code otherwise
//
// Note that not being able to map an address to a symbol is not
// considered an error. Rather, you get NULL back in the symbolName
// field of the corresponding symbols array element.
#ifdef __cplusplus
}
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,274 @@
/*
File: MoreBacktrace.h
Contains: Code for generating backtraces.
Written by: DTS
Copyright: Copyright (c) 2006 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Apples
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 Computer, 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: MoreBacktrace.h,v $
Revision 1.4 2006/01/22 22:46:48 eskimo1
Complete rewrite to account for architecture independence.
Revision 1.3 2003/04/09 22:48:15 eskimo1
Added comments.
Revision 1.2 2003/04/09 21:58:18 eskimo1
Removed the "uncertain PC" flag. I may need to bring it back later, but for now I never use it so there's no point declaring it.
Revision 1.1 2003/04/04 15:03:08 eskimo1
First checked in. This code still has bugs, but I've written enough code that checking in is a good idea.
*/
#pragma once
/////////////////////////////////////////////////////////////////
// MoreIsBetter Setup
#include "MoreSetup.h"
// Mac OS Interfaces
// 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
#include <stdint.h>
/////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
/////////////////////////////////////////////////////////////////
#if TARGET_RT_MAC_CFM
#error MoreBacktrace no longer supports CFM builds.
#endif
/////////////////////////////////////////////////////////////////
/* Overview
--------
This module implements a number of 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).
IMPORTANT:
The current code does not support cross-architecture backtraces
because of technical limitations (specifically, I haven't had
time to implement cross-architecture symbol translation, which
is required for cross-architecture backtraces to work properly;
see the comments for InitSigTrampAddress in the implementation
file for the details).
Backtraces are inherently processor-specific. Internal to this
module is a ISA later than adapts the backtrace for various ISA.
Currently it supports PowerPC (32-bit), PowerPC (64-bit), and
Intel (32-bit).
If you're curious about how stack frames work for each ISA, check
out the comments in the implementation file. The comments in the
header focus on how you use these routines.
*/
/* Changes Since Previous Version
------------------------------
If you used the previous version of this code, please note the
following changes:
o Everything has changed (-:
I completely rewrote this code to support multiple architectures.
By including support for PowerPC (64-bit), I was forced to
eliminate my dependencies on CoreServices (which isn't available
to PowerPC (64-bit) on Mac OS X 10.4.x), which means now I depend
solely on the System framework. Also, because I had to support
Intel, which requires Mach-O, I decided to drop support for CFM.
My theory is that anyone who wants to adopt the new version of this
module is doing so because they're porting to Intel, and those folks
have to leave their CFM build behind.
The good news is that the new implementation is very similar
in spirit to the old, and it should be very easy for you to
adopt the new code.
*/
// Within this module, I treat all addresses as 64-bit. That way
// the code doesn't change for 64-bit and 32-bit architectures.
//
// Note:
// I could have made this type scale with the current pointer size,
// but my eventual goal is to support cross-architecture backtraces,
// which means I wanted a size that's at least as big as the 'largest'
// architecture I support.
typedef uint64_t MoreBTAddr;
// The following flags provide information about a specific frame in
// a backtrace.
//
// IMPORTANT:
// kMoreBTFrameBadMask is set for the last frame in the backtrace
// (where we've run off the end of the stack), but it can also be set
// for intermediate frames (where we've detected a frameless leaf
// routine, either at the top of the stack or as part of crossing
// a signal frame).
typedef int MoreBTFlags;
enum {
kMoreBTFrameBadMask = 0x0001, // this frame pointer is bad
kMoreBTPCBadMask = 0x0002, // this PC is bad
kMoreBTSignalHandlerMask = 0x0004 // this frame is a signal handler
};
// The end result of a backtrace is an array of MoreBTFrame
// structures describing a particular frame in the backtrace.
//
// Note:
// The PC points to the code that's using the frame. It is not
// the return address for that code. On architectures where the
// frame holds the return address (Intel, but not PowerPC), I do
// the appropriate corrections.
struct MoreBTFrame {
MoreBTAddr pc; // PC for this function invocation
MoreBTAddr fp; // frame pointer for this function invocation
MoreBTFlags flags; // various flags, see above
};
typedef struct MoreBTFrame MoreBTFrame;
/* Common Parameters
-----------------
All of the backtrace routines accept certain common parameters.
o function result -- This is an errno-style error code.
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 frameCountPtr -- 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.
IMPORTANT:
Because of the above, on return, *frameCountPtr can be larger than
frameArrayCount.
The following assertions apply to these common parameters.
o On entry, stackBottom and stackTop must both be zero, or stackBottom
must be strictly less than stackTop.
o On entry, if frameArrayCount is not zero, frameArray must be not NULL.
o On entry, frameCountPtr must not be NULL.
o On return, *frameCountPtr will be the number of frames that were
found. On success, this is likely to be a meaningful number. On
error, this just indicates how far we got.
o On return, if frameArrayCount is not NULL, frame data has been placed
into the frame array. The number of valid entries is
min(frameArray, *frameArrayCount).
*/
extern int MoreBacktraceMachSelf(
MoreBTAddr stackBottom,
MoreBTAddr stackTop,
MoreBTFrame * frameArray,
size_t frameArrayCount,
size_t * frameCountPtr
);
// Does a backtrace of the current thread. All of the parameters
// are described by the "Common Parameters" section above.
extern int MoreBacktraceMachThread(
task_t task,
thread_t thread,
MoreBTAddr stackBottom,
MoreBTAddr stackTop,
MoreBTFrame * frameArray,
size_t frameArrayCount,
size_t * frameCountPtr
);
// Does a backtrace of a particular thread within a particular tasks.
// The common parameters (stackBottom and later) are described by the
// "Common Parameters" section above. The task parameter must a
// task control port; for a thread in the current task, use
// mach_task_self to get this value. The thread parameter is the thread
// to sample. It's generally inappropriate to use mach_thread_self
// (call MoreBacktraceMachSelf instead), but it does work.
//
// On entry, task must not be MACH_PORT_NULL.
// On entry, thread must not be MACH_PORT_NULL.
#ifdef __cplusplus
}
#endif

Двоичные данные
opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreBacktraceTest/._MainWindow.nib сгенерированный Обычный файл

Двоичный файл не отображается.

Двоичные данные
opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreBacktraceTest/._main.nib сгенерированный Обычный файл

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>MoreBacktraceTest</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.apple.dts.MoreIsBetter.MoreBacktraceTest</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>MoreBacktraceTest</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.1</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,4 @@
{
IBClasses = ();
IBVersion = 1;
}

Просмотреть файл

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>69 10 356 240 0 0 1280 832 </string>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBOpenObjects</key>
<array>
<integer>166</integer>
</array>
<key>IBSystem Version</key>
<string>8G32</string>
<key>targetFramework</key>
<string>IBCarbonFramework</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,81 @@
<?xml version="1.0" standalone="yes"?>
<object class="NSIBObjectData">
<string name="targetFramework">IBCarbonFramework</string>
<object name="rootObject" class="NSCustomObject" id="1">
<string name="customClass">NSApplication</string>
</object>
<array count="9" name="allObjects">
<object class="IBCarbonWindow" id="166">
<string name="windowRect">51 8 649 747 </string>
<string name="title">MoreBacktraceTest</string>
<object name="rootControl" class="IBCarbonRootControl" id="167">
<string name="bounds">0 0 598 739 </string>
<array count="7" name="subviews">
<object class="IBCarbonButton" id="199">
<string name="bounds">20 20 40 245 </string>
<string name="title">MoreBacktraceMachSelf</string>
<ostype name="command">btMS</ostype>
</object>
<object class="IBCarbonButton" id="202">
<string name="bounds">20 251 40 488 </string>
<string name="title">MoreBacktraceMachThread</string>
<ostype name="command">btMT</ostype>
</object>
<object class="IBCarbonEditText" id="203">
<string name="bounds">23 536 39 613 </string>
<ostype name="controlSignature">PIDT</ostype>
</object>
<object class="IBCarbonStaticText" id="204">
<string name="bounds">22 494 38 525 </string>
<string name="title">PID:</string>
</object>
<object class="IBCarbonButton" id="205">
<string name="bounds">52 257 72 482 </string>
<string name="title">Signal Test</string>
<ostype name="command">btST</ostype>
</object>
<object class="IBCarbonButton" id="208">
<string name="bounds">52 20 72 245 </string>
<string name="title">Stack Smash Test</string>
<ostype name="command">btSS</ostype>
</object>
<object class="IBCarbonEditText" id="209">
<string name="bounds">95 23 575 716 </string>
<ostype name="controlSignature">ETXT</ostype>
</object>
</array>
</object>
<boolean name="hasCloseBox">FALSE</boolean>
<boolean name="hasHorizontalZoom">FALSE</boolean>
<boolean name="isResizable">FALSE</boolean>
<boolean name="hasVerticalZoom">FALSE</boolean>
<int name="windowPosition">1</int>
</object>
<reference idRef="167"/>
<reference idRef="199"/>
<reference idRef="202"/>
<reference idRef="203"/>
<reference idRef="204"/>
<reference idRef="205"/>
<reference idRef="208"/>
<reference idRef="209"/>
</array>
<array count="9" name="allParents">
<reference idRef="1"/>
<reference idRef="166"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
</array>
<dictionary count="2" name="nameTable">
<string>Files Owner</string>
<reference idRef="1"/>
<string>MainWindow</string>
<reference idRef="166"/>
</dictionary>
<unsigned_int name="nextObjectID">248</unsigned_int>
</object>

Просмотреть файл

@ -0,0 +1,573 @@
/*
File: MoreBacktraceTest.c
Contains: A simple program to test MoreBacktrace.
Written by: DTS
Copyright: Copyright (c) 2006 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Apples
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 Computer, 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):
*/
/////////////////////////////////////////////////////////////////
#include "MoreSetup.h"
// System prototypes
#include <Carbon/Carbon.h>
// Our interfaces
#include "MoreBacktraceTestCommon.h"
/////////////////////////////////////////////////////////////////
#pragma mark ***** Utilities
static OSStatus GetControlByIDQ(WindowRef inWindow, OSType signature, SInt32 id, ControlRef *outControl)
// A simple wrapper around GetControlByID.
{
ControlID theID;
theID.signature = signature;
theID.id = id;
return GetControlByID(inWindow, &theID, outControl);
}
static OSStatus FindFinderProcess(ProcessSerialNumber *psnPtr)
// Find the ProcessSerialNumber of the Finder process.
{
OSStatus err;
ProcessInfoRec info;
Boolean found;
psnPtr->lowLongOfPSN = kNoProcess;
psnPtr->highLongOfPSN = kNoProcess;
found = false;
do {
err = GetNextProcess(psnPtr);
if (err == noErr) {
memset(&info, 0, sizeof(info));
err = GetProcessInformation(psnPtr, &info);
if (err == noErr) {
found = (info.processSignature == 'MACS');
}
}
} while ( (err == noErr) && ! found );
return err;
}
/////////////////////////////////////////////////////////////////
#pragma mark ***** Compile-Time Parameters
// We hard-code our output to Monaco 10. This is bad programming,
// but it suffices for a simple hack like this.
static const UInt8 kOutputFont[] = "\pMonaco";
static const SInt16 kOutputSize = 10;
// The main text field will display about 70 frames, so that's all that
// we ask for. This is more than enough for our tests.
enum {
kFrameCount = 70
};
/////////////////////////////////////////////////////////////////
#pragma mark ***** GUI Infrastructure
static void DoAbout(void)
// Displays the about box.
{
SInt16 junkHit;
(void) StandardAlert(kAlertPlainAlert, "\pMoreBacktraceTest", "\pA simple program to test MoreBacktrace.\r\rDTS\r\rй 2006 Apple Computer, Inc.", NULL, &junkHit);
}
static void DisplayError(OSStatus errNum)
{
OSStatus junk;
Str255 errStr;
SInt16 junkHit;
if ( (errNum != noErr) && (errNum != userCanceledErr) ) {
NumToString(errNum, errStr);
junk = StandardAlert(kAlertStopAlert, "\pError.", errStr, NULL, &junkHit);
assert(junk == noErr);
}
}
static ControlRef gOutputText = NULL;
static ControlRef gPIDText = NULL;
static OSStatus SetOutputText(CFStringRef newText)
// Put newText into the output edit text control.
// We use an edit text control because it's
// a) easy, b) handles multiple lines of text, and
// c) allows the user to copy the results.
{
OSStatus err;
assert(newText != NULL);
err = SetControlData(gOutputText, kControlEntireControl, kControlEditTextCFStringTag, sizeof(newText), &newText);
Draw1Control(gOutputText);
return err;
}
static void ClearOutput(void)
// Clear the output text.
{
OSStatus junk;
junk = SetOutputText(CFSTR(""));
assert(junk == noErr);
}
static OSStatus OutputFrames(char *bt)
// Output a textual description of frameCount frames from frameArray
// into the output text control. Actually generating the text from
// the frame array is handled by the common test code; all we have
// to do here is reflow the text into two columns so it fits in
// our text field.
{
OSStatus err;
Boolean removedOne;
size_t row;
size_t col;
CFStringRef btStr;
CFArrayRef frameStrings;
size_t frameCount;
size_t frameIndex;
CFMutableStringRef result;
btStr = NULL;
frameStrings = NULL;
result = NULL;
// Remove any trailing newlines.
removedOne = false;
do {
size_t len;
len = strlen(bt);
if (len > 0 && bt[len] == '\n') {
bt[len] = 0;
removedOne = true;
}
} while ( removedOne );
// Break the string up into lines.
err = noErr;
btStr = CFStringCreateWithCString(NULL, bt, kCFStringEncodingUTF8);
if (btStr == NULL) {
err = coreFoundationUnknownErr;
}
if (err == noErr) {
frameStrings = CFStringCreateArrayBySeparatingStrings(NULL, btStr, CFSTR("\n"));
if (frameStrings == NULL) {
err = coreFoundationUnknownErr;
}
assert(frameStrings != NULL);
}
// Count the frames and then place it into the output text field.
if (err == noErr) {
frameCount = (size_t) CFArrayGetCount(frameStrings);
result = CFStringCreateMutable(NULL, 0);
if (result == NULL) {
err = coreFoundationUnknownErr;
}
}
if (err == noErr) {
if ( frameCount > (kFrameCount / 2) ) {
// We need two columns, so reflow. Nasty.
for (row = 0; row < (kFrameCount / 2); row++) {
for (col = 0; col < 2; col++) {
frameIndex = (col * (kFrameCount / 2)) + row;
if (frameIndex < frameCount) {
CFStringRef frameStr;
CFStringRef frameStrTrimmed;
CFStringRef columnPad;
columnPad = NULL;
frameStrTrimmed = NULL;
frameStr = CFArrayGetValueAtIndex(frameStrings, frameIndex);
assert(frameStr != NULL);
if ( CFStringGetLength(frameStr) > 56 ) {
frameStrTrimmed = CFStringCreateWithSubstring(NULL, frameStr, CFRangeMake(0, 56));
columnPad = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8);
} else {
frameStrTrimmed = CFRetain(frameStr);
if (col == 0) {
columnPad = CFStringCreateWithFormat(NULL, NULL, CFSTR("%*.*s"), 56 - CFStringGetLength(frameStr), 56 - CFStringGetLength(frameStr), "");
} else {
columnPad = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8);
}
}
assert(frameStrTrimmed != NULL);
assert(columnPad != NULL);
if ( (frameStrTrimmed != NULL) && (columnPad != NULL) ) {
CFStringAppendFormat(result, NULL, CFSTR("%@%@"), frameStrTrimmed, columnPad);
if (col == 0) {
CFStringAppend(result, CFSTR(" "));
}
}
if (columnPad != NULL) {
CFRelease(columnPad);
}
if (frameStrTrimmed != NULL) {
CFRelease(frameStrTrimmed);
}
}
}
CFStringAppend(result, CFSTR("\r"));
}
} else {
// We can get away with a single column.
for (frameIndex = 0; frameIndex < frameCount; frameIndex++) {
CFStringAppendFormat(result, NULL, CFSTR("%@\r"), CFArrayGetValueAtIndex(frameStrings, frameIndex));
}
}
}
// Put the string into the control.
if (err == noErr) {
err = SetOutputText(result);
}
// Clean up.
if (btStr != NULL) {
CFRelease(btStr);
}
if (frameStrings != NULL) {
CFRelease(frameStrings);
}
if (result != NULL) {
CFRelease(result);
}
return err;
}
/////////////////////////////////////////////////////////////////
#pragma mark ***** Test Handlers
static void GUITestMoreBacktraceMachSelf(void)
// Run in response to a click of the "MoreBacktraceMachSelf"
// button. It does the test and displays the result.
{
OSStatus err;
char * bt;
ClearOutput();
bt = NULL;
err = TestMoreBacktraceMachSelf(&bt);
if (err == noErr) {
err = OutputFrames(bt);
}
DisplayError(err);
free(bt);
}
static void GUITestMoreBacktraceMachThread(void)
// Run in response to a click of the "MoreBacktraceMachThread"
// button. It does the test and displays the result. It gets
// the target PID from the "PID" field.
{
OSStatus err;
CFStringRef pidStr;
pid_t pid;
char * bt;
ClearOutput();
bt = NULL;
pidStr = NULL;
// Get the PID of the process to sample from the
// gPIDText edit text control and convert that to
// the Mach task control port.
err = GetControlData(gPIDText, kControlEntireControl, kControlEditTextCFStringTag, sizeof(pidStr), &pidStr, NULL);
if (err == noErr) {
pid = (pid_t) CFStringGetIntValue(pidStr);
}
if (err == noErr) {
err = TestMoreBacktraceMachThread(pid, &bt);
}
if (err == noErr) {
err = OutputFrames(bt);
}
DisplayError(err);
// Clean up.
free(bt);
if (pidStr != NULL) {
CFRelease(pidStr);
}
}
static void GUITestSignalBacktrace(void)
// Run in response to a click of the "Signal Test"
// button. It does the test and displays the result.
{
OSStatus err;
char * bt;
bt = NULL;
ClearOutput();
// Call a routine that sends a signal to us.
err = TestMoreBacktraceMachSelfSignal(false, &bt);
if (err == noErr) {
err = OutputFrames(bt);
}
DisplayError(err);
free(bt);
}
static void GUITestStackSmash(void)
// Run in response to a click of the "Stack Smash Test"
// button. It does the test and displays the result.
{
OSStatus err;
char * bt;
ClearOutput();
bt = NULL;
err = TestMoreBacktraceMachThreadStackSmash(&bt);
if (err == noErr) {
err = OutputFrames(bt);
}
DisplayError(err);
free(bt);
}
/////////////////////////////////////////////////////////////////
#pragma mark ***** Boilerplate Application Stuff
static EventHandlerUPP gApplicationEventHandlerUPP; // -> ApplicationEventHandler
static const EventTypeSpec kApplicationEvents[] = { {kEventClassCommand, kEventCommandProcess} };
static pascal OSStatus ApplicationEventHandler(EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void *inUserData)
// Dispatches HICommands to their implementations.
{
OSStatus err;
HICommand command;
#pragma unused(inHandlerCallRef)
#pragma unused(inUserData)
assert( GetEventClass(inEvent) == kEventClassCommand );
assert( GetEventKind(inEvent) == kEventCommandProcess);
err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command);
if (err == noErr) {
switch (command.commandID) {
case kHICommandAbout:
DoAbout();
break;
case 'btMS':
GUITestMoreBacktraceMachSelf();
break;
case 'btMT':
GUITestMoreBacktraceMachThread();
break;
case 'btST':
GUITestSignalBacktrace();
break;
case 'btSS':
GUITestStackSmash();
break;
default:
err = eventNotHandledErr;
break;
}
}
return err;
}
int main(int argc, char* argv[])
{
OSStatus err;
IBNibRef nibRef;
WindowRef window;
#pragma unused(argc)
#pragma unused(argv)
// DebugStr("\pmain");
nibRef = NULL;
// Create menu bar from NIB.
err = CreateNibReference(CFSTR("main"), &nibRef);
if (err == noErr) {
err = SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
}
if (nibRef != NULL) {
DisposeNibReference(nibRef);
nibRef = NULL;
}
// Create main window from NIB.
if (err == noErr) {
err = CreateNibReference(CFSTR("MainWindow"), &nibRef);
}
if (err == noErr) {
err = CreateWindowFromNib(nibRef, CFSTR("MainWindow"), &window);
}
if (nibRef != NULL) {
DisposeNibReference(nibRef);
nibRef = NULL;
}
// Install our HICommand handler.
if (err == noErr) {
gApplicationEventHandlerUPP = NewEventHandlerUPP(ApplicationEventHandler);
assert(gApplicationEventHandlerUPP != NULL);
err = InstallApplicationEventHandler(gApplicationEventHandlerUPP,
GetEventTypeCount(kApplicationEvents),
kApplicationEvents, NULL, NULL);
}
// Get the output static text control and set it to Monaco 9.
if (err == noErr) {
err = GetControlByIDQ(window, 'ETXT', 0, &gOutputText);
}
if (err == noErr) {
ControlFontStyleRec styleRec;
SInt16 monacoFontNum;
GetFNum(kOutputFont, &monacoFontNum);
styleRec.flags = kControlUseFontMask | kControlUseSizeMask;
styleRec.font = monacoFontNum;
styleRec.size = kOutputSize;
err = SetControlData(gOutputText, kControlEntireControl, kControlStaticTextStyleTag,
sizeof(styleRec), &styleRec);
}
// Get the PID edit text field and initialise it to the Finder's PID.
if (err == noErr) {
err = GetControlByIDQ(window, 'PIDT', 0, &gPIDText);
}
if (err == noErr) {
ProcessSerialNumber finderPSN;
pid_t finderPID;
CFStringRef finderPIDStr;
finderPIDStr = NULL;
err = FindFinderProcess(&finderPSN);
if (err == noErr) {
err = GetProcessPID(&finderPSN, &finderPID);
}
if (err == noErr) {
finderPIDStr = CFStringCreateWithFormat(NULL, NULL, CFSTR("%ld"), (long) finderPID);
if (finderPIDStr == NULL) {
err = coreFoundationUnknownErr;
}
}
if (err == noErr) {
err = SetControlData(gPIDText, kControlEntireControl, kControlEditTextCFStringTag, sizeof(finderPIDStr), &finderPIDStr);
}
if (finderPIDStr) {
CFRelease(finderPIDStr);
}
// I don't want to refuse to start up just because this code failed,
// so swallow any error.
assert(err == noErr);
err = noErr;
}
if (err == noErr) {
// The window was created hidden so show it.
ShowWindow( window );
// Call the event loop
RunApplicationEventLoop();
}
return (err == noErr) ? EXIT_SUCCESS : EXIT_FAILURE;
}

Просмотреть файл

@ -0,0 +1,424 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXBuildFile section */
E42C50FB097D62FC00D1B30B /* MoreBacktrace.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D9D9CA043A170400002802 /* MoreBacktrace.h */; };
E42C50FC097D62FC00D1B30B /* MoreSetup.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D9D9CD043A171200002802 /* MoreSetup.h */; };
E42C5104097D62FC00D1B30B /* MoreAddrToSym.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E6C079043DD1A000002802 /* MoreAddrToSym.h */; };
E42C5108097D62FC00D1B30B /* main.nib in Resources */ = {isa = PBXBuildFile; fileRef = E4D9D9D3043AEDB800002802 /* main.nib */; };
E42C5109097D62FC00D1B30B /* MainWindow.nib in Resources */ = {isa = PBXBuildFile; fileRef = E4A2067F0444ADE300002802 /* MainWindow.nib */; };
E42C510B097D62FC00D1B30B /* MoreBacktrace.c in Sources */ = {isa = PBXBuildFile; fileRef = E4D9D9C9043A170400002802 /* MoreBacktrace.c */; };
E42C510C097D62FC00D1B30B /* MoreBacktraceTest.c in Sources */ = {isa = PBXBuildFile; fileRef = E4D9D9CF043A172300002802 /* MoreBacktraceTest.c */; };
E42C5114097D62FC00D1B30B /* MoreAddrToSym.c in Sources */ = {isa = PBXBuildFile; fileRef = E4E6C078043DD1A000002802 /* MoreAddrToSym.c */; };
E42C5117097D62FC00D1B30B /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; };
E42C5285097D728200D1B30B /* MoreBacktraceTestTool.c in Sources */ = {isa = PBXBuildFile; fileRef = E42C5163097D6D7400D1B30B /* MoreBacktraceTestTool.c */; };
E4CA23DB0982F7690043C210 /* MoreBacktrace.c in Sources */ = {isa = PBXBuildFile; fileRef = E4D9D9C9043A170400002802 /* MoreBacktrace.c */; };
E4CA24050982FE650043C210 /* MoreBacktraceTestCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = E4CA24040982FE650043C210 /* MoreBacktraceTestCommon.c */; };
E4CA24060982FE650043C210 /* MoreBacktraceTestCommon.c in Sources */ = {isa = PBXBuildFile; fileRef = E4CA24040982FE650043C210 /* MoreBacktraceTestCommon.c */; };
E4CA24080982FE6C0043C210 /* MoreBacktraceTestCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = E4CA24070982FE6C0043C210 /* MoreBacktraceTestCommon.h */; };
E4CA25F709831B6D0043C210 /* MoreAddrToSym.c in Sources */ = {isa = PBXBuildFile; fileRef = E4E6C078043DD1A000002802 /* MoreAddrToSym.c */; };
/* End PBXBuildFile section */
/* Begin PBXBuildStyle section */
4A9504C5FFE6A39111CA0CBA /* Development */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
OPTIMIZATION_CFLAGS = "-O0";
ZERO_LINK = YES;
};
name = Development;
};
4A9504C6FFE6A39111CA0CBA /* Deployment */ = {
isa = PBXBuildStyle;
buildSettings = {
COPY_PHASE_STRIP = YES;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
ZERO_LINK = NO;
};
name = Deployment;
};
/* End PBXBuildStyle section */
/* Begin PBXFileReference section */
20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
E42C511D097D62FC00D1B30B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
E42C511E097D62FC00D1B30B /* MoreBacktraceTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MoreBacktraceTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
E42C5163097D6D7400D1B30B /* MoreBacktraceTestTool.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = MoreBacktraceTestTool.c; sourceTree = "<group>"; };
E42C5172097D6E1D00D1B30B /* MoreBacktraceTestTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MoreBacktraceTestTool; sourceTree = BUILT_PRODUCTS_DIR; };
E4A2067F0444ADE300002802 /* MainWindow.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = MainWindow.nib; sourceTree = "<group>"; };
E4CA24040982FE650043C210 /* MoreBacktraceTestCommon.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = MoreBacktraceTestCommon.c; sourceTree = "<group>"; };
E4CA24070982FE6C0043C210 /* MoreBacktraceTestCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MoreBacktraceTestCommon.h; sourceTree = "<group>"; };
E4D9D9C9043A170400002802 /* MoreBacktrace.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = MoreBacktrace.c; path = ../MoreBacktrace.c; sourceTree = SOURCE_ROOT; };
E4D9D9CA043A170400002802 /* MoreBacktrace.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MoreBacktrace.h; path = ../MoreBacktrace.h; sourceTree = SOURCE_ROOT; };
E4D9D9CD043A171200002802 /* MoreSetup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MoreSetup.h; path = ../../MoreSetup.h; sourceTree = SOURCE_ROOT; };
E4D9D9CF043A172300002802 /* MoreBacktraceTest.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = MoreBacktraceTest.c; sourceTree = "<group>"; };
E4D9D9D3043AEDB800002802 /* main.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = main.nib; sourceTree = "<group>"; };
E4E6C078043DD1A000002802 /* MoreAddrToSym.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = MoreAddrToSym.c; path = ../MoreAddrToSym.c; sourceTree = SOURCE_ROOT; };
E4E6C079043DD1A000002802 /* MoreAddrToSym.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = MoreAddrToSym.h; path = ../MoreAddrToSym.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E42C5116097D62FC00D1B30B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E42C5117097D62FC00D1B30B /* Carbon.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E42C5170097D6E1D00D1B30B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
195DF8CFFE9D517E11CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
E42C511E097D62FC00D1B30B /* MoreBacktraceTest.app */,
E42C5172097D6E1D00D1B30B /* MoreBacktraceTestTool */,
);
name = Products;
sourceTree = "<group>";
};
20286C29FDCF999611CA2CEA /* MoreBacktraceTest */ = {
isa = PBXGroup;
children = (
E4DA7D6B09843FE2000630D1 /* Test Code */,
20286C2AFDCF999611CA2CEA /* Reusable Code */,
195DF8CFFE9D517E11CA2CBB /* Products */,
E42C511D097D62FC00D1B30B /* Info.plist */,
);
name = MoreBacktraceTest;
sourceTree = "<group>";
};
20286C2AFDCF999611CA2CEA /* Reusable Code */ = {
isa = PBXGroup;
children = (
E4E6C079043DD1A000002802 /* MoreAddrToSym.h */,
E4E6C078043DD1A000002802 /* MoreAddrToSym.c */,
E4D9D9CA043A170400002802 /* MoreBacktrace.h */,
E4D9D9C9043A170400002802 /* MoreBacktrace.c */,
E4D9D9CD043A171200002802 /* MoreSetup.h */,
);
name = "Reusable Code";
sourceTree = "<group>";
};
E4DA7D6B09843FE2000630D1 /* Test Code */ = {
isa = PBXGroup;
children = (
E42C5163097D6D7400D1B30B /* MoreBacktraceTestTool.c */,
E4D9D9CF043A172300002802 /* MoreBacktraceTest.c */,
E4CA24070982FE6C0043C210 /* MoreBacktraceTestCommon.h */,
E4CA24040982FE650043C210 /* MoreBacktraceTestCommon.c */,
E4D9D9D3043AEDB800002802 /* main.nib */,
E4A2067F0444ADE300002802 /* MainWindow.nib */,
20286C33FDCF999611CA2CEA /* Carbon.framework */,
);
name = "Test Code";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
E42C50FA097D62FC00D1B30B /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
E42C50FB097D62FC00D1B30B /* MoreBacktrace.h in Headers */,
E42C50FC097D62FC00D1B30B /* MoreSetup.h in Headers */,
E42C5104097D62FC00D1B30B /* MoreAddrToSym.h in Headers */,
E4CA24080982FE6C0043C210 /* MoreBacktraceTestCommon.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
E42C50F9097D62FC00D1B30B /* App */ = {
isa = PBXNativeTarget;
buildConfigurationList = E42C5119097D62FC00D1B30B /* Build configuration list for PBXNativeTarget "App" */;
buildPhases = (
E42C50FA097D62FC00D1B30B /* Headers */,
E42C5107097D62FC00D1B30B /* Resources */,
E42C510A097D62FC00D1B30B /* Sources */,
E42C5116097D62FC00D1B30B /* Frameworks */,
E42C5118097D62FC00D1B30B /* Rez */,
);
buildRules = (
);
buildSettings = {
FRAMEWORK_SEARCH_PATHS = "";
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = "$(HOME)/Applications";
LIBRARY_SEARCH_PATHS = "";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = MoreBacktraceTest;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
WRAPPER_EXTENSION = app;
};
dependencies = (
);
name = App;
productInstallPath = "$(HOME)/Applications";
productName = MoreBacktraceTest;
productReference = E42C511E097D62FC00D1B30B /* MoreBacktraceTest.app */;
productType = "com.apple.product-type.application";
};
E42C5171097D6E1D00D1B30B /* Tool */ = {
isa = PBXNativeTarget;
buildConfigurationList = E42C5179097D6E2E00D1B30B /* Build configuration list for PBXNativeTarget "Tool" */;
buildPhases = (
E42C516F097D6E1D00D1B30B /* Sources */,
E42C5170097D6E1D00D1B30B /* Frameworks */,
);
buildRules = (
);
buildSettings = {
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
INSTALL_PATH = "$(HOME)/bin";
PREBINDING = NO;
PRODUCT_NAME = MoreBacktraceTestTool;
ZERO_LINK = YES;
};
dependencies = (
);
name = Tool;
productName = MoreBacktraceTestTool;
productReference = E42C5172097D6E1D00D1B30B /* MoreBacktraceTestTool */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
20286C28FDCF999611CA2CEA /* Project object */ = {
isa = PBXProject;
buildConfigurationList = E42C5087097D61DA00D1B30B /* Build configuration list for PBXProject "MoreBacktraceTest" */;
buildSettings = {
};
buildStyles = (
4A9504C5FFE6A39111CA0CBA /* Development */,
4A9504C6FFE6A39111CA0CBA /* Deployment */,
);
hasScannedForEncodings = 1;
mainGroup = 20286C29FDCF999611CA2CEA /* MoreBacktraceTest */;
projectDirPath = "";
targets = (
E42C50F9097D62FC00D1B30B /* App */,
E42C5171097D6E1D00D1B30B /* Tool */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
E42C5107097D62FC00D1B30B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E42C5108097D62FC00D1B30B /* main.nib in Resources */,
E42C5109097D62FC00D1B30B /* MainWindow.nib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXRezBuildPhase section */
E42C5118097D62FC00D1B30B /* Rez */ = {
isa = PBXRezBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXRezBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
E42C510A097D62FC00D1B30B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E42C510B097D62FC00D1B30B /* MoreBacktrace.c in Sources */,
E42C510C097D62FC00D1B30B /* MoreBacktraceTest.c in Sources */,
E42C5114097D62FC00D1B30B /* MoreAddrToSym.c in Sources */,
E4CA24050982FE650043C210 /* MoreBacktraceTestCommon.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E42C516F097D6E1D00D1B30B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E42C5285097D728200D1B30B /* MoreBacktraceTestTool.c in Sources */,
E4CA23DB0982F7690043C210 /* MoreBacktrace.c in Sources */,
E4CA24060982FE650043C210 /* MoreBacktraceTestCommon.c in Sources */,
E4CA25F709831B6D0043C210 /* MoreAddrToSym.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
E42C5088097D61DA00D1B30B /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
DEPLOYMENT_POSTPROCESSING = NO;
GCC_DYNAMIC_NO_PIC = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.1;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
WARNING_CFLAGS = "-Wall";
ZERO_LINK = NO;
};
name = Development;
};
E42C5089097D61DA00D1B30B /* Deployment */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = YES;
DEPLOYMENT_POSTPROCESSING = YES;
GCC_DYNAMIC_NO_PIC = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = s;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.1;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
WARNING_CFLAGS = "-Wall";
ZERO_LINK = NO;
};
name = Deployment;
};
E42C511A097D62FC00D1B30B /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = (
ppc,
i386,
);
INFOPLIST_FILE = Info.plist;
PRODUCT_NAME = MoreBacktraceTest;
WRAPPER_EXTENSION = app;
};
name = Development;
};
E42C511B097D62FC00D1B30B /* Deployment */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = (
ppc,
i386,
);
INFOPLIST_FILE = Info.plist;
PRODUCT_NAME = MoreBacktraceTest;
WRAPPER_EXTENSION = app;
};
name = Deployment;
};
E42C517A097D6E2E00D1B30B /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = (
ppc,
ppc64,
i386,
);
BUILD_VARIANTS = normal;
INSTALL_PATH = "$(HOME)/bin";
OTHER_CFLAGS = "-fasm-blocks";
OTHER_LDFLAGS = (
"-pagezero_size",
1000,
);
PRODUCT_NAME = MoreBacktraceTestTool;
};
name = Development;
};
E42C517B097D6E2E00D1B30B /* Deployment */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = (
ppc,
ppc64,
i386,
);
BUILD_VARIANTS = normal;
INSTALL_PATH = "$(HOME)/bin";
OTHER_CFLAGS = "-fasm-blocks";
OTHER_LDFLAGS = (
"-pagezero_size",
1000,
);
PRODUCT_NAME = MoreBacktraceTestTool;
};
name = Deployment;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E42C5087097D61DA00D1B30B /* Build configuration list for PBXProject "MoreBacktraceTest" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E42C5088097D61DA00D1B30B /* Development */,
E42C5089097D61DA00D1B30B /* Deployment */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Development;
};
E42C5119097D62FC00D1B30B /* Build configuration list for PBXNativeTarget "App" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E42C511A097D62FC00D1B30B /* Development */,
E42C511B097D62FC00D1B30B /* Deployment */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Development;
};
E42C5179097D6E2E00D1B30B /* Build configuration list for PBXNativeTarget "Tool" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E42C517A097D6E2E00D1B30B /* Development */,
E42C517B097D6E2E00D1B30B /* Deployment */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Development;
};
/* End XCConfigurationList section */
};
rootObject = 20286C28FDCF999611CA2CEA /* Project object */;
}

Просмотреть файл

@ -0,0 +1,765 @@
/*
File: MoreBacktraceTestCommon.c
Contains: Common code for testing MoreBacktrace.
Written by: DTS
Copyright: Copyright (c) 2006 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Apples
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 Computer, 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: MoreBacktraceTestCommon.c,v $
Revision 1.5 2006/01/23 19:26:07 eskimo1
Spin on a volatile int because the compiler doesn't like spinning an a volatile pointer (even after I declare it correctly).
Revision 1.1 2006/01/22 22:47:49 eskimo1
A new module that abstracts the test code out of the GUI test app so that it can also be used by the command line tool.
*/
/////////////////////////////////////////////////////////////////
// Our Prototypes
#include "MoreBacktraceTestCommon.h"
// Mac OS Interfaces
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// MIB Interfaces
#include "MoreAddrToSym.h"
/////////////////////////////////////////////////////////////////
#pragma mark ***** Backtrace To Text
// TestMoreBacktraceFramesToText uses a memory based (FILE *) (created using
// fwopen) to collect its results. WriteCallback is the routine that handles
// writes for this (FILE *). WriteCallbackContext holds its state.
struct WriteCallbackContext {
size_t dataSize; // current data size
char * data; // current data
};
typedef struct WriteCallbackContext WriteCallbackContext;
static int WriteCallback(void *cookie, const char *data, int dataSize)
// Passed as a write callback to fwopen to create a memory-based
// (FILE *). See <x-man-page://3/fwopen> for details.
{
int err;
int result;
char * tmp;
WriteCallbackContext * context;
// Recover our context from the cookie.
context = (WriteCallbackContext *) cookie;
// Allocate a new buffer to accommodate the old data and the new.
err = 0;
tmp = malloc(context->dataSize + dataSize);
if (tmp == NULL) {
err = ENOMEM;
}
// Fill it in.
if (err == 0) {
memcpy(tmp, context->data, context->dataSize); // old data
memcpy(tmp + context->dataSize, data, dataSize); // new data
free(context->data);
context->data = tmp;
context->dataSize += dataSize;
}
// Clean up.
if (err == 0) {
result = dataSize;
} else {
errno = err;
result = -1;
}
return result;
}
extern int TestMoreBacktraceFramesToText(
const MoreBTFrame frames[],
size_t frameCount,
bool lookupSymbolNames,
char ** btPtr
)
// See comments in header.
{
int err;
int junk;
WriteCallbackContext resultContext;
FILE * result;
size_t frameIndex;
MoreAToSSymInfo * symbols;
assert(frames != NULL);
assert(btPtr != NULL);
assert(*btPtr == NULL);
result = NULL;
resultContext.dataSize = 0;
resultContext.data = NULL;
symbols = NULL;
// Create an array of NULL CFStringRefs to hold the symbol pointers.
err = MoreAToSCreate(frameCount, &symbols);
// If we've been asked to look up the symbols, do so.
if ( (err == 0) && lookupSymbolNames) {
MoreAToSAddr *addresses;
// Allocate an array for the addresses and fill it in.
addresses = (MoreAToSAddr *) malloc(frameCount * sizeof(*addresses));
if (addresses == NULL) {
err = ENOMEM;
}
if (err == 0) {
for (frameIndex = 0; frameIndex < frameCount; frameIndex++) {
if (frames[frameIndex].flags & kMoreBTPCBadMask) {
addresses[frameIndex] = 0;
} else {
addresses[frameIndex] = frames[frameIndex].pc;
}
}
}
// Call MoreAddrToSym module to do the job.
if (err == 0) {
err = MoreAToSCopySymbolNamesUsingDyld(frameCount, addresses, symbols);
}
free(addresses);
}
// Create the output string, starting with an empty string and then
// appending an entry for each frame. This uses the little known
// ability of BSD to create a (FILE *) with custom I/O routines. In this
// case, I have a write routine that outputs to a memory buffer (the
// details of which are held in resultContext).
if (err == 0) {
result = fwopen(&resultContext, WriteCallback);
if (result == NULL) {
err = errno;
}
}
if (err == 0) {
int ptrWidth;
// Determine whether we can treat the backtrace is 32-bit or whether we have to
// output the full 64-bits of each pointer.
ptrWidth = 8;
for (frameIndex = 0; frameIndex < frameCount; frameIndex++) {
const MoreBTFrame * thisFrame;
thisFrame = &frames[frameIndex];
if ( !(thisFrame->flags & kMoreBTPCBadMask) && (thisFrame->pc & 0xFFFFFFFF00000000LL) ) {
ptrWidth = 16;
}
if ( !(thisFrame->flags & kMoreBTFrameBadMask) && (thisFrame->fp & 0xFFFFFFFF00000000LL) ) {
ptrWidth = 16;
}
}
// Now output each entry.
for (frameIndex = 0; frameIndex < frameCount; frameIndex++) {
const char *thisSymbol;
// First the frame number and the flags.
junk = fprintf(result, "%2zu %c%c%c ",
frameIndex,
(frames[frameIndex].flags & kMoreBTFrameBadMask) ? 'F' : 'f',
(frames[frameIndex].flags & kMoreBTPCBadMask) ? 'P' : 'p',
(frames[frameIndex].flags & kMoreBTSignalHandlerMask) ? 'S' : 's'
);
assert(junk > 0);
// Then the frame pointer.
if (frames[frameIndex].flags & kMoreBTFrameBadMask) {
fprintf(result, "%*s ", ptrWidth, "");
} else {
fprintf(result, "%*llx ", ptrWidth, frames[frameIndex].fp);
}
// Then the PC.
if (frames[frameIndex].flags & kMoreBTPCBadMask) {
fprintf(result, "%*s ", ptrWidth, "");
} else {
fprintf(result, "%*llx ", ptrWidth, frames[frameIndex].pc);
}
// Finally the symbolic name, if present.
thisSymbol = symbols[frameIndex].symbolName;
if (thisSymbol != NULL) {
junk = fprintf(result, " %s+%04llx", thisSymbol, symbols[frameIndex].symbolOffset);
assert(junk > 0);
}
junk = fprintf(result, "\n");
assert(junk > 0);
}
}
// Null terminate the string.
if (err == 0) {
junk = fputc(0, result);
assert(junk >= 0);
}
// Clean up.
if (result != NULL) {
junk = fclose(result);
assert(junk == 0);
}
if (err == 0) {
*btPtr = resultContext.data; // all good, return resultContext.data to the client
} else {
free(resultContext.data); // all bad, free up resultContext.data and leave *btPtr as NULL
}
MoreAToSDestroy(frameCount, symbols);
assert( (err == 0) == (*btPtr != NULL) );
return err;
}
#pragma mark ***** Self Test
// To simplify the test code, I receive the backtrace into a fixed size array.
// The number of elements in this array, 70, is the number that I can reasonably
// display in the window of the GUI app. I've carried it forward into the common
// code because I don't see any pressing need to change it.
enum {
kFrameCount = 70
};
extern int TestMoreBacktraceMachSelf(char **btPtr)
// See comments in header.
{
int err;
MoreBTFrame frames[kFrameCount];
size_t frameCount;
size_t validFrames;
assert( btPtr != NULL);
assert(*btPtr == NULL);
frameCount = sizeof(frames) / sizeof(*frames);
err = MoreBacktraceMachSelf(0, 0, frames, frameCount, &validFrames);
if (err == 0) {
if (validFrames > frameCount) {
validFrames = frameCount;
}
err = TestMoreBacktraceFramesToText(frames, validFrames, true, btPtr);
}
assert( (err == 0) == (*btPtr != NULL) );
return err;
}
#pragma mark ***** Other Task Test
extern int TestMoreBacktraceMachThread(pid_t pid, char **btPtr)
// See comments in header.
{
int err;
int junk;
MoreBTFrame frames[kFrameCount];
size_t frameCount;
size_t validFrames;
task_t targetTask;
bool didSuspend;
thread_array_t threadList;
mach_msg_type_number_t threadCount;
assert(pid > 0);
assert(btPtr != NULL);
assert(*btPtr == NULL);
targetTask = MACH_PORT_NULL;
threadList = NULL;
didSuspend = false;
frameCount = 0; // just to quieten a warning
// Convert pid to the Mach task control port.
err = task_for_pid(mach_task_self(), pid, &targetTask);
if (err == 0) {
if (targetTask == mach_task_self()) {
err = -1; // this won't go well
}
}
// Suspend the task while we sample it. Otherwise the
// list of threads might change.
if (err == 0) {
err = task_suspend(targetTask);
didSuspend = (err == 0);
}
if (err == 0) {
err = task_threads(targetTask, &threadList, &threadCount);
}
if (err == 0) {
// A task without any threads makes no sense.
assert(threadCount > 0);
// We always sample the first thread. This has no real
// significance because Mach doesn't guarantee to return
// the threads in any particular order. In a real tool
// you'd iterate over all of the threads and sample each,
// but I have no way of displaying the results in my
// test framework.
frameCount = sizeof(frames) / sizeof(*frames);
err = MoreBacktraceMachThread(targetTask, threadList[0], 0, 0, frames, frameCount, &validFrames);
}
// Resume the task as quickly as possibly after the backtrace.
if (didSuspend) {
junk = task_resume(targetTask);
assert(junk == 0);
}
// Create the text output without symbols.
if (err == 0) {
if (validFrames > frameCount) {
validFrames = frameCount;
}
err = TestMoreBacktraceFramesToText(frames, validFrames, false, btPtr);
}
// Clean up.
junk = mach_port_deallocate(mach_task_self(), targetTask);
assert(junk == 0);
if (threadList != NULL) {
mach_msg_type_number_t thisThread;
for (thisThread = 0; thisThread < threadCount; thisThread++) {
junk = mach_port_deallocate(mach_task_self(), threadList[thisThread]);
assert(junk == 0);
}
junk = vm_deallocate(mach_task_self(), (vm_address_t) threadList, threadCount * sizeof(*threadList));
assert(junk == 0);
}
assert( (err == 0) == (*btPtr != NULL) );
return err;
}
#pragma mark ***** Signal Test
// The following are set by the signal handler when it runs.
static volatile int gError = -1;
static char volatile * gBacktrace = NULL;
static void MySIGUSR1Handler(int signal)
// Handle SIGUSR1. Note that we call many functions
// here that aren't "signal safe". However, we know
// that this signal isn't happening asynchronously,
// we're sending it to ourselves via a call to "pthread_kill",
// so most of the unsafeness is moot. Still, if this
// wasn't a just test program I'd figure out a better way.
{
int err;
char * tmp;
assert(signal == SIGUSR1);
fprintf(stderr, "MySIGUSR1Handler calls TestMoreBacktraceMachSelf.\n");
tmp = (char *) gBacktrace;
err = TestMoreBacktraceMachSelf(&tmp);
gBacktrace = tmp; // Because the code in TestSignalBacktraceNested
gError = err; // might be spinning on gError, assign that last.
}
static int TestSignalBacktraceNested(bool nonLeaf)
// Send a SIGUSR1 to ourselves.
{
int err;
if ( ! nonLeaf ) {
// This is the standard branch. We use pthread_kill to send a signal
// to ourself.
err = pthread_kill(pthread_self(), SIGUSR1);
} else {
// Use this branch of the code, in tandem with sending the SIGUSR1 from
// the command line, to test the case where a signal interrupts a non-leaf
// routine. I added this because pthread_kill (well, actually __pthread_kill)
// is a system call leaf routine, so the main test only checks the
// in leaf routine case.
//
// Also, this is a hard spin loop because I can't
// add a delay call because then it's likely that the signal would come
// in while we're blocked in the delay, and then we're back to the leaf
// routine test again.
fprintf(stderr, "Signal this process using:\n");
fprintf(stderr, "\n");
fprintf(stderr, "$ kill -USR1 %ld\n", (long) getpid());
while (gError == -1) {
// do nothing
}
err = 0;
}
return err;
}
extern int TestMoreBacktraceMachSelfSignal(bool nonLeaf, char **btPtr)
// See comments in header.
{
int err;
int junk;
struct sigaction oldSig;
struct sigaction newSig;
assert(btPtr != NULL);
assert(*btPtr == NULL);
assert(gBacktrace == NULL);
assert(gError == -1);
// Install MySIGUSR1Handler as the SIGUSR1 handler.
memset(&newSig, 0, sizeof(newSig));
newSig.sa_handler = &MySIGUSR1Handler;
err = sigaction(SIGUSR1, &newSig, &oldSig);
if (err < 0) {
err = errno;
}
if (err == 0) {
// Call a routine that sends a signal to us.
err = TestSignalBacktraceNested(nonLeaf);
// Restore the old signal handler.
junk = sigaction(SIGUSR1, &oldSig, NULL);
assert(junk == 0);
if (err == 0) {
err = gError; // get the error from the signal handler
gError = -1; // just for tidiness
}
}
if (err == 0) {
*btPtr = (char *) gBacktrace; // get the backtrace from the signal handler
gBacktrace = NULL; // just for tidiness
}
assert( (err == 0) == (*btPtr != NULL) );
return err;
}
#pragma mark ***** Stack Smash Test
// This test works by create a dummy thread that blocks forever deep in nested
// routines, then smashing its stack.
static pthread_t gDeadThread;
// The dummy thread itself.
static pthread_mutex_t gDeadThreadReadyMutex;
static pthread_cond_t gDeadThreadReadyCond;
// A condition variable that protects gDeadThreadReady and gDeadThreadID.
static volatile bool gDeadThreadReady = false;
// True if the dead thread is ready to be smashed.
static volatile thread_t gDeadThreadID = MACH_PORT_NULL;
// The Mach thread ID of the thread.
static void DeadThreadNested4(void)
// The victim routine itself.
{
int junk;
// Set our condition to true.
junk = pthread_mutex_lock(&gDeadThreadReadyMutex);
assert(junk == 0);
gDeadThreadReady = true;
gDeadThreadID = mach_thread_self();
junk = pthread_mutex_unlock(&gDeadThreadReadyMutex);
assert(junk == 0);
// Signal the main thread who is waiting on our condition.
junk = pthread_cond_signal(&gDeadThreadReadyCond);
assert(junk == 0);
// Loop forever.
do {
(void) pause();
} while (true);
}
static void DeadThreadNested3(void)
// A few nested procedures so you get an interesting trace.
{
DeadThreadNested4();
}
static void DeadThreadNested2(void)
// A few nested procedures so you get an interesting trace.
{
DeadThreadNested3();
}
static void DeadThreadNested1(void)
// A few nested procedures so you get an interesting trace.
{
DeadThreadNested2();
}
static void * DeadThread(void *param)
// The thread entry point for the victim thread.
{
#pragma unused(param)
DeadThreadNested1();
return NULL;
}
static int StartDeadThread(void)
// Start a victim thread whose stack we intend to smash
// in order to test our handling of bad pointers in a
// stack crawl.
//
// Returns an errno-style error.
{
int err;
int junk;
thread_t threadID;
MoreBTFrame frames[10];
size_t frameCount;
size_t validFrames;
// Init resources required for condition variable.
err = pthread_mutex_init(&gDeadThreadReadyMutex, NULL);
if (err == 0) {
err = pthread_cond_init(&gDeadThreadReadyCond, NULL);
}
// Start the thread.
if (err == 0) {
err = pthread_create(&gDeadThread, NULL, DeadThread, NULL);
}
if (err == 0) {
junk = pthread_detach(gDeadThread);
assert(junk == 0);
}
// Wait for the condition.
if (err == 0) {
threadID = MACH_PORT_NULL;
do {
junk = pthread_mutex_lock(&gDeadThreadReadyMutex);
assert(junk == 0);
if (gDeadThreadReady) {
threadID = gDeadThreadID;
}
if (threadID == MACH_PORT_NULL) {
junk = pthread_cond_wait(&gDeadThreadReadyCond, &gDeadThreadReadyMutex);
assert(junk == 0);
}
junk = pthread_mutex_unlock(&gDeadThreadReadyMutex);
assert(junk == 0);
} while ( threadID == MACH_PORT_NULL );
}
// Take a backtrace.
if (err == 0) {
frameCount = sizeof(frames) / sizeof(frames[0]);
err = MoreBacktraceMachThread(
mach_task_self(),
threadID,
0,
0,
frames,
frameCount,
&validFrames
);
}
if (err == 0) {
if (validFrames < frameCount) {
err = -1;
} else if (validFrames > frameCount) {
validFrames = frameCount;
}
}
if ( (err == 0) && true) {
char * bt;
bt = NULL;
err = TestMoreBacktraceFramesToText(frames, validFrames, true, &bt);
if (err == 0) {
fprintf(stderr, "Pre-smash backtrace:\n");
fprintf(stdout, "%s\n", bt);
}
free(bt);
err = 0;
}
// Now let's use that backtrace to vandalise the stack!
if (err == 0) {
int i;
char * busErrorAddress;
char ** fp;
// I don't want to use 0 for the Mac OS X bus error value, because
// it's a little obvious. Instead I use a value that's in the bottom
// page (ie is less than 0x1000) and is easily recognisable.
busErrorAddress = (char *) (intptr_t) 0xfec;
// 1. We go down 4 frames on the stack and smash the next
// frame pointer.
fp = (char **) (intptr_t) frames[4].fp;
fp[0] = busErrorAddress;
// 2. We go down 2 frames on the stack and smash the
// return address. As its location is architecture dependent,
// we just smash 8 words and hope that we get it (-:
fp = (char **) (intptr_t) frames[2].fp;
for (i = 0; i < 8; i++) {
fp[i] = busErrorAddress;
}
}
return err;
}
extern int TestMoreBacktraceMachThreadStackSmash(char **btPtr)
// See comments in header.
{
int err;
MoreBTFrame frames[kFrameCount];
size_t frameCount;
size_t validFrames;
assert( btPtr != NULL);
assert(*btPtr == NULL);
// Start a thread that just blocks indefinitely. In the
// process, smash its stack.
err = 0;
if ( ! gDeadThreadReady ) {
err = StartDeadThread();
}
assert( (err != 0) || (gDeadThreadReady && (gDeadThreadID != MACH_PORT_NULL)) );
// Take a backtrace of that thread and return it.
if (err == 0) {
frameCount = sizeof(frames) / sizeof(*frames);
err = MoreBacktraceMachThread(mach_task_self(), gDeadThreadID, 0, 0, frames, frameCount, &validFrames);
}
if (err == 0) {
if (validFrames > frameCount) {
validFrames = frameCount;
}
err = TestMoreBacktraceFramesToText(frames, validFrames, true, btPtr);
}
assert( (err == 0) == (*btPtr != NULL) );
return err;
}

Просмотреть файл

@ -0,0 +1,127 @@
/*
File: MoreBacktraceTestCommon.h
Contains: Common code for testing backtraces.
Written by: DTS
Copyright: Copyright (c) 2006 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Apples
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 Computer, 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: MoreBacktraceTestCommon.h,v $
Revision 1.1 2006/01/22 22:47:51 eskimo1
A new module that abstracts the test code out of the GUI test app so that it can also be used by the command line tool.
*/
#pragma once
/////////////////////////////////////////////////////////////////
// MoreIsBetter Setup
#include "MoreSetup.h"
// Mac OS Interfaces
#include <stdbool.h>
#include <unistd.h>
// MIB Interfaces
#include "MoreBacktrace.h"
/////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
/////////////////////////////////////////////////////////////////
// This module contains common test code that's shared between the application
// and the command line tool.
extern int TestMoreBacktraceFramesToText(
const MoreBTFrame frames[],
size_t frameCount,
bool lookupSymbolNames,
char ** btPtr
);
// Converts a backtrace (specified by frames and frameCount)
// to textual form, returning a pointer to the text in *btPtr.
// Each line is separated by a '\n' and the entire string
// is null terminated. The caller is responsible for disposing
// of this result using free.
//
// If lookupSymbolNames is true,
// the textual representation will contain symbols generated
// using the MoreAddrToSym module. Given that this module
// only supports looking up symbols in the current task
// (at least currently), you should only pass true to this
// parameter if the backtrace came from the current task.
//
// On entry, frames must not be NULL.
// On entry, btPtr must not be NULL.
// On entry, *btPtr must be NULL.
// Returns an errno-style error code.
// On success, *btPtr will not be NULL.
// On error, *btPtr will be NULL.
// The following routines run a variety of different backtrace tests.
// This each return an errno-style error code, and set *btPtr as
// specified by TestMoreBacktraceFramesToText.
extern int TestMoreBacktraceMachSelf(char **btPtr);
// Backtrace the current thread.
extern int TestMoreBacktraceMachThread(pid_t pid, char **btPtr);
// Backtrace a random thread in the specified task.
extern int TestMoreBacktraceMachSelfSignal(bool nonLeaf, char **btPtr);
// Backtrace across a signal handler. If nonLeaf is set,
// this requires user intervention to deliver the signal.
extern int TestMoreBacktraceMachThreadStackSmash(char **btPtr);
// Backtrace a thread with a smashed stack.
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -0,0 +1,169 @@
/*
File: MoreBacktraceTestTool.c
Contains: Command line tool to test MoreBacktrace.
Written by: DTS
Copyright: Copyright (c) 2006 by Apple Computer, Inc., All Rights Reserved.
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Apples
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 Computer, 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):
*/
/////////////////////////////////////////////////////////////////
// System interfaces
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <TargetConditionals.h>
// MIB interfaces
#include "MoreBacktraceTestCommon.h"
/////////////////////////////////////////////////////////////////
static void PrintUsage(const char *argv0)
// Print the program's usage.
{
const char *command;
command = strrchr(argv0, '/');
if (command == NULL) {
command = argv0;
} else {
command += 1;
}
fprintf(stderr, "usage: %s command...\n", command);
fprintf(stderr, " commands: -self\n");
fprintf(stderr, " commands: -signal\n");
fprintf(stderr, " commands: -signal-nonleaf\n");
fprintf(stderr, " commands: -pid <pid>\n");
fprintf(stderr, " commands: -smash\n");
}
int main(int argc, char **argv)
{
int err;
int retVal;
const char * builtArch;
bool printUsage;
int argIndex;
pid_t pid;
// Just for convenience's sake, print out the architecture of the
// code we're actually running. In the world of universal binaries,
// Rosseta, and PowerPC 32- and 64-bit, it's often hard to remember
// what's what.
#if TARGET_CPU_PPC
builtArch = "ppc";
#elif TARGET_CPU_PPC64
builtArch = "ppc64";
#elif TARGET_CPU_X86
builtArch = "i386";
#else
#error What are you building?
#endif
fprintf(stderr, "Built for %s.\n", builtArch);
// Process command line arguments.
retVal = EXIT_SUCCESS;
printUsage = false;
if (argc < 2) {
printUsage = true;
} else {
argIndex = 1;
while (argIndex < argc) {
char * bt;
err = 0;
bt = NULL;
if ( strcmp(argv[argIndex], "-self") == 0 ) {
argIndex += 1;
err = TestMoreBacktraceMachSelf(&bt);
} else if ( strcmp(argv[argIndex], "-pid") == 0 ) {
argIndex += 1;
if (argIndex < argc) {
pid = (pid_t) atol(argv[argIndex]);
argIndex += 1;
err = TestMoreBacktraceMachThread(pid, &bt);
} else {
printUsage = true;
}
} else if ( strcmp(argv[argIndex], "-signal") == 0 ) {
argIndex += 1;
err = TestMoreBacktraceMachSelfSignal(false, &bt);
} else if ( strcmp(argv[argIndex], "-signal-nonleaf") == 0 ) {
argIndex += 1;
err = TestMoreBacktraceMachSelfSignal(true, &bt);
} else if ( strcmp(argv[argIndex], "-smash") == 0 ) {
argIndex += 1;
err = TestMoreBacktraceMachThreadStackSmash(&bt);
if (err == 0) {
fprintf(stderr, "Post-smash backtrace:\n");
}
} else {
argIndex = argc;
printUsage = true;
}
if ( (err == 0) && (bt != NULL) ) {
fprintf(stdout, "%s\n", bt);
} else {
fprintf(stderr, "Failed to backtrace (error %d).\n", err);
}
free(bt);
}
}
if (printUsage) {
PrintUsage(argv[0]);
retVal = EXIT_FAILURE;
}
return retVal;
}

Просмотреть файл

@ -0,0 +1,4 @@
{
IBClasses = ();
IBVersion = 1;
}

19
opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreBacktraceTest/main.nib/info.nib сгенерированный Обычный файл
Просмотреть файл

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>69 10 356 240 0 0 1280 832 </string>
<key>IBEditorPositions</key>
<dict>
<key>29</key>
<string>69 252 216 44 0 0 1280 1002 </string>
</dict>
<key>IBFramework Version</key>
<string>443.0</string>
<key>IBSystem Version</key>
<string>8G32</string>
<key>targetFramework</key>
<string>IBCarbonFramework</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,101 @@
<?xml version="1.0" standalone="yes"?>
<object class="NSIBObjectData">
<string name="targetFramework">IBCarbonFramework</string>
<object name="rootObject" class="NSCustomObject" id="1">
<string name="customClass">NSApplication</string>
</object>
<array count="12" name="allObjects">
<object class="IBCarbonMenu" id="29">
<string name="title">main</string>
<array count="2" name="items">
<object class="IBCarbonMenuItem" id="185">
<string name="title">MoreBacktraceTest</string>
<object name="submenu" class="IBCarbonMenu" id="184">
<string name="title">MoreBacktraceTest</string>
<array count="1" name="items">
<object class="IBCarbonMenuItem" id="187">
<string name="title">About MoreBacktraceTest</string>
<int name="keyEquivalentModifier">0</int>
<ostype name="command">abou</ostype>
</object>
</array>
<string name="name">_NSAppleMenu</string>
</object>
</object>
<object class="IBCarbonMenuItem" id="192">
<string name="title">Window</string>
<object name="submenu" class="IBCarbonMenu" id="195">
<string name="title">Window</string>
<array count="6" name="items">
<object class="IBCarbonMenuItem" id="197">
<string name="title">Zoom Window</string>
<ostype name="command">zoom</ostype>
</object>
<object class="IBCarbonMenuItem" id="190">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Minimize Window</string>
<string name="keyEquivalent">m</string>
<ostype name="command">mini</ostype>
</object>
<object class="IBCarbonMenuItem" id="191">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Minimize All Windows</string>
<string name="keyEquivalent">m</string>
<int name="keyEquivalentModifier">1572864</int>
<ostype name="command">mina</ostype>
</object>
<object class="IBCarbonMenuItem" id="194">
<boolean name="separator">TRUE</boolean>
</object>
<object class="IBCarbonMenuItem" id="196">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Bring All to Front</string>
<ostype name="command">bfrt</ostype>
</object>
<object class="IBCarbonMenuItem" id="193">
<boolean name="dynamic">TRUE</boolean>
<string name="title">Arrange in Front</string>
<int name="keyEquivalentModifier">1572864</int>
<ostype name="command">frnt</ostype>
</object>
</array>
<string name="name">_NSWindowsMenu</string>
</object>
</object>
</array>
<string name="name">_NSMainMenu</string>
</object>
<reference idRef="184"/>
<reference idRef="185"/>
<reference idRef="187"/>
<reference idRef="190"/>
<reference idRef="191"/>
<reference idRef="192"/>
<reference idRef="193"/>
<reference idRef="194"/>
<reference idRef="195"/>
<reference idRef="196"/>
<reference idRef="197"/>
</array>
<array count="12" name="allParents">
<reference idRef="1"/>
<reference idRef="185"/>
<reference idRef="29"/>
<reference idRef="184"/>
<reference idRef="195"/>
<reference idRef="195"/>
<reference idRef="29"/>
<reference idRef="195"/>
<reference idRef="195"/>
<reference idRef="192"/>
<reference idRef="195"/>
<reference idRef="195"/>
</array>
<dictionary count="2" name="nameTable">
<string>Files Owner</string>
<reference idRef="1"/>
<string>MenuBar</string>
<reference idRef="29"/>
</dictionary>
<unsigned_int name="nextObjectID">246</unsigned_int>
</object>

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

105
opal/mca/backtrace/darwin/backtrace_darwin.c Обычный файл
Просмотреть файл

@ -0,0 +1,105 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include <stdio.h>
#include "opal/constants.h"
#include "opal/mca/backtrace/backtrace.h"
#include "opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreBacktrace.h"
#include "opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreAddrToSym.h"
#define SIGNAL_SKIPFRAME 4
#define ALWAYS_SKIPFRAME 2
#define kFrameCount 32
void
opal_backtrace_print(FILE *file)
{
int ret;
unsigned long frameCount;
unsigned long validFrames;
MoreBTFrame frames[kFrameCount];
unsigned long frameIndex, skipframe = 0;
MoreAToSSymInfo symbol;
MoreAToSAddr address;
frameCount = sizeof(frames) / sizeof(*frames);
ret = MoreBacktraceMachSelf(0, 0, frames, frameCount, &validFrames);
if (0 != ret) {
fprintf(file, "Stack corrupted and not printable\n");
fflush(stderr);
return;
}
if (validFrames > frameCount) {
validFrames = frameCount;
}
if ((validFrames >= SIGNAL_SKIPFRAME) &&
(frames[SIGNAL_SKIPFRAME-1].flags & kMoreBTSignalHandlerMask)) {
skipframe = SIGNAL_SKIPFRAME;
} else if (validFrames >= ALWAYS_SKIPFRAME) {
skipframe = ALWAYS_SKIPFRAME;
}
for (frameIndex = skipframe; frameIndex < validFrames; frameIndex++) {
fprintf(stderr, "[%2ld] ", frameIndex - skipframe + 1);
if (frames[frameIndex].flags & kMoreBTPCBadMask) {
address = 0;
} else {
address = (MoreAToSAddr) frames[frameIndex].pc;
}
symbol.symbolName = NULL;
symbol.symbolType = kMoreAToSNoSymbol;
symbol.symbolOffset = 0;
ret = MoreAToSCopySymbolNamesUsingDyld(1, &address, &symbol);
if (symbol.symbolName) {
if (symbol.symbolName[0]) {
fprintf(file, "(%s + 0x%llx) ",
symbol.symbolName, symbol.symbolOffset);
free( (void *) symbol.symbolName);
}
}
fprintf(file, "[0x%08llx, 0x%08llx] ",
frames[frameIndex].fp,
frames[frameIndex].pc);
if (frames[frameIndex].flags) {
fprintf(file, "(%c%c%c)",
(frames[frameIndex].flags & kMoreBTFrameBadMask) ? 'F' : '-',
(frames[frameIndex].flags & kMoreBTPCBadMask) ? 'P' : '-',
(frames[frameIndex].flags & kMoreBTSignalHandlerMask) ? 'S' : '-');
}
fprintf(file, "\n");
}
}
int
opal_backtrace_buffer(char ***message_out, int *len_out)
{
return OPAL_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,47 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include "opal/mca/backtrace/backtrace.h"
const opal_backtrace_base_component_1_0_0_t mca_backtrace_darwin_component = {
/* First, the mca_component_t struct containing meta information
about the component itself */
{
/* Indicate that we are a backtrace v1.0.0 component (which also
implies a specific MCA version) */
OPAL_BACKTRACE_BASE_VERSION_1_0_0,
/* Component name and version */
"darwin",
OPAL_MAJOR_VERSION,
OPAL_MINOR_VERSION,
OPAL_RELEASE_VERSION,
/* Component open and close functions */
NULL,
NULL
},
/* Next the MCA v1.0.0 component meta data */
{
/* Whether the component is checkpointable or not */
true
},
};

43
opal/mca/backtrace/darwin/configure.m4 Обычный файл
Просмотреть файл

@ -0,0 +1,43 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
AC_DEFUN([MCA_backtrace_darwin_COMPILE_MODE], [
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
$4="static"
AC_MSG_RESULT([$$4])
])
# MCA_backtrace_darwin_CONFIG(action-if-can-compile,
# [action-if-cant-compile])
# ------------------------------------------------
AC_DEFUN([MCA_backtrace_darwin_CONFIG],[
AC_CHECK_FUNCS([vm_read_overwrite],
[backtrace_darwin_happy="yes"],
[backtrace_darwin_happy="no"])
if test "$backtrace_darwin_happy" = "yes" ; then
if test "$OMPI_C_GCC_INLINE_ASSEMBLY" = "0" ; then
backtrace_darwin_happy="no"
fi
fi
AS_IF([test "$backtrace_darwin_happy" = "yes"],
[$1], [$2])
])

15
opal/mca/backtrace/darwin/configure.params Обычный файл
Просмотреть файл

@ -0,0 +1,15 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2006 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
# Specific to this module
PARAM_CONFIG_PRIORITY=30
PARAM_CONFIG_FILES="Makefile"

23
opal/mca/backtrace/execinfo/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,23 @@
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
noinst_LTLIBRARIES = libmca_backtrace_execinfo.la
libmca_backtrace_execinfo_la_SOURCES = \
backtrace_execinfo.c \
backtrace_execinfo_component.c

Просмотреть файл

@ -0,0 +1,61 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include <stdio.h>
#include <execinfo.h>
#include "opal/constants.h"
#include "opal/mca/backtrace/backtrace.h"
void
opal_backtrace_print(FILE *file)
{
int i;
int trace_size;
void * trace[32];
char ** messages = (char **)NULL;
trace_size = backtrace (trace, 32);
messages = backtrace_symbols (trace, trace_size);
for (i = 0; i < trace_size; i++) {
fprintf(file, "[%d] func:%s\n", i, messages[i]);
fflush(file);
}
free(messages);
}
int
opal_backtrace_buffer(char ***message_out, int *len_out)
{
int trace_size;
void * trace[32];
char ** funcs = (char **)NULL;
trace_size = backtrace (trace, 32);
funcs = backtrace_symbols (trace, trace_size);
*message_out = funcs;
*len_out = trace_size;
return OPAL_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,47 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include "opal/mca/backtrace/backtrace.h"
const opal_backtrace_base_component_1_0_0_t mca_backtrace_execinfo_component = {
/* First, the mca_component_t struct containing meta information
about the component itself */
{
/* Indicate that we are a backtrace v1.0.0 component (which also
implies a specific MCA version) */
OPAL_BACKTRACE_BASE_VERSION_1_0_0,
/* Component name and version */
"execinfo",
OPAL_MAJOR_VERSION,
OPAL_MINOR_VERSION,
OPAL_RELEASE_VERSION,
/* Component open and close functions */
NULL,
NULL
},
/* Next the MCA v1.0.0 component meta data */
{
/* Whether the component is checkpointable or not */
true
},
};

39
opal/mca/backtrace/execinfo/configure.m4 Обычный файл
Просмотреть файл

@ -0,0 +1,39 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
AC_DEFUN([MCA_backtrace_execinfo_COMPILE_MODE], [
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
$4="static"
AC_MSG_RESULT([$$4])
])
# MCA_backtrace_execinfo_CONFIG(action-if-can-compile,
# [action-if-cant-compile])
# ------------------------------------------------
AC_DEFUN([MCA_backtrace_execinfo_CONFIG],[
AC_CHECK_HEADERS([execinfo.h])
# FreeBSD has backtrace in -lexecinfo, usually in libc
OMPI_CHECK_FUNC_LIB([backtrace], [execinfo],
[backtrace_execinfo_happy="yes"],
[backtrace_execinfo_happy="no"])
AS_IF([test "$backtrace_execinfo_happy" = "yes"],
[$1], [$2])
])

Просмотреть файл

@ -0,0 +1,15 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2006 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
# Specific to this module
PARAM_CONFIG_PRIORITY=30
PARAM_CONFIG_FILES="Makefile"

23
opal/mca/backtrace/none/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,23 @@
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
noinst_LTLIBRARIES = libmca_backtrace_none.la
libmca_backtrace_none_la_SOURCES = \
backtrace_none.c \
backtrace_none_component.c

33
opal/mca/backtrace/none/backtrace_none.c Обычный файл
Просмотреть файл

@ -0,0 +1,33 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
void
opal_backtrace_print(FILE *file)
{
}
int
opal_backtrace_buffer(char ***message_out, int *len_out);
{
*messages_out = NULL;
*len_out = 0;
return OMPI_ERR_NOT_IMPLEMENTED
}

Просмотреть файл

@ -0,0 +1,47 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include "opal/mca/backtrace/backtrace.h"
const opal_backtrace_base_component_1_0_0_t mca_backtrace_none_component = {
/* First, the mca_component_t struct containing meta information
about the component itself */
{
/* Indicate that we are a backtrace v1.0.0 component (which also
implies a specific MCA version) */
OPAL_BACKTRACE_BASE_VERSION_1_0_0,
/* Component name and version */
"none",
OPAL_MAJOR_VERSION,
OPAL_MINOR_VERSION,
OPAL_RELEASE_VERSION,
/* Component open and close functions */
NULL,
NULL
},
/* Next the MCA v1.0.0 component meta data */
{
/* Whether the component is checkpointable or not */
true
},
};

30
opal/mca/backtrace/none/configure.m4 Обычный файл
Просмотреть файл

@ -0,0 +1,30 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
AC_DEFUN([MCA_backtrace_none_COMPILE_MODE], [
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
$4="static"
AC_MSG_RESULT([$$4])
])
# MCA_backtrace_none_CONFIG(action-if-can-compile,
# [action-if-cant-compile])
# ------------------------------------------------
AC_DEFUN([MCA_backtrace_none_CONFIG],[$1])

15
opal/mca/backtrace/none/configure.params Обычный файл
Просмотреть файл

@ -0,0 +1,15 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2006 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
# Specific to this module
PARAM_CONFIG_PRIORITY=0
PARAM_CONFIG_FILES="Makefile"

23
opal/mca/backtrace/printstack/Makefile.am Обычный файл
Просмотреть файл

@ -0,0 +1,23 @@
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
noinst_LTLIBRARIES = libmca_backtrace_printstack.la
libmca_backtrace_printstack_la_SOURCES = \
backtrace_printstack.c \
backtrace_printstack_component.c

Просмотреть файл

@ -0,0 +1,38 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
void
opal_backtrace_print(FILE *file)
{
printstack(fileno(file));
}
int
opal_backtrace_buffer(char ***message_out, int *len_out);
{
*messages_out = NULL;
*len_out = 0;
/* BWB - I think we can implement this in a similar way that
printstack is implemented. I just don't have time right
now. */
return OMPI_ERR_NOT_IMPLEMENTED
}

Просмотреть файл

@ -0,0 +1,47 @@
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2006 The Regents of the University of California.
* All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include "opal/mca/backtrace/backtrace.h"
const opal_backtrace_base_component_1_0_0_t mca_backtrace_printstack_component = {
/* First, the mca_component_t struct containing meta information
about the component itself */
{
/* Indicate that we are a backtrace v1.0.0 component (which also
implies a specific MCA version) */
OPAL_BACKTRACE_BASE_VERSION_1_0_0,
/* Component name and version */
"printstack",
OPAL_MAJOR_VERSION,
OPAL_MINOR_VERSION,
OPAL_RELEASE_VERSION,
/* Component open and close functions */
NULL,
NULL
},
/* Next the MCA v1.0.0 component meta data */
{
/* Whether the component is checkpointable or not */
true
},
};

39
opal/mca/backtrace/printstack/configure.m4 Обычный файл
Просмотреть файл

@ -0,0 +1,39 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
# University Research and Technology
# Corporation. All rights reserved.
# Copyright (c) 2004-2005 The University of Tennessee and The University
# of Tennessee Research Foundation. All rights
# reserved.
# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
# University of Stuttgart. All rights reserved.
# Copyright (c) 2004-2005 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
AC_DEFUN([MCA_backtrace_printstack_COMPILE_MODE], [
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
$4="static"
AC_MSG_RESULT([$$4])
])
# MCA_backtrace_printstack_CONFIG(action-if-can-compile,
# [action-if-cant-compile])
# ------------------------------------------------
AC_DEFUN([MCA_backtrace_printstack_CONFIG],[
AC_CHECK_HEADERS([ucontext.h])
# FreeBSD has backtrace in -lexecinfo, usually in libc
AC_CHECK_FUNCS([printstack],
[backtrace_printstack_happy="yes"],
[backtrace_printstack_happy="no"])
AS_IF([test "$backtrace_printstack_happy" = "yes"],
[$1], [$2])
])

Просмотреть файл

@ -0,0 +1,15 @@
# -*- shell-script -*-
#
# Copyright (c) 2004-2006 The Regents of the University of California.
# All rights reserved.
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
#
# Specific to this module
PARAM_CONFIG_PRIORITY=30
PARAM_CONFIG_FILES="Makefile"

Просмотреть файл

@ -24,14 +24,6 @@
#include <unistd.h>
#endif
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#ifdef HAVE_UCONTEXT_H
#include <ucontext.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@ -42,6 +34,7 @@
#include "opal/util/stacktrace.h"
#include "opal/mca/base/mca_base_param.h"
#include "opal/mca/backtrace/backtrace.h"
#include "opal/constants.h"
#ifndef _NSIG
@ -67,12 +60,6 @@
#if OMPI_WANT_PRETTY_PRINT_STACKTRACE && ! defined(__WINDOWS__)
static void opal_show_stackframe (int signo, siginfo_t * info, void * p)
{
#ifdef HAVE_BACKTRACE
int i;
int trace_size;
void * trace[32];
char ** messages = (char **)NULL;
#endif
char print_buffer[1024];
char * tmp = print_buffer;
int size = sizeof (print_buffer);
@ -295,17 +282,7 @@ static void opal_show_stackframe (int signo, siginfo_t * info, void * p)
write(fileno(stderr), print_buffer, sizeof(print_buffer)-size);
fflush(stderr);
#ifdef HAVE_BACKTRACE
trace_size = backtrace (trace, 32);
messages = backtrace_symbols (trace, trace_size);
for (i = 0; i < trace_size; i++) {
fprintf(stderr, "[%d] func:%s\n", i, messages[i]);
fflush(stderr);
}
#elif defined(HAVE_PRINTSTACK)
printstack(fileno(stderr));
#endif
opal_backtrace_print(stderr);
write(fileno(stderr), eof_msg, sizeof(eof_msg));
fflush(stderr);