Check point commit of backtrace frame handling
git-svn-id: https://plcrashreporter.googlecode.com/svn/trunk@115 25172300-ee46-11dd-abe2-393a09110dd0
This commit is contained in:
Родитель
92765187d0
Коммит
2377929cec
|
@ -59,11 +59,12 @@ message CrashReport {
|
|||
|
||||
/* Stack frame */
|
||||
message StackFrame {
|
||||
/* Nearest symbol name for the given PC. This may be inaccurate. */
|
||||
optional string symbol_name = 1;
|
||||
/* Nearest symbol name for the given PC. This may be inaccurate. This may not be the symbol name
|
||||
* for the code block containing the instruction pc.*/
|
||||
optional string nearest_symbol_name = 1;
|
||||
|
||||
/* Address of the named symbol, if one is available */
|
||||
optional uint64 symbol_address = 2;
|
||||
/* Address of the nearest named symbol, if one is available. */
|
||||
optional uint64 nearest_symbol_address = 2;
|
||||
|
||||
/* Instruction pointer */
|
||||
required uint64 pc = 3;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#import <errno.h>
|
||||
#import <string.h>
|
||||
#import <stdbool.h>
|
||||
#import <dlfcn.h>
|
||||
|
||||
#import <sys/time.h>
|
||||
|
||||
|
@ -48,16 +49,16 @@ enum {
|
|||
PLCRASH_PROTO_BACKTRACE_THREAD_NUMBER_ID = 1,
|
||||
|
||||
/** CrashReports.thread.frames */
|
||||
PLCRASH_PROTO_BACKTRACE_FRAMES = 2,
|
||||
PLCRASH_PROTO_BACKTRACE_FRAMES_ID = 2,
|
||||
|
||||
/** CrashReport.thread.frame.symbol_name */
|
||||
PLCRASH_PROTO_BACKTRACE_FRAME_SYMBOL_NAME = 1,
|
||||
PLCRASH_PROTO_BACKTRACE_FRAME_NEAREST_SYMBOL_NAME_ID = 1,
|
||||
|
||||
/** CrashReport.thread.frame.symbol_address */
|
||||
PLCRASH_PROTO_BACKTRACE_FRAME_SYMBOL_ADDRESS = 2,
|
||||
PLCRASH_PROTO_BACKTRACE_FRAME_NEAREST_SYMBOL_ADDRESS_ID = 2,
|
||||
|
||||
/** CrashReport.thread.frame.pc */
|
||||
PLCRASH_PROTO_BACKTRACE_FRAME_PC = 3
|
||||
PLCRASH_PROTO_BACKTRACE_FRAME_PC_ID = 3
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -109,18 +110,60 @@ size_t plcrash_writer_write_system_info (plasync_file_t *file, struct utsname *u
|
|||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Write a thread backtrace frame
|
||||
*
|
||||
* @param file Output file
|
||||
* @param cursor The cursor from which to acquire frame data.
|
||||
*/
|
||||
size_t plcrash_writer_write_backtrace_frame (plasync_file_t *file, plframe_cursor_t *cursor) {
|
||||
plframe_error_t err;
|
||||
uint64_t uint64val;
|
||||
Dl_info dlinfo;
|
||||
size_t rv = 0;
|
||||
|
||||
/* PC */
|
||||
plframe_word_t pc = 0;
|
||||
if ((err = plframe_get_reg(cursor, PLFRAME_REG_IP, &pc)) != PLFRAME_ESUCCESS) {
|
||||
PLCF_DEBUG("Could not retrieve frame PC register: %s", plframe_strerror(err));
|
||||
return 0;
|
||||
}
|
||||
uint64val = pc << 4;
|
||||
PLCF_DEBUG("Want to encode pc of val: %p (%llx %llx)", (void *) pc, uint64val, (uint64val << 4));
|
||||
|
||||
rv += plcrash_writer_pack(file, PLCRASH_PROTO_BACKTRACE_FRAME_PC_ID, PROTOBUF_C_TYPE_UINT64, &uint64val);
|
||||
|
||||
/* Attempt to fetch symbol data (not async-safe! usually OK) */
|
||||
if (dladdr((void *) pc, &dlinfo) != 0) {
|
||||
if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) {
|
||||
PLCF_DEBUG("Packing in a symbol name: %s", dlinfo.dli_sname);
|
||||
/* Write the name */
|
||||
rv += plcrash_writer_pack(file, PLCRASH_PROTO_BACKTRACE_FRAME_NEAREST_SYMBOL_NAME_ID, PROTOBUF_C_TYPE_STRING, dlinfo.dli_sname);
|
||||
|
||||
/* Write the address */
|
||||
uint64val = ((intptr_t) dlinfo.dli_saddr) << 4;
|
||||
rv += plcrash_writer_pack(file, PLCRASH_PROTO_BACKTRACE_FRAME_NEAREST_SYMBOL_ADDRESS_ID, PROTOBUF_C_TYPE_UINT64, &uint64val);
|
||||
} else {
|
||||
PLCF_DEBUG("Is NULL symbol");
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Write a thread state message
|
||||
* Write a thread backtrace message
|
||||
*
|
||||
* @param file Output file
|
||||
* @param thread Thread for which we'll output data.
|
||||
* @param crashctx Context to use for currently running thread (rather than fetching the thread
|
||||
* context, which we've invalidated by running at all)
|
||||
*/
|
||||
size_t plcrash_writer_write_thread (plasync_file_t *file, thread_t thread, uint32_t thread_number, ucontext_t *crashctx) {
|
||||
size_t plcrash_writer_write_backtrace (plasync_file_t *file, thread_t thread, uint32_t thread_number, ucontext_t *crashctx) {
|
||||
size_t rv = 0;
|
||||
plframe_cursor_t cursor;
|
||||
plframe_error_t ferr;
|
||||
|
@ -147,9 +190,15 @@ size_t plcrash_writer_write_thread (plasync_file_t *file, thread_t thread, uint3
|
|||
|
||||
/* Walk the stack */
|
||||
while ((ferr = plframe_cursor_next(&cursor)) == PLFRAME_ESUCCESS) {
|
||||
// TODO: Output the frame record
|
||||
uint32_t frame_size;
|
||||
|
||||
/* Determine the size */
|
||||
frame_size = plcrash_writer_write_backtrace_frame(NULL, &cursor);
|
||||
|
||||
rv += plcrash_writer_pack(file, PLCRASH_PROTO_BACKTRACE_FRAMES_ID, PROTOBUF_C_TYPE_MESSAGE, &frame_size);
|
||||
rv += plcrash_writer_write_backtrace_frame(file, &cursor);
|
||||
}
|
||||
|
||||
|
||||
/* Did we reach the end successfully? */
|
||||
if (ferr != PLFRAME_ENOFRAME)
|
||||
PLCF_DEBUG("Terminated stack walking early: %s", plframe_strerror(ferr));
|
||||
|
@ -220,11 +269,11 @@ plcrash_error_t plcrash_writer_report (plcrash_writer_t *writer, plasync_file_t
|
|||
}
|
||||
|
||||
/* Determine the size */
|
||||
size = plcrash_writer_write_thread(NULL, thread, i, crashctx);
|
||||
size = plcrash_writer_write_backtrace(NULL, thread, i, crashctx);
|
||||
|
||||
/* Write message */
|
||||
plcrash_writer_pack(file, PLCRASH_PROTO_BACKTRACES_ID, PROTOBUF_C_TYPE_MESSAGE, &size);
|
||||
plcrash_writer_write_thread(file, thread, i, crashctx);
|
||||
plcrash_writer_write_backtrace(file, thread, i, crashctx);
|
||||
|
||||
/* Resume the thread */
|
||||
if (suspend_thread)
|
||||
|
|
|
@ -40,10 +40,11 @@
|
|||
}
|
||||
|
||||
- (void) tearDown {
|
||||
NSError *error;
|
||||
//NSError *error;
|
||||
|
||||
/* Delete the file */
|
||||
STAssertTrue([[NSFileManager defaultManager] removeItemAtPath: _logPath error: &error], @"Could not remove log file");
|
||||
//STAssertTrue([[NSFileManager defaultManager] removeItemAtPath: _logPath error: &error], @"Could not remove log file");
|
||||
NSLog(@"Not deleting file at path %@", _logPath);
|
||||
[_logPath release];
|
||||
|
||||
/* Stop the test thread */
|
||||
|
@ -78,6 +79,19 @@
|
|||
STAssertNotNULL(bts, @"No thread messages were written");
|
||||
STAssertTrue(crashReport->n_backtraces > 0, @"0 thread messages were written");
|
||||
|
||||
NSLog(@"Number of backtraces: %d", crashReport->n_backtraces);
|
||||
for (int i = 0; i < crashReport->n_backtraces; i++) {
|
||||
Plcrash__CrashReport__Backtrace *bt = bts[i];
|
||||
|
||||
NSLog(@"\nBacktrace for thread ID: %d", bt->thread_number);
|
||||
|
||||
for (int j = 0; j < bt->n_frames; j++) {
|
||||
Plcrash__CrashReport__Backtrace__StackFrame *f = bt->frames[j];
|
||||
NSLog(@"Frame at pc %lx", f->pc);
|
||||
if (f->nearest_symbol_name != NULL)
|
||||
NSLog(@"Frame symbol %lx %p", f->pc, f->nearest_symbol_name);
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче