]>
Commit | Line | Data |
---|---|---|
949e84da FCE |
1 | /* -*- linux-c -*- |
2 | * | |
3 | * dwarf unwinder header file | |
4285dc9a | 4 | * Copyright (C) 2008, 2009 Red Hat Inc. |
949e84da FCE |
5 | * Copyright (C) 2002-2006 Novell, Inc. |
6 | * | |
7 | * This file is part of systemtap, and is free software. You can | |
8 | * redistribute it and/or modify it under the terms of the GNU General | |
9 | * Public License (GPL); either version 2, or (at your option) any | |
10 | * later version. | |
11 | */ | |
12 | ||
13 | #ifndef _STP_UNWIND_H_ | |
14 | #define _STP_UNWIND_H_ | |
15 | ||
ca1655b0 FCE |
16 | #ifdef STP_USE_DWARF_UNWINDER |
17 | ||
949e84da FCE |
18 | #if defined (__x86_64__) |
19 | #include "x86_64.h" | |
20 | #elif defined (__i386__) | |
21 | #include "i386.h" | |
22 | #else | |
23 | #error "Unsupported dwarf unwind architecture" | |
24 | #endif | |
25 | ||
9afe68ed | 26 | #define STP_MAX_STACK_DEPTH 8 |
949e84da | 27 | |
f1743f00 FCE |
28 | #ifndef BUILD_BUG_ON_ZERO |
29 | #define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1) | |
30 | #endif | |
31 | ||
32 | ||
949e84da FCE |
33 | #define EXTRA_INFO(f) { \ |
34 | BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \ | |
35 | % FIELD_SIZEOF(struct unwind_frame_info, f)) \ | |
36 | + offsetof(struct unwind_frame_info, f) \ | |
37 | / FIELD_SIZEOF(struct unwind_frame_info, f), \ | |
38 | FIELD_SIZEOF(struct unwind_frame_info, f) \ | |
39 | } | |
40 | #define PTREGS_INFO(f) EXTRA_INFO(regs.f) | |
41 | ||
42 | static const struct { | |
43 | unsigned offs:BITS_PER_LONG / 2; | |
44 | unsigned width:BITS_PER_LONG / 2; | |
45 | } reg_info[] = { | |
46 | UNW_REGISTER_INFO | |
47 | }; | |
48 | ||
49 | #undef PTREGS_INFO | |
50 | #undef EXTRA_INFO | |
51 | ||
52 | #ifndef REG_INVALID | |
53 | #define REG_INVALID(r) (reg_info[r].width == 0) | |
54 | #endif | |
55 | ||
56 | #define DW_CFA_nop 0x00 | |
57 | #define DW_CFA_set_loc 0x01 | |
58 | #define DW_CFA_advance_loc1 0x02 | |
59 | #define DW_CFA_advance_loc2 0x03 | |
60 | #define DW_CFA_advance_loc4 0x04 | |
61 | #define DW_CFA_offset_extended 0x05 | |
62 | #define DW_CFA_restore_extended 0x06 | |
63 | #define DW_CFA_undefined 0x07 | |
64 | #define DW_CFA_same_value 0x08 | |
65 | #define DW_CFA_register 0x09 | |
66 | #define DW_CFA_remember_state 0x0a | |
67 | #define DW_CFA_restore_state 0x0b | |
68 | #define DW_CFA_def_cfa 0x0c | |
69 | #define DW_CFA_def_cfa_register 0x0d | |
70 | #define DW_CFA_def_cfa_offset 0x0e | |
71 | #define DW_CFA_def_cfa_expression 0x0f | |
72 | #define DW_CFA_expression 0x10 | |
73 | #define DW_CFA_offset_extended_sf 0x11 | |
74 | #define DW_CFA_def_cfa_sf 0x12 | |
75 | #define DW_CFA_def_cfa_offset_sf 0x13 | |
76 | #define DW_CFA_val_offset 0x14 | |
77 | #define DW_CFA_val_offset_sf 0x15 | |
78 | #define DW_CFA_val_expression 0x16 | |
79 | #define DW_CFA_lo_user 0x1c | |
80 | #define DW_CFA_GNU_window_save 0x2d | |
81 | #define DW_CFA_GNU_args_size 0x2e | |
82 | #define DW_CFA_GNU_negative_offset_extended 0x2f | |
83 | #define DW_CFA_hi_user 0x3f | |
84 | ||
85 | #define DW_EH_PE_absptr 0x00 | |
86 | #define DW_EH_PE_leb128 0x01 | |
87 | #define DW_EH_PE_data2 0x02 | |
88 | #define DW_EH_PE_data4 0x03 | |
89 | #define DW_EH_PE_data8 0x04 | |
90 | #define DW_EH_PE_FORM 0x07 /* mask */ | |
91 | #define DW_EH_PE_signed 0x08 /* signed versions of above have this bit set */ | |
92 | ||
93 | #define DW_EH_PE_pcrel 0x10 | |
94 | #define DW_EH_PE_textrel 0x20 | |
95 | #define DW_EH_PE_datarel 0x30 | |
96 | #define DW_EH_PE_funcrel 0x40 | |
97 | #define DW_EH_PE_aligned 0x50 | |
98 | #define DW_EH_PE_ADJUST 0x70 /* mask */ | |
99 | #define DW_EH_PE_indirect 0x80 | |
100 | #define DW_EH_PE_omit 0xff | |
101 | ||
102 | typedef unsigned long uleb128_t; | |
103 | typedef signed long sleb128_t; | |
104 | ||
105 | static struct unwind_table { | |
106 | unsigned long pc; /* text */ | |
107 | unsigned long range; /* text_size */ | |
108 | const void *address; /* unwind_data */ | |
109 | unsigned long size; /* unwind_data_len */ | |
110 | const unsigned char *header; /* unwind_header */ | |
111 | unsigned long hdrsz; | |
112 | struct unwind_table *link; | |
113 | const char *name; /* module name */ | |
114 | } root_table; | |
115 | ||
116 | struct unwind_item { | |
117 | enum item_location { | |
118 | Nowhere, | |
119 | Memory, | |
120 | Register, | |
121 | Value | |
122 | } where; | |
123 | uleb128_t value; | |
124 | }; | |
125 | ||
126 | struct unwind_state { | |
127 | uleb128_t loc, org; | |
128 | const u8 *cieStart, *cieEnd; | |
129 | uleb128_t codeAlign; | |
130 | sleb128_t dataAlign; | |
131 | struct cfa { | |
132 | uleb128_t reg, offs; | |
133 | } cfa; | |
134 | struct unwind_item regs[ARRAY_SIZE(reg_info)]; | |
135 | unsigned stackDepth:8; | |
136 | unsigned version:8; | |
137 | const u8 *label; | |
9afe68ed | 138 | const u8 *stack[STP_MAX_STACK_DEPTH]; |
949e84da FCE |
139 | }; |
140 | ||
141 | static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 }; | |
142 | static unsigned long read_pointer(const u8 **pLoc, | |
143 | const void *end, | |
144 | signed ptrType); | |
145 | static const u32 bad_cie, not_fde; | |
bf043a5f MW |
146 | static const u32 *cie_for_fde(const u32 *fde, void *table, |
147 | uint32_t table_len, int is_ehframe); | |
148 | static signed fde_pointer_type(const u32 *cie, | |
149 | void *table, uint32_t table_len); | |
949e84da | 150 | |
ca1655b0 FCE |
151 | |
152 | #endif /* STP_USE_DWARF_UNWINDER */ | |
949e84da | 153 | #endif /*_STP_UNWIND_H_*/ |