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