| /* ARM EABI compliant unwinding routines. |
| Copyright (C) 2004, 2005 Free Software Foundation, Inc. |
| Contributed by Paul Brook |
| |
| This file is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by the |
| Free Software Foundation; either version 2, or (at your option) any |
| later version. |
| |
| In addition to the permissions in the GNU General Public License, the |
| Free Software Foundation gives you unlimited permission to link the |
| compiled version of this file into combinations with other programs, |
| and to distribute those combinations without any restriction coming |
| from the use of this file. (The General Public License restrictions |
| do apply in other respects; for example, they cover modification of |
| the file, and distribution when not linked into a combine |
| executable.) |
| |
| This file is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; see the file COPYING. If not, write to |
| the Free Software Foundation, 51 Franklin Street, Fifth Floor, |
| Boston, MA 02110-1301, USA. */ |
| |
| /**************************************************************************** |
| * The functions here are derived from gcc/config/arm/unwind-arm.c from the |
| * 4.3.x release. The main changes here involve the use of ptrace to retrieve |
| * memory/processor states from a remote process. |
| ****************************************************************************/ |
| |
| #include <cutils/logd.h> |
| #include <sys/ptrace.h> |
| #include <unwind.h> |
| #include "utility.h" |
| |
| typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */ |
| |
| void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp); |
| bool __attribute__((weak)) __cxa_begin_cleanup(_Unwind_Control_Block *ucbp); |
| bool __attribute__((weak)) __cxa_type_match(_Unwind_Control_Block *ucbp, |
| const type_info *rttip, |
| bool is_reference, |
| void **matched_object); |
| |
| /* Misc constants. */ |
| #define R_IP 12 |
| #define R_SP 13 |
| #define R_LR 14 |
| #define R_PC 15 |
| |
| #define EXIDX_CANTUNWIND 1 |
| #define uint32_highbit (((_uw) 1) << 31) |
| |
| #define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1) |
| #define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2) |
| #define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3) |
| #define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4) |
| |
| struct core_regs |
| { |
| _uw r[16]; |
| }; |
| |
| /* We use normal integer types here to avoid the compiler generating |
| coprocessor instructions. */ |
| struct vfp_regs |
| { |
| _uw64 d[16]; |
| _uw pad; |
| }; |
| |
| struct vfpv3_regs |
| { |
| /* Always populated via VSTM, so no need for the "pad" field from |
| vfp_regs (which is used to store the format word for FSTMX). */ |
| _uw64 d[16]; |
| }; |
| |
| struct fpa_reg |
| { |
| _uw w[3]; |
| }; |
| |
| struct fpa_regs |
| { |
| struct fpa_reg f[8]; |
| }; |
| |
| struct wmmxd_regs |
| { |
| _uw64 wd[16]; |
| }; |
| |
| struct wmmxc_regs |
| { |
| _uw wc[4]; |
| }; |
| |
| /* Unwind descriptors. */ |
| |
| typedef struct |
| { |
| _uw16 length; |
| _uw16 offset; |
| } EHT16; |
| |
| typedef struct |
| { |
| _uw length; |
| _uw offset; |
| } EHT32; |
| |
| /* The ABI specifies that the unwind routines may only use core registers, |
| except when actually manipulating coprocessor state. This allows |
| us to write one implementation that works on all platforms by |
| demand-saving coprocessor registers. |
| |
| During unwinding we hold the coprocessor state in the actual hardware |
| registers and allocate demand-save areas for use during phase1 |
| unwinding. */ |
| |
| typedef struct |
| { |
| /* The first fields must be the same as a phase2_vrs. */ |
| _uw demand_save_flags; |
| struct core_regs core; |
| _uw prev_sp; /* Only valid during forced unwinding. */ |
| struct vfp_regs vfp; |
| struct vfpv3_regs vfp_regs_16_to_31; |
| struct fpa_regs fpa; |
| struct wmmxd_regs wmmxd; |
| struct wmmxc_regs wmmxc; |
| } phase1_vrs; |
| |
| /* This must match the structure created by the assembly wrappers. */ |
| typedef struct |
| { |
| _uw demand_save_flags; |
| struct core_regs core; |
| } phase2_vrs; |
| |
| |
| /* An exception index table entry. */ |
| |
| typedef struct __EIT_entry |
| { |
| _uw fnoffset; |
| _uw content; |
| } __EIT_entry; |
| |
| /* Derived version to use ptrace */ |
| typedef _Unwind_Reason_Code (*personality_routine_with_ptrace) |
| (_Unwind_State, |
| _Unwind_Control_Block *, |
| _Unwind_Context *, |
| pid_t); |
| |
| /* Derived version to use ptrace */ |
| /* ABI defined personality routines. */ |
| static _Unwind_Reason_Code unwind_cpp_pr0_with_ptrace (_Unwind_State, |
| _Unwind_Control_Block *, _Unwind_Context *, pid_t); |
| static _Unwind_Reason_Code unwind_cpp_pr1_with_ptrace (_Unwind_State, |
| _Unwind_Control_Block *, _Unwind_Context *, pid_t); |
| static _Unwind_Reason_Code unwind_cpp_pr2_with_ptrace (_Unwind_State, |
| _Unwind_Control_Block *, _Unwind_Context *, pid_t); |
| |
| /* Execute the unwinding instructions described by UWS. */ |
| extern _Unwind_Reason_Code |
| unwind_execute_with_ptrace(_Unwind_Context * context, __gnu_unwind_state * uws, |
| pid_t pid); |
| |
| /* Derived version to use ptrace. Only handles core registers. Disregards |
| * FP and others. |
| */ |
| /* ABI defined function to pop registers off the stack. */ |
| |
| _Unwind_VRS_Result unwind_VRS_Pop_with_ptrace (_Unwind_Context *context, |
| _Unwind_VRS_RegClass regclass, |
| _uw discriminator, |
| _Unwind_VRS_DataRepresentation representation, |
| pid_t pid) |
| { |
| phase1_vrs *vrs = (phase1_vrs *) context; |
| |
| switch (regclass) |
| { |
| case _UVRSC_CORE: |
| { |
| _uw *ptr; |
| _uw mask; |
| int i; |
| |
| if (representation != _UVRSD_UINT32) |
| return _UVRSR_FAILED; |
| |
| mask = discriminator & 0xffff; |
| ptr = (_uw *) vrs->core.r[R_SP]; |
| /* Pop the requested registers. */ |
| for (i = 0; i < 16; i++) |
| { |
| if (mask & (1 << i)) { |
| vrs->core.r[i] = get_remote_word(pid, ptr); |
| ptr++; |
| } |
| } |
| /* Writeback the stack pointer value if it wasn't restored. */ |
| if ((mask & (1 << R_SP)) == 0) |
| vrs->core.r[R_SP] = (_uw) ptr; |
| } |
| return _UVRSR_OK; |
| |
| default: |
| return _UVRSR_FAILED; |
| } |
| } |
| |
| /* Core unwinding functions. */ |
| |
| /* Calculate the address encoded by a 31-bit self-relative offset at address |
| P. */ |
| static inline _uw |
| selfrel_offset31 (const _uw *p, pid_t pid) |
| { |
| _uw offset = get_remote_word(pid, (void*)p); |
| |
| //offset = *p; |
| /* Sign extend to 32 bits. */ |
| if (offset & (1 << 30)) |
| offset |= 1u << 31; |
| else |
| offset &= ~(1u << 31); |
| |
| return offset + (_uw) p; |
| } |
| |
| |
| /* Perform a binary search for RETURN_ADDRESS in TABLE. The table contains |
| NREC entries. */ |
| |
| static const __EIT_entry * |
| search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address, |
| pid_t pid) |
| { |
| _uw next_fn; |
| _uw this_fn; |
| int n, left, right; |
| |
| if (nrec == 0) |
| return (__EIT_entry *) 0; |
| |
| left = 0; |
| right = nrec - 1; |
| |
| while (1) |
| { |
| n = (left + right) / 2; |
| this_fn = selfrel_offset31 (&table[n].fnoffset, pid); |
| if (n != nrec - 1) |
| next_fn = selfrel_offset31 (&table[n + 1].fnoffset, pid) - 1; |
| else |
| next_fn = (_uw)0 - 1; |
| |
| if (return_address < this_fn) |
| { |
| if (n == left) |
| return (__EIT_entry *) 0; |
| right = n - 1; |
| } |
| else if (return_address <= next_fn) |
| return &table[n]; |
| else |
| left = n + 1; |
| } |
| } |
| |
| /* Find the exception index table eintry for the given address. */ |
| static const __EIT_entry* |
| get_eitp(_uw return_address, pid_t pid, mapinfo *map, mapinfo **containing_map) |
| { |
| const __EIT_entry *eitp = NULL; |
| int nrec; |
| mapinfo *mi; |
| |
| /* The return address is the address of the instruction following the |
| call instruction (plus one in thumb mode). If this was the last |
| instruction in the function the address will lie in the following |
| function. Subtract 2 from the address so that it points within the call |
| instruction itself. */ |
| if (return_address >= 2) |
| return_address -= 2; |
| |
| for (mi = map; mi != NULL; mi = mi->next) { |
| if (return_address >= mi->start && return_address <= mi->end) break; |
| } |
| |
| if (mi) { |
| if (containing_map) *containing_map = mi; |
| eitp = (__EIT_entry *) mi->exidx_start; |
| nrec = (mi->exidx_end - mi->exidx_start)/sizeof(__EIT_entry); |
| eitp = search_EIT_table (eitp, nrec, return_address, pid); |
| } |
| return eitp; |
| } |
| |
| /* Find the exception index table eintry for the given address. |
| Fill in the relevant fields of the UCB. |
| Returns _URC_FAILURE if an error occurred, _URC_OK on success. */ |
| |
| static _Unwind_Reason_Code |
| get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address, pid_t pid, |
| mapinfo *map, mapinfo **containing_map) |
| { |
| const __EIT_entry *eitp; |
| |
| eitp = get_eitp(return_address, pid, map, containing_map); |
| |
| if (!eitp) |
| { |
| UCB_PR_ADDR (ucbp) = 0; |
| return _URC_FAILURE; |
| } |
| ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset, pid); |
| |
| _uw eitp_content = get_remote_word(pid, (void *)&eitp->content); |
| |
| /* Can this frame be unwound at all? */ |
| if (eitp_content == EXIDX_CANTUNWIND) |
| { |
| UCB_PR_ADDR (ucbp) = 0; |
| return _URC_END_OF_STACK; |
| } |
| |
| /* Obtain the address of the "real" __EHT_Header word. */ |
| |
| if (eitp_content & uint32_highbit) |
| { |
| /* It is immediate data. */ |
| ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content; |
| ucbp->pr_cache.additional = 1; |
| } |
| else |
| { |
| /* The low 31 bits of the content field are a self-relative |
| offset to an _Unwind_EHT_Entry structure. */ |
| ucbp->pr_cache.ehtp = |
| (_Unwind_EHT_Header *) selfrel_offset31 (&eitp->content, pid); |
| ucbp->pr_cache.additional = 0; |
| } |
| |
| /* Discover the personality routine address. */ |
| if (get_remote_word(pid, ucbp->pr_cache.ehtp) & (1u << 31)) |
| { |
| /* One of the predefined standard routines. */ |
| _uw idx = (get_remote_word(pid, ucbp->pr_cache.ehtp) >> 24) & 0xf; |
| if (idx == 0) |
| UCB_PR_ADDR (ucbp) = (_uw) &unwind_cpp_pr0_with_ptrace; |
| else if (idx == 1) |
| UCB_PR_ADDR (ucbp) = (_uw) &unwind_cpp_pr1_with_ptrace; |
| else if (idx == 2) |
| UCB_PR_ADDR (ucbp) = (_uw) &unwind_cpp_pr2_with_ptrace; |
| else |
| { /* Failed */ |
| UCB_PR_ADDR (ucbp) = 0; |
| return _URC_FAILURE; |
| } |
| } |
| else |
| { |
| /* Execute region offset to PR */ |
| UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp, pid); |
| /* Since we are unwinding the stack from a different process, it is |
| * impossible to execute the personality routine in debuggerd. Punt here. |
| */ |
| return _URC_FAILURE; |
| } |
| return _URC_OK; |
| } |
| |
| /* Print out the current call level, pc, and module name in the crash log */ |
| 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; |
| |
| if (stack_level < STACK_CONTENT_DEPTH) { |
| sp_list[stack_level] = vrs->core.r[R_SP]; |
| } |
| pc = vrs->core.r[R_PC]; |
| |
| // Top level frame |
| if (stack_level == 0) { |
| pc &= ~1; |
| } |
| // For deeper framers, rollback pc by one instruction |
| else { |
| pc = vrs->core.r[R_PC]; |
| /* 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) { |
| _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; |
| } |
| } |
| |
| /* 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, rel_pc, |
| mi ? mi->name : ""); |
| |
| return _URC_NO_REASON; |
| } |
| |
| /* Derived from __gnu_Unwind_Backtrace to use ptrace */ |
| /* Perform stack backtrace through unwind data. Return the level of stack it |
| * unwinds. |
| */ |
| int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, |
| unsigned int sp_list[], int *frame0_pc_sane, |
| bool at_fault) |
| { |
| phase1_vrs saved_vrs; |
| _Unwind_Reason_Code code = _URC_OK; |
| struct pt_regs r; |
| int i; |
| int stack_level = 0; |
| |
| _Unwind_Control_Block ucb; |
| _Unwind_Control_Block *ucbp = &ucb; |
| |
| if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return 0; |
| |
| for (i = 0; i < 16; i++) { |
| saved_vrs.core.r[i] = r.uregs[i]; |
| /* |
| _LOG(tfd, "r[%d] = 0x%x\n", i, saved_vrs.core.r[i]); |
| */ |
| } |
| |
| /* Set demand-save flags. */ |
| saved_vrs.demand_save_flags = ~(_uw) 0; |
| |
| /* |
| * If the app crashes because of calling the weeds, we cannot pass the PC |
| * to the usual unwinding code as the EXIDX mapping will fail. |
| * Instead, we simply print out the 0 as the top frame, and resume the |
| * unwinding process with the value stored in LR. |
| */ |
| if (get_eitp(saved_vrs.core.r[R_PC], pid, map, NULL) == NULL) { |
| *frame0_pc_sane = 0; |
| 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++; |
| } |
| |
| do { |
| mapinfo *this_map = NULL; |
| /* Find the entry for this routine. */ |
| if (get_eit_entry(ucbp, saved_vrs.core.r[R_PC], pid, map, &this_map) |
| != _URC_OK) { |
| /* Uncomment the code below to study why the unwinder failed */ |
| #if 0 |
| /* Shed more debugging info for stack unwinder improvement */ |
| if (this_map) { |
| _LOG(tfd, 1, |
| "Relative PC=%#x from %s not contained in EXIDX\n", |
| saved_vrs.core.r[R_PC] - this_map->start, this_map->name); |
| } |
| _LOG(tfd, 1, "PC=%#x SP=%#x\n", |
| saved_vrs.core.r[R_PC], saved_vrs.core.r[R_SP]); |
| #endif |
| code = _URC_FAILURE; |
| break; |
| } |
| |
| /* The dwarf unwinder assumes the context structure holds things |
| like the function and LSDA pointers. The ARM implementation |
| caches these in the exception header (UCB). To avoid |
| rewriting everything we make the virtual IP register point at |
| the UCB. */ |
| _Unwind_SetGR((_Unwind_Context *)&saved_vrs, 12, (_Unwind_Ptr) ucbp); |
| |
| /* Call log function. */ |
| if (log_function ((_Unwind_Context *) &saved_vrs, pid, tfd, stack_level, |
| map, sp_list, at_fault) != _URC_NO_REASON) { |
| code = _URC_FAILURE; |
| break; |
| } |
| stack_level++; |
| |
| /* Call the pr to decide what to do. */ |
| code = ((personality_routine_with_ptrace) UCB_PR_ADDR (ucbp))( |
| _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, ucbp, |
| (void *) &saved_vrs, pid); |
| /* |
| * In theory the unwinding process will stop when the end of stack is |
| * reached or there is no unwinding information for the code address. |
| * To add another level of guarantee that the unwinding process |
| * will terminate we will stop it when the STACK_CONTENT_DEPTH is reached. |
| */ |
| } while (code != _URC_END_OF_STACK && code != _URC_FAILURE && |
| stack_level < STACK_CONTENT_DEPTH); |
| return stack_level; |
| } |
| |
| |
| /* Derived version to use ptrace */ |
| /* Common implementation for ARM ABI defined personality routines. |
| ID is the index of the personality routine, other arguments are as defined |
| by __aeabi_unwind_cpp_pr{0,1,2}. */ |
| |
| static _Unwind_Reason_Code |
| unwind_pr_common_with_ptrace (_Unwind_State state, |
| _Unwind_Control_Block *ucbp, |
| _Unwind_Context *context, |
| int id, |
| pid_t pid) |
| { |
| __gnu_unwind_state uws; |
| _uw *data; |
| int phase2_call_unexpected_after_unwind = 0; |
| |
| state &= _US_ACTION_MASK; |
| |
| data = (_uw *) ucbp->pr_cache.ehtp; |
| uws.data = get_remote_word(pid, data); |
| data++; |
| uws.next = data; |
| if (id == 0) |
| { |
| uws.data <<= 8; |
| uws.words_left = 0; |
| uws.bytes_left = 3; |
| } |
| else |
| { |
| uws.words_left = (uws.data >> 16) & 0xff; |
| uws.data <<= 16; |
| uws.bytes_left = 2; |
| data += uws.words_left; |
| } |
| |
| /* Restore the saved pointer. */ |
| if (state == _US_UNWIND_FRAME_RESUME) |
| data = (_uw *) ucbp->cleanup_cache.bitpattern[0]; |
| |
| if ((ucbp->pr_cache.additional & 1) == 0) |
| { |
| /* Process descriptors. */ |
| while (get_remote_word(pid, data)) { |
| /********************************************************************** |
| * The original code here seems to deal with exceptions that are not |
| * applicable in our toolchain, thus there is no way to test it for now. |
| * Instead of leaving it here and causing potential instability in |
| * debuggerd, we'd better punt here and leave the stack unwound. |
| * In the future when we discover cases where the stack should be unwound |
| * further but is not, we can revisit the code here. |
| **********************************************************************/ |
| return _URC_FAILURE; |
| } |
| /* Finished processing this descriptor. */ |
| } |
| |
| if (unwind_execute_with_ptrace (context, &uws, pid) != _URC_OK) |
| return _URC_FAILURE; |
| |
| if (phase2_call_unexpected_after_unwind) |
| { |
| /* Enter __cxa_unexpected as if called from the call site. */ |
| _Unwind_SetGR (context, R_LR, _Unwind_GetGR (context, R_PC)); |
| _Unwind_SetGR (context, R_PC, (_uw) &__cxa_call_unexpected); |
| return _URC_INSTALL_CONTEXT; |
| } |
| |
| return _URC_CONTINUE_UNWIND; |
| } |
| |
| |
| /* ABI defined personality routine entry points. */ |
| |
| static _Unwind_Reason_Code |
| unwind_cpp_pr0_with_ptrace (_Unwind_State state, |
| _Unwind_Control_Block *ucbp, |
| _Unwind_Context *context, |
| pid_t pid) |
| { |
| return unwind_pr_common_with_ptrace (state, ucbp, context, 0, pid); |
| } |
| |
| static _Unwind_Reason_Code |
| unwind_cpp_pr1_with_ptrace (_Unwind_State state, |
| _Unwind_Control_Block *ucbp, |
| _Unwind_Context *context, |
| pid_t pid) |
| { |
| return unwind_pr_common_with_ptrace (state, ucbp, context, 1, pid); |
| } |
| |
| static _Unwind_Reason_Code |
| unwind_cpp_pr2_with_ptrace (_Unwind_State state, |
| _Unwind_Control_Block *ucbp, |
| _Unwind_Context *context, |
| pid_t pid) |
| { |
| return unwind_pr_common_with_ptrace (state, ucbp, context, 2, pid); |
| } |