linux/arch/arc/kernel/unwind.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
   3 * Copyright (C) 2002-2006 Novell, Inc.
   4 *      Jan Beulich <jbeulich@novell.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 * A simple API for unwinding kernel stacks.  This is used for
  11 * debugging and error reporting purposes.  The kernel doesn't need
  12 * full-blown stack unwinding with all the bells and whistles, so there
  13 * is not much point in implementing the full Dwarf2 unwind API.
  14 */
  15
  16#include <linux/sched.h>
  17#include <linux/module.h>
  18#include <linux/bootmem.h>
  19#include <linux/sort.h>
  20#include <linux/slab.h>
  21#include <linux/stop_machine.h>
  22#include <linux/uaccess.h>
  23#include <linux/ptrace.h>
  24#include <asm/sections.h>
  25#include <asm/unaligned.h>
  26#include <asm/unwind.h>
  27
  28extern char __start_unwind[], __end_unwind[];
  29/* extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];*/
  30
  31/* #define UNWIND_DEBUG */
  32
  33#ifdef UNWIND_DEBUG
  34int dbg_unw;
  35#define unw_debug(fmt, ...)                     \
  36do {                                            \
  37        if (dbg_unw)                            \
  38                pr_info(fmt, ##__VA_ARGS__);    \
  39} while (0);
  40#else
  41#define unw_debug(fmt, ...)
  42#endif
  43
  44#define MAX_STACK_DEPTH 8
  45
  46#define EXTRA_INFO(f) { \
  47                BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
  48                                % FIELD_SIZEOF(struct unwind_frame_info, f)) \
  49                                + offsetof(struct unwind_frame_info, f) \
  50                                / FIELD_SIZEOF(struct unwind_frame_info, f), \
  51                                FIELD_SIZEOF(struct unwind_frame_info, f) \
  52        }
  53#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
  54
  55static const struct {
  56        unsigned offs:BITS_PER_LONG / 2;
  57        unsigned width:BITS_PER_LONG / 2;
  58} reg_info[] = {
  59UNW_REGISTER_INFO};
  60
  61#undef PTREGS_INFO
  62#undef EXTRA_INFO
  63
  64#ifndef REG_INVALID
  65#define REG_INVALID(r) (reg_info[r].width == 0)
  66#endif
  67
  68#define DW_CFA_nop                          0x00
  69#define DW_CFA_set_loc                      0x01
  70#define DW_CFA_advance_loc1                 0x02
  71#define DW_CFA_advance_loc2                 0x03
  72#define DW_CFA_advance_loc4                 0x04
  73#define DW_CFA_offset_extended              0x05
  74#define DW_CFA_restore_extended             0x06
  75#define DW_CFA_undefined                    0x07
  76#define DW_CFA_same_value                   0x08
  77#define DW_CFA_register                     0x09
  78#define DW_CFA_remember_state               0x0a
  79#define DW_CFA_restore_state                0x0b
  80#define DW_CFA_def_cfa                      0x0c
  81#define DW_CFA_def_cfa_register             0x0d
  82#define DW_CFA_def_cfa_offset               0x0e
  83#define DW_CFA_def_cfa_expression           0x0f
  84#define DW_CFA_expression                   0x10
  85#define DW_CFA_offset_extended_sf           0x11
  86#define DW_CFA_def_cfa_sf                   0x12
  87#define DW_CFA_def_cfa_offset_sf            0x13
  88#define DW_CFA_val_offset                   0x14
  89#define DW_CFA_val_offset_sf                0x15
  90#define DW_CFA_val_expression               0x16
  91#define DW_CFA_lo_user                      0x1c
  92#define DW_CFA_GNU_window_save              0x2d
  93#define DW_CFA_GNU_args_size                0x2e
  94#define DW_CFA_GNU_negative_offset_extended 0x2f
  95#define DW_CFA_hi_user                      0x3f
  96
  97#define DW_EH_PE_FORM     0x07
  98#define DW_EH_PE_native   0x00
  99#define DW_EH_PE_leb128   0x01
 100#define DW_EH_PE_data2    0x02
 101#define DW_EH_PE_data4    0x03
 102#define DW_EH_PE_data8    0x04
 103#define DW_EH_PE_signed   0x08
 104#define DW_EH_PE_ADJUST   0x70
 105#define DW_EH_PE_abs      0x00
 106#define DW_EH_PE_pcrel    0x10
 107#define DW_EH_PE_textrel  0x20
 108#define DW_EH_PE_datarel  0x30
 109#define DW_EH_PE_funcrel  0x40
 110#define DW_EH_PE_aligned  0x50
 111#define DW_EH_PE_indirect 0x80
 112#define DW_EH_PE_omit     0xff
 113
 114typedef unsigned long uleb128_t;
 115typedef signed long sleb128_t;
 116
 117static struct unwind_table {
 118        struct {
 119                unsigned long pc;
 120                unsigned long range;
 121        } core, init;
 122        const void *address;
 123        unsigned long size;
 124        const unsigned char *header;
 125        unsigned long hdrsz;
 126        struct unwind_table *link;
 127        const char *name;
 128} root_table;
 129
 130struct unwind_item {
 131        enum item_location {
 132                Nowhere,
 133                Memory,
 134                Register,
 135                Value
 136        } where;
 137        uleb128_t value;
 138};
 139
 140struct unwind_state {
 141        uleb128_t loc, org;
 142        const u8 *cieStart, *cieEnd;
 143        uleb128_t codeAlign;
 144        sleb128_t dataAlign;
 145        struct cfa {
 146                uleb128_t reg, offs;
 147        } cfa;
 148        struct unwind_item regs[ARRAY_SIZE(reg_info)];
 149        unsigned stackDepth:8;
 150        unsigned version:8;
 151        const u8 *label;
 152        const u8 *stack[MAX_STACK_DEPTH];
 153};
 154
 155static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
 156
 157static struct unwind_table *find_table(unsigned long pc)
 158{
 159        struct unwind_table *table;
 160
 161        for (table = &root_table; table; table = table->link)
 162                if ((pc >= table->core.pc
 163                     && pc < table->core.pc + table->core.range)
 164                    || (pc >= table->init.pc
 165                        && pc < table->init.pc + table->init.range))
 166                        break;
 167
 168        return table;
 169}
 170
 171static unsigned long read_pointer(const u8 **pLoc,
 172                                  const void *end, signed ptrType);
 173static void init_unwind_hdr(struct unwind_table *table,
 174                            void *(*alloc) (unsigned long));
 175
 176/*
 177 * wrappers for header alloc (vs. calling one vs. other at call site)
 178 * to elide section mismatches warnings
 179 */
 180static void *__init unw_hdr_alloc_early(unsigned long sz)
 181{
 182        return __alloc_bootmem_nopanic(sz, sizeof(unsigned int),
 183                                       MAX_DMA_ADDRESS);
 184}
 185
 186static void *unw_hdr_alloc(unsigned long sz)
 187{
 188        return kmalloc(sz, GFP_KERNEL);
 189}
 190
 191static void init_unwind_table(struct unwind_table *table, const char *name,
 192                              const void *core_start, unsigned long core_size,
 193                              const void *init_start, unsigned long init_size,
 194                              const void *table_start, unsigned long table_size,
 195                              const u8 *header_start, unsigned long header_size)
 196{
 197        const u8 *ptr = header_start + 4;
 198        const u8 *end = header_start + header_size;
 199
 200        table->core.pc = (unsigned long)core_start;
 201        table->core.range = core_size;
 202        table->init.pc = (unsigned long)init_start;
 203        table->init.range = init_size;
 204        table->address = table_start;
 205        table->size = table_size;
 206
 207        /* See if the linker provided table looks valid. */
 208        if (header_size <= 4
 209            || header_start[0] != 1
 210            || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
 211            || header_start[2] == DW_EH_PE_omit
 212            || read_pointer(&ptr, end, header_start[2]) <= 0
 213            || header_start[3] == DW_EH_PE_omit)
 214                header_start = NULL;
 215
 216        table->hdrsz = header_size;
 217        smp_wmb();
 218        table->header = header_start;
 219        table->link = NULL;
 220        table->name = name;
 221}
 222
 223void __init arc_unwind_init(void)
 224{
 225        init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
 226                          __start_unwind, __end_unwind - __start_unwind,
 227                          NULL, 0);
 228          /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
 229
 230        init_unwind_hdr(&root_table, unw_hdr_alloc_early);
 231}
 232
 233static const u32 bad_cie, not_fde;
 234static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
 235static signed fde_pointer_type(const u32 *cie);
 236
 237struct eh_frame_hdr_table_entry {
 238        unsigned long start, fde;
 239};
 240
 241static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
 242{
 243        const struct eh_frame_hdr_table_entry *e1 = p1;
 244        const struct eh_frame_hdr_table_entry *e2 = p2;
 245
 246        return (e1->start > e2->start) - (e1->start < e2->start);
 247}
 248
 249static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
 250{
 251        struct eh_frame_hdr_table_entry *e1 = p1;
 252        struct eh_frame_hdr_table_entry *e2 = p2;
 253        unsigned long v;
 254
 255        v = e1->start;
 256        e1->start = e2->start;
 257        e2->start = v;
 258        v = e1->fde;
 259        e1->fde = e2->fde;
 260        e2->fde = v;
 261}
 262
 263static void init_unwind_hdr(struct unwind_table *table,
 264                            void *(*alloc) (unsigned long))
 265{
 266        const u8 *ptr;
 267        unsigned long tableSize = table->size, hdrSize;
 268        unsigned n;
 269        const u32 *fde;
 270        struct {
 271                u8 version;
 272                u8 eh_frame_ptr_enc;
 273                u8 fde_count_enc;
 274                u8 table_enc;
 275                unsigned long eh_frame_ptr;
 276                unsigned int fde_count;
 277                struct eh_frame_hdr_table_entry table[];
 278        } __attribute__ ((__packed__)) *header;
 279
 280        if (table->header)
 281                return;
 282
 283        if (table->hdrsz)
 284                pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
 285                        table->name);
 286
 287        if (tableSize & (sizeof(*fde) - 1))
 288                return;
 289
 290        for (fde = table->address, n = 0;
 291             tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
 292             tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
 293                const u32 *cie = cie_for_fde(fde, table);
 294                signed ptrType;
 295
 296                if (cie == &not_fde)
 297                        continue;
 298                if (cie == NULL || cie == &bad_cie)
 299                        goto ret_err;
 300                ptrType = fde_pointer_type(cie);
 301                if (ptrType < 0)
 302                        goto ret_err;
 303
 304                ptr = (const u8 *)(fde + 2);
 305                if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
 306                                                                ptrType)) {
 307                        /* FIXME_Rajesh We have 4 instances of null addresses
 308                         * instead of the initial loc addr
 309                         * return;
 310                         */
 311                        WARN(1, "unwinder: FDE->initial_location NULL %p\n",
 312                                (const u8 *)(fde + 1) + *fde);
 313                }
 314                ++n;
 315        }
 316
 317        if (tableSize || !n)
 318                goto ret_err;
 319
 320        hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
 321            + 2 * n * sizeof(unsigned long);
 322
 323        header = alloc(hdrSize);
 324        if (!header)
 325                goto ret_err;
 326
 327        header->version = 1;
 328        header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
 329        header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
 330        header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
 331        put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
 332        BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
 333                     % __alignof(typeof(header->fde_count)));
 334        header->fde_count = n;
 335
 336        BUILD_BUG_ON(offsetof(typeof(*header), table)
 337                     % __alignof(typeof(*header->table)));
 338        for (fde = table->address, tableSize = table->size, n = 0;
 339             tableSize;
 340             tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
 341                /* const u32 *cie = fde + 1 - fde[1] / sizeof(*fde); */
 342                const u32 *cie = (const u32 *)(fde[1]);
 343
 344                if (fde[1] == 0xffffffff)
 345                        continue;       /* this is a CIE */
 346                ptr = (const u8 *)(fde + 2);
 347                header->table[n].start = read_pointer(&ptr,
 348                                                      (const u8 *)(fde + 1) +
 349                                                      *fde,
 350                                                      fde_pointer_type(cie));
 351                header->table[n].fde = (unsigned long)fde;
 352                ++n;
 353        }
 354        WARN_ON(n != header->fde_count);
 355
 356        sort(header->table,
 357             n,
 358             sizeof(*header->table),
 359             cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
 360
 361        table->hdrsz = hdrSize;
 362        smp_wmb();
 363        table->header = (const void *)header;
 364        return;
 365
 366ret_err:
 367        panic("Attention !!! Dwarf FDE parsing errors\n");;
 368}
 369
 370#ifdef CONFIG_MODULES
 371
 372static struct unwind_table *last_table;
 373
 374/* Must be called with module_mutex held. */
 375void *unwind_add_table(struct module *module, const void *table_start,
 376                       unsigned long table_size)
 377{
 378        struct unwind_table *table;
 379
 380        if (table_size <= 0)
 381                return NULL;
 382
 383        table = kmalloc(sizeof(*table), GFP_KERNEL);
 384        if (!table)
 385                return NULL;
 386
 387        init_unwind_table(table, module->name,
 388                          module->core_layout.base, module->core_layout.size,
 389                          module->init_layout.base, module->init_layout.size,
 390                          table_start, table_size,
 391                          NULL, 0);
 392
 393        init_unwind_hdr(table, unw_hdr_alloc);
 394
 395#ifdef UNWIND_DEBUG
 396        unw_debug("Table added for [%s] %lx %lx\n",
 397                module->name, table->core.pc, table->core.range);
 398#endif
 399        if (last_table)
 400                last_table->link = table;
 401        else
 402                root_table.link = table;
 403        last_table = table;
 404
 405        return table;
 406}
 407
 408struct unlink_table_info {
 409        struct unwind_table *table;
 410        int init_only;
 411};
 412
 413static int unlink_table(void *arg)
 414{
 415        struct unlink_table_info *info = arg;
 416        struct unwind_table *table = info->table, *prev;
 417
 418        for (prev = &root_table; prev->link && prev->link != table;
 419             prev = prev->link)
 420                ;
 421
 422        if (prev->link) {
 423                if (info->init_only) {
 424                        table->init.pc = 0;
 425                        table->init.range = 0;
 426                        info->table = NULL;
 427                } else {
 428                        prev->link = table->link;
 429                        if (!prev->link)
 430                                last_table = prev;
 431                }
 432        } else
 433                info->table = NULL;
 434
 435        return 0;
 436}
 437
 438/* Must be called with module_mutex held. */
 439void unwind_remove_table(void *handle, int init_only)
 440{
 441        struct unwind_table *table = handle;
 442        struct unlink_table_info info;
 443
 444        if (!table || table == &root_table)
 445                return;
 446
 447        if (init_only && table == last_table) {
 448                table->init.pc = 0;
 449                table->init.range = 0;
 450                return;
 451        }
 452
 453        info.table = table;
 454        info.init_only = init_only;
 455
 456        unlink_table(&info); /* XXX: SMP */
 457        kfree(table->header);
 458        kfree(table);
 459}
 460
 461#endif /* CONFIG_MODULES */
 462
 463static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
 464{
 465        const u8 *cur = *pcur;
 466        uleb128_t value;
 467        unsigned shift;
 468
 469        for (shift = 0, value = 0; cur < end; shift += 7) {
 470                if (shift + 7 > 8 * sizeof(value)
 471                    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
 472                        cur = end + 1;
 473                        break;
 474                }
 475                value |= (uleb128_t) (*cur & 0x7f) << shift;
 476                if (!(*cur++ & 0x80))
 477                        break;
 478        }
 479        *pcur = cur;
 480
 481        return value;
 482}
 483
 484static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
 485{
 486        const u8 *cur = *pcur;
 487        sleb128_t value;
 488        unsigned shift;
 489
 490        for (shift = 0, value = 0; cur < end; shift += 7) {
 491                if (shift + 7 > 8 * sizeof(value)
 492                    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
 493                        cur = end + 1;
 494                        break;
 495                }
 496                value |= (sleb128_t) (*cur & 0x7f) << shift;
 497                if (!(*cur & 0x80)) {
 498                        value |= -(*cur++ & 0x40) << shift;
 499                        break;
 500                }
 501        }
 502        *pcur = cur;
 503
 504        return value;
 505}
 506
 507static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
 508{
 509        const u32 *cie;
 510
 511        if (!*fde || (*fde & (sizeof(*fde) - 1)))
 512                return &bad_cie;
 513
 514        if (fde[1] == 0xffffffff)
 515                return &not_fde;        /* this is a CIE */
 516
 517        if ((fde[1] & (sizeof(*fde) - 1)))
 518/* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
 519                return NULL;    /* this is not a valid FDE */
 520
 521        /* cie = fde + 1 - fde[1] / sizeof(*fde); */
 522        cie = (u32 *) fde[1];
 523
 524        if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
 525            || (*cie & (sizeof(*cie) - 1))
 526            || (cie[1] != 0xffffffff))
 527                return NULL;    /* this is not a (valid) CIE */
 528        return cie;
 529}
 530
 531static unsigned long read_pointer(const u8 **pLoc, const void *end,
 532                                  signed ptrType)
 533{
 534        unsigned long value = 0;
 535        union {
 536                const u8 *p8;
 537                const u16 *p16u;
 538                const s16 *p16s;
 539                const u32 *p32u;
 540                const s32 *p32s;
 541                const unsigned long *pul;
 542        } ptr;
 543
 544        if (ptrType < 0 || ptrType == DW_EH_PE_omit)
 545                return 0;
 546        ptr.p8 = *pLoc;
 547        switch (ptrType & DW_EH_PE_FORM) {
 548        case DW_EH_PE_data2:
 549                if (end < (const void *)(ptr.p16u + 1))
 550                        return 0;
 551                if (ptrType & DW_EH_PE_signed)
 552                        value = get_unaligned((u16 *) ptr.p16s++);
 553                else
 554                        value = get_unaligned((u16 *) ptr.p16u++);
 555                break;
 556        case DW_EH_PE_data4:
 557#ifdef CONFIG_64BIT
 558                if (end < (const void *)(ptr.p32u + 1))
 559                        return 0;
 560                if (ptrType & DW_EH_PE_signed)
 561                        value = get_unaligned(ptr.p32s++);
 562                else
 563                        value = get_unaligned(ptr.p32u++);
 564                break;
 565        case DW_EH_PE_data8:
 566                BUILD_BUG_ON(sizeof(u64) != sizeof(value));
 567#else
 568                BUILD_BUG_ON(sizeof(u32) != sizeof(value));
 569#endif
 570        case DW_EH_PE_native:
 571                if (end < (const void *)(ptr.pul + 1))
 572                        return 0;
 573                value = get_unaligned((unsigned long *)ptr.pul++);
 574                break;
 575        case DW_EH_PE_leb128:
 576                BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
 577                value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
 578                    : get_uleb128(&ptr.p8, end);
 579                if ((const void *)ptr.p8 > end)
 580                        return 0;
 581                break;
 582        default:
 583                return 0;
 584        }
 585        switch (ptrType & DW_EH_PE_ADJUST) {
 586        case DW_EH_PE_abs:
 587                break;
 588        case DW_EH_PE_pcrel:
 589                value += (unsigned long)*pLoc;
 590                break;
 591        default:
 592                return 0;
 593        }
 594        if ((ptrType & DW_EH_PE_indirect)
 595            && __get_user(value, (unsigned long __user *)value))
 596                return 0;
 597        *pLoc = ptr.p8;
 598
 599        return value;
 600}
 601
 602static signed fde_pointer_type(const u32 *cie)
 603{
 604        const u8 *ptr = (const u8 *)(cie + 2);
 605        unsigned version = *ptr;
 606
 607        if (*++ptr) {
 608                const char *aug;
 609                const u8 *end = (const u8 *)(cie + 1) + *cie;
 610                uleb128_t len;
 611
 612                /* check if augmentation size is first (and thus present) */
 613                if (*ptr != 'z')
 614                        return -1;
 615
 616                /* check if augmentation string is nul-terminated */
 617                aug = (const void *)ptr;
 618                ptr = memchr(aug, 0, end - ptr);
 619                if (ptr == NULL)
 620                        return -1;
 621
 622                ++ptr;          /* skip terminator */
 623                get_uleb128(&ptr, end); /* skip code alignment */
 624                get_sleb128(&ptr, end); /* skip data alignment */
 625                /* skip return address column */
 626                version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
 627                len = get_uleb128(&ptr, end);   /* augmentation length */
 628
 629                if (ptr + len < ptr || ptr + len > end)
 630                        return -1;
 631
 632                end = ptr + len;
 633                while (*++aug) {
 634                        if (ptr >= end)
 635                                return -1;
 636                        switch (*aug) {
 637                        case 'L':
 638                                ++ptr;
 639                                break;
 640                        case 'P':{
 641                                        signed ptrType = *ptr++;
 642
 643                                        if (!read_pointer(&ptr, end, ptrType)
 644                                            || ptr > end)
 645                                                return -1;
 646                                }
 647                                break;
 648                        case 'R':
 649                                return *ptr;
 650                        default:
 651                                return -1;
 652                        }
 653                }
 654        }
 655        return DW_EH_PE_native | DW_EH_PE_abs;
 656}
 657
 658static int advance_loc(unsigned long delta, struct unwind_state *state)
 659{
 660        state->loc += delta * state->codeAlign;
 661
 662        /* FIXME_Rajesh: Probably we are defining for the initial range as well;
 663           return delta > 0;
 664         */
 665        unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
 666        return 1;
 667}
 668
 669static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
 670                     struct unwind_state *state)
 671{
 672        if (reg < ARRAY_SIZE(state->regs)) {
 673                state->regs[reg].where = where;
 674                state->regs[reg].value = value;
 675
 676#ifdef UNWIND_DEBUG
 677                unw_debug("r%lu: ", reg);
 678                switch (where) {
 679                case Nowhere:
 680                        unw_debug("s ");
 681                        break;
 682                case Memory:
 683                        unw_debug("c(%lu) ", value);
 684                        break;
 685                case Register:
 686                        unw_debug("r(%lu) ", value);
 687                        break;
 688                case Value:
 689                        unw_debug("v(%lu) ", value);
 690                        break;
 691                default:
 692                        break;
 693                }
 694#endif
 695        }
 696}
 697
 698static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
 699                      signed ptrType, struct unwind_state *state)
 700{
 701        union {
 702                const u8 *p8;
 703                const u16 *p16;
 704                const u32 *p32;
 705        } ptr;
 706        int result = 1;
 707        u8 opcode;
 708
 709        if (start != state->cieStart) {
 710                state->loc = state->org;
 711                result =
 712                    processCFI(state->cieStart, state->cieEnd, 0, ptrType,
 713                               state);
 714                if (targetLoc == 0 && state->label == NULL)
 715                        return result;
 716        }
 717        for (ptr.p8 = start; result && ptr.p8 < end;) {
 718                switch (*ptr.p8 >> 6) {
 719                        uleb128_t value;
 720
 721                case 0:
 722                        opcode = *ptr.p8++;
 723
 724                        switch (opcode) {
 725                        case DW_CFA_nop:
 726                                unw_debug("cfa nop ");
 727                                break;
 728                        case DW_CFA_set_loc:
 729                                state->loc = read_pointer(&ptr.p8, end,
 730                                                          ptrType);
 731                                if (state->loc == 0)
 732                                        result = 0;
 733                                unw_debug("cfa_set_loc: 0x%lx ", state->loc);
 734                                break;
 735                        case DW_CFA_advance_loc1:
 736                                unw_debug("\ncfa advance loc1:");
 737                                result = ptr.p8 < end
 738                                    && advance_loc(*ptr.p8++, state);
 739                                break;
 740                        case DW_CFA_advance_loc2:
 741                                value = *ptr.p8++;
 742                                value += *ptr.p8++ << 8;
 743                                unw_debug("\ncfa advance loc2:");
 744                                result = ptr.p8 <= end + 2
 745                                    /* && advance_loc(*ptr.p16++, state); */
 746                                    && advance_loc(value, state);
 747                                break;
 748                        case DW_CFA_advance_loc4:
 749                                unw_debug("\ncfa advance loc4:");
 750                                result = ptr.p8 <= end + 4
 751                                    && advance_loc(*ptr.p32++, state);
 752                                break;
 753                        case DW_CFA_offset_extended:
 754                                value = get_uleb128(&ptr.p8, end);
 755                                unw_debug("cfa_offset_extended: ");
 756                                set_rule(value, Memory,
 757                                         get_uleb128(&ptr.p8, end), state);
 758                                break;
 759                        case DW_CFA_val_offset:
 760                                value = get_uleb128(&ptr.p8, end);
 761                                set_rule(value, Value,
 762                                         get_uleb128(&ptr.p8, end), state);
 763                                break;
 764                        case DW_CFA_offset_extended_sf:
 765                                value = get_uleb128(&ptr.p8, end);
 766                                set_rule(value, Memory,
 767                                         get_sleb128(&ptr.p8, end), state);
 768                                break;
 769                        case DW_CFA_val_offset_sf:
 770                                value = get_uleb128(&ptr.p8, end);
 771                                set_rule(value, Value,
 772                                         get_sleb128(&ptr.p8, end), state);
 773                                break;
 774                        case DW_CFA_restore_extended:
 775                                unw_debug("cfa_restore_extended: ");
 776                        case DW_CFA_undefined:
 777                                unw_debug("cfa_undefined: ");
 778                        case DW_CFA_same_value:
 779                                unw_debug("cfa_same_value: ");
 780                                set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0,
 781                                         state);
 782                                break;
 783                        case DW_CFA_register:
 784                                unw_debug("cfa_register: ");
 785                                value = get_uleb128(&ptr.p8, end);
 786                                set_rule(value,
 787                                         Register,
 788                                         get_uleb128(&ptr.p8, end), state);
 789                                break;
 790                        case DW_CFA_remember_state:
 791                                unw_debug("cfa_remember_state: ");
 792                                if (ptr.p8 == state->label) {
 793                                        state->label = NULL;
 794                                        return 1;
 795                                }
 796                                if (state->stackDepth >= MAX_STACK_DEPTH)
 797                                        return 0;
 798                                state->stack[state->stackDepth++] = ptr.p8;
 799                                break;
 800                        case DW_CFA_restore_state:
 801                                unw_debug("cfa_restore_state: ");
 802                                if (state->stackDepth) {
 803                                        const uleb128_t loc = state->loc;
 804                                        const u8 *label = state->label;
 805
 806                                        state->label =
 807                                            state->stack[state->stackDepth - 1];
 808                                        memcpy(&state->cfa, &badCFA,
 809                                               sizeof(state->cfa));
 810                                        memset(state->regs, 0,
 811                                               sizeof(state->regs));
 812                                        state->stackDepth = 0;
 813                                        result =
 814                                            processCFI(start, end, 0, ptrType,
 815                                                       state);
 816                                        state->loc = loc;
 817                                        state->label = label;
 818                                } else
 819                                        return 0;
 820                                break;
 821                        case DW_CFA_def_cfa:
 822                                state->cfa.reg = get_uleb128(&ptr.p8, end);
 823                                unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
 824                                /*nobreak*/
 825                        case DW_CFA_def_cfa_offset:
 826                                state->cfa.offs = get_uleb128(&ptr.p8, end);
 827                                unw_debug("cfa_def_cfa_offset: 0x%lx ",
 828                                          state->cfa.offs);
 829                                break;
 830                        case DW_CFA_def_cfa_sf:
 831                                state->cfa.reg = get_uleb128(&ptr.p8, end);
 832                                /*nobreak */
 833                        case DW_CFA_def_cfa_offset_sf:
 834                                state->cfa.offs = get_sleb128(&ptr.p8, end)
 835                                    * state->dataAlign;
 836                                break;
 837                        case DW_CFA_def_cfa_register:
 838                                unw_debug("cfa_def_cfa_regsiter: ");
 839                                state->cfa.reg = get_uleb128(&ptr.p8, end);
 840                                break;
 841                                /*todo case DW_CFA_def_cfa_expression: */
 842                                /*todo case DW_CFA_expression: */
 843                                /*todo case DW_CFA_val_expression: */
 844                        case DW_CFA_GNU_args_size:
 845                                get_uleb128(&ptr.p8, end);
 846                                break;
 847                        case DW_CFA_GNU_negative_offset_extended:
 848                                value = get_uleb128(&ptr.p8, end);
 849                                set_rule(value,
 850                                         Memory,
 851                                         (uleb128_t) 0 - get_uleb128(&ptr.p8,
 852                                                                     end),
 853                                         state);
 854                                break;
 855                        case DW_CFA_GNU_window_save:
 856                        default:
 857                                unw_debug("UNKNOWN OPCODE 0x%x\n", opcode);
 858                                result = 0;
 859                                break;
 860                        }
 861                        break;
 862                case 1:
 863                        unw_debug("\ncfa_adv_loc: ");
 864                        result = advance_loc(*ptr.p8++ & 0x3f, state);
 865                        break;
 866                case 2:
 867                        unw_debug("cfa_offset: ");
 868                        value = *ptr.p8++ & 0x3f;
 869                        set_rule(value, Memory, get_uleb128(&ptr.p8, end),
 870                                 state);
 871                        break;
 872                case 3:
 873                        unw_debug("cfa_restore: ");
 874                        set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
 875                        break;
 876                }
 877
 878                if (ptr.p8 > end)
 879                        result = 0;
 880                if (result && targetLoc != 0 && targetLoc < state->loc)
 881                        return 1;
 882        }
 883
 884        return result && ptr.p8 == end && (targetLoc == 0 || (
 885                /*todo While in theory this should apply, gcc in practice omits
 886                  everything past the function prolog, and hence the location
 887                  never reaches the end of the function.
 888                targetLoc < state->loc && */  state->label == NULL));
 889}
 890
 891/* Unwind to previous to frame.  Returns 0 if successful, negative
 892 * number in case of an error. */
 893int arc_unwind(struct unwind_frame_info *frame)
 894{
 895#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
 896        const u32 *fde = NULL, *cie = NULL;
 897        const u8 *ptr = NULL, *end = NULL;
 898        unsigned long pc = UNW_PC(frame) - frame->call_frame;
 899        unsigned long startLoc = 0, endLoc = 0, cfa;
 900        unsigned i;
 901        signed ptrType = -1;
 902        uleb128_t retAddrReg = 0;
 903        const struct unwind_table *table;
 904        struct unwind_state state;
 905        unsigned long *fptr;
 906        unsigned long addr;
 907
 908        unw_debug("\n\nUNWIND FRAME:\n");
 909        unw_debug("PC: 0x%lx BLINK: 0x%lx, SP: 0x%lx, FP: 0x%x\n",
 910                  UNW_PC(frame), UNW_BLINK(frame), UNW_SP(frame),
 911                  UNW_FP(frame));
 912
 913        if (UNW_PC(frame) == 0)
 914                return -EINVAL;
 915
 916#ifdef UNWIND_DEBUG
 917        {
 918                unsigned long *sptr = (unsigned long *)UNW_SP(frame);
 919                unw_debug("\nStack Dump:\n");
 920                for (i = 0; i < 20; i++, sptr++)
 921                        unw_debug("0x%p:  0x%lx\n", sptr, *sptr);
 922                unw_debug("\n");
 923        }
 924#endif
 925
 926        table = find_table(pc);
 927        if (table != NULL
 928            && !(table->size & (sizeof(*fde) - 1))) {
 929                const u8 *hdr = table->header;
 930                unsigned long tableSize;
 931
 932                smp_rmb();
 933                if (hdr && hdr[0] == 1) {
 934                        switch (hdr[3] & DW_EH_PE_FORM) {
 935                        case DW_EH_PE_native:
 936                                tableSize = sizeof(unsigned long);
 937                                break;
 938                        case DW_EH_PE_data2:
 939                                tableSize = 2;
 940                                break;
 941                        case DW_EH_PE_data4:
 942                                tableSize = 4;
 943                                break;
 944                        case DW_EH_PE_data8:
 945                                tableSize = 8;
 946                                break;
 947                        default:
 948                                tableSize = 0;
 949                                break;
 950                        }
 951                        ptr = hdr + 4;
 952                        end = hdr + table->hdrsz;
 953                        if (tableSize && read_pointer(&ptr, end, hdr[1])
 954                            == (unsigned long)table->address
 955                            && (i = read_pointer(&ptr, end, hdr[2])) > 0
 956                            && i == (end - ptr) / (2 * tableSize)
 957                            && !((end - ptr) % (2 * tableSize))) {
 958                                do {
 959                                        const u8 *cur =
 960                                            ptr + (i / 2) * (2 * tableSize);
 961
 962                                        startLoc = read_pointer(&cur,
 963                                                                cur + tableSize,
 964                                                                hdr[3]);
 965                                        if (pc < startLoc)
 966                                                i /= 2;
 967                                        else {
 968                                                ptr = cur - tableSize;
 969                                                i = (i + 1) / 2;
 970                                        }
 971                                } while (startLoc && i > 1);
 972                                if (i == 1
 973                                    && (startLoc = read_pointer(&ptr,
 974                                                                ptr + tableSize,
 975                                                                hdr[3])) != 0
 976                                    && pc >= startLoc)
 977                                        fde = (void *)read_pointer(&ptr,
 978                                                                   ptr +
 979                                                                   tableSize,
 980                                                                   hdr[3]);
 981                        }
 982                }
 983
 984                if (fde != NULL) {
 985                        cie = cie_for_fde(fde, table);
 986                        ptr = (const u8 *)(fde + 2);
 987                        if (cie != NULL
 988                            && cie != &bad_cie
 989                            && cie != &not_fde
 990                            && (ptrType = fde_pointer_type(cie)) >= 0
 991                            && read_pointer(&ptr,
 992                                            (const u8 *)(fde + 1) + *fde,
 993                                            ptrType) == startLoc) {
 994                                if (!(ptrType & DW_EH_PE_indirect))
 995                                        ptrType &=
 996                                            DW_EH_PE_FORM | DW_EH_PE_signed;
 997                                endLoc =
 998                                    startLoc + read_pointer(&ptr,
 999                                                            (const u8 *)(fde +
1000                                                                         1) +
1001                                                            *fde, ptrType);
1002                                if (pc >= endLoc) {
1003                                        fde = NULL;
1004                                        cie = NULL;
1005                                }
1006                        } else {
1007                                fde = NULL;
1008                                cie = NULL;
1009                        }
1010                }
1011        }
1012        if (cie != NULL) {
1013                memset(&state, 0, sizeof(state));
1014                state.cieEnd = ptr;     /* keep here temporarily */
1015                ptr = (const u8 *)(cie + 2);
1016                end = (const u8 *)(cie + 1) + *cie;
1017                frame->call_frame = 1;
1018                if (*++ptr) {
1019                        /* check if augmentation size is first (thus present) */
1020                        if (*ptr == 'z') {
1021                                while (++ptr < end && *ptr) {
1022                                        switch (*ptr) {
1023                                        /* chk for ignorable or already handled
1024                                         * nul-terminated augmentation string */
1025                                        case 'L':
1026                                        case 'P':
1027                                        case 'R':
1028                                                continue;
1029                                        case 'S':
1030                                                frame->call_frame = 0;
1031                                                continue;
1032                                        default:
1033                                                break;
1034                                        }
1035                                        break;
1036                                }
1037                        }
1038                        if (ptr >= end || *ptr)
1039                                cie = NULL;
1040                }
1041                ++ptr;
1042        }
1043        if (cie != NULL) {
1044                /* get code aligment factor */
1045                state.codeAlign = get_uleb128(&ptr, end);
1046                /* get data aligment factor */
1047                state.dataAlign = get_sleb128(&ptr, end);
1048                if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
1049                        cie = NULL;
1050                else {
1051                        retAddrReg =
1052                            state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
1053                                                                      end);
1054                        unw_debug("CIE Frame Info:\n");
1055                        unw_debug("return Address register 0x%lx\n",
1056                                  retAddrReg);
1057                        unw_debug("data Align: %ld\n", state.dataAlign);
1058                        unw_debug("code Align: %lu\n", state.codeAlign);
1059                        /* skip augmentation */
1060                        if (((const char *)(cie + 2))[1] == 'z') {
1061                                uleb128_t augSize = get_uleb128(&ptr, end);
1062
1063                                ptr += augSize;
1064                        }
1065                        if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
1066                            || REG_INVALID(retAddrReg)
1067                            || reg_info[retAddrReg].width !=
1068                            sizeof(unsigned long))
1069                                cie = NULL;
1070                }
1071        }
1072        if (cie != NULL) {
1073                state.cieStart = ptr;
1074                ptr = state.cieEnd;
1075                state.cieEnd = end;
1076                end = (const u8 *)(fde + 1) + *fde;
1077                /* skip augmentation */
1078                if (((const char *)(cie + 2))[1] == 'z') {
1079                        uleb128_t augSize = get_uleb128(&ptr, end);
1080
1081                        if ((ptr += augSize) > end)
1082                                fde = NULL;
1083                }
1084        }
1085        if (cie == NULL || fde == NULL) {
1086#ifdef CONFIG_FRAME_POINTER
1087                unsigned long top, bottom;
1088
1089                top = STACK_TOP_UNW(frame->task);
1090                bottom = STACK_BOTTOM_UNW(frame->task);
1091#if FRAME_RETADDR_OFFSET < 0
1092                if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
1093                    && bottom < UNW_FP(frame)
1094#else
1095                if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
1096                    && bottom > UNW_FP(frame)
1097#endif
1098                    && !((UNW_SP(frame) | UNW_FP(frame))
1099                         & (sizeof(unsigned long) - 1))) {
1100                        unsigned long link;
1101
1102                        if (!__get_user(link, (unsigned long *)
1103                                        (UNW_FP(frame) + FRAME_LINK_OFFSET))
1104#if FRAME_RETADDR_OFFSET < 0
1105                            && link > bottom && link < UNW_FP(frame)
1106#else
1107                            && link > UNW_FP(frame) && link < bottom
1108#endif
1109                            && !(link & (sizeof(link) - 1))
1110                            && !__get_user(UNW_PC(frame),
1111                                           (unsigned long *)(UNW_FP(frame)
1112                                                + FRAME_RETADDR_OFFSET)))
1113                        {
1114                                UNW_SP(frame) =
1115                                    UNW_FP(frame) + FRAME_RETADDR_OFFSET
1116#if FRAME_RETADDR_OFFSET < 0
1117                                    -
1118#else
1119                                    +
1120#endif
1121                                    sizeof(UNW_PC(frame));
1122                                UNW_FP(frame) = link;
1123                                return 0;
1124                        }
1125                }
1126#endif
1127                return -ENXIO;
1128        }
1129        state.org = startLoc;
1130        memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
1131
1132        unw_debug("\nProcess instructions\n");
1133
1134        /* process instructions
1135         * For ARC, we optimize by having blink(retAddrReg) with
1136         * the sameValue in the leaf function, so we should not check
1137         * state.regs[retAddrReg].where == Nowhere
1138         */
1139        if (!processCFI(ptr, end, pc, ptrType, &state)
1140            || state.loc > endLoc
1141/*         || state.regs[retAddrReg].where == Nowhere */
1142            || state.cfa.reg >= ARRAY_SIZE(reg_info)
1143            || reg_info[state.cfa.reg].width != sizeof(unsigned long)
1144            || state.cfa.offs % sizeof(unsigned long))
1145                return -EIO;
1146
1147#ifdef UNWIND_DEBUG
1148        unw_debug("\n");
1149
1150        unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
1151        for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1152
1153                if (REG_INVALID(i))
1154                        continue;
1155
1156                switch (state.regs[i].where) {
1157                case Nowhere:
1158                        break;
1159                case Memory:
1160                        unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
1161                        break;
1162                case Register:
1163                        unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
1164                        break;
1165                case Value:
1166                        unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
1167                        break;
1168                }
1169        }
1170
1171        unw_debug("\n");
1172#endif
1173
1174        /* update frame */
1175#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
1176        if (frame->call_frame
1177            && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
1178                frame->call_frame = 0;
1179#endif
1180        cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
1181        startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
1182        endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
1183        if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
1184                startLoc = min(STACK_LIMIT(cfa), cfa);
1185                endLoc = max(STACK_LIMIT(cfa), cfa);
1186        }
1187
1188        unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx =>  0x%lx\n",
1189                  state.cfa.reg, state.cfa.offs, cfa);
1190
1191        for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
1192                if (REG_INVALID(i)) {
1193                        if (state.regs[i].where == Nowhere)
1194                                continue;
1195                        return -EIO;
1196                }
1197                switch (state.regs[i].where) {
1198                default:
1199                        break;
1200                case Register:
1201                        if (state.regs[i].value >= ARRAY_SIZE(reg_info)
1202                            || REG_INVALID(state.regs[i].value)
1203                            || reg_info[i].width >
1204                            reg_info[state.regs[i].value].width)
1205                                return -EIO;
1206                        switch (reg_info[state.regs[i].value].width) {
1207                        case sizeof(u8):
1208                                state.regs[i].value =
1209                                FRAME_REG(state.regs[i].value, const u8);
1210                                break;
1211                        case sizeof(u16):
1212                                state.regs[i].value =
1213                                FRAME_REG(state.regs[i].value, const u16);
1214                                break;
1215                        case sizeof(u32):
1216                                state.regs[i].value =
1217                                FRAME_REG(state.regs[i].value, const u32);
1218                                break;
1219#ifdef CONFIG_64BIT
1220                        case sizeof(u64):
1221                                state.regs[i].value =
1222                                FRAME_REG(state.regs[i].value, const u64);
1223                                break;
1224#endif
1225                        default:
1226                                return -EIO;
1227                        }
1228                        break;
1229                }
1230        }
1231
1232        unw_debug("\nRegister state after evaluation with realtime Stack:\n");
1233        fptr = (unsigned long *)(&frame->regs);
1234        for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
1235
1236                if (REG_INVALID(i))
1237                        continue;
1238                switch (state.regs[i].where) {
1239                case Nowhere:
1240                        if (reg_info[i].width != sizeof(UNW_SP(frame))
1241                            || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
1242                            != &UNW_SP(frame))
1243                                continue;
1244                        UNW_SP(frame) = cfa;
1245                        break;
1246                case Register:
1247                        switch (reg_info[i].width) {
1248                        case sizeof(u8):
1249                                FRAME_REG(i, u8) = state.regs[i].value;
1250                                break;
1251                        case sizeof(u16):
1252                                FRAME_REG(i, u16) = state.regs[i].value;
1253                                break;
1254                        case sizeof(u32):
1255                                FRAME_REG(i, u32) = state.regs[i].value;
1256                                break;
1257#ifdef CONFIG_64BIT
1258                        case sizeof(u64):
1259                                FRAME_REG(i, u64) = state.regs[i].value;
1260                                break;
1261#endif
1262                        default:
1263                                return -EIO;
1264                        }
1265                        break;
1266                case Value:
1267                        if (reg_info[i].width != sizeof(unsigned long))
1268                                return -EIO;
1269                        FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
1270                            * state.dataAlign;
1271                        break;
1272                case Memory:
1273                        addr = cfa + state.regs[i].value * state.dataAlign;
1274
1275                        if ((state.regs[i].value * state.dataAlign)
1276                            % sizeof(unsigned long)
1277                            || addr < startLoc
1278                            || addr + sizeof(unsigned long) < addr
1279                            || addr + sizeof(unsigned long) > endLoc)
1280                                        return -EIO;
1281
1282                        switch (reg_info[i].width) {
1283                        case sizeof(u8):
1284                                __get_user(FRAME_REG(i, u8),
1285                                           (u8 __user *)addr);
1286                                break;
1287                        case sizeof(u16):
1288                                __get_user(FRAME_REG(i, u16),
1289                                           (u16 __user *)addr);
1290                                break;
1291                        case sizeof(u32):
1292                                __get_user(FRAME_REG(i, u32),
1293                                           (u32 __user *)addr);
1294                                break;
1295#ifdef CONFIG_64BIT
1296                        case sizeof(u64):
1297                                __get_user(FRAME_REG(i, u64),
1298                                           (u64 __user *)addr);
1299                                break;
1300#endif
1301                        default:
1302                                return -EIO;
1303                        }
1304
1305                        break;
1306                }
1307                unw_debug("r%d: 0x%lx ", i, *fptr);
1308        }
1309
1310        return 0;
1311#undef FRAME_REG
1312}
1313EXPORT_SYMBOL(arc_unwind);
1314