From 35237d135807af84bf9b0e5b8d7f8633e58db6f5 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Wed, 17 Dec 2008 18:08:08 -0800 Subject: Code drop from //branches/cupcake/...@124589 --- debuggerd/Android.mk | 4 ++++ debuggerd/unwind-arm.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- debuggerd/utility.c | 7 ++++++- debuggerd/utility.h | 2 +- 4 files changed, 54 insertions(+), 9 deletions(-) (limited to 'debuggerd') diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 03046bd..b22e1a8 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -1,5 +1,7 @@ # Copyright 2005 The Android Open Source Project +ifeq ($(TARGET_ARCH),arm) + LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -20,3 +22,5 @@ LOCAL_MODULE_TAGS := eng #LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_SHARED_LIBRARIES := libcutils libc include $(BUILD_EXECUTABLE) + +endif # TARGET_ARCH == arm diff --git a/debuggerd/unwind-arm.c b/debuggerd/unwind-arm.c index fdc0a6a..9642d2e 100644 --- a/debuggerd/unwind-arm.c +++ b/debuggerd/unwind-arm.c @@ -381,13 +381,15 @@ get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address, pid_t pid, } /* Print out the current call level, pc, and module name in the crash log */ -static _Unwind_Reason_Code log_function(_Unwind_Context *context, int tfd, +static _Unwind_Reason_Code log_function(_Unwind_Context *context, pid_t pid, + int tfd, int stack_level, mapinfo *map, unsigned int sp_list[], bool at_fault) { _uw pc; + _uw rel_pc; phase2_vrs *vrs = (phase2_vrs*) context; const mapinfo *mi; bool only_in_tombstone = !at_fault; @@ -404,19 +406,53 @@ static _Unwind_Reason_Code log_function(_Unwind_Context *context, int tfd, // For deeper framers, rollback pc by one instruction else { pc = vrs->core.r[R_PC]; - // Thumb mode + /* Thumb mode - need to check whether the bl(x) has long offset or not. + * Examples: + * + * arm blx in the middle of thumb: + * 187ae: 2300 movs r3, #0 + * 187b0: f7fe ee1c blx 173ec + * 187b4: 2c00 cmp r4, #0 + * + * arm bl in the middle of thumb: + * 187d8: 1c20 adds r0, r4, #0 + * 187da: f136 fd15 bl 14f208 + * 187de: 2800 cmp r0, #0 + * + * pure thumb: + * 18894: 189b adds r3, r3, r2 + * 18896: 4798 blx r3 + * 18898: b001 add sp, #4 + */ if (pc & 1) { - pc = (pc & ~1) - 2; + _uw prev_word; + pc = (pc & ~1); + prev_word = get_remote_word(pid, (void *) pc-4); + // Long offset + if ((prev_word & 0xf0000000) == 0xf0000000 && + (prev_word & 0x0000e000) == 0x0000e000) { + pc -= 4; + } + else { + pc -= 2; + } } else { pc -= 4; } } - mi = pc_to_mapinfo(map, pc); + /* We used to print the absolute PC in the back trace, and mask out the top + * 3 bits to guesstimate the offset in the .so file. This is not working for + * non-prelinked libraries since the starting offset may not be aligned on + * 1MB boundaries, and the library may be larger than 1MB. So for .so + * addresses we print the relative offset in back trace. + */ + rel_pc = pc; + mi = pc_to_mapinfo(map, pc, &rel_pc); _LOG(tfd, only_in_tombstone, - " #%02d pc %08x %s\n", stack_level, pc, + " #%02d pc %08x %s\n", stack_level, rel_pc, mi ? mi->name : ""); return _URC_NO_REASON; @@ -459,7 +495,7 @@ int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, */ if (get_eitp(saved_vrs.core.r[R_PC], pid, map, NULL) == NULL) { *frame0_pc_sane = 0; - log_function ((_Unwind_Context *) &saved_vrs, tfd, stack_level, + log_function ((_Unwind_Context *) &saved_vrs, pid, tfd, stack_level, map, sp_list, at_fault); saved_vrs.core.r[R_PC] = saved_vrs.core.r[R_LR]; stack_level++; @@ -493,7 +529,7 @@ int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp); /* Call log function. */ - if (log_function ((_Unwind_Context *) &saved_vrs, tfd, stack_level, + if (log_function ((_Unwind_Context *) &saved_vrs, pid, tfd, stack_level, map, sp_list, at_fault) != _URC_NO_REASON) { code = _URC_FAILURE; break; diff --git a/debuggerd/utility.c b/debuggerd/utility.c index 0cb790f..8f3931c 100644 --- a/debuggerd/utility.c +++ b/debuggerd/utility.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "utility.h" @@ -66,10 +67,14 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def) } /* Find the containing map info for the pc */ -const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc) +const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc) { while(mi) { if((pc >= mi->start) && (pc < mi->end)){ + // Only calculate the relative offset for shared libraries + if (strstr(mi->name, ".so")) { + *rel_pc = pc - mi->start; + } return mi; } mi = mi->next; diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 802e3ad..49f5951 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -45,7 +45,7 @@ extern int get_remote_word(int pid, void *src); extern void get_remote_struct(int pid, void *src, void *dst, size_t size); /* Find the containing map for the pc */ -const mapinfo *pc_to_mapinfo (mapinfo *mi, unsigned pc); +const mapinfo *pc_to_mapinfo (mapinfo *mi, unsigned pc, unsigned *rel_pc); /* Map a pc address to the name of the containing ELF file */ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def); -- cgit v1.1