blob: 08645aa7c2d6c2ae3e9edc741771d8401ac70da8 [file] [log] [blame]
Jan Beulich4552d5d2006-06-26 13:57:28 +02001/*
2 * Copyright (C) 2002-2006 Novell, Inc.
3 * Jan Beulich <jbeulich@novell.com>
4 * This code is released under version 2 of the GNU GPL.
5 *
6 * A simple API for unwinding kernel stacks. This is used for
7 * debugging and error reporting purposes. The kernel doesn't need
8 * full-blown stack unwinding with all the bells and whistles, so there
9 * is not much point in implementing the full Dwarf2 unwind API.
10 */
11
12#include <linux/unwind.h>
13#include <linux/module.h>
Jan Beulich690a9732006-10-21 18:37:01 +020014#include <linux/bootmem.h>
15#include <linux/sort.h>
Jan Beulich4552d5d2006-06-26 13:57:28 +020016#include <linux/stop_machine.h>
Andi Kleene2124bb2006-12-07 02:14:12 +010017#include <linux/uaccess.h>
Jan Beulich4552d5d2006-06-26 13:57:28 +020018#include <asm/sections.h>
19#include <asm/uaccess.h>
20#include <asm/unaligned.h>
21
22extern char __start_unwind[], __end_unwind[];
Jan Beulich690a9732006-10-21 18:37:01 +020023extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];
Jan Beulich4552d5d2006-06-26 13:57:28 +020024
25#define MAX_STACK_DEPTH 8
26
27#define EXTRA_INFO(f) { \
28 BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
29 % FIELD_SIZEOF(struct unwind_frame_info, f)) \
30 + offsetof(struct unwind_frame_info, f) \
31 / FIELD_SIZEOF(struct unwind_frame_info, f), \
32 FIELD_SIZEOF(struct unwind_frame_info, f) \
33 }
34#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
35
36static const struct {
37 unsigned offs:BITS_PER_LONG / 2;
38 unsigned width:BITS_PER_LONG / 2;
39} reg_info[] = {
40 UNW_REGISTER_INFO
41};
42
43#undef PTREGS_INFO
44#undef EXTRA_INFO
45
46#ifndef REG_INVALID
47#define REG_INVALID(r) (reg_info[r].width == 0)
48#endif
49
50#define DW_CFA_nop 0x00
51#define DW_CFA_set_loc 0x01
52#define DW_CFA_advance_loc1 0x02
53#define DW_CFA_advance_loc2 0x03
54#define DW_CFA_advance_loc4 0x04
55#define DW_CFA_offset_extended 0x05
56#define DW_CFA_restore_extended 0x06
57#define DW_CFA_undefined 0x07
58#define DW_CFA_same_value 0x08
59#define DW_CFA_register 0x09
60#define DW_CFA_remember_state 0x0a
61#define DW_CFA_restore_state 0x0b
62#define DW_CFA_def_cfa 0x0c
63#define DW_CFA_def_cfa_register 0x0d
64#define DW_CFA_def_cfa_offset 0x0e
65#define DW_CFA_def_cfa_expression 0x0f
66#define DW_CFA_expression 0x10
67#define DW_CFA_offset_extended_sf 0x11
68#define DW_CFA_def_cfa_sf 0x12
69#define DW_CFA_def_cfa_offset_sf 0x13
70#define DW_CFA_val_offset 0x14
71#define DW_CFA_val_offset_sf 0x15
72#define DW_CFA_val_expression 0x16
73#define DW_CFA_lo_user 0x1c
74#define DW_CFA_GNU_window_save 0x2d
75#define DW_CFA_GNU_args_size 0x2e
76#define DW_CFA_GNU_negative_offset_extended 0x2f
77#define DW_CFA_hi_user 0x3f
78
79#define DW_EH_PE_FORM 0x07
80#define DW_EH_PE_native 0x00
81#define DW_EH_PE_leb128 0x01
82#define DW_EH_PE_data2 0x02
83#define DW_EH_PE_data4 0x03
84#define DW_EH_PE_data8 0x04
85#define DW_EH_PE_signed 0x08
86#define DW_EH_PE_ADJUST 0x70
87#define DW_EH_PE_abs 0x00
88#define DW_EH_PE_pcrel 0x10
89#define DW_EH_PE_textrel 0x20
90#define DW_EH_PE_datarel 0x30
91#define DW_EH_PE_funcrel 0x40
92#define DW_EH_PE_aligned 0x50
93#define DW_EH_PE_indirect 0x80
94#define DW_EH_PE_omit 0xff
95
96typedef unsigned long uleb128_t;
97typedef signed long sleb128_t;
Jan Beulich359ad0d2006-12-07 02:14:13 +010098#define sleb128abs __builtin_labs
Jan Beulich4552d5d2006-06-26 13:57:28 +020099
100static struct unwind_table {
101 struct {
102 unsigned long pc;
103 unsigned long range;
104 } core, init;
105 const void *address;
106 unsigned long size;
Jan Beulich690a9732006-10-21 18:37:01 +0200107 const unsigned char *header;
108 unsigned long hdrsz;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200109 struct unwind_table *link;
110 const char *name;
Chuck Ebberte6cab992006-09-29 01:59:57 -0700111} root_table;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200112
113struct unwind_item {
114 enum item_location {
115 Nowhere,
116 Memory,
117 Register,
118 Value
119 } where;
120 uleb128_t value;
121};
122
123struct unwind_state {
124 uleb128_t loc, org;
125 const u8 *cieStart, *cieEnd;
126 uleb128_t codeAlign;
127 sleb128_t dataAlign;
128 struct cfa {
129 uleb128_t reg, offs;
130 } cfa;
131 struct unwind_item regs[ARRAY_SIZE(reg_info)];
132 unsigned stackDepth:8;
133 unsigned version:8;
134 const u8 *label;
135 const u8 *stack[MAX_STACK_DEPTH];
136};
137
138static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
139
Jan Beulich6d0185e2006-12-07 02:14:13 +0100140static unsigned unwind_debug;
141static int __init unwind_debug_setup(char *s)
142{
143 unwind_debug = simple_strtoul(s, NULL, 0);
144 return 1;
145}
146__setup("unwind_debug=", unwind_debug_setup);
147#define dprintk(lvl, fmt, args...) \
148 ((void)(lvl > unwind_debug \
149 || printk(KERN_DEBUG "unwind: " fmt "\n", ##args)))
150
Jan Beulich4552d5d2006-06-26 13:57:28 +0200151static struct unwind_table *find_table(unsigned long pc)
152{
153 struct unwind_table *table;
154
155 for (table = &root_table; table; table = table->link)
156 if ((pc >= table->core.pc
157 && pc < table->core.pc + table->core.range)
158 || (pc >= table->init.pc
159 && pc < table->init.pc + table->init.range))
160 break;
161
162 return table;
163}
164
Jan Beulich690a9732006-10-21 18:37:01 +0200165static unsigned long read_pointer(const u8 **pLoc,
166 const void *end,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100167 signed ptrType,
168 unsigned long text_base,
169 unsigned long data_base);
Jan Beulich690a9732006-10-21 18:37:01 +0200170
Jan Beulich4552d5d2006-06-26 13:57:28 +0200171static void init_unwind_table(struct unwind_table *table,
172 const char *name,
173 const void *core_start,
174 unsigned long core_size,
175 const void *init_start,
176 unsigned long init_size,
177 const void *table_start,
Jan Beulich690a9732006-10-21 18:37:01 +0200178 unsigned long table_size,
179 const u8 *header_start,
180 unsigned long header_size)
Jan Beulich4552d5d2006-06-26 13:57:28 +0200181{
Jan Beulich690a9732006-10-21 18:37:01 +0200182 const u8 *ptr = header_start + 4;
183 const u8 *end = header_start + header_size;
184
Jan Beulich4552d5d2006-06-26 13:57:28 +0200185 table->core.pc = (unsigned long)core_start;
186 table->core.range = core_size;
187 table->init.pc = (unsigned long)init_start;
188 table->init.range = init_size;
189 table->address = table_start;
190 table->size = table_size;
Jan Beulich690a9732006-10-21 18:37:01 +0200191 /* See if the linker provided table looks valid. */
192 if (header_size <= 4
193 || header_start[0] != 1
Jan Beulichc65f38d2006-12-07 02:14:19 +0100194 || (void *)read_pointer(&ptr, end, header_start[1], 0, 0)
195 != table_start
196 || !read_pointer(&ptr, end, header_start[2], 0, 0)
197 || !read_pointer(&ptr, end, header_start[3], 0,
198 (unsigned long)header_start)
199 || !read_pointer(&ptr, end, header_start[3], 0,
200 (unsigned long)header_start))
Jan Beulich690a9732006-10-21 18:37:01 +0200201 header_start = NULL;
202 table->hdrsz = header_size;
203 smp_wmb();
204 table->header = header_start;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200205 table->link = NULL;
206 table->name = name;
207}
208
209void __init unwind_init(void)
210{
211 init_unwind_table(&root_table, "kernel",
212 _text, _end - _text,
213 NULL, 0,
Jan Beulich690a9732006-10-21 18:37:01 +0200214 __start_unwind, __end_unwind - __start_unwind,
215 __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);
216}
217
218static const u32 bad_cie, not_fde;
219static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
220static signed fde_pointer_type(const u32 *cie);
221
222struct eh_frame_hdr_table_entry {
223 unsigned long start, fde;
224};
225
226static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
227{
228 const struct eh_frame_hdr_table_entry *e1 = p1;
229 const struct eh_frame_hdr_table_entry *e2 = p2;
230
231 return (e1->start > e2->start) - (e1->start < e2->start);
232}
233
234static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
235{
236 struct eh_frame_hdr_table_entry *e1 = p1;
237 struct eh_frame_hdr_table_entry *e2 = p2;
238 unsigned long v;
239
240 v = e1->start;
241 e1->start = e2->start;
242 e2->start = v;
243 v = e1->fde;
244 e1->fde = e2->fde;
245 e2->fde = v;
246}
247
248static void __init setup_unwind_table(struct unwind_table *table,
249 void *(*alloc)(unsigned long))
250{
251 const u8 *ptr;
252 unsigned long tableSize = table->size, hdrSize;
253 unsigned n;
254 const u32 *fde;
255 struct {
256 u8 version;
257 u8 eh_frame_ptr_enc;
258 u8 fde_count_enc;
259 u8 table_enc;
260 unsigned long eh_frame_ptr;
261 unsigned int fde_count;
262 struct eh_frame_hdr_table_entry table[];
263 } __attribute__((__packed__)) *header;
264
265 if (table->header)
266 return;
267
268 if (table->hdrsz)
269 printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n",
270 table->name);
271
272 if (tableSize & (sizeof(*fde) - 1))
273 return;
274
275 for (fde = table->address, n = 0;
276 tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
277 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
278 const u32 *cie = cie_for_fde(fde, table);
279 signed ptrType;
280
281 if (cie == &not_fde)
282 continue;
283 if (cie == NULL
284 || cie == &bad_cie
285 || (ptrType = fde_pointer_type(cie)) < 0)
286 return;
287 ptr = (const u8 *)(fde + 2);
288 if (!read_pointer(&ptr,
289 (const u8 *)(fde + 1) + *fde,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100290 ptrType, 0, 0))
Jan Beulich690a9732006-10-21 18:37:01 +0200291 return;
292 ++n;
293 }
294
295 if (tableSize || !n)
296 return;
297
298 hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
299 + 2 * n * sizeof(unsigned long);
Jan Beulich6d0185e2006-12-07 02:14:13 +0100300 dprintk(2, "Binary lookup table size for %s: %lu bytes", table->name, hdrSize);
Jan Beulich690a9732006-10-21 18:37:01 +0200301 header = alloc(hdrSize);
302 if (!header)
303 return;
304 header->version = 1;
305 header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native;
306 header->fde_count_enc = DW_EH_PE_abs|DW_EH_PE_data4;
307 header->table_enc = DW_EH_PE_abs|DW_EH_PE_native;
308 put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
309 BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
310 % __alignof(typeof(header->fde_count)));
311 header->fde_count = n;
312
313 BUILD_BUG_ON(offsetof(typeof(*header), table)
314 % __alignof(typeof(*header->table)));
315 for (fde = table->address, tableSize = table->size, n = 0;
316 tableSize;
317 tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
318 const u32 *cie = fde + 1 - fde[1] / sizeof(*fde);
319
320 if (!fde[1])
321 continue; /* this is a CIE */
322 ptr = (const u8 *)(fde + 2);
323 header->table[n].start = read_pointer(&ptr,
324 (const u8 *)(fde + 1) + *fde,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100325 fde_pointer_type(cie), 0, 0);
Jan Beulich690a9732006-10-21 18:37:01 +0200326 header->table[n].fde = (unsigned long)fde;
327 ++n;
328 }
329 WARN_ON(n != header->fde_count);
330
331 sort(header->table,
332 n,
333 sizeof(*header->table),
334 cmp_eh_frame_hdr_table_entries,
335 swap_eh_frame_hdr_table_entries);
336
337 table->hdrsz = hdrSize;
338 smp_wmb();
339 table->header = (const void *)header;
340}
341
342static void *__init balloc(unsigned long sz)
343{
344 return __alloc_bootmem_nopanic(sz,
345 sizeof(unsigned int),
346 __pa(MAX_DMA_ADDRESS));
347}
348
349void __init unwind_setup(void)
350{
351 setup_unwind_table(&root_table, balloc);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200352}
353
Jan Beulich83f4fcc2006-06-26 13:57:50 +0200354#ifdef CONFIG_MODULES
355
Chuck Ebberte6cab992006-09-29 01:59:57 -0700356static struct unwind_table *last_table;
357
Jan Beulich4552d5d2006-06-26 13:57:28 +0200358/* Must be called with module_mutex held. */
359void *unwind_add_table(struct module *module,
360 const void *table_start,
361 unsigned long table_size)
362{
363 struct unwind_table *table;
364
365 if (table_size <= 0)
366 return NULL;
367
368 table = kmalloc(sizeof(*table), GFP_KERNEL);
369 if (!table)
370 return NULL;
371
372 init_unwind_table(table, module->name,
373 module->module_core, module->core_size,
374 module->module_init, module->init_size,
Jan Beulich690a9732006-10-21 18:37:01 +0200375 table_start, table_size,
376 NULL, 0);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200377
378 if (last_table)
379 last_table->link = table;
380 else
381 root_table.link = table;
382 last_table = table;
383
384 return table;
385}
386
387struct unlink_table_info
388{
389 struct unwind_table *table;
390 int init_only;
391};
392
393static int unlink_table(void *arg)
394{
395 struct unlink_table_info *info = arg;
396 struct unwind_table *table = info->table, *prev;
397
398 for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
399 ;
400
401 if (prev->link) {
402 if (info->init_only) {
403 table->init.pc = 0;
404 table->init.range = 0;
405 info->table = NULL;
406 } else {
407 prev->link = table->link;
408 if (!prev->link)
409 last_table = prev;
410 }
411 } else
412 info->table = NULL;
413
414 return 0;
415}
416
417/* Must be called with module_mutex held. */
418void unwind_remove_table(void *handle, int init_only)
419{
420 struct unwind_table *table = handle;
421 struct unlink_table_info info;
422
423 if (!table || table == &root_table)
424 return;
425
426 if (init_only && table == last_table) {
427 table->init.pc = 0;
428 table->init.range = 0;
429 return;
430 }
431
432 info.table = table;
433 info.init_only = init_only;
434 stop_machine_run(unlink_table, &info, NR_CPUS);
435
436 if (info.table)
437 kfree(table);
438}
439
Jan Beulich83f4fcc2006-06-26 13:57:50 +0200440#endif /* CONFIG_MODULES */
441
Jan Beulich4552d5d2006-06-26 13:57:28 +0200442static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
443{
444 const u8 *cur = *pcur;
445 uleb128_t value;
446 unsigned shift;
447
448 for (shift = 0, value = 0; cur < end; shift += 7) {
449 if (shift + 7 > 8 * sizeof(value)
450 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
451 cur = end + 1;
452 break;
453 }
454 value |= (uleb128_t)(*cur & 0x7f) << shift;
455 if (!(*cur++ & 0x80))
456 break;
457 }
458 *pcur = cur;
459
460 return value;
461}
462
463static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
464{
465 const u8 *cur = *pcur;
466 sleb128_t value;
467 unsigned shift;
468
469 for (shift = 0, value = 0; cur < end; shift += 7) {
470 if (shift + 7 > 8 * sizeof(value)
471 && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
472 cur = end + 1;
473 break;
474 }
475 value |= (sleb128_t)(*cur & 0x7f) << shift;
476 if (!(*cur & 0x80)) {
477 value |= -(*cur++ & 0x40) << shift;
478 break;
479 }
480 }
481 *pcur = cur;
482
483 return value;
484}
485
Jan Beulich690a9732006-10-21 18:37:01 +0200486static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
487{
488 const u32 *cie;
489
490 if (!*fde || (*fde & (sizeof(*fde) - 1)))
491 return &bad_cie;
492 if (!fde[1])
493 return &not_fde; /* this is a CIE */
494 if ((fde[1] & (sizeof(*fde) - 1))
495 || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address)
496 return NULL; /* this is not a valid FDE */
497 cie = fde + 1 - fde[1] / sizeof(*fde);
498 if (*cie <= sizeof(*cie) + 4
499 || *cie >= fde[1] - sizeof(*fde)
500 || (*cie & (sizeof(*cie) - 1))
501 || cie[1])
502 return NULL; /* this is not a (valid) CIE */
503 return cie;
504}
505
Jan Beulich4552d5d2006-06-26 13:57:28 +0200506static unsigned long read_pointer(const u8 **pLoc,
507 const void *end,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100508 signed ptrType,
509 unsigned long text_base,
510 unsigned long data_base)
Jan Beulich4552d5d2006-06-26 13:57:28 +0200511{
512 unsigned long value = 0;
513 union {
514 const u8 *p8;
515 const u16 *p16u;
516 const s16 *p16s;
517 const u32 *p32u;
518 const s32 *p32s;
519 const unsigned long *pul;
520 } ptr;
521
Jan Beulich6d0185e2006-12-07 02:14:13 +0100522 if (ptrType < 0 || ptrType == DW_EH_PE_omit) {
523 dprintk(1, "Invalid pointer encoding %02X (%p,%p).", ptrType, *pLoc, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200524 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100525 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200526 ptr.p8 = *pLoc;
527 switch(ptrType & DW_EH_PE_FORM) {
528 case DW_EH_PE_data2:
Jan Beulich6d0185e2006-12-07 02:14:13 +0100529 if (end < (const void *)(ptr.p16u + 1)) {
530 dprintk(1, "Data16 overrun (%p,%p).", ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200531 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100532 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200533 if(ptrType & DW_EH_PE_signed)
534 value = get_unaligned(ptr.p16s++);
535 else
536 value = get_unaligned(ptr.p16u++);
537 break;
538 case DW_EH_PE_data4:
539#ifdef CONFIG_64BIT
Jan Beulich6d0185e2006-12-07 02:14:13 +0100540 if (end < (const void *)(ptr.p32u + 1)) {
541 dprintk(1, "Data32 overrun (%p,%p).", ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200542 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100543 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200544 if(ptrType & DW_EH_PE_signed)
545 value = get_unaligned(ptr.p32s++);
546 else
547 value = get_unaligned(ptr.p32u++);
548 break;
549 case DW_EH_PE_data8:
550 BUILD_BUG_ON(sizeof(u64) != sizeof(value));
551#else
552 BUILD_BUG_ON(sizeof(u32) != sizeof(value));
553#endif
554 case DW_EH_PE_native:
Jan Beulich6d0185e2006-12-07 02:14:13 +0100555 if (end < (const void *)(ptr.pul + 1)) {
556 dprintk(1, "DataUL overrun (%p,%p).", ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200557 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100558 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200559 value = get_unaligned(ptr.pul++);
560 break;
561 case DW_EH_PE_leb128:
562 BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
563 value = ptrType & DW_EH_PE_signed
564 ? get_sleb128(&ptr.p8, end)
565 : get_uleb128(&ptr.p8, end);
Jan Beulich6d0185e2006-12-07 02:14:13 +0100566 if ((const void *)ptr.p8 > end) {
567 dprintk(1, "DataLEB overrun (%p,%p).", ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200568 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100569 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200570 break;
571 default:
Jan Beulich6d0185e2006-12-07 02:14:13 +0100572 dprintk(2, "Cannot decode pointer type %02X (%p,%p).",
573 ptrType, ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200574 return 0;
575 }
576 switch(ptrType & DW_EH_PE_ADJUST) {
577 case DW_EH_PE_abs:
578 break;
579 case DW_EH_PE_pcrel:
580 value += (unsigned long)*pLoc;
581 break;
Jan Beulichc65f38d2006-12-07 02:14:19 +0100582 case DW_EH_PE_textrel:
583 if (likely(text_base)) {
584 value += text_base;
585 break;
586 }
587 dprintk(2, "Text-relative encoding %02X (%p,%p), but zero text base.",
588 ptrType, *pLoc, end);
589 return 0;
590 case DW_EH_PE_datarel:
591 if (likely(data_base)) {
592 value += data_base;
593 break;
594 }
595 dprintk(2, "Data-relative encoding %02X (%p,%p), but zero data base.",
596 ptrType, *pLoc, end);
597 return 0;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200598 default:
Jan Beulich6d0185e2006-12-07 02:14:13 +0100599 dprintk(2, "Cannot adjust pointer type %02X (%p,%p).",
600 ptrType, *pLoc, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200601 return 0;
602 }
603 if ((ptrType & DW_EH_PE_indirect)
Jan Beulich6d0185e2006-12-07 02:14:13 +0100604 && probe_kernel_address((unsigned long *)value, value)) {
605 dprintk(1, "Cannot read indirect value %lx (%p,%p).",
606 value, *pLoc, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200607 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100608 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200609 *pLoc = ptr.p8;
610
611 return value;
612}
613
614static signed fde_pointer_type(const u32 *cie)
615{
616 const u8 *ptr = (const u8 *)(cie + 2);
617 unsigned version = *ptr;
618
619 if (version != 1)
620 return -1; /* unsupported */
621 if (*++ptr) {
622 const char *aug;
623 const u8 *end = (const u8 *)(cie + 1) + *cie;
624 uleb128_t len;
625
626 /* check if augmentation size is first (and thus present) */
627 if (*ptr != 'z')
628 return -1;
629 /* check if augmentation string is nul-terminated */
630 if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
631 return -1;
632 ++ptr; /* skip terminator */
633 get_uleb128(&ptr, end); /* skip code alignment */
634 get_sleb128(&ptr, end); /* skip data alignment */
635 /* skip return address column */
636 version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
637 len = get_uleb128(&ptr, end); /* augmentation length */
638 if (ptr + len < ptr || ptr + len > end)
639 return -1;
640 end = ptr + len;
641 while (*++aug) {
642 if (ptr >= end)
643 return -1;
644 switch(*aug) {
645 case 'L':
646 ++ptr;
647 break;
648 case 'P': {
649 signed ptrType = *ptr++;
650
Jan Beulichc65f38d2006-12-07 02:14:19 +0100651 if (!read_pointer(&ptr, end, ptrType, 0, 0)
652 || ptr > end)
Jan Beulich4552d5d2006-06-26 13:57:28 +0200653 return -1;
654 }
655 break;
656 case 'R':
657 return *ptr;
658 default:
659 return -1;
660 }
661 }
662 }
663 return DW_EH_PE_native|DW_EH_PE_abs;
664}
665
666static int advance_loc(unsigned long delta, struct unwind_state *state)
667{
668 state->loc += delta * state->codeAlign;
669
670 return delta > 0;
671}
672
673static void set_rule(uleb128_t reg,
674 enum item_location where,
675 uleb128_t value,
676 struct unwind_state *state)
677{
678 if (reg < ARRAY_SIZE(state->regs)) {
679 state->regs[reg].where = where;
680 state->regs[reg].value = value;
681 }
682}
683
684static int processCFI(const u8 *start,
685 const u8 *end,
686 unsigned long targetLoc,
687 signed ptrType,
688 struct unwind_state *state)
689{
690 union {
691 const u8 *p8;
692 const u16 *p16;
693 const u32 *p32;
694 } ptr;
695 int result = 1;
696
697 if (start != state->cieStart) {
698 state->loc = state->org;
699 result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
700 if (targetLoc == 0 && state->label == NULL)
701 return result;
702 }
703 for (ptr.p8 = start; result && ptr.p8 < end; ) {
704 switch(*ptr.p8 >> 6) {
705 uleb128_t value;
706
707 case 0:
708 switch(*ptr.p8++) {
709 case DW_CFA_nop:
710 break;
711 case DW_CFA_set_loc:
Jan Beulichc65f38d2006-12-07 02:14:19 +0100712 state->loc = read_pointer(&ptr.p8, end, ptrType, 0, 0);
713 if (state->loc == 0)
Jan Beulich4552d5d2006-06-26 13:57:28 +0200714 result = 0;
715 break;
716 case DW_CFA_advance_loc1:
717 result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
718 break;
719 case DW_CFA_advance_loc2:
720 result = ptr.p8 <= end + 2
721 && advance_loc(*ptr.p16++, state);
722 break;
723 case DW_CFA_advance_loc4:
724 result = ptr.p8 <= end + 4
725 && advance_loc(*ptr.p32++, state);
726 break;
727 case DW_CFA_offset_extended:
728 value = get_uleb128(&ptr.p8, end);
729 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
730 break;
731 case DW_CFA_val_offset:
732 value = get_uleb128(&ptr.p8, end);
733 set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
734 break;
735 case DW_CFA_offset_extended_sf:
736 value = get_uleb128(&ptr.p8, end);
737 set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
738 break;
739 case DW_CFA_val_offset_sf:
740 value = get_uleb128(&ptr.p8, end);
741 set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
742 break;
743 case DW_CFA_restore_extended:
744 case DW_CFA_undefined:
745 case DW_CFA_same_value:
746 set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
747 break;
748 case DW_CFA_register:
749 value = get_uleb128(&ptr.p8, end);
750 set_rule(value,
751 Register,
752 get_uleb128(&ptr.p8, end), state);
753 break;
754 case DW_CFA_remember_state:
755 if (ptr.p8 == state->label) {
756 state->label = NULL;
757 return 1;
758 }
Jan Beulich6d0185e2006-12-07 02:14:13 +0100759 if (state->stackDepth >= MAX_STACK_DEPTH) {
760 dprintk(1, "State stack overflow (%p,%p).", ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200761 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100762 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200763 state->stack[state->stackDepth++] = ptr.p8;
764 break;
765 case DW_CFA_restore_state:
766 if (state->stackDepth) {
767 const uleb128_t loc = state->loc;
768 const u8 *label = state->label;
769
770 state->label = state->stack[state->stackDepth - 1];
771 memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
772 memset(state->regs, 0, sizeof(state->regs));
773 state->stackDepth = 0;
774 result = processCFI(start, end, 0, ptrType, state);
775 state->loc = loc;
776 state->label = label;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100777 } else {
778 dprintk(1, "State stack underflow (%p,%p).", ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200779 return 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100780 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200781 break;
782 case DW_CFA_def_cfa:
783 state->cfa.reg = get_uleb128(&ptr.p8, end);
784 /*nobreak*/
785 case DW_CFA_def_cfa_offset:
786 state->cfa.offs = get_uleb128(&ptr.p8, end);
787 break;
788 case DW_CFA_def_cfa_sf:
789 state->cfa.reg = get_uleb128(&ptr.p8, end);
790 /*nobreak*/
791 case DW_CFA_def_cfa_offset_sf:
792 state->cfa.offs = get_sleb128(&ptr.p8, end)
793 * state->dataAlign;
794 break;
795 case DW_CFA_def_cfa_register:
796 state->cfa.reg = get_uleb128(&ptr.p8, end);
797 break;
798 /*todo case DW_CFA_def_cfa_expression: */
799 /*todo case DW_CFA_expression: */
800 /*todo case DW_CFA_val_expression: */
801 case DW_CFA_GNU_args_size:
802 get_uleb128(&ptr.p8, end);
803 break;
804 case DW_CFA_GNU_negative_offset_extended:
805 value = get_uleb128(&ptr.p8, end);
806 set_rule(value,
807 Memory,
808 (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
809 break;
810 case DW_CFA_GNU_window_save:
811 default:
Jan Beulich6d0185e2006-12-07 02:14:13 +0100812 dprintk(1, "Unrecognized CFI op %02X (%p,%p).", ptr.p8[-1], ptr.p8 - 1, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200813 result = 0;
814 break;
815 }
816 break;
817 case 1:
818 result = advance_loc(*ptr.p8++ & 0x3f, state);
819 break;
820 case 2:
821 value = *ptr.p8++ & 0x3f;
822 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
823 break;
824 case 3:
825 set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
826 break;
827 }
Jan Beulich6d0185e2006-12-07 02:14:13 +0100828 if (ptr.p8 > end) {
829 dprintk(1, "Data overrun (%p,%p).", ptr.p8, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200830 result = 0;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100831 }
Jan Beulich4552d5d2006-06-26 13:57:28 +0200832 if (result && targetLoc != 0 && targetLoc < state->loc)
833 return 1;
834 }
835
Jan Beulich6d0185e2006-12-07 02:14:13 +0100836 if (result && ptr.p8 < end)
837 dprintk(1, "Data underrun (%p,%p).", ptr.p8, end);
838
Jan Beulich4552d5d2006-06-26 13:57:28 +0200839 return result
840 && ptr.p8 == end
841 && (targetLoc == 0
842 || (/*todo While in theory this should apply, gcc in practice omits
843 everything past the function prolog, and hence the location
844 never reaches the end of the function.
845 targetLoc < state->loc &&*/ state->label == NULL));
846}
847
848/* Unwind to previous to frame. Returns 0 if successful, negative
849 * number in case of an error. */
850int unwind(struct unwind_frame_info *frame)
851{
852#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
853 const u32 *fde = NULL, *cie = NULL;
854 const u8 *ptr = NULL, *end = NULL;
Jan Beulich359ad0d2006-12-07 02:14:13 +0100855 unsigned long pc = UNW_PC(frame) - frame->call_frame, sp;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200856 unsigned long startLoc = 0, endLoc = 0, cfa;
857 unsigned i;
858 signed ptrType = -1;
859 uleb128_t retAddrReg = 0;
Jan Beulich690a9732006-10-21 18:37:01 +0200860 const struct unwind_table *table;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200861 struct unwind_state state;
862
863 if (UNW_PC(frame) == 0)
864 return -EINVAL;
Jan Beulichadf14232006-09-26 10:52:41 +0200865 if ((table = find_table(pc)) != NULL
Jan Beulich4552d5d2006-06-26 13:57:28 +0200866 && !(table->size & (sizeof(*fde) - 1))) {
Jan Beulich690a9732006-10-21 18:37:01 +0200867 const u8 *hdr = table->header;
868 unsigned long tableSize;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200869
Jan Beulich690a9732006-10-21 18:37:01 +0200870 smp_rmb();
871 if (hdr && hdr[0] == 1) {
872 switch(hdr[3] & DW_EH_PE_FORM) {
873 case DW_EH_PE_native: tableSize = sizeof(unsigned long); break;
874 case DW_EH_PE_data2: tableSize = 2; break;
875 case DW_EH_PE_data4: tableSize = 4; break;
876 case DW_EH_PE_data8: tableSize = 8; break;
877 default: tableSize = 0; break;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200878 }
Jan Beulich690a9732006-10-21 18:37:01 +0200879 ptr = hdr + 4;
880 end = hdr + table->hdrsz;
881 if (tableSize
Jan Beulichc65f38d2006-12-07 02:14:19 +0100882 && read_pointer(&ptr, end, hdr[1], 0, 0)
Jan Beulich690a9732006-10-21 18:37:01 +0200883 == (unsigned long)table->address
Jan Beulichc65f38d2006-12-07 02:14:19 +0100884 && (i = read_pointer(&ptr, end, hdr[2], 0, 0)) > 0
Jan Beulich690a9732006-10-21 18:37:01 +0200885 && i == (end - ptr) / (2 * tableSize)
886 && !((end - ptr) % (2 * tableSize))) {
887 do {
888 const u8 *cur = ptr + (i / 2) * (2 * tableSize);
889
890 startLoc = read_pointer(&cur,
891 cur + tableSize,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100892 hdr[3], 0,
893 (unsigned long)hdr);
Jan Beulich690a9732006-10-21 18:37:01 +0200894 if (pc < startLoc)
895 i /= 2;
896 else {
897 ptr = cur - tableSize;
898 i = (i + 1) / 2;
899 }
900 } while (startLoc && i > 1);
901 if (i == 1
902 && (startLoc = read_pointer(&ptr,
903 ptr + tableSize,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100904 hdr[3], 0,
905 (unsigned long)hdr)) != 0
Jan Beulich690a9732006-10-21 18:37:01 +0200906 && pc >= startLoc)
907 fde = (void *)read_pointer(&ptr,
908 ptr + tableSize,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100909 hdr[3], 0,
910 (unsigned long)hdr);
Jan Beulich690a9732006-10-21 18:37:01 +0200911 }
912 }
Jan Beulich6d0185e2006-12-07 02:14:13 +0100913 if(hdr && !fde)
914 dprintk(3, "Binary lookup for %lx failed.", pc);
Jan Beulich690a9732006-10-21 18:37:01 +0200915
916 if (fde != NULL) {
917 cie = cie_for_fde(fde, table);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200918 ptr = (const u8 *)(fde + 2);
Jan Beulich690a9732006-10-21 18:37:01 +0200919 if(cie != NULL
920 && cie != &bad_cie
921 && cie != &not_fde
922 && (ptrType = fde_pointer_type(cie)) >= 0
923 && read_pointer(&ptr,
924 (const u8 *)(fde + 1) + *fde,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100925 ptrType, 0, 0) == startLoc) {
Jan Beulich690a9732006-10-21 18:37:01 +0200926 if (!(ptrType & DW_EH_PE_indirect))
927 ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
928 endLoc = startLoc
929 + read_pointer(&ptr,
930 (const u8 *)(fde + 1) + *fde,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100931 ptrType, 0, 0);
Jan Beulich690a9732006-10-21 18:37:01 +0200932 if(pc >= endLoc)
933 fde = NULL;
934 } else
935 fde = NULL;
Jan Beulich6d0185e2006-12-07 02:14:13 +0100936 if(!fde)
937 dprintk(1, "Binary lookup result for %lx discarded.", pc);
Jan Beulich690a9732006-10-21 18:37:01 +0200938 }
939 if (fde == NULL) {
940 for (fde = table->address, tableSize = table->size;
941 cie = NULL, tableSize > sizeof(*fde)
942 && tableSize - sizeof(*fde) >= *fde;
943 tableSize -= sizeof(*fde) + *fde,
944 fde += 1 + *fde / sizeof(*fde)) {
945 cie = cie_for_fde(fde, table);
946 if (cie == &bad_cie) {
947 cie = NULL;
948 break;
949 }
950 if (cie == NULL
951 || cie == &not_fde
952 || (ptrType = fde_pointer_type(cie)) < 0)
953 continue;
954 ptr = (const u8 *)(fde + 2);
955 startLoc = read_pointer(&ptr,
956 (const u8 *)(fde + 1) + *fde,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100957 ptrType, 0, 0);
Jan Beulich690a9732006-10-21 18:37:01 +0200958 if (!startLoc)
959 continue;
960 if (!(ptrType & DW_EH_PE_indirect))
961 ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed;
962 endLoc = startLoc
963 + read_pointer(&ptr,
964 (const u8 *)(fde + 1) + *fde,
Jan Beulichc65f38d2006-12-07 02:14:19 +0100965 ptrType, 0, 0);
Jan Beulich690a9732006-10-21 18:37:01 +0200966 if (pc >= startLoc && pc < endLoc)
967 break;
968 }
Jan Beulich6d0185e2006-12-07 02:14:13 +0100969 if(!fde)
970 dprintk(3, "Linear lookup for %lx failed.", pc);
Jan Beulich4552d5d2006-06-26 13:57:28 +0200971 }
972 }
973 if (cie != NULL) {
974 memset(&state, 0, sizeof(state));
975 state.cieEnd = ptr; /* keep here temporarily */
976 ptr = (const u8 *)(cie + 2);
977 end = (const u8 *)(cie + 1) + *cie;
Jan Beulichadf14232006-09-26 10:52:41 +0200978 frame->call_frame = 1;
Jan Beulich4552d5d2006-06-26 13:57:28 +0200979 if ((state.version = *ptr) != 1)
980 cie = NULL; /* unsupported version */
981 else if (*++ptr) {
982 /* check if augmentation size is first (and thus present) */
983 if (*ptr == 'z') {
Jan Beulichadf14232006-09-26 10:52:41 +0200984 while (++ptr < end && *ptr) {
985 switch(*ptr) {
986 /* check for ignorable (or already handled)
987 * nul-terminated augmentation string */
988 case 'L':
989 case 'P':
990 case 'R':
991 continue;
992 case 'S':
993 frame->call_frame = 0;
994 continue;
995 default:
Jan Beulich4552d5d2006-06-26 13:57:28 +0200996 break;
Jan Beulichadf14232006-09-26 10:52:41 +0200997 }
998 break;
999 }
Jan Beulich4552d5d2006-06-26 13:57:28 +02001000 }
1001 if (ptr >= end || *ptr)
1002 cie = NULL;
1003 }
Jan Beulich6d0185e2006-12-07 02:14:13 +01001004 if(!cie)
1005 dprintk(1, "CIE unusable (%p,%p).", ptr, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001006 ++ptr;
1007 }
1008 if (cie != NULL) {
1009 /* get code aligment factor */
1010 state.codeAlign = get_uleb128(&ptr, end);
1011 /* get data aligment factor */
1012 state.dataAlign = get_sleb128(&ptr, end);
1013 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1014 cie = NULL;
Jan Beulich359ad0d2006-12-07 02:14:13 +01001015 else if (UNW_PC(frame) % state.codeAlign
Jan Beulich6d0185e2006-12-07 02:14:13 +01001016 || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
1017 dprintk(1, "Input pointer(s) misaligned (%lx,%lx).",
1018 UNW_PC(frame), UNW_SP(frame));
Jan Beulich359ad0d2006-12-07 02:14:13 +01001019 return -EPERM;
Jan Beulich6d0185e2006-12-07 02:14:13 +01001020 } else {
Jan Beulich4552d5d2006-06-26 13:57:28 +02001021 retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
1022 /* skip augmentation */
Jan Beulichff0a5382006-11-28 20:12:59 +01001023 if (((const char *)(cie + 2))[1] == 'z') {
1024 uleb128_t augSize = get_uleb128(&ptr, end);
1025
1026 ptr += augSize;
1027 }
Jan Beulich4552d5d2006-06-26 13:57:28 +02001028 if (ptr > end
1029 || retAddrReg >= ARRAY_SIZE(reg_info)
1030 || REG_INVALID(retAddrReg)
1031 || reg_info[retAddrReg].width != sizeof(unsigned long))
1032 cie = NULL;
1033 }
Jan Beulich6d0185e2006-12-07 02:14:13 +01001034 if(!cie)
1035 dprintk(1, "CIE validation failed (%p,%p).", ptr, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001036 }
1037 if (cie != NULL) {
1038 state.cieStart = ptr;
1039 ptr = state.cieEnd;
1040 state.cieEnd = end;
1041 end = (const u8 *)(fde + 1) + *fde;
1042 /* skip augmentation */
1043 if (((const char *)(cie + 2))[1] == 'z') {
1044 uleb128_t augSize = get_uleb128(&ptr, end);
1045
1046 if ((ptr += augSize) > end)
1047 fde = NULL;
1048 }
Jan Beulich6d0185e2006-12-07 02:14:13 +01001049 if(!fde)
1050 dprintk(1, "FDE validation failed (%p,%p).", ptr, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001051 }
1052 if (cie == NULL || fde == NULL) {
1053#ifdef CONFIG_FRAME_POINTER
1054 unsigned long top, bottom;
Jan Beulich4552d5d2006-06-26 13:57:28 +02001055
Jan Beulich359ad0d2006-12-07 02:14:13 +01001056 if ((UNW_SP(frame) | UNW_FP(frame)) % sizeof(unsigned long))
1057 return -EPERM;
Jan Beulich4552d5d2006-06-26 13:57:28 +02001058 top = STACK_TOP(frame->task);
1059 bottom = STACK_BOTTOM(frame->task);
1060# if FRAME_RETADDR_OFFSET < 0
1061 if (UNW_SP(frame) < top
1062 && UNW_FP(frame) <= UNW_SP(frame)
1063 && bottom < UNW_FP(frame)
1064# else
1065 if (UNW_SP(frame) > top
1066 && UNW_FP(frame) >= UNW_SP(frame)
1067 && bottom > UNW_FP(frame)
1068# endif
1069 && !((UNW_SP(frame) | UNW_FP(frame))
1070 & (sizeof(unsigned long) - 1))) {
1071 unsigned long link;
1072
Andi Kleene2124bb2006-12-07 02:14:12 +01001073 if (!probe_kernel_address(
Jan Beulich4552d5d2006-06-26 13:57:28 +02001074 (unsigned long *)(UNW_FP(frame)
Andi Kleene2124bb2006-12-07 02:14:12 +01001075 + FRAME_LINK_OFFSET),
1076 link)
Jan Beulich4552d5d2006-06-26 13:57:28 +02001077# if FRAME_RETADDR_OFFSET < 0
1078 && link > bottom && link < UNW_FP(frame)
1079# else
1080 && link > UNW_FP(frame) && link < bottom
1081# endif
1082 && !(link & (sizeof(link) - 1))
Andi Kleene2124bb2006-12-07 02:14:12 +01001083 && !probe_kernel_address(
Jan Beulich4552d5d2006-06-26 13:57:28 +02001084 (unsigned long *)(UNW_FP(frame)
Andi Kleene2124bb2006-12-07 02:14:12 +01001085 + FRAME_RETADDR_OFFSET), UNW_PC(frame))) {
Jan Beulich4552d5d2006-06-26 13:57:28 +02001086 UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
1087# if FRAME_RETADDR_OFFSET < 0
1088 -
1089# else
1090 +
1091# endif
1092 sizeof(UNW_PC(frame));
1093 UNW_FP(frame) = link;
1094 return 0;
1095 }
1096 }
1097#endif
1098 return -ENXIO;
1099 }
1100 state.org = startLoc;
1101 memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1102 /* process instructions */
Jan Beulichadf14232006-09-26 10:52:41 +02001103 if (!processCFI(ptr, end, pc, ptrType, &state)
Jan Beulich4552d5d2006-06-26 13:57:28 +02001104 || state.loc > endLoc
1105 || state.regs[retAddrReg].where == Nowhere
1106 || state.cfa.reg >= ARRAY_SIZE(reg_info)
1107 || reg_info[state.cfa.reg].width != sizeof(unsigned long)
Jan Beulich359ad0d2006-12-07 02:14:13 +01001108 || FRAME_REG(state.cfa.reg, unsigned long) % sizeof(unsigned long)
Jan Beulich6d0185e2006-12-07 02:14:13 +01001109 || state.cfa.offs % sizeof(unsigned long)) {
1110 dprintk(1, "Unusable unwind info (%p,%p).", ptr, end);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001111 return -EIO;
Jan Beulich6d0185e2006-12-07 02:14:13 +01001112 }
Jan Beulich4552d5d2006-06-26 13:57:28 +02001113 /* update frame */
Jan Beulichadf14232006-09-26 10:52:41 +02001114#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
1115 if(frame->call_frame
1116 && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1117 frame->call_frame = 0;
1118#endif
Jan Beulich4552d5d2006-06-26 13:57:28 +02001119 cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1120 startLoc = min((unsigned long)UNW_SP(frame), cfa);
1121 endLoc = max((unsigned long)UNW_SP(frame), cfa);
1122 if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1123 startLoc = min(STACK_LIMIT(cfa), cfa);
1124 endLoc = max(STACK_LIMIT(cfa), cfa);
1125 }
1126#ifndef CONFIG_64BIT
1127# define CASES CASE(8); CASE(16); CASE(32)
1128#else
1129# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
1130#endif
Jan Beulich359ad0d2006-12-07 02:14:13 +01001131 pc = UNW_PC(frame);
1132 sp = UNW_SP(frame);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001133 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1134 if (REG_INVALID(i)) {
1135 if (state.regs[i].where == Nowhere)
1136 continue;
Jan Beulich6d0185e2006-12-07 02:14:13 +01001137 dprintk(1, "Cannot restore register %u (%d).",
1138 i, state.regs[i].where);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001139 return -EIO;
1140 }
1141 switch(state.regs[i].where) {
1142 default:
1143 break;
1144 case Register:
1145 if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1146 || REG_INVALID(state.regs[i].value)
Jan Beulich6d0185e2006-12-07 02:14:13 +01001147 || reg_info[i].width > reg_info[state.regs[i].value].width) {
1148 dprintk(1, "Cannot restore register %u from register %lu.",
1149 i, state.regs[i].value);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001150 return -EIO;
Jan Beulich6d0185e2006-12-07 02:14:13 +01001151 }
Jan Beulich4552d5d2006-06-26 13:57:28 +02001152 switch(reg_info[state.regs[i].value].width) {
1153#define CASE(n) \
1154 case sizeof(u##n): \
1155 state.regs[i].value = FRAME_REG(state.regs[i].value, \
1156 const u##n); \
1157 break
1158 CASES;
1159#undef CASE
1160 default:
Jan Beulich6d0185e2006-12-07 02:14:13 +01001161 dprintk(1, "Unsupported register size %u (%lu).",
1162 reg_info[state.regs[i].value].width,
1163 state.regs[i].value);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001164 return -EIO;
1165 }
1166 break;
1167 }
1168 }
1169 for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1170 if (REG_INVALID(i))
1171 continue;
1172 switch(state.regs[i].where) {
1173 case Nowhere:
1174 if (reg_info[i].width != sizeof(UNW_SP(frame))
1175 || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1176 != &UNW_SP(frame))
1177 continue;
1178 UNW_SP(frame) = cfa;
1179 break;
1180 case Register:
1181 switch(reg_info[i].width) {
1182#define CASE(n) case sizeof(u##n): \
1183 FRAME_REG(i, u##n) = state.regs[i].value; \
1184 break
1185 CASES;
1186#undef CASE
1187 default:
Jan Beulich6d0185e2006-12-07 02:14:13 +01001188 dprintk(1, "Unsupported register size %u (%u).",
1189 reg_info[i].width, i);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001190 return -EIO;
1191 }
1192 break;
1193 case Value:
Jan Beulich6d0185e2006-12-07 02:14:13 +01001194 if (reg_info[i].width != sizeof(unsigned long)) {
1195 dprintk(1, "Unsupported value size %u (%u).",
1196 reg_info[i].width, i);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001197 return -EIO;
Jan Beulich6d0185e2006-12-07 02:14:13 +01001198 }
Jan Beulich4552d5d2006-06-26 13:57:28 +02001199 FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1200 * state.dataAlign;
1201 break;
1202 case Memory: {
1203 unsigned long addr = cfa + state.regs[i].value
1204 * state.dataAlign;
1205
1206 if ((state.regs[i].value * state.dataAlign)
1207 % sizeof(unsigned long)
1208 || addr < startLoc
1209 || addr + sizeof(unsigned long) < addr
Jan Beulich6d0185e2006-12-07 02:14:13 +01001210 || addr + sizeof(unsigned long) > endLoc) {
1211 dprintk(1, "Bad memory location %lx (%lx).",
1212 addr, state.regs[i].value);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001213 return -EIO;
Jan Beulich6d0185e2006-12-07 02:14:13 +01001214 }
Jan Beulich4552d5d2006-06-26 13:57:28 +02001215 switch(reg_info[i].width) {
1216#define CASE(n) case sizeof(u##n): \
Andi Kleene2124bb2006-12-07 02:14:12 +01001217 probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \
Jan Beulich4552d5d2006-06-26 13:57:28 +02001218 break
1219 CASES;
1220#undef CASE
1221 default:
Jan Beulich6d0185e2006-12-07 02:14:13 +01001222 dprintk(1, "Unsupported memory size %u (%u).",
1223 reg_info[i].width, i);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001224 return -EIO;
1225 }
1226 }
1227 break;
1228 }
1229 }
1230
Jan Beulich359ad0d2006-12-07 02:14:13 +01001231 if (UNW_PC(frame) % state.codeAlign
Jan Beulich6d0185e2006-12-07 02:14:13 +01001232 || UNW_SP(frame) % sleb128abs(state.dataAlign)) {
1233 dprintk(1, "Output pointer(s) misaligned (%lx,%lx).",
1234 UNW_PC(frame), UNW_SP(frame));
Jan Beulich359ad0d2006-12-07 02:14:13 +01001235 return -EIO;
Jan Beulich6d0185e2006-12-07 02:14:13 +01001236 }
1237 if (pc == UNW_PC(frame) && sp == UNW_SP(frame)) {
1238 dprintk(1, "No progress (%lx,%lx).", pc, sp);
1239 return -EIO;
1240 }
Jan Beulich359ad0d2006-12-07 02:14:13 +01001241
Jan Beulich4552d5d2006-06-26 13:57:28 +02001242 return 0;
1243#undef CASES
1244#undef FRAME_REG
1245}
1246EXPORT_SYMBOL(unwind);
1247
1248int unwind_init_frame_info(struct unwind_frame_info *info,
1249 struct task_struct *tsk,
1250 /*const*/ struct pt_regs *regs)
1251{
1252 info->task = tsk;
Jan Beulichadf14232006-09-26 10:52:41 +02001253 info->call_frame = 0;
Jan Beulich4552d5d2006-06-26 13:57:28 +02001254 arch_unw_init_frame_info(info, regs);
1255
1256 return 0;
1257}
1258EXPORT_SYMBOL(unwind_init_frame_info);
1259
1260/*
1261 * Prepare to unwind a blocked task.
1262 */
1263int unwind_init_blocked(struct unwind_frame_info *info,
1264 struct task_struct *tsk)
1265{
1266 info->task = tsk;
Jan Beulichadf14232006-09-26 10:52:41 +02001267 info->call_frame = 0;
Jan Beulich4552d5d2006-06-26 13:57:28 +02001268 arch_unw_init_blocked(info);
1269
1270 return 0;
1271}
1272EXPORT_SYMBOL(unwind_init_blocked);
1273
1274/*
1275 * Prepare to unwind the currently running thread.
1276 */
1277int unwind_init_running(struct unwind_frame_info *info,
Jan Beulichc33bd9a2006-06-26 13:57:47 +02001278 asmlinkage int (*callback)(struct unwind_frame_info *,
1279 void *arg),
Jan Beulich4552d5d2006-06-26 13:57:28 +02001280 void *arg)
1281{
1282 info->task = current;
Jan Beulichadf14232006-09-26 10:52:41 +02001283 info->call_frame = 0;
Jan Beulich4552d5d2006-06-26 13:57:28 +02001284
Jan Beulichc33bd9a2006-06-26 13:57:47 +02001285 return arch_unwind_init_running(info, callback, arg);
Jan Beulich4552d5d2006-06-26 13:57:28 +02001286}
1287EXPORT_SYMBOL(unwind_init_running);
1288
1289/*
1290 * Unwind until the return pointer is in user-land (or until an error
1291 * occurs). Returns 0 if successful, negative number in case of
1292 * error.
1293 */
1294int unwind_to_user(struct unwind_frame_info *info)
1295{
1296 while (!arch_unw_user_mode(info)) {
1297 int err = unwind(info);
1298
1299 if (err < 0)
1300 return err;
1301 }
1302
1303 return 0;
1304}
1305EXPORT_SYMBOL(unwind_to_user);