^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2002-2006 Novell, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Jan Beulich <jbeulich@novell.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * A simple API for unwinding kernel stacks. This is used for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * debugging and error reporting purposes. The kernel doesn't need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * full-blown stack unwinding with all the bells and whistles, so there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * is not much point in implementing the full Dwarf2 unwind API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/sort.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/stop_machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/unwind.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) extern char __start_unwind[], __end_unwind[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* #define UNWIND_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #ifdef UNWIND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int dbg_unw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define unw_debug(fmt, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (dbg_unw) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) pr_info(fmt, ##__VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) } while (0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define unw_debug(fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MAX_STACK_DEPTH 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define EXTRA_INFO(f) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) % sizeof_field(struct unwind_frame_info, f)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) + offsetof(struct unwind_frame_info, f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) / sizeof_field(struct unwind_frame_info, f), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) sizeof_field(struct unwind_frame_info, f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define PTREGS_INFO(f) EXTRA_INFO(regs.f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned offs:BITS_PER_LONG / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned width:BITS_PER_LONG / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) } reg_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) UNW_REGISTER_INFO};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #undef PTREGS_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #undef EXTRA_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #ifndef REG_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define REG_INVALID(r) (reg_info[r].width == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define DW_CFA_nop 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define DW_CFA_set_loc 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define DW_CFA_advance_loc1 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define DW_CFA_advance_loc2 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define DW_CFA_advance_loc4 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define DW_CFA_offset_extended 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define DW_CFA_restore_extended 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define DW_CFA_undefined 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define DW_CFA_same_value 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define DW_CFA_register 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define DW_CFA_remember_state 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define DW_CFA_restore_state 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define DW_CFA_def_cfa 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define DW_CFA_def_cfa_register 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define DW_CFA_def_cfa_offset 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define DW_CFA_def_cfa_expression 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define DW_CFA_expression 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define DW_CFA_offset_extended_sf 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define DW_CFA_def_cfa_sf 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define DW_CFA_def_cfa_offset_sf 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define DW_CFA_val_offset 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define DW_CFA_val_offset_sf 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define DW_CFA_val_expression 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define DW_CFA_lo_user 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define DW_CFA_GNU_window_save 0x2d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define DW_CFA_GNU_args_size 0x2e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define DW_CFA_GNU_negative_offset_extended 0x2f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define DW_CFA_hi_user 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define DW_EH_PE_FORM 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define DW_EH_PE_native 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define DW_EH_PE_leb128 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define DW_EH_PE_data2 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define DW_EH_PE_data4 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define DW_EH_PE_data8 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define DW_EH_PE_signed 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define DW_EH_PE_ADJUST 0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define DW_EH_PE_abs 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define DW_EH_PE_pcrel 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define DW_EH_PE_textrel 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define DW_EH_PE_datarel 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define DW_EH_PE_funcrel 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define DW_EH_PE_aligned 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define DW_EH_PE_indirect 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define DW_EH_PE_omit 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define CIE_ID 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) typedef unsigned long uleb128_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) typedef signed long sleb128_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static struct unwind_table {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned long pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) unsigned long range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) } core, init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) const void *address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) const unsigned char *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned long hdrsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct unwind_table *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) } root_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct unwind_item {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) enum item_location {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) Nowhere,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) Memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) Register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) Value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) } where;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) uleb128_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct unwind_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) uleb128_t loc, org;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) const u8 *cieStart, *cieEnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) uleb128_t codeAlign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) sleb128_t dataAlign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct cfa {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) uleb128_t reg, offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) } cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct unwind_item regs[ARRAY_SIZE(reg_info)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) unsigned stackDepth:8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned version:8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) const u8 *label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) const u8 *stack[MAX_STACK_DEPTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static struct unwind_table *find_table(unsigned long pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct unwind_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) for (table = &root_table; table; table = table->link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if ((pc >= table->core.pc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) && pc < table->core.pc + table->core.range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) || (pc >= table->init.pc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) && pc < table->init.pc + table->init.range))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static unsigned long read_pointer(const u8 **pLoc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) const void *end, signed ptrType);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void init_unwind_hdr(struct unwind_table *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) void *(*alloc) (unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * wrappers for header alloc (vs. calling one vs. other at call site)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * to elide section mismatches warnings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void *__init unw_hdr_alloc_early(unsigned long sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return memblock_alloc_from(sz, sizeof(unsigned int), MAX_DMA_ADDRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void init_unwind_table(struct unwind_table *table, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) const void *core_start, unsigned long core_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) const void *init_start, unsigned long init_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) const void *table_start, unsigned long table_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) const u8 *header_start, unsigned long header_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) const u8 *ptr = header_start + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) const u8 *end = header_start + header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) table->core.pc = (unsigned long)core_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) table->core.range = core_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) table->init.pc = (unsigned long)init_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) table->init.range = init_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) table->address = table_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) table->size = table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* See if the linker provided table looks valid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (header_size <= 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) || header_start[0] != 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) || header_start[2] == DW_EH_PE_omit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) || read_pointer(&ptr, end, header_start[2]) <= 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) || header_start[3] == DW_EH_PE_omit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) header_start = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) table->hdrsz = header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) smp_wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) table->header = header_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) table->link = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) table->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) void __init arc_unwind_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) __start_unwind, __end_unwind - __start_unwind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) init_unwind_hdr(&root_table, unw_hdr_alloc_early);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static const u32 bad_cie, not_fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static const u32 *__cie_for_fde(const u32 *fde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static signed fde_pointer_type(const u32 *cie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct eh_frame_hdr_table_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) unsigned long start, fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) const struct eh_frame_hdr_table_entry *e1 = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) const struct eh_frame_hdr_table_entry *e2 = p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return (e1->start > e2->start) - (e1->start < e2->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct eh_frame_hdr_table_entry *e1 = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct eh_frame_hdr_table_entry *e2 = p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) v = e1->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) e1->start = e2->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) e2->start = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) v = e1->fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) e1->fde = e2->fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) e2->fde = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static void init_unwind_hdr(struct unwind_table *table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) void *(*alloc) (unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) const u8 *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) unsigned long tableSize = table->size, hdrSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) unsigned n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) const u32 *fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) u8 eh_frame_ptr_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) u8 fde_count_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) u8 table_enc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned long eh_frame_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) unsigned int fde_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct eh_frame_hdr_table_entry table[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) } __attribute__ ((__packed__)) *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (table->header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (table->hdrsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) table->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (tableSize & (sizeof(*fde) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) for (fde = table->address, n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) const u32 *cie = cie_for_fde(fde, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) signed ptrType;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (cie == ¬_fde)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (cie == NULL || cie == &bad_cie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) goto ret_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) ptrType = fde_pointer_type(cie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (ptrType < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) goto ret_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ptr = (const u8 *)(fde + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ptrType)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* FIXME_Rajesh We have 4 instances of null addresses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * instead of the initial loc addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) WARN(1, "unwinder: FDE->initial_location NULL %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) (const u8 *)(fde + 1) + *fde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ++n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (tableSize || !n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) goto ret_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) + 2 * n * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) header = alloc(hdrSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (!header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) goto ret_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) header->version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) % __alignof(typeof(header->fde_count)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) header->fde_count = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) BUILD_BUG_ON(offsetof(typeof(*header), table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) % __alignof(typeof(*header->table)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) for (fde = table->address, tableSize = table->size, n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) tableSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) const u32 *cie = __cie_for_fde(fde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (fde[1] == CIE_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) continue; /* this is a CIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ptr = (const u8 *)(fde + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) header->table[n].start = read_pointer(&ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) (const u8 *)(fde + 1) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *fde,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) fde_pointer_type(cie));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) header->table[n].fde = (unsigned long)fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ++n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) WARN_ON(n != header->fde_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) sort(header->table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) sizeof(*header->table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) table->hdrsz = hdrSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) smp_wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) table->header = (const void *)header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ret_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) panic("Attention !!! Dwarf FDE parsing errors\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) #ifdef CONFIG_MODULES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static void *unw_hdr_alloc(unsigned long sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return kmalloc(sz, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static struct unwind_table *last_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* Must be called with module_mutex held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) void *unwind_add_table(struct module *module, const void *table_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) unsigned long table_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct unwind_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (table_size <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) table = kmalloc(sizeof(*table), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) init_unwind_table(table, module->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) module->core_layout.base, module->core_layout.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) module->init_layout.base, module->init_layout.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) table_start, table_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) init_unwind_hdr(table, unw_hdr_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) #ifdef UNWIND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) unw_debug("Table added for [%s] %lx %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) module->name, table->core.pc, table->core.range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (last_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) last_table->link = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) root_table.link = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) last_table = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct unlink_table_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct unwind_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int init_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static int unlink_table(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct unlink_table_info *info = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct unwind_table *table = info->table, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) for (prev = &root_table; prev->link && prev->link != table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) prev = prev->link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (prev->link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (info->init_only) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) table->init.pc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) table->init.range = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) info->table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) prev->link = table->link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!prev->link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) last_table = prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) info->table = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* Must be called with module_mutex held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) void unwind_remove_table(void *handle, int init_only)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct unwind_table *table = handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct unlink_table_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (!table || table == &root_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (init_only && table == last_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) table->init.pc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) table->init.range = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) info.table = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) info.init_only = init_only;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) unlink_table(&info); /* XXX: SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) kfree(table->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) kfree(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) #endif /* CONFIG_MODULES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) const u8 *cur = *pcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) uleb128_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) unsigned shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) for (shift = 0, value = 0; cur < end; shift += 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (shift + 7 > 8 * sizeof(value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) cur = end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) value |= (uleb128_t) (*cur & 0x7f) << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (!(*cur++ & 0x80))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) *pcur = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) const u8 *cur = *pcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) sleb128_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) unsigned shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) for (shift = 0, value = 0; cur < end; shift += 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (shift + 7 > 8 * sizeof(value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) cur = end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) value |= (sleb128_t) (*cur & 0x7f) << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (!(*cur & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) value |= -(*cur++ & 0x40) << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) *pcur = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static const u32 *__cie_for_fde(const u32 *fde)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) const u32 *cie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) cie = fde + 1 - fde[1] / sizeof(*fde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) return cie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) const u32 *cie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!*fde || (*fde & (sizeof(*fde) - 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return &bad_cie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (fde[1] == CIE_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return ¬_fde; /* this is a CIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if ((fde[1] & (sizeof(*fde) - 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return NULL; /* this is not a valid FDE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) cie = __cie_for_fde(fde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) || (*cie & (sizeof(*cie) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) || (cie[1] != CIE_ID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return NULL; /* this is not a (valid) CIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return cie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static unsigned long read_pointer(const u8 **pLoc, const void *end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) signed ptrType)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) unsigned long value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) const u8 *p8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) const u16 *p16u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) const s16 *p16s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) const u32 *p32u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) const s32 *p32s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) const unsigned long *pul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) } ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (ptrType < 0 || ptrType == DW_EH_PE_omit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ptr.p8 = *pLoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) switch (ptrType & DW_EH_PE_FORM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case DW_EH_PE_data2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (end < (const void *)(ptr.p16u + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (ptrType & DW_EH_PE_signed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) value = get_unaligned((u16 *) ptr.p16s++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) value = get_unaligned((u16 *) ptr.p16u++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) case DW_EH_PE_data4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (end < (const void *)(ptr.p32u + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (ptrType & DW_EH_PE_signed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) value = get_unaligned(ptr.p32s++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) value = get_unaligned(ptr.p32u++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) case DW_EH_PE_data8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) BUILD_BUG_ON(sizeof(u64) != sizeof(value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) BUILD_BUG_ON(sizeof(u32) != sizeof(value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) case DW_EH_PE_native:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (end < (const void *)(ptr.pul + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) value = get_unaligned((unsigned long *)ptr.pul++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case DW_EH_PE_leb128:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) : get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if ((const void *)ptr.p8 > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) switch (ptrType & DW_EH_PE_ADJUST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) case DW_EH_PE_abs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case DW_EH_PE_pcrel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) value += (unsigned long)*pLoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if ((ptrType & DW_EH_PE_indirect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) && __get_user(value, (unsigned long __user *)value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) *pLoc = ptr.p8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static signed fde_pointer_type(const u32 *cie)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) const u8 *ptr = (const u8 *)(cie + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) unsigned version = *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (*++ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) const char *aug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) const u8 *end = (const u8 *)(cie + 1) + *cie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) uleb128_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /* check if augmentation size is first (and thus present) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (*ptr != 'z')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* check if augmentation string is nul-terminated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) aug = (const void *)ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ptr = memchr(aug, 0, end - ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (ptr == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ++ptr; /* skip terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) get_uleb128(&ptr, end); /* skip code alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) get_sleb128(&ptr, end); /* skip data alignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) /* skip return address column */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) len = get_uleb128(&ptr, end); /* augmentation length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (ptr + len < ptr || ptr + len > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) end = ptr + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) while (*++aug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (ptr >= end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) switch (*aug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) ++ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) case 'P':{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) signed ptrType = *ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (!read_pointer(&ptr, end, ptrType)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) || ptr > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) case 'R':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return DW_EH_PE_native | DW_EH_PE_abs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) static int advance_loc(unsigned long delta, struct unwind_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) state->loc += delta * state->codeAlign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* FIXME_Rajesh: Probably we are defining for the initial range as well;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return delta > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct unwind_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (reg < ARRAY_SIZE(state->regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) state->regs[reg].where = where;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) state->regs[reg].value = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) #ifdef UNWIND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) unw_debug("r%lu: ", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) switch (where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case Nowhere:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) unw_debug("s ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) case Memory:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) unw_debug("c(%lu) ", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) case Register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) unw_debug("r(%lu) ", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case Value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) unw_debug("v(%lu) ", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) signed ptrType, struct unwind_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) const u8 *p8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) const u16 *p16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) const u32 *p32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) } ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) int result = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) u8 opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (start != state->cieStart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) state->loc = state->org;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) processCFI(state->cieStart, state->cieEnd, 0, ptrType,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (targetLoc == 0 && state->label == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) for (ptr.p8 = start; result && ptr.p8 < end;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) switch (*ptr.p8 >> 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) uleb128_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) opcode = *ptr.p8++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) switch (opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) case DW_CFA_nop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) unw_debug("cfa nop ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) case DW_CFA_set_loc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) state->loc = read_pointer(&ptr.p8, end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) ptrType);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (state->loc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) unw_debug("cfa_set_loc: 0x%lx ", state->loc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) case DW_CFA_advance_loc1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) unw_debug("\ncfa advance loc1:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) result = ptr.p8 < end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) && advance_loc(*ptr.p8++, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) case DW_CFA_advance_loc2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) value = *ptr.p8++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) value += *ptr.p8++ << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) unw_debug("\ncfa advance loc2:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) result = ptr.p8 <= end + 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* && advance_loc(*ptr.p16++, state); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) && advance_loc(value, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) case DW_CFA_advance_loc4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) unw_debug("\ncfa advance loc4:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) result = ptr.p8 <= end + 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) && advance_loc(*ptr.p32++, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) case DW_CFA_offset_extended:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) value = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) unw_debug("cfa_offset_extended: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) set_rule(value, Memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) get_uleb128(&ptr.p8, end), state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) case DW_CFA_val_offset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) value = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) set_rule(value, Value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) get_uleb128(&ptr.p8, end), state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) case DW_CFA_offset_extended_sf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) value = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) set_rule(value, Memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) get_sleb128(&ptr.p8, end), state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) case DW_CFA_val_offset_sf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) value = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) set_rule(value, Value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) get_sleb128(&ptr.p8, end), state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) case DW_CFA_restore_extended:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) unw_debug("cfa_restore_extended: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) case DW_CFA_undefined:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) unw_debug("cfa_undefined: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) case DW_CFA_same_value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) unw_debug("cfa_same_value: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) case DW_CFA_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) unw_debug("cfa_register: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) value = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) set_rule(value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) Register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) get_uleb128(&ptr.p8, end), state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) case DW_CFA_remember_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) unw_debug("cfa_remember_state: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (ptr.p8 == state->label) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) state->label = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (state->stackDepth >= MAX_STACK_DEPTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) state->stack[state->stackDepth++] = ptr.p8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) case DW_CFA_restore_state:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) unw_debug("cfa_restore_state: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (state->stackDepth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) const uleb128_t loc = state->loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) const u8 *label = state->label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) state->label =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) state->stack[state->stackDepth - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) memcpy(&state->cfa, &badCFA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) sizeof(state->cfa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) memset(state->regs, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) sizeof(state->regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) state->stackDepth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) processCFI(start, end, 0, ptrType,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) state->loc = loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) state->label = label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) case DW_CFA_def_cfa:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) state->cfa.reg = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) case DW_CFA_def_cfa_offset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) state->cfa.offs = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) unw_debug("cfa_def_cfa_offset: 0x%lx ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) state->cfa.offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) case DW_CFA_def_cfa_sf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) state->cfa.reg = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) case DW_CFA_def_cfa_offset_sf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) state->cfa.offs = get_sleb128(&ptr.p8, end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * state->dataAlign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) case DW_CFA_def_cfa_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) unw_debug("cfa_def_cfa_register: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) state->cfa.reg = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /*todo case DW_CFA_def_cfa_expression: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /*todo case DW_CFA_expression: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /*todo case DW_CFA_val_expression: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) case DW_CFA_GNU_args_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) case DW_CFA_GNU_negative_offset_extended:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) value = get_uleb128(&ptr.p8, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) set_rule(value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) Memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) (uleb128_t) 0 - get_uleb128(&ptr.p8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) end),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) case DW_CFA_GNU_window_save:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) unw_debug("\ncfa_adv_loc: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) result = advance_loc(*ptr.p8++ & 0x3f, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) unw_debug("cfa_offset: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) value = *ptr.p8++ & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) set_rule(value, Memory, get_uleb128(&ptr.p8, end),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) unw_debug("cfa_restore: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (ptr.p8 > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (result && targetLoc != 0 && targetLoc < state->loc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) return result && ptr.p8 == end && (targetLoc == 0 || (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) /*todo While in theory this should apply, gcc in practice omits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) everything past the function prolog, and hence the location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) never reaches the end of the function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) targetLoc < state->loc && */ state->label == NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /* Unwind to previous to frame. Returns 0 if successful, negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * number in case of an error. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) int arc_unwind(struct unwind_frame_info *frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) const u32 *fde = NULL, *cie = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) const u8 *ptr = NULL, *end = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) unsigned long pc = UNW_PC(frame) - frame->call_frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) unsigned long startLoc = 0, endLoc = 0, cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) signed ptrType = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) uleb128_t retAddrReg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) const struct unwind_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct unwind_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) unsigned long *fptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) unw_debug("\n\nUNWIND FRAME:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) unw_debug("PC: 0x%lx BLINK: 0x%lx, SP: 0x%lx, FP: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) UNW_PC(frame), UNW_BLINK(frame), UNW_SP(frame),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) UNW_FP(frame));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (UNW_PC(frame) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) #ifdef UNWIND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) unsigned long *sptr = (unsigned long *)UNW_SP(frame);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) unw_debug("\nStack Dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) for (i = 0; i < 20; i++, sptr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) unw_debug("0x%p: 0x%lx\n", sptr, *sptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) unw_debug("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) table = find_table(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (table != NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) && !(table->size & (sizeof(*fde) - 1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) const u8 *hdr = table->header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) unsigned long tableSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) smp_rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (hdr && hdr[0] == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) switch (hdr[3] & DW_EH_PE_FORM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case DW_EH_PE_native:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) tableSize = sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) case DW_EH_PE_data2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) tableSize = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) case DW_EH_PE_data4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) tableSize = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case DW_EH_PE_data8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) tableSize = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) tableSize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) ptr = hdr + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) end = hdr + table->hdrsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if (tableSize && read_pointer(&ptr, end, hdr[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) == (unsigned long)table->address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) && (i = read_pointer(&ptr, end, hdr[2])) > 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) && i == (end - ptr) / (2 * tableSize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) && !((end - ptr) % (2 * tableSize))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) const u8 *cur =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) ptr + (i / 2) * (2 * tableSize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) startLoc = read_pointer(&cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) cur + tableSize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) hdr[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (pc < startLoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) i /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) ptr = cur - tableSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) i = (i + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) } while (startLoc && i > 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (i == 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) && (startLoc = read_pointer(&ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ptr + tableSize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) hdr[3])) != 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) && pc >= startLoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) fde = (void *)read_pointer(&ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) ptr +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) tableSize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) hdr[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (fde != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) cie = cie_for_fde(fde, table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) ptr = (const u8 *)(fde + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (cie != NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) && cie != &bad_cie
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) && cie != ¬_fde
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) && (ptrType = fde_pointer_type(cie)) >= 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) && read_pointer(&ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) (const u8 *)(fde + 1) + *fde,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ptrType) == startLoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (!(ptrType & DW_EH_PE_indirect))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) ptrType &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) DW_EH_PE_FORM | DW_EH_PE_signed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) endLoc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) startLoc + read_pointer(&ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) (const u8 *)(fde +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 1) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *fde, ptrType);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) if (pc >= endLoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) fde = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) cie = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) fde = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) cie = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (cie != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) memset(&state, 0, sizeof(state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) state.cieEnd = ptr; /* keep here temporarily */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) ptr = (const u8 *)(cie + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) end = (const u8 *)(cie + 1) + *cie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) frame->call_frame = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (*++ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) /* check if augmentation size is first (thus present) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) if (*ptr == 'z') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) while (++ptr < end && *ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) switch (*ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /* chk for ignorable or already handled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * nul-terminated augmentation string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) case 'L':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case 'P':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) case 'R':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) case 'S':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) frame->call_frame = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (ptr >= end || *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) cie = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ++ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (cie != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /* get code alignment factor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) state.codeAlign = get_uleb128(&ptr, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /* get data alignment factor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) state.dataAlign = get_sleb128(&ptr, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) cie = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) retAddrReg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) unw_debug("CIE Frame Info:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) unw_debug("return Address register 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) retAddrReg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) unw_debug("data Align: %ld\n", state.dataAlign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) unw_debug("code Align: %lu\n", state.codeAlign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /* skip augmentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (((const char *)(cie + 2))[1] == 'z') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) uleb128_t augSize = get_uleb128(&ptr, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ptr += augSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) || REG_INVALID(retAddrReg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) || reg_info[retAddrReg].width !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) cie = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (cie != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) state.cieStart = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) ptr = state.cieEnd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) state.cieEnd = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) end = (const u8 *)(fde + 1) + *fde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) /* skip augmentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (((const char *)(cie + 2))[1] == 'z') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) uleb128_t augSize = get_uleb128(&ptr, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if ((ptr += augSize) > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) fde = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (cie == NULL || fde == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) #ifdef CONFIG_FRAME_POINTER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) unsigned long top, bottom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) top = STACK_TOP_UNW(frame->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) bottom = STACK_BOTTOM_UNW(frame->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) #if FRAME_RETADDR_OFFSET < 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) && bottom < UNW_FP(frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) && bottom > UNW_FP(frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) && !((UNW_SP(frame) | UNW_FP(frame))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) & (sizeof(unsigned long) - 1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) unsigned long link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (!__get_user(link, (unsigned long *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) (UNW_FP(frame) + FRAME_LINK_OFFSET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) #if FRAME_RETADDR_OFFSET < 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) && link > bottom && link < UNW_FP(frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) && link > UNW_FP(frame) && link < bottom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) && !(link & (sizeof(link) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) && !__get_user(UNW_PC(frame),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) (unsigned long *)(UNW_FP(frame)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) + FRAME_RETADDR_OFFSET)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) UNW_SP(frame) =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) UNW_FP(frame) + FRAME_RETADDR_OFFSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) #if FRAME_RETADDR_OFFSET < 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) sizeof(UNW_PC(frame));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) UNW_FP(frame) = link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) state.org = startLoc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) unw_debug("\nProcess instructions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /* process instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) * For ARC, we optimize by having blink(retAddrReg) with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) * the sameValue in the leaf function, so we should not check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) * state.regs[retAddrReg].where == Nowhere
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (!processCFI(ptr, end, pc, ptrType, &state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) || state.loc > endLoc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) /* || state.regs[retAddrReg].where == Nowhere */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) || state.cfa.reg >= ARRAY_SIZE(reg_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) || reg_info[state.cfa.reg].width != sizeof(unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) || state.cfa.offs % sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) #ifdef UNWIND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) unw_debug("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (REG_INVALID(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) switch (state.regs[i].where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) case Nowhere:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) case Memory:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) case Register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) case Value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) unw_debug("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) /* update frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) if (frame->call_frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) frame->call_frame = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) startLoc = min(STACK_LIMIT(cfa), cfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) endLoc = max(STACK_LIMIT(cfa), cfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx => 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) state.cfa.reg, state.cfa.offs, cfa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (REG_INVALID(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (state.regs[i].where == Nowhere)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) switch (state.regs[i].where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) case Register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (state.regs[i].value >= ARRAY_SIZE(reg_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) || REG_INVALID(state.regs[i].value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) || reg_info[i].width >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) reg_info[state.regs[i].value].width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) switch (reg_info[state.regs[i].value].width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) case sizeof(u8):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) state.regs[i].value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) FRAME_REG(state.regs[i].value, const u8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) case sizeof(u16):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) state.regs[i].value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) FRAME_REG(state.regs[i].value, const u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) case sizeof(u32):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) state.regs[i].value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) FRAME_REG(state.regs[i].value, const u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) case sizeof(u64):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) state.regs[i].value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) FRAME_REG(state.regs[i].value, const u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) unw_debug("\nRegister state after evaluation with realtime Stack:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) fptr = (unsigned long *)(&frame->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) if (REG_INVALID(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) switch (state.regs[i].where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) case Nowhere:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (reg_info[i].width != sizeof(UNW_SP(frame))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) != &UNW_SP(frame))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) UNW_SP(frame) = cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) case Register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) switch (reg_info[i].width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) case sizeof(u8):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) FRAME_REG(i, u8) = state.regs[i].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) case sizeof(u16):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) FRAME_REG(i, u16) = state.regs[i].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) case sizeof(u32):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) FRAME_REG(i, u32) = state.regs[i].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) case sizeof(u64):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) FRAME_REG(i, u64) = state.regs[i].value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) case Value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (reg_info[i].width != sizeof(unsigned long))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * state.dataAlign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) case Memory:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) addr = cfa + state.regs[i].value * state.dataAlign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if ((state.regs[i].value * state.dataAlign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) % sizeof(unsigned long)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) || addr < startLoc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) || addr + sizeof(unsigned long) < addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) || addr + sizeof(unsigned long) > endLoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) switch (reg_info[i].width) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) case sizeof(u8):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) __get_user(FRAME_REG(i, u8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) (u8 __user *)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) case sizeof(u16):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) __get_user(FRAME_REG(i, u16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) (u16 __user *)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) case sizeof(u32):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) __get_user(FRAME_REG(i, u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) (u32 __user *)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) case sizeof(u64):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) __get_user(FRAME_REG(i, u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) (u64 __user *)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) unw_debug("r%d: 0x%lx ", i, *fptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) #undef FRAME_REG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) EXPORT_SYMBOL(arc_unwind);