30 template<
typename T> T
static get(
char **p)
31 {
auto v = *
reinterpret_cast<T *
>(*p); (*p) +=
sizeof(T);
return v;}
44 #define REMEMBER_STACK_SIZE 10 45 #define EXPRESSION_STACK_SIZE 100 66 uint64_t
index()
const 72 uint64_t value()
const 75 void set_index(uint64_t index)
81 void set_value(uint64_t value)
111 uint64_t value()
const 117 cfi_cfa_type
type()
const 120 void set_value(uint64_t value)
123 void set_offset(int64_t
offset)
126 void set_type(cfi_cfa_type
type)
146 m_registers[i].set_index(i);
149 const cfi_cfa &cfa()
const 152 uint64_t arg_size()
const 153 {
return m_arg_size; }
155 const cfi_register &
reg(uint64_t
index)
const 157 if (index >= MAX_NUM_REGISTERS)
158 ABORT(
"index out of bounds. increase MAX_NUM_REGISTERS");
160 return m_registers[
index];
163 void set_cfa(
const cfi_cfa &cfa)
166 void set_arg_size(uint64_t arg_size)
167 { m_arg_size = arg_size; }
169 void set_reg(
const cfi_register &
reg)
172 ABORT(
"index out of bounds. increase MAX_NUM_REGISTERS");
174 m_registers[reg.index()] =
reg;
179 if (index >= MAX_NUM_REGISTERS)
180 ABORT(
"index out of bounds. increase MAX_NUM_REGISTERS");
182 m_registers[
index].set_rule(rule);
185 void set_reg(uint64_t index, uint64_t value)
187 if (index >= MAX_NUM_REGISTERS)
188 ABORT(
"index out of bounds. increase MAX_NUM_REGISTERS");
190 m_registers[
index].set_value(value);
208 private_parse_expression(
char *p,
209 uint64_t initialStackValue,
215 stack[i] = initialStackValue;
221 uint8_t opcode = *
reinterpret_cast<uint8_t *
>(p);
225 ABORT(
"out of DWARF expression stack space");
231 stack[++i] = *
reinterpret_cast<uint64_t *
>(p);
232 p +=
sizeof(uint64_t);
239 ABORT(
"DW_OP_deref: attempted to dereference nullptr");
241 stack[i] = *
reinterpret_cast<uint64_t *
>(stack[i]);
247 stack[++i] =
static_cast<uint64_t
>(*
reinterpret_cast<uint8_t *
>(p));
248 p +=
sizeof(uint8_t);
254 stack[++i] =
static_cast<uint64_t
>(*
reinterpret_cast<int8_t *
>(p));
261 stack[++i] =
static_cast<uint64_t
>(*
reinterpret_cast<uint16_t *
>(p));
262 p +=
sizeof(uint16_t);
268 stack[++i] =
static_cast<uint64_t
>(*
reinterpret_cast<int16_t *
>(p));
269 p +=
sizeof(int16_t);
275 stack[++i] =
static_cast<uint64_t
>(*
reinterpret_cast<uint32_t *
>(p));
276 p +=
sizeof(uint32_t);
282 stack[++i] =
static_cast<uint64_t
>(*
reinterpret_cast<int32_t *
>(p));
283 p +=
sizeof(int32_t);
289 stack[++i] = *
reinterpret_cast<uint64_t *
>(p);
290 p +=
sizeof(uint64_t);
296 stack[++i] =
static_cast<uint64_t
>(*
reinterpret_cast<int64_t *
>(p));
297 p +=
sizeof(int64_t);
315 auto value = stack[i];
323 ABORT(
"DW_OP_drop out-of-bounds");
331 ABORT(
"DW_OP_over out-of-bounds");
332 auto value = stack[i - 1];
339 auto index = *
reinterpret_cast<uint8_t *
>(p);
340 p +=
sizeof(uint8_t);
343 ABORT(
"DW_OP_pick out-of-bounds");
345 auto value = stack[i -
index];
353 ABORT(
"DW_OP_swap out-of-bounds");
355 auto value = stack[i];
356 stack[i] = stack[i - 1];
357 stack[i - 1] = value;
364 ABORT(
"DW_OP_swap out-of-bounds");
366 auto value = stack[i];
367 stack[i] = stack[i - 1];
368 stack[i - 1] = stack[i - 2];
369 stack[i - 2] = value;
376 ABORT(
"DW_OP_xderef out-of-bounds");
378 auto value = stack[i--];
381 ABORT(
"DW_OP_deref: attempted to dereference nullptr");
383 stack[i] = *
reinterpret_cast<uint64_t *
>(value);
389 auto value =
static_cast<int64_t
>(stack[i]);
391 stack[i] =
static_cast<uint64_t
>(-value);
398 ABORT(
"DW_OP_and out-of-bounds");
400 auto value = stack[i--];
408 ABORT(
"DW_OP_minus out-of-bounds");
410 auto value = stack[i--];
418 ABORT(
"DW_OP_minus out-of-bounds");
420 auto value = stack[i--];
427 stack[i] =
static_cast<uint64_t
>(0 -
static_cast<int64_t
>(stack[i]));
433 stack[i] = ~stack[i];
440 ABORT(
"DW_OP_or out-of-bounds");
442 auto value = stack[i--];
450 ABORT(
"DW_OP_plus out-of-bounds");
452 auto value = stack[i--];
466 ABORT(
"DW_OP_shl out-of-bounds");
468 auto value = stack[i--];
469 stack[i] = stack[i] << value;
476 ABORT(
"DW_OP_shr out-of-bounds");
478 auto value = stack[i--];
479 stack[i] = stack[i] >> value;
486 ABORT(
"DW_OP_shra out-of-bounds");
488 auto value1 = stack[i--];
489 auto value2 =
static_cast<int64_t
>(stack[i]);
490 stack[i] =
static_cast<uint64_t
>(value2 >> value1);
497 ABORT(
"DW_OP_xor out-of-bounds");
499 auto value = stack[i--];
506 auto value = *
reinterpret_cast<int16_t *
>(p);
515 ABORT(
"DW_OP_bra out-of-bounds");
517 auto value = *
reinterpret_cast<int16_t *
>(p);
527 ABORT(
"DW_OP_eq out-of-bounds");
529 auto value = stack[i--];
530 stack[i] = (stack[i] == value) ? 1 : 0;
537 ABORT(
"DW_OP_ge out-of-bounds");
539 auto value = stack[i--];
540 stack[i] = (stack[i] >= value) ? 1 : 0;
547 ABORT(
"DW_OP_gt out-of-bounds");
549 auto value = stack[i--];
550 stack[i] = (stack[i] > value) ? 1 : 0;
557 ABORT(
"DW_OP_le out-of-bounds");
559 auto value = stack[i--];
560 stack[i] = (stack[i] <= value) ? 1 : 0;
567 ABORT(
"DW_OP_lt out-of-bounds");
569 auto value = stack[i--];
570 stack[i] = (stack[i] < value) ? 1 : 0;
577 ABORT(
"DW_OP_ne out-of-bounds");
579 auto value = stack[i--];
580 stack[i] = (stack[i] != value) ? 1 : 0;
778 stack[++i] = state->
get(0);
784 stack[++i] = state->
get(1);
790 stack[++i] = state->
get(2);
796 stack[++i] = state->
get(3);
802 stack[++i] = state->
get(4);
808 stack[++i] = state->
get(5);
814 stack[++i] = state->
get(6);
820 stack[++i] = state->
get(7);
826 stack[++i] = state->
get(8);
832 stack[++i] = state->
get(9);
838 stack[++i] = state->
get(10);
844 stack[++i] = state->
get(11);
850 stack[++i] = state->
get(12);
856 stack[++i] = state->
get(13);
862 stack[++i] = state->
get(14);
868 stack[++i] = state->
get(15);
874 stack[++i] = state->
get(16);
880 stack[++i] = state->
get(17);
886 stack[++i] = state->
get(18);
892 stack[++i] = state->
get(19);
898 stack[++i] = state->
get(20);
904 stack[++i] = state->
get(21);
910 stack[++i] = state->
get(22);
916 stack[++i] = state->
get(23);
922 stack[++i] = state->
get(24);
928 stack[++i] = state->
get(25);
934 stack[++i] = state->
get(26);
940 stack[++i] = state->
get(27);
946 stack[++i] = state->
get(28);
952 stack[++i] = state->
get(29);
958 stack[++i] = state->
get(30);
964 stack[++i] = state->
get(31);
970 auto reg = state->
get(0);
978 auto reg = state->
get(1);
986 auto reg = state->
get(2);
994 auto reg = state->
get(3);
1002 auto reg = state->
get(4);
1010 auto reg = state->
get(5);
1018 auto reg = state->
get(6);
1026 auto reg = state->
get(7);
1034 auto reg = state->
get(8);
1042 auto reg = state->
get(9);
1050 auto reg = state->
get(10);
1058 auto reg = state->
get(11);
1066 auto reg = state->
get(12);
1074 auto reg = state->
get(13);
1082 auto reg = state->
get(14);
1090 auto reg = state->
get(15);
1098 auto reg = state->
get(16);
1106 auto reg = state->
get(17);
1114 auto reg = state->
get(18);
1122 auto reg = state->
get(19);
1130 auto reg = state->
get(20);
1138 auto reg = state->
get(21);
1146 auto reg = state->
get(22);
1154 auto reg = state->
get(23);
1162 auto reg = state->
get(24);
1170 auto reg = state->
get(25);
1178 auto reg = state->
get(26);
1186 auto reg = state->
get(27);
1194 auto reg = state->
get(28);
1202 auto reg = state->
get(29);
1210 auto reg = state->
get(30);
1218 auto reg = state->
get(31);
1240 ABORT(
"DW_OP_deref: attempted to dereference nullptr");
1242 switch (*reinterpret_cast<uint8_t *>(p++))
1245 stack[i] = *
reinterpret_cast<uint8_t *
>(stack[i]);
1249 stack[i] = *
reinterpret_cast<uint16_t *
>(stack[i]);
1253 stack[i] = *
reinterpret_cast<uint32_t *
>(stack[i]);
1257 stack[i] = *
reinterpret_cast<uint64_t *
>(stack[i]);
1261 ABORT(
"DW_OP_deref_size: invalid size");
1268 ABORT(
"DWARF expression opcode not supported");
1276 private_decode_cfa(
const cfi_table_row &row,
register_state *state)
1279 const auto &cfa = row.cfa();
1283 case cfi_cfa::cfa_register:
1287 case cfi_cfa::cfa_expression:
1288 value = private_parse_expression(reinterpret_cast<char *>(cfa.value()), 0, state);
1296 private_decode_reg(
const cfi_register ®, uint64_t cfa,
register_state *state)
1303 ABORT(
"unable to get register value for unused register");
1307 value = state->
get(reg.index());
1311 value = *
reinterpret_cast<uint64_t *
>(
add_offset(cfa, static_cast<int64_t>(reg.value())));
1315 value =
add_offset(cfa, static_cast<int64_t>(reg.value()));
1319 value = state->
get(reg.value());
1323 value = private_parse_expression(reinterpret_cast<char *>(reg.value()), cfa, state);
1324 value = *
reinterpret_cast<uint64_t *
>(value);
1328 value = private_parse_expression(reinterpret_cast<char *>(reg.value()), cfa, state);
1332 ABORT(
"unknown rule. cfi table is malformed");
1346 uint64_t &rememberIndex,
1347 cfi_table_row *rememberStack,
1348 cfi_table_row *initialRow)
1354 uint8_t opcode = *
reinterpret_cast<uint8_t *
>(*p) & 0xC0;
1355 uint8_t operand = *
reinterpret_cast<uint8_t *
>(*p) & 0x3F;
1373 row->set_reg(cfi_register(operand,
rule_offsetn, static_cast<uint64_t>(value)));
1379 row->set_reg(initialRow->reg(operand));
1416 row->set_reg(cfi_register(reg,
rule_offsetn, static_cast<uint64_t>(value)));
1423 row->set_reg(initialRow->reg(reg));
1445 row->set_reg(reg1, row->reg(reg2).rule());
1452 ABORT(
"remember stack is full. unable to continue unwind");
1454 rememberStack[rememberIndex++] = *row;
1460 if (rememberIndex == 0)
1461 ABORT(
"remember stack is empty. unable to continue unwind");
1463 *row = rememberStack[--rememberIndex];
1469 auto cfa = row->cfa();
1478 auto cfa = row->cfa();
1486 auto cfa = row->cfa();
1494 auto cfa = row->cfa();
1495 cfa.set_value(reinterpret_cast<uint64_t>(*p));
1496 cfa.set_type(cfi_cfa::cfa_expression);
1505 auto value =
reinterpret_cast<uint64_t
>(*p);
1515 row->set_reg(cfi_register(reg,
rule_offsetn, static_cast<uint64_t>(value)));
1521 auto cfa = row->cfa();
1530 auto cfa = row->cfa();
1540 row->set_reg(cfi_register(reg,
rule_val_offsetn, static_cast<uint64_t>(value)));
1548 row->set_reg(cfi_register(reg,
rule_val_offsetn, static_cast<uint64_t>(value)));
1555 auto value =
reinterpret_cast<uint64_t
>(*p);
1564 row->set_arg_size(arg_size);
1572 row->set_reg(cfi_register(reg,
rule_offsetn, static_cast<uint64_t>(-value)));
1577 ABORT(
"unknown cfi cfa");
1582 private_parse_instructions(cfi_table_row *row,
1588 uint64_t pc_begin = is_cie ? 0 : fde.
pc_begin();
1595 uint64_t rememberIndex = 0ULL;
1598 auto initialRow = *row;
1600 while (p < end && l1 >= l2)
1602 rememberIndex, rememberStack, &initialRow);
1608 auto row = cfi_table_row();
1609 const auto &cie = fde.
cie();
1611 private_parse_instructions(&row, cie, fde, state,
true);
1612 private_parse_instructions(&row, cie, fde, state,
false);
1630 byte = *(
reinterpret_cast<uint8_t *
>((*addr)++));
1631 result |= ((byte & 0x7f) << shift);
1633 if ((byte & 0x80) == 0)
1637 if ((shift < 0x40) && (byte & 0x40) != 0)
1638 result |= -(1LL << shift);
1648 uint64_t result = 0;
1652 byte = *(
reinterpret_cast<uint8_t *
>((*addr)++));
1653 result |= ((byte & 0x7f) << shift);
1655 if ((byte & 0x80) == 0)
1663 #pragma GCC diagnostic push 1664 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 1670 if (state ==
nullptr)
1674 auto cfa = private_decode_cfa(row, state);
1678 auto reg = row.reg(i);
1683 state->
set(i, private_decode_reg(reg, cfa, state));
1686 state->
commit(cfa + row.arg_size());
1690 #pragma GCC diagnostic pop #define DW_CFA_same_value
static void unwind(const fd_entry &fde, register_state *state=nullptr)
const ci_entry & cie() const
#define DW_CFA_val_expression
#define MAX_NUM_REGISTERS
static uint64_t decode_uleb128(char **addr)
uint64_t pc_begin() const
uint64_t pointer_encoding() const
#define DW_CFA_val_offset_sf
cfi_table_row private_decode_cfi(const fd_entry &fde, register_state *state)
#define DW_CFA_expression
#define DW_CFA_restore_state
static int64_t decode_sleb128(char **addr)
char * initial_instructions() const
#define DW_CFA_def_cfa_offset
void private_parse_instruction(cfi_table_row *row, const ci_entry &cie, char **p, uint64_t *l1, uint64_t *l2, uint64_t pc_begin, register_state *state, uint64_t &rememberIndex, cfi_table_row *rememberStack, cfi_table_row *initialRow)
#define DW_CFA_offset_extended
#define DW_CFA_def_cfa_register
#define DW_OP_plus_uconst
#define DW_CFA_offset_extended_sf
uint64_t add_offset(uint64_t value, int64_t offset)
virtual uint64_t max_num_registers() const
virtual uint64_t get(uint64_t index) const
auto index(const T virt, const F from)
constexpr const auto addr
#define DW_CFA_GNU_negative_offset_extended
uint64_t decode_pointer(char **addr, uint64_t encoding)
#define DW_CFA_advance_loc4
#define DW_CFA_def_cfa_sf
uint64_t code_alignment() const
#define DW_CFA_advance_loc1
#define DW_CFA_def_cfa_offset_sf
#define EXPRESSION_STACK_SIZE
virtual register_state & set(uint64_t index, uint64_t value)
#define DW_CFA_val_offset
#define DW_CFA_remember_state
char * instructions() const
auto end(reversed_container< T > container) -> decltype(container.container.rend())
#define DW_CFA_advance_loc
#define DW_CFA_def_cfa_expression
#define REMEMBER_STACK_SIZE
virtual uint64_t get_ip() const
int64_t data_alignment() const
#define DW_CFA_restore_extended
#define DW_CFA_GNU_args_size
#define DW_CFA_advance_loc2