Last active
August 29, 2015 14:12
-
-
Save wancw/5919507003871603a6a9 to your computer and use it in GitHub Desktop.
Dump stack traces
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A helper function to dump backtrace in more accurate information | |
with helper script to translate dumped address to source code line. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import os | |
import re | |
import sys | |
from subprocess import PIPE, Popen | |
from Queue import Queue | |
def line_wrapper(line): | |
def _wrapper(): | |
return line | |
return _wrapper | |
def one_line_reader(out, prefix=''): | |
def _reader(): | |
return prefix + out.readline().strip(os.linesep) | |
return _reader | |
def create_atos_pipe(image_name): | |
args = ["xcrun", "atos", "-o", image_name, "-l", "0x100000000"] | |
return Popen(args, stdin=PIPE, stdout=PIPE) | |
trace_pattern = re.compile("^(\s+)(.+)\(.+\) \[(0x1[0-9a-f]+)\]$") | |
trace_address_not_found_pattern = re.compile("(\s+)(\?+) \[(0x[0-9a-f]+)\]$") | |
def translate(f): | |
pipes = {} | |
output_queue = Queue() | |
for line in f: | |
line = line.strip(os.linesep) | |
match = trace_pattern.match(line) | |
if not match: | |
unknown_match = trace_address_not_found_pattern.match(line) | |
output_queue.put(line_wrapper( | |
''.join(unknown_match.groups()[0:2]) if unknown_match | |
else line | |
)) | |
else: | |
prefix, image_name, address = match.groups() | |
if image_name not in pipes: | |
pipes[image_name] = create_atos_pipe(image_name) | |
atos_pipe = pipes[image_name] | |
atos_pipe.stdin.write('%s\n' % address) | |
output_queue.put(one_line_reader(atos_pipe.stdout, prefix)) | |
for atos_pipe in pipes.itervalues(): | |
atos_pipe.stdin.close() | |
while not output_queue.empty(): | |
print output_queue.get()() | |
if __name__ == '__main__': | |
if sys.platform != 'darwin': | |
print '%s: This script is only for Mac' % (sys.argv[0]) | |
exit(1) | |
translate(sys.stdin) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef STACK_TRACE_H | |
#define STACK_TRACE_H | |
#include <stdio.h> | |
/** | |
* dump_stack_trace() prints stack trace to `fp` as all binary image are loaded | |
* at 0x100000000. | |
* | |
* Add "-g" or "-gline-tables-only" to comipling options to dump more accurate | |
* stack trace. | |
*/ | |
void dump_stack_trace(FILE *fp = stderr, const unsigned short size = 64); | |
#endif // STACK_TRACE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <execinfo.h> | |
#include <dlfcn.h> | |
namespace { | |
Dl_info info; | |
} | |
void dump_stack_trace(FILE *fp, const unsigned short size) { | |
void *traces[size]; | |
int trace_count = backtrace(traces, size); | |
for (int i=1; i<trace_count; ++i) { | |
void *call_addr = traces[i]; | |
if (call_addr == 0 || dladdr(call_addr, &info) == 0) { | |
fprintf(fp, " ??? [0x%09lx]\n", reinterpret_cast<unsigned long>(call_addr)); | |
continue; | |
} | |
auto img_offset = reinterpret_cast<unsigned long>(call_addr) - reinterpret_cast<unsigned long>(info.dli_fbase); | |
auto sym_offset = reinterpret_cast<unsigned long>(call_addr) - reinterpret_cast<unsigned long>(info.dli_saddr); | |
fprintf(fp, " %s(%s+0x%02lx) [0x1%08lx]\n", info.dli_fname, info.dli_sname, sym_offset, img_offset); | |
} | |
fflush(fp); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment