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