tegra-profiler: fix unused function build issue
[linux-3.10.git] / drivers / misc / tegra-profiler / dwarf_unwind.c
1 /*
2  * drivers/misc/tegra-profiler/dwarf_unwind.c
3  *
4  * Copyright (c) 2015-2016, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include <linux/mm.h>
20 #include <linux/sched.h>
21 #include <linux/slab.h>
22 #include <linux/uaccess.h>
23 #include <linux/err.h>
24
25 #include <asm/unaligned.h>
26
27 #include <linux/tegra_profiler.h>
28
29 #include "comm.h"
30 #include "backtrace.h"
31 #include "eh_unwind.h"
32 #include "dwarf.h"
33 #include "dwarf_unwind.h"
34
35 enum {
36         DW_WHERE_UNDEF,         /* register isn't saved at all */
37         DW_WHERE_SAME,          /* register has same value as in prev. frame */
38         DW_WHERE_CFAREL,        /* register saved at CFA-relative address */
39         DW_WHERE_REG,           /* register saved in another register */
40         DW_WHERE_EXPR,          /* register saved */
41         DW_WHERE_VAL_OFFSET,    /* value offset */
42         DW_WHERE_VAL_EXPR,      /* register has computed value */
43 };
44
45 #define QUADD_AARCH64_REGISTERS 32
46 #define QUADD_AARCH32_REGISTERS 16
47
48 #define QUADD_NUM_REGS QUADD_AARCH64_REGISTERS
49
50 enum regs32 {
51         ARM32_FP_THUMB = 7,
52         ARM32_FP = 11,
53
54         ARM32_SP = 13,
55         ARM32_LR = 14,
56         ARM32_PC = 15
57 };
58
59 enum regs64 {
60         ARM64_FP = 29,
61         ARM64_LR = 30,
62         ARM64_SP = 31,
63 };
64
65 enum {
66         DW_MODE_ARM32,
67         DW_MODE_ARM64,
68 };
69
70 union dw_loc {
71         unsigned long reg;
72         long offset;
73         const unsigned char *exp;
74 };
75
76 struct reg_info {
77         int where;
78         union dw_loc loc;
79 };
80
81 enum {
82         DW_CFA_UNSET,
83         DW_CFA_REG_OFFSET,
84         DW_CFA_EXP,
85 };
86
87 struct dw_eh_frame_hdr {
88         unsigned char version;
89         unsigned char eh_frame_ptr_enc;
90         unsigned char fde_count_enc;
91         unsigned char table_enc;
92 };
93
94 struct dw_fde_table {
95         s32 initial_loc;
96         s32 fde;
97 };
98
99 struct regs_state {
100         struct reg_info reg[QUADD_NUM_REGS];
101
102         long cfa_offset;
103         int cfa_register;
104
105         unsigned char *cfa_expr;
106         unsigned int cfa_expr_len;
107
108         int cfa_how;
109 };
110
111 #define DW_MAX_RS_STACK_DEPTH   8
112
113 struct stackframe {
114         unsigned long pc;
115         unsigned long vregs[QUADD_NUM_REGS];
116
117         struct regs_state rs;
118         struct regs_state rs_initial;
119
120         unsigned long cfa;
121
122         int mode;
123 };
124
125 struct dwarf_cpu_context {
126         struct regs_state rs_stack[DW_MAX_RS_STACK_DEPTH];
127         int depth;
128
129         struct stackframe sf;
130         int dw_ptr_size;
131 };
132
133 struct quadd_dwarf_context {
134         struct dwarf_cpu_context __percpu *cpu_ctx;
135         atomic_t started;
136 };
137
138 struct dw_cie {
139         unsigned long offset;
140         unsigned long length;
141
142         unsigned char *aug_string;
143         unsigned long aug_size;
144
145         unsigned char fde_encoding;
146         unsigned char lsda_encoding;
147
148         unsigned long code_align_factor;
149         long data_align_factor;
150
151         unsigned int initial_insn_len;
152         unsigned char *initial_insn;
153
154         int z_aug;
155         unsigned int retaddr_reg;
156         void *personality;
157
158         unsigned char *data;
159 };
160
161 struct dw_fde {
162         unsigned long offset;
163         unsigned long length;
164
165         unsigned long cie_pointer;
166         struct dw_cie *cie;
167
168         unsigned long initial_location;
169         unsigned long address_range;
170
171         unsigned int insn_length;
172         unsigned char *instructions;
173
174         unsigned char *data;
175 };
176
177
178 struct eh_sec_data {
179         size_t length;
180         unsigned char *data;
181 };
182
183 #define read_user_data(addr, retval)                            \
184 ({                                                              \
185         long ret;                                               \
186                                                                 \
187         pagefault_disable();                                    \
188         ret = __get_user(retval, addr);                         \
189         pagefault_enable();                                     \
190                                                                 \
191         if (ret) {                                              \
192                 pr_debug("%s: failed for address: %p\n",        \
193                          __func__, addr);                       \
194                 ret = -QUADD_URC_EACCESS;                       \
195         }                                                       \
196                                                                 \
197         ret;                                                    \
198 })
199
200 static struct quadd_dwarf_context ctx;
201
202 static inline int regnum_sp(int mode)
203 {
204         return (mode == DW_MODE_ARM32) ?
205                 ARM32_SP : ARM64_SP;
206 }
207
208 static inline int regnum_fp(int mode)
209 {
210         return (mode == DW_MODE_ARM32) ?
211                 ARM32_FP : ARM64_FP;
212 }
213
214 static inline int regnum_lr(int mode)
215 {
216         return (mode == DW_MODE_ARM32) ?
217                 ARM32_LR : ARM64_LR;
218 }
219
220 static inline unsigned long
221 get_user_reg_size(int mode)
222 {
223         return (mode == DW_MODE_ARM32) ?
224                 sizeof(u32) : sizeof(u64);
225 }
226
227 static inline int
228 get_secid_frame(int is_eh)
229 {
230         return is_eh ?
231                 QUADD_SEC_TYPE_EH_FRAME :
232                 QUADD_SEC_TYPE_DEBUG_FRAME;
233 }
234
235 static inline int
236 get_secid_frame_hdr(int is_eh)
237 {
238         return is_eh ?
239                 QUADD_SEC_TYPE_EH_FRAME_HDR :
240                 QUADD_SEC_TYPE_DEBUG_FRAME_HDR;
241 }
242
243 static inline int
244 is_frame_present(struct ex_region_info *ri, int is_eh)
245 {
246         struct extab_info *ti, *ti_hdr;
247
248         ti = &ri->ex_sec[get_secid_frame(is_eh)];
249         ti_hdr = &ri->ex_sec[get_secid_frame_hdr(is_eh)];
250
251         return (ti->length && ti_hdr->length) ? 1 : 0;
252 }
253
254 static inline int
255 validate_addr(struct ex_region_info *ri,
256               unsigned long addr,
257               unsigned long nbytes,
258               int st)
259 {
260         struct extab_info *ti;
261         struct quadd_mmap_area *mmap;
262         unsigned long start, end;
263
264         mmap = ri->mmap;
265
266         ti = &ri->ex_sec[st];
267
268         start = (unsigned long)mmap->data + ti->mmap_offset;
269         end = start + ti->length;
270
271         if (unlikely(addr < start || addr > end - nbytes)) {
272                 pr_err_once("%s: error: addr: %#lx, len: %ld, data: %#lx-%#lx\n",
273                             __func__, addr, nbytes, start, end);
274                 return 0;
275         }
276
277         return 1;
278 }
279
280 static inline u8
281 read_mmap_data_u8(struct ex_region_info *ri,
282                   const u8 *addr, int st, long *err)
283 {
284         unsigned long a = (unsigned long)addr;
285
286         if (unlikely(!validate_addr(ri, a, sizeof(*addr), st))) {
287                 *err = -QUADD_URC_EACCESS;
288                 return 0;
289         }
290
291         *err = 0;
292         return *addr;
293 }
294
295 static inline u16
296 read_mmap_data_u16(struct ex_region_info *ri,
297                    const u16 *addr, int st, long *err)
298 {
299         unsigned long a = (unsigned long)addr;
300
301         if (unlikely(!validate_addr(ri, a, sizeof(*addr), st))) {
302                 *err = -QUADD_URC_EACCESS;
303                 return 0;
304         }
305
306         *err = 0;
307
308         return get_unaligned(addr);
309 }
310
311 static inline s16
312 read_mmap_data_s16(struct ex_region_info *ri,
313                    const s16 *addr, int st, long *err)
314 {
315         unsigned long a = (unsigned long)addr;
316
317         if (unlikely(!validate_addr(ri, a, sizeof(*addr), st))) {
318                 *err = -QUADD_URC_EACCESS;
319                 return 0;
320         }
321
322         *err = 0;
323
324         return get_unaligned(addr);
325 }
326
327 static inline u32
328 read_mmap_data_u32(struct ex_region_info *ri,
329                    const u32 *addr, int st, long *err)
330 {
331         unsigned long a = (unsigned long)addr;
332
333         if (unlikely(!validate_addr(ri, a, sizeof(*addr), st))) {
334                 *err = -QUADD_URC_EACCESS;
335                 return 0;
336         }
337
338         *err = 0;
339
340         return get_unaligned(addr);
341 }
342
343 static inline s32
344 read_mmap_data_s32(struct ex_region_info *ri,
345                    const s32 *addr, int st, long *err)
346 {
347         unsigned long a = (unsigned long)addr;
348
349         if (unlikely(!validate_addr(ri, a, sizeof(*addr), st))) {
350                 *err = -QUADD_URC_EACCESS;
351                 return 0;
352         }
353
354         *err = 0;
355
356         return get_unaligned(addr);
357 }
358
359 static inline s64
360 read_mmap_data_s64(struct ex_region_info *ri,
361                    const s64 *addr, int st, long *err)
362 {
363         unsigned long a = (unsigned long)addr;
364
365         if (unlikely(!validate_addr(ri, a, sizeof(*addr), st))) {
366                 *err = -QUADD_URC_EACCESS;
367                 return 0;
368         }
369
370         *err = 0;
371
372         return get_unaligned(addr);
373 }
374
375 static inline u64
376 read_mmap_data_u64(struct ex_region_info *ri,
377                    const u64 *addr, int st, long *err)
378 {
379         unsigned long a = (unsigned long)addr;
380
381         if (unlikely(!validate_addr(ri, a, sizeof(*addr), st))) {
382                 *err = -QUADD_URC_EACCESS;
383                 return 0;
384         }
385
386         *err = 0;
387
388         return get_unaligned(addr);
389 }
390
391 static inline unsigned long
392 ex_addr_to_mmap_addr(unsigned long addr,
393                      struct ex_region_info *ri, int st)
394 {
395         unsigned long offset;
396         struct extab_info *ti;
397
398         ti = &ri->ex_sec[st];
399         offset = addr - ti->addr;
400
401         return ti->mmap_offset + offset + (unsigned long)ri->mmap->data;
402 }
403
404 static inline unsigned long
405 mmap_addr_to_ex_addr(unsigned long addr,
406                      struct ex_region_info *ri, int st)
407 {
408         unsigned long offset;
409         struct extab_info *ti;
410
411         ti = &ri->ex_sec[st];
412         offset = addr - ti->mmap_offset - (unsigned long)ri->mmap->data;
413
414         return ti->addr + offset;
415 }
416
417 static inline int validate_regnum(struct regs_state *rs, int regnum)
418 {
419         if (unlikely(regnum >= ARRAY_SIZE(rs->reg))) {
420                 pr_err_once("error: invalid reg: %d\n", regnum);
421                 return 0;
422         }
423
424         return 1;
425 }
426
427 static inline void
428 set_rule_offset(struct regs_state *rs, int regnum, int where, long offset)
429 {
430         struct reg_info *r;
431
432         if (!validate_regnum(rs, regnum))
433                 return;
434
435         r = &rs->reg[regnum];
436
437         r->where = where;
438         r->loc.offset = offset;
439 }
440
441 static inline void
442 set_rule_exp(struct regs_state *rs, int regnum,
443              int where, const unsigned char *exp)
444 {
445         struct reg_info *r;
446
447         if (!validate_regnum(rs, regnum))
448                 return;
449
450         r = &rs->reg[regnum];
451
452         r->where = where;
453         r->loc.exp = exp;
454 }
455
456 static inline void
457 set_rule(struct regs_state *rs, int regnum, int where, long value)
458 {
459         set_rule_offset(rs, regnum, where, value);
460 }
461
462 static inline unsigned long
463 dw_bst_get_initial_loc(const struct dw_fde_table *fi,
464                        unsigned long data_base)
465 {
466         return data_base + fi->initial_loc;
467 }
468
469 static inline unsigned long
470 dw_bst_get_fde_addr(const struct dw_fde_table *fi,
471                     unsigned long data_base)
472 {
473         return data_base + fi->fde;
474 }
475
476 static inline unsigned long
477 dwarf_read_uleb128(struct ex_region_info *ri,
478                    unsigned char *addr,
479                    unsigned long *ret,
480                    int st,
481                    long *err)
482 {
483         unsigned long result;
484         unsigned char byte;
485         int shift, count;
486
487         result = 0;
488         shift = 0;
489         count = 0;
490
491         while (1) {
492                 byte = read_mmap_data_u8(ri, addr, st, err);
493                 if (*err)
494                         return 0;
495
496                 addr++;
497                 count++;
498
499                 result |= (byte & 0x7f) << shift;
500                 shift += 7;
501
502                 if (!(byte & 0x80))
503                         break;
504         }
505
506         *ret = result;
507
508         return count;
509 }
510
511 static inline unsigned long
512 dwarf_read_sleb128(struct ex_region_info *ri,
513                    unsigned char *addr,
514                    long *ret,
515                    int st,
516                    long *err)
517 {
518         unsigned char byte;
519         long result, shift;
520         int num_bits;
521         int count;
522
523         result = 0;
524         shift = 0;
525         count = 0;
526
527         while (1) {
528                 byte = read_mmap_data_u8(ri, addr, st, err);
529                 if (*err)
530                         return 0;
531
532                 addr++;
533                 result |= (byte & 0x7f) << shift;
534                 shift += 7;
535                 count++;
536
537                 if (!(byte & 0x80))
538                         break;
539         }
540
541         num_bits = 8 * sizeof(result);
542
543         if ((shift < num_bits) && (byte & 0x40))
544                 result |= (-1 << shift);
545
546         *ret = result;
547
548         return count;
549 }
550
551 static inline unsigned int
552 dw_cfa_opcode(unsigned int insn)
553 {
554         return insn & 0xc0;
555 }
556
557 static inline unsigned int
558 dw_cfa_operand(unsigned int insn)
559 {
560         return insn & 0x3f;
561 }
562
563 static void
564 rules_cleanup(struct regs_state *rs, int mode)
565 {
566         int i, num_regs;
567
568         num_regs = (mode == DW_MODE_ARM32) ?
569                 QUADD_AARCH32_REGISTERS :
570                 QUADD_AARCH64_REGISTERS;
571
572         for (i = 0; i < num_regs; i++)
573                 set_rule(rs, i, DW_WHERE_UNDEF, 0);
574 }
575
576 static int
577 dwarf_read_encoded_value(struct ex_region_info *ri,
578                          void *addr,
579                          void *pcrel_base,
580                          unsigned long *val,
581                          char encoding,
582                          int st)
583 {
584         int dw_ptr_size, count = 0;
585         long stmp = 0, err = 0;
586         unsigned long utmp, res = 0;
587         struct dwarf_cpu_context *cpu_ctx = this_cpu_ptr(ctx.cpu_ctx);
588
589         pr_debug("encoding: %#x\n", encoding);
590
591         dw_ptr_size = cpu_ctx->dw_ptr_size;
592
593         if (encoding == DW_EH_PE_omit) {
594                 pr_debug("DW_EH_PE_omit\n");
595
596                 *val = 0;
597                 return 0;
598         } else if (encoding == DW_EH_PE_aligned) {
599                 unsigned long aligned = ALIGN((unsigned long)addr,
600                                               dw_ptr_size);
601
602                 pr_debug("DW_EH_PE_aligned\n");
603
604                 if (dw_ptr_size == 4) {
605                         *val = read_mmap_data_u32(ri, (u32 *)aligned, st, &err);
606                 } else if (dw_ptr_size == 8) {
607                         *val = read_mmap_data_u64(ri, (u64 *)aligned, st, &err);
608                 } else {
609                         pr_err_once("%s: error: encoding\n", __func__);
610                         return -QUADD_URC_TBL_IS_CORRUPT;
611                 }
612
613                 if (err)
614                         return err;
615
616                 return dw_ptr_size;
617         }
618
619         switch (encoding & 0x0f) {
620         case DW_EH_PE_absptr:
621                 pr_debug("%s: absptr encoding\n", __func__);
622
623                 if (dw_ptr_size == 4) {
624                         *val = read_mmap_data_u32(ri, (u32 *)addr, st, &err);
625                 } else if (dw_ptr_size == 8) {
626                         *val = read_mmap_data_u64(ri, (u64 *)addr, st, &err);
627                 } else {
628                         pr_err_once("error: wrong dwarf size\n");
629                         return -QUADD_URC_UNHANDLED_INSTRUCTION;
630                 }
631
632                 if (err)
633                         return err;
634
635                 return dw_ptr_size;
636
637         case DW_EH_PE_sdata2:
638         case DW_EH_PE_udata2:
639                 pr_debug("encoding: DW_EH_PE_sdata2\n");
640                 stmp = read_mmap_data_s16(ri, (s16 *)addr, st, &err);
641                 if (err)
642                         return err;
643
644                 count += sizeof(s16);
645                 break;
646
647         case DW_EH_PE_sdata4:
648         case DW_EH_PE_udata4:
649                 pr_debug("encoding: DW_EH_PE_udata4/sdata4\n");
650                 stmp = read_mmap_data_s32(ri, (s32 *)addr, st, &err);
651                 if (err)
652                         return err;
653
654                 count += sizeof(s32);
655                 break;
656
657         case DW_EH_PE_sdata8:
658         case DW_EH_PE_udata8:
659                 pr_debug("encoding: DW_EH_PE_udata8\n");
660                 stmp = read_mmap_data_s64(ri, (s64 *)addr, st, &err);
661                 if (err)
662                         return err;
663
664                 count += sizeof(s64);
665                 break;
666
667         case DW_EH_PE_uleb128:
668                 pr_debug("encoding: DW_EH_PE_uleb128\n");
669                 count += dwarf_read_uleb128(ri, addr, &utmp, st, &err);
670                 if (err)
671                         return err;
672
673                 stmp = utmp;
674                 break;
675
676         case DW_EH_PE_sleb128:
677                 pr_debug("encoding: DW_EH_PE_sleb128\n");
678                 count += dwarf_read_sleb128(ri, addr, &stmp, st, &err);
679                 if (err)
680                         return err;
681
682                 break;
683
684         default:
685                 pr_warn_once("%s: warning: encoding: %#x\n",
686                              __func__, encoding & 0x0f);
687                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
688         }
689
690         switch (encoding & 0x70) {
691         case DW_EH_PE_absptr:
692                 pr_debug("DW_EH_PE_absptr\n");
693                 res = stmp;
694                 break;
695
696         case DW_EH_PE_pcrel:
697                 pr_debug("DW_EH_PE_pcrel, pcrel_base: %p, stmp: %ld\n",
698                          pcrel_base, stmp);
699                 res = (unsigned long)pcrel_base + stmp;
700                 break;
701
702         case DW_EH_PE_textrel:
703                 pr_warn_once("warning: DW_EH_PE_textrel\n");
704                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
705
706         case DW_EH_PE_datarel:
707                 pr_warn_once("warning: DW_EH_PE_datarel\n");
708                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
709
710         case DW_EH_PE_funcrel:
711                 pr_warn_once("warning: DW_EH_PE_funcrel\n");
712                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
713
714         default:
715                 pr_warn_once("%s: warning: encoding: %#x\n",
716                              __func__, encoding & 0x70);
717                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
718         }
719
720         if (res != 0) {
721                 if (encoding & DW_EH_PE_indirect) {
722                         pr_debug("DW_EH_PE_indirect\n");
723
724                         if (dw_ptr_size == 4) {
725                                 res = read_mmap_data_u32(ri, (u32 *)res,
726                                                          st, &err);
727                         } else if (dw_ptr_size == 8) {
728                                 res = read_mmap_data_u64(ri, (u64 *)res,
729                                                          st, &err);
730                         } else {
731                                 pr_err_once("error: wrong dwarf size\n");
732                                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
733                         }
734
735                         /* we ignore links to unloaded sections */
736                         if (err)
737                                 res = 0;
738                 }
739         }
740
741         *val = res;
742
743         return count;
744 }
745
746 static long
747 dwarf_cfa_exec_insns(struct ex_region_info *ri,
748                      unsigned char *insn_start,
749                      unsigned char *insn_end,
750                      struct dw_cie *cie,
751                      struct stackframe *sf,
752                      unsigned long pc,
753                      int is_eh)
754 {
755         unsigned char insn;
756         unsigned char *c_insn;
757         unsigned int expr_len, delta, secid;
758         unsigned long utmp, reg;
759         long offset, stmp, err = 0;
760         struct regs_state *rs, *rs_initial, *rs_stack;
761         struct dwarf_cpu_context *cpu_ctx = this_cpu_ptr(ctx.cpu_ctx);
762
763         secid = get_secid_frame(is_eh);
764
765         rs = &sf->rs;
766         rs_initial = &sf->rs_initial;
767
768         rs_stack = cpu_ctx->rs_stack;
769         cpu_ctx->depth = 0;
770
771         c_insn = insn_start;
772
773         while (c_insn < insn_end && sf->pc <= pc) {
774                 insn = read_mmap_data_u8(ri, c_insn++,
775                                          secid, &err);
776                 if (err)
777                         return err;
778
779                 switch (dw_cfa_opcode(insn)) {
780                 case DW_CFA_advance_loc:
781                         delta = dw_cfa_operand(insn);
782                         delta *= cie->code_align_factor;
783                         sf->pc += delta;
784                         pr_debug("DW_CFA_advance_loc: pc: %#lx --> %#lx (delta: %#x)\n",
785                                 sf->pc - delta, sf->pc, delta);
786                         continue;
787
788                 case DW_CFA_offset:
789                         reg = dw_cfa_operand(insn);
790                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
791                                                      secid, &err);
792                         if (err)
793                                 return err;
794
795                         offset = utmp * cie->data_align_factor;
796                         set_rule_offset(rs, reg, DW_WHERE_CFAREL, offset);
797                         pr_debug("DW_CFA_offset: reg: r%lu, offset(addr): %#lx (%ld)\n",
798                                 reg, offset, offset);
799                         continue;
800
801                 case DW_CFA_restore:
802                         reg = dw_cfa_operand(insn);
803
804                         if (!validate_regnum(rs, reg))
805                                 break;
806
807                         rs->reg[reg] = rs_initial->reg[reg];
808                         pr_debug("DW_CFA_restore: reg: r%lu\n", reg);
809                         continue;
810                 }
811
812                 switch (insn) {
813                 case DW_CFA_nop:
814                         pr_debug("DW_CFA_nop\n");
815                         continue;
816
817                 case DW_CFA_advance_loc1:
818                         delta = read_mmap_data_u8(ri, c_insn++,
819                                                   secid, &err);
820                         if (err)
821                                 return err;
822
823                         sf->pc += delta * cie->code_align_factor;
824                         pr_debug("DW_CFA_advance_loc1: pc: %#lx --> %#lx (delta: %#lx)\n",
825                                 sf->pc - delta * cie->code_align_factor, sf->pc,
826                                 delta * cie->code_align_factor);
827                         break;
828
829                 case DW_CFA_advance_loc2:
830                         delta = read_mmap_data_u16(ri, (u16 *)c_insn,
831                                                    secid, &err);
832                         if (err)
833                                 return err;
834
835                         c_insn += 2;
836                         sf->pc += delta * cie->code_align_factor;
837                         pr_debug("DW_CFA_advance_loc2: pc: %#lx --> %#lx (delta: %#lx)\n",
838                                 sf->pc - delta * cie->code_align_factor, sf->pc,
839                                 delta * cie->code_align_factor);
840                         break;
841
842                 case DW_CFA_advance_loc4:
843                         delta = read_mmap_data_u32(ri, (u32 *)c_insn,
844                                                    secid, &err);
845                         if (err)
846                                 return err;
847
848                         c_insn += 4;
849                         sf->pc += delta * cie->code_align_factor;
850                         pr_debug("DW_CFA_advance_loc4: pc: %#lx --> %#lx (delta: %#lx)\n",
851                                 sf->pc - delta * cie->code_align_factor, sf->pc,
852                                 delta * cie->code_align_factor);
853                         break;
854
855                 case DW_CFA_offset_extended:
856                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
857                                                      secid, &err);
858                         if (err)
859                                 return err;
860
861                         reg = utmp;
862                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
863                                                      secid, &err);
864                         if (err)
865                                 return err;
866
867                         offset = utmp * cie->data_align_factor;
868                         pr_debug("DW_CFA_offset_extended: reg: r%lu, offset: %#lx\n",
869                                  reg, offset);
870                         break;
871
872                 case DW_CFA_restore_extended:
873                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
874                                                      secid, &err);
875                         if (err)
876                                 return err;
877
878                         pr_debug("DW_CFA_restore_extended: reg: r%lu\n", reg);
879                         break;
880
881                 case DW_CFA_undefined:
882                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
883                                                      secid, &err);
884                         if (err)
885                                 return err;
886
887                         set_rule(rs, reg, DW_WHERE_UNDEF, 0);
888                         pr_debug("DW_CFA_undefined: reg: r%lu\n", reg);
889                         break;
890
891                 case DW_CFA_def_cfa:
892                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
893                                                      secid, &err);
894                         if (err)
895                                 return err;
896
897                         rs->cfa_register = utmp;
898                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
899                                                      secid, &err);
900                         if (err)
901                                 return err;
902
903                         rs->cfa_offset = utmp;
904                         pr_debug("DW_CFA_def_cfa: cfa_register: r%u, cfa_offset: %ld (%#lx)\n",
905                                  rs->cfa_register, rs->cfa_offset,
906                                  rs->cfa_offset);
907                         break;
908
909                 case DW_CFA_def_cfa_register:
910                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
911                                                      secid, &err);
912                         if (err)
913                                 return err;
914
915                         rs->cfa_register = utmp;
916                         pr_debug("DW_CFA_def_cfa_register: cfa_register: r%u\n",
917                                rs->cfa_register);
918                         break;
919
920                 case DW_CFA_def_cfa_offset:
921                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
922                                                      secid, &err);
923                         if (err)
924                                 return err;
925
926                         rs->cfa_offset = utmp;
927                         pr_debug("DW_CFA_def_cfa_offset: cfa_offset: %ld (%#lx)\n",
928                                rs->cfa_offset, rs->cfa_offset);
929                         break;
930
931                 case DW_CFA_def_cfa_expression:
932                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
933                                                      secid, &err);
934                         if (err)
935                                 return err;
936
937                         expr_len = utmp;
938
939                         rs->cfa_expr = c_insn;
940                         rs->cfa_expr_len = expr_len;
941                         rs->cfa_how = DW_CFA_EXP;
942                         c_insn += expr_len;
943
944                         pr_debug("DW_CFA_def_cfa_expression: expr_len: %#x\n",
945                                  expr_len);
946                         break;
947
948                 case DW_CFA_expression:
949                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
950                                                      secid, &err);
951                         if (err)
952                                 return err;
953
954                         set_rule_exp(rs, reg, DW_WHERE_EXPR, c_insn);
955
956                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
957                                                      secid, &err);
958                         if (err)
959                                 return err;
960
961                         c_insn += utmp;
962
963                         pr_debug("DW_CFA_expression: reg: r%lu\n", reg);
964                         break;
965
966                 case DW_CFA_offset_extended_sf:
967                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
968                                                      secid, &err);
969                         if (err)
970                                 return err;
971
972                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
973                                                      secid, &err);
974                         if (err)
975                                 return err;
976
977                         offset = stmp * cie->data_align_factor;
978                         set_rule_offset(rs, reg, DW_WHERE_CFAREL, offset);
979                         pr_debug("DW_CFA_offset_extended_sf: reg: r%lu, offset: %#lx\n",
980                                  reg, offset);
981                         break;
982
983                 case DW_CFA_val_offset:
984                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
985                                                      secid, &err);
986                         if (err)
987                                 return err;
988
989                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
990                                                      secid, &err);
991                         if (err)
992                                 return err;
993
994                         offset = utmp * cie->data_align_factor;
995                         set_rule_offset(rs, reg, DW_WHERE_VAL_OFFSET, offset);
996                         pr_debug("DW_CFA_val_offset: reg: r%lu, offset(addr): %#lx\n",
997                                  reg, offset);
998                         break;
999
1000                 case DW_CFA_val_offset_sf:
1001                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1002                                                      secid, &err);
1003                         if (err)
1004                                 return err;
1005
1006                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
1007                                                      secid, &err);
1008                         if (err)
1009                                 return err;
1010
1011                         offset = stmp * cie->data_align_factor;
1012                         set_rule_offset(rs, reg, DW_WHERE_VAL_OFFSET, offset);
1013                         pr_debug("DW_CFA_val_offset_sf: reg: r%lu, offset(addr): %#lx\n",
1014                                  reg, offset);
1015                         break;
1016
1017                 case DW_CFA_GNU_args_size:
1018                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1019                                                      secid, &err);
1020                         if (err)
1021                                 return err;
1022
1023                         pr_debug("DW_CFA_GNU_args_size: offset: %#lx\n", utmp);
1024                         break;
1025
1026                 case DW_CFA_GNU_negative_offset_extended:
1027                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1028                                                      secid, &err);
1029                         if (err)
1030                                 return err;
1031
1032                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1033                                                      secid, &err);
1034                         if (err)
1035                                 return err;
1036
1037                         offset = utmp * cie->data_align_factor;
1038                         set_rule_offset(rs, reg, DW_WHERE_CFAREL, -offset);
1039                         pr_debug("DW_CFA_GNU_negative_offset_extended: reg: r%lu, offset: %#lx\n",
1040                                  reg, offset);
1041                         break;
1042
1043                 case DW_CFA_remember_state:
1044                         pr_debug("DW_CFA_remember_state\n");
1045
1046                         if (cpu_ctx->depth >= DW_MAX_RS_STACK_DEPTH) {
1047                                 pr_warn_once("error: rs stack was overflowed\n");
1048                                 return 0;
1049                         }
1050
1051                         rs_stack[cpu_ctx->depth++] = *rs;
1052                         break;
1053
1054                 case DW_CFA_restore_state:
1055                         pr_debug("DW_CFA_restore_state\n");
1056
1057                         if (cpu_ctx->depth == 0) {
1058                                 pr_warn_once("error: rs stack error\n");
1059                                 return 0;
1060                         }
1061
1062                         *rs = rs_stack[--cpu_ctx->depth];
1063                         break;
1064
1065                 case DW_CFA_def_cfa_sf:
1066                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1067                                                      secid, &err);
1068                         if (err)
1069                                 return err;
1070
1071                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
1072                                                      secid, &err);
1073                         if (err)
1074                                 return err;
1075
1076                         rs->cfa_register = utmp;
1077                         rs->cfa_offset = stmp * cie->data_align_factor;
1078                         rs->cfa_how = DW_CFA_REG_OFFSET;
1079
1080                         pr_debug("DW_CFA_def_cfa_sf: cfa_register: r%u, cfa_offset: %ld (%#lx)\n",
1081                                 rs->cfa_register, rs->cfa_offset,
1082                                 rs->cfa_offset);
1083                         break;
1084
1085                 case DW_CFA_def_cfa_offset_sf:
1086                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
1087                                                      secid, &err);
1088                         if (err)
1089                                 return err;
1090
1091                         rs->cfa_offset = stmp * cie->data_align_factor;
1092                         pr_debug("DW_CFA_def_cfa_offset_sf: cfa_offset: %ld (%#lx)\n",
1093                                 rs->cfa_offset, rs->cfa_offset);
1094                         break;
1095
1096                 case DW_CFA_same_value:
1097                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1098                                                      secid, &err);
1099                         if (err)
1100                                 return err;
1101
1102                         set_rule(rs, reg, DW_WHERE_SAME, 0);
1103                         pr_debug("DW_CFA_same_value: reg: r%lu\n", reg);
1104                         break;
1105
1106                 case DW_CFA_val_expression:
1107                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1108                                                      secid, &err);
1109                         if (err)
1110                                 return err;
1111
1112                         set_rule_exp(rs, reg, DW_WHERE_VAL_EXPR, c_insn);
1113                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1114                                                      secid, &err);
1115                         if (err)
1116                                 return err;
1117
1118                         c_insn += utmp;
1119                         pr_debug("DW_CFA_val_expression: reg: r%lu\n", reg);
1120                         break;
1121
1122                 default:
1123                         pr_warn_once("warning: unhandled dwarf instr %#x\n",
1124                                      insn);
1125                         break;
1126                 }
1127         }
1128
1129         return 0;
1130 }
1131
1132 static long
1133 decode_cie_entry(struct ex_region_info *ri,
1134                  struct dw_cie *cie,
1135                  unsigned char *entry,
1136                  size_t length,
1137                  int is_eh)
1138 {
1139         long err;
1140         unsigned long utmp;
1141         unsigned char *p, *end, *aug;
1142         unsigned int secid, cie_id;
1143         unsigned int cie_version, id, len, max_len;
1144
1145         secid = get_secid_frame(is_eh);
1146
1147         p = entry;
1148         end = entry + length;
1149
1150         p += sizeof(u32);
1151
1152         id = read_mmap_data_u32(ri, (u32 *)p, secid, &err);
1153         if (err)
1154                 return err;
1155
1156         p += sizeof(u32);
1157
1158         cie_id = is_eh ? 0 : DW_CIE_ID;
1159         if (id != cie_id) {
1160                 pr_err_once("error: incorrect cie_id");
1161                 return -QUADD_URC_TBL_IS_CORRUPT;
1162         }
1163
1164         cie_version = read_mmap_data_u8(ri, p++, secid, &err);
1165         if (err)
1166                 return err;
1167
1168         if (cie_version != 1 && cie_version != 3) {
1169                 pr_err_once("error: wrong cie_version: %u\n", cie_version);
1170                 return -QUADD_URC_TBL_IS_CORRUPT;
1171         }
1172
1173         if (p >= end)
1174                 return -QUADD_URC_TBL_IS_CORRUPT;
1175
1176         max_len = end - p - 1;
1177         len = strnlen((const char *)p, max_len);
1178         if (len == max_len)
1179                 return -QUADD_URC_TBL_IS_CORRUPT;
1180
1181         cie->aug_string = p;
1182         p += len + 1;
1183
1184         pr_debug("aug_string: %s\n", cie->aug_string);
1185
1186         p += dwarf_read_uleb128(ri, p, &cie->code_align_factor,
1187                                 secid, &err);
1188         if (err)
1189                 return err;
1190
1191         p += dwarf_read_sleb128(ri, p, &cie->data_align_factor,
1192                                 secid, &err);
1193         if (err)
1194                 return err;
1195
1196         if (cie_version == 1) {
1197                 cie->retaddr_reg = read_mmap_data_u8(ri, p++,
1198                                                      secid,
1199                                                      &err);
1200                 if (err)
1201                         return err;
1202         } else {
1203                 p += dwarf_read_uleb128(ri, p, &utmp,
1204                                         secid, &err);
1205                 if (err)
1206                         return err;
1207
1208                 cie->retaddr_reg = utmp;
1209         }
1210
1211         pr_debug("address column: %u\n", cie->retaddr_reg);
1212
1213         aug = cie->aug_string;
1214         cie->z_aug = 0;
1215
1216         cie->initial_insn = NULL;
1217         cie->initial_insn_len = 0;
1218
1219         if (*aug == 'z') {
1220                 p += dwarf_read_uleb128(ri, p, &cie->aug_size,
1221                                         secid, &err);
1222                 if (err)
1223                         return err;
1224
1225                 cie->initial_insn = p + cie->aug_size;
1226                 aug++;
1227
1228                 cie->z_aug = 1;
1229         }
1230
1231         cie->fde_encoding = 0;
1232         cie->lsda_encoding = DW_EH_PE_omit;
1233         cie->personality = NULL;
1234
1235         while (*aug != '\0') {
1236                 if (p >= end)
1237                         return -QUADD_URC_TBL_IS_CORRUPT;
1238
1239                 if (*aug == 'L') {
1240                         cie->lsda_encoding =
1241                                 read_mmap_data_u8(ri, p++,
1242                                                   secid,
1243                                                   &err);
1244                         if (err)
1245                                 return err;
1246
1247                         aug++;
1248                 } else if (*aug == 'R') {
1249                         cie->fde_encoding =
1250                                 read_mmap_data_u8(ri, p++,
1251                                                   secid,
1252                                                   &err);
1253                         if (err)
1254                                 return err;
1255
1256                         aug++;
1257                         pr_debug("fde_encoding: %#x\n", cie->fde_encoding);
1258                 } else if (*aug == 'P') {
1259                         int cnt;
1260                         void *pcrel_base;
1261                         unsigned char handler_encoding;
1262                         unsigned long personality;
1263
1264                         handler_encoding = *p++;
1265
1266                         pcrel_base = (void *)
1267                                 mmap_addr_to_ex_addr((unsigned long)p,
1268                                                      ri,
1269                                                      secid);
1270
1271                         cnt = dwarf_read_encoded_value(ri, p, pcrel_base,
1272                                                        &personality,
1273                                                        handler_encoding,
1274                                                        secid);
1275                         if (cnt < 0) {
1276                                 pr_err_once("%s: error: personality routine\n",
1277                                             __func__);
1278                                 return cnt;
1279                         }
1280                         p += cnt;
1281
1282                         pr_debug("personality: %#lx\n", personality);
1283                         cie->personality = (void *)personality;
1284                         aug++;
1285                 } else if (*aug == 'S') {
1286                         aug++;
1287                         pr_debug("%s: aug: S\n", __func__);
1288                 } else {
1289                         pr_warn_once("%s: warning: unknown aug\n", __func__);
1290                         return -QUADD_URC_UNHANDLED_INSTRUCTION;
1291                 }
1292         }
1293
1294         if (p > end) {
1295                 pr_err_once("%s: error: cie\n", __func__);
1296                 return -QUADD_URC_TBL_IS_CORRUPT;
1297         }
1298
1299         if (p == end)
1300                 return 0;
1301
1302         if (!cie->initial_insn)
1303                 cie->initial_insn = p;
1304
1305         cie->initial_insn_len = end - cie->initial_insn;
1306
1307         return 0;
1308 }
1309
1310 static long
1311 decode_fde_entry(struct ex_region_info *ri,
1312                  struct dw_fde *fde,
1313                  unsigned char *entry,
1314                  size_t length,
1315                  int is_eh)
1316 {
1317         int count, secid;
1318         long err = 0;
1319         unsigned long utmp;
1320         unsigned char *p, *end, *pcrel_base;
1321         struct dw_cie *cie = fde->cie;
1322
1323         secid = get_secid_frame(is_eh);
1324
1325         p = entry;
1326         end = entry + length;
1327
1328         p += sizeof(u32);
1329         p += sizeof(u32);
1330
1331         pcrel_base = (unsigned char *)
1332                 mmap_addr_to_ex_addr((unsigned long)p, ri, secid);
1333
1334         count = dwarf_read_encoded_value(ri, p, pcrel_base,
1335                                          &fde->initial_location,
1336                                          cie->fde_encoding,
1337                                          secid);
1338         if (count < 0)
1339                 return count;
1340
1341         p += count;
1342
1343         fde->address_range = read_mmap_data_u32(ri, (u32 *)p,
1344                                                 secid, &err);
1345         if (err)
1346                 return err;
1347
1348         p += sizeof(u32);
1349
1350         if (fde->initial_location < ri->vm_start)
1351                 fde->initial_location += ri->vm_start;
1352
1353         pr_debug("pcrel_base: %p\n", pcrel_base);
1354         pr_debug("init location: %#lx\n", fde->initial_location);
1355         pr_debug("address_range: %#lx\n", fde->address_range);
1356
1357         if (cie->z_aug) {
1358                 p += dwarf_read_uleb128(ri, p, &utmp,
1359                                         secid, &err);
1360                 if (err)
1361                         return err;
1362
1363                 p += utmp;
1364         }
1365
1366         if (p > end) {
1367                 pr_err_once("%s: error: incorrect fde\n", __func__);
1368                 return -QUADD_URC_TBL_IS_CORRUPT;
1369         }
1370
1371         fde->insn_length = end - p;
1372
1373         if (fde->insn_length > 0)
1374                 fde->instructions = p;
1375         else
1376                 fde->instructions = NULL;
1377
1378         return 0;
1379 }
1380
1381 static const struct dw_fde_table *
1382 dwarf_bst_find_idx(unsigned long data_base,
1383                    struct dw_fde_table *fde_table,
1384                    unsigned long length,
1385                    unsigned long addr)
1386 {
1387         unsigned long initial_loc;
1388         struct dw_fde_table *start, *stop;
1389         struct dw_fde_table *mid = NULL;
1390
1391         if (unlikely(!length))
1392                 return NULL;
1393
1394         start = fde_table;
1395         stop = start + length - 1;
1396
1397         initial_loc = dw_bst_get_initial_loc(start, data_base);
1398         if (addr < initial_loc)
1399                 return NULL;
1400
1401         initial_loc = dw_bst_get_initial_loc(stop, data_base);
1402         if (addr >= initial_loc)
1403                 return NULL;
1404
1405         while (start < stop - 1) {
1406                 mid = start + ((stop - start) >> 1);
1407
1408                 initial_loc = dw_bst_get_initial_loc(mid, data_base);
1409
1410                 if (addr < initial_loc)
1411                         stop = mid;
1412                 else
1413                         start = mid;
1414         }
1415
1416         return start;
1417 }
1418
1419 static struct dw_fde_table *
1420 dwarf_get_bs_table(struct ex_region_info *ri,
1421                    void *data,
1422                    unsigned long length,
1423                    unsigned long data_base,
1424                    unsigned long *nr_entries,
1425                    int is_eh)
1426 {
1427         int count, secid_hdr;
1428         unsigned char *p, *end;
1429         struct dw_fde_table *bst;
1430         unsigned long fde_count, frame_ptr;
1431         struct dw_eh_frame_hdr *hdr = data;
1432
1433         if (length <= sizeof(*hdr))
1434                 return NULL;
1435
1436         end = data + length;
1437
1438         pr_debug("hdr: %p\n", hdr);
1439
1440         secid_hdr = get_secid_frame_hdr(is_eh);
1441
1442         if (hdr->version != 1) {
1443                 pr_warn_once("warning: unknown eh hdr format\n");
1444                 return NULL;
1445         }
1446         p = (unsigned char *)(hdr + 1);
1447
1448         if (hdr->eh_frame_ptr_enc != DW_EH_PE_omit) {
1449                 count = dwarf_read_encoded_value(ri, p, (void *)data_base,
1450                                                  &frame_ptr,
1451                                                  hdr->eh_frame_ptr_enc,
1452                                                  secid_hdr);
1453                 if (count < 0)
1454                         return NULL;
1455
1456                 p += count;
1457         }
1458
1459         if (hdr->fde_count_enc == DW_EH_PE_omit)
1460                 return NULL;
1461
1462         count = dwarf_read_encoded_value(ri, p, (void *)data_base,
1463                                          &fde_count, hdr->fde_count_enc,
1464                                          secid_hdr);
1465         if (count < 0)
1466                 return NULL;
1467
1468         p += count;
1469
1470         if (p >= end)
1471                 return NULL;
1472
1473         if (fde_count * sizeof(*bst) !=  end - p)
1474                 return NULL;
1475
1476         if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) {
1477                 pr_warn_once("warning: unknown eh hdr format\n");
1478                 return NULL;
1479         }
1480
1481         bst = (struct dw_fde_table *)p;
1482         *nr_entries = fde_count;
1483
1484         pr_debug("bst: %lu fde entries\n", fde_count);
1485
1486         return bst;
1487 }
1488
1489 static long
1490 dwarf_decode_fde_cie(struct ex_region_info *ri,
1491                      unsigned char *fde_p,
1492                      struct dw_cie *cie,
1493                      struct dw_fde *fde,
1494                      int is_eh)
1495 {
1496         u32 *p;
1497         int secid;
1498         long err;
1499         unsigned char *cie_p;
1500         unsigned long cie_pointer, length;
1501         unsigned char *frame_start;
1502         unsigned long frame_len, addr;
1503         struct extab_info *ti;
1504
1505         secid = get_secid_frame(is_eh);
1506         ti = &ri->ex_sec[secid];
1507
1508         addr = ti->addr;
1509
1510         frame_start = (unsigned char *)
1511                 ex_addr_to_mmap_addr(addr, ri, secid);
1512
1513         frame_len = ti->length;
1514
1515         pr_debug("frame: %p - %p\n",
1516                  frame_start, frame_start + frame_len);
1517
1518         p = (u32 *)fde_p;
1519
1520         length = read_mmap_data_u32(ri, p++, secid, &err);
1521         if (err)
1522                 return err;
1523
1524         if (length == 0xffffffff) {
1525                 pr_warn_once("warning: 64-bit frame is not supported\n");
1526                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
1527         }
1528
1529         fde->offset = fde_p - frame_start;
1530         fde->length = length + sizeof(u32);
1531
1532         pr_debug("FDE: fde_p: %p, offset: %#lx, len: %#lx\n",
1533                  fde_p, fde->offset, fde->length);
1534
1535         cie_pointer = read_mmap_data_u32(ri, p, secid, &err);
1536         if (err)
1537                 return err;
1538
1539         fde->cie_pointer = cie_pointer;
1540
1541         cie_p = is_eh ? (unsigned char *)p - cie_pointer :
1542                 frame_start + cie_pointer;
1543
1544         length = read_mmap_data_u32(ri, (u32 *)cie_p,
1545                                     secid, &err);
1546         if (err)
1547                 return err;
1548
1549         if (length == 0xffffffff) {
1550                 pr_warn_once("warning: 64-bit frame is not supported\n");
1551                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
1552         }
1553
1554         cie->offset = cie_p - frame_start;
1555         cie->length = length + sizeof(u32);
1556
1557         pr_debug("CIE: cie_p: %p, offset: %#lx, len: %#lx\n",
1558                  cie_p, cie->offset, cie->length);
1559
1560         err = decode_cie_entry(ri, cie, cie_p, cie->length, is_eh);
1561         if (err < 0)
1562                 return err;
1563
1564         fde->cie = cie;
1565
1566         err = decode_fde_entry(ri, fde, fde_p, fde->length, is_eh);
1567         if (err < 0)
1568                 return err;
1569
1570         return 0;
1571 }
1572
1573 static void *
1574 dwarf_find_fde(struct ex_region_info *ri,
1575                void *data,
1576                unsigned long length,
1577                unsigned long pc,
1578                int is_eh)
1579 {
1580         long err;
1581         int secid, secid_hdr;
1582         const struct dw_fde_table *fi;
1583         unsigned long fde_count = 0, data_base;
1584         unsigned long fde_addr, init_loc;
1585         struct dw_fde_table *bst;
1586         struct extab_info *ti;
1587
1588         secid = get_secid_frame(is_eh);
1589         secid_hdr = get_secid_frame_hdr(is_eh);
1590
1591         ti = &ri->ex_sec[secid_hdr];
1592         data_base = ti->addr;
1593
1594         bst = dwarf_get_bs_table(ri, data, length, data_base,
1595                                  &fde_count, is_eh);
1596         if (!bst || fde_count == 0) {
1597                 pr_warn_once("warning: bs_table\n");
1598                 return NULL;
1599         }
1600
1601         fi = &bst[fde_count - 1];
1602         init_loc = dw_bst_get_initial_loc(fi, data_base);
1603
1604         pr_debug("pc: %#lx, last bst init_loc: %#lx", pc, init_loc);
1605
1606         if (pc >= init_loc) {
1607                 unsigned long start, end;
1608                 struct extab_info *ti = &ri->ex_sec[secid];
1609
1610                 fde_addr = dw_bst_get_fde_addr(fi, data_base);
1611                 fde_addr = ex_addr_to_mmap_addr(fde_addr, ri,
1612                                                 secid);
1613
1614                 if (pc == init_loc)
1615                         return (void *)fde_addr;
1616
1617                 if (ti->tf_end > 0) {
1618                         start = ti->tf_start;
1619                         end = ti->tf_end;
1620                 } else {
1621                         struct dw_cie cie;
1622                         struct dw_fde fde;
1623
1624                         err = dwarf_decode_fde_cie(ri, (void *)fde_addr,
1625                                                    &cie, &fde, is_eh);
1626                         if (err < 0)
1627                                 return NULL;
1628
1629                         start = fde.initial_location;
1630                         end = start + fde.address_range;
1631
1632                         quadd_unwind_set_tail_info(ri->vm_start, secid,
1633                                                    start, end);
1634                 }
1635
1636                 pr_debug("pc: %#lx, last bst entry: %#lx - %#lx",
1637                          pc, start, end);
1638
1639                 return (pc >= start && pc < end) ?
1640                        (void *)fde_addr : NULL;
1641         }
1642
1643         fi = dwarf_bst_find_idx(data_base, bst, fde_count, pc);
1644         if (!fi)
1645                 return NULL;
1646
1647         fde_addr = dw_bst_get_fde_addr(fi, data_base);
1648         fde_addr = ex_addr_to_mmap_addr(fde_addr, ri, secid);
1649
1650         return (void *)fde_addr;
1651 }
1652
1653 static int
1654 __is_fde_entry_exist(struct ex_region_info *ri, unsigned long addr, int is_eh)
1655 {
1656         int secid_hdr;
1657         unsigned char *fde_p;
1658         struct extab_info *ti;
1659         unsigned char *hdr_start;
1660         unsigned long hdr_len, a;
1661
1662         secid_hdr = get_secid_frame_hdr(is_eh);
1663
1664         ti = &ri->ex_sec[secid_hdr];
1665
1666         a = ti->addr;
1667
1668         hdr_start = (unsigned char *)
1669                 ex_addr_to_mmap_addr(a, ri, secid_hdr);
1670
1671         hdr_len = ti->length;
1672
1673         fde_p = dwarf_find_fde(ri, hdr_start, hdr_len, addr, is_eh);
1674
1675         return fde_p ? 1 : 0;
1676 }
1677
1678 static int
1679 is_fde_entry_exist(struct ex_region_info *ri,
1680                    unsigned long addr,
1681                    int *is_eh,
1682                    int *is_debug)
1683 {
1684         *is_eh = 0;
1685         *is_debug = 0;
1686
1687         if (is_frame_present(ri, 1)) {
1688                 if (__is_fde_entry_exist(ri, addr, 1))
1689                         *is_eh = 1;
1690         }
1691
1692         if (is_frame_present(ri, 0)) {
1693                 if (__is_fde_entry_exist(ri, addr, 0))
1694                         *is_debug = 1;
1695         }
1696
1697         return (*is_eh || *is_debug) ? 1 : 0;
1698 }
1699
1700 static long
1701 dwarf_decode(struct ex_region_info *ri,
1702              struct dw_cie *cie,
1703              struct dw_fde *fde,
1704              unsigned long pc,
1705              int is_eh)
1706 {
1707         long err;
1708         int secid_hdr;
1709         unsigned char *fde_p;
1710         unsigned char *hdr_start;
1711         unsigned long hdr_len, addr;
1712         struct extab_info *ti;
1713
1714         secid_hdr = get_secid_frame_hdr(is_eh);
1715         ti = &ri->ex_sec[secid_hdr];
1716
1717         addr = ti->addr;
1718
1719         hdr_start = (unsigned char *)
1720                 ex_addr_to_mmap_addr(addr, ri, secid_hdr);
1721
1722         hdr_len = ti->length;
1723
1724         pr_debug("eh frame hdr: %p - %p\n",
1725                  hdr_start, hdr_start + hdr_len);
1726
1727         fde_p = dwarf_find_fde(ri, hdr_start, hdr_len, pc, is_eh);
1728         if (!fde_p)
1729                 return -QUADD_URC_IDX_NOT_FOUND;
1730
1731         err = dwarf_decode_fde_cie(ri, fde_p, cie, fde, is_eh);
1732         if (err < 0)
1733                 return err;
1734
1735         if (pc < fde->initial_location ||
1736             pc >= fde->initial_location + fde->address_range) {
1737                 pr_debug("pc is not in range: %#lx - %#lx\n",
1738                          fde->initial_location,
1739                          fde->initial_location + fde->address_range);
1740                 return -QUADD_URC_IDX_NOT_FOUND;
1741         }
1742
1743         return 0;
1744 }
1745
1746 static long def_cfa(struct stackframe *sf, struct regs_state *rs)
1747 {
1748         int reg = rs->cfa_register;
1749
1750         if (reg >= 0) {
1751                 if (reg >= QUADD_NUM_REGS)
1752                         return -QUADD_URC_TBL_IS_CORRUPT;
1753
1754                 pr_debug("r%d --> cfa (%#lx)\n", reg, sf->cfa);
1755                 sf->cfa = sf->vregs[reg];
1756         }
1757
1758         sf->cfa += rs->cfa_offset;
1759         pr_debug("cfa += %#lx (%#lx)\n", rs->cfa_offset, sf->cfa);
1760
1761         return 0;
1762 }
1763
1764 static long
1765 unwind_frame(struct ex_region_info *ri,
1766              struct stackframe *sf,
1767              struct vm_area_struct *vma_sp,
1768              int is_eh)
1769 {
1770         int i, num_regs;
1771         long err;
1772         unsigned char *insn_end;
1773         unsigned long addr, return_addr, val, user_reg_size;
1774         struct dw_fde fde;
1775         struct dw_cie cie;
1776         unsigned long pc = sf->pc;
1777         struct regs_state *rs, *rs_initial;
1778         int mode = sf->mode;
1779
1780         err = dwarf_decode(ri, &cie, &fde, pc, is_eh);
1781         if (err < 0)
1782                 return err;
1783
1784         sf->pc = fde.initial_location;
1785
1786         rs = &sf->rs;
1787         rs_initial = &sf->rs_initial;
1788
1789         rs->cfa_register = -1;
1790         rs_initial->cfa_register = -1;
1791
1792         rules_cleanup(rs, mode);
1793
1794         if (cie.initial_insn) {
1795                 insn_end = cie.initial_insn + cie.initial_insn_len;
1796                 err = dwarf_cfa_exec_insns(ri, cie.initial_insn,
1797                                            insn_end, &cie, sf, pc, is_eh);
1798                 if (err)
1799                         return err;
1800         }
1801
1802         memcpy(rs_initial, rs, sizeof(*rs));
1803
1804         if (fde.instructions) {
1805                 insn_end = fde.instructions + fde.insn_length;
1806                 err = dwarf_cfa_exec_insns(ri, fde.instructions,
1807                                            insn_end, fde.cie, sf, pc, is_eh);
1808                 if (err)
1809                         return err;
1810         }
1811
1812         pr_debug("mode: %s\n", (mode == DW_MODE_ARM32) ? "arm32" : "arm64");
1813         pr_debug("initial cfa: %#lx\n", sf->cfa);
1814
1815         user_reg_size = get_user_reg_size(mode);
1816
1817         err = def_cfa(sf, rs);
1818         if (err < 0)
1819                 return err;
1820
1821         pr_debug("pc: %#lx, exec pc: %#lx, lr: %#lx\n",
1822                  pc, sf->pc, sf->vregs[regnum_lr(mode)]);
1823
1824         pr_debug("sp: %#lx, fp: %#lx, fp_thumb: %#lx\n",
1825                  sf->vregs[regnum_sp(mode)],
1826                  sf->vregs[regnum_fp(mode)],
1827                  sf->vregs[ARM32_FP_THUMB]);
1828
1829         pr_debug("lr rule: %#lx/%ld (where: %u)\n",
1830                  rs->reg[regnum_lr(mode)].loc.reg,
1831                  rs->reg[regnum_lr(mode)].loc.offset,
1832                  rs->reg[regnum_lr(mode)].where);
1833
1834         pr_debug("fp rule: %#lx/%ld (where: %u)\n",
1835                  rs->reg[regnum_fp(mode)].loc.reg,
1836                  rs->reg[regnum_fp(mode)].loc.offset,
1837                  rs->reg[regnum_fp(mode)].where);
1838
1839         pr_debug("fp_thumb rule: %#lx/%ld (where: %u)\n",
1840                  rs->reg[ARM32_FP_THUMB].loc.reg,
1841                  rs->reg[ARM32_FP_THUMB].loc.offset,
1842                  rs->reg[ARM32_FP_THUMB].where);
1843
1844         pr_debug("cfa_offset: %ld (%#lx)\n",
1845                  rs->cfa_offset, rs->cfa_offset);
1846         pr_debug("cfa_register: %u\n", rs->cfa_register);
1847         pr_debug("new cfa: %#lx\n", sf->cfa);
1848
1849         num_regs = (mode == DW_MODE_ARM32) ?
1850                 QUADD_AARCH32_REGISTERS :
1851                 QUADD_AARCH64_REGISTERS;
1852
1853         for (i = 0; i < num_regs; i++) {
1854                 switch (rs->reg[i].where) {
1855                 case DW_WHERE_UNDEF:
1856                         break;
1857
1858                 case DW_WHERE_SAME:
1859                         break;
1860
1861                 case DW_WHERE_CFAREL:
1862                         addr = sf->cfa + rs->reg[i].loc.offset;
1863
1864                         if (!validate_stack_addr(addr, vma_sp, user_reg_size))
1865                                 return -QUADD_URC_SP_INCORRECT;
1866
1867                         if (mode == DW_MODE_ARM32)
1868                                 err = read_user_data((u32 __user *)addr, val);
1869                         else
1870                                 err = read_user_data((unsigned long __user *)
1871                                                      addr, val);
1872
1873                         if (err < 0)
1874                                 return err;
1875
1876                         sf->vregs[i] = val;
1877                         pr_debug("[r%d] DW_WHERE_CFAREL: new val: %#lx\n",
1878                                  i, val);
1879
1880                         break;
1881
1882                 default:
1883                         pr_err_once("[r%d] error: unsupported rule (%d)\n",
1884                                     i, rs->reg[i].where);
1885                         break;
1886                 }
1887         }
1888
1889         return_addr = sf->vregs[regnum_lr(mode)];
1890         pr_debug("return_addr: %#lx\n", return_addr);
1891
1892         if (!validate_pc_addr(return_addr, user_reg_size))
1893                 return -QUADD_URC_PC_INCORRECT;
1894
1895         sf->pc = return_addr;
1896         sf->vregs[regnum_sp(mode)] = sf->cfa;
1897
1898         return 0;
1899 }
1900
1901 static void
1902 unwind_backtrace(struct quadd_callchain *cc,
1903                  struct ex_region_info *ri,
1904                  struct stackframe *sf,
1905                  struct vm_area_struct *vma_sp,
1906                  struct task_struct *task)
1907 {
1908         unsigned long user_reg_size;
1909         struct ex_region_info ri_new;
1910         unsigned int unw_type;
1911         int is_eh = 1, mode = sf->mode;
1912
1913         cc->urc_dwarf = QUADD_URC_FAILURE;
1914         user_reg_size = get_user_reg_size(mode);
1915
1916         while (1) {
1917                 long sp, err;
1918                 int nr_added;
1919                 int __is_eh, __is_debug;
1920                 struct vm_area_struct *vma_pc;
1921                 unsigned long addr, where = sf->pc;
1922                 struct mm_struct *mm = task->mm;
1923
1924                 if (!mm)
1925                         break;
1926
1927                 sp = sf->vregs[regnum_sp(mode)];
1928
1929                 if (!validate_stack_addr(sp, vma_sp, user_reg_size)) {
1930                         cc->urc_dwarf = QUADD_URC_SP_INCORRECT;
1931                         break;
1932                 }
1933
1934                 vma_pc = find_vma(mm, sf->pc);
1935                 if (!vma_pc)
1936                         break;
1937
1938                 addr = ri->vm_start;
1939
1940                 if (!is_vma_addr(addr, vma_pc, user_reg_size)) {
1941                         err = quadd_get_dw_frames(vma_pc->vm_start, &ri_new);
1942                         if (err) {
1943                                 cc->urc_dwarf = QUADD_URC_TBL_NOT_EXIST;
1944                                 break;
1945                         }
1946
1947                         pr_debug("ri: %#lx ---> %#lx",
1948                                  ri->vm_start, ri_new.vm_start);
1949
1950                         ri = &ri_new;
1951                 }
1952
1953                 if (!is_fde_entry_exist(ri, sf->pc, &__is_eh, &__is_debug)) {
1954                         pr_debug("eh/debug fde entries are not existed\n");
1955                         cc->urc_dwarf = QUADD_URC_IDX_NOT_FOUND;
1956                         break;
1957                 }
1958                 pr_debug("is_eh: %d, is_debug: %d\n", __is_eh, __is_debug);
1959
1960                 if (is_eh) {
1961                         if (!__is_eh)
1962                                 is_eh = 0;
1963                 } else {
1964                         if (!__is_debug)
1965                                 is_eh = 1;
1966                 }
1967
1968                 err = unwind_frame(ri, sf, vma_sp, is_eh);
1969                 if (err < 0) {
1970                         if (__is_eh && __is_debug) {
1971                                 is_eh ^= 1;
1972
1973                                 err = unwind_frame(ri, sf, vma_sp, is_eh);
1974                                 if (err < 0) {
1975                                         cc->urc_dwarf = -err;
1976                                         break;
1977                                 }
1978                         } else {
1979                                 cc->urc_dwarf = -err;
1980                                 break;
1981                         }
1982                 }
1983
1984                 unw_type = is_eh ? QUADD_UNW_TYPE_DWARF_EH :
1985                                    QUADD_UNW_TYPE_DWARF_DF;
1986
1987                 pr_debug("[%s]: function at [<%08lx>] from [<%08lx>]\n",
1988                          is_eh ? "eh" : "debug", where, sf->pc);
1989
1990                 cc->curr_sp = sf->vregs[regnum_sp(mode)];
1991
1992                 cc->curr_fp = sf->vregs[regnum_fp(mode)];
1993                 if (mode == DW_MODE_ARM32)
1994                         cc->curr_fp_thumb = sf->vregs[ARM32_FP_THUMB];
1995
1996                 cc->curr_pc = sf->pc;
1997                 cc->curr_lr = sf->vregs[regnum_lr(mode)];
1998
1999                 nr_added = quadd_callchain_store(cc, sf->pc, unw_type);
2000                 if (nr_added == 0)
2001                         break;
2002         }
2003 }
2004
2005 int
2006 quadd_is_ex_entry_exist_dwarf(struct pt_regs *regs,
2007                               unsigned long addr,
2008                               struct task_struct *task)
2009 {
2010         long err;
2011         int is_eh, is_debug;
2012         struct ex_region_info ri;
2013         struct vm_area_struct *vma;
2014         struct mm_struct *mm = task->mm;
2015
2016         if (!regs || !mm)
2017                 return 0;
2018
2019         vma = find_vma(mm, addr);
2020         if (!vma)
2021                 return 0;
2022
2023         err = quadd_get_dw_frames(vma->vm_start, &ri);
2024         if (err)
2025                 return 0;
2026
2027         return is_fde_entry_exist(&ri, addr, &is_eh, &is_debug);
2028 }
2029
2030 unsigned int
2031 quadd_get_user_cc_dwarf(struct pt_regs *regs,
2032                         struct quadd_callchain *cc,
2033                         struct task_struct *task)
2034 {
2035         long err;
2036         int mode, nr_prev = cc->nr;
2037         unsigned long ip, lr, sp, fp, fp_thumb;
2038         struct vm_area_struct *vma, *vma_sp;
2039         struct mm_struct *mm = task->mm;
2040         struct ex_region_info ri;
2041         struct stackframe *sf;
2042         struct dwarf_cpu_context *cpu_ctx = this_cpu_ptr(ctx.cpu_ctx);
2043
2044         if (!regs || !mm)
2045                 return 0;
2046
2047         if (cc->urc_dwarf == QUADD_URC_LEVEL_TOO_DEEP)
2048                 return nr_prev;
2049
2050         cc->urc_dwarf = QUADD_URC_FAILURE;
2051
2052         if (nr_prev > 0) {
2053                 ip = cc->curr_pc;
2054                 sp = cc->curr_sp;
2055                 fp = cc->curr_fp;
2056                 fp_thumb = cc->curr_fp_thumb;
2057                 lr = cc->curr_lr;
2058         } else {
2059                 ip = instruction_pointer(regs);
2060                 lr = quadd_user_link_register(regs);
2061                 sp = quadd_user_stack_pointer(regs);
2062
2063 #ifdef CONFIG_ARM64
2064                 if (compat_user_mode(regs)) {
2065                         fp = regs->compat_usr(ARM32_FP);
2066                         fp_thumb = regs->compat_usr(ARM32_FP_THUMB);
2067                 } else {
2068                         fp = regs->regs[ARM64_FP];
2069                         fp_thumb = 0;
2070                 }
2071 #else
2072                 fp = regs->ARM_fp;
2073                 fp_thumb = regs->ARM_r7;
2074 #endif
2075         }
2076
2077 #ifdef CONFIG_ARM64
2078         mode = compat_user_mode(regs) ?
2079                 DW_MODE_ARM32 : DW_MODE_ARM64;
2080 #else
2081         mode = DW_MODE_ARM32;
2082 #endif
2083
2084         pr_debug("%s: pc: %#lx, lr: %#lx\n", __func__, ip, lr);
2085         pr_debug("%s: sp: %#lx, fp: %#lx, fp_thumb: %#lx\n",
2086                  __func__, sp, fp, fp_thumb);
2087
2088         sf = &cpu_ctx->sf;
2089
2090         sf->vregs[regnum_lr(mode)] = lr;
2091         sf->pc = ip;
2092
2093         sf->vregs[regnum_sp(mode)] = sp;
2094         sf->vregs[regnum_fp(mode)] = fp;
2095
2096         if (mode == DW_MODE_ARM32)
2097                 sf->vregs[ARM32_FP_THUMB] = fp_thumb;
2098
2099         cpu_ctx->dw_ptr_size = (mode == DW_MODE_ARM32) ?
2100                                 sizeof(u32) : sizeof(u64);
2101
2102         sf->mode = mode;
2103         sf->cfa = 0;
2104
2105         vma = find_vma(mm, ip);
2106         if (!vma)
2107                 return 0;
2108
2109         vma_sp = find_vma(mm, sp);
2110         if (!vma_sp)
2111                 return 0;
2112
2113         err = quadd_get_dw_frames(vma->vm_start, &ri);
2114         if (err) {
2115                 cc->urc_dwarf = QUADD_URC_TBL_NOT_EXIST;
2116                 return 0;
2117         }
2118
2119         unwind_backtrace(cc, &ri, sf, vma_sp, task);
2120
2121         pr_debug("%s: mode: %s, cc->nr: %d --> %d\n", __func__,
2122                  (mode == DW_MODE_ARM32) ? "arm32" : "arm64",
2123                  nr_prev, cc->nr);
2124
2125         return cc->nr;
2126 }
2127
2128 int quadd_dwarf_unwind_start(void)
2129 {
2130         if (!atomic_cmpxchg(&ctx.started, 0, 1)) {
2131                 ctx.cpu_ctx = alloc_percpu(struct dwarf_cpu_context);
2132                 if (!ctx.cpu_ctx) {
2133                         atomic_set(&ctx.started, 0);
2134                         return -ENOMEM;
2135                 }
2136         }
2137
2138         return 0;
2139 }
2140
2141 void quadd_dwarf_unwind_stop(void)
2142 {
2143         if (atomic_cmpxchg(&ctx.started, 1, 0))
2144                 free_percpu(ctx.cpu_ctx);
2145 }
2146
2147 int quadd_dwarf_unwind_init(void)
2148 {
2149         atomic_set(&ctx.started, 0);
2150         return 0;
2151 }