blob: 788f4d3c76f51afc7662c79e64f8da4f73310bf1 [file] [log] [blame]
Jiri Olsa71ad0f52012-08-07 15:20:46 +02001/*
2 * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
3 *
4 * Lots of this code have been borrowed or heavily inspired from parts of
5 * the libunwind 0.99 code which are (amongst other contributors I may have
6 * forgotten):
7 *
8 * Copyright (C) 2002-2007 Hewlett-Packard Co
9 * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
10 *
11 * And the bugs have been added by:
12 *
13 * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
14 * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
15 *
16 */
17
18#include <elf.h>
19#include <gelf.h>
20#include <fcntl.h>
Arnaldo Carvalho de Melofd20e812017-04-17 15:23:08 -030021#include <inttypes.h>
Jiri Olsa71ad0f52012-08-07 15:20:46 +020022#include <string.h>
23#include <unistd.h>
24#include <sys/mman.h>
25#include <linux/list.h>
He Kuang19473e72016-06-03 03:33:21 +000026#ifndef REMOTE_UNWIND_LIBUNWIND
Jiri Olsa71ad0f52012-08-07 15:20:46 +020027#include <libunwind.h>
28#include <libunwind-ptrace.h>
He Kuang19473e72016-06-03 03:33:21 +000029#endif
Namhyung Kim66f066d82014-10-06 09:46:00 +090030#include "callchain.h"
Jiri Olsa71ad0f52012-08-07 15:20:46 +020031#include "thread.h"
32#include "session.h"
33#include "perf_regs.h"
34#include "unwind.h"
Masami Hiramatsu99ca4232014-01-16 09:39:49 +000035#include "symbol.h"
Jiri Olsa71ad0f52012-08-07 15:20:46 +020036#include "util.h"
Jiri Olsa84f5d362014-07-14 23:46:48 +020037#include "debug.h"
Jiri Olsae583d702016-04-07 09:11:12 +020038#include "asm/bug.h"
Matija Glavinic Pecotic9343e452017-01-17 15:50:35 +010039#include "dso.h"
Jiri Olsa71ad0f52012-08-07 15:20:46 +020040
41extern int
42UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
43 unw_word_t ip,
44 unw_dyn_info_t *di,
45 unw_proc_info_t *pi,
46 int need_unwind_info, void *arg);
47
48#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
49
Jean Pihetab255e72013-09-26 12:36:38 +010050extern int
51UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
52 unw_word_t ip,
53 unw_word_t segbase,
54 const char *obj_name, unw_word_t start,
55 unw_word_t end);
56
57#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
58
Jiri Olsa71ad0f52012-08-07 15:20:46 +020059#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
60#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
61
62/* Pointer-encoding formats: */
63#define DW_EH_PE_omit 0xff
64#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
65#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
66#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
67#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
68#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
69
70/* Pointer-encoding application: */
71#define DW_EH_PE_absptr 0x00 /* absolute value */
72#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
73
74/*
75 * The following are not documented by LSB v1.3, yet they are used by
76 * GCC, presumably they aren't documented by LSB since they aren't
77 * used on Linux:
78 */
79#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
80#define DW_EH_PE_aligned 0x50 /* aligned pointer */
81
82/* Flags intentionaly not handled, since they're not needed:
83 * #define DW_EH_PE_indirect 0x80
84 * #define DW_EH_PE_uleb128 0x01
85 * #define DW_EH_PE_udata2 0x02
86 * #define DW_EH_PE_sleb128 0x09
87 * #define DW_EH_PE_sdata2 0x0a
88 * #define DW_EH_PE_textrel 0x20
89 * #define DW_EH_PE_datarel 0x30
90 */
91
92struct unwind_info {
93 struct perf_sample *sample;
94 struct machine *machine;
95 struct thread *thread;
Jiri Olsa71ad0f52012-08-07 15:20:46 +020096};
97
98#define dw_read(ptr, type, end) ({ \
99 type *__p = (type *) ptr; \
100 type __v; \
101 if ((__p + 1) > (type *) end) \
102 return -EINVAL; \
103 __v = *__p++; \
104 ptr = (typeof(ptr)) __p; \
105 __v; \
106 })
107
108static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
109 u8 encoding)
110{
111 u8 *cur = *p;
112 *val = 0;
113
114 switch (encoding) {
115 case DW_EH_PE_omit:
116 *val = 0;
117 goto out;
118 case DW_EH_PE_ptr:
119 *val = dw_read(cur, unsigned long, end);
120 goto out;
121 default:
122 break;
123 }
124
125 switch (encoding & DW_EH_PE_APPL_MASK) {
126 case DW_EH_PE_absptr:
127 break;
128 case DW_EH_PE_pcrel:
129 *val = (unsigned long) cur;
130 break;
131 default:
132 return -EINVAL;
133 }
134
135 if ((encoding & 0x07) == 0x00)
136 encoding |= DW_EH_PE_udata4;
137
138 switch (encoding & DW_EH_PE_FORMAT_MASK) {
139 case DW_EH_PE_sdata4:
140 *val += dw_read(cur, s32, end);
141 break;
142 case DW_EH_PE_udata4:
143 *val += dw_read(cur, u32, end);
144 break;
145 case DW_EH_PE_sdata8:
146 *val += dw_read(cur, s64, end);
147 break;
148 case DW_EH_PE_udata8:
149 *val += dw_read(cur, u64, end);
150 break;
151 default:
152 return -EINVAL;
153 }
154
155 out:
156 *p = cur;
157 return 0;
158}
159
160#define dw_read_encoded_value(ptr, end, enc) ({ \
161 u64 __v; \
162 if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
163 return -EINVAL; \
164 } \
165 __v; \
166 })
167
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200168static u64 elf_section_offset(int fd, const char *name)
169{
170 Elf *elf;
171 GElf_Ehdr ehdr;
172 GElf_Shdr shdr;
173 u64 offset = 0;
174
175 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
176 if (elf == NULL)
177 return 0;
178
179 do {
180 if (gelf_getehdr(elf, &ehdr) == NULL)
181 break;
182
Masami Hiramatsu99ca4232014-01-16 09:39:49 +0000183 if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200184 break;
185
186 offset = shdr.sh_offset;
187 } while (0);
188
189 elf_end(elf);
190 return offset;
191}
192
Wang Nanb93b0962015-01-14 10:36:47 +0800193#ifndef NO_LIBUNWIND_DEBUG_FRAME
194static int elf_is_exec(int fd, const char *name)
195{
196 Elf *elf;
197 GElf_Ehdr ehdr;
198 int retval = 0;
199
200 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
201 if (elf == NULL)
202 return 0;
203 if (gelf_getehdr(elf, &ehdr) == NULL)
204 goto out;
205
206 retval = (ehdr.e_type == ET_EXEC);
207
208out:
209 elf_end(elf);
210 pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
211 return retval;
212}
213#endif
214
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200215struct table_entry {
216 u32 start_ip_offset;
217 u32 fde_offset;
218};
219
220struct eh_frame_hdr {
221 unsigned char version;
222 unsigned char eh_frame_ptr_enc;
223 unsigned char fde_count_enc;
224 unsigned char table_enc;
225
226 /*
227 * The rest of the header is variable-length and consists of the
228 * following members:
229 *
230 * encoded_t eh_frame_ptr;
231 * encoded_t fde_count;
232 */
233
234 /* A single encoded pointer should not be more than 8 bytes. */
235 u64 enc[2];
236
237 /*
238 * struct {
239 * encoded_t start_ip;
240 * encoded_t fde_addr;
241 * } binary_search_table[fde_count];
242 */
243 char data[0];
244} __packed;
245
246static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
247 u64 offset, u64 *table_data, u64 *segbase,
248 u64 *fde_count)
249{
250 struct eh_frame_hdr hdr;
251 u8 *enc = (u8 *) &hdr.enc;
252 u8 *end = (u8 *) &hdr.data;
253 ssize_t r;
254
255 r = dso__data_read_offset(dso, machine, offset,
256 (u8 *) &hdr, sizeof(hdr));
257 if (r != sizeof(hdr))
258 return -EINVAL;
259
260 /* We dont need eh_frame_ptr, just skip it. */
261 dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
262
263 *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
264 *segbase = offset;
265 *table_data = (enc - (u8 *) &hdr) + offset;
266 return 0;
267}
268
Jean Pihetab255e72013-09-26 12:36:38 +0100269static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
270 u64 *table_data, u64 *segbase,
271 u64 *fde_count)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200272{
273 int ret = -EINVAL, fd;
Wang Nan303cb892015-03-13 15:02:56 +0800274 u64 offset = dso->data.eh_frame_hdr_offset;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200275
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900276 if (offset == 0) {
Namhyung Kim4bb11d02015-05-21 01:03:41 +0900277 fd = dso__data_get_fd(dso, machine);
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900278 if (fd < 0)
279 return -EINVAL;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200280
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900281 /* Check the .eh_frame section for unwinding info */
282 offset = elf_section_offset(fd, ".eh_frame_hdr");
Wang Nan303cb892015-03-13 15:02:56 +0800283 dso->data.eh_frame_hdr_offset = offset;
Namhyung Kim4bb11d02015-05-21 01:03:41 +0900284 dso__data_put_fd(dso);
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900285 }
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200286
287 if (offset)
288 ret = unwind_spec_ehframe(dso, machine, offset,
289 table_data, segbase,
290 fde_count);
291
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200292 return ret;
293}
294
Jean Pihetab255e72013-09-26 12:36:38 +0100295#ifndef NO_LIBUNWIND_DEBUG_FRAME
296static int read_unwind_spec_debug_frame(struct dso *dso,
297 struct machine *machine, u64 *offset)
298{
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900299 int fd;
Wang Nan303cb892015-03-13 15:02:56 +0800300 u64 ofs = dso->data.debug_frame_offset;
Jean Pihetab255e72013-09-26 12:36:38 +0100301
Matija Glavinic Pecotic9343e452017-01-17 15:50:35 +0100302 /* debug_frame can reside in:
303 * - dso
304 * - debug pointed by symsrc_filename
305 * - gnu_debuglink, which doesn't necessary
306 * has to be pointed by symsrc_filename
307 */
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900308 if (ofs == 0) {
Namhyung Kim4bb11d02015-05-21 01:03:41 +0900309 fd = dso__data_get_fd(dso, machine);
Matija Glavinic Pecotic9343e452017-01-17 15:50:35 +0100310 if (fd >= 0) {
311 ofs = elf_section_offset(fd, ".debug_frame");
312 dso__data_put_fd(dso);
313 }
Jean Pihetab255e72013-09-26 12:36:38 +0100314
Matija Glavinic Pecotic9343e452017-01-17 15:50:35 +0100315 if (ofs <= 0) {
316 fd = open(dso->symsrc_filename, O_RDONLY);
317 if (fd >= 0) {
318 ofs = elf_section_offset(fd, ".debug_frame");
319 close(fd);
320 }
321 }
322
323 if (ofs <= 0) {
324 char *debuglink = malloc(PATH_MAX);
325 int ret = 0;
326
327 ret = dso__read_binary_type_filename(
328 dso, DSO_BINARY_TYPE__DEBUGLINK,
329 machine->root_dir, debuglink, PATH_MAX);
330 if (!ret) {
331 fd = open(debuglink, O_RDONLY);
332 if (fd >= 0) {
333 ofs = elf_section_offset(fd,
334 ".debug_frame");
335 close(fd);
336 }
337 }
338 if (ofs > 0) {
339 if (dso->symsrc_filename != NULL) {
340 pr_warning(
341 "%s: overwrite symsrc(%s,%s)\n",
342 __func__,
343 dso->symsrc_filename,
344 debuglink);
345 free(dso->symsrc_filename);
346 }
347 dso->symsrc_filename = debuglink;
348 } else {
349 free(debuglink);
350 }
351 }
352
Wang Nan303cb892015-03-13 15:02:56 +0800353 dso->data.debug_frame_offset = ofs;
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900354 }
Jean Pihetab255e72013-09-26 12:36:38 +0100355
Namhyung Kimf1f13af2015-01-29 17:07:21 +0900356 *offset = ofs;
Jean Pihetab255e72013-09-26 12:36:38 +0100357 if (*offset)
358 return 0;
359
360 return -EINVAL;
361}
362#endif
363
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200364static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
365{
366 struct addr_location al;
367
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -0300368 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
Adrian Hunter326f59b2013-08-08 14:32:27 +0300369 MAP__FUNCTION, ip, &al);
Jiri Olsa0ddf5242016-01-07 10:14:01 +0100370 if (!al.map) {
371 /*
372 * We've seen cases (softice) where DWARF unwinder went
373 * through non executable mmaps, which we need to lookup
374 * in MAP__VARIABLE tree.
375 */
376 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
377 MAP__VARIABLE, ip, &al);
378 }
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200379 return al.map;
380}
381
382static int
383find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
384 int need_unwind_info, void *arg)
385{
386 struct unwind_info *ui = arg;
387 struct map *map;
388 unw_dyn_info_t di;
389 u64 table_data, segbase, fde_count;
Rabin Vincent8eac1d52015-09-27 20:37:57 +0200390 int ret = -EINVAL;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200391
392 map = find_map(ip, ui);
393 if (!map || !map->dso)
394 return -EINVAL;
395
396 pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
397
Jean Pihetab255e72013-09-26 12:36:38 +0100398 /* Check the .eh_frame section for unwinding info */
399 if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
400 &table_data, &segbase, &fde_count)) {
401 memset(&di, 0, sizeof(di));
402 di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
403 di.start_ip = map->start;
404 di.end_ip = map->end;
Stefano Sanfilippoeac05af2016-10-13 03:59:39 -0700405 di.u.rti.segbase = map->start + segbase - map->pgoff;
406 di.u.rti.table_data = map->start + table_data - map->pgoff;
Jean Pihetab255e72013-09-26 12:36:38 +0100407 di.u.rti.table_len = fde_count * sizeof(struct table_entry)
408 / sizeof(unw_word_t);
Rabin Vincent8eac1d52015-09-27 20:37:57 +0200409 ret = dwarf_search_unwind_table(as, ip, &di, pi,
410 need_unwind_info, arg);
Jean Pihetab255e72013-09-26 12:36:38 +0100411 }
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200412
Jean Pihetab255e72013-09-26 12:36:38 +0100413#ifndef NO_LIBUNWIND_DEBUG_FRAME
414 /* Check the .debug_frame section for unwinding info */
Rabin Vincent8eac1d52015-09-27 20:37:57 +0200415 if (ret < 0 &&
416 !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
Namhyung Kim4bb11d02015-05-21 01:03:41 +0900417 int fd = dso__data_get_fd(map->dso, ui->machine);
Wang Nanb93b0962015-01-14 10:36:47 +0800418 int is_exec = elf_is_exec(fd, map->dso->name);
419 unw_word_t base = is_exec ? 0 : map->start;
Rabin Vincent7ed49152015-10-29 08:49:36 +0100420 const char *symfile;
Wang Nanb93b0962015-01-14 10:36:47 +0800421
Namhyung Kim4bb11d02015-05-21 01:03:41 +0900422 if (fd >= 0)
Hou Pengyangf0058132015-06-16 11:16:35 +0000423 dso__data_put_fd(map->dso);
Namhyung Kim4bb11d02015-05-21 01:03:41 +0900424
Rabin Vincent7ed49152015-10-29 08:49:36 +0100425 symfile = map->dso->symsrc_filename ?: map->dso->name;
426
Jean Pihetab255e72013-09-26 12:36:38 +0100427 memset(&di, 0, sizeof(di));
Rabin Vincent7ed49152015-10-29 08:49:36 +0100428 if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
Jean Pihetd11416e2013-12-16 17:43:14 +0100429 map->start, map->end))
430 return dwarf_search_unwind_table(as, ip, &di, pi,
431 need_unwind_info, arg);
Jean Pihetab255e72013-09-26 12:36:38 +0100432 }
433#endif
434
Rabin Vincent8eac1d52015-09-27 20:37:57 +0200435 return ret;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200436}
437
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300438static int access_fpreg(unw_addr_space_t __maybe_unused as,
439 unw_regnum_t __maybe_unused num,
440 unw_fpreg_t __maybe_unused *val,
441 int __maybe_unused __write,
442 void __maybe_unused *arg)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200443{
444 pr_err("unwind: access_fpreg unsupported\n");
445 return -UNW_EINVAL;
446}
447
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300448static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
449 unw_word_t __maybe_unused *dil_addr,
450 void __maybe_unused *arg)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200451{
452 return -UNW_ENOINFO;
453}
454
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300455static int resume(unw_addr_space_t __maybe_unused as,
456 unw_cursor_t __maybe_unused *cu,
457 void __maybe_unused *arg)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200458{
459 pr_err("unwind: resume unsupported\n");
460 return -UNW_EINVAL;
461}
462
463static int
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300464get_proc_name(unw_addr_space_t __maybe_unused as,
465 unw_word_t __maybe_unused addr,
466 char __maybe_unused *bufp, size_t __maybe_unused buf_len,
467 unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200468{
469 pr_err("unwind: get_proc_name unsupported\n");
470 return -UNW_EINVAL;
471}
472
473static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
474 unw_word_t *data)
475{
Jiri Olsaf22ed822016-01-07 10:14:00 +0100476 struct map *map;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200477 ssize_t size;
478
Jiri Olsaf22ed822016-01-07 10:14:00 +0100479 map = find_map(addr, ui);
480 if (!map) {
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200481 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
482 return -1;
483 }
484
Jiri Olsaf22ed822016-01-07 10:14:00 +0100485 if (!map->dso)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200486 return -1;
487
Jiri Olsaf22ed822016-01-07 10:14:00 +0100488 size = dso__data_read_addr(map->dso, map, ui->machine,
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200489 addr, (u8 *) data, sizeof(*data));
490
491 return !(size == sizeof(*data));
492}
493
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300494static int access_mem(unw_addr_space_t __maybe_unused as,
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200495 unw_word_t addr, unw_word_t *valp,
496 int __write, void *arg)
497{
498 struct unwind_info *ui = arg;
499 struct stack_dump *stack = &ui->sample->user_stack;
Jiri Olsac9b951c2014-01-07 13:47:29 +0100500 u64 start, end;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200501 int offset;
502 int ret;
503
504 /* Don't support write, probably not needed. */
505 if (__write || !stack || !ui->sample->user_regs.regs) {
506 *valp = 0;
507 return 0;
508 }
509
He Kuang78ff1d62016-06-22 06:57:02 +0000510 ret = perf_reg_value(&start, &ui->sample->user_regs,
511 LIBUNWIND__ARCH_REG_SP);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200512 if (ret)
513 return ret;
514
515 end = start + stack->size;
516
517 /* Check overflow. */
518 if (addr + sizeof(unw_word_t) < addr)
519 return -EINVAL;
520
521 if (addr < start || addr + sizeof(unw_word_t) >= end) {
522 ret = access_dso_mem(ui, addr, valp);
523 if (ret) {
Jiri Olsac9b951c2014-01-07 13:47:29 +0100524 pr_debug("unwind: access_mem %p not inside range"
525 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
Rabin Vincent186c6cf2015-09-27 20:37:55 +0200526 (void *) (uintptr_t) addr, start, end);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200527 *valp = 0;
528 return ret;
529 }
530 return 0;
531 }
532
533 offset = addr - start;
534 *valp = *(unw_word_t *)&stack->data[offset];
Jiri Olsac9b951c2014-01-07 13:47:29 +0100535 pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
Rabin Vincent186c6cf2015-09-27 20:37:55 +0200536 (void *) (uintptr_t) addr, (unsigned long)*valp, offset);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200537 return 0;
538}
539
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300540static int access_reg(unw_addr_space_t __maybe_unused as,
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200541 unw_regnum_t regnum, unw_word_t *valp,
542 int __write, void *arg)
543{
544 struct unwind_info *ui = arg;
545 int id, ret;
Jiri Olsac9b951c2014-01-07 13:47:29 +0100546 u64 val;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200547
548 /* Don't support write, I suspect we don't need it. */
549 if (__write) {
550 pr_err("unwind: access_reg w %d\n", regnum);
551 return 0;
552 }
553
554 if (!ui->sample->user_regs.regs) {
555 *valp = 0;
556 return 0;
557 }
558
He Kuangeeb118c2016-06-03 03:33:20 +0000559 id = LIBUNWIND__ARCH_REG_ID(regnum);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200560 if (id < 0)
561 return -EINVAL;
562
Jiri Olsac9b951c2014-01-07 13:47:29 +0100563 ret = perf_reg_value(&val, &ui->sample->user_regs, id);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200564 if (ret) {
565 pr_err("unwind: can't read reg %d\n", regnum);
566 return ret;
567 }
568
Jiri Olsac9b951c2014-01-07 13:47:29 +0100569 *valp = (unw_word_t) val;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200570 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
571 return 0;
572}
573
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300574static void put_unwind_info(unw_addr_space_t __maybe_unused as,
575 unw_proc_info_t *pi __maybe_unused,
576 void *arg __maybe_unused)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200577{
578 pr_debug("unwind: put_unwind_info called\n");
579}
580
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -0300581static int entry(u64 ip, struct thread *thread,
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200582 unwind_entry_cb_t cb, void *arg)
583{
584 struct unwind_entry e;
585 struct addr_location al;
586
Arnaldo Carvalho de Melobb871a92014-10-23 12:50:25 -0300587 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
Adrian Hunter61710bd2013-08-08 14:32:26 +0300588 MAP__FUNCTION, ip, &al);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200589
Milian Wolff67540752016-08-16 17:39:26 +0200590 e.ip = al.addr;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200591 e.map = al.map;
592 e.sym = al.sym;
593
594 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
595 al.sym ? al.sym->name : "''",
596 ip,
597 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
598
599 return cb(&e, arg);
600}
601
602static void display_error(int err)
603{
604 switch (err) {
605 case UNW_EINVAL:
606 pr_err("unwind: Only supports local.\n");
607 break;
608 case UNW_EUNSPEC:
609 pr_err("unwind: Unspecified error.\n");
610 break;
611 case UNW_EBADREG:
612 pr_err("unwind: Register unavailable.\n");
613 break;
614 default:
615 break;
616 }
617}
618
619static unw_accessors_t accessors = {
620 .find_proc_info = find_proc_info,
621 .put_unwind_info = put_unwind_info,
622 .get_dyn_info_list_addr = get_dyn_info_list_addr,
623 .access_mem = access_mem,
624 .access_reg = access_reg,
625 .access_fpreg = access_fpreg,
626 .resume = resume,
627 .get_proc_name = get_proc_name,
628};
629
He Kuangf83c0412016-06-03 03:33:12 +0000630static int _unwind__prepare_access(struct thread *thread)
Namhyung Kim66f066d82014-10-06 09:46:00 +0900631{
Namhyung Kim66f066d82014-10-06 09:46:00 +0900632 if (callchain_param.record_mode != CALLCHAIN_DWARF)
633 return 0;
634
Jiri Olsae583d702016-04-07 09:11:12 +0200635 thread->addr_space = unw_create_addr_space(&accessors, 0);
636 if (!thread->addr_space) {
Namhyung Kim66f066d82014-10-06 09:46:00 +0900637 pr_err("unwind: Can't create unwind address space.\n");
638 return -ENOMEM;
639 }
640
Jiri Olsae583d702016-04-07 09:11:12 +0200641 unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
Namhyung Kim66f066d82014-10-06 09:46:00 +0900642 return 0;
643}
644
He Kuangf83c0412016-06-03 03:33:12 +0000645static void _unwind__flush_access(struct thread *thread)
Namhyung Kim380b5142014-10-06 09:46:01 +0900646{
Namhyung Kim380b5142014-10-06 09:46:01 +0900647 if (callchain_param.record_mode != CALLCHAIN_DWARF)
648 return;
649
Jiri Olsae583d702016-04-07 09:11:12 +0200650 unw_flush_cache(thread->addr_space, 0, 0);
Namhyung Kim380b5142014-10-06 09:46:01 +0900651}
652
He Kuangf83c0412016-06-03 03:33:12 +0000653static void _unwind__finish_access(struct thread *thread)
Namhyung Kim66f066d82014-10-06 09:46:00 +0900654{
Namhyung Kim66f066d82014-10-06 09:46:00 +0900655 if (callchain_param.record_mode != CALLCHAIN_DWARF)
656 return;
657
Jiri Olsae583d702016-04-07 09:11:12 +0200658 unw_destroy_addr_space(thread->addr_space);
Namhyung Kim66f066d82014-10-06 09:46:00 +0900659}
660
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200661static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
Arnaldo Carvalho de Melo37676af2013-11-13 17:40:36 -0300662 void *arg, int max_stack)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200663{
Jiri Olsab26b2182015-11-17 16:05:37 +0100664 u64 val;
Jiri Olsacb1dc222015-11-18 08:52:47 +0100665 unw_word_t ips[max_stack];
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200666 unw_addr_space_t addr_space;
667 unw_cursor_t c;
Jiri Olsacb1dc222015-11-18 08:52:47 +0100668 int ret, i = 0;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200669
He Kuang78ff1d62016-06-22 06:57:02 +0000670 ret = perf_reg_value(&val, &ui->sample->user_regs,
671 LIBUNWIND__ARCH_REG_IP);
Jiri Olsab26b2182015-11-17 16:05:37 +0100672 if (ret)
673 return ret;
674
Jiri Olsacb1dc222015-11-18 08:52:47 +0100675 ips[i++] = (unw_word_t) val;
Jiri Olsab26b2182015-11-17 16:05:37 +0100676
Jiri Olsacb1dc222015-11-18 08:52:47 +0100677 /*
678 * If we need more than one entry, do the DWARF
679 * unwind itself.
680 */
681 if (max_stack - 1 > 0) {
Jiri Olsae583d702016-04-07 09:11:12 +0200682 WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
683 addr_space = ui->thread->addr_space;
684
Jiri Olsacb1dc222015-11-18 08:52:47 +0100685 if (addr_space == NULL)
686 return -1;
Jiri Olsab26b2182015-11-17 16:05:37 +0100687
Jiri Olsacb1dc222015-11-18 08:52:47 +0100688 ret = unw_init_remote(&c, addr_space, ui);
689 if (ret)
690 display_error(ret);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200691
Jiri Olsacb1dc222015-11-18 08:52:47 +0100692 while (!ret && (unw_step(&c) > 0) && i < max_stack) {
693 unw_get_reg(&c, UNW_REG_IP, &ips[i]);
694 ++i;
695 }
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200696
Jiri Olsacb1dc222015-11-18 08:52:47 +0100697 max_stack = i;
698 }
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200699
Jiri Olsacb1dc222015-11-18 08:52:47 +0100700 /*
701 * Display what we got based on the order setup.
702 */
703 for (i = 0; i < max_stack && !ret; i++) {
704 int j = i;
705
706 if (callchain_param.order == ORDER_CALLER)
707 j = max_stack - i - 1;
708 ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200709 }
710
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200711 return ret;
712}
713
He Kuangf83c0412016-06-03 03:33:12 +0000714static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
Arnaldo Carvalho de Melodd8c17a2014-10-23 16:42:19 -0300715 struct thread *thread,
Jiri Olsa352ea452014-01-07 13:47:25 +0100716 struct perf_sample *data, int max_stack)
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200717{
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200718 struct unwind_info ui = {
719 .sample = data,
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200720 .thread = thread,
Arnaldo Carvalho de Melodd8c17a2014-10-23 16:42:19 -0300721 .machine = thread->mg->machine,
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200722 };
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200723
724 if (!data->user_regs.regs)
725 return -EINVAL;
726
Jiri Olsab26b2182015-11-17 16:05:37 +0100727 if (max_stack <= 0)
728 return -EINVAL;
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200729
Jiri Olsab26b2182015-11-17 16:05:37 +0100730 return get_entries(&ui, cb, arg, max_stack);
Jiri Olsa71ad0f52012-08-07 15:20:46 +0200731}
He Kuangf83c0412016-06-03 03:33:12 +0000732
733static struct unwind_libunwind_ops
734_unwind_libunwind_ops = {
735 .prepare_access = _unwind__prepare_access,
736 .flush_access = _unwind__flush_access,
737 .finish_access = _unwind__finish_access,
738 .get_entries = _unwind__get_entries,
739};
740
He Kuang19473e72016-06-03 03:33:21 +0000741#ifndef REMOTE_UNWIND_LIBUNWIND
He Kuangf83c0412016-06-03 03:33:12 +0000742struct unwind_libunwind_ops *
743local_unwind_libunwind_ops = &_unwind_libunwind_ops;
He Kuang19473e72016-06-03 03:33:21 +0000744#endif