Home | History | Annotate | Download | only in arch-arm
      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 ARM.
     19  *
     20  * This implementation uses the exception unwinding tables provided by
     21  * the compiler to unwind call frames.  Refer to the ARM Exception Handling ABI
     22  * documentation (EHABI) for more details about what's going on here.
     23  *
     24  * An ELF binary may contain an EXIDX section that provides an index to
     25  * the exception handling table of each function, sorted by program
     26  * counter address.
     27  *
     28  * This implementation also supports unwinding other processes via ptrace().
     29  * In that case, the EXIDX section is found by reading the ELF section table
     30  * structures using ptrace().
     31  *
     32  * Because the tables are used for exception handling, it can happen that
     33  * a given function will not have an exception handling table.  In particular,
     34  * exceptions are assumed to only ever be thrown at call sites.  Therefore,
     35  * by definition leaf functions will not have exception handling tables.
     36  * This may make unwinding impossible in some cases although we can still get
     37  * some idea of the call stack by examining the PC and LR registers.
     38  *
     39  * As we are only interested in backtrace information, we do not need
     40  * to perform all of the work of unwinding such as restoring register
     41  * state and running cleanup functions.  Unwinding is performed virtually on
     42  * an abstract machine context consisting of just the ARM core registers.
     43  * Furthermore, we do not run generic "personality functions" because
     44  * we may not be in a position to execute arbitrary code, especially if
     45  * we are running in a signal handler or using ptrace()!
     46  */
     47 
     48 #define LOG_TAG "Corkscrew"
     49 //#define LOG_NDEBUG 0
     50 
     51 #include "../backtrace-arch.h"
     52 #include "../backtrace-helper.h"
     53 #include "../ptrace-arch.h"
     54 #include <corkscrew/ptrace.h>
     55 
     56 #include <stdlib.h>
     57 #include <signal.h>
     58 #include <stdbool.h>
     59 #include <limits.h>
     60 #include <errno.h>
     61 #include <sys/ptrace.h>
     62 #include <sys/exec_elf.h>
     63 #include <cutils/log.h>
     64 
     65 /* Machine context at the time a signal was raised. */
     66 typedef struct ucontext {
     67     uint32_t uc_flags;
     68     struct ucontext* uc_link;
     69     stack_t uc_stack;
     70     struct sigcontext {
     71         uint32_t trap_no;
     72         uint32_t error_code;
     73         uint32_t oldmask;
     74         uint32_t gregs[16];
     75         uint32_t arm_cpsr;
     76         uint32_t fault_address;
     77     } uc_mcontext;
     78     uint32_t uc_sigmask;
     79 } ucontext_t;
     80 
     81 /* Unwind state. */
     82 typedef struct {
     83     uint32_t gregs[16];
     84 } unwind_state_t;
     85 
     86 static const int R_SP = 13;
     87 static const int R_LR = 14;
     88 static const int R_PC = 15;
     89 
     90 /* Special EXIDX value that indicates that a frame cannot be unwound. */
     91 static const uint32_t EXIDX_CANTUNWIND = 1;
     92 
     93 /* Get the EXIDX section start and size for the module that contains a
     94  * given program counter address.
     95  *
     96  * When the executable is statically linked, the EXIDX section can be
     97  * accessed by querying the values of the __exidx_start and __exidx_end
     98  * symbols.
     99  *
    100  * When the executable is dynamically linked, the linker exports a function
    101  * called dl_unwind_find_exidx that obtains the EXIDX section for a given
    102  * absolute program counter address.
    103  *
    104  * Bionic exports a helpful function called __gnu_Unwind_Find_exidx that
    105  * handles both cases, so we use that here.
    106  */
    107 typedef long unsigned int* _Unwind_Ptr;
    108 extern _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int *pcount);
    109 
    110 static uintptr_t find_exidx(uintptr_t pc, size_t* out_exidx_size) {
    111     int count;
    112     uintptr_t start = (uintptr_t)__gnu_Unwind_Find_exidx((_Unwind_Ptr)pc, &count);
    113     *out_exidx_size = count;
    114     return start;
    115 }
    116 
    117 /* Transforms a 31-bit place-relative offset to an absolute address.
    118  * We assume the most significant bit is clear. */
    119 static uintptr_t prel_to_absolute(uintptr_t place, uint32_t prel_offset) {
    120     return place + (((int32_t)(prel_offset << 1)) >> 1);
    121 }
    122 
    123 static uintptr_t get_exception_handler(const memory_t* memory,
    124         const map_info_t* map_info_list, uintptr_t pc) {
    125     if (!pc) {
    126         ALOGV("get_exception_handler: pc is zero, no handler");
    127         return 0;
    128     }
    129 
    130     uintptr_t exidx_start;
    131     size_t exidx_size;
    132     const map_info_t* mi;
    133     if (memory->tid < 0) {
    134         mi = NULL;
    135         exidx_start = find_exidx(pc, &exidx_size);
    136     } else {
    137         mi = find_map_info(map_info_list, pc);
    138         if (mi && mi->data) {
    139             const map_info_data_t* data = (const map_info_data_t*)mi->data;
    140             exidx_start = data->exidx_start;
    141             exidx_size = data->exidx_size;
    142         } else {
    143             exidx_start = 0;
    144             exidx_size = 0;
    145         }
    146     }
    147 
    148     uintptr_t handler = 0;
    149     int32_t handler_index = -1;
    150     if (exidx_start) {
    151         uint32_t low = 0;
    152         uint32_t high = exidx_size;
    153         while (low < high) {
    154             uint32_t index = (low + high) / 2;
    155             uintptr_t entry = exidx_start + index * 8;
    156             uint32_t entry_prel_pc;
    157             ALOGV("XXX low=%u, high=%u, index=%u", low, high, index);
    158             if (!try_get_word(memory, entry, &entry_prel_pc)) {
    159                 break;
    160             }
    161             uintptr_t entry_pc = prel_to_absolute(entry, entry_prel_pc);
    162             ALOGV("XXX entry_pc=0x%08x", entry_pc);
    163             if (pc < entry_pc) {
    164                 high = index;
    165                 continue;
    166             }
    167             if (index + 1 < exidx_size) {
    168                 uintptr_t next_entry = entry + 8;
    169                 uint32_t next_entry_prel_pc;
    170                 if (!try_get_word(memory, next_entry, &next_entry_prel_pc)) {
    171                     break;
    172                 }
    173                 uintptr_t next_entry_pc = prel_to_absolute(next_entry, next_entry_prel_pc);
    174                 ALOGV("XXX next_entry_pc=0x%08x", next_entry_pc);
    175                 if (pc >= next_entry_pc) {
    176                     low = index + 1;
    177                     continue;
    178                 }
    179             }
    180 
    181             uintptr_t entry_handler_ptr = entry + 4;
    182             uint32_t entry_handler;
    183             if (!try_get_word(memory, entry_handler_ptr, &entry_handler)) {
    184                 break;
    185             }
    186             if (entry_handler & (1L << 31)) {
    187                 handler = entry_handler_ptr; // in-place handler data
    188             } else if (entry_handler != EXIDX_CANTUNWIND) {
    189                 handler = prel_to_absolute(entry_handler_ptr, entry_handler);
    190             }
    191             handler_index = index;
    192             break;
    193         }
    194     }
    195     if (mi) {
    196         ALOGV("get_exception_handler: pc=0x%08x, module='%s', module_start=0x%08x, "
    197                 "exidx_start=0x%08x, exidx_size=%d, handler=0x%08x, handler_index=%d",
    198                 pc, mi->name, mi->start, exidx_start, exidx_size, handler, handler_index);
    199     } else {
    200         ALOGV("get_exception_handler: pc=0x%08x, "
    201                 "exidx_start=0x%08x, exidx_size=%d, handler=0x%08x, handler_index=%d",
    202                 pc, exidx_start, exidx_size, handler, handler_index);
    203     }
    204     return handler;
    205 }
    206 
    207 typedef struct {
    208     uintptr_t ptr;
    209     uint32_t word;
    210 } byte_stream_t;
    211 
    212 static bool try_next_byte(const memory_t* memory, byte_stream_t* stream, uint8_t* out_value) {
    213     uint8_t result;
    214     switch (stream->ptr & 3) {
    215     case 0:
    216         if (!try_get_word(memory, stream->ptr, &stream->word)) {
    217             *out_value = 0;
    218             return false;
    219         }
    220         *out_value = stream->word >> 24;
    221         break;
    222 
    223     case 1:
    224         *out_value = stream->word >> 16;
    225         break;
    226 
    227     case 2:
    228         *out_value = stream->word >> 8;
    229         break;
    230 
    231     default:
    232         *out_value = stream->word;
    233         break;
    234     }
    235 
    236     ALOGV("next_byte: ptr=0x%08x, value=0x%02x", stream->ptr, *out_value);
    237     stream->ptr += 1;
    238     return true;
    239 }
    240 
    241 static void set_reg(unwind_state_t* state, uint32_t reg, uint32_t value) {
    242     ALOGV("set_reg: reg=%d, value=0x%08x", reg, value);
    243     state->gregs[reg] = value;
    244 }
    245 
    246 static bool try_pop_registers(const memory_t* memory, unwind_state_t* state, uint32_t mask) {
    247     uint32_t sp = state->gregs[R_SP];
    248     bool sp_updated = false;
    249     for (int i = 0; i < 16; i++) {
    250         if (mask & (1 << i)) {
    251             uint32_t value;
    252             if (!try_get_word(memory, sp, &value)) {
    253                 return false;
    254             }
    255             if (i == R_SP) {
    256                 sp_updated = true;
    257             }
    258             set_reg(state, i, value);
    259             sp += 4;
    260         }
    261     }
    262     if (!sp_updated) {
    263         set_reg(state, R_SP, sp);
    264     }
    265     return true;
    266 }
    267 
    268 /* Executes a built-in personality routine as defined in the EHABI.
    269  * Returns true if unwinding should continue.
    270  *
    271  * The data for the built-in personality routines consists of a sequence
    272  * of unwinding instructions, followed by a sequence of scope descriptors,
    273  * each of which has a length and offset encoded using 16-bit or 32-bit
    274  * values.
    275  *
    276  * We only care about the unwinding instructions.  They specify the
    277  * operations of an abstract machine whose purpose is to transform the
    278  * virtual register state (including the stack pointer) such that
    279  * the call frame is unwound and the PC register points to the call site.
    280  */
    281 static bool execute_personality_routine(const memory_t* memory,
    282         unwind_state_t* state, byte_stream_t* stream, int pr_index) {
    283     size_t size;
    284     switch (pr_index) {
    285     case 0: // Personality routine #0, short frame, descriptors have 16-bit scope.
    286         size = 3;
    287         break;
    288     case 1: // Personality routine #1, long frame, descriptors have 16-bit scope.
    289     case 2: { // Personality routine #2, long frame, descriptors have 32-bit scope.
    290         uint8_t size_byte;
    291         if (!try_next_byte(memory, stream, &size_byte)) {
    292             return false;
    293         }
    294         size = (uint32_t)size_byte * sizeof(uint32_t) + 2;
    295         break;
    296     }
    297     default: // Unknown personality routine.  Stop here.
    298         return false;
    299     }
    300 
    301     bool pc_was_set = false;
    302     while (size--) {
    303         uint8_t op;
    304         if (!try_next_byte(memory, stream, &op)) {
    305             return false;
    306         }
    307         if ((op & 0xc0) == 0x00) {
    308             // "vsp = vsp + (xxxxxx << 2) + 4"
    309             set_reg(state, R_SP, state->gregs[R_SP] + ((op & 0x3f) << 2) + 4);
    310         } else if ((op & 0xc0) == 0x40) {
    311             // "vsp = vsp - (xxxxxx << 2) - 4"
    312             set_reg(state, R_SP, state->gregs[R_SP] - ((op & 0x3f) << 2) - 4);
    313         } else if ((op & 0xf0) == 0x80) {
    314             uint8_t op2;
    315             if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    316                 return false;
    317             }
    318             uint32_t mask = (((uint32_t)op & 0x0f) << 12) | ((uint32_t)op2 << 4);
    319             if (mask) {
    320                 // "Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}"
    321                 if (!try_pop_registers(memory, state, mask)) {
    322                     return false;
    323                 }
    324                 if (mask & (1 << R_PC)) {
    325                     pc_was_set = true;
    326                 }
    327             } else {
    328                 // "Refuse to unwind"
    329                 return false;
    330             }
    331         } else if ((op & 0xf0) == 0x90) {
    332             if (op != 0x9d && op != 0x9f) {
    333                 // "Set vsp = r[nnnn]"
    334                 set_reg(state, R_SP, state->gregs[op & 0x0f]);
    335             } else {
    336                 // "Reserved as prefix for ARM register to register moves"
    337                 // "Reserved as prefix for Intel Wireless MMX register to register moves"
    338                 return false;
    339             }
    340         } else if ((op & 0xf8) == 0xa0) {
    341             // "Pop r4-r[4+nnn]"
    342             uint32_t mask = (0x0ff0 >> (7 - (op & 0x07))) & 0x0ff0;
    343             if (!try_pop_registers(memory, state, mask)) {
    344                 return false;
    345             }
    346         } else if ((op & 0xf8) == 0xa8) {
    347             // "Pop r4-r[4+nnn], r14"
    348             uint32_t mask = ((0x0ff0 >> (7 - (op & 0x07))) & 0x0ff0) | 0x4000;
    349             if (!try_pop_registers(memory, state, mask)) {
    350                 return false;
    351             }
    352         } else if (op == 0xb0) {
    353             // "Finish"
    354             break;
    355         } else if (op == 0xb1) {
    356             uint8_t op2;
    357             if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    358                 return false;
    359             }
    360             if (op2 != 0x00 && (op2 & 0xf0) == 0x00) {
    361                 // "Pop integer registers under mask {r3, r2, r1, r0}"
    362                 if (!try_pop_registers(memory, state, op2)) {
    363                     return false;
    364                 }
    365             } else {
    366                 // "Spare"
    367                 return false;
    368             }
    369         } else if (op == 0xb2) {
    370             // "vsp = vsp + 0x204 + (uleb128 << 2)"
    371             uint32_t value = 0;
    372             uint32_t shift = 0;
    373             uint8_t op2;
    374             do {
    375                 if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    376                     return false;
    377                 }
    378                 value |= (op2 & 0x7f) << shift;
    379                 shift += 7;
    380             } while (op2 & 0x80);
    381             set_reg(state, R_SP, state->gregs[R_SP] + (value << 2) + 0x204);
    382         } else if (op == 0xb3) {
    383             // "Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDX"
    384             uint8_t op2;
    385             if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    386                 return false;
    387             }
    388             set_reg(state, R_SP, state->gregs[R_SP] + (uint32_t)(op2 & 0x0f) * 8 + 12);
    389         } else if ((op & 0xf8) == 0xb8) {
    390             // "Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDX"
    391             set_reg(state, R_SP, state->gregs[R_SP] + (uint32_t)(op & 0x07) * 8 + 12);
    392         } else if ((op & 0xf8) == 0xc0) {
    393             // "Intel Wireless MMX pop wR[10]-wR[10+nnn]"
    394             set_reg(state, R_SP, state->gregs[R_SP] + (uint32_t)(op & 0x07) * 8 + 8);
    395         } else if (op == 0xc6) {
    396             // "Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]"
    397             uint8_t op2;
    398             if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    399                 return false;
    400             }
    401             set_reg(state, R_SP, state->gregs[R_SP] + (uint32_t)(op2 & 0x0f) * 8 + 8);
    402         } else if (op == 0xc7) {
    403             uint8_t op2;
    404             if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    405                 return false;
    406             }
    407             if (op2 != 0x00 && (op2 & 0xf0) == 0x00) {
    408                 // "Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}"
    409                 set_reg(state, R_SP, state->gregs[R_SP] + __builtin_popcount(op2) * 4);
    410             } else {
    411                 // "Spare"
    412                 return false;
    413             }
    414         } else if (op == 0xc8) {
    415             // "Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc]
    416             // saved (as if) by FSTMFD"
    417             uint8_t op2;
    418             if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    419                 return false;
    420             }
    421             set_reg(state, R_SP, state->gregs[R_SP] + (uint32_t)(op2 & 0x0f) * 8 + 8);
    422         } else if (op == 0xc9) {
    423             // "Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDD"
    424             uint8_t op2;
    425             if (!(size--) || !try_next_byte(memory, stream, &op2)) {
    426                 return false;
    427             }
    428             set_reg(state, R_SP, state->gregs[R_SP] + (uint32_t)(op2 & 0x0f) * 8 + 8);
    429         } else if ((op == 0xf8) == 0xd0) {
    430             // "Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDD"
    431             set_reg(state, R_SP, state->gregs[R_SP] + (uint32_t)(op & 0x07) * 8 + 8);
    432         } else {
    433             // "Spare"
    434             return false;
    435         }
    436     }
    437     if (!pc_was_set) {
    438         set_reg(state, R_PC, state->gregs[R_LR]);
    439     }
    440     return true;
    441 }
    442 
    443 static bool try_get_half_word(const memory_t* memory, uint32_t pc, uint16_t* out_value) {
    444     uint32_t word;
    445     if (try_get_word(memory, pc & ~2, &word)) {
    446         *out_value = pc & 2 ? word >> 16 : word & 0xffff;
    447         return true;
    448     }
    449     return false;
    450 }
    451 
    452 uintptr_t rewind_pc_arch(const memory_t* memory, uintptr_t pc) {
    453     if (pc & 1) {
    454         /* Thumb mode - need to check whether the bl(x) has long offset or not.
    455          * Examples:
    456          *
    457          * arm blx in the middle of thumb:
    458          * 187ae:       2300            movs    r3, #0
    459          * 187b0:       f7fe ee1c       blx     173ec
    460          * 187b4:       2c00            cmp     r4, #0
    461          *
    462          * arm bl in the middle of thumb:
    463          * 187d8:       1c20            adds    r0, r4, #0
    464          * 187da:       f136 fd15       bl      14f208
    465          * 187de:       2800            cmp     r0, #0
    466          *
    467          * pure thumb:
    468          * 18894:       189b            adds    r3, r3, r2
    469          * 18896:       4798            blx     r3
    470          * 18898:       b001            add     sp, #4
    471          */
    472         uint16_t prev1, prev2;
    473         if (try_get_half_word(memory, pc - 5, &prev1)
    474             && ((prev1 & 0xf000) == 0xf000)
    475             && try_get_half_word(memory, pc - 3, &prev2)
    476             && ((prev2 & 0xe000) == 0xe000)) {
    477             pc -= 4; // long offset
    478         } else {
    479             pc -= 2;
    480         }
    481     } else {
    482         /* ARM mode, all instructions are 32bit.  Yay! */
    483         pc -= 4;
    484     }
    485     return pc;
    486 }
    487 
    488 static ssize_t unwind_backtrace_common(const memory_t* memory,
    489         const map_info_t* map_info_list,
    490         unwind_state_t* state, backtrace_frame_t* backtrace,
    491         size_t ignore_depth, size_t max_depth) {
    492     size_t ignored_frames = 0;
    493     size_t returned_frames = 0;
    494 
    495     for (size_t index = 0; returned_frames < max_depth; index++) {
    496         uintptr_t pc = index ? rewind_pc_arch(memory, state->gregs[R_PC])
    497                 : state->gregs[R_PC];
    498         backtrace_frame_t* frame = add_backtrace_entry(pc,
    499                 backtrace, ignore_depth, max_depth, &ignored_frames, &returned_frames);
    500         if (frame) {
    501             frame->stack_top = state->gregs[R_SP];
    502         }
    503 
    504         uintptr_t handler = get_exception_handler(memory, map_info_list, pc);
    505         if (!handler) {
    506             // If there is no handler for the PC and this is the first frame,
    507             // then the program may have branched to an invalid address.
    508             // Try starting from the LR instead, otherwise stop unwinding.
    509             if (index == 0 && state->gregs[R_LR]
    510                     && state->gregs[R_LR] != state->gregs[R_PC]) {
    511                 set_reg(state, R_PC, state->gregs[R_LR]);
    512                 continue;
    513             } else {
    514                 break;
    515             }
    516         }
    517 
    518         byte_stream_t stream;
    519         stream.ptr = handler;
    520         uint8_t pr;
    521         if (!try_next_byte(memory, &stream, &pr)) {
    522             break;
    523         }
    524         if ((pr & 0xf0) != 0x80) {
    525             // The first word is a place-relative pointer to a generic personality
    526             // routine function.  We don't support invoking such functions, so stop here.
    527             break;
    528         }
    529 
    530         // The first byte indicates the personality routine to execute.
    531         // Following bytes provide instructions to the personality routine.
    532         if (!execute_personality_routine(memory, state, &stream, pr & 0x0f)) {
    533             break;
    534         }
    535         if (frame && state->gregs[R_SP] > frame->stack_top) {
    536             frame->stack_size = state->gregs[R_SP] - frame->stack_top;
    537         }
    538         if (!state->gregs[R_PC]) {
    539             break;
    540         }
    541     }
    542 
    543     // Ran out of frames that we could unwind using handlers.
    544     // Add a final entry for the LR if it looks sane and call it good.
    545     if (returned_frames < max_depth
    546             && state->gregs[R_LR]
    547             && state->gregs[R_LR] != state->gregs[R_PC]
    548             && is_executable_map(map_info_list, state->gregs[R_LR])) {
    549         // We don't know where the stack for this extra frame starts so we
    550         // don't return any stack information for it.
    551         add_backtrace_entry(rewind_pc_arch(memory, state->gregs[R_LR]),
    552                 backtrace, ignore_depth, max_depth, &ignored_frames, &returned_frames);
    553     }
    554     return returned_frames;
    555 }
    556 
    557 ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext,
    558         const map_info_t* map_info_list,
    559         backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
    560     const ucontext_t* uc = (const ucontext_t*)sigcontext;
    561 
    562     unwind_state_t state;
    563     for (int i = 0; i < 16; i++) {
    564         state.gregs[i] = uc->uc_mcontext.gregs[i];
    565     }
    566 
    567     memory_t memory;
    568     init_memory(&memory, map_info_list);
    569     return unwind_backtrace_common(&memory, map_info_list, &state,
    570             backtrace, ignore_depth, max_depth);
    571 }
    572 
    573 ssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
    574         backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
    575     struct pt_regs regs;
    576     if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
    577         return -1;
    578     }
    579 
    580     unwind_state_t state;
    581     for (int i = 0; i < 16; i++) {
    582         state.gregs[i] = regs.uregs[i];
    583     }
    584 
    585     memory_t memory;
    586     init_memory_ptrace(&memory, tid);
    587     return unwind_backtrace_common(&memory, context->map_info_list, &state,
    588             backtrace, ignore_depth, max_depth);
    589 }
    590