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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &regs)) {
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