linux/arch/arm/kernel/unwind.c
<<
>>
Prefs
   1/*
   2 * arch/arm/kernel/unwind.c
   3 *
   4 * Copyright (C) 2008 ARM Limited
   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 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18 *
  19 *
  20 * Stack unwinding support for ARM
  21 *
  22 * An ARM EABI version of gcc is required to generate the unwind
  23 * tables. For information about the structure of the unwind tables,
  24 * see "Exception Handling ABI for the ARM Architecture" at:
  25 *
  26 * http://infocenter.arm.com/help/topic/com.arm.doc.subset.swdev.abi/index.html
  27 */
  28
  29#include <linux/kernel.h>
  30#include <linux/init.h>
  31#include <linux/module.h>
  32#include <linux/sched.h>
  33#include <linux/slab.h>
  34#include <linux/spinlock.h>
  35#include <linux/list.h>
  36
  37#include <asm/stacktrace.h>
  38#include <asm/traps.h>
  39#include <asm/unwind.h>
  40
  41/* Dummy functions to avoid linker complaints */
  42void __aeabi_unwind_cpp_pr0(void)
  43{
  44};
  45EXPORT_SYMBOL(__aeabi_unwind_cpp_pr0);
  46
  47void __aeabi_unwind_cpp_pr1(void)
  48{
  49};
  50EXPORT_SYMBOL(__aeabi_unwind_cpp_pr1);
  51
  52void __aeabi_unwind_cpp_pr2(void)
  53{
  54};
  55EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2);
  56
  57struct unwind_ctrl_block {
  58        unsigned long vrs[16];          /* virtual register set */
  59        unsigned long *insn;            /* pointer to the current instructions word */
  60        int entries;                    /* number of entries left to interpret */
  61        int byte;                       /* current byte number in the instructions word */
  62};
  63
  64enum regs {
  65        FP = 11,
  66        SP = 13,
  67        LR = 14,
  68        PC = 15
  69};
  70
  71extern struct unwind_idx __start_unwind_idx[];
  72extern struct unwind_idx __stop_unwind_idx[];
  73
  74static DEFINE_SPINLOCK(unwind_lock);
  75static LIST_HEAD(unwind_tables);
  76
  77/* Convert a prel31 symbol to an absolute address */
  78#define prel31_to_addr(ptr)                             \
  79({                                                      \
  80        /* sign-extend to 32 bits */                    \
  81        long offset = (((long)*(ptr)) << 1) >> 1;       \
  82        (unsigned long)(ptr) + offset;                  \
  83})
  84
  85/*
  86 * Binary search in the unwind index. The entries entries are
  87 * guaranteed to be sorted in ascending order by the linker.
  88 */
  89static struct unwind_idx *search_index(unsigned long addr,
  90                                       struct unwind_idx *first,
  91                                       struct unwind_idx *last)
  92{
  93        pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last);
  94
  95        if (addr < first->addr) {
  96                pr_warning("unwind: Unknown symbol address %08lx\n", addr);
  97                return NULL;
  98        } else if (addr >= last->addr)
  99                return last;
 100
 101        while (first < last - 1) {
 102                struct unwind_idx *mid = first + ((last - first + 1) >> 1);
 103
 104                if (addr < mid->addr)
 105                        last = mid;
 106                else
 107                        first = mid;
 108        }
 109
 110        return first;
 111}
 112
 113static struct unwind_idx *unwind_find_idx(unsigned long addr)
 114{
 115        struct unwind_idx *idx = NULL;
 116        unsigned long flags;
 117
 118        pr_debug("%s(%08lx)\n", __func__, addr);
 119
 120        if (core_kernel_text(addr))
 121                /* main unwind table */
 122                idx = search_index(addr, __start_unwind_idx,
 123                                   __stop_unwind_idx - 1);
 124        else {
 125                /* module unwind tables */
 126                struct unwind_table *table;
 127
 128                spin_lock_irqsave(&unwind_lock, flags);
 129                list_for_each_entry(table, &unwind_tables, list) {
 130                        if (addr >= table->begin_addr &&
 131                            addr < table->end_addr) {
 132                                idx = search_index(addr, table->start,
 133                                                   table->stop - 1);
 134                                break;
 135                        }
 136                }
 137                spin_unlock_irqrestore(&unwind_lock, flags);
 138        }
 139
 140        pr_debug("%s: idx = %p\n", __func__, idx);
 141        return idx;
 142}
 143
 144static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl)
 145{
 146        unsigned long ret;
 147
 148        if (ctrl->entries <= 0) {
 149                pr_warning("unwind: Corrupt unwind table\n");
 150                return 0;
 151        }
 152
 153        ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff;
 154
 155        if (ctrl->byte == 0) {
 156                ctrl->insn++;
 157                ctrl->entries--;
 158                ctrl->byte = 3;
 159        } else
 160                ctrl->byte--;
 161
 162        return ret;
 163}
 164
 165/*
 166 * Execute the current unwind instruction.
 167 */
 168static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
 169{
 170        unsigned long insn = unwind_get_byte(ctrl);
 171
 172        pr_debug("%s: insn = %08lx\n", __func__, insn);
 173
 174        if ((insn & 0xc0) == 0x00)
 175                ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4;
 176        else if ((insn & 0xc0) == 0x40)
 177                ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4;
 178        else if ((insn & 0xf0) == 0x80) {
 179                unsigned long mask;
 180                unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
 181                int load_sp, reg = 4;
 182
 183                insn = (insn << 8) | unwind_get_byte(ctrl);
 184                mask = insn & 0x0fff;
 185                if (mask == 0) {
 186                        pr_warning("unwind: 'Refuse to unwind' instruction %04lx\n",
 187                                   insn);
 188                        return -URC_FAILURE;
 189                }
 190
 191                /* pop R4-R15 according to mask */
 192                load_sp = mask & (1 << (13 - 4));
 193                while (mask) {
 194                        if (mask & 1)
 195                                ctrl->vrs[reg] = *vsp++;
 196                        mask >>= 1;
 197                        reg++;
 198                }
 199                if (!load_sp)
 200                        ctrl->vrs[SP] = (unsigned long)vsp;
 201        } else if ((insn & 0xf0) == 0x90 &&
 202                   (insn & 0x0d) != 0x0d)
 203                ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f];
 204        else if ((insn & 0xf0) == 0xa0) {
 205                unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
 206                int reg;
 207
 208                /* pop R4-R[4+bbb] */
 209                for (reg = 4; reg <= 4 + (insn & 7); reg++)
 210                        ctrl->vrs[reg] = *vsp++;
 211                if (insn & 0x80)
 212                        ctrl->vrs[14] = *vsp++;
 213                ctrl->vrs[SP] = (unsigned long)vsp;
 214        } else if (insn == 0xb0) {
 215                ctrl->vrs[PC] = ctrl->vrs[LR];
 216                /* no further processing */
 217                ctrl->entries = 0;
 218        } else if (insn == 0xb1) {
 219                unsigned long mask = unwind_get_byte(ctrl);
 220                unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
 221                int reg = 0;
 222
 223                if (mask == 0 || mask & 0xf0) {
 224                        pr_warning("unwind: Spare encoding %04lx\n",
 225                               (insn << 8) | mask);
 226                        return -URC_FAILURE;
 227                }
 228
 229                /* pop R0-R3 according to mask */
 230                while (mask) {
 231                        if (mask & 1)
 232                                ctrl->vrs[reg] = *vsp++;
 233                        mask >>= 1;
 234                        reg++;
 235                }
 236                ctrl->vrs[SP] = (unsigned long)vsp;
 237        } else if (insn == 0xb2) {
 238                unsigned long uleb128 = unwind_get_byte(ctrl);
 239
 240                ctrl->vrs[SP] += 0x204 + (uleb128 << 2);
 241        } else {
 242                pr_warning("unwind: Unhandled instruction %02lx\n", insn);
 243                return -URC_FAILURE;
 244        }
 245
 246        pr_debug("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx\n", __func__,
 247                 ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]);
 248
 249        return URC_OK;
 250}
 251
 252/*
 253 * Unwind a single frame starting with *sp for the symbol at *pc. It
 254 * updates the *pc and *sp with the new values.
 255 */
 256int unwind_frame(struct stackframe *frame)
 257{
 258        unsigned long high, low;
 259        struct unwind_idx *idx;
 260        struct unwind_ctrl_block ctrl;
 261
 262        /* only go to a higher address on the stack */
 263        low = frame->sp;
 264        high = ALIGN(low, THREAD_SIZE) + THREAD_SIZE;
 265
 266        pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__,
 267                 frame->pc, frame->lr, frame->sp);
 268
 269        if (!kernel_text_address(frame->pc))
 270                return -URC_FAILURE;
 271
 272        idx = unwind_find_idx(frame->pc);
 273        if (!idx) {
 274                pr_warning("unwind: Index not found %08lx\n", frame->pc);
 275                return -URC_FAILURE;
 276        }
 277
 278        ctrl.vrs[FP] = frame->fp;
 279        ctrl.vrs[SP] = frame->sp;
 280        ctrl.vrs[LR] = frame->lr;
 281        ctrl.vrs[PC] = 0;
 282
 283        if (idx->insn == 1)
 284                /* can't unwind */
 285                return -URC_FAILURE;
 286        else if ((idx->insn & 0x80000000) == 0)
 287                /* prel31 to the unwind table */
 288                ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn);
 289        else if ((idx->insn & 0xff000000) == 0x80000000)
 290                /* only personality routine 0 supported in the index */
 291                ctrl.insn = &idx->insn;
 292        else {
 293                pr_warning("unwind: Unsupported personality routine %08lx in the index at %p\n",
 294                           idx->insn, idx);
 295                return -URC_FAILURE;
 296        }
 297
 298        /* check the personality routine */
 299        if ((*ctrl.insn & 0xff000000) == 0x80000000) {
 300                ctrl.byte = 2;
 301                ctrl.entries = 1;
 302        } else if ((*ctrl.insn & 0xff000000) == 0x81000000) {
 303                ctrl.byte = 1;
 304                ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16);
 305        } else {
 306                pr_warning("unwind: Unsupported personality routine %08lx at %p\n",
 307                           *ctrl.insn, ctrl.insn);
 308                return -URC_FAILURE;
 309        }
 310
 311        while (ctrl.entries > 0) {
 312                int urc;
 313
 314                if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
 315                        return -URC_FAILURE;
 316                urc = unwind_exec_insn(&ctrl);
 317                if (urc < 0)
 318                        return urc;
 319        }
 320
 321        if (ctrl.vrs[PC] == 0)
 322                ctrl.vrs[PC] = ctrl.vrs[LR];
 323
 324        frame->fp = ctrl.vrs[FP];
 325        frame->sp = ctrl.vrs[SP];
 326        frame->lr = ctrl.vrs[LR];
 327        frame->pc = ctrl.vrs[PC];
 328
 329        return URC_OK;
 330}
 331
 332void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 333{
 334        struct stackframe frame;
 335        unsigned long high, low;
 336        register unsigned long current_sp asm ("sp");
 337
 338        pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
 339
 340        if (!tsk)
 341                tsk = current;
 342
 343        if (regs) {
 344                frame.fp = regs->ARM_fp;
 345                frame.sp = regs->ARM_sp;
 346                frame.lr = regs->ARM_lr;
 347                frame.pc = regs->ARM_pc;
 348        } else if (tsk == current) {
 349                frame.fp = (unsigned long)__builtin_frame_address(0);
 350                frame.sp = current_sp;
 351                frame.lr = (unsigned long)__builtin_return_address(0);
 352                frame.pc = (unsigned long)unwind_backtrace;
 353        } else {
 354                /* task blocked in __switch_to */
 355                frame.fp = thread_saved_fp(tsk);
 356                frame.sp = thread_saved_sp(tsk);
 357                /*
 358                 * The function calling __switch_to cannot be a leaf function
 359                 * so LR is recovered from the stack.
 360                 */
 361                frame.lr = 0;
 362                frame.pc = thread_saved_pc(tsk);
 363        }
 364
 365        low = frame.sp & ~(THREAD_SIZE - 1);
 366        high = low + THREAD_SIZE;
 367
 368        while (1) {
 369                int urc;
 370                unsigned long where = frame.pc;
 371
 372                urc = unwind_frame(&frame);
 373                if (urc < 0)
 374                        break;
 375                dump_backtrace_entry(where, frame.pc, frame.sp - 4);
 376        }
 377}
 378
 379struct unwind_table *unwind_table_add(unsigned long start, unsigned long size,
 380                                      unsigned long text_addr,
 381                                      unsigned long text_size)
 382{
 383        unsigned long flags;
 384        struct unwind_idx *idx;
 385        struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL);
 386
 387        pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size,
 388                 text_addr, text_size);
 389
 390        if (!tab)
 391                return tab;
 392
 393        tab->start = (struct unwind_idx *)start;
 394        tab->stop = (struct unwind_idx *)(start + size);
 395        tab->begin_addr = text_addr;
 396        tab->end_addr = text_addr + text_size;
 397
 398        /* Convert the symbol addresses to absolute values */
 399        for (idx = tab->start; idx < tab->stop; idx++)
 400                idx->addr = prel31_to_addr(&idx->addr);
 401
 402        spin_lock_irqsave(&unwind_lock, flags);
 403        list_add_tail(&tab->list, &unwind_tables);
 404        spin_unlock_irqrestore(&unwind_lock, flags);
 405
 406        return tab;
 407}
 408
 409void unwind_table_del(struct unwind_table *tab)
 410{
 411        unsigned long flags;
 412
 413        if (!tab)
 414                return;
 415
 416        spin_lock_irqsave(&unwind_lock, flags);
 417        list_del(&tab->list);
 418        spin_unlock_irqrestore(&unwind_lock, flags);
 419
 420        kfree(tab);
 421}
 422
 423int __init unwind_init(void)
 424{
 425        struct unwind_idx *idx;
 426
 427        /* Convert the symbol addresses to absolute values */
 428        for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++)
 429                idx->addr = prel31_to_addr(&idx->addr);
 430
 431        pr_debug("unwind: ARM stack unwinding initialised\n");
 432
 433        return 0;
 434}
 435
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.