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