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