110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* 210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Copyright (C) 2011 The Android Open Source Project 310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * 410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * you may not use this file except in compliance with the License. 610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * You may obtain a copy of the License at 710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * 810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * 1010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Unless required by applicable law or agreed to in writing, software 1110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * See the License for the specific language governing permissions and 1410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * limitations under the License. 1510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown */ 1610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 1710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* 1810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown * Backtracing functions for x86. 1910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown */ 2010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 2110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#define LOG_TAG "Corkscrew" 2210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown//#define LOG_NDEBUG 0 2310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 2410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include "../backtrace-arch.h" 2510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include "../backtrace-helper.h" 26af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin#include "../ptrace-arch.h" 2710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <corkscrew/ptrace.h> 28af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin#include "dwarf.h" 2910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 3010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <stdlib.h> 3110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <signal.h> 3210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <stdbool.h> 3310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <limits.h> 3410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <errno.h> 35af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin#include <string.h> 3610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <sys/ptrace.h> 3710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown#include <cutils/log.h> 3810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 396b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#if defined(__BIONIC__) 406b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 415f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#if defined(__BIONIC_HAVE_UCONTEXT_T) 425f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 436b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes// Bionic offers the Linux kernel headers. 446b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#include <asm/sigcontext.h> 456b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes#include <asm/ucontext.h> 466b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughestypedef struct ucontext ucontext_t; 476b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 485f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#else /* __BIONIC_HAVE_UCONTEXT_T */ 495f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 50b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner/* Old versions of the Android <signal.h> didn't define ucontext_t. */ 51b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner 52b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turnertypedef struct { 53b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner uint32_t gregs[32]; 54b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner void* fpregs; 55b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner uint32_t oldmask; 56b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner uint32_t cr2; 57b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner} mcontext_t; 58b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner 59b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turnerenum { 60b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_GS = 0, REG_FS, REG_ES, REG_DS, 61b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_EDI, REG_ESI, REG_EBP, REG_ESP, 62b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_EBX, REG_EDX, REG_ECX, REG_EAX, 63b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_TRAPNO, REG_ERR, REG_EIP, REG_CS, 64b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner REG_EFL, REG_UESP, REG_SS 65b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner}; 66b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner 6710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Machine context at the time a signal was raised. */ 6810484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct ucontext { 6910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t uc_flags; 7010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown struct ucontext* uc_link; 7110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown stack_t uc_stack; 72b4ef91b97513434a13d6d84a810512315ecf4768David 'Digit' Turner mcontext_t uc_mcontext; 7310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown uint32_t uc_sigmask; 7410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} ucontext_t; 755f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 765f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru#endif /* __BIONIC_HAVE_UCONTEXT_T */ 775f83cf0bcf96fc58ca7314571ae264353cdee321Jean-Baptiste Queru 78bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#elif defined(__APPLE__) 79bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes 80bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#define _XOPEN_SOURCE 81bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#include <ucontext.h> 82bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes 83bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#else 846b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 856b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes// glibc has its own renaming of the Linux kernel's structures. 8671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#define __USE_GNU // For REG_EBP, REG_ESP, and REG_EIP. 8771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <ucontext.h> 8810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 89bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#endif 906b3bab39d128947bf51deefe6a28c247cafd7baeElliott Hughes 9110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown/* Unwind state. */ 9210484a068412613aaf3924f63a0b2f61400c7d1eJeff Browntypedef struct { 93af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t reg[DWARF_REGISTERS]; 9410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} unwind_state_t; 9510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 96af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupintypedef struct { 97af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin backtrace_frame_t* backtrace; 98af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin size_t ignore_depth; 99af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin size_t max_depth; 100af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin size_t ignored_frames; 101af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin size_t returned_frames; 102af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin memory_t memory; 103af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} backtrace_state_t; 104af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 10546beebea823878218fc0f14723829d83886af978Edwin Vaneuintptr_t rewind_pc_arch(const memory_t* memory __attribute__((unused)), uintptr_t pc) { 106af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* TODO: x86 instructions are 1-16 bytes, to define exact size of previous instruction 107af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin we have to disassemble from the function entry point up to pc. 108af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Returning pc-1 is probably enough for now, the only drawback is that 109af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin it points somewhere between the first byte of instruction we are looking for and 110af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin the first byte of the next instruction. */ 111af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 112af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return pc-1; 113af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* TODO: We should adjust that for the signal frames and return pc for them instead of pc-1. 114af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin To recognize signal frames we should read cie_info property. */ 115af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 116af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 117af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Read byte through 4 byte cache. Usually we read byte by byte and updating cursor. */ 118af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool try_get_byte(const memory_t* memory, uintptr_t ptr, uint8_t* out_value, uint32_t* cursor) { 119af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin static uintptr_t lastptr; 120af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin static uint32_t buf; 121af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 122af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ptr += *cursor; 123af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 124af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (ptr < lastptr || lastptr + 3 < ptr) { 125af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin lastptr = (ptr >> 2) << 2; 126af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, lastptr, &buf)) { 127af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 128af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 129af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 130af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = (uint8_t)((buf >> ((ptr & 3) * 8)) & 0xff); 131af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ++*cursor; 132af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 133af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 134af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 135af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Getting X bytes. 4 is maximum for now. */ 136af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool try_get_xbytes(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint8_t bytes, uint32_t* cursor) { 137af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t data = 0; 138af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (bytes > 4) { 139af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("can't read more than 4 bytes, trying to read %d", bytes); 140af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 141af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 142af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin for (int i = 0; i < bytes; i++) { 143af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint8_t buf; 144af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, ptr, &buf, cursor)) { 145af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 146af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 147af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin data |= (uint32_t)buf << (i * 8); 148af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 149af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = data; 150af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 151af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 152af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 153af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Reads signed/unsigned LEB128 encoded data. From 1 to 4 bytes. */ 154af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool try_get_leb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor, bool sign_extend) { 155af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint8_t buf = 0; 156af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t val = 0; 157af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint8_t c = 0; 158af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin do { 159af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, ptr, &buf, cursor)) { 160af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 161af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 162af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin val |= ((uint32_t)buf & 0x7f) << (c * 7); 163af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin c++; 164af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } while (buf & 0x80 && (c * 7) <= 32); 165af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (c * 7 > 32) { 166af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("%s: data exceeds expected 4 bytes maximum", __FUNCTION__); 167af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 168af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 169af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (sign_extend) { 170af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (buf & 0x40) { 171af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin val |= ((uint32_t)-1 << (c * 7)); 172af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 173af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 174af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = val; 175af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 176af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 177af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 178af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Reads signed LEB128 encoded data. From 1 to 4 bytes. */ 179af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool try_get_sleb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor) { 180af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return try_get_leb128(memory, ptr, out_value, cursor, true); 181af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 182af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 183af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Reads unsigned LEB128 encoded data. From 1 to 4 bytes. */ 184af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool try_get_uleb128(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint32_t* cursor) { 185af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return try_get_leb128(memory, ptr, out_value, cursor, false); 186af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 187af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 188af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Getting data encoded by dwarf encodings. */ 189af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool read_dwarf(const memory_t* memory, uintptr_t ptr, uint32_t* out_value, uint8_t encoding, uint32_t* cursor) { 190af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t data = 0; 191af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin bool issigned = true; 192af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t addr = ptr + *cursor; 193af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Lower 4 bits is data type/size */ 194af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* TODO: add more encodings if it becomes necessary */ 195af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin switch (encoding & 0xf) { 196af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_EH_PE_absptr: 197af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_xbytes(memory, ptr, &data, 4, cursor)) { 198af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 199af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 200af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = data; 201af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 202af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_EH_PE_udata4: 203af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin issigned = false; 204af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_EH_PE_sdata4: 205af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_xbytes(memory, ptr, &data, 4, cursor)) { 206af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 207af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 208af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 209af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin default: 210af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("unrecognized dwarf lower part encoding: 0x%x", encoding); 211af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 212af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 213af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Higher 4 bits is modifier */ 214af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* TODO: add more encodings if it becomes necessary */ 215af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin switch (encoding & 0xf0) { 216af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 0: 217af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = data; 218af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 219af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_EH_PE_pcrel: 220af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (issigned) { 221af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = addr + (int32_t)data; 222af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 223af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = addr + data; 224af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 225af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 226af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Assuming ptr is correct base to calculate datarel */ 227af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_EH_PE_datarel: 228af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (issigned) { 229af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = ptr + (int32_t)data; 230af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 231af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *out_value = ptr + data; 232af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 233af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 234af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin default: 235af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("unrecognized dwarf higher part encoding: 0x%x", encoding); 236af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 237af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 238af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 239af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 240af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 241af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Having PC find corresponding FDE by reading .eh_frame_hdr section data. */ 242af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic uintptr_t find_fde(const memory_t* memory, 243af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin const map_info_t* map_info_list, uintptr_t pc) { 244af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!pc) { 245af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("find_fde: pc is zero, no eh_frame"); 246af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return 0; 247af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 248af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin const map_info_t* mi = find_map_info(map_info_list, pc); 249af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!mi) { 250af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("find_fde: no map info for pc:0x%x", pc); 251af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return 0; 252af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 253af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin const map_info_data_t* midata = mi->data; 254af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!midata) { 255af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("find_fde: no eh_frame_hdr for map: start=0x%x, end=0x%x", mi->start, mi->end); 256af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return 0; 257af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 258af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 259af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin eh_frame_hdr_info_t eh_hdr_info; 260af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin memset(&eh_hdr_info, 0, sizeof(eh_frame_hdr_info_t)); 261af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 262af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Getting the first word of eh_frame_hdr: 263af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 1st byte is version; 264af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 2nd byte is encoding of pointer to eh_frames; 265af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 3rd byte is encoding of count of FDEs in lookup table; 266af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 4th byte is encoding of lookup table entries. 267af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin */ 268af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t eh_frame_hdr = midata->eh_frame_hdr; 269af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t c = 0; 270af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.version, &c)) return 0; 271af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.eh_frame_ptr_enc, &c)) return 0; 272af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.fde_count_enc, &c)) return 0; 273af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, eh_frame_hdr, &eh_hdr_info.fde_table_enc, &c)) return 0; 274af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 275af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* TODO: 3rd byte can be DW_EH_PE_omit, that means no lookup table available and we should 276af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin try to parse eh_frame instead. Not sure how often it may occur, skipping now. 277af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin */ 278af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (eh_hdr_info.version != 1) { 279af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("find_fde: eh_frame_hdr version %d is not supported", eh_hdr_info.version); 280af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return 0; 281af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 282af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Getting the data: 283af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 2nd word is eh_frame pointer (normally not used, because lookup table has all we need); 284af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 3rd word is count of FDEs in the lookup table; 285af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin starting from 4 word there is FDE lookup table (pairs of PC and FDE pointer) sorted by PC; 286af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin */ 287af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, eh_frame_hdr, &eh_hdr_info.eh_frame_ptr, eh_hdr_info.eh_frame_ptr_enc, &c)) return 0; 288af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, eh_frame_hdr, &eh_hdr_info.fde_count, eh_hdr_info.fde_count_enc, &c)) return 0; 289af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("find_fde: found %d FDEs", eh_hdr_info.fde_count); 290af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 291af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin int32_t low = 0; 292af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin int32_t high = eh_hdr_info.fde_count; 293af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t start = 0; 294af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t fde = 0; 295af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* eh_frame_hdr + c points to lookup table at this point. */ 296af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin while (low <= high) { 297af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t mid = (high + low)/2; 298af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t entry = c + mid * 8; 299af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, eh_frame_hdr, &start, eh_hdr_info.fde_table_enc, &entry)) return 0; 300af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (pc <= start) { 301af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin high = mid - 1; 302af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 303af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin low = mid + 1; 304af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 305af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 306af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Value found is at high. */ 307af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (high < 0) { 308af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("find_fde: pc %x is out of FDE bounds: %x", pc, start); 309af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return 0; 310af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 311af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin c += high * 8; 312af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, eh_frame_hdr, &start, eh_hdr_info.fde_table_enc, &c)) return 0; 313af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, eh_frame_hdr, &fde, eh_hdr_info.fde_table_enc, &c)) return 0; 314af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("pc 0x%x, ENTRY %d: start=0x%x, fde=0x%x", pc, high, start, fde); 315af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return fde; 316af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 317af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 318af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Execute single dwarf instruction and update dwarf state accordingly. */ 319af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool execute_dwarf(const memory_t* memory, uintptr_t ptr, cie_info_t* cie_info, 320af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dwarf_state_t* dstate, uint32_t* cursor, 321af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dwarf_state_t* stack, uint8_t* stack_ptr) { 322af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint8_t inst; 323af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint8_t op = 0; 324af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 325af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, ptr, &inst, cursor)) { 326af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 327af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 328af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA inst: 0x%x", inst); 329af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 330af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* For some instructions upper 2 bits is opcode and lower 6 bits is operand. See dwarf-2.0 7.23. */ 331af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (inst & 0xc0) { 332af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin op = inst & 0x3f; 333af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin inst &= 0xc0; 334af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 335af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 336af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin switch ((dwarf_CFA)inst) { 337af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t reg = 0; 338af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t offset = 0; 339af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_advance_loc: 340af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->loc += op * cie_info->code_align; 341af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_advance_loc: %d to 0x%x", op, dstate->loc); 342af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 343af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_offset: 344af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false; 345af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[op].rule = 'o'; 346af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[op].value = offset * cie_info->data_align; 347af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_offset: r%d = o(%d)", op, dstate->regs[op].value); 348af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 349af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_restore: 350af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[op].rule = stack->regs[op].rule; 351af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[op].value = stack->regs[op].value; 352af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_restore: r%d = %c(%d)", op, dstate->regs[op].rule, dstate->regs[op].value); 353af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 354af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_nop: 355af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 356af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_set_loc: // probably we don't have it on x86. 357af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_xbytes(memory, ptr, &offset, 4, cursor)) return false; 358af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (offset < dstate->loc) { 359af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_set_loc: attempt to move location backward"); 360af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 361af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 362af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->loc = offset * cie_info->code_align; 363af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_set_loc: %d to 0x%x", offset * cie_info->code_align, dstate->loc); 364af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 365af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_advance_loc1: 366af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, ptr, (uint8_t*)&offset, cursor)) return false; 367af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->loc += (uint8_t)offset * cie_info->code_align; 368af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_advance_loc1: %d to 0x%x", (uint8_t)offset * cie_info->code_align, dstate->loc); 369af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 370af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_advance_loc2: 371af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_xbytes(memory, ptr, &offset, 2, cursor)) return false; 372af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->loc += (uint16_t)offset * cie_info->code_align; 373af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_advance_loc2: %d to 0x%x", (uint16_t)offset * cie_info->code_align, dstate->loc); 374af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 375af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_advance_loc4: 376af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_xbytes(memory, ptr, &offset, 4, cursor)) return false; 377af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->loc += offset * cie_info->code_align; 378af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_advance_loc4: %d to 0x%x", offset * cie_info->code_align, dstate->loc); 379af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 380af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_offset_extended: // probably we don't have it on x86. 381af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, ®, cursor)) return false; 382af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false; 383af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (reg > DWARF_REGISTERS) { 384af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_offset_extended: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS); 385af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 386af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 387af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].rule = 'o'; 388af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].value = offset * cie_info->data_align; 389af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_offset_extended: r%d = o(%d)", reg, dstate->regs[reg].value); 390af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 391af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_restore_extended: // probably we don't have it on x86. 392af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, ®, cursor)) return false; 393af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].rule = stack->regs[reg].rule; 394af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].value = stack->regs[reg].value; 395af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (reg > DWARF_REGISTERS) { 396af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_restore_extended: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS); 397af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 398af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 399af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_restore: r%d = %c(%d)", reg, dstate->regs[reg].rule, dstate->regs[reg].value); 400af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 401af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_undefined: // probably we don't have it on x86. 402af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, ®, cursor)) return false; 403af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].rule = 'u'; 404af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].value = 0; 405af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (reg > DWARF_REGISTERS) { 406af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS); 407af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 408af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 409af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_undefined: r%d", reg); 410af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 411af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_same_value: // probably we don't have it on x86. 412af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, ®, cursor)) return false; 413af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].rule = 's'; 414af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].value = 0; 415af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (reg > DWARF_REGISTERS) { 416af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_undefined: r%d exceeds supported number of registers (%d)", reg, DWARF_REGISTERS); 417af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 418af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 419af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_same_value: r%d", reg); 420af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 421af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_register: // probably we don't have it on x86. 422af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, ®, cursor)) return false; 423af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* that's new register actually, not offset */ 424af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false; 425af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (reg > DWARF_REGISTERS || offset > DWARF_REGISTERS) { 426af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_register: r%d or r%d exceeds supported number of registers (%d)", reg, offset, DWARF_REGISTERS); 427af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 428af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 429af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].rule = 'r'; 430af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].value = offset; 431af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_register: r%d = r(%d)", reg, dstate->regs[reg].value); 432af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 433af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_remember_state: 434af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (*stack_ptr == DWARF_STATES_STACK) { 435af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_remember_state: states stack overflow %d", *stack_ptr); 436af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 437af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 438af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin stack[(*stack_ptr)++] = *dstate; 439af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_remember_state: stacktop moves to %d", *stack_ptr); 440af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 441af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_restore_state: 442af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* We have CIE state saved at 0 position. It's not supposed to be taken 443af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin by DW_CFA_restore_state. */ 444af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (*stack_ptr == 1) { 445af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("DW_CFA_restore_state: states stack is empty"); 446af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 447af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 448af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Don't touch location on restore. */ 449af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t saveloc = dstate->loc; 450af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *dstate = stack[--*stack_ptr]; 451af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->loc = saveloc; 452af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_restore_state: stacktop moves to %d", *stack_ptr); 453af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 454af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_def_cfa: 455af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, ®, cursor)) return false; 456af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, &offset, cursor)) return false; 457af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->cfa_reg = reg; 458af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->cfa_off = offset; 459af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_def_cfa: %x(r%d)", offset, reg); 460af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 461af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_def_cfa_register: 462af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, ®, cursor)) { 463af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 464af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 465af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->cfa_reg = reg; 466af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_def_cfa_register: r%d", reg); 467af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 468af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case DW_CFA_def_cfa_offset: 469af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, ptr, &offset, cursor)) { 470af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 471af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 472af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->cfa_off = offset; 473af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("DW_CFA_def_cfa_offset: %x", offset); 474af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 475af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin default: 476af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("unrecognized DW_CFA_* instruction: 0x%x", inst); 477af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 478af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 479af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 480af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 481af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 482af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Restoring particular register value based on dwarf state. */ 483af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool get_old_register_value(const memory_t* memory, uint32_t cfa, 484af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dwarf_state_t* dstate, uint8_t reg, 485af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin unwind_state_t* state, unwind_state_t* newstate) { 486af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t addr; 487af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin switch (dstate->regs[reg].rule) { 488af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 0: 489af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* We don't have dstate updated for this register, so assuming value kept the same. 490af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Normally we should look into state and return current value as the old one 491af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin but we don't have all registers in state to handle this properly */ 492af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("get_old_register_value: value of r%d is the same", reg); 493af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin // for ESP if it's not updated by dwarf rule we assume it's equal to CFA 494af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (reg == DWARF_ESP) { 495af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("get_old_register_value: adjusting esp to CFA: 0x%x", cfa); 496af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin newstate->reg[reg] = cfa; 497af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 498af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin newstate->reg[reg] = state->reg[reg]; 499af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 500af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 501af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 'o': 502af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin addr = cfa + (int32_t)dstate->regs[reg].value; 503af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, addr, &newstate->reg[reg])) { 504af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("get_old_register_value: can't read from 0x%x", addr); 505af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 506af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 507af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("get_old_register_value: r%d at 0x%x is 0x%x", reg, addr, newstate->reg[reg]); 508af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 509af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 'r': 510af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* We don't have all registers in state so don't even try to look at 'r' */ 511af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("get_old_register_value: register lookup not implemented yet"); 512af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 513af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin default: 514af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("get_old_register_value: unexpected rule:%c value:%d for register %d", 515af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->regs[reg].rule, (int32_t)dstate->regs[reg].value, reg); 516af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 517af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 518af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 519af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 520af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 521af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Updaing state based on dwarf state. */ 522af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool update_state(const memory_t* memory, unwind_state_t* state, 523af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dwarf_state_t* dstate, cie_info_t* cie_info) { 524af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin unwind_state_t newstate; 525af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* We can restore more registers here if we need them. Meanwile doing minimal work here. */ 526af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Getting CFA. */ 527af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t cfa = 0; 528af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (dstate->cfa_reg == DWARF_ESP) { 529af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cfa = state->reg[DWARF_ESP] + dstate->cfa_off; 530af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else if (dstate->cfa_reg == DWARF_EBP) { 531af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cfa = state->reg[DWARF_EBP] + dstate->cfa_off; 532af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 533af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGE("update_state: unexpected CFA register: %d", dstate->cfa_reg); 534af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 535af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 536af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("update_state: new CFA: 0x%x", cfa); 537af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Getting EIP. */ 538af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!get_old_register_value(memory, cfa, dstate, DWARF_EIP, state, &newstate)) return false; 539af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Getting EBP. */ 540af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!get_old_register_value(memory, cfa, dstate, DWARF_EBP, state, &newstate)) return false; 541af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Getting ESP. */ 542af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!get_old_register_value(memory, cfa, dstate, DWARF_ESP, state, &newstate)) return false; 543af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 544af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("update_state: IP: 0x%x; restore IP: 0x%x", state->reg[DWARF_EIP], newstate.reg[DWARF_EIP]); 545af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("update_state: EBP: 0x%x; restore EBP: 0x%x", state->reg[DWARF_EBP], newstate.reg[DWARF_EBP]); 546af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("update_state: ESP: 0x%x; restore ESP: 0x%x", state->reg[DWARF_ESP], newstate.reg[DWARF_ESP]); 547af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin *state = newstate; 548af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return true; 549af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin} 550af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 551af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin/* Execute CIE and FDE instructions for FDE found with find_fde. */ 552af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupinstatic bool execute_fde(const memory_t* memory, 553af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin const map_info_t* map_info_list, 554af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t fde, 555af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin unwind_state_t* state) { 556af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t fde_length = 0; 557af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t cie_length = 0; 558af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t cie = 0; 559af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t cie_offset = 0; 560af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cie_info_t cie_i; 561af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cie_info_t* cie_info = &cie_i; 562af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin fde_info_t fde_i; 563af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin fde_info_t* fde_info = &fde_i; 564af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dwarf_state_t dwarf_state; 565af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dwarf_state_t* dstate = &dwarf_state; 566af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dwarf_state_t stack[DWARF_STATES_STACK]; 567af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint8_t stack_ptr = 0; 568af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 569af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin memset(dstate, 0, sizeof(dwarf_state_t)); 570af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin memset(cie_info, 0, sizeof(cie_info_t)); 571af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin memset(fde_info, 0, sizeof(fde_info_t)); 572af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 573af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Read common CIE or FDE area: 574af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 1st word is length; 575af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 2nd word is ID: 0 for CIE, CIE pointer for FDE. 576af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin */ 577af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, fde, &fde_length)) { 578af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 579af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 580af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if ((int32_t)fde_length == -1) { 581af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet"); 582af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 583af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 584af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, fde + 4, &cie_offset)) { 585af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 586af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 587af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_offset == 0) { 588af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* This is CIE. We shouldn't be here normally. */ 589af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cie = fde; 590af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cie_length = fde_length; 591af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 592af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Find CIE. */ 593af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Positive cie_offset goes backward from current field. */ 594af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cie = fde + 4 - cie_offset; 595af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, cie, &cie_length)) { 596af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 597af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 598af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if ((int32_t)cie_length == -1) { 599af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: 64-bit dwarf detected, not implemented yet"); 600af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 601af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 602af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, cie + 4, &cie_offset)) { 603af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 604af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 605af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_offset != 0) { 606af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: can't find CIE"); 607af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 608af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 609af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 610af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: FDE length: %d", fde_length); 611af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: CIE pointer: %x", cie); 612af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: CIE length: %d", cie_length); 613af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 614af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Read CIE: 615af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Augmentation independent: 616af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 1st byte is version; 617af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin next x bytes is /0 terminated augmentation string; 618af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin next x bytes is unsigned LEB128 encoded code alignment factor; 619af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin next x bytes is signed LEB128 encoded data alignment factor; 620af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin next 1 (CIE version 1) or x (CIE version 3 unsigned LEB128) bytes is return register column; 621af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Augmentation dependent: 622af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if 'z' next x bytes is unsigned LEB128 encoded augmentation data size; 623af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if 'L' next 1 byte is LSDA encoding; 624af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if 'R' next 1 byte is FDE encoding; 625af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if 'S' CIE represents signal handler stack frame; 626af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if 'P' next 1 byte is personality encoding folowed by personality function pointer; 627af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Next x bytes is CIE program. 628af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin */ 629af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 630af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t c = 8; 631af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, cie, &cie_info->version, &c)) { 632af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 633af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 634af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: CIE version: %d", cie_info->version); 635af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint8_t ch; 636af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin do { 637af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, cie, &ch, &c)) { 638af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 639af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 640af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin switch (ch) { 641af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case '\0': break; 642af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 'z': cie_info->aug_z = 1; break; 643af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 'L': cie_info->aug_L = 1; break; 644af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 'R': cie_info->aug_R = 1; break; 645af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 'S': cie_info->aug_S = 1; break; 646af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin case 'P': cie_info->aug_P = 1; break; 647af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin default: 648af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: Unrecognized CIE augmentation char: '%c'", ch); 649af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 650af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 651af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 652af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } while (ch); 653af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, cie, &cie_info->code_align, &c)) { 654af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 655af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 656af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_sleb128(memory, cie, &cie_info->data_align, &c)) { 657af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 658af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 659af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_info->version >= 3) { 660af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, cie, &cie_info->reg, &c)) { 661af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 662af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 663af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 664af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->reg, &c)) { 665af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 666af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 667af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 668af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: CIE code alignment factor: %d", cie_info->code_align); 669af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: CIE data alignment factor: %d", cie_info->data_align); 670af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_info->aug_z) { 671af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, cie, &cie_info->aug_z, &c)) { 672af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 673af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 674af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 675af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_info->aug_L) { 676af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, cie, &cie_info->aug_L, &c)) { 677af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 678af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 679af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 680af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Default encoding. */ 681af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cie_info->aug_L = DW_EH_PE_absptr; 682af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 683af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_info->aug_R) { 684af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, cie, &cie_info->aug_R, &c)) { 685af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 686af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 687af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } else { 688af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Default encoding. */ 689af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin cie_info->aug_R = DW_EH_PE_absptr; 690af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 691af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_info->aug_P) { 692af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Get encoding of personality routine pointer. We don't use it now. */ 693af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_byte(memory, cie, (uint8_t*)&cie_info->aug_P, &c)) { 694af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 695af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 696af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Get routine pointer. */ 697af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, cie, &cie_info->aug_P, (uint8_t)cie_info->aug_P, &c)) { 698af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 699af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 700af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 701af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* CIE program. */ 702af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Length field itself (4 bytes) is not included into length. */ 703af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin stack[0] = *dstate; 704af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin stack_ptr = 1; 705af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin while (c < cie_length + 4) { 706af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!execute_dwarf(memory, cie, cie_info, dstate, &c, stack, &stack_ptr)) { 707af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 708af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 709af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 710af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 711af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* We went directly to CIE. Normally it shouldn't occur. */ 712af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie == fde) return true; 713af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 714af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Go back to FDE. */ 715af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin c = 8; 716af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Read FDE: 717af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Augmentation independent: 718af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin next x bytes (encoded as specified in CIE) is FDE starting address; 719af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin next x bytes (encoded as specified in CIE) is FDE number of instructions covered; 720af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Augmentation dependent: 721af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if 'z' next x bytes is unsigned LEB128 encoded augmentation data size; 722af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if 'L' next x bytes is LSDA pointer (encoded as specified in CIE); 723af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Next x bytes is FDE program. 724af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin */ 725af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, fde, &fde_info->start, (uint8_t)cie_info->aug_R, &c)) { 726af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 727af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 728af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin dstate->loc = fde_info->start; 729af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: FDE start: %x", dstate->loc); 730af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, fde, &fde_info->length, 0, &c)) { 731af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 732af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 733af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("execute_fde: FDE length: %x", fde_info->length); 734af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_info->aug_z) { 735af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_uleb128(memory, fde, &fde_info->aug_z, &c)) { 736af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 737af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 738af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 739af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (cie_info->aug_L && cie_info->aug_L != DW_EH_PE_omit) { 740af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!read_dwarf(memory, fde, &fde_info->aug_L, cie_info->aug_L, &c)) { 741af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 742af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 743af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 744af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* FDE program. */ 745af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Length field itself (4 bytes) is not included into length. */ 746af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* Save CIE state as 0 element of stack. Used by DW_CFA_restore. */ 747af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin stack[0] = *dstate; 748af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin stack_ptr = 1; 749af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin while (c < fde_length + 4 && state->reg[DWARF_EIP] >= dstate->loc) { 750af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!execute_dwarf(memory, fde, cie_info, dstate, &c, stack, &stack_ptr)) { 751af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return false; 752af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 753af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("IP: %x, LOC: %x", state->reg[DWARF_EIP], dstate->loc); 754af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 755af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 756af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin return update_state(memory, state, dstate, cie_info); 757f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown} 758f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 759f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brownstatic ssize_t unwind_backtrace_common(const memory_t* memory, 760af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin const map_info_t* map_info_list, 76110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t* state, backtrace_frame_t* backtrace, 76210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t ignore_depth, size_t max_depth) { 763af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 76410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t ignored_frames = 0; 76510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown size_t returned_frames = 0; 76610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 767af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("Unwinding tid: %d", memory->tid); 768af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("IP: %x", state->reg[DWARF_EIP]); 769af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("BP: %x", state->reg[DWARF_EBP]); 770af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("SP: %x", state->reg[DWARF_ESP]); 771af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 772af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin for (size_t index = 0; returned_frames < max_depth; index++) { 773af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uintptr_t fde = find_fde(memory, map_info_list, state->reg[DWARF_EIP]); 774af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* FDE is not found, it may happen if stack is corrupted or calling wrong adress. 775af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin Getting return address from stack. 776af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin */ 777af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!fde) { 778af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t ip; 779af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("trying to restore registers from stack"); 780af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, state->reg[DWARF_EBP] + 4, &ip) || 781af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ip == state->reg[DWARF_EIP]) { 782af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("can't get IP from stack"); 783af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 784af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 785af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin /* We've been able to get IP from stack so recording the frame before continue. */ 786af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin backtrace_frame_t* frame = add_backtrace_entry( 787af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin index ? rewind_pc_arch(memory, state->reg[DWARF_EIP]) : state->reg[DWARF_EIP], 788af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin backtrace, ignore_depth, max_depth, 789af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin &ignored_frames, &returned_frames); 790af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state->reg[DWARF_EIP] = ip; 791af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state->reg[DWARF_ESP] = state->reg[DWARF_EBP] + 8; 792af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!try_get_word(memory, state->reg[DWARF_EBP], &state->reg[DWARF_EBP])) { 793af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("can't get EBP from stack"); 794af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin break; 795af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 796af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("restore IP: %x", state->reg[DWARF_EIP]); 797af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("restore BP: %x", state->reg[DWARF_EBP]); 798af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("restore SP: %x", state->reg[DWARF_ESP]); 799af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin continue; 800af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin } 801f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown backtrace_frame_t* frame = add_backtrace_entry( 802af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin index ? rewind_pc_arch(memory, state->reg[DWARF_EIP]) : state->reg[DWARF_EIP], 80310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace, ignore_depth, max_depth, 80410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown &ignored_frames, &returned_frames); 805af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 806af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin uint32_t stack_top = state->reg[DWARF_ESP]; 807af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 808af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (!execute_fde(memory, map_info_list, fde, state)) break; 809af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin 81010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (frame) { 811af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin frame->stack_top = stack_top; 812af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin if (stack_top < state->reg[DWARF_ESP]) { 813af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin frame->stack_size = state->reg[DWARF_ESP] - stack_top; 81410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 81510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 816af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin ALOGV("Stack: 0x%x ... 0x%x - %d bytes", frame->stack_top, state->reg[DWARF_ESP], frame->stack_size); 81710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 81810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return returned_frames; 81910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 82010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 82146beebea823878218fc0f14723829d83886af978Edwin Vanessize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), void* sigcontext, 822f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown const map_info_t* map_info_list, 82310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 82410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown const ucontext_t* uc = (const ucontext_t*)sigcontext; 82510484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 82610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t state; 827bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#if defined(__APPLE__) 828bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes state.reg[DWARF_EBP] = uc->uc_mcontext->__ss.__ebp; 829bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes state.reg[DWARF_ESP] = uc->uc_mcontext->__ss.__esp; 830bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes state.reg[DWARF_EIP] = uc->uc_mcontext->__ss.__eip; 831bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#else 832af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state.reg[DWARF_EBP] = uc->uc_mcontext.gregs[REG_EBP]; 833af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state.reg[DWARF_ESP] = uc->uc_mcontext.gregs[REG_ESP]; 834af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state.reg[DWARF_EIP] = uc->uc_mcontext.gregs[REG_EIP]; 835bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#endif 83610484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 837f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown memory_t memory; 838f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown init_memory(&memory, map_info_list); 839f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown return unwind_backtrace_common(&memory, map_info_list, 840f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown &state, backtrace, ignore_depth, max_depth); 84110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 84210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 84310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brownssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context, 84410484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 845bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#if defined(__APPLE__) 846bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes return -1; 847bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#else 84810484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown pt_regs_x86_t regs; 84910484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown if (ptrace(PTRACE_GETREGS, tid, 0, ®s)) { 85010484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown return -1; 85110484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown } 85210484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 85310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown unwind_state_t state; 854af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state.reg[DWARF_EBP] = regs.ebp; 855af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state.reg[DWARF_EIP] = regs.eip; 856af2cb3667ba24d1ef3037aa5a7b3bc0a238cf040Pavel Chupin state.reg[DWARF_ESP] = regs.esp; 85710484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown 858f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown memory_t memory; 859f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown init_memory_ptrace(&memory, tid); 860f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown return unwind_backtrace_common(&memory, context->map_info_list, 861f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown &state, backtrace, ignore_depth, max_depth); 862bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#endif 86310484a068412613aaf3924f63a0b2f61400c7d1eJeff Brown} 864