mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Stack trace improvements.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@24484 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
109c415048
commit
75b17ed3cc
2 changed files with 147 additions and 49 deletions
|
@ -1,9 +1,14 @@
|
|||
2007-02-06 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Documentation/manual/manual.texi: fix format errors
|
||||
* Source/NSException.m: control stack trace with environment variable
|
||||
* Headers/Foundation/NSException.h: document stack trace
|
||||
* Documentation/Base.gsdoc: document stack trace
|
||||
* Source/NSException.m: control stack trace with environment variable
|
||||
Rewrite module loading code to be thread safe.
|
||||
Use dladdr where available, to get offsets for dynamic library
|
||||
symbols so bfi based lookup of function/method name and line
|
||||
number information can work for libraries as well as the main
|
||||
executable.
|
||||
|
||||
2007-02-05 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
|
|
|
@ -34,9 +34,46 @@
|
|||
#include "Foundation/NSCoder.h"
|
||||
#include "Foundation/NSNull.h"
|
||||
#include "Foundation/NSThread.h"
|
||||
#include "Foundation/NSLock.h"
|
||||
#include "Foundation/NSDictionary.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
static NSString *
|
||||
GSPrivateBaseAddress(void *addr, void **base)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
#else /* __MINGW32__ */
|
||||
|
||||
#ifndef GNU_SOURCE
|
||||
#define GNU_SOURCE
|
||||
#endif
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <dlfcn.h>
|
||||
|
||||
static NSString *
|
||||
GSPrivateBaseAddress(void *addr, void **base)
|
||||
{
|
||||
#ifdef HAVE_DLADDR
|
||||
Dl_info info;
|
||||
|
||||
if (!dladdr(addr, &info))
|
||||
return nil;
|
||||
|
||||
*base = info.dli_fbase;
|
||||
|
||||
return [NSString stringWithUTF8String: info.dli_fname];
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
#endif /* __MINGW32__ */
|
||||
|
||||
|
||||
/* This is the GNU name for the CTOR list */
|
||||
|
||||
@interface GSStackTrace : NSObject
|
||||
{
|
||||
|
@ -107,14 +144,14 @@
|
|||
|
||||
@interface GSBinaryFileInfo : NSObject
|
||||
{
|
||||
NSString *_filename;
|
||||
NSString *_fileName;
|
||||
bfd *_abfd;
|
||||
asymbol **_symbols;
|
||||
long _symbolCount;
|
||||
}
|
||||
- (NSString *) filename;
|
||||
- (NSString *) fileName;
|
||||
- (GSFunctionInfo *) functionForAddress: (void*) address;
|
||||
- (id) initWithBinaryFile: (NSString *)filename;
|
||||
- (id) initWithBinaryFile: (NSString *)fileName;
|
||||
- (id) init; // return info for the current executing process
|
||||
|
||||
@end
|
||||
|
@ -142,7 +179,7 @@
|
|||
- (NSString *) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"(%@: %p) %@ %@: %d",
|
||||
[_module filename], _address, _functionName, _fileName, _lineNo];
|
||||
[_module fileName], _address, _functionName, _fileName, _lineNo];
|
||||
}
|
||||
|
||||
- (NSString *) fileName
|
||||
|
@ -192,9 +229,9 @@
|
|||
|
||||
@implementation GSBinaryFileInfo
|
||||
|
||||
+ (GSBinaryFileInfo*) infoWithBinaryFile: (NSString *)filename
|
||||
+ (GSBinaryFileInfo*) infoWithBinaryFile: (NSString *)fileName
|
||||
{
|
||||
return [[[self alloc] initWithBinaryFile: filename] autorelease];
|
||||
return [[[self alloc] initWithBinaryFile: fileName] autorelease];
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
|
@ -211,8 +248,8 @@
|
|||
|
||||
- (oneway void) dealloc
|
||||
{
|
||||
[_filename release];
|
||||
_filename = nil;
|
||||
[_fileName release];
|
||||
_fileName = nil;
|
||||
if (_abfd)
|
||||
{
|
||||
bfd_close (_abfd);
|
||||
|
@ -226,9 +263,9 @@
|
|||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) filename
|
||||
- (NSString *) fileName
|
||||
{
|
||||
return _filename;
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
|
@ -239,19 +276,19 @@
|
|||
return [self initWithBinaryFile: processName];
|
||||
}
|
||||
|
||||
- (id) initWithBinaryFile: (NSString *)filename
|
||||
- (id) initWithBinaryFile: (NSString *)fileName
|
||||
{
|
||||
int neededSpace;
|
||||
|
||||
// 1st initialize the bfd
|
||||
if ([filename length] == 0)
|
||||
if ([fileName length] == 0)
|
||||
{
|
||||
NSLog (@"GSBinaryFileInfo: No File");
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
_filename = [filename copy];
|
||||
_abfd = bfd_openr ([filename cString], NULL);
|
||||
_fileName = [fileName copy];
|
||||
_abfd = bfd_openr ([fileName cString], NULL);
|
||||
if (!_abfd)
|
||||
{
|
||||
NSLog (@"GSBinaryFileInfo: No Binary Info");
|
||||
|
@ -368,9 +405,12 @@ static void find_address (bfd *abfd, asection *section,
|
|||
|
||||
@end
|
||||
|
||||
static BOOL GSLoadModule(NSString *filename);
|
||||
static id GSLoadModule(NSString *fileName);
|
||||
|
||||
// this method automatically load the current process + GNUstep base & gui.
|
||||
/*
|
||||
* This method automatically load the current process + GNUstep base & gui.
|
||||
* Only call this when protected by modLock!!
|
||||
*/
|
||||
static NSMutableDictionary *
|
||||
GSGetStackModules()
|
||||
{
|
||||
|
@ -405,34 +445,57 @@ GSGetStackModules()
|
|||
return stackModules;
|
||||
}
|
||||
|
||||
static NSRecursiveLock *modLock = nil;
|
||||
|
||||
// initialize stack trace info
|
||||
static BOOL
|
||||
GSLoadModule(NSString *filename)
|
||||
static id
|
||||
GSLoadModule(NSString *fileName)
|
||||
{
|
||||
if ([filename length] > 0)
|
||||
GSBinaryFileInfo *module = nil;
|
||||
|
||||
if ([fileName length] > 0)
|
||||
{
|
||||
NSMutableDictionary *modules = GSGetStackModules();
|
||||
NSMutableDictionary *modules;
|
||||
|
||||
if ([modules objectForKey: filename] == nil)
|
||||
[modLock lock];
|
||||
modules = GSGetStackModules();
|
||||
module = [modules objectForKey: fileName];
|
||||
[modLock unlock];
|
||||
if (module == nil);
|
||||
{
|
||||
GSBinaryFileInfo *module;
|
||||
|
||||
module = [GSBinaryFileInfo infoWithBinaryFile: filename];
|
||||
if (module != nil)
|
||||
module = [GSBinaryFileInfo infoWithBinaryFile: fileName];
|
||||
if (module == nil)
|
||||
{
|
||||
[modules setObject: module forKey: filename];
|
||||
module = (id)[NSNull null];
|
||||
}
|
||||
[modLock lock];
|
||||
if ([modules objectForKey: fileName] == nil)
|
||||
{
|
||||
[modules setObject: module forKey: fileName];
|
||||
}
|
||||
else
|
||||
{
|
||||
[modules setObject: [NSNull null] forKey: filename];
|
||||
module = [modules objectForKey: fileName];
|
||||
}
|
||||
}
|
||||
if ([modules objectForKey: filename] != [NSNull null])
|
||||
{
|
||||
return YES;
|
||||
[modLock unlock];
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
if (module == (id)[NSNull null])
|
||||
{
|
||||
module = nil;
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
static NSArray*
|
||||
GSListModules()
|
||||
{
|
||||
NSArray *result;
|
||||
|
||||
[modLock lock];
|
||||
result = [GSGetStackModules() allValues];
|
||||
[modLock unlock];
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* STACKSYMBOLS */
|
||||
|
@ -488,38 +551,60 @@ GSLoadModule(NSString *filename)
|
|||
- (id) init
|
||||
{
|
||||
#if defined(STACKSYMBOLS)
|
||||
NSArray *modules;
|
||||
int i;
|
||||
int j;
|
||||
int n;
|
||||
int m;
|
||||
|
||||
frames = [[NSMutableArray alloc] init];
|
||||
modules = [GSGetStackModules() allValues];
|
||||
n = NSCountFrames();
|
||||
m = [modules count];
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
GSFunctionInfo *aFrame = nil;
|
||||
void *address = NSReturnAddress(i);
|
||||
void *base;
|
||||
NSString *modulePath = GSPrivateBaseAddress(address, &base);
|
||||
GSBinaryFileInfo *bfi;
|
||||
|
||||
for (j = 0; j < m; j++)
|
||||
{
|
||||
GSBinaryFileInfo *bfi = [modules objectAtIndex: j];
|
||||
|
||||
if ((id)bfi != (id)[NSNull null])
|
||||
if (modulePath != nil && (bfi = GSLoadModule(modulePath)) != nil)
|
||||
{
|
||||
aFrame = [bfi functionForAddress: (void*)(address - base)];
|
||||
if (aFrame == nil)
|
||||
{
|
||||
/* We know we have the right module be function lookup
|
||||
* failed ... perhaps we need to use the absolute
|
||||
* address rather than offest by 'base' in this case.
|
||||
*/
|
||||
aFrame = [bfi functionForAddress: address];
|
||||
if (aFrame)
|
||||
}
|
||||
if (aFrame == nil) NSLog(@"BFI base for %@ (%p) is %p", modulePath, address, base);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSArray *modules;
|
||||
int j;
|
||||
int m;
|
||||
|
||||
if (modulePath != nil) NSLog(@"BFI not found for %@ (%p)", modulePath, address);
|
||||
|
||||
modules = GSListModules();
|
||||
m = [modules count];
|
||||
for (j = 0; j < m; j++)
|
||||
{
|
||||
bfi = [modules objectAtIndex: j];
|
||||
|
||||
if ((id)bfi != (id)[NSNull null])
|
||||
{
|
||||
[frames addObject: aFrame];
|
||||
break;
|
||||
aFrame = [bfi functionForAddress: address];
|
||||
if (aFrame != nil)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not found (?!), add an 'unknown' function
|
||||
if (!aFrame)
|
||||
if (aFrame == nil)
|
||||
{
|
||||
aFrame = [GSFunctionInfo alloc];
|
||||
[aFrame initWithModule: nil
|
||||
|
@ -528,8 +613,8 @@ GSLoadModule(NSString *filename)
|
|||
function: nil
|
||||
line: 0];
|
||||
[aFrame autorelease];
|
||||
[frames addObject: aFrame];
|
||||
}
|
||||
[frames addObject: aFrame];
|
||||
}
|
||||
#else
|
||||
int i;
|
||||
|
@ -624,6 +709,14 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
|
|||
|
||||
@implementation NSException
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (modLock == nil)
|
||||
{
|
||||
modLock = [NSRecursiveLock new];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSException*) exceptionWithName: (NSString*)name
|
||||
reason: (NSString*)reason
|
||||
userInfo: (NSDictionary*)userInfo
|
||||
|
|
Loading…
Reference in a new issue