[PATCH] x86_64: reliable stack trace support
[pandora-kernel.git] / kernel / unwind.c
1 /*
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>
14 #include <linux/delay.h>
15 #include <linux/stop_machine.h>
16 #include <asm/sections.h>
17 #include <asm/uaccess.h>
18 #include <asm/unaligned.h>
19
20 extern char __start_unwind[], __end_unwind[];
21
22 #define MAX_STACK_DEPTH 8
23
24 #define EXTRA_INFO(f) { \
25                 BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
26                                   % FIELD_SIZEOF(struct unwind_frame_info, f)) \
27                 + offsetof(struct unwind_frame_info, f) \
28                   / FIELD_SIZEOF(struct unwind_frame_info, f), \
29                 FIELD_SIZEOF(struct unwind_frame_info, f) \
30         }
31 #define PTREGS_INFO(f) EXTRA_INFO(regs.f)
32
33 static const struct {
34         unsigned offs:BITS_PER_LONG / 2;
35         unsigned width:BITS_PER_LONG / 2;
36 } reg_info[] = {
37         UNW_REGISTER_INFO
38 };
39
40 #undef PTREGS_INFO
41 #undef EXTRA_INFO
42
43 #ifndef REG_INVALID
44 #define REG_INVALID(r) (reg_info[r].width == 0)
45 #endif
46
47 #define DW_CFA_nop                          0x00
48 #define DW_CFA_set_loc                      0x01
49 #define DW_CFA_advance_loc1                 0x02
50 #define DW_CFA_advance_loc2                 0x03
51 #define DW_CFA_advance_loc4                 0x04
52 #define DW_CFA_offset_extended              0x05
53 #define DW_CFA_restore_extended             0x06
54 #define DW_CFA_undefined                    0x07
55 #define DW_CFA_same_value                   0x08
56 #define DW_CFA_register                     0x09
57 #define DW_CFA_remember_state               0x0a
58 #define DW_CFA_restore_state                0x0b
59 #define DW_CFA_def_cfa                      0x0c
60 #define DW_CFA_def_cfa_register             0x0d
61 #define DW_CFA_def_cfa_offset               0x0e
62 #define DW_CFA_def_cfa_expression           0x0f
63 #define DW_CFA_expression                   0x10
64 #define DW_CFA_offset_extended_sf           0x11
65 #define DW_CFA_def_cfa_sf                   0x12
66 #define DW_CFA_def_cfa_offset_sf            0x13
67 #define DW_CFA_val_offset                   0x14
68 #define DW_CFA_val_offset_sf                0x15
69 #define DW_CFA_val_expression               0x16
70 #define DW_CFA_lo_user                      0x1c
71 #define DW_CFA_GNU_window_save              0x2d
72 #define DW_CFA_GNU_args_size                0x2e
73 #define DW_CFA_GNU_negative_offset_extended 0x2f
74 #define DW_CFA_hi_user                      0x3f
75
76 #define DW_EH_PE_FORM     0x07
77 #define DW_EH_PE_native   0x00
78 #define DW_EH_PE_leb128   0x01
79 #define DW_EH_PE_data2    0x02
80 #define DW_EH_PE_data4    0x03
81 #define DW_EH_PE_data8    0x04
82 #define DW_EH_PE_signed   0x08
83 #define DW_EH_PE_ADJUST   0x70
84 #define DW_EH_PE_abs      0x00
85 #define DW_EH_PE_pcrel    0x10
86 #define DW_EH_PE_textrel  0x20
87 #define DW_EH_PE_datarel  0x30
88 #define DW_EH_PE_funcrel  0x40
89 #define DW_EH_PE_aligned  0x50
90 #define DW_EH_PE_indirect 0x80
91 #define DW_EH_PE_omit     0xff
92
93 typedef unsigned long uleb128_t;
94 typedef   signed long sleb128_t;
95
96 static struct unwind_table {
97         struct {
98                 unsigned long pc;
99                 unsigned long range;
100         } core, init;
101         const void *address;
102         unsigned long size;
103         struct unwind_table *link;
104         const char *name;
105 } root_table, *last_table;
106
107 struct unwind_item {
108         enum item_location {
109                 Nowhere,
110                 Memory,
111                 Register,
112                 Value
113         } where;
114         uleb128_t value;
115 };
116
117 struct unwind_state {
118         uleb128_t loc, org;
119         const u8 *cieStart, *cieEnd;
120         uleb128_t codeAlign;
121         sleb128_t dataAlign;
122         struct cfa {
123                 uleb128_t reg, offs;
124         } cfa;
125         struct unwind_item regs[ARRAY_SIZE(reg_info)];
126         unsigned stackDepth:8;
127         unsigned version:8;
128         const u8 *label;
129         const u8 *stack[MAX_STACK_DEPTH];
130 };
131
132 static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
133
134 static struct unwind_table *find_table(unsigned long pc)
135 {
136         struct unwind_table *table;
137
138         for (table = &root_table; table; table = table->link)
139                 if ((pc >= table->core.pc
140                      && pc < table->core.pc + table->core.range)
141                     || (pc >= table->init.pc
142                         && pc < table->init.pc + table->init.range))
143                         break;
144
145         return table;
146 }
147
148 static void init_unwind_table(struct unwind_table *table,
149                               const char *name,
150                               const void *core_start,
151                               unsigned long core_size,
152                               const void *init_start,
153                               unsigned long init_size,
154                               const void *table_start,
155                               unsigned long table_size)
156 {
157         table->core.pc = (unsigned long)core_start;
158         table->core.range = core_size;
159         table->init.pc = (unsigned long)init_start;
160         table->init.range = init_size;
161         table->address = table_start;
162         table->size = table_size;
163         table->link = NULL;
164         table->name = name;
165 }
166
167 void __init unwind_init(void)
168 {
169         init_unwind_table(&root_table, "kernel",
170                           _text, _end - _text,
171                           NULL, 0,
172                           __start_unwind, __end_unwind - __start_unwind);
173 }
174
175 /* Must be called with module_mutex held. */
176 void *unwind_add_table(struct module *module,
177                        const void *table_start,
178                        unsigned long table_size)
179 {
180         struct unwind_table *table;
181
182         if (table_size <= 0)
183                 return NULL;
184
185         table = kmalloc(sizeof(*table), GFP_KERNEL);
186         if (!table)
187                 return NULL;
188
189         init_unwind_table(table, module->name,
190                           module->module_core, module->core_size,
191                           module->module_init, module->init_size,
192                           table_start, table_size);
193
194         if (last_table)
195                 last_table->link = table;
196         else
197                 root_table.link = table;
198         last_table = table;
199
200         return table;
201 }
202
203 struct unlink_table_info
204 {
205         struct unwind_table *table;
206         int init_only;
207 };
208
209 static int unlink_table(void *arg)
210 {
211         struct unlink_table_info *info = arg;
212         struct unwind_table *table = info->table, *prev;
213
214         for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
215                 ;
216
217         if (prev->link) {
218                 if (info->init_only) {
219                         table->init.pc = 0;
220                         table->init.range = 0;
221                         info->table = NULL;
222                 } else {
223                         prev->link = table->link;
224                         if (!prev->link)
225                                 last_table = prev;
226                 }
227         } else
228                 info->table = NULL;
229
230         return 0;
231 }
232
233 /* Must be called with module_mutex held. */
234 void unwind_remove_table(void *handle, int init_only)
235 {
236         struct unwind_table *table = handle;
237         struct unlink_table_info info;
238
239         if (!table || table == &root_table)
240                 return;
241
242         if (init_only && table == last_table) {
243                 table->init.pc = 0;
244                 table->init.range = 0;
245                 return;
246         }
247
248         info.table = table;
249         info.init_only = init_only;
250         stop_machine_run(unlink_table, &info, NR_CPUS);
251
252         if (info.table)
253                 kfree(table);
254 }
255
256 static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
257 {
258         const u8 *cur = *pcur;
259         uleb128_t value;
260         unsigned shift;
261
262         for (shift = 0, value = 0; cur < end; shift += 7) {
263                 if (shift + 7 > 8 * sizeof(value)
264                     && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
265                         cur = end + 1;
266                         break;
267                 }
268                 value |= (uleb128_t)(*cur & 0x7f) << shift;
269                 if (!(*cur++ & 0x80))
270                         break;
271         }
272         *pcur = cur;
273
274         return value;
275 }
276
277 static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
278 {
279         const u8 *cur = *pcur;
280         sleb128_t value;
281         unsigned shift;
282
283         for (shift = 0, value = 0; cur < end; shift += 7) {
284                 if (shift + 7 > 8 * sizeof(value)
285                     && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
286                         cur = end + 1;
287                         break;
288                 }
289                 value |= (sleb128_t)(*cur & 0x7f) << shift;
290                 if (!(*cur & 0x80)) {
291                         value |= -(*cur++ & 0x40) << shift;
292                         break;
293                 }
294         }
295         *pcur = cur;
296
297         return value;
298 }
299
300 static unsigned long read_pointer(const u8 **pLoc,
301                                   const void *end,
302                                   signed ptrType)
303 {
304         unsigned long value = 0;
305         union {
306                 const u8 *p8;
307                 const u16 *p16u;
308                 const s16 *p16s;
309                 const u32 *p32u;
310                 const s32 *p32s;
311                 const unsigned long *pul;
312         } ptr;
313
314         if (ptrType < 0 || ptrType == DW_EH_PE_omit)
315                 return 0;
316         ptr.p8 = *pLoc;
317         switch(ptrType & DW_EH_PE_FORM) {
318         case DW_EH_PE_data2:
319                 if (end < (const void *)(ptr.p16u + 1))
320                         return 0;
321                 if(ptrType & DW_EH_PE_signed)
322                         value = get_unaligned(ptr.p16s++);
323                 else
324                         value = get_unaligned(ptr.p16u++);
325                 break;
326         case DW_EH_PE_data4:
327 #ifdef CONFIG_64BIT
328                 if (end < (const void *)(ptr.p32u + 1))
329                         return 0;
330                 if(ptrType & DW_EH_PE_signed)
331                         value = get_unaligned(ptr.p32s++);
332                 else
333                         value = get_unaligned(ptr.p32u++);
334                 break;
335         case DW_EH_PE_data8:
336                 BUILD_BUG_ON(sizeof(u64) != sizeof(value));
337 #else
338                 BUILD_BUG_ON(sizeof(u32) != sizeof(value));
339 #endif
340         case DW_EH_PE_native:
341                 if (end < (const void *)(ptr.pul + 1))
342                         return 0;
343                 value = get_unaligned(ptr.pul++);
344                 break;
345         case DW_EH_PE_leb128:
346                 BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
347                 value = ptrType & DW_EH_PE_signed
348                         ? get_sleb128(&ptr.p8, end)
349                         : get_uleb128(&ptr.p8, end);
350                 if ((const void *)ptr.p8 > end)
351                         return 0;
352                 break;
353         default:
354                 return 0;
355         }
356         switch(ptrType & DW_EH_PE_ADJUST) {
357         case DW_EH_PE_abs:
358                 break;
359         case DW_EH_PE_pcrel:
360                 value += (unsigned long)*pLoc;
361                 break;
362         default:
363                 return 0;
364         }
365         if ((ptrType & DW_EH_PE_indirect)
366             && __get_user(value, (unsigned long *)value))
367                 return 0;
368         *pLoc = ptr.p8;
369
370         return value;
371 }
372
373 static signed fde_pointer_type(const u32 *cie)
374 {
375         const u8 *ptr = (const u8 *)(cie + 2);
376         unsigned version = *ptr;
377
378         if (version != 1)
379                 return -1; /* unsupported */
380         if (*++ptr) {
381                 const char *aug;
382                 const u8 *end = (const u8 *)(cie + 1) + *cie;
383                 uleb128_t len;
384
385                 /* check if augmentation size is first (and thus present) */
386                 if (*ptr != 'z')
387                         return -1;
388                 /* check if augmentation string is nul-terminated */
389                 if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
390                         return -1;
391                 ++ptr; /* skip terminator */
392                 get_uleb128(&ptr, end); /* skip code alignment */
393                 get_sleb128(&ptr, end); /* skip data alignment */
394                 /* skip return address column */
395                 version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
396                 len = get_uleb128(&ptr, end); /* augmentation length */
397                 if (ptr + len < ptr || ptr + len > end)
398                         return -1;
399                 end = ptr + len;
400                 while (*++aug) {
401                         if (ptr >= end)
402                                 return -1;
403                         switch(*aug) {
404                         case 'L':
405                                 ++ptr;
406                                 break;
407                         case 'P': {
408                                         signed ptrType = *ptr++;
409
410                                         if (!read_pointer(&ptr, end, ptrType) || ptr > end)
411                                                 return -1;
412                                 }
413                                 break;
414                         case 'R':
415                                 return *ptr;
416                         default:
417                                 return -1;
418                         }
419                 }
420         }
421         return DW_EH_PE_native|DW_EH_PE_abs;
422 }
423
424 static int advance_loc(unsigned long delta, struct unwind_state *state)
425 {
426         state->loc += delta * state->codeAlign;
427
428         return delta > 0;
429 }
430
431 static void set_rule(uleb128_t reg,
432                      enum item_location where,
433                      uleb128_t value,
434                      struct unwind_state *state)
435 {
436         if (reg < ARRAY_SIZE(state->regs)) {
437                 state->regs[reg].where = where;
438                 state->regs[reg].value = value;
439         }
440 }
441
442 static int processCFI(const u8 *start,
443                       const u8 *end,
444                       unsigned long targetLoc,
445                       signed ptrType,
446                       struct unwind_state *state)
447 {
448         union {
449                 const u8 *p8;
450                 const u16 *p16;
451                 const u32 *p32;
452         } ptr;
453         int result = 1;
454
455         if (start != state->cieStart) {
456                 state->loc = state->org;
457                 result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
458                 if (targetLoc == 0 && state->label == NULL)
459                         return result;
460         }
461         for (ptr.p8 = start; result && ptr.p8 < end; ) {
462                 switch(*ptr.p8 >> 6) {
463                         uleb128_t value;
464
465                 case 0:
466                         switch(*ptr.p8++) {
467                         case DW_CFA_nop:
468                                 break;
469                         case DW_CFA_set_loc:
470                                 if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
471                                         result = 0;
472                                 break;
473                         case DW_CFA_advance_loc1:
474                                 result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
475                                 break;
476                         case DW_CFA_advance_loc2:
477                                 result = ptr.p8 <= end + 2
478                                          && advance_loc(*ptr.p16++, state);
479                                 break;
480                         case DW_CFA_advance_loc4:
481                                 result = ptr.p8 <= end + 4
482                                          && advance_loc(*ptr.p32++, state);
483                                 break;
484                         case DW_CFA_offset_extended:
485                                 value = get_uleb128(&ptr.p8, end);
486                                 set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
487                                 break;
488                         case DW_CFA_val_offset:
489                                 value = get_uleb128(&ptr.p8, end);
490                                 set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
491                                 break;
492                         case DW_CFA_offset_extended_sf:
493                                 value = get_uleb128(&ptr.p8, end);
494                                 set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
495                                 break;
496                         case DW_CFA_val_offset_sf:
497                                 value = get_uleb128(&ptr.p8, end);
498                                 set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
499                                 break;
500                         case DW_CFA_restore_extended:
501                         case DW_CFA_undefined:
502                         case DW_CFA_same_value:
503                                 set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
504                                 break;
505                         case DW_CFA_register:
506                                 value = get_uleb128(&ptr.p8, end);
507                                 set_rule(value,
508                                          Register,
509                                          get_uleb128(&ptr.p8, end), state);
510                                 break;
511                         case DW_CFA_remember_state:
512                                 if (ptr.p8 == state->label) {
513                                         state->label = NULL;
514                                         return 1;
515                                 }
516                                 if (state->stackDepth >= MAX_STACK_DEPTH)
517                                         return 0;
518                                 state->stack[state->stackDepth++] = ptr.p8;
519                                 break;
520                         case DW_CFA_restore_state:
521                                 if (state->stackDepth) {
522                                         const uleb128_t loc = state->loc;
523                                         const u8 *label = state->label;
524
525                                         state->label = state->stack[state->stackDepth - 1];
526                                         memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
527                                         memset(state->regs, 0, sizeof(state->regs));
528                                         state->stackDepth = 0;
529                                         result = processCFI(start, end, 0, ptrType, state);
530                                         state->loc = loc;
531                                         state->label = label;
532                                 } else
533                                         return 0;
534                                 break;
535                         case DW_CFA_def_cfa:
536                                 state->cfa.reg = get_uleb128(&ptr.p8, end);
537                                 /*nobreak*/
538                         case DW_CFA_def_cfa_offset:
539                                 state->cfa.offs = get_uleb128(&ptr.p8, end);
540                                 break;
541                         case DW_CFA_def_cfa_sf:
542                                 state->cfa.reg = get_uleb128(&ptr.p8, end);
543                                 /*nobreak*/
544                         case DW_CFA_def_cfa_offset_sf:
545                                 state->cfa.offs = get_sleb128(&ptr.p8, end)
546                                                   * state->dataAlign;
547                                 break;
548                         case DW_CFA_def_cfa_register:
549                                 state->cfa.reg = get_uleb128(&ptr.p8, end);
550                                 break;
551                         /*todo case DW_CFA_def_cfa_expression: */
552                         /*todo case DW_CFA_expression: */
553                         /*todo case DW_CFA_val_expression: */
554                         case DW_CFA_GNU_args_size:
555                                 get_uleb128(&ptr.p8, end);
556                                 break;
557                         case DW_CFA_GNU_negative_offset_extended:
558                                 value = get_uleb128(&ptr.p8, end);
559                                 set_rule(value,
560                                          Memory,
561                                          (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
562                                 break;
563                         case DW_CFA_GNU_window_save:
564                         default:
565                                 result = 0;
566                                 break;
567                         }
568                         break;
569                 case 1:
570                         result = advance_loc(*ptr.p8++ & 0x3f, state);
571                         break;
572                 case 2:
573                         value = *ptr.p8++ & 0x3f;
574                         set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
575                         break;
576                 case 3:
577                         set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
578                         break;
579                 }
580                 if (ptr.p8 > end)
581                         result = 0;
582                 if (result && targetLoc != 0 && targetLoc < state->loc)
583                         return 1;
584         }
585
586         return result
587            && ptr.p8 == end
588            && (targetLoc == 0
589             || (/*todo While in theory this should apply, gcc in practice omits
590                   everything past the function prolog, and hence the location
591                   never reaches the end of the function.
592                 targetLoc < state->loc &&*/ state->label == NULL));
593 }
594
595 /* Unwind to previous to frame.  Returns 0 if successful, negative
596  * number in case of an error. */
597 int unwind(struct unwind_frame_info *frame)
598 {
599 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
600         const u32 *fde = NULL, *cie = NULL;
601         const u8 *ptr = NULL, *end = NULL;
602         unsigned long startLoc = 0, endLoc = 0, cfa;
603         unsigned i;
604         signed ptrType = -1;
605         uleb128_t retAddrReg = 0;
606         struct unwind_table *table;
607         struct unwind_state state;
608
609         if (UNW_PC(frame) == 0)
610                 return -EINVAL;
611         if ((table = find_table(UNW_PC(frame))) != NULL
612             && !(table->size & (sizeof(*fde) - 1))) {
613                 unsigned long tableSize = table->size;
614
615                 for (fde = table->address;
616                      tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
617                      tableSize -= sizeof(*fde) + *fde,
618                      fde += 1 + *fde / sizeof(*fde)) {
619                         if (!*fde || (*fde & (sizeof(*fde) - 1)))
620                                 break;
621                         if (!fde[1])
622                                 continue; /* this is a CIE */
623                         if ((fde[1] & (sizeof(*fde) - 1))
624                             || fde[1] > (unsigned long)(fde + 1)
625                                         - (unsigned long)table->address)
626                                 continue; /* this is not a valid FDE */
627                         cie = fde + 1 - fde[1] / sizeof(*fde);
628                         if (*cie <= sizeof(*cie) + 4
629                             || *cie >= fde[1] - sizeof(*fde)
630                             || (*cie & (sizeof(*cie) - 1))
631                             || cie[1]
632                             || (ptrType = fde_pointer_type(cie)) < 0) {
633                                 cie = NULL; /* this is not a (valid) CIE */
634                                 continue;
635                         }
636                         ptr = (const u8 *)(fde + 2);
637                         startLoc = read_pointer(&ptr,
638                                                 (const u8 *)(fde + 1) + *fde,
639                                                 ptrType);
640                         endLoc = startLoc
641                                  + read_pointer(&ptr,
642                                                 (const u8 *)(fde + 1) + *fde,
643                                                 ptrType & DW_EH_PE_indirect
644                                                 ? ptrType
645                                                 : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
646                         if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
647                                 break;
648                         cie = NULL;
649                 }
650         }
651         if (cie != NULL) {
652                 memset(&state, 0, sizeof(state));
653                 state.cieEnd = ptr; /* keep here temporarily */
654                 ptr = (const u8 *)(cie + 2);
655                 end = (const u8 *)(cie + 1) + *cie;
656                 if ((state.version = *ptr) != 1)
657                         cie = NULL; /* unsupported version */
658                 else if (*++ptr) {
659                         /* check if augmentation size is first (and thus present) */
660                         if (*ptr == 'z') {
661                                 /* check for ignorable (or already handled)
662                                  * nul-terminated augmentation string */
663                                 while (++ptr < end && *ptr)
664                                         if (strchr("LPR", *ptr) == NULL)
665                                                 break;
666                         }
667                         if (ptr >= end || *ptr)
668                                 cie = NULL;
669                 }
670                 ++ptr;
671         }
672         if (cie != NULL) {
673                 /* get code aligment factor */
674                 state.codeAlign = get_uleb128(&ptr, end);
675                 /* get data aligment factor */
676                 state.dataAlign = get_sleb128(&ptr, end);
677                 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
678                         cie = NULL;
679                 else {
680                         retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
681                         /* skip augmentation */
682                         if (((const char *)(cie + 2))[1] == 'z')
683                                 ptr += get_uleb128(&ptr, end);
684                         if (ptr > end
685                            || retAddrReg >= ARRAY_SIZE(reg_info)
686                            || REG_INVALID(retAddrReg)
687                            || reg_info[retAddrReg].width != sizeof(unsigned long))
688                                 cie = NULL;
689                 }
690         }
691         if (cie != NULL) {
692                 state.cieStart = ptr;
693                 ptr = state.cieEnd;
694                 state.cieEnd = end;
695                 end = (const u8 *)(fde + 1) + *fde;
696                 /* skip augmentation */
697                 if (((const char *)(cie + 2))[1] == 'z') {
698                         uleb128_t augSize = get_uleb128(&ptr, end);
699
700                         if ((ptr += augSize) > end)
701                                 fde = NULL;
702                 }
703         }
704         if (cie == NULL || fde == NULL) {
705 #ifdef CONFIG_FRAME_POINTER
706                 unsigned long top, bottom;
707 #endif
708
709 #ifdef CONFIG_FRAME_POINTER
710                 top = STACK_TOP(frame->task);
711                 bottom = STACK_BOTTOM(frame->task);
712 # if FRAME_RETADDR_OFFSET < 0
713                 if (UNW_SP(frame) < top
714                     && UNW_FP(frame) <= UNW_SP(frame)
715                     && bottom < UNW_FP(frame)
716 # else
717                 if (UNW_SP(frame) > top
718                     && UNW_FP(frame) >= UNW_SP(frame)
719                     && bottom > UNW_FP(frame)
720 # endif
721                    && !((UNW_SP(frame) | UNW_FP(frame))
722                         & (sizeof(unsigned long) - 1))) {
723                         unsigned long link;
724
725                         if (!__get_user(link,
726                                         (unsigned long *)(UNW_FP(frame)
727                                                           + FRAME_LINK_OFFSET))
728 # if FRAME_RETADDR_OFFSET < 0
729                            && link > bottom && link < UNW_FP(frame)
730 # else
731                            && link > UNW_FP(frame) && link < bottom
732 # endif
733                            && !(link & (sizeof(link) - 1))
734                            && !__get_user(UNW_PC(frame),
735                                           (unsigned long *)(UNW_FP(frame)
736                                                             + FRAME_RETADDR_OFFSET))) {
737                                 UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
738 # if FRAME_RETADDR_OFFSET < 0
739                                         -
740 # else
741                                         +
742 # endif
743                                           sizeof(UNW_PC(frame));
744                                 UNW_FP(frame) = link;
745                                 return 0;
746                         }
747                 }
748 #endif
749                 return -ENXIO;
750         }
751         state.org = startLoc;
752         memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
753         /* process instructions */
754         if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
755            || state.loc > endLoc
756            || state.regs[retAddrReg].where == Nowhere
757            || state.cfa.reg >= ARRAY_SIZE(reg_info)
758            || reg_info[state.cfa.reg].width != sizeof(unsigned long)
759            || state.cfa.offs % sizeof(unsigned long))
760                 return -EIO;
761         /* update frame */
762         cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
763         startLoc = min((unsigned long)UNW_SP(frame), cfa);
764         endLoc = max((unsigned long)UNW_SP(frame), cfa);
765         if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
766                 startLoc = min(STACK_LIMIT(cfa), cfa);
767                 endLoc = max(STACK_LIMIT(cfa), cfa);
768         }
769 #ifndef CONFIG_64BIT
770 # define CASES CASE(8); CASE(16); CASE(32)
771 #else
772 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
773 #endif
774         for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
775                 if (REG_INVALID(i)) {
776                         if (state.regs[i].where == Nowhere)
777                                 continue;
778                         return -EIO;
779                 }
780                 switch(state.regs[i].where) {
781                 default:
782                         break;
783                 case Register:
784                         if (state.regs[i].value >= ARRAY_SIZE(reg_info)
785                            || REG_INVALID(state.regs[i].value)
786                            || reg_info[i].width > reg_info[state.regs[i].value].width)
787                                 return -EIO;
788                         switch(reg_info[state.regs[i].value].width) {
789 #define CASE(n) \
790                         case sizeof(u##n): \
791                                 state.regs[i].value = FRAME_REG(state.regs[i].value, \
792                                                                 const u##n); \
793                                 break
794                         CASES;
795 #undef CASE
796                         default:
797                                 return -EIO;
798                         }
799                         break;
800                 }
801         }
802         for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
803                 if (REG_INVALID(i))
804                         continue;
805                 switch(state.regs[i].where) {
806                 case Nowhere:
807                         if (reg_info[i].width != sizeof(UNW_SP(frame))
808                            || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
809                               != &UNW_SP(frame))
810                                 continue;
811                         UNW_SP(frame) = cfa;
812                         break;
813                 case Register:
814                         switch(reg_info[i].width) {
815 #define CASE(n) case sizeof(u##n): \
816                                 FRAME_REG(i, u##n) = state.regs[i].value; \
817                                 break
818                         CASES;
819 #undef CASE
820                         default:
821                                 return -EIO;
822                         }
823                         break;
824                 case Value:
825                         if (reg_info[i].width != sizeof(unsigned long))
826                                 return -EIO;
827                         FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
828                                                             * state.dataAlign;
829                         break;
830                 case Memory: {
831                                 unsigned long addr = cfa + state.regs[i].value
832                                                            * state.dataAlign;
833
834                                 if ((state.regs[i].value * state.dataAlign)
835                                     % sizeof(unsigned long)
836                                     || addr < startLoc
837                                     || addr + sizeof(unsigned long) < addr
838                                     || addr + sizeof(unsigned long) > endLoc)
839                                         return -EIO;
840                                 switch(reg_info[i].width) {
841 #define CASE(n)     case sizeof(u##n): \
842                                         __get_user(FRAME_REG(i, u##n), (u##n *)addr); \
843                                         break
844                                 CASES;
845 #undef CASE
846                                 default:
847                                         return -EIO;
848                                 }
849                         }
850                         break;
851                 }
852         }
853
854         return 0;
855 #undef CASES
856 #undef FRAME_REG
857 }
858 EXPORT_SYMBOL(unwind);
859
860 int unwind_init_frame_info(struct unwind_frame_info *info,
861                            struct task_struct *tsk,
862                            /*const*/ struct pt_regs *regs)
863 {
864         info->task = tsk;
865         arch_unw_init_frame_info(info, regs);
866
867         return 0;
868 }
869 EXPORT_SYMBOL(unwind_init_frame_info);
870
871 /*
872  * Prepare to unwind a blocked task.
873  */
874 int unwind_init_blocked(struct unwind_frame_info *info,
875                         struct task_struct *tsk)
876 {
877         info->task = tsk;
878         arch_unw_init_blocked(info);
879
880         return 0;
881 }
882 EXPORT_SYMBOL(unwind_init_blocked);
883
884 /*
885  * Prepare to unwind the currently running thread.
886  */
887 int unwind_init_running(struct unwind_frame_info *info,
888                         asmlinkage void (*callback)(struct unwind_frame_info *,
889                                                     void *arg),
890                         void *arg)
891 {
892         info->task = current;
893         arch_unwind_init_running(info, callback, arg);
894
895         return 0;
896 }
897 EXPORT_SYMBOL(unwind_init_running);
898
899 /*
900  * Unwind until the return pointer is in user-land (or until an error
901  * occurs).  Returns 0 if successful, negative number in case of
902  * error.
903  */
904 int unwind_to_user(struct unwind_frame_info *info)
905 {
906         while (!arch_unw_user_mode(info)) {
907                 int err = unwind(info);
908
909                 if (err < 0)
910                         return err;
911         }
912
913         return 0;
914 }
915 EXPORT_SYMBOL(unwind_to_user);