linux/tools/perf/util/unwind.c
<<
>>
Prefs
   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, NULL);
 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