1/* 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> 21#include <string.h> 22#include <unistd.h> 23#include <sys/mman.h> 24#include <linux/list.h> 25#include <libunwind.h> 26#include <libunwind-ptrace.h> 27#include "thread.h" 28#include "session.h" 29#include "perf_regs.h" 30#include "unwind.h" 31#include "util.h" 32 33extern int 34UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, 35 unw_word_t ip, 36 unw_dyn_info_t *di, 37 unw_proc_info_t *pi, 38 int need_unwind_info, void *arg); 39 40#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) 41 42#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ 43#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ 44 45/* Pointer-encoding formats: */ 46#define DW_EH_PE_omit 0xff 47#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ 48#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ 49#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ 50#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ 51#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ 52 53/* Pointer-encoding application: */ 54#define DW_EH_PE_absptr 0x00 /* absolute value */ 55#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ 56 57/* 58 * The following are not documented by LSB v1.3, yet they are used by 59 * GCC, presumably they aren't documented by LSB since they aren't 60 * used on Linux: 61 */ 62#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ 63#define DW_EH_PE_aligned 0x50 /* aligned pointer */ 64 65/* Flags intentionaly not handled, since they're not needed: 66 * #define DW_EH_PE_indirect 0x80 67 * #define DW_EH_PE_uleb128 0x01 68 * #define DW_EH_PE_udata2 0x02 69 * #define DW_EH_PE_sleb128 0x09 70 * #define DW_EH_PE_sdata2 0x0a 71 * #define DW_EH_PE_textrel 0x20 72 * #define DW_EH_PE_datarel 0x30 73 */ 74 75struct unwind_info { 76 struct perf_sample *sample; 77 struct machine *machine; 78 struct thread *thread; 79 u64 sample_uregs; 80}; 81 82#define dw_read(ptr, type, end) ({ \ 83 type *__p = (type *) ptr; \ 84 type __v; \ 85 if ((__p + 1) > (type *) end) \ 86 return -EINVAL; \ 87 __v = *__p++; \ 88 ptr = (typeof(ptr)) __p; \ 89 __v; \ 90 }) 91 92static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, 93 u8 encoding) 94{ 95 u8 *cur = *p; 96 *val = 0; 97 98 switch (encoding) { 99 case DW_EH_PE_omit: 100 *val = 0; 101 goto out; 102 case DW_EH_PE_ptr: 103 *val = dw_read(cur, unsigned long, end); 104 goto out; 105 default: 106 break; 107 } 108 109 switch (encoding & DW_EH_PE_APPL_MASK) { 110 case DW_EH_PE_absptr: 111 break; 112 case DW_EH_PE_pcrel: 113 *val = (unsigned long) cur; 114 break; 115 default: 116 return -EINVAL; 117 } 118 119 if ((encoding & 0x07) == 0x00) 120 encoding |= DW_EH_PE_udata4; 121 122 switch (encoding & DW_EH_PE_FORMAT_MASK) { 123 case DW_EH_PE_sdata4: 124 *val += dw_read(cur, s32, end); 125 break; 126 case DW_EH_PE_udata4: 127 *val += dw_read(cur, u32, end); 128 break; 129 case DW_EH_PE_sdata8: 130 *val += dw_read(cur, s64, end); 131 break; 132 case DW_EH_PE_udata8: 133 *val += dw_read(cur, u64, end); 134 break; 135 default: 136 return -EINVAL; 137 } 138 139 out: 140 *p = cur; 141 return 0; 142} 143 144#define dw_read_encoded_value(ptr, end, enc) ({ \ 145 u64 __v; \ 146 if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \ 147 return -EINVAL; \ 148 } \ 149 __v; \ 150 }) 151 152static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 153 GElf_Shdr *shp, const char *name) 154{ 155 Elf_Scn *sec = NULL; 156 157 while ((sec = elf_nextscn(elf, sec)) != NULL) { 158 char *str; 159 160 gelf_getshdr(sec, shp); 161 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); 162 if (!strcmp(name, str)) 163 break; 164 } 165 166 return sec; 167} 168 169static u64 elf_section_offset(int fd, const char *name) 170{ 171 Elf *elf; 172 GElf_Ehdr ehdr; 173 GElf_Shdr shdr; 174 u64 offset = 0; 175 176 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 177 if (elf == NULL) 178 return 0; 179 180 do { 181 if (gelf_getehdr(elf, &ehdr) == NULL) 182 break; 183 184 if (!elf_section_by_name(elf, &ehdr, &shdr, name)) 185 break; 186 187 offset = shdr.sh_offset; 188 } while (0); 189 190 elf_end(elf); 191 return offset; 192} 193 194struct table_entry { 195 u32 start_ip_offset; 196 u32 fde_offset; 197}; 198 199struct eh_frame_hdr { 200 unsigned char version; 201 unsigned char eh_frame_ptr_enc; 202 unsigned char fde_count_enc; 203 unsigned char table_enc; 204 205 /* 206 * The rest of the header is variable-length and consists of the 207 * following members: 208 * 209 * encoded_t eh_frame_ptr; 210 * encoded_t fde_count; 211 */ 212 213 /* A single encoded pointer should not be more than 8 bytes. */ 214 u64 enc[2]; 215 216 /* 217 * struct { 218 * encoded_t start_ip; 219 * encoded_t fde_addr; 220 * } binary_search_table[fde_count]; 221 */ 222 char data[0]; 223} __packed; 224 225static int unwind_spec_ehframe(struct dso *dso, struct machine *machine, 226 u64 offset, u64 *table_data, u64 *segbase, 227 u64 *fde_count) 228{ 229 struct eh_frame_hdr hdr; 230 u8 *enc = (u8 *) &hdr.enc; 231 u8 *end = (u8 *) &hdr.data; 232 ssize_t r; 233 234 r = dso__data_read_offset(dso, machine, offset, 235 (u8 *) &hdr, sizeof(hdr)); 236 if (r != sizeof(hdr)) 237 return -EINVAL; 238 239 /* We dont need eh_frame_ptr, just skip it. */ 240 dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc); 241 242 *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc); 243 *segbase = offset; 244 *table_data = (enc - (u8 *) &hdr) + offset; 245 return 0; 246} 247 248static int read_unwind_spec(struct dso *dso, struct machine *machine, 249 u64 *table_data, u64 *segbase, u64 *fde_count) 250{ 251 int ret = -EINVAL, fd; 252 u64 offset; 253 254 fd = dso__data_fd(dso, machine); 255 if (fd < 0) 256 return -EINVAL; 257 258 offset = elf_section_offset(fd, ".eh_frame_hdr"); 259 close(fd); 260 261 if (offset) 262 ret = unwind_spec_ehframe(dso, machine, offset, 263 table_data, segbase, 264 fde_count); 265 266 /* TODO .debug_frame check if eh_frame_hdr fails */ 267 return ret; 268} 269 270static struct map *find_map(unw_word_t ip, struct unwind_info *ui) 271{ 272 struct addr_location al; 273 274 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 275 MAP__FUNCTION, ip, &al); 276 return al.map; 277} 278 279static int 280find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, 281 int need_unwind_info, void *arg) 282{ 283 struct unwind_info *ui = arg; 284 struct map *map; 285 unw_dyn_info_t di; 286 u64 table_data, segbase, fde_count; 287 288 map = find_map(ip, ui); 289 if (!map || !map->dso) 290 return -EINVAL; 291 292 pr_debug("unwind: find_proc_info dso %s\n", map->dso->name); 293 294 if (read_unwind_spec(map->dso, ui->machine, 295 &table_data, &segbase, &fde_count)) 296 return -EINVAL; 297 298 memset(&di, 0, sizeof(di)); 299 di.format = UNW_INFO_FORMAT_REMOTE_TABLE; 300 di.start_ip = map->start; 301 di.end_ip = map->end; 302 di.u.rti.segbase = map->start + segbase; 303 di.u.rti.table_data = map->start + table_data; 304 di.u.rti.table_len = fde_count * sizeof(struct table_entry) 305 / sizeof(unw_word_t); 306 return dwarf_search_unwind_table(as, ip, &di, pi, 307 need_unwind_info, arg); 308} 309 310static int access_fpreg(unw_addr_space_t __maybe_unused as, 311 unw_regnum_t __maybe_unused num, 312 unw_fpreg_t __maybe_unused *val, 313 int __maybe_unused __write, 314 void __maybe_unused *arg) 315{ 316 pr_err("unwind: access_fpreg unsupported\n"); 317 return -UNW_EINVAL; 318} 319 320static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, 321 unw_word_t __maybe_unused *dil_addr, 322 void __maybe_unused *arg) 323{ 324 return -UNW_ENOINFO; 325} 326 327static int resume(unw_addr_space_t __maybe_unused as, 328 unw_cursor_t __maybe_unused *cu, 329 void __maybe_unused *arg) 330{ 331 pr_err("unwind: resume unsupported\n"); 332 return -UNW_EINVAL; 333} 334 335static int 336get_proc_name(unw_addr_space_t __maybe_unused as, 337 unw_word_t __maybe_unused addr, 338 char __maybe_unused *bufp, size_t __maybe_unused buf_len, 339 unw_word_t __maybe_unused *offp, void __maybe_unused *arg) 340{ 341 pr_err("unwind: get_proc_name unsupported\n"); 342 return -UNW_EINVAL; 343} 344 345static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, 346 unw_word_t *data) 347{ 348 struct addr_location al; 349 ssize_t size; 350 351 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 352 MAP__FUNCTION, addr, &al); 353 if (!al.map) { 354 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 355 return -1; 356 } 357 358 if (!al.map->dso) 359 return -1; 360 361 size = dso__data_read_addr(al.map->dso, al.map, ui->machine, 362 addr, (u8 *) data, sizeof(*data)); 363 364 return !(size == sizeof(*data)); 365} 366 367static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id, 368 u64 sample_regs) 369{ 370 int i, idx = 0; 371 372 if (!(sample_regs & (1 << id))) 373 return -EINVAL; 374 375 for (i = 0; i < id; i++) { 376 if (sample_regs & (1 << i)) 377 idx++; 378 } 379 380 *valp = regs->regs[idx]; 381 return 0; 382} 383 384static int access_mem(unw_addr_space_t __maybe_unused as, 385 unw_word_t addr, unw_word_t *valp, 386 int __write, void *arg) 387{ 388 struct unwind_info *ui = arg; 389 struct stack_dump *stack = &ui->sample->user_stack; 390 unw_word_t start, end; 391 int offset; 392 int ret; 393 394 /* Don't support write, probably not needed. */ 395 if (__write || !stack || !ui->sample->user_regs.regs) { 396 *valp = 0; 397 return 0; 398 } 399 400 ret = reg_value(&start, &ui->sample->user_regs, PERF_REG_SP, 401 ui->sample_uregs); 402 if (ret) 403 return ret; 404 405 end = start + stack->size; 406 407 /* Check overflow. */ 408 if (addr + sizeof(unw_word_t) < addr) 409 return -EINVAL; 410 411 if (addr < start || addr + sizeof(unw_word_t) >= end) { 412 ret = access_dso_mem(ui, addr, valp); 413 if (ret) { 414 pr_debug("unwind: access_mem %p not inside range %p-%p\n", 415 (void *)addr, (void *)start, (void *)end); 416 *valp = 0; 417 return ret; 418 } 419 return 0; 420 } 421 422 offset = addr - start; 423 *valp = *(unw_word_t *)&stack->data[offset]; 424 pr_debug("unwind: access_mem addr %p, val %lx, offset %d\n", 425 (void *)addr, (unsigned long)*valp, offset); 426 return 0; 427} 428 429static int access_reg(unw_addr_space_t __maybe_unused as, 430 unw_regnum_t regnum, unw_word_t *valp, 431 int __write, void *arg) 432{ 433 struct unwind_info *ui = arg; 434 int id, ret; 435 436 /* Don't support write, I suspect we don't need it. */ 437 if (__write) { 438 pr_err("unwind: access_reg w %d\n", regnum); 439 return 0; 440 } 441 442 if (!ui->sample->user_regs.regs) { 443 *valp = 0; 444 return 0; 445 } 446 447 id = unwind__arch_reg_id(regnum); 448 if (id < 0) 449 return -EINVAL; 450 451 ret = reg_value(valp, &ui->sample->user_regs, id, ui->sample_uregs); 452 if (ret) { 453 pr_err("unwind: can't read reg %d\n", regnum); 454 return ret; 455 } 456 457 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); 458 return 0; 459} 460 461static void put_unwind_info(unw_addr_space_t __maybe_unused as, 462 unw_proc_info_t *pi __maybe_unused, 463 void *arg __maybe_unused) 464{ 465 pr_debug("unwind: put_unwind_info called\n"); 466} 467 468static int entry(u64 ip, struct thread *thread, struct machine *machine, 469 unwind_entry_cb_t cb, void *arg) 470{ 471 struct unwind_entry e; 472 struct addr_location al; 473 474 thread__find_addr_location(thread, machine, 475 PERF_RECORD_MISC_USER, 476 MAP__FUNCTION, ip, &al); 477 478 e.ip = ip; 479 e.map = al.map; 480 e.sym = al.sym; 481 482 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", 483 al.sym ? al.sym->name : "''", 484 ip, 485 al.map ? al.map->map_ip(al.map, ip) : (u64) 0); 486 487 return cb(&e, arg); 488} 489 490static void display_error(int err) 491{ 492 switch (err) { 493 case UNW_EINVAL: 494 pr_err("unwind: Only supports local.\n"); 495 break; 496 case UNW_EUNSPEC: 497 pr_err("unwind: Unspecified error.\n"); 498 break; 499 case UNW_EBADREG: 500 pr_err("unwind: Register unavailable.\n"); 501 break; 502 default: 503 break; 504 } 505} 506 507static unw_accessors_t accessors = { 508 .find_proc_info = find_proc_info, 509 .put_unwind_info = put_unwind_info, 510 .get_dyn_info_list_addr = get_dyn_info_list_addr, 511 .access_mem = access_mem, 512 .access_reg = access_reg, 513 .access_fpreg = access_fpreg, 514 .resume = resume, 515 .get_proc_name = get_proc_name, 516}; 517 518static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, 519 void *arg) 520{ 521 unw_addr_space_t addr_space; 522 unw_cursor_t c; 523 int ret; 524 525 addr_space = unw_create_addr_space(&accessors, 0); 526 if (!addr_space) { 527 pr_err("unwind: Can't create unwind address space.\n"); 528 return -ENOMEM; 529 } 530 531 ret = unw_init_remote(&c, addr_space, ui); 532 if (ret) 533 display_error(ret); 534 535 while (!ret && (unw_step(&c) > 0)) { 536 unw_word_t ip; 537 538 unw_get_reg(&c, UNW_REG_IP, &ip); 539 ret = entry(ip, ui->thread, ui->machine, cb, arg); 540 } 541 542 unw_destroy_addr_space(addr_space); 543 return ret; 544} 545 546int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 547 struct machine *machine, struct thread *thread, 548 u64 sample_uregs, struct perf_sample *data) 549{ 550 unw_word_t ip; 551 struct unwind_info ui = { 552 .sample = data, 553 .sample_uregs = sample_uregs, 554 .thread = thread, 555 .machine = machine, 556 }; 557 int ret; 558 559 if (!data->user_regs.regs) 560 return -EINVAL; 561 562 ret = reg_value(&ip, &data->user_regs, PERF_REG_IP, sample_uregs); 563 if (ret) 564 return ret; 565 566 ret = entry(ip, thread, machine, cb, arg); 567 if (ret) 568 return -ENOMEM; 569 570 return get_entries(&ui, cb, arg); 571} 572