/src/libunwind/include/dwarf_i.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef DWARF_I_H |
2 | | #define DWARF_I_H |
3 | | |
4 | | /* This file contains definitions that cannot be used in code outside |
5 | | of libunwind. In particular, most inline functions are here |
6 | | because otherwise they'd generate unresolved references when the |
7 | | files are compiled with inlining disabled. */ |
8 | | |
9 | | #include "dwarf.h" |
10 | | #include "libunwind_i.h" |
11 | | |
12 | | /* Unless we are told otherwise, assume that a "machine address" is |
13 | | the size of an unw_word_t. */ |
14 | | #ifndef dwarf_addr_size |
15 | 75 | # define dwarf_addr_size(as) (sizeof (unw_word_t)) |
16 | | #endif |
17 | | |
18 | | #ifndef dwarf_to_unw_regnum |
19 | 48.0k | # define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map) |
20 | | extern const uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH]; |
21 | | /* REG is evaluated multiple times; it better be side-effects free! */ |
22 | | # define dwarf_to_unw_regnum(reg) \ |
23 | 48.0k | (((reg) < DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0) |
24 | | #endif |
25 | | |
26 | | #ifdef UNW_LOCAL_ONLY |
27 | | |
28 | | /* In the local-only case, we can let the compiler directly access |
29 | | memory and don't need to worry about differing byte-order. */ |
30 | | |
31 | | typedef union __attribute__ ((packed)) |
32 | | { |
33 | | int8_t s8; |
34 | | int16_t s16; |
35 | | int32_t s32; |
36 | | int64_t s64; |
37 | | uint8_t u8; |
38 | | uint16_t u16; |
39 | | uint32_t u32; |
40 | | uint64_t u64; |
41 | | void *ptr; |
42 | | } |
43 | | dwarf_misaligned_value_t; |
44 | | |
45 | | static inline int |
46 | | dwarf_reads8 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
47 | | int8_t *val, void *arg UNUSED) |
48 | 0 | { |
49 | 0 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
50 | 0 |
|
51 | 0 | *val = mvp->s8; |
52 | 0 | *addr += sizeof (mvp->s8); |
53 | 0 | return 0; |
54 | 0 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_reads8 Unexecuted instantiation: Lglobal.c:dwarf_reads8 Unexecuted instantiation: Lparser.c:dwarf_reads8 Unexecuted instantiation: Lpe.c:dwarf_reads8 Unexecuted instantiation: Lexpr.c:dwarf_reads8 Unexecuted instantiation: Lfde.c:dwarf_reads8 |
55 | | |
56 | | static inline int |
57 | | dwarf_reads16 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
58 | | int16_t *val, void *arg UNUSED) |
59 | 0 | { |
60 | 0 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
61 | |
|
62 | 0 | *val = mvp->s16; |
63 | 0 | *addr += sizeof (mvp->s16); |
64 | 0 | return 0; |
65 | 0 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_reads16 Unexecuted instantiation: Lglobal.c:dwarf_reads16 Unexecuted instantiation: Lparser.c:dwarf_reads16 Unexecuted instantiation: Lpe.c:dwarf_reads16 Unexecuted instantiation: Lexpr.c:dwarf_reads16 Unexecuted instantiation: Lfde.c:dwarf_reads16 |
66 | | |
67 | | static inline int |
68 | | dwarf_reads32 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
69 | | int32_t *val, void *arg UNUSED) |
70 | 60 | { |
71 | 60 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
72 | | |
73 | 60 | *val = mvp->s32; |
74 | 60 | *addr += sizeof (mvp->s32); |
75 | 60 | return 0; |
76 | 60 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_reads32 Unexecuted instantiation: Lglobal.c:dwarf_reads32 Unexecuted instantiation: Lparser.c:dwarf_reads32 Line | Count | Source | 70 | 45 | { | 71 | 45 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; | 72 | | | 73 | 45 | *val = mvp->s32; | 74 | 45 | *addr += sizeof (mvp->s32); | 75 | 45 | return 0; | 76 | 45 | } |
Unexecuted instantiation: Lexpr.c:dwarf_reads32 Line | Count | Source | 70 | 15 | { | 71 | 15 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; | 72 | | | 73 | 15 | *val = mvp->s32; | 74 | 15 | *addr += sizeof (mvp->s32); | 75 | 15 | return 0; | 76 | 15 | } |
|
77 | | |
78 | | static inline int |
79 | | dwarf_reads64 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
80 | | int64_t *val, void *arg UNUSED) |
81 | 0 | { |
82 | 0 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
83 | |
|
84 | 0 | *val = mvp->s64; |
85 | 0 | *addr += sizeof (mvp->s64); |
86 | 0 | return 0; |
87 | 0 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_reads64 Unexecuted instantiation: Lglobal.c:dwarf_reads64 Unexecuted instantiation: Lparser.c:dwarf_reads64 Unexecuted instantiation: Lpe.c:dwarf_reads64 Unexecuted instantiation: Lexpr.c:dwarf_reads64 Unexecuted instantiation: Lfde.c:dwarf_reads64 |
88 | | |
89 | | static inline int |
90 | | dwarf_readu8 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
91 | | uint8_t *val, void *arg UNUSED) |
92 | 520 | { |
93 | 520 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
94 | | |
95 | 520 | *val = mvp->u8; |
96 | 520 | *addr += sizeof (mvp->u8); |
97 | 520 | return 0; |
98 | 520 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_readu8 Unexecuted instantiation: Lglobal.c:dwarf_readu8 Line | Count | Source | 92 | 370 | { | 93 | 370 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; | 94 | | | 95 | 370 | *val = mvp->u8; | 96 | 370 | *addr += sizeof (mvp->u8); | 97 | 370 | return 0; | 98 | 370 | } |
Unexecuted instantiation: Lpe.c:dwarf_readu8 Unexecuted instantiation: Lexpr.c:dwarf_readu8 Line | Count | Source | 92 | 150 | { | 93 | 150 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; | 94 | | | 95 | 150 | *val = mvp->u8; | 96 | 150 | *addr += sizeof (mvp->u8); | 97 | 150 | return 0; | 98 | 150 | } |
|
99 | | |
100 | | static inline int |
101 | | dwarf_readu16 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
102 | | uint16_t *val, void *arg UNUSED) |
103 | 7 | { |
104 | 7 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
105 | | |
106 | 7 | *val = mvp->u16; |
107 | 7 | *addr += sizeof (mvp->u16); |
108 | 7 | return 0; |
109 | 7 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_readu16 Unexecuted instantiation: Lglobal.c:dwarf_readu16 Line | Count | Source | 103 | 7 | { | 104 | 7 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; | 105 | | | 106 | 7 | *val = mvp->u16; | 107 | 7 | *addr += sizeof (mvp->u16); | 108 | 7 | return 0; | 109 | 7 | } |
Unexecuted instantiation: Lpe.c:dwarf_readu16 Unexecuted instantiation: Lexpr.c:dwarf_readu16 Unexecuted instantiation: Lfde.c:dwarf_readu16 |
110 | | |
111 | | static inline int |
112 | | dwarf_readu32 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
113 | | uint32_t *val, void *arg UNUSED) |
114 | 60 | { |
115 | 60 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
116 | | |
117 | 60 | *val = mvp->u32; |
118 | 60 | *addr += sizeof (mvp->u32); |
119 | 60 | return 0; |
120 | 60 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_readu32 Unexecuted instantiation: Lglobal.c:dwarf_readu32 Unexecuted instantiation: Lparser.c:dwarf_readu32 Line | Count | Source | 114 | 15 | { | 115 | 15 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; | 116 | | | 117 | 15 | *val = mvp->u32; | 118 | 15 | *addr += sizeof (mvp->u32); | 119 | 15 | return 0; | 120 | 15 | } |
Unexecuted instantiation: Lexpr.c:dwarf_readu32 Line | Count | Source | 114 | 45 | { | 115 | 45 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; | 116 | | | 117 | 45 | *val = mvp->u32; | 118 | 45 | *addr += sizeof (mvp->u32); | 119 | 45 | return 0; | 120 | 45 | } |
|
121 | | |
122 | | static inline int |
123 | | dwarf_readu64 (unw_addr_space_t as UNUSED, unw_accessors_t *a UNUSED, unw_word_t *addr, |
124 | | uint64_t *val, void *arg UNUSED) |
125 | 0 | { |
126 | 0 | dwarf_misaligned_value_t *mvp = (void *) (uintptr_t) *addr; |
127 | |
|
128 | 0 | *val = mvp->u64; |
129 | 0 | *addr += sizeof (mvp->u64); |
130 | 0 | return 0; |
131 | 0 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_readu64 Unexecuted instantiation: Lglobal.c:dwarf_readu64 Unexecuted instantiation: Lparser.c:dwarf_readu64 Unexecuted instantiation: Lpe.c:dwarf_readu64 Unexecuted instantiation: Lexpr.c:dwarf_readu64 Unexecuted instantiation: Lfde.c:dwarf_readu64 |
132 | | |
133 | | #else /* !UNW_LOCAL_ONLY */ |
134 | | |
135 | | static inline int |
136 | | dwarf_readu8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
137 | | uint8_t *valp, void *arg) |
138 | 0 | { |
139 | 0 | unw_word_t val, aligned_addr = *addr & (~sizeof (unw_word_t) + 1); |
140 | 0 | unw_word_t off = *addr - aligned_addr; |
141 | 0 | int ret; |
142 | 0 |
|
143 | 0 | *addr += 1; |
144 | 0 | ret = (*a->access_mem) (as, aligned_addr, &val, 0, arg); |
145 | 0 | #if UNW_BYTE_ORDER == UNW_LITTLE_ENDIAN |
146 | 0 | val >>= 8*off; |
147 | 0 | #else |
148 | 0 | val >>= 8*(sizeof (unw_word_t) - 1 - off); |
149 | 0 | #endif |
150 | 0 | *valp = (uint8_t) val; |
151 | 0 | return ret; |
152 | 0 | } |
153 | | |
154 | | static inline int |
155 | | dwarf_readu16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
156 | | uint16_t *val, void *arg) |
157 | 0 | { |
158 | 0 | uint8_t v0, v1; |
159 | 0 | int ret; |
160 | 0 |
|
161 | 0 | if ((ret = dwarf_readu8 (as, a, addr, &v0, arg)) < 0 |
162 | 0 | || (ret = dwarf_readu8 (as, a, addr, &v1, arg)) < 0) |
163 | 0 | return ret; |
164 | 0 |
|
165 | 0 | if (tdep_big_endian (as)) |
166 | 0 | *val = (uint16_t) v0 << 8 | v1; |
167 | 0 | else |
168 | 0 | *val = (uint16_t) v1 << 8 | v0; |
169 | 0 | return 0; |
170 | 0 | } |
171 | | |
172 | | static inline int |
173 | | dwarf_readu32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
174 | | uint32_t *val, void *arg) |
175 | 0 | { |
176 | 0 | uint16_t v0, v1; |
177 | 0 | int ret; |
178 | 0 |
|
179 | 0 | if ((ret = dwarf_readu16 (as, a, addr, &v0, arg)) < 0 |
180 | 0 | || (ret = dwarf_readu16 (as, a, addr, &v1, arg)) < 0) |
181 | 0 | return ret; |
182 | 0 |
|
183 | 0 | if (tdep_big_endian (as)) |
184 | 0 | *val = (uint32_t) v0 << 16 | v1; |
185 | 0 | else |
186 | 0 | *val = (uint32_t) v1 << 16 | v0; |
187 | 0 | return 0; |
188 | 0 | } |
189 | | |
190 | | static inline int |
191 | | dwarf_readu64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
192 | | uint64_t *val, void *arg) |
193 | 0 | { |
194 | 0 | uint32_t v0, v1; |
195 | 0 | int ret; |
196 | 0 |
|
197 | 0 | if ((ret = dwarf_readu32 (as, a, addr, &v0, arg)) < 0 |
198 | 0 | || (ret = dwarf_readu32 (as, a, addr, &v1, arg)) < 0) |
199 | 0 | return ret; |
200 | 0 |
|
201 | 0 | if (tdep_big_endian (as)) |
202 | 0 | *val = (uint64_t) v0 << 32 | v1; |
203 | 0 | else |
204 | 0 | *val = (uint64_t) v1 << 32 | v0; |
205 | 0 | return 0; |
206 | 0 | } |
207 | | |
208 | | static inline int |
209 | | dwarf_reads8 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
210 | | int8_t *val, void *arg) |
211 | 0 | { |
212 | 0 | uint8_t uval; |
213 | 0 | int ret; |
214 | 0 |
|
215 | 0 | if ((ret = dwarf_readu8 (as, a, addr, &uval, arg)) < 0) |
216 | 0 | return ret; |
217 | 0 | *val = (int8_t) uval; |
218 | 0 | return 0; |
219 | 0 | } |
220 | | |
221 | | static inline int |
222 | | dwarf_reads16 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
223 | | int16_t *val, void *arg) |
224 | 0 | { |
225 | 0 | uint16_t uval; |
226 | 0 | int ret; |
227 | 0 |
|
228 | 0 | if ((ret = dwarf_readu16 (as, a, addr, &uval, arg)) < 0) |
229 | 0 | return ret; |
230 | 0 | *val = (int16_t) uval; |
231 | 0 | return 0; |
232 | 0 | } |
233 | | |
234 | | static inline int |
235 | | dwarf_reads32 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
236 | | int32_t *val, void *arg) |
237 | 0 | { |
238 | 0 | uint32_t uval; |
239 | 0 | int ret; |
240 | 0 |
|
241 | 0 | if ((ret = dwarf_readu32 (as, a, addr, &uval, arg)) < 0) |
242 | 0 | return ret; |
243 | 0 | *val = (int32_t) uval; |
244 | 0 | return 0; |
245 | 0 | } |
246 | | |
247 | | static inline int |
248 | | dwarf_reads64 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
249 | | int64_t *val, void *arg) |
250 | 0 | { |
251 | 0 | uint64_t uval; |
252 | 0 | int ret; |
253 | 0 |
|
254 | 0 | if ((ret = dwarf_readu64 (as, a, addr, &uval, arg)) < 0) |
255 | 0 | return ret; |
256 | 0 | *val = (int64_t) uval; |
257 | 0 | return 0; |
258 | 0 | } |
259 | | |
260 | | #endif /* !UNW_LOCAL_ONLY */ |
261 | | |
262 | | static inline int |
263 | | dwarf_readw (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
264 | | unw_word_t *val, void *arg) |
265 | 0 | { |
266 | 0 | uint32_t u32; |
267 | 0 | uint64_t u64; |
268 | 0 | int ret; |
269 | |
|
270 | 0 | switch (dwarf_addr_size (as)) |
271 | 0 | { |
272 | 0 | case 4: |
273 | 0 | ret = dwarf_readu32 (as, a, addr, &u32, arg); |
274 | 0 | if (ret < 0) |
275 | 0 | return ret; |
276 | 0 | *val = u32; |
277 | 0 | return ret; |
278 | | |
279 | 0 | case 8: |
280 | 0 | ret = dwarf_readu64 (as, a, addr, &u64, arg); |
281 | 0 | if (ret < 0) |
282 | 0 | return ret; |
283 | 0 | *val = (unw_word_t) u64; |
284 | 0 | return ret; |
285 | | |
286 | 0 | default: |
287 | 0 | abort (); |
288 | 0 | } |
289 | 0 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_readw Unexecuted instantiation: Lglobal.c:dwarf_readw Unexecuted instantiation: Lparser.c:dwarf_readw Unexecuted instantiation: Lpe.c:dwarf_readw Unexecuted instantiation: global.c:dwarf_readw Unexecuted instantiation: Lexpr.c:dwarf_readw Unexecuted instantiation: Lfde.c:dwarf_readw |
290 | | |
291 | | /* Read an unsigned "little-endian base 128" value. See Chapter 7.6 |
292 | | of DWARF spec v3. */ |
293 | | |
294 | | static inline int |
295 | | dwarf_read_uleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
296 | | unw_word_t *valp, void *arg) |
297 | 187 | { |
298 | 187 | unw_word_t val = 0, shift = 0; |
299 | 187 | unsigned char byte; |
300 | 187 | int ret; |
301 | | |
302 | 187 | do |
303 | 188 | { |
304 | 188 | if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) |
305 | 0 | return ret; |
306 | | |
307 | 188 | val |= ((unw_word_t) byte & 0x7f) << shift; |
308 | 188 | shift += 7; |
309 | 188 | } |
310 | 188 | while (byte & 0x80); |
311 | | |
312 | 187 | *valp = val; |
313 | 187 | return 0; |
314 | 187 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_read_uleb128 Unexecuted instantiation: Lglobal.c:dwarf_read_uleb128 Lparser.c:dwarf_read_uleb128 Line | Count | Source | 297 | 142 | { | 298 | 142 | unw_word_t val = 0, shift = 0; | 299 | 142 | unsigned char byte; | 300 | 142 | int ret; | 301 | | | 302 | 142 | do | 303 | 143 | { | 304 | 143 | if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) | 305 | 0 | return ret; | 306 | | | 307 | 143 | val |= ((unw_word_t) byte & 0x7f) << shift; | 308 | 143 | shift += 7; | 309 | 143 | } | 310 | 143 | while (byte & 0x80); | 311 | | | 312 | 142 | *valp = val; | 313 | 142 | return 0; | 314 | 142 | } |
Unexecuted instantiation: Lpe.c:dwarf_read_uleb128 Unexecuted instantiation: global.c:dwarf_read_uleb128 Unexecuted instantiation: Lexpr.c:dwarf_read_uleb128 Lfde.c:dwarf_read_uleb128 Line | Count | Source | 297 | 45 | { | 298 | 45 | unw_word_t val = 0, shift = 0; | 299 | 45 | unsigned char byte; | 300 | 45 | int ret; | 301 | | | 302 | 45 | do | 303 | 45 | { | 304 | 45 | if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) | 305 | 0 | return ret; | 306 | | | 307 | 45 | val |= ((unw_word_t) byte & 0x7f) << shift; | 308 | 45 | shift += 7; | 309 | 45 | } | 310 | 45 | while (byte & 0x80); | 311 | | | 312 | 45 | *valp = val; | 313 | 45 | return 0; | 314 | 45 | } |
|
315 | | |
316 | | /* Read a signed "little-endian base 128" value. See Chapter 7.6 of |
317 | | DWARF spec v3. */ |
318 | | |
319 | | static inline int |
320 | | dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, |
321 | | unw_word_t *valp, void *arg) |
322 | 15 | { |
323 | 15 | unw_word_t val = 0, shift = 0; |
324 | 15 | unsigned char byte; |
325 | 15 | int ret; |
326 | | |
327 | 15 | do |
328 | 15 | { |
329 | 15 | if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) |
330 | 0 | return ret; |
331 | | |
332 | 15 | val |= ((unw_word_t) byte & 0x7f) << shift; |
333 | 15 | shift += 7; |
334 | 15 | } |
335 | 15 | while (byte & 0x80); |
336 | | |
337 | 15 | if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0) |
338 | | /* sign-extend negative value */ |
339 | 15 | val |= ((unw_word_t) -1) << shift; |
340 | | |
341 | 15 | *valp = val; |
342 | 15 | return 0; |
343 | 15 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_read_sleb128 Unexecuted instantiation: Lglobal.c:dwarf_read_sleb128 Unexecuted instantiation: Lparser.c:dwarf_read_sleb128 Unexecuted instantiation: Lpe.c:dwarf_read_sleb128 Unexecuted instantiation: global.c:dwarf_read_sleb128 Unexecuted instantiation: Lexpr.c:dwarf_read_sleb128 Lfde.c:dwarf_read_sleb128 Line | Count | Source | 322 | 15 | { | 323 | 15 | unw_word_t val = 0, shift = 0; | 324 | 15 | unsigned char byte; | 325 | 15 | int ret; | 326 | | | 327 | 15 | do | 328 | 15 | { | 329 | 15 | if ((ret = dwarf_readu8 (as, a, addr, &byte, arg)) < 0) | 330 | 0 | return ret; | 331 | | | 332 | 15 | val |= ((unw_word_t) byte & 0x7f) << shift; | 333 | 15 | shift += 7; | 334 | 15 | } | 335 | 15 | while (byte & 0x80); | 336 | | | 337 | 15 | if (shift < 8 * sizeof (unw_word_t) && (byte & 0x40) != 0) | 338 | | /* sign-extend negative value */ | 339 | 15 | val |= ((unw_word_t) -1) << shift; | 340 | | | 341 | 15 | *valp = val; | 342 | 15 | return 0; | 343 | 15 | } |
|
344 | | |
345 | | static ALWAYS_INLINE int |
346 | | dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a, |
347 | | unw_word_t *addr, unsigned char encoding, |
348 | | const unw_proc_info_t *pi, |
349 | | unw_word_t *valp, void *arg) |
350 | 75 | { |
351 | 75 | unw_word_t val, initial_addr = *addr; |
352 | 75 | uint16_t uval16; |
353 | 75 | uint32_t uval32; |
354 | 75 | uint64_t uval64; |
355 | 75 | int16_t sval16 = 0; |
356 | 75 | int32_t sval32 = 0; |
357 | 75 | int64_t sval64 = 0; |
358 | 75 | int ret; |
359 | | |
360 | | /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal |
361 | | format/application encoding. Handle them first. */ |
362 | 75 | if (encoding == DW_EH_PE_omit) |
363 | 15 | { |
364 | 15 | *valp = 0; |
365 | 15 | return 0; |
366 | 15 | } |
367 | 60 | else if (encoding == DW_EH_PE_aligned) |
368 | 0 | { |
369 | 0 | int size = dwarf_addr_size (as); |
370 | 0 | *addr = (initial_addr + size - 1) & -size; |
371 | 0 | return dwarf_readw (as, a, addr, valp, arg); |
372 | 0 | } |
373 | | |
374 | 60 | switch (encoding & DW_EH_PE_FORMAT_MASK) |
375 | 60 | { |
376 | 0 | case DW_EH_PE_ptr: |
377 | 0 | if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0) |
378 | 0 | return ret; |
379 | 0 | break; |
380 | | |
381 | 0 | case DW_EH_PE_uleb128: |
382 | 0 | if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) |
383 | 0 | return ret; |
384 | 0 | break; |
385 | | |
386 | 0 | case DW_EH_PE_udata2: |
387 | 0 | if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0) |
388 | 0 | return ret; |
389 | 0 | val = uval16; |
390 | 0 | break; |
391 | | |
392 | 15 | case DW_EH_PE_udata4: |
393 | 15 | if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0) |
394 | 0 | return ret; |
395 | 15 | val = uval32; |
396 | 15 | break; |
397 | | |
398 | 0 | case DW_EH_PE_udata8: |
399 | 0 | if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0) |
400 | 0 | return ret; |
401 | 0 | val = (unw_word_t) uval64; |
402 | 0 | break; |
403 | | |
404 | 0 | case DW_EH_PE_sleb128: |
405 | 0 | if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) |
406 | 0 | return ret; |
407 | 0 | break; |
408 | | |
409 | 0 | case DW_EH_PE_sdata2: |
410 | 0 | if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0) |
411 | 0 | return ret; |
412 | 0 | val = sval16; |
413 | 0 | break; |
414 | | |
415 | 45 | case DW_EH_PE_sdata4: |
416 | 45 | if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0) |
417 | 0 | return ret; |
418 | 45 | val = sval32; |
419 | 45 | break; |
420 | | |
421 | 0 | case DW_EH_PE_sdata8: |
422 | 0 | if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0) |
423 | 0 | return ret; |
424 | 0 | val = (unw_word_t) sval64; |
425 | 0 | break; |
426 | | |
427 | 0 | default: |
428 | 0 | Debug (1, "unexpected encoding format 0x%x\n", |
429 | 0 | encoding & DW_EH_PE_FORMAT_MASK); |
430 | 0 | return -UNW_EINVAL; |
431 | 60 | } |
432 | | |
433 | 60 | if (val == 0) |
434 | 0 | { |
435 | | /* 0 is a special value and always absolute. */ |
436 | 0 | *valp = 0; |
437 | 0 | return 0; |
438 | 0 | } |
439 | | |
440 | 60 | switch (encoding & DW_EH_PE_APPL_MASK) |
441 | 60 | { |
442 | 30 | case DW_EH_PE_absptr: |
443 | 30 | break; |
444 | | |
445 | 30 | case DW_EH_PE_pcrel: |
446 | 30 | val += initial_addr; |
447 | 30 | break; |
448 | | |
449 | 0 | case DW_EH_PE_datarel: |
450 | | /* XXX For now, assume that data-relative addresses are relative |
451 | | to the global pointer. */ |
452 | 0 | val += pi->gp; |
453 | 0 | break; |
454 | | |
455 | 0 | case DW_EH_PE_funcrel: |
456 | 0 | val += pi->start_ip; |
457 | 0 | break; |
458 | | |
459 | 0 | case DW_EH_PE_textrel: |
460 | | /* XXX For now we don't support text-rel values. If there is a |
461 | | platform which needs this, we probably would have to add a |
462 | | "segbase" member to unw_proc_info_t. */ |
463 | 0 | default: |
464 | 0 | Debug (1, "unexpected application type 0x%x\n", |
465 | 0 | encoding & DW_EH_PE_APPL_MASK); |
466 | 0 | return -UNW_EINVAL; |
467 | 60 | } |
468 | | |
469 | | /* Trim off any extra bits. Assume that sign extension isn't |
470 | | required; the only place it is needed is MIPS kernel space |
471 | | addresses. */ |
472 | 60 | if (sizeof (val) > dwarf_addr_size (as)) |
473 | 0 | { |
474 | 0 | assert (dwarf_addr_size (as) == 4); |
475 | 0 | val = (uint32_t) val; |
476 | 0 | } |
477 | | |
478 | 60 | if (encoding & DW_EH_PE_indirect) |
479 | 0 | { |
480 | 0 | unw_word_t indirect_addr = val; |
481 | |
|
482 | 0 | if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0) |
483 | 0 | return ret; |
484 | 0 | } |
485 | | |
486 | 60 | *valp = val; |
487 | 60 | return 0; |
488 | 60 | } Unexecuted instantiation: Lfind_proc_info-lsb.c:dwarf_read_encoded_pointer_inlined Unexecuted instantiation: Lglobal.c:dwarf_read_encoded_pointer_inlined Unexecuted instantiation: Lparser.c:dwarf_read_encoded_pointer_inlined Lpe.c:dwarf_read_encoded_pointer_inlined Line | Count | Source | 350 | 75 | { | 351 | 75 | unw_word_t val, initial_addr = *addr; | 352 | 75 | uint16_t uval16; | 353 | 75 | uint32_t uval32; | 354 | 75 | uint64_t uval64; | 355 | 75 | int16_t sval16 = 0; | 356 | 75 | int32_t sval32 = 0; | 357 | 75 | int64_t sval64 = 0; | 358 | 75 | int ret; | 359 | | | 360 | | /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal | 361 | | format/application encoding. Handle them first. */ | 362 | 75 | if (encoding == DW_EH_PE_omit) | 363 | 15 | { | 364 | 15 | *valp = 0; | 365 | 15 | return 0; | 366 | 15 | } | 367 | 60 | else if (encoding == DW_EH_PE_aligned) | 368 | 0 | { | 369 | 0 | int size = dwarf_addr_size (as); | 370 | 0 | *addr = (initial_addr + size - 1) & -size; | 371 | 0 | return dwarf_readw (as, a, addr, valp, arg); | 372 | 0 | } | 373 | | | 374 | 60 | switch (encoding & DW_EH_PE_FORMAT_MASK) | 375 | 60 | { | 376 | 0 | case DW_EH_PE_ptr: | 377 | 0 | if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0) | 378 | 0 | return ret; | 379 | 0 | break; | 380 | | | 381 | 0 | case DW_EH_PE_uleb128: | 382 | 0 | if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) | 383 | 0 | return ret; | 384 | 0 | break; | 385 | | | 386 | 0 | case DW_EH_PE_udata2: | 387 | 0 | if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0) | 388 | 0 | return ret; | 389 | 0 | val = uval16; | 390 | 0 | break; | 391 | | | 392 | 15 | case DW_EH_PE_udata4: | 393 | 15 | if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0) | 394 | 0 | return ret; | 395 | 15 | val = uval32; | 396 | 15 | break; | 397 | | | 398 | 0 | case DW_EH_PE_udata8: | 399 | 0 | if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0) | 400 | 0 | return ret; | 401 | 0 | val = (unw_word_t) uval64; | 402 | 0 | break; | 403 | | | 404 | 0 | case DW_EH_PE_sleb128: | 405 | 0 | if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) | 406 | 0 | return ret; | 407 | 0 | break; | 408 | | | 409 | 0 | case DW_EH_PE_sdata2: | 410 | 0 | if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0) | 411 | 0 | return ret; | 412 | 0 | val = sval16; | 413 | 0 | break; | 414 | | | 415 | 45 | case DW_EH_PE_sdata4: | 416 | 45 | if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0) | 417 | 0 | return ret; | 418 | 45 | val = sval32; | 419 | 45 | break; | 420 | | | 421 | 0 | case DW_EH_PE_sdata8: | 422 | 0 | if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0) | 423 | 0 | return ret; | 424 | 0 | val = (unw_word_t) sval64; | 425 | 0 | break; | 426 | | | 427 | 0 | default: | 428 | 0 | Debug (1, "unexpected encoding format 0x%x\n", | 429 | 0 | encoding & DW_EH_PE_FORMAT_MASK); | 430 | 0 | return -UNW_EINVAL; | 431 | 60 | } | 432 | | | 433 | 60 | if (val == 0) | 434 | 0 | { | 435 | | /* 0 is a special value and always absolute. */ | 436 | 0 | *valp = 0; | 437 | 0 | return 0; | 438 | 0 | } | 439 | | | 440 | 60 | switch (encoding & DW_EH_PE_APPL_MASK) | 441 | 60 | { | 442 | 30 | case DW_EH_PE_absptr: | 443 | 30 | break; | 444 | | | 445 | 30 | case DW_EH_PE_pcrel: | 446 | 30 | val += initial_addr; | 447 | 30 | break; | 448 | | | 449 | 0 | case DW_EH_PE_datarel: | 450 | | /* XXX For now, assume that data-relative addresses are relative | 451 | | to the global pointer. */ | 452 | 0 | val += pi->gp; | 453 | 0 | break; | 454 | | | 455 | 0 | case DW_EH_PE_funcrel: | 456 | 0 | val += pi->start_ip; | 457 | 0 | break; | 458 | | | 459 | 0 | case DW_EH_PE_textrel: | 460 | | /* XXX For now we don't support text-rel values. If there is a | 461 | | platform which needs this, we probably would have to add a | 462 | | "segbase" member to unw_proc_info_t. */ | 463 | 0 | default: | 464 | 0 | Debug (1, "unexpected application type 0x%x\n", | 465 | 0 | encoding & DW_EH_PE_APPL_MASK); | 466 | 0 | return -UNW_EINVAL; | 467 | 60 | } | 468 | | | 469 | | /* Trim off any extra bits. Assume that sign extension isn't | 470 | | required; the only place it is needed is MIPS kernel space | 471 | | addresses. */ | 472 | 60 | if (sizeof (val) > dwarf_addr_size (as)) | 473 | 0 | { | 474 | 0 | assert (dwarf_addr_size (as) == 4); | 475 | 0 | val = (uint32_t) val; | 476 | 0 | } | 477 | | | 478 | 60 | if (encoding & DW_EH_PE_indirect) | 479 | 0 | { | 480 | 0 | unw_word_t indirect_addr = val; | 481 | |
| 482 | 0 | if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0) | 483 | 0 | return ret; | 484 | 0 | } | 485 | | | 486 | 60 | *valp = val; | 487 | 60 | return 0; | 488 | 60 | } |
Unexecuted instantiation: global.c:dwarf_read_encoded_pointer_inlined Unexecuted instantiation: Lexpr.c:dwarf_read_encoded_pointer_inlined Unexecuted instantiation: Lfde.c:dwarf_read_encoded_pointer_inlined |
489 | | |
490 | | #endif /* DWARF_I_H */ |