4a55b8e6867ec6873463e50da8db782e2dcf124d
[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_reg(struct regs_state *rs, int regnum, int where, unsigned long reg)
443 {
444         struct reg_info *r;
445
446         if (!validate_regnum(rs, regnum))
447                 return;
448
449         r = &rs->reg[regnum];
450
451         r->where = where;
452         r->loc.reg = reg;
453 }
454
455 static inline void
456 set_rule_exp(struct regs_state *rs, int regnum,
457              int where, const unsigned char *exp)
458 {
459         struct reg_info *r;
460
461         if (!validate_regnum(rs, regnum))
462                 return;
463
464         r = &rs->reg[regnum];
465
466         r->where = where;
467         r->loc.exp = exp;
468 }
469
470 static inline void
471 set_rule(struct regs_state *rs, int regnum, int where, long value)
472 {
473         set_rule_offset(rs, regnum, where, value);
474 }
475
476 static inline unsigned long
477 dw_bst_get_initial_loc(const struct dw_fde_table *fi,
478                        unsigned long data_base)
479 {
480         return data_base + fi->initial_loc;
481 }
482
483 static inline unsigned long
484 dw_bst_get_fde_addr(const struct dw_fde_table *fi,
485                     unsigned long data_base)
486 {
487         return data_base + fi->fde;
488 }
489
490 static inline unsigned long
491 dwarf_read_uleb128(struct ex_region_info *ri,
492                    unsigned char *addr,
493                    unsigned long *ret,
494                    int st,
495                    long *err)
496 {
497         unsigned long result;
498         unsigned char byte;
499         int shift, count;
500
501         result = 0;
502         shift = 0;
503         count = 0;
504
505         while (1) {
506                 byte = read_mmap_data_u8(ri, addr, st, err);
507                 if (*err)
508                         return 0;
509
510                 addr++;
511                 count++;
512
513                 result |= (byte & 0x7f) << shift;
514                 shift += 7;
515
516                 if (!(byte & 0x80))
517                         break;
518         }
519
520         *ret = result;
521
522         return count;
523 }
524
525 static inline unsigned long
526 dwarf_read_sleb128(struct ex_region_info *ri,
527                    unsigned char *addr,
528                    long *ret,
529                    int st,
530                    long *err)
531 {
532         unsigned char byte;
533         long result, shift;
534         int num_bits;
535         int count;
536
537         result = 0;
538         shift = 0;
539         count = 0;
540
541         while (1) {
542                 byte = read_mmap_data_u8(ri, addr, st, err);
543                 if (*err)
544                         return 0;
545
546                 addr++;
547                 result |= (byte & 0x7f) << shift;
548                 shift += 7;
549                 count++;
550
551                 if (!(byte & 0x80))
552                         break;
553         }
554
555         num_bits = 8 * sizeof(result);
556
557         if ((shift < num_bits) && (byte & 0x40))
558                 result |= (-1 << shift);
559
560         *ret = result;
561
562         return count;
563 }
564
565 static inline unsigned int
566 dw_cfa_opcode(unsigned int insn)
567 {
568         return insn & 0xc0;
569 }
570
571 static inline unsigned int
572 dw_cfa_operand(unsigned int insn)
573 {
574         return insn & 0x3f;
575 }
576
577 static void
578 rules_cleanup(struct regs_state *rs, int mode)
579 {
580         int i, num_regs;
581
582         num_regs = (mode == DW_MODE_ARM32) ?
583                 QUADD_AARCH32_REGISTERS :
584                 QUADD_AARCH64_REGISTERS;
585
586         for (i = 0; i < num_regs; i++)
587                 set_rule(rs, i, DW_WHERE_UNDEF, 0);
588 }
589
590 static int
591 dwarf_read_encoded_value(struct ex_region_info *ri,
592                          void *addr,
593                          void *pcrel_base,
594                          unsigned long *val,
595                          char encoding,
596                          int st)
597 {
598         int dw_ptr_size, count = 0;
599         long stmp = 0, err = 0;
600         unsigned long utmp, res = 0;
601         struct dwarf_cpu_context *cpu_ctx = this_cpu_ptr(ctx.cpu_ctx);
602
603         pr_debug("encoding: %#x\n", encoding);
604
605         dw_ptr_size = cpu_ctx->dw_ptr_size;
606
607         if (encoding == DW_EH_PE_omit) {
608                 pr_debug("DW_EH_PE_omit\n");
609
610                 *val = 0;
611                 return 0;
612         } else if (encoding == DW_EH_PE_aligned) {
613                 unsigned long aligned = ALIGN((unsigned long)addr,
614                                               dw_ptr_size);
615
616                 pr_debug("DW_EH_PE_aligned\n");
617
618                 if (dw_ptr_size == 4) {
619                         *val = read_mmap_data_u32(ri, (u32 *)aligned, st, &err);
620                 } else if (dw_ptr_size == 8) {
621                         *val = read_mmap_data_u64(ri, (u64 *)aligned, st, &err);
622                 } else {
623                         pr_err_once("%s: error: encoding\n", __func__);
624                         return -QUADD_URC_TBL_IS_CORRUPT;
625                 }
626
627                 if (err)
628                         return err;
629
630                 return dw_ptr_size;
631         }
632
633         switch (encoding & 0x0f) {
634         case DW_EH_PE_absptr:
635                 pr_debug("%s: absptr encoding\n", __func__);
636
637                 if (dw_ptr_size == 4) {
638                         *val = read_mmap_data_u32(ri, (u32 *)addr, st, &err);
639                 } else if (dw_ptr_size == 8) {
640                         *val = read_mmap_data_u64(ri, (u64 *)addr, st, &err);
641                 } else {
642                         pr_err_once("error: wrong dwarf size\n");
643                         return -QUADD_URC_UNHANDLED_INSTRUCTION;
644                 }
645
646                 if (err)
647                         return err;
648
649                 return dw_ptr_size;
650
651         case DW_EH_PE_sdata2:
652         case DW_EH_PE_udata2:
653                 pr_debug("encoding: DW_EH_PE_sdata2\n");
654                 stmp = read_mmap_data_s16(ri, (s16 *)addr, st, &err);
655                 if (err)
656                         return err;
657
658                 count += sizeof(s16);
659                 break;
660
661         case DW_EH_PE_sdata4:
662         case DW_EH_PE_udata4:
663                 pr_debug("encoding: DW_EH_PE_udata4/sdata4\n");
664                 stmp = read_mmap_data_s32(ri, (s32 *)addr, st, &err);
665                 if (err)
666                         return err;
667
668                 count += sizeof(s32);
669                 break;
670
671         case DW_EH_PE_sdata8:
672         case DW_EH_PE_udata8:
673                 pr_debug("encoding: DW_EH_PE_udata8\n");
674                 stmp = read_mmap_data_s64(ri, (s64 *)addr, st, &err);
675                 if (err)
676                         return err;
677
678                 count += sizeof(s64);
679                 break;
680
681         case DW_EH_PE_uleb128:
682                 pr_debug("encoding: DW_EH_PE_uleb128\n");
683                 count += dwarf_read_uleb128(ri, addr, &utmp, st, &err);
684                 if (err)
685                         return err;
686
687                 stmp = utmp;
688                 break;
689
690         case DW_EH_PE_sleb128:
691                 pr_debug("encoding: DW_EH_PE_sleb128\n");
692                 count += dwarf_read_sleb128(ri, addr, &stmp, st, &err);
693                 if (err)
694                         return err;
695
696                 break;
697
698         default:
699                 pr_warn_once("%s: warning: encoding: %#x\n",
700                              __func__, encoding & 0x0f);
701                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
702         }
703
704         switch (encoding & 0x70) {
705         case DW_EH_PE_absptr:
706                 pr_debug("DW_EH_PE_absptr\n");
707                 res = stmp;
708                 break;
709
710         case DW_EH_PE_pcrel:
711                 pr_debug("DW_EH_PE_pcrel, pcrel_base: %p, stmp: %ld\n",
712                          pcrel_base, stmp);
713                 res = (unsigned long)pcrel_base + stmp;
714                 break;
715
716         case DW_EH_PE_textrel:
717                 pr_warn_once("warning: DW_EH_PE_textrel\n");
718                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
719
720         case DW_EH_PE_datarel:
721                 pr_warn_once("warning: DW_EH_PE_datarel\n");
722                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
723
724         case DW_EH_PE_funcrel:
725                 pr_warn_once("warning: DW_EH_PE_funcrel\n");
726                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
727
728         default:
729                 pr_warn_once("%s: warning: encoding: %#x\n",
730                              __func__, encoding & 0x70);
731                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
732         }
733
734         if (res != 0) {
735                 if (encoding & DW_EH_PE_indirect) {
736                         pr_debug("DW_EH_PE_indirect\n");
737
738                         if (dw_ptr_size == 4) {
739                                 res = read_mmap_data_u32(ri, (u32 *)res,
740                                                          st, &err);
741                         } else if (dw_ptr_size == 8) {
742                                 res = read_mmap_data_u64(ri, (u64 *)res,
743                                                          st, &err);
744                         } else {
745                                 pr_err_once("error: wrong dwarf size\n");
746                                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
747                         }
748
749                         /* we ignore links to unloaded sections */
750                         if (err)
751                                 res = 0;
752                 }
753         }
754
755         *val = res;
756
757         return count;
758 }
759
760 static long
761 dwarf_cfa_exec_insns(struct ex_region_info *ri,
762                      unsigned char *insn_start,
763                      unsigned char *insn_end,
764                      struct dw_cie *cie,
765                      struct stackframe *sf,
766                      unsigned long pc,
767                      int is_eh)
768 {
769         unsigned char insn;
770         unsigned char *c_insn;
771         unsigned int expr_len, delta, secid;
772         unsigned long utmp, reg;
773         long offset, stmp, err = 0;
774         struct regs_state *rs, *rs_initial, *rs_stack;
775         struct dwarf_cpu_context *cpu_ctx = this_cpu_ptr(ctx.cpu_ctx);
776
777         secid = get_secid_frame(is_eh);
778
779         rs = &sf->rs;
780         rs_initial = &sf->rs_initial;
781
782         rs_stack = cpu_ctx->rs_stack;
783         cpu_ctx->depth = 0;
784
785         c_insn = insn_start;
786
787         while (c_insn < insn_end && sf->pc <= pc) {
788                 insn = read_mmap_data_u8(ri, c_insn++,
789                                          secid, &err);
790                 if (err)
791                         return err;
792
793                 switch (dw_cfa_opcode(insn)) {
794                 case DW_CFA_advance_loc:
795                         delta = dw_cfa_operand(insn);
796                         delta *= cie->code_align_factor;
797                         sf->pc += delta;
798                         pr_debug("DW_CFA_advance_loc: pc: %#lx --> %#lx (delta: %#x)\n",
799                                 sf->pc - delta, sf->pc, delta);
800                         continue;
801
802                 case DW_CFA_offset:
803                         reg = dw_cfa_operand(insn);
804                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
805                                                      secid, &err);
806                         if (err)
807                                 return err;
808
809                         offset = utmp * cie->data_align_factor;
810                         set_rule_offset(rs, reg, DW_WHERE_CFAREL, offset);
811                         pr_debug("DW_CFA_offset: reg: r%lu, offset(addr): %#lx (%ld)\n",
812                                 reg, offset, offset);
813                         continue;
814
815                 case DW_CFA_restore:
816                         reg = dw_cfa_operand(insn);
817
818                         if (!validate_regnum(rs, reg))
819                                 break;
820
821                         rs->reg[reg] = rs_initial->reg[reg];
822                         pr_debug("DW_CFA_restore: reg: r%lu\n", reg);
823                         continue;
824                 }
825
826                 switch (insn) {
827                 case DW_CFA_nop:
828                         pr_debug("DW_CFA_nop\n");
829                         continue;
830
831                 case DW_CFA_advance_loc1:
832                         delta = read_mmap_data_u8(ri, c_insn++,
833                                                   secid, &err);
834                         if (err)
835                                 return err;
836
837                         sf->pc += delta * cie->code_align_factor;
838                         pr_debug("DW_CFA_advance_loc1: pc: %#lx --> %#lx (delta: %#lx)\n",
839                                 sf->pc - delta * cie->code_align_factor, sf->pc,
840                                 delta * cie->code_align_factor);
841                         break;
842
843                 case DW_CFA_advance_loc2:
844                         delta = read_mmap_data_u16(ri, (u16 *)c_insn,
845                                                    secid, &err);
846                         if (err)
847                                 return err;
848
849                         c_insn += 2;
850                         sf->pc += delta * cie->code_align_factor;
851                         pr_debug("DW_CFA_advance_loc2: pc: %#lx --> %#lx (delta: %#lx)\n",
852                                 sf->pc - delta * cie->code_align_factor, sf->pc,
853                                 delta * cie->code_align_factor);
854                         break;
855
856                 case DW_CFA_advance_loc4:
857                         delta = read_mmap_data_u32(ri, (u32 *)c_insn,
858                                                    secid, &err);
859                         if (err)
860                                 return err;
861
862                         c_insn += 4;
863                         sf->pc += delta * cie->code_align_factor;
864                         pr_debug("DW_CFA_advance_loc4: pc: %#lx --> %#lx (delta: %#lx)\n",
865                                 sf->pc - delta * cie->code_align_factor, sf->pc,
866                                 delta * cie->code_align_factor);
867                         break;
868
869                 case DW_CFA_offset_extended:
870                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
871                                                      secid, &err);
872                         if (err)
873                                 return err;
874
875                         reg = utmp;
876                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
877                                                      secid, &err);
878                         if (err)
879                                 return err;
880
881                         offset = utmp * cie->data_align_factor;
882                         pr_debug("DW_CFA_offset_extended: reg: r%lu, offset: %#lx\n",
883                                  reg, offset);
884                         break;
885
886                 case DW_CFA_restore_extended:
887                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
888                                                      secid, &err);
889                         if (err)
890                                 return err;
891
892                         pr_debug("DW_CFA_restore_extended: reg: r%lu\n", reg);
893                         break;
894
895                 case DW_CFA_undefined:
896                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
897                                                      secid, &err);
898                         if (err)
899                                 return err;
900
901                         set_rule(rs, reg, DW_WHERE_UNDEF, 0);
902                         pr_debug("DW_CFA_undefined: reg: r%lu\n", reg);
903                         break;
904
905                 case DW_CFA_def_cfa:
906                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
907                                                      secid, &err);
908                         if (err)
909                                 return err;
910
911                         rs->cfa_register = utmp;
912                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
913                                                      secid, &err);
914                         if (err)
915                                 return err;
916
917                         rs->cfa_offset = utmp;
918                         pr_debug("DW_CFA_def_cfa: cfa_register: r%u, cfa_offset: %ld (%#lx)\n",
919                                  rs->cfa_register, rs->cfa_offset,
920                                  rs->cfa_offset);
921                         break;
922
923                 case DW_CFA_def_cfa_register:
924                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
925                                                      secid, &err);
926                         if (err)
927                                 return err;
928
929                         rs->cfa_register = utmp;
930                         pr_debug("DW_CFA_def_cfa_register: cfa_register: r%u\n",
931                                rs->cfa_register);
932                         break;
933
934                 case DW_CFA_def_cfa_offset:
935                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
936                                                      secid, &err);
937                         if (err)
938                                 return err;
939
940                         rs->cfa_offset = utmp;
941                         pr_debug("DW_CFA_def_cfa_offset: cfa_offset: %ld (%#lx)\n",
942                                rs->cfa_offset, rs->cfa_offset);
943                         break;
944
945                 case DW_CFA_def_cfa_expression:
946                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
947                                                      secid, &err);
948                         if (err)
949                                 return err;
950
951                         expr_len = utmp;
952
953                         rs->cfa_expr = c_insn;
954                         rs->cfa_expr_len = expr_len;
955                         rs->cfa_how = DW_CFA_EXP;
956                         c_insn += expr_len;
957
958                         pr_debug("DW_CFA_def_cfa_expression: expr_len: %#x\n",
959                                  expr_len);
960                         break;
961
962                 case DW_CFA_expression:
963                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
964                                                      secid, &err);
965                         if (err)
966                                 return err;
967
968                         set_rule_exp(rs, reg, DW_WHERE_EXPR, c_insn);
969
970                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
971                                                      secid, &err);
972                         if (err)
973                                 return err;
974
975                         c_insn += utmp;
976
977                         pr_debug("DW_CFA_expression: reg: r%lu\n", reg);
978                         break;
979
980                 case DW_CFA_offset_extended_sf:
981                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
982                                                      secid, &err);
983                         if (err)
984                                 return err;
985
986                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
987                                                      secid, &err);
988                         if (err)
989                                 return err;
990
991                         offset = stmp * cie->data_align_factor;
992                         set_rule_offset(rs, reg, DW_WHERE_CFAREL, offset);
993                         pr_debug("DW_CFA_offset_extended_sf: reg: r%lu, offset: %#lx\n",
994                                  reg, offset);
995                         break;
996
997                 case DW_CFA_val_offset:
998                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
999                                                      secid, &err);
1000                         if (err)
1001                                 return err;
1002
1003                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1004                                                      secid, &err);
1005                         if (err)
1006                                 return err;
1007
1008                         offset = utmp * cie->data_align_factor;
1009                         set_rule_offset(rs, reg, DW_WHERE_VAL_OFFSET, offset);
1010                         pr_debug("DW_CFA_val_offset: reg: r%lu, offset(addr): %#lx\n",
1011                                  reg, offset);
1012                         break;
1013
1014                 case DW_CFA_val_offset_sf:
1015                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1016                                                      secid, &err);
1017                         if (err)
1018                                 return err;
1019
1020                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
1021                                                      secid, &err);
1022                         if (err)
1023                                 return err;
1024
1025                         offset = stmp * cie->data_align_factor;
1026                         set_rule_offset(rs, reg, DW_WHERE_VAL_OFFSET, offset);
1027                         pr_debug("DW_CFA_val_offset_sf: reg: r%lu, offset(addr): %#lx\n",
1028                                  reg, offset);
1029                         break;
1030
1031                 case DW_CFA_GNU_args_size:
1032                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1033                                                      secid, &err);
1034                         if (err)
1035                                 return err;
1036
1037                         pr_debug("DW_CFA_GNU_args_size: offset: %#lx\n", utmp);
1038                         break;
1039
1040                 case DW_CFA_GNU_negative_offset_extended:
1041                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1042                                                      secid, &err);
1043                         if (err)
1044                                 return err;
1045
1046                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1047                                                      secid, &err);
1048                         if (err)
1049                                 return err;
1050
1051                         offset = utmp * cie->data_align_factor;
1052                         set_rule_offset(rs, reg, DW_WHERE_CFAREL, -offset);
1053                         pr_debug("DW_CFA_GNU_negative_offset_extended: reg: r%lu, offset: %#lx\n",
1054                                  reg, offset);
1055                         break;
1056
1057                 case DW_CFA_remember_state:
1058                         pr_debug("DW_CFA_remember_state\n");
1059
1060                         if (cpu_ctx->depth >= DW_MAX_RS_STACK_DEPTH) {
1061                                 pr_warn_once("error: rs stack was overflowed\n");
1062                                 return 0;
1063                         }
1064
1065                         rs_stack[cpu_ctx->depth++] = *rs;
1066                         break;
1067
1068                 case DW_CFA_restore_state:
1069                         pr_debug("DW_CFA_restore_state\n");
1070
1071                         if (cpu_ctx->depth == 0) {
1072                                 pr_warn_once("error: rs stack error\n");
1073                                 return 0;
1074                         }
1075
1076                         *rs = rs_stack[--cpu_ctx->depth];
1077                         break;
1078
1079                 case DW_CFA_def_cfa_sf:
1080                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1081                                                      secid, &err);
1082                         if (err)
1083                                 return err;
1084
1085                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
1086                                                      secid, &err);
1087                         if (err)
1088                                 return err;
1089
1090                         rs->cfa_register = utmp;
1091                         rs->cfa_offset = stmp * cie->data_align_factor;
1092                         rs->cfa_how = DW_CFA_REG_OFFSET;
1093
1094                         pr_debug("DW_CFA_def_cfa_sf: cfa_register: r%u, cfa_offset: %ld (%#lx)\n",
1095                                 rs->cfa_register, rs->cfa_offset,
1096                                 rs->cfa_offset);
1097                         break;
1098
1099                 case DW_CFA_def_cfa_offset_sf:
1100                         c_insn += dwarf_read_sleb128(ri, c_insn, &stmp,
1101                                                      secid, &err);
1102                         if (err)
1103                                 return err;
1104
1105                         rs->cfa_offset = stmp * cie->data_align_factor;
1106                         pr_debug("DW_CFA_def_cfa_offset_sf: cfa_offset: %ld (%#lx)\n",
1107                                 rs->cfa_offset, rs->cfa_offset);
1108                         break;
1109
1110                 case DW_CFA_same_value:
1111                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1112                                                      secid, &err);
1113                         if (err)
1114                                 return err;
1115
1116                         set_rule(rs, reg, DW_WHERE_SAME, 0);
1117                         pr_debug("DW_CFA_same_value: reg: r%lu\n", reg);
1118                         break;
1119
1120                 case DW_CFA_val_expression:
1121                         c_insn += dwarf_read_uleb128(ri, c_insn, &reg,
1122                                                      secid, &err);
1123                         if (err)
1124                                 return err;
1125
1126                         set_rule_exp(rs, reg, DW_WHERE_VAL_EXPR, c_insn);
1127                         c_insn += dwarf_read_uleb128(ri, c_insn, &utmp,
1128                                                      secid, &err);
1129                         if (err)
1130                                 return err;
1131
1132                         c_insn += utmp;
1133                         pr_debug("DW_CFA_val_expression: reg: r%lu\n", reg);
1134                         break;
1135
1136                 default:
1137                         pr_warn_once("warning: unhandled dwarf instr %#x\n",
1138                                      insn);
1139                         break;
1140                 }
1141         }
1142
1143         return 0;
1144 }
1145
1146 static long
1147 decode_cie_entry(struct ex_region_info *ri,
1148                  struct dw_cie *cie,
1149                  unsigned char *entry,
1150                  size_t length,
1151                  int is_eh)
1152 {
1153         long err;
1154         unsigned long utmp;
1155         unsigned char *p, *end, *aug;
1156         unsigned int secid, cie_id;
1157         unsigned int cie_version, id, len, max_len;
1158
1159         secid = get_secid_frame(is_eh);
1160
1161         p = entry;
1162         end = entry + length;
1163
1164         p += sizeof(u32);
1165
1166         id = read_mmap_data_u32(ri, (u32 *)p, secid, &err);
1167         if (err)
1168                 return err;
1169
1170         p += sizeof(u32);
1171
1172         cie_id = is_eh ? 0 : DW_CIE_ID;
1173         if (id != cie_id) {
1174                 pr_err_once("error: incorrect cie_id");
1175                 return -QUADD_URC_TBL_IS_CORRUPT;
1176         }
1177
1178         cie_version = read_mmap_data_u8(ri, p++, secid, &err);
1179         if (err)
1180                 return err;
1181
1182         if (cie_version != 1 && cie_version != 3) {
1183                 pr_err_once("error: wrong cie_version: %u\n", cie_version);
1184                 return -QUADD_URC_TBL_IS_CORRUPT;
1185         }
1186
1187         if (p >= end)
1188                 return -QUADD_URC_TBL_IS_CORRUPT;
1189
1190         max_len = end - p - 1;
1191         len = strnlen((const char *)p, max_len);
1192         if (len == max_len)
1193                 return -QUADD_URC_TBL_IS_CORRUPT;
1194
1195         cie->aug_string = p;
1196         p += len + 1;
1197
1198         pr_debug("aug_string: %s\n", cie->aug_string);
1199
1200         p += dwarf_read_uleb128(ri, p, &cie->code_align_factor,
1201                                 secid, &err);
1202         if (err)
1203                 return err;
1204
1205         p += dwarf_read_sleb128(ri, p, &cie->data_align_factor,
1206                                 secid, &err);
1207         if (err)
1208                 return err;
1209
1210         if (cie_version == 1) {
1211                 cie->retaddr_reg = read_mmap_data_u8(ri, p++,
1212                                                      secid,
1213                                                      &err);
1214                 if (err)
1215                         return err;
1216         } else {
1217                 p += dwarf_read_uleb128(ri, p, &utmp,
1218                                         secid, &err);
1219                 if (err)
1220                         return err;
1221
1222                 cie->retaddr_reg = utmp;
1223         }
1224
1225         pr_debug("address column: %u\n", cie->retaddr_reg);
1226
1227         aug = cie->aug_string;
1228         cie->z_aug = 0;
1229
1230         cie->initial_insn = NULL;
1231         cie->initial_insn_len = 0;
1232
1233         if (*aug == 'z') {
1234                 p += dwarf_read_uleb128(ri, p, &cie->aug_size,
1235                                         secid, &err);
1236                 if (err)
1237                         return err;
1238
1239                 cie->initial_insn = p + cie->aug_size;
1240                 aug++;
1241
1242                 cie->z_aug = 1;
1243         }
1244
1245         cie->fde_encoding = 0;
1246         cie->lsda_encoding = DW_EH_PE_omit;
1247         cie->personality = NULL;
1248
1249         while (*aug != '\0') {
1250                 if (p >= end)
1251                         return -QUADD_URC_TBL_IS_CORRUPT;
1252
1253                 if (*aug == 'L') {
1254                         cie->lsda_encoding =
1255                                 read_mmap_data_u8(ri, p++,
1256                                                   secid,
1257                                                   &err);
1258                         if (err)
1259                                 return err;
1260
1261                         aug++;
1262                 } else if (*aug == 'R') {
1263                         cie->fde_encoding =
1264                                 read_mmap_data_u8(ri, p++,
1265                                                   secid,
1266                                                   &err);
1267                         if (err)
1268                                 return err;
1269
1270                         aug++;
1271                         pr_debug("fde_encoding: %#x\n", cie->fde_encoding);
1272                 } else if (*aug == 'P') {
1273                         int cnt;
1274                         void *pcrel_base;
1275                         unsigned char handler_encoding;
1276                         unsigned long personality;
1277
1278                         handler_encoding = *p++;
1279
1280                         pcrel_base = (void *)
1281                                 mmap_addr_to_ex_addr((unsigned long)p,
1282                                                      ri,
1283                                                      secid);
1284
1285                         cnt = dwarf_read_encoded_value(ri, p, pcrel_base,
1286                                                        &personality,
1287                                                        handler_encoding,
1288                                                        secid);
1289                         if (cnt < 0) {
1290                                 pr_err_once("%s: error: personality routine\n",
1291                                             __func__);
1292                                 return cnt;
1293                         }
1294                         p += cnt;
1295
1296                         pr_debug("personality: %#lx\n", personality);
1297                         cie->personality = (void *)personality;
1298                         aug++;
1299                 } else if (*aug == 'S') {
1300                         aug++;
1301                         pr_debug("%s: aug: S\n", __func__);
1302                 } else {
1303                         pr_warn_once("%s: warning: unknown aug\n", __func__);
1304                         return -QUADD_URC_UNHANDLED_INSTRUCTION;
1305                 }
1306         }
1307
1308         if (p > end) {
1309                 pr_err_once("%s: error: cie\n", __func__);
1310                 return -QUADD_URC_TBL_IS_CORRUPT;
1311         }
1312
1313         if (p == end)
1314                 return 0;
1315
1316         if (!cie->initial_insn)
1317                 cie->initial_insn = p;
1318
1319         cie->initial_insn_len = end - cie->initial_insn;
1320
1321         return 0;
1322 }
1323
1324 static long
1325 decode_fde_entry(struct ex_region_info *ri,
1326                  struct dw_fde *fde,
1327                  unsigned char *entry,
1328                  size_t length,
1329                  int is_eh)
1330 {
1331         int count, secid;
1332         long err = 0;
1333         unsigned long utmp;
1334         unsigned char *p, *end, *pcrel_base;
1335         struct dw_cie *cie = fde->cie;
1336
1337         secid = get_secid_frame(is_eh);
1338
1339         p = entry;
1340         end = entry + length;
1341
1342         p += sizeof(u32);
1343         p += sizeof(u32);
1344
1345         pcrel_base = (unsigned char *)
1346                 mmap_addr_to_ex_addr((unsigned long)p, ri, secid);
1347
1348         count = dwarf_read_encoded_value(ri, p, pcrel_base,
1349                                          &fde->initial_location,
1350                                          cie->fde_encoding,
1351                                          secid);
1352         if (count < 0)
1353                 return count;
1354
1355         p += count;
1356
1357         fde->address_range = read_mmap_data_u32(ri, (u32 *)p,
1358                                                 secid, &err);
1359         if (err)
1360                 return err;
1361
1362         p += sizeof(u32);
1363
1364         if (fde->initial_location < ri->vm_start)
1365                 fde->initial_location += ri->vm_start;
1366
1367         pr_debug("pcrel_base: %p\n", pcrel_base);
1368         pr_debug("init location: %#lx\n", fde->initial_location);
1369         pr_debug("address_range: %#lx\n", fde->address_range);
1370
1371         if (cie->z_aug) {
1372                 p += dwarf_read_uleb128(ri, p, &utmp,
1373                                         secid, &err);
1374                 if (err)
1375                         return err;
1376
1377                 p += utmp;
1378         }
1379
1380         if (p > end) {
1381                 pr_err_once("%s: error: incorrect fde\n", __func__);
1382                 return -QUADD_URC_TBL_IS_CORRUPT;
1383         }
1384
1385         fde->insn_length = end - p;
1386
1387         if (fde->insn_length > 0)
1388                 fde->instructions = p;
1389         else
1390                 fde->instructions = NULL;
1391
1392         return 0;
1393 }
1394
1395 static const struct dw_fde_table *
1396 dwarf_bst_find_idx(unsigned long data_base,
1397                    struct dw_fde_table *fde_table,
1398                    unsigned long length,
1399                    unsigned long addr)
1400 {
1401         unsigned long initial_loc;
1402         struct dw_fde_table *start, *stop;
1403         struct dw_fde_table *mid = NULL;
1404
1405         if (unlikely(!length))
1406                 return NULL;
1407
1408         start = fde_table;
1409         stop = start + length - 1;
1410
1411         initial_loc = dw_bst_get_initial_loc(start, data_base);
1412         if (addr < initial_loc)
1413                 return NULL;
1414
1415         initial_loc = dw_bst_get_initial_loc(stop, data_base);
1416         if (addr >= initial_loc)
1417                 return NULL;
1418
1419         while (start < stop - 1) {
1420                 mid = start + ((stop - start) >> 1);
1421
1422                 initial_loc = dw_bst_get_initial_loc(mid, data_base);
1423
1424                 if (addr < initial_loc)
1425                         stop = mid;
1426                 else
1427                         start = mid;
1428         }
1429
1430         return start;
1431 }
1432
1433 static struct dw_fde_table *
1434 dwarf_get_bs_table(struct ex_region_info *ri,
1435                    void *data,
1436                    unsigned long length,
1437                    unsigned long data_base,
1438                    unsigned long *nr_entries,
1439                    int is_eh)
1440 {
1441         int count, secid_hdr;
1442         unsigned char *p, *end;
1443         struct dw_fde_table *bst;
1444         unsigned long fde_count, frame_ptr;
1445         struct dw_eh_frame_hdr *hdr = data;
1446
1447         if (length <= sizeof(*hdr))
1448                 return NULL;
1449
1450         end = data + length;
1451
1452         pr_debug("hdr: %p\n", hdr);
1453
1454         secid_hdr = get_secid_frame_hdr(is_eh);
1455
1456         if (hdr->version != 1) {
1457                 pr_warn_once("warning: unknown eh hdr format\n");
1458                 return NULL;
1459         }
1460         p = (unsigned char *)(hdr + 1);
1461
1462         if (hdr->eh_frame_ptr_enc != DW_EH_PE_omit) {
1463                 count = dwarf_read_encoded_value(ri, p, (void *)data_base,
1464                                                  &frame_ptr,
1465                                                  hdr->eh_frame_ptr_enc,
1466                                                  secid_hdr);
1467                 if (count < 0)
1468                         return NULL;
1469
1470                 p += count;
1471         }
1472
1473         if (hdr->fde_count_enc == DW_EH_PE_omit)
1474                 return NULL;
1475
1476         count = dwarf_read_encoded_value(ri, p, (void *)data_base,
1477                                          &fde_count, hdr->fde_count_enc,
1478                                          secid_hdr);
1479         if (count < 0)
1480                 return NULL;
1481
1482         p += count;
1483
1484         if (p >= end)
1485                 return NULL;
1486
1487         if (fde_count * sizeof(*bst) !=  end - p)
1488                 return NULL;
1489
1490         if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) {
1491                 pr_warn_once("warning: unknown eh hdr format\n");
1492                 return NULL;
1493         }
1494
1495         bst = (struct dw_fde_table *)p;
1496         *nr_entries = fde_count;
1497
1498         pr_debug("bst: %lu fde entries\n", fde_count);
1499
1500         return bst;
1501 }
1502
1503 static long
1504 dwarf_decode_fde_cie(struct ex_region_info *ri,
1505                      unsigned char *fde_p,
1506                      struct dw_cie *cie,
1507                      struct dw_fde *fde,
1508                      int is_eh)
1509 {
1510         u32 *p;
1511         int secid;
1512         long err;
1513         unsigned char *cie_p;
1514         unsigned long cie_pointer, length;
1515         unsigned char *frame_start;
1516         unsigned long frame_len, addr;
1517         struct extab_info *ti;
1518
1519         secid = get_secid_frame(is_eh);
1520         ti = &ri->ex_sec[secid];
1521
1522         addr = ti->addr;
1523
1524         frame_start = (unsigned char *)
1525                 ex_addr_to_mmap_addr(addr, ri, secid);
1526
1527         frame_len = ti->length;
1528
1529         pr_debug("frame: %p - %p\n",
1530                  frame_start, frame_start + frame_len);
1531
1532         p = (u32 *)fde_p;
1533
1534         length = read_mmap_data_u32(ri, p++, secid, &err);
1535         if (err)
1536                 return err;
1537
1538         if (length == 0xffffffff) {
1539                 pr_warn_once("warning: 64-bit frame is not supported\n");
1540                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
1541         }
1542
1543         fde->offset = fde_p - frame_start;
1544         fde->length = length + sizeof(u32);
1545
1546         pr_debug("FDE: fde_p: %p, offset: %#lx, len: %#lx\n",
1547                  fde_p, fde->offset, fde->length);
1548
1549         cie_pointer = read_mmap_data_u32(ri, p, secid, &err);
1550         if (err)
1551                 return err;
1552
1553         fde->cie_pointer = cie_pointer;
1554
1555         cie_p = is_eh ? (unsigned char *)p - cie_pointer :
1556                 frame_start + cie_pointer;
1557
1558         length = read_mmap_data_u32(ri, (u32 *)cie_p,
1559                                     secid, &err);
1560         if (err)
1561                 return err;
1562
1563         if (length == 0xffffffff) {
1564                 pr_warn_once("warning: 64-bit frame is not supported\n");
1565                 return -QUADD_URC_UNHANDLED_INSTRUCTION;
1566         }
1567
1568         cie->offset = cie_p - frame_start;
1569         cie->length = length + sizeof(u32);
1570
1571         pr_debug("CIE: cie_p: %p, offset: %#lx, len: %#lx\n",
1572                  cie_p, cie->offset, cie->length);
1573
1574         err = decode_cie_entry(ri, cie, cie_p, cie->length, is_eh);
1575         if (err < 0)
1576                 return err;
1577
1578         fde->cie = cie;
1579
1580         err = decode_fde_entry(ri, fde, fde_p, fde->length, is_eh);
1581         if (err < 0)
1582                 return err;
1583
1584         return 0;
1585 }
1586
1587 static void *
1588 dwarf_find_fde(struct ex_region_info *ri,
1589                void *data,
1590                unsigned long length,
1591                unsigned long pc,
1592                int is_eh)
1593 {
1594         long err;
1595         int secid, secid_hdr;
1596         const struct dw_fde_table *fi;
1597         unsigned long fde_count = 0, data_base;
1598         unsigned long fde_addr, init_loc;
1599         struct dw_fde_table *bst;
1600         struct extab_info *ti;
1601
1602         secid = get_secid_frame(is_eh);
1603         secid_hdr = get_secid_frame_hdr(is_eh);
1604
1605         ti = &ri->ex_sec[secid_hdr];
1606         data_base = ti->addr;
1607
1608         bst = dwarf_get_bs_table(ri, data, length, data_base,
1609                                  &fde_count, is_eh);
1610         if (!bst || fde_count == 0) {
1611                 pr_warn_once("warning: bs_table\n");
1612                 return NULL;
1613         }
1614
1615         fi = &bst[fde_count - 1];
1616         init_loc = dw_bst_get_initial_loc(fi, data_base);
1617
1618         pr_debug("pc: %#lx, last bst init_loc: %#lx", pc, init_loc);
1619
1620         if (pc >= init_loc) {
1621                 unsigned long start, end;
1622                 struct extab_info *ti = &ri->ex_sec[secid];
1623
1624                 fde_addr = dw_bst_get_fde_addr(fi, data_base);
1625                 fde_addr = ex_addr_to_mmap_addr(fde_addr, ri,
1626                                                 secid);
1627
1628                 if (pc == init_loc)
1629                         return (void *)fde_addr;
1630
1631                 if (ti->tf_end > 0) {
1632                         start = ti->tf_start;
1633                         end = ti->tf_end;
1634                 } else {
1635                         struct dw_cie cie;
1636                         struct dw_fde fde;
1637
1638                         err = dwarf_decode_fde_cie(ri, (void *)fde_addr,
1639                                                    &cie, &fde, is_eh);
1640                         if (err < 0)
1641                                 return NULL;
1642
1643                         start = fde.initial_location;
1644                         end = start + fde.address_range;
1645
1646                         quadd_unwind_set_tail_info(ri->vm_start, secid,
1647                                                    start, end);
1648                 }
1649
1650                 pr_debug("pc: %#lx, last bst entry: %#lx - %#lx",
1651                          pc, start, end);
1652
1653                 return (pc >= start && pc < end) ?
1654                        (void *)fde_addr : NULL;
1655         }
1656
1657         fi = dwarf_bst_find_idx(data_base, bst, fde_count, pc);
1658         if (!fi)
1659                 return NULL;
1660
1661         fde_addr = dw_bst_get_fde_addr(fi, data_base);
1662         fde_addr = ex_addr_to_mmap_addr(fde_addr, ri, secid);
1663
1664         return (void *)fde_addr;
1665 }
1666
1667 static int
1668 __is_fde_entry_exist(struct ex_region_info *ri, unsigned long addr, int is_eh)
1669 {
1670         int secid_hdr;
1671         unsigned char *fde_p;
1672         struct extab_info *ti;
1673         unsigned char *hdr_start;
1674         unsigned long hdr_len, a;
1675
1676         secid_hdr = get_secid_frame_hdr(is_eh);
1677
1678         ti = &ri->ex_sec[secid_hdr];
1679
1680         a = ti->addr;
1681
1682         hdr_start = (unsigned char *)
1683                 ex_addr_to_mmap_addr(a, ri, secid_hdr);
1684
1685         hdr_len = ti->length;
1686
1687         fde_p = dwarf_find_fde(ri, hdr_start, hdr_len, addr, is_eh);
1688
1689         return fde_p ? 1 : 0;
1690 }
1691
1692 static int
1693 is_fde_entry_exist(struct ex_region_info *ri,
1694                    unsigned long addr,
1695                    int *is_eh,
1696                    int *is_debug)
1697 {
1698         *is_eh = 0;
1699         *is_debug = 0;
1700
1701         if (is_frame_present(ri, 1)) {
1702                 if (__is_fde_entry_exist(ri, addr, 1))
1703                         *is_eh = 1;
1704         }
1705
1706         if (is_frame_present(ri, 0)) {
1707                 if (__is_fde_entry_exist(ri, addr, 0))
1708                         *is_debug = 1;
1709         }
1710
1711         return (*is_eh || *is_debug) ? 1 : 0;
1712 }
1713
1714 static long
1715 dwarf_decode(struct ex_region_info *ri,
1716              struct dw_cie *cie,
1717              struct dw_fde *fde,
1718              unsigned long pc,
1719              int is_eh)
1720 {
1721         long err;
1722         int secid_hdr;
1723         unsigned char *fde_p;
1724         unsigned char *hdr_start;
1725         unsigned long hdr_len, addr;
1726         struct extab_info *ti;
1727
1728         secid_hdr = get_secid_frame_hdr(is_eh);
1729         ti = &ri->ex_sec[secid_hdr];
1730
1731         addr = ti->addr;
1732
1733         hdr_start = (unsigned char *)
1734                 ex_addr_to_mmap_addr(addr, ri, secid_hdr);
1735
1736         hdr_len = ti->length;
1737
1738         pr_debug("eh frame hdr: %p - %p\n",
1739                  hdr_start, hdr_start + hdr_len);
1740
1741         fde_p = dwarf_find_fde(ri, hdr_start, hdr_len, pc, is_eh);
1742         if (!fde_p)
1743                 return -QUADD_URC_IDX_NOT_FOUND;
1744
1745         err = dwarf_decode_fde_cie(ri, fde_p, cie, fde, is_eh);
1746         if (err < 0)
1747                 return err;
1748
1749         if (pc < fde->initial_location ||
1750             pc >= fde->initial_location + fde->address_range) {
1751                 pr_debug("pc is not in range: %#lx - %#lx\n",
1752                          fde->initial_location,
1753                          fde->initial_location + fde->address_range);
1754                 return -QUADD_URC_IDX_NOT_FOUND;
1755         }
1756
1757         return 0;
1758 }
1759
1760 static long def_cfa(struct stackframe *sf, struct regs_state *rs)
1761 {
1762         int reg = rs->cfa_register;
1763
1764         if (reg >= 0) {
1765                 if (reg >= QUADD_NUM_REGS)
1766                         return -QUADD_URC_TBL_IS_CORRUPT;
1767
1768                 pr_debug("r%d --> cfa (%#lx)\n", reg, sf->cfa);
1769                 sf->cfa = sf->vregs[reg];
1770         }
1771
1772         sf->cfa += rs->cfa_offset;
1773         pr_debug("cfa += %#lx (%#lx)\n", rs->cfa_offset, sf->cfa);
1774
1775         return 0;
1776 }
1777
1778 static long
1779 unwind_frame(struct ex_region_info *ri,
1780              struct stackframe *sf,
1781              struct vm_area_struct *vma_sp,
1782              int is_eh)
1783 {
1784         int i, num_regs;
1785         long err;
1786         unsigned char *insn_end;
1787         unsigned long addr, return_addr, val, user_reg_size;
1788         struct dw_fde fde;
1789         struct dw_cie cie;
1790         unsigned long pc = sf->pc;
1791         struct regs_state *rs, *rs_initial;
1792         int mode = sf->mode;
1793
1794         err = dwarf_decode(ri, &cie, &fde, pc, is_eh);
1795         if (err < 0)
1796                 return err;
1797
1798         sf->pc = fde.initial_location;
1799
1800         rs = &sf->rs;
1801         rs_initial = &sf->rs_initial;
1802
1803         rs->cfa_register = -1;
1804         rs_initial->cfa_register = -1;
1805
1806         rules_cleanup(rs, mode);
1807
1808         if (cie.initial_insn) {
1809                 insn_end = cie.initial_insn + cie.initial_insn_len;
1810                 err = dwarf_cfa_exec_insns(ri, cie.initial_insn,
1811                                            insn_end, &cie, sf, pc, is_eh);
1812                 if (err)
1813                         return err;
1814         }
1815
1816         memcpy(rs_initial, rs, sizeof(*rs));
1817
1818         if (fde.instructions) {
1819                 insn_end = fde.instructions + fde.insn_length;
1820                 err = dwarf_cfa_exec_insns(ri, fde.instructions,
1821                                            insn_end, fde.cie, sf, pc, is_eh);
1822                 if (err)
1823                         return err;
1824         }
1825
1826         pr_debug("mode: %s\n", (mode == DW_MODE_ARM32) ? "arm32" : "arm64");
1827         pr_debug("initial cfa: %#lx\n", sf->cfa);
1828
1829         user_reg_size = get_user_reg_size(mode);
1830
1831         err = def_cfa(sf, rs);
1832         if (err < 0)
1833                 return err;
1834
1835         pr_debug("pc: %#lx, exec pc: %#lx, lr: %#lx\n",
1836                  pc, sf->pc, sf->vregs[regnum_lr(mode)]);
1837
1838         pr_debug("sp: %#lx, fp: %#lx, fp_thumb: %#lx\n",
1839                  sf->vregs[regnum_sp(mode)],
1840                  sf->vregs[regnum_fp(mode)],
1841                  sf->vregs[ARM32_FP_THUMB]);
1842
1843         pr_debug("lr rule: %#lx/%ld (where: %u)\n",
1844                  rs->reg[regnum_lr(mode)].loc.reg,
1845                  rs->reg[regnum_lr(mode)].loc.offset,
1846                  rs->reg[regnum_lr(mode)].where);
1847
1848         pr_debug("fp rule: %#lx/%ld (where: %u)\n",
1849                  rs->reg[regnum_fp(mode)].loc.reg,
1850                  rs->reg[regnum_fp(mode)].loc.offset,
1851                  rs->reg[regnum_fp(mode)].where);
1852
1853         pr_debug("fp_thumb rule: %#lx/%ld (where: %u)\n",
1854                  rs->reg[ARM32_FP_THUMB].loc.reg,
1855                  rs->reg[ARM32_FP_THUMB].loc.offset,
1856                  rs->reg[ARM32_FP_THUMB].where);
1857
1858         pr_debug("cfa_offset: %ld (%#lx)\n",
1859                  rs->cfa_offset, rs->cfa_offset);
1860         pr_debug("cfa_register: %u\n", rs->cfa_register);
1861         pr_debug("new cfa: %#lx\n", sf->cfa);
1862
1863         num_regs = (mode == DW_MODE_ARM32) ?
1864                 QUADD_AARCH32_REGISTERS :
1865                 QUADD_AARCH64_REGISTERS;
1866
1867         for (i = 0; i < num_regs; i++) {
1868                 switch (rs->reg[i].where) {
1869                 case DW_WHERE_UNDEF:
1870                         break;
1871
1872                 case DW_WHERE_SAME:
1873                         break;
1874
1875                 case DW_WHERE_CFAREL:
1876                         addr = sf->cfa + rs->reg[i].loc.offset;
1877
1878                         if (!validate_stack_addr(addr, vma_sp, user_reg_size))
1879                                 return -QUADD_URC_SP_INCORRECT;
1880
1881                         if (mode == DW_MODE_ARM32)
1882                                 err = read_user_data((u32 __user *)addr, val);
1883                         else
1884                                 err = read_user_data((unsigned long __user *)
1885                                                      addr, val);
1886
1887                         if (err < 0)
1888                                 return err;
1889
1890                         sf->vregs[i] = val;
1891                         pr_debug("[r%d] DW_WHERE_CFAREL: new val: %#lx\n",
1892                                  i, val);
1893
1894                         break;
1895
1896                 default:
1897                         pr_err_once("[r%d] error: unsupported rule (%d)\n",
1898                                     i, rs->reg[i].where);
1899                         break;
1900                 }
1901         }
1902
1903         return_addr = sf->vregs[regnum_lr(mode)];
1904         pr_debug("return_addr: %#lx\n", return_addr);
1905
1906         if (!validate_pc_addr(return_addr, user_reg_size))
1907                 return -QUADD_URC_PC_INCORRECT;
1908
1909         sf->pc = return_addr;
1910         sf->vregs[regnum_sp(mode)] = sf->cfa;
1911
1912         return 0;
1913 }
1914
1915 static void
1916 unwind_backtrace(struct quadd_callchain *cc,
1917                  struct ex_region_info *ri,
1918                  struct stackframe *sf,
1919                  struct vm_area_struct *vma_sp,
1920                  struct task_struct *task)
1921 {
1922         unsigned long user_reg_size;
1923         struct ex_region_info ri_new;
1924         unsigned int unw_type;
1925         int is_eh = 1, mode = sf->mode;
1926
1927         cc->urc_dwarf = QUADD_URC_FAILURE;
1928         user_reg_size = get_user_reg_size(mode);
1929
1930         while (1) {
1931                 long sp, err;
1932                 int nr_added;
1933                 int __is_eh, __is_debug;
1934                 struct vm_area_struct *vma_pc;
1935                 unsigned long addr, where = sf->pc;
1936                 struct mm_struct *mm = task->mm;
1937
1938                 if (!mm)
1939                         break;
1940
1941                 sp = sf->vregs[regnum_sp(mode)];
1942
1943                 if (!validate_stack_addr(sp, vma_sp, user_reg_size)) {
1944                         cc->urc_dwarf = QUADD_URC_SP_INCORRECT;
1945                         break;
1946                 }
1947
1948                 vma_pc = find_vma(mm, sf->pc);
1949                 if (!vma_pc)
1950                         break;
1951
1952                 addr = ri->vm_start;
1953
1954                 if (!is_vma_addr(addr, vma_pc, user_reg_size)) {
1955                         err = quadd_get_dw_frames(vma_pc->vm_start, &ri_new);
1956                         if (err) {
1957                                 cc->urc_dwarf = QUADD_URC_TBL_NOT_EXIST;
1958                                 break;
1959                         }
1960
1961                         pr_debug("ri: %#lx ---> %#lx",
1962                                  ri->vm_start, ri_new.vm_start);
1963
1964                         ri = &ri_new;
1965                 }
1966
1967                 if (!is_fde_entry_exist(ri, sf->pc, &__is_eh, &__is_debug)) {
1968                         pr_debug("eh/debug fde entries are not existed\n");
1969                         cc->urc_dwarf = QUADD_URC_IDX_NOT_FOUND;
1970                         break;
1971                 }
1972                 pr_debug("is_eh: %d, is_debug: %d\n", __is_eh, __is_debug);
1973
1974                 if (is_eh) {
1975                         if (!__is_eh)
1976                                 is_eh = 0;
1977                 } else {
1978                         if (!__is_debug)
1979                                 is_eh = 1;
1980                 }
1981
1982                 err = unwind_frame(ri, sf, vma_sp, is_eh);
1983                 if (err < 0) {
1984                         if (__is_eh && __is_debug) {
1985                                 is_eh ^= 1;
1986
1987                                 err = unwind_frame(ri, sf, vma_sp, is_eh);
1988                                 if (err < 0) {
1989                                         cc->urc_dwarf = -err;
1990                                         break;
1991                                 }
1992                         } else {
1993                                 cc->urc_dwarf = -err;
1994                                 break;
1995                         }
1996                 }
1997
1998                 unw_type = is_eh ? QUADD_UNW_TYPE_DWARF_EH :
1999                                    QUADD_UNW_TYPE_DWARF_DF;
2000
2001                 pr_debug("[%s]: function at [<%08lx>] from [<%08lx>]\n",
2002                          is_eh ? "eh" : "debug", where, sf->pc);
2003
2004                 cc->curr_sp = sf->vregs[regnum_sp(mode)];
2005
2006                 cc->curr_fp = sf->vregs[regnum_fp(mode)];
2007                 if (mode == DW_MODE_ARM32)
2008                         cc->curr_fp_thumb = sf->vregs[ARM32_FP_THUMB];
2009
2010                 cc->curr_pc = sf->pc;
2011                 cc->curr_lr = sf->vregs[regnum_lr(mode)];
2012
2013                 nr_added = quadd_callchain_store(cc, sf->pc, unw_type);
2014                 if (nr_added == 0)
2015                         break;
2016         }
2017 }
2018
2019 int
2020 quadd_is_ex_entry_exist_dwarf(struct pt_regs *regs,
2021                               unsigned long addr,
2022                               struct task_struct *task)
2023 {
2024         long err;
2025         int is_eh, is_debug;
2026         struct ex_region_info ri;
2027         struct vm_area_struct *vma;
2028         struct mm_struct *mm = task->mm;
2029
2030         if (!regs || !mm)
2031                 return 0;
2032
2033         vma = find_vma(mm, addr);
2034         if (!vma)
2035                 return 0;
2036
2037         err = quadd_get_dw_frames(vma->vm_start, &ri);
2038         if (err)
2039                 return 0;
2040
2041         return is_fde_entry_exist(&ri, addr, &is_eh, &is_debug);
2042 }
2043
2044 unsigned int
2045 quadd_get_user_cc_dwarf(struct pt_regs *regs,
2046                         struct quadd_callchain *cc,
2047                         struct task_struct *task)
2048 {
2049         long err;
2050         int mode, nr_prev = cc->nr;
2051         unsigned long ip, lr, sp, fp, fp_thumb;
2052         struct vm_area_struct *vma, *vma_sp;
2053         struct mm_struct *mm = task->mm;
2054         struct ex_region_info ri;
2055         struct stackframe *sf;
2056         struct dwarf_cpu_context *cpu_ctx = this_cpu_ptr(ctx.cpu_ctx);
2057
2058         if (!regs || !mm)
2059                 return 0;
2060
2061         if (cc->urc_dwarf == QUADD_URC_LEVEL_TOO_DEEP)
2062                 return nr_prev;
2063
2064         cc->urc_dwarf = QUADD_URC_FAILURE;
2065
2066         if (nr_prev > 0) {
2067                 ip = cc->curr_pc;
2068                 sp = cc->curr_sp;
2069                 fp = cc->curr_fp;
2070                 fp_thumb = cc->curr_fp_thumb;
2071                 lr = cc->curr_lr;
2072         } else {
2073                 ip = instruction_pointer(regs);
2074                 lr = quadd_user_link_register(regs);
2075                 sp = quadd_user_stack_pointer(regs);
2076
2077 #ifdef CONFIG_ARM64
2078                 if (compat_user_mode(regs)) {
2079                         fp = regs->compat_usr(ARM32_FP);
2080                         fp_thumb = regs->compat_usr(ARM32_FP_THUMB);
2081                 } else {
2082                         fp = regs->regs[ARM64_FP];
2083                         fp_thumb = 0;
2084                 }
2085 #else
2086                 fp = regs->ARM_fp;
2087                 fp_thumb = regs->ARM_r7;
2088 #endif
2089         }
2090
2091 #ifdef CONFIG_ARM64
2092         mode = compat_user_mode(regs) ?
2093                 DW_MODE_ARM32 : DW_MODE_ARM64;
2094 #else
2095         mode = DW_MODE_ARM32;
2096 #endif
2097
2098         pr_debug("%s: pc: %#lx, lr: %#lx\n", __func__, ip, lr);
2099         pr_debug("%s: sp: %#lx, fp: %#lx, fp_thumb: %#lx\n",
2100                  __func__, sp, fp, fp_thumb);
2101
2102         sf = &cpu_ctx->sf;
2103
2104         sf->vregs[regnum_lr(mode)] = lr;
2105         sf->pc = ip;
2106
2107         sf->vregs[regnum_sp(mode)] = sp;
2108         sf->vregs[regnum_fp(mode)] = fp;
2109
2110         if (mode == DW_MODE_ARM32)
2111                 sf->vregs[ARM32_FP_THUMB] = fp_thumb;
2112
2113         cpu_ctx->dw_ptr_size = (mode == DW_MODE_ARM32) ?
2114                                 sizeof(u32) : sizeof(u64);
2115
2116         sf->mode = mode;
2117         sf->cfa = 0;
2118
2119         vma = find_vma(mm, ip);
2120         if (!vma)
2121                 return 0;
2122
2123         vma_sp = find_vma(mm, sp);
2124         if (!vma_sp)
2125                 return 0;
2126
2127         err = quadd_get_dw_frames(vma->vm_start, &ri);
2128         if (err) {
2129                 cc->urc_dwarf = QUADD_URC_TBL_NOT_EXIST;
2130                 return 0;
2131         }
2132
2133         unwind_backtrace(cc, &ri, sf, vma_sp, task);
2134
2135         pr_debug("%s: mode: %s, cc->nr: %d --> %d\n", __func__,
2136                  (mode == DW_MODE_ARM32) ? "arm32" : "arm64",
2137                  nr_prev, cc->nr);
2138
2139         return cc->nr;
2140 }
2141
2142 int quadd_dwarf_unwind_start(void)
2143 {
2144         if (!atomic_cmpxchg(&ctx.started, 0, 1)) {
2145                 ctx.cpu_ctx = alloc_percpu(struct dwarf_cpu_context);
2146                 if (!ctx.cpu_ctx) {
2147                         atomic_set(&ctx.started, 0);
2148                         return -ENOMEM;
2149                 }
2150         }
2151
2152         return 0;
2153 }
2154
2155 void quadd_dwarf_unwind_stop(void)
2156 {
2157         if (atomic_cmpxchg(&ctx.started, 1, 0))
2158                 free_percpu(ctx.cpu_ctx);
2159 }
2160
2161 int quadd_dwarf_unwind_init(void)
2162 {
2163         atomic_set(&ctx.started, 0);
2164         return 0;
2165 }