Adapting the stack-trace on Mac OS X. Got rid of a couple of nasty hacks
This commit is contained in:
parent
74bc4eacdf
commit
bb2113dfc5
2 changed files with 103 additions and 130 deletions
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Reference in a new issue