LCOV - code coverage report
Current view: top level - arch/arm/kernel - unwind.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 112 172 65.1 %
Date: 2014-04-16 Functions: 6 11 54.5 %
Branches: 68 108 63.0 %

           Branch data     Line data    Source code
       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                 :            : #ifndef __CHECKER__
      30                 :            : #if !defined (__ARM_EABI__)
      31                 :            : #warning Your compiler does not have EABI support.
      32                 :            : #warning    ARM unwind is known to compile only with EABI compilers.
      33                 :            : #warning    Change compiler or disable ARM_UNWIND option.
      34                 :            : #elif (__GNUC__ == 4 && __GNUC_MINOR__ <= 2) && !defined(__clang__)
      35                 :            : #warning Your compiler is too buggy; it is known to not compile ARM unwind support.
      36                 :            : #warning    Change compiler or disable ARM_UNWIND option.
      37                 :            : #endif
      38                 :            : #endif /* __CHECKER__ */
      39                 :            : 
      40                 :            : #include <linux/kernel.h>
      41                 :            : #include <linux/init.h>
      42                 :            : #include <linux/export.h>
      43                 :            : #include <linux/sched.h>
      44                 :            : #include <linux/slab.h>
      45                 :            : #include <linux/spinlock.h>
      46                 :            : #include <linux/list.h>
      47                 :            : 
      48                 :            : #include <asm/stacktrace.h>
      49                 :            : #include <asm/traps.h>
      50                 :            : #include <asm/unwind.h>
      51                 :            : 
      52                 :            : /* Dummy functions to avoid linker complaints */
      53                 :          0 : void __aeabi_unwind_cpp_pr0(void)
      54                 :            : {
      55                 :          0 : };
      56                 :            : EXPORT_SYMBOL(__aeabi_unwind_cpp_pr0);
      57                 :            : 
      58                 :          0 : void __aeabi_unwind_cpp_pr1(void)
      59                 :            : {
      60                 :          0 : };
      61                 :            : EXPORT_SYMBOL(__aeabi_unwind_cpp_pr1);
      62                 :            : 
      63                 :          0 : void __aeabi_unwind_cpp_pr2(void)
      64                 :            : {
      65                 :          0 : };
      66                 :            : EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2);
      67                 :            : 
      68                 :            : struct unwind_ctrl_block {
      69                 :            :         unsigned long vrs[16];          /* virtual register set */
      70                 :            :         const unsigned long *insn;      /* pointer to the current instructions word */
      71                 :            :         int entries;                    /* number of entries left to interpret */
      72                 :            :         int byte;                       /* current byte number in the instructions word */
      73                 :            : };
      74                 :            : 
      75                 :            : enum regs {
      76                 :            : #ifdef CONFIG_THUMB2_KERNEL
      77                 :            :         FP = 7,
      78                 :            : #else
      79                 :            :         FP = 11,
      80                 :            : #endif
      81                 :            :         SP = 13,
      82                 :            :         LR = 14,
      83                 :            :         PC = 15
      84                 :            : };
      85                 :            : 
      86                 :            : extern const struct unwind_idx __start_unwind_idx[];
      87                 :            : static const struct unwind_idx *__origin_unwind_idx;
      88                 :            : extern const struct unwind_idx __stop_unwind_idx[];
      89                 :            : 
      90                 :            : static DEFINE_SPINLOCK(unwind_lock);
      91                 :            : static LIST_HEAD(unwind_tables);
      92                 :            : 
      93                 :            : /* Convert a prel31 symbol to an absolute address */
      94                 :            : #define prel31_to_addr(ptr)                             \
      95                 :            : ({                                                      \
      96                 :            :         /* sign-extend to 32 bits */                    \
      97                 :            :         long offset = (((long)*(ptr)) << 1) >> 1;   \
      98                 :            :         (unsigned long)(ptr) + offset;                  \
      99                 :            : })
     100                 :            : 
     101                 :            : /*
     102                 :            :  * Binary search in the unwind index. The entries are
     103                 :            :  * guaranteed to be sorted in ascending order by the linker.
     104                 :            :  *
     105                 :            :  * start = first entry
     106                 :            :  * origin = first entry with positive offset (or stop if there is no such entry)
     107                 :            :  * stop - 1 = last entry
     108                 :            :  */
     109                 :          0 : static const struct unwind_idx *search_index(unsigned long addr,
     110                 :            :                                        const struct unwind_idx *start,
     111                 :            :                                        const struct unwind_idx *origin,
     112                 :            :                                        const struct unwind_idx *stop)
     113                 :            : {
     114                 :            :         unsigned long addr_prel31;
     115                 :            : 
     116                 :            :         pr_debug("%s(%08lx, %p, %p, %p)\n",
     117                 :            :                         __func__, addr, start, origin, stop);
     118                 :            : 
     119                 :            :         /*
     120                 :            :          * only search in the section with the matching sign. This way the
     121                 :            :          * prel31 numbers can be compared as unsigned longs.
     122                 :            :          */
     123         [ -  + ]:      23472 :         if (addr < (unsigned long)start)
     124                 :            :                 /* negative offsets: [start; origin) */
     125                 :            :                 stop = origin;
     126                 :            :         else
     127                 :            :                 /* positive offsets: [origin; stop) */
     128                 :            :                 start = origin;
     129                 :            : 
     130                 :            :         /* prel31 for address relavive to start */
     131                 :      23472 :         addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff;
     132                 :            : 
     133         [ +  + ]:     352116 :         while (start < stop - 1) {
     134                 :     328644 :                 const struct unwind_idx *mid = start + ((stop - start) >> 1);
     135                 :            : 
     136                 :            :                 /*
     137                 :            :                  * As addr_prel31 is relative to start an offset is needed to
     138                 :            :                  * make it relative to mid.
     139                 :            :                  */
     140         [ +  + ]:     328644 :                 if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) <
     141                 :     328644 :                                 mid->addr_offset)
     142                 :            :                         stop = mid;
     143                 :            :                 else {
     144                 :            :                         /* keep addr_prel31 relative to start */
     145                 :            :                         addr_prel31 -= ((unsigned long)mid -
     146                 :            :                                         (unsigned long)start);
     147                 :            :                         start = mid;
     148                 :            :                 }
     149                 :            :         }
     150                 :            : 
     151         [ -  + ]:      23472 :         if (likely(start->addr_offset <= addr_prel31))
     152                 :            :                 return start;
     153                 :            :         else {
     154                 :          0 :                 pr_warning("unwind: Unknown symbol address %08lx\n", addr);
     155                 :          0 :                 return NULL;
     156                 :            :         }
     157                 :            : }
     158                 :            : 
     159                 :            : static const struct unwind_idx *unwind_find_origin(
     160                 :            :                 const struct unwind_idx *start, const struct unwind_idx *stop)
     161                 :            : {
     162                 :            :         pr_debug("%s(%p, %p)\n", __func__, start, stop);
     163 [ #  # ][ +  + ]:         16 :         while (start < stop) {
     164                 :         15 :                 const struct unwind_idx *mid = start + ((stop - start) >> 1);
     165                 :            : 
     166 [ #  # ][ +  + ]:         15 :                 if (mid->addr_offset >= 0x40000000)
     167                 :            :                         /* negative offset */
     168                 :          9 :                         start = mid + 1;
     169                 :            :                 else
     170                 :            :                         /* positive offset */
     171                 :            :                         stop = mid;
     172                 :            :         }
     173                 :            :         pr_debug("%s -> %p\n", __func__, stop);
     174                 :            :         return stop;
     175                 :            : }
     176                 :            : 
     177                 :          0 : static const struct unwind_idx *unwind_find_idx(unsigned long addr)
     178                 :            : {
     179                 :            :         const struct unwind_idx *idx = NULL;
     180                 :            :         unsigned long flags;
     181                 :            : 
     182                 :            :         pr_debug("%s(%08lx)\n", __func__, addr);
     183                 :            : 
     184         [ +  - ]:      23472 :         if (core_kernel_text(addr)) {
     185            [ + ]:      23472 :                 if (unlikely(!__origin_unwind_idx))
     186                 :          1 :                         __origin_unwind_idx =
     187                 :            :                                 unwind_find_origin(__start_unwind_idx,
     188                 :            :                                                 __stop_unwind_idx);
     189                 :            : 
     190                 :            :                 /* main unwind table */
     191                 :          0 :                 idx = search_index(addr, __start_unwind_idx,
     192                 :            :                                    __origin_unwind_idx,
     193                 :            :                                    __stop_unwind_idx);
     194                 :            :         } else {
     195                 :            :                 /* module unwind tables */
     196                 :            :                 struct unwind_table *table;
     197                 :            : 
     198                 :          0 :                 spin_lock_irqsave(&unwind_lock, flags);
     199         [ #  # ]:          0 :                 list_for_each_entry(table, &unwind_tables, list) {
     200 [ #  # ][ #  # ]:          0 :                         if (addr >= table->begin_addr &&
     201                 :          0 :                             addr < table->end_addr) {
     202                 :          0 :                                 idx = search_index(addr, table->start,
     203                 :            :                                                    table->origin,
     204                 :            :                                                    table->stop);
     205                 :            :                                 /* Move-to-front to exploit common traces */
     206                 :            :                                 list_move(&table->list, &unwind_tables);
     207                 :            :                                 break;
     208                 :            :                         }
     209                 :            :                 }
     210                 :            :                 spin_unlock_irqrestore(&unwind_lock, flags);
     211                 :            :         }
     212                 :            : 
     213                 :            :         pr_debug("%s: idx = %p\n", __func__, idx);
     214                 :      23472 :         return idx;
     215                 :            : }
     216                 :            : 
     217                 :          0 : static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl)
     218                 :            : {
     219                 :            :         unsigned long ret;
     220                 :            : 
     221         [ -  + ]:      23581 :         if (ctrl->entries <= 0) {
     222                 :          0 :                 pr_warning("unwind: Corrupt unwind table\n");
     223                 :          0 :                 return 0;
     224                 :            :         }
     225                 :            : 
     226                 :      23581 :         ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff;
     227                 :            : 
     228         [ +  + ]:      23581 :         if (ctrl->byte == 0) {
     229                 :         53 :                 ctrl->insn++;
     230                 :         53 :                 ctrl->entries--;
     231                 :         53 :                 ctrl->byte = 3;
     232                 :            :         } else
     233                 :      23528 :                 ctrl->byte--;
     234                 :            : 
     235                 :      23581 :         return ret;
     236                 :            : }
     237                 :            : 
     238                 :            : /*
     239                 :            :  * Execute the current unwind instruction.
     240                 :            :  */
     241                 :          0 : static int unwind_exec_insn(struct unwind_ctrl_block *ctrl)
     242                 :            : {
     243                 :      23565 :         unsigned long insn = unwind_get_byte(ctrl);
     244                 :            : 
     245                 :            :         pr_debug("%s: insn = %08lx\n", __func__, insn);
     246                 :            : 
     247         [ +  + ]:      47130 :         if ((insn & 0xc0) == 0x00)
     248                 :         42 :                 ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4;
     249         [ -  + ]:      47088 :         else if ((insn & 0xc0) == 0x40)
     250                 :          0 :                 ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4;
     251         [ +  + ]:      47088 :         else if ((insn & 0xf0) == 0x80) {
     252                 :            :                 unsigned long mask;
     253                 :          5 :                 unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
     254                 :            :                 int load_sp, reg = 4;
     255                 :            : 
     256                 :          5 :                 insn = (insn << 8) | unwind_get_byte(ctrl);
     257                 :          5 :                 mask = insn & 0x0fff;
     258         [ -  + ]:          5 :                 if (mask == 0) {
     259                 :          0 :                         pr_warning("unwind: 'Refuse to unwind' instruction %04lx\n",
     260                 :            :                                    insn);
     261                 :          0 :                         return -URC_FAILURE;
     262                 :            :                 }
     263                 :            : 
     264                 :            :                 /* pop R4-R15 according to mask */
     265                 :          5 :                 load_sp = mask & (1 << (13 - 4));
     266         [ +  + ]:         60 :                 while (mask) {
     267         [ +  + ]:         55 :                         if (mask & 1)
     268                 :         40 :                                 ctrl->vrs[reg] = *vsp++;
     269                 :         55 :                         mask >>= 1;
     270                 :         55 :                         reg++;
     271                 :            :                 }
     272         [ +  - ]:          5 :                 if (!load_sp)
     273                 :          5 :                         ctrl->vrs[SP] = (unsigned long)vsp;
     274 [ +  + ][ +  - ]:      23518 :         } else if ((insn & 0xf0) == 0x90 &&
     275                 :      23420 :                    (insn & 0x0d) != 0x0d)
     276                 :      23420 :                 ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f];
     277         [ +  + ]:         98 :         else if ((insn & 0xf0) == 0xa0) {
     278                 :         47 :                 unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
     279                 :            :                 int reg;
     280                 :            : 
     281                 :            :                 /* pop R4-R[4+bbb] */
     282         [ +  + ]:        375 :                 for (reg = 4; reg <= 4 + (insn & 7); reg++)
     283                 :        328 :                         ctrl->vrs[reg] = *vsp++;
     284         [ +  - ]:         47 :                 if (insn & 0x80)
     285                 :         47 :                         ctrl->vrs[14] = *vsp++;
     286                 :         47 :                 ctrl->vrs[SP] = (unsigned long)vsp;
     287         [ +  + ]:         51 :         } else if (insn == 0xb0) {
     288         [ +  - ]:         40 :                 if (ctrl->vrs[PC] == 0)
     289                 :         40 :                         ctrl->vrs[PC] = ctrl->vrs[LR];
     290                 :            :                 /* no further processing */
     291                 :         40 :                 ctrl->entries = 0;
     292         [ +  - ]:         11 :         } else if (insn == 0xb1) {
     293                 :         11 :                 unsigned long mask = unwind_get_byte(ctrl);
     294                 :         11 :                 unsigned long *vsp = (unsigned long *)ctrl->vrs[SP];
     295                 :            :                 int reg = 0;
     296                 :            : 
     297 [ +  - ][ +  - ]:         11 :                 if (mask == 0 || mask & 0xf0) {
     298                 :          0 :                         pr_warning("unwind: Spare encoding %04lx\n",
     299                 :            :                                (insn << 8) | mask);
     300                 :          0 :                         return -URC_FAILURE;
     301                 :            :                 }
     302                 :            : 
     303                 :            :                 /* pop R0-R3 according to mask */
     304         [ +  + ]:         55 :                 while (mask) {
     305         [ +  + ]:         44 :                         if (mask & 1)
     306                 :         12 :                                 ctrl->vrs[reg] = *vsp++;
     307                 :         44 :                         mask >>= 1;
     308                 :         44 :                         reg++;
     309                 :            :                 }
     310                 :         11 :                 ctrl->vrs[SP] = (unsigned long)vsp;
     311         [ #  # ]:          0 :         } else if (insn == 0xb2) {
     312                 :          0 :                 unsigned long uleb128 = unwind_get_byte(ctrl);
     313                 :            : 
     314                 :          0 :                 ctrl->vrs[SP] += 0x204 + (uleb128 << 2);
     315                 :            :         } else {
     316                 :          0 :                 pr_warning("unwind: Unhandled instruction %02lx\n", insn);
     317                 :          0 :                 return -URC_FAILURE;
     318                 :            :         }
     319                 :            : 
     320                 :            :         pr_debug("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx\n", __func__,
     321                 :            :                  ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]);
     322                 :            : 
     323                 :            :         return URC_OK;
     324                 :            : }
     325                 :            : 
     326                 :            : /*
     327                 :            :  * Unwind a single frame starting with *sp for the symbol at *pc. It
     328                 :            :  * updates the *pc and *sp with the new values.
     329                 :            :  */
     330                 :          0 : int unwind_frame(struct stackframe *frame)
     331                 :            : {
     332                 :            :         unsigned long high, low;
     333                 :            :         const struct unwind_idx *idx;
     334                 :            :         struct unwind_ctrl_block ctrl;
     335                 :            : 
     336                 :            :         /* only go to a higher address on the stack */
     337                 :      23472 :         low = frame->sp;
     338                 :      23472 :         high = ALIGN(low, THREAD_SIZE);
     339                 :            : 
     340                 :            :         pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__,
     341                 :            :                  frame->pc, frame->lr, frame->sp);
     342                 :            : 
     343         [ +  - ]:      23472 :         if (!kernel_text_address(frame->pc))
     344                 :            :                 return -URC_FAILURE;
     345                 :            : 
     346                 :      23472 :         idx = unwind_find_idx(frame->pc);
     347         [ -  + ]:      23472 :         if (!idx) {
     348                 :          0 :                 pr_warning("unwind: Index not found %08lx\n", frame->pc);
     349                 :          0 :                 return -URC_FAILURE;
     350                 :            :         }
     351                 :            : 
     352                 :      23472 :         ctrl.vrs[FP] = frame->fp;
     353                 :      23472 :         ctrl.vrs[SP] = frame->sp;
     354                 :      23472 :         ctrl.vrs[LR] = frame->lr;
     355                 :      23472 :         ctrl.vrs[PC] = 0;
     356                 :            : 
     357            [ + ]:      23472 :         if (idx->insn == 1)
     358                 :            :                 /* can't unwind */
     359                 :            :                 return -URC_FAILURE;
     360         [ +  + ]:      46938 :         else if ((idx->insn & 0x80000000) == 0)
     361                 :            :                 /* prel31 to the unwind table */
     362                 :      23477 :                 ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn);
     363         [ +  - ]:      23461 :         else if ((idx->insn & 0xff000000) == 0x80000000)
     364                 :            :                 /* only personality routine 0 supported in the index */
     365                 :      23461 :                 ctrl.insn = &idx->insn;
     366                 :            :         else {
     367                 :          0 :                 pr_warning("unwind: Unsupported personality routine %08lx in the index at %p\n",
     368                 :            :                            idx->insn, idx);
     369                 :          0 :                 return -URC_FAILURE;
     370                 :            :         }
     371                 :            : 
     372                 :            :         /* check the personality routine */
     373         [ +  + ]:      23466 :         if ((*ctrl.insn & 0xff000000) == 0x80000000) {
     374                 :      23461 :                 ctrl.byte = 2;
     375                 :      23461 :                 ctrl.entries = 1;
     376         [ +  - ]:          5 :         } else if ((*ctrl.insn & 0xff000000) == 0x81000000) {
     377                 :          5 :                 ctrl.byte = 1;
     378                 :          5 :                 ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16);
     379                 :            :         } else {
     380                 :          0 :                 pr_warning("unwind: Unsupported personality routine %08lx at %p\n",
     381                 :            :                            *ctrl.insn, ctrl.insn);
     382                 :          0 :                 return -URC_FAILURE;
     383                 :            :         }
     384                 :            : 
     385         [ +  + ]:      23617 :         while (ctrl.entries > 0) {
     386                 :      23565 :                 int urc = unwind_exec_insn(&ctrl);
     387         [ +  - ]:      23565 :                 if (urc < 0)
     388                 :            :                         return urc;
     389 [ +  + ][ +  - ]:      47031 :                 if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high)
     390                 :            :                         return -URC_FAILURE;
     391                 :            :         }
     392                 :            : 
     393         [ +  + ]:         52 :         if (ctrl.vrs[PC] == 0)
     394                 :         12 :                 ctrl.vrs[PC] = ctrl.vrs[LR];
     395                 :            : 
     396                 :            :         /* check for infinite loop */
     397         [ +  - ]:         52 :         if (frame->pc == ctrl.vrs[PC])
     398                 :            :                 return -URC_FAILURE;
     399                 :            : 
     400                 :         52 :         frame->fp = ctrl.vrs[FP];
     401                 :         52 :         frame->sp = ctrl.vrs[SP];
     402                 :         52 :         frame->lr = ctrl.vrs[LR];
     403                 :         52 :         frame->pc = ctrl.vrs[PC];
     404                 :            : 
     405                 :         52 :         return URC_OK;
     406                 :            : }
     407                 :            : 
     408                 :          0 : void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk)
     409                 :            : {
     410                 :            :         struct stackframe frame;
     411                 :            : 
     412                 :            :         pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
     413                 :            : 
     414         [ +  - ]:          4 :         if (!tsk)
     415                 :          4 :                 tsk = current;
     416                 :            : 
     417         [ -  + ]:          4 :         if (regs) {
     418                 :          0 :                 frame.fp = regs->ARM_fp;
     419                 :          0 :                 frame.sp = regs->ARM_sp;
     420                 :          0 :                 frame.lr = regs->ARM_lr;
     421                 :            :                 /* PC might be corrupted, use LR in that case. */
     422                 :          0 :                 frame.pc = kernel_text_address(regs->ARM_pc)
     423         [ +  - ]:          4 :                          ? regs->ARM_pc : regs->ARM_lr;
     424         [ +  - ]:          4 :         } else if (tsk == current) {
     425                 :          4 :                 frame.fp = (unsigned long)__builtin_frame_address(0);
     426                 :          4 :                 frame.sp = __builtin_stack_pointer();
     427                 :          4 :                 frame.lr = (unsigned long)__builtin_return_address(0);
     428                 :          4 :                 frame.pc = (unsigned long)unwind_backtrace;
     429                 :            :         } else {
     430                 :            :                 /* task blocked in __switch_to */
     431                 :          0 :                 frame.fp = thread_saved_fp(tsk);
     432                 :          0 :                 frame.sp = thread_saved_sp(tsk);
     433                 :            :                 /*
     434                 :            :                  * The function calling __switch_to cannot be a leaf function
     435                 :            :                  * so LR is recovered from the stack.
     436                 :            :                  */
     437                 :          0 :                 frame.lr = 0;
     438                 :          4 :                 frame.pc = thread_saved_pc(tsk);
     439                 :            :         }
     440                 :            : 
     441                 :            :         while (1) {
     442                 :            :                 int urc;
     443                 :         44 :                 unsigned long where = frame.pc;
     444                 :            : 
     445                 :         44 :                 urc = unwind_frame(&frame);
     446         [ +  + ]:         44 :                 if (urc < 0)
     447                 :            :                         break;
     448                 :         40 :                 dump_backtrace_entry(where, frame.pc, frame.sp - 4);
     449                 :         40 :         }
     450                 :          4 : }
     451                 :            : 
     452                 :          0 : struct unwind_table *unwind_table_add(unsigned long start, unsigned long size,
     453                 :            :                                       unsigned long text_addr,
     454                 :            :                                       unsigned long text_size)
     455                 :            : {
     456                 :            :         unsigned long flags;
     457                 :            :         struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL);
     458                 :            : 
     459                 :            :         pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size,
     460                 :            :                  text_addr, text_size);
     461                 :            : 
     462         [ #  # ]:          0 :         if (!tab)
     463                 :            :                 return tab;
     464                 :            : 
     465                 :          0 :         tab->start = (const struct unwind_idx *)start;
     466                 :          0 :         tab->stop = (const struct unwind_idx *)(start + size);
     467                 :          0 :         tab->origin = unwind_find_origin(tab->start, tab->stop);
     468                 :          0 :         tab->begin_addr = text_addr;
     469                 :          0 :         tab->end_addr = text_addr + text_size;
     470                 :            : 
     471                 :          0 :         spin_lock_irqsave(&unwind_lock, flags);
     472                 :          0 :         list_add_tail(&tab->list, &unwind_tables);
     473                 :            :         spin_unlock_irqrestore(&unwind_lock, flags);
     474                 :            : 
     475                 :          0 :         return tab;
     476                 :            : }
     477                 :            : 
     478                 :          0 : void unwind_table_del(struct unwind_table *tab)
     479                 :            : {
     480                 :            :         unsigned long flags;
     481                 :            : 
     482         [ #  # ]:          0 :         if (!tab)
     483                 :          0 :                 return;
     484                 :            : 
     485                 :          0 :         spin_lock_irqsave(&unwind_lock, flags);
     486                 :            :         list_del(&tab->list);
     487                 :            :         spin_unlock_irqrestore(&unwind_lock, flags);
     488                 :            : 
     489                 :          0 :         kfree(tab);
     490                 :            : }

Generated by: LCOV version 1.9