This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.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 startLoc = 0, endLoc = 0, cfa;
609         unsigned i;
610         signed ptrType = -1;
611         uleb128_t retAddrReg = 0;
612         struct unwind_table *table;
613         struct unwind_state state;
614
615         if (UNW_PC(frame) == 0)
616                 return -EINVAL;
617         if ((table = find_table(UNW_PC(frame))) != NULL
618             && !(table->size & (sizeof(*fde) - 1))) {
619                 unsigned long tableSize = table->size;
620
621                 for (fde = table->address;
622                      tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
623                      tableSize -= sizeof(*fde) + *fde,
624                      fde += 1 + *fde / sizeof(*fde)) {
625                         if (!*fde || (*fde & (sizeof(*fde) - 1)))
626                                 break;
627                         if (!fde[1])
628                                 continue; /* this is a CIE */
629                         if ((fde[1] & (sizeof(*fde) - 1))
630                             || fde[1] > (unsigned long)(fde + 1)
631                                         - (unsigned long)table->address)
632                                 continue; /* this is not a valid FDE */
633                         cie = fde + 1 - fde[1] / sizeof(*fde);
634                         if (*cie <= sizeof(*cie) + 4
635                             || *cie >= fde[1] - sizeof(*fde)
636                             || (*cie & (sizeof(*cie) - 1))
637                             || cie[1]
638                             || (ptrType = fde_pointer_type(cie)) < 0) {
639                                 cie = NULL; /* this is not a (valid) CIE */
640                                 continue;
641                         }
642                         ptr = (const u8 *)(fde + 2);
643                         startLoc = read_pointer(&ptr,
644                                                 (const u8 *)(fde + 1) + *fde,
645                                                 ptrType);
646                         endLoc = startLoc
647                                  + read_pointer(&ptr,
648                                                 (const u8 *)(fde + 1) + *fde,
649                                                 ptrType & DW_EH_PE_indirect
650                                                 ? ptrType
651                                                 : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
652                         if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
653                                 break;
654                         cie = NULL;
655                 }
656         }
657         if (cie != NULL) {
658                 memset(&state, 0, sizeof(state));
659                 state.cieEnd = ptr; /* keep here temporarily */
660                 ptr = (const u8 *)(cie + 2);
661                 end = (const u8 *)(cie + 1) + *cie;
662                 if ((state.version = *ptr) != 1)
663                         cie = NULL; /* unsupported version */
664                 else if (*++ptr) {
665                         /* check if augmentation size is first (and thus present) */
666                         if (*ptr == 'z') {
667                                 /* check for ignorable (or already handled)
668                                  * nul-terminated augmentation string */
669                                 while (++ptr < end && *ptr)
670                                         if (strchr("LPR", *ptr) == NULL)
671                                                 break;
672                         }
673                         if (ptr >= end || *ptr)
674                                 cie = NULL;
675                 }
676                 ++ptr;
677         }
678         if (cie != NULL) {
679                 /* get code aligment factor */
680                 state.codeAlign = get_uleb128(&ptr, end);
681                 /* get data aligment factor */
682                 state.dataAlign = get_sleb128(&ptr, end);
683                 if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
684                         cie = NULL;
685                 else {
686                         retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
687                         /* skip augmentation */
688                         if (((const char *)(cie + 2))[1] == 'z')
689                                 ptr += get_uleb128(&ptr, end);
690                         if (ptr > end
691                            || retAddrReg >= ARRAY_SIZE(reg_info)
692                            || REG_INVALID(retAddrReg)
693                            || reg_info[retAddrReg].width != sizeof(unsigned long))
694                                 cie = NULL;
695                 }
696         }
697         if (cie != NULL) {
698                 state.cieStart = ptr;
699                 ptr = state.cieEnd;
700                 state.cieEnd = end;
701                 end = (const u8 *)(fde + 1) + *fde;
702                 /* skip augmentation */
703                 if (((const char *)(cie + 2))[1] == 'z') {
704                         uleb128_t augSize = get_uleb128(&ptr, end);
705
706                         if ((ptr += augSize) > end)
707                                 fde = NULL;
708                 }
709         }
710         if (cie == NULL || fde == NULL) {
711 #ifdef CONFIG_FRAME_POINTER
712                 unsigned long top, bottom;
713 #endif
714
715 #ifdef CONFIG_FRAME_POINTER
716                 top = STACK_TOP(frame->task);
717                 bottom = STACK_BOTTOM(frame->task);
718 # if FRAME_RETADDR_OFFSET < 0
719                 if (UNW_SP(frame) < top
720                     && UNW_FP(frame) <= UNW_SP(frame)
721                     && bottom < UNW_FP(frame)
722 # else
723                 if (UNW_SP(frame) > top
724                     && UNW_FP(frame) >= UNW_SP(frame)
725                     && bottom > UNW_FP(frame)
726 # endif
727                    && !((UNW_SP(frame) | UNW_FP(frame))
728                         & (sizeof(unsigned long) - 1))) {
729                         unsigned long link;
730
731                         if (!__get_user(link,
732                                         (unsigned long *)(UNW_FP(frame)
733                                                           + FRAME_LINK_OFFSET))
734 # if FRAME_RETADDR_OFFSET < 0
735                            && link > bottom && link < UNW_FP(frame)
736 # else
737                            && link > UNW_FP(frame) && link < bottom
738 # endif
739                            && !(link & (sizeof(link) - 1))
740                            && !__get_user(UNW_PC(frame),
741                                           (unsigned long *)(UNW_FP(frame)
742                                                             + FRAME_RETADDR_OFFSET))) {
743                                 UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
744 # if FRAME_RETADDR_OFFSET < 0
745                                         -
746 # else
747                                         +
748 # endif
749                                           sizeof(UNW_PC(frame));
750                                 UNW_FP(frame) = link;
751                                 return 0;
752                         }
753                 }
754 #endif
755                 return -ENXIO;
756         }
757         state.org = startLoc;
758         memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
759         /* process instructions */
760         if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
761            || state.loc > endLoc
762            || state.regs[retAddrReg].where == Nowhere
763            || state.cfa.reg >= ARRAY_SIZE(reg_info)
764            || reg_info[state.cfa.reg].width != sizeof(unsigned long)
765            || state.cfa.offs % sizeof(unsigned long))
766                 return -EIO;
767         /* update frame */
768         cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
769         startLoc = min((unsigned long)UNW_SP(frame), cfa);
770         endLoc = max((unsigned long)UNW_SP(frame), cfa);
771         if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
772                 startLoc = min(STACK_LIMIT(cfa), cfa);
773                 endLoc = max(STACK_LIMIT(cfa), cfa);
774         }
775 #ifndef CONFIG_64BIT
776 # define CASES CASE(8); CASE(16); CASE(32)
777 #else
778 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
779 #endif
780         for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
781                 if (REG_INVALID(i)) {
782                         if (state.regs[i].where == Nowhere)
783                                 continue;
784                         return -EIO;
785                 }
786                 switch(state.regs[i].where) {
787                 default:
788                         break;
789                 case Register:
790                         if (state.regs[i].value >= ARRAY_SIZE(reg_info)
791                            || REG_INVALID(state.regs[i].value)
792                            || reg_info[i].width > reg_info[state.regs[i].value].width)
793                                 return -EIO;
794                         switch(reg_info[state.regs[i].value].width) {
795 #define CASE(n) \
796                         case sizeof(u##n): \
797                                 state.regs[i].value = FRAME_REG(state.regs[i].value, \
798                                                                 const u##n); \
799                                 break
800                         CASES;
801 #undef CASE
802                         default:
803                                 return -EIO;
804                         }
805                         break;
806                 }
807         }
808         for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
809                 if (REG_INVALID(i))
810                         continue;
811                 switch(state.regs[i].where) {
812                 case Nowhere:
813                         if (reg_info[i].width != sizeof(UNW_SP(frame))
814                            || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
815                               != &UNW_SP(frame))
816                                 continue;
817                         UNW_SP(frame) = cfa;
818                         break;
819                 case Register:
820                         switch(reg_info[i].width) {
821 #define CASE(n) case sizeof(u##n): \
822                                 FRAME_REG(i, u##n) = state.regs[i].value; \
823                                 break
824                         CASES;
825 #undef CASE
826                         default:
827                                 return -EIO;
828                         }
829                         break;
830                 case Value:
831                         if (reg_info[i].width != sizeof(unsigned long))
832                                 return -EIO;
833                         FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
834                                                             * state.dataAlign;
835                         break;
836                 case Memory: {
837                                 unsigned long addr = cfa + state.regs[i].value
838                                                            * state.dataAlign;
839
840                                 if ((state.regs[i].value * state.dataAlign)
841                                     % sizeof(unsigned long)
842                                     || addr < startLoc
843                                     || addr + sizeof(unsigned long) < addr
844                                     || addr + sizeof(unsigned long) > endLoc)
845                                         return -EIO;
846                                 switch(reg_info[i].width) {
847 #define CASE(n)     case sizeof(u##n): \
848                                         __get_user(FRAME_REG(i, u##n), (u##n *)addr); \
849                                         break
850                                 CASES;
851 #undef CASE
852                                 default:
853                                         return -EIO;
854                                 }
855                         }
856                         break;
857                 }
858         }
859
860         return 0;
861 #undef CASES
862 #undef FRAME_REG
863 }
864 EXPORT_SYMBOL(unwind);
865
866 int unwind_init_frame_info(struct unwind_frame_info *info,
867                            struct task_struct *tsk,
868                            /*const*/ struct pt_regs *regs)
869 {
870         info->task = tsk;
871         arch_unw_init_frame_info(info, regs);
872
873         return 0;
874 }
875 EXPORT_SYMBOL(unwind_init_frame_info);
876
877 /*
878  * Prepare to unwind a blocked task.
879  */
880 int unwind_init_blocked(struct unwind_frame_info *info,
881                         struct task_struct *tsk)
882 {
883         info->task = tsk;
884         arch_unw_init_blocked(info);
885
886         return 0;
887 }
888 EXPORT_SYMBOL(unwind_init_blocked);
889
890 /*
891  * Prepare to unwind the currently running thread.
892  */
893 int unwind_init_running(struct unwind_frame_info *info,
894                         asmlinkage int (*callback)(struct unwind_frame_info *,
895                                                    void *arg),
896                         void *arg)
897 {
898         info->task = current;
899
900         return arch_unwind_init_running(info, callback, arg);
901 }
902 EXPORT_SYMBOL(unwind_init_running);
903
904 /*
905  * Unwind until the return pointer is in user-land (or until an error
906  * occurs).  Returns 0 if successful, negative number in case of
907  * error.
908  */
909 int unwind_to_user(struct unwind_frame_info *info)
910 {
911         while (!arch_unw_user_mode(info)) {
912                 int err = unwind(info);
913
914                 if (err < 0)
915                         return err;
916         }
917
918         return 0;
919 }
920 EXPORT_SYMBOL(unwind_to_user);