Adapting the stack-trace on Mac OS X. Got rid of a couple of nasty hacks

This commit is contained in:
Bernhard F.W. Gschaider 2014-02-21 21:22:46 +01:00
parent 74bc4eacdf
commit bb2113dfc5
2 changed files with 103 additions and 130 deletions

View file

@ -4,27 +4,46 @@ import sys
filename=sys.argv[1] filename=sys.argv[1]
address=sys.argv[2] address=sys.argv[2]
import re import re
from os import environ,path
import subprocess fullFile=None
if path.exists(filename):
fullFile=filename
p = subprocess.Popen("gdb -batch -x /dev/stdin", for v in ["PATH","LD_LIBRARY_PATH"]:
shell=True, if not fullFile:
bufsize=0, for d in environ[v].split(':'):
stdin=subprocess.PIPE, if path.exists(path.join(d,filename)):
stdout=subprocess.PIPE, fullFile=path.join(d,filename)
close_fds=True) break
(child_stdin, child_stdout) = (p.stdin, p.stdout) if not fullFile:
child_stdin.write("set sharedlibrary preload-libraries no\n") fullFile=filename
child_stdin.write("file "+filename+"\n")
child_stdin.write("info line *"+address+"\n")
result=child_stdout.readline()
answer="??:0" answer="??:0"
match=re.compile('Line (.+) of "(.+)" starts at').match(result) if path.exists(fullFile):
if match: import subprocess
answer=match.group(2)+":"+match.group(1)
result=subprocess.Popen(["xcrun", "atos",
"-o",fullFile,
address],
stdout=subprocess.PIPE
).communicate()[0]
match=re.compile('.+ \((.+)\) \((.+)\)').match(result)
if match:
answer=match.group(2)+" "+match.group(1)
else:
import os
result=subprocess.Popen(["xcrun", "atos",
"-p",str(os.getppid()),
address],
stdout=subprocess.PIPE
).communicate()[0]
match=re.compile('.+ \((.+)\) \((.+)\)').match(result)
if match:
answer=match.group(2)+" "+match.group(1)
print answer, print answer,
sys.exit(255) sys.exit(255)

View file

@ -31,10 +31,13 @@ License
#include "readHexLabel.H" #include "readHexLabel.H"
#include <cxxabi.h> #include <cxxabi.h>
#ifndef darwin
#include <execinfo.h> #include <execinfo.h>
#endif
#include <dlfcn.h> #include <dlfcn.h>
#include <string.h>
#ifdef darwin
#include <mach-o/dyld.h>
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -126,14 +129,17 @@ void printSourceFileAndLine
myAddress = nStream.str(); myAddress = nStream.str();
} }
#ifndef darwin
if (filename[0] == '/') if (filename[0] == '/')
#else
if (1)
#endif
{ {
string line = pOpen string line = pOpen
( (
#ifndef darwin #ifndef darwin
"addr2line -f --demangle=auto --exe " "addr2line -f --demangle=auto --exe "
#else #else
// "gaddr2line -f --inline --demangle=auto --exe "
"addr2line4Mac.py " "addr2line4Mac.py "
#endif #endif
+ filename + filename
@ -144,119 +150,22 @@ void printSourceFileAndLine
if (line == "") if (line == "")
{ {
os << " addr2line failed"; os << " addr2line failed";
} }
else if (line == "??:0") else if (line == "??:0")
{ {
os << " in " << filename; os << " in " << filename;
} }
else else
{ {
string cwdLine(line.replaceAll(cwd() + '/', "")); string cwdLine(line.replaceAll(cwd() + '/', ""));
string homeLine(cwdLine.replaceAll(home(), '~')); string homeLine(cwdLine.replaceAll(home(), '~'));
os << " at " << homeLine.c_str(); os << " at " << homeLine.c_str();
} }
} }
} }
#ifdef darwin
// Trying to emulate the original backtrace and backtrace_symbol from the glibc
// After an idea published by Rush Manbert at http://lists.apple.com/archives/xcode-users/2006/Apr/msg00528.html
template<int level>
void *getStackAddress()
{
const unsigned int stackLevel=level;
return (
__builtin_frame_address(level)
? __builtin_return_address(stackLevel)
: (void *)0
);
};
#define GET_STACK_ADDRESS(lvl) \
case lvl: {return getStackAddress<lvl>(); break; }
// please don't laugh. For some reason this is necessary (the compiler won't accept it otherwise)
void *getStackAddress(int level)
{
switch(level) {
GET_STACK_ADDRESS(0);
GET_STACK_ADDRESS(1);
GET_STACK_ADDRESS(2);
GET_STACK_ADDRESS(3);
GET_STACK_ADDRESS(4);
GET_STACK_ADDRESS(5);
GET_STACK_ADDRESS(6);
GET_STACK_ADDRESS(7);
GET_STACK_ADDRESS(8);
GET_STACK_ADDRESS(9);
GET_STACK_ADDRESS(10);
GET_STACK_ADDRESS(11);
GET_STACK_ADDRESS(12);
GET_STACK_ADDRESS(13);
GET_STACK_ADDRESS(14);
GET_STACK_ADDRESS(15);
GET_STACK_ADDRESS(16);
GET_STACK_ADDRESS(17);
GET_STACK_ADDRESS(18);
GET_STACK_ADDRESS(19);
GET_STACK_ADDRESS(20);
GET_STACK_ADDRESS(21);
default:
return (void *)0;
break;
}
}
unsigned backtrace(void **bt, unsigned maxAddrs)
{
unsigned valid=0;
bool ok=true;
for(int level=0;level<maxAddrs;level++) {
if(ok) {
bt[level]=getStackAddress(level);
if(bt[level]!=(void *)0) {
valid=level;
} else {
ok=false;
}
} else {
bt[level]=(void *)0;
}
}
return valid;
}
// This function is a potential memory leak. But I don't care because the program is terminating anyway
char **backtrace_symbols(void **bt,unsigned nr)
{
char **strings=(char **)malloc(sizeof(char *)*nr);
for(unsigned i=0;i<nr;i++) {
Dl_info info;
int result=dladdr(bt[i],&info);
char tmp[1000];
#ifdef darwinIntel64
sprintf(tmp,"%s(%s+%p) [%p]",info.dli_fname,info.dli_sname,(void *)((unsigned long)bt[i]-(unsigned long)info.dli_saddr),bt[i]);
#else
sprintf(tmp,"%s(%s+%p) [%p]",info.dli_fname,info.dli_sname,(void *)((unsigned int)bt[i]-(unsigned int)info.dli_saddr),bt[i]);
#endif
strings[i]=(char *)malloc(strlen(tmp)+1);
strcpy(strings[i],tmp);
}
return strings;
}
#endif
void getSymbolForRaw void getSymbolForRaw
( (
@ -273,7 +182,6 @@ void getSymbolForRaw
#ifndef darwin #ifndef darwin
"addr2line -f --demangle=auto --exe " "addr2line -f --demangle=auto --exe "
#else #else
// "gaddr2line -f --inline --demangle=auto --exe "
"addr2line4Mac.py " "addr2line4Mac.py "
#endif #endif
+ filename + filename
@ -283,11 +191,11 @@ void getSymbolForRaw
if (fcnt != "") if (fcnt != "")
{ {
os << fcnt.c_str(); os << fcnt.c_str();
return; return;
} }
} }
os << "Uninterpreted: " << raw.c_str(); os << "Uninterpreted: " << raw.c_str();
} }
void error::printStack(Ostream& os) void error::printStack(Ostream& os)
@ -308,7 +216,7 @@ void error::printStack(Ostream& os)
{ {
IFstream is("/proc/" + name(pid()) + "/maps"); IFstream is("/proc/" + name(pid()) + "/maps");
while(is.good()) while (is.good())
{ {
string line; string line;
is.getLine(line); is.getLine(line);
@ -340,13 +248,14 @@ void error::printStack(Ostream& os)
fileName programFile; fileName programFile;
word address; word address;
os << '#' << label(i) << " "; os << '#' << label(i) << " ";
//os << "Raw : " << msg << "\n\t"; //os << "Raw : " << msg << "\n\t";
#ifndef darwin
{ {
string::size_type lPos = msg.find('['); string::size_type lPos = msg.find('[');
string::size_type rPos = msg.find(']'); string::size_type rPos = msg.find(']');
if (lPos != string::npos && rPos != string::npos && lPos<rPos) if (lPos != string::npos && rPos != string::npos && lPos < rPos)
{ {
address = msg.substr(lPos+1, rPos-lPos-1); address = msg.substr(lPos+1, rPos-lPos-1);
msg = msg.substr(0, lPos); msg = msg.substr(0, lPos);
@ -371,7 +280,38 @@ void error::printStack(Ostream& os)
} }
string::size_type bracketPos = msg.find('('); string::size_type bracketPos = msg.find('(');
#else
string::size_type counter=0;
while(msg[counter]!=' ') {
counter++;
}
while(msg[counter]==' ') {
counter++;
}
string::size_type fileStart=counter;
while(msg[counter]!=' ') {
counter++;
}
programFile = msg.substr(fileStart,counter-fileStart);
if(programFile=="???") {
char path[1024];
uint32_t size = sizeof(path);
if (_NSGetExecutablePath(path, &size) == 0) {
programFile=path;
} else {
programFile="unknownFile";
}
}
while(msg[counter]==' ') {
counter++;
}
string::size_type addrStart=counter;
while(msg[counter]!=' ') {
counter++;
}
address = msg.substr(addrStart,counter-addrStart);
#endif
#ifndef darwin
if (bracketPos != string::npos) if (bracketPos != string::npos)
{ {
string::size_type start = bracketPos+1; string::size_type start = bracketPos+1;
@ -381,7 +321,21 @@ void error::printStack(Ostream& os)
if (plusPos != string::npos) if (plusPos != string::npos)
{ {
string cName(msg.substr(start, plusPos-start)); string cName(msg.substr(start, plusPos-start));
#else
if(1){
while(msg[counter]==' ') {
counter++;
}
string::size_type nameStart=counter;
while(msg[counter]!=' ') {
counter++;
}
string::size_type start = counter;
if(1) {
string cName(msg.substr(nameStart,counter-nameStart));
#endif
int status; int status;
char* cplusNamePtr = abi::__cxa_demangle char* cplusNamePtr = abi::__cxa_demangle
( (
@ -393,12 +347,12 @@ void error::printStack(Ostream& os)
if (status == 0 && cplusNamePtr) if (status == 0 && cplusNamePtr)
{ {
os << cplusNamePtr; os << cplusNamePtr;
free(cplusNamePtr); free(cplusNamePtr);
} }
else else
{ {
os << cName.c_str(); os << cName.c_str();
} }
} }
else else
@ -409,7 +363,7 @@ void error::printStack(Ostream& os)
{ {
string fullName(msg.substr(start, endBracketPos-start)); string fullName(msg.substr(start, endBracketPos-start));
os << fullName.c_str() << nl; os << fullName.c_str() << nl;
} }
else else
{ {
@ -426,7 +380,7 @@ void error::printStack(Ostream& os)
printSourceFileAndLine(os, addressMap, programFile, address); printSourceFileAndLine(os, addressMap, programFile, address);
os << nl; os << nl;
} }
free(strings); free(strings);