linux/tools/perf/util/dso.c
<<
>>
Prefs
   1#include "symbol.h"
   2#include "dso.h"
   3#include "machine.h"
   4#include "util.h"
   5#include "debug.h"
   6
   7char dso__symtab_origin(const struct dso *dso)
   8{
   9        static const char origin[] = {
  10                [DSO_BINARY_TYPE__KALLSYMS]                     = 'k',
  11                [DSO_BINARY_TYPE__VMLINUX]                      = 'v',
  12                [DSO_BINARY_TYPE__JAVA_JIT]                     = 'j',
  13                [DSO_BINARY_TYPE__DEBUGLINK]                    = 'l',
  14                [DSO_BINARY_TYPE__BUILD_ID_CACHE]               = 'B',
  15                [DSO_BINARY_TYPE__FEDORA_DEBUGINFO]             = 'f',
  16                [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO]             = 'u',
  17                [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO]       = 'o',
  18                [DSO_BINARY_TYPE__BUILDID_DEBUGINFO]            = 'b',
  19                [DSO_BINARY_TYPE__SYSTEM_PATH_DSO]              = 'd',
  20                [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE]          = 'K',
  21                [DSO_BINARY_TYPE__GUEST_KALLSYMS]               = 'g',
  22                [DSO_BINARY_TYPE__GUEST_KMODULE]                = 'G',
  23                [DSO_BINARY_TYPE__GUEST_VMLINUX]                = 'V',
  24        };
  25
  26        if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
  27                return '!';
  28        return origin[dso->symtab_type];
  29}
  30
  31int dso__read_binary_type_filename(const struct dso *dso,
  32                                   enum dso_binary_type type,
  33                                   char *root_dir, char *filename, size_t size)
  34{
  35        char build_id_hex[BUILD_ID_SIZE * 2 + 1];
  36        int ret = 0;
  37
  38        switch (type) {
  39        case DSO_BINARY_TYPE__DEBUGLINK: {
  40                char *debuglink;
  41
  42                strncpy(filename, dso->long_name, size);
  43                debuglink = filename + dso->long_name_len;
  44                while (debuglink != filename && *debuglink != '/')
  45                        debuglink--;
  46                if (*debuglink == '/')
  47                        debuglink++;
  48                filename__read_debuglink(dso->long_name, debuglink,
  49                                         size - (debuglink - filename));
  50                }
  51                break;
  52        case DSO_BINARY_TYPE__BUILD_ID_CACHE:
  53                /* skip the locally configured cache if a symfs is given */
  54                if (symbol_conf.symfs[0] ||
  55                    (dso__build_id_filename(dso, filename, size) == NULL))
  56                        ret = -1;
  57                break;
  58
  59        case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
  60                snprintf(filename, size, "%s/usr/lib/debug%s.debug",
  61                         symbol_conf.symfs, dso->long_name);
  62                break;
  63
  64        case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
  65                snprintf(filename, size, "%s/usr/lib/debug%s",
  66                         symbol_conf.symfs, dso->long_name);
  67                break;
  68
  69        case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
  70        {
  71                const char *last_slash;
  72                size_t len;
  73                size_t dir_size;
  74
  75                last_slash = dso->long_name + dso->long_name_len;
  76                while (last_slash != dso->long_name && *last_slash != '/')
  77                        last_slash--;
  78
  79                len = scnprintf(filename, size, "%s", symbol_conf.symfs);
  80                dir_size = last_slash - dso->long_name + 2;
  81                if (dir_size > (size - len)) {
  82                        ret = -1;
  83                        break;
  84                }
  85                len += scnprintf(filename + len, dir_size, "%s",  dso->long_name);
  86                len += scnprintf(filename + len , size - len, ".debug%s",
  87                                                                last_slash);
  88                break;
  89        }
  90
  91        case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
  92                if (!dso->has_build_id) {
  93                        ret = -1;
  94                        break;
  95                }
  96
  97                build_id__sprintf(dso->build_id,
  98                                  sizeof(dso->build_id),
  99                                  build_id_hex);
 100                snprintf(filename, size,
 101                         "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
 102                         symbol_conf.symfs, build_id_hex, build_id_hex + 2);
 103                break;
 104
 105        case DSO_BINARY_TYPE__VMLINUX:
 106        case DSO_BINARY_TYPE__GUEST_VMLINUX:
 107        case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
 108                snprintf(filename, size, "%s%s",
 109                         symbol_conf.symfs, dso->long_name);
 110                break;
 111
 112        case DSO_BINARY_TYPE__GUEST_KMODULE:
 113                snprintf(filename, size, "%s%s%s", symbol_conf.symfs,
 114                         root_dir, dso->long_name);
 115                break;
 116
 117        case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
 118                snprintf(filename, size, "%s%s", symbol_conf.symfs,
 119                         dso->long_name);
 120                break;
 121
 122        case DSO_BINARY_TYPE__KCORE:
 123        case DSO_BINARY_TYPE__GUEST_KCORE:
 124                snprintf(filename, size, "%s", dso->long_name);
 125                break;
 126
 127        default:
 128        case DSO_BINARY_TYPE__KALLSYMS:
 129        case DSO_BINARY_TYPE__GUEST_KALLSYMS:
 130        case DSO_BINARY_TYPE__JAVA_JIT:
 131        case DSO_BINARY_TYPE__NOT_FOUND:
 132                ret = -1;
 133                break;
 134        }
 135
 136        return ret;
 137}
 138
 139static int open_dso(struct dso *dso, struct machine *machine)
 140{
 141        int fd;
 142        char *root_dir = (char *)"";
 143        char *name = malloc(PATH_MAX);
 144
 145        if (!name)
 146                return -ENOMEM;
 147
 148        if (machine)
 149                root_dir = machine->root_dir;
 150
 151        if (dso__read_binary_type_filename(dso, dso->binary_type,
 152                                            root_dir, name, PATH_MAX)) {
 153                free(name);
 154                return -EINVAL;
 155        }
 156
 157        fd = open(name, O_RDONLY);
 158        free(name);
 159        return fd;
 160}
 161
 162int dso__data_fd(struct dso *dso, struct machine *machine)
 163{
 164        enum dso_binary_type binary_type_data[] = {
 165                DSO_BINARY_TYPE__BUILD_ID_CACHE,
 166                DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
 167                DSO_BINARY_TYPE__NOT_FOUND,
 168        };
 169        int i = 0;
 170
 171        if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND)
 172                return open_dso(dso, machine);
 173
 174        do {
 175                int fd;
 176
 177                dso->binary_type = binary_type_data[i++];
 178
 179                fd = open_dso(dso, machine);
 180                if (fd >= 0)
 181                        return fd;
 182
 183        } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
 184
 185        return -EINVAL;
 186}
 187
 188static void
 189dso_cache__free(struct rb_root *root)
 190{
 191        struct rb_node *next = rb_first(root);
 192
 193        while (next) {
 194                struct dso_cache *cache;
 195
 196                cache = rb_entry(next, struct dso_cache, rb_node);
 197                next = rb_next(&cache->rb_node);
 198                rb_erase(&cache->rb_node, root);
 199                free(cache);
 200        }
 201}
 202
 203static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
 204{
 205        struct rb_node * const *p = &root->rb_node;
 206        const struct rb_node *parent = NULL;
 207        struct dso_cache *cache;
 208
 209        while (*p != NULL) {
 210                u64 end;
 211
 212                parent = *p;
 213                cache = rb_entry(parent, struct dso_cache, rb_node);
 214                end = cache->offset + DSO__DATA_CACHE_SIZE;
 215
 216                if (offset < cache->offset)
 217                        p = &(*p)->rb_left;
 218                else if (offset >= end)
 219                        p = &(*p)->rb_right;
 220                else
 221                        return cache;
 222        }
 223        return NULL;
 224}
 225
 226static void
 227dso_cache__insert(struct rb_root *root, struct dso_cache *new)
 228{
 229        struct rb_node **p = &root->rb_node;
 230        struct rb_node *parent = NULL;
 231        struct dso_cache *cache;
 232        u64 offset = new->offset;
 233
 234        while (*p != NULL) {
 235                u64 end;
 236
 237                parent = *p;
 238                cache = rb_entry(parent, struct dso_cache, rb_node);
 239                end = cache->offset + DSO__DATA_CACHE_SIZE;
 240
 241                if (offset < cache->offset)
 242                        p = &(*p)->rb_left;
 243                else if (offset >= end)
 244                        p = &(*p)->rb_right;
 245        }
 246
 247        rb_link_node(&new->rb_node, parent, p);
 248        rb_insert_color(&new->rb_node, root);
 249}
 250
 251static ssize_t
 252dso_cache__memcpy(struct dso_cache *cache, u64 offset,
 253                  u8 *data, u64 size)
 254{
 255        u64 cache_offset = offset - cache->offset;
 256        u64 cache_size   = min(cache->size - cache_offset, size);
 257
 258        memcpy(data, cache->data + cache_offset, cache_size);
 259        return cache_size;
 260}
 261
 262static ssize_t
 263dso_cache__read(struct dso *dso, struct machine *machine,
 264                 u64 offset, u8 *data, ssize_t size)
 265{
 266        struct dso_cache *cache;
 267        ssize_t ret;
 268        int fd;
 269
 270        fd = dso__data_fd(dso, machine);
 271        if (fd < 0)
 272                return -1;
 273
 274        do {
 275                u64 cache_offset;
 276
 277                ret = -ENOMEM;
 278
 279                cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
 280                if (!cache)
 281                        break;
 282
 283                cache_offset = offset & DSO__DATA_CACHE_MASK;
 284                ret = -EINVAL;
 285
 286                if (-1 == lseek(fd, cache_offset, SEEK_SET))
 287                        break;
 288
 289                ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
 290                if (ret <= 0)
 291                        break;
 292
 293                cache->offset = cache_offset;
 294                cache->size   = ret;
 295                dso_cache__insert(&dso->cache, cache);
 296
 297                ret = dso_cache__memcpy(cache, offset, data, size);
 298
 299        } while (0);
 300
 301        if (ret <= 0)
 302                free(cache);
 303
 304        close(fd);
 305        return ret;
 306}
 307
 308static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
 309                              u64 offset, u8 *data, ssize_t size)
 310{
 311        struct dso_cache *cache;
 312
 313        cache = dso_cache__find(&dso->cache, offset);
 314        if (cache)
 315                return dso_cache__memcpy(cache, offset, data, size);
 316        else
 317                return dso_cache__read(dso, machine, offset, data, size);
 318}
 319
 320ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
 321                              u64 offset, u8 *data, ssize_t size)
 322{
 323        ssize_t r = 0;
 324        u8 *p = data;
 325
 326        do {
 327                ssize_t ret;
 328
 329                ret = dso_cache_read(dso, machine, offset, p, size);
 330                if (ret < 0)
 331                        return ret;
 332
 333                /* Reached EOF, return what we have. */
 334                if (!ret)
 335                        break;
 336
 337                BUG_ON(ret > size);
 338
 339                r      += ret;
 340                p      += ret;
 341                offset += ret;
 342                size   -= ret;
 343
 344        } while (size);
 345
 346        return r;
 347}
 348
 349ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
 350                            struct machine *machine, u64 addr,
 351                            u8 *data, ssize_t size)
 352{
 353        u64 offset = map->map_ip(map, addr);
 354        return dso__data_read_offset(dso, machine, offset, data, size);
 355}
 356
 357struct map *dso__new_map(const char *name)
 358{
 359        struct map *map = NULL;
 360        struct dso *dso = dso__new(name);
 361
 362        if (dso)
 363                map = map__new2(0, dso, MAP__FUNCTION);
 364
 365        return map;
 366}
 367
 368struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
 369                    const char *short_name, int dso_type)
 370{
 371        /*
 372         * The kernel dso could be created by build_id processing.
 373         */
 374        struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
 375
 376        /*
 377         * We need to run this in all cases, since during the build_id
 378         * processing we had no idea this was the kernel dso.
 379         */
 380        if (dso != NULL) {
 381                dso__set_short_name(dso, short_name, false);
 382                dso->kernel = dso_type;
 383        }
 384
 385        return dso;
 386}
 387
 388void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
 389{
 390        if (name == NULL)
 391                return;
 392
 393        if (dso->long_name_allocated)
 394                free((char *)dso->long_name);
 395
 396        dso->long_name           = name;
 397        dso->long_name_len       = strlen(name);
 398        dso->long_name_allocated = name_allocated;
 399}
 400
 401void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
 402{
 403        if (name == NULL)
 404                return;
 405
 406        if (dso->short_name_allocated)
 407                free((char *)dso->short_name);
 408
 409        dso->short_name           = name;
 410        dso->short_name_len       = strlen(name);
 411        dso->short_name_allocated = name_allocated;
 412}
 413
 414static void dso__set_basename(struct dso *dso)
 415{
 416       /*
 417        * basename() may modify path buffer, so we must pass
 418        * a copy.
 419        */
 420       char *base, *lname = strdup(dso->long_name);
 421
 422       if (!lname)
 423               return;
 424
 425       /*
 426        * basename() may return a pointer to internal
 427        * storage which is reused in subsequent calls
 428        * so copy the result.
 429        */
 430       base = strdup(basename(lname));
 431
 432       free(lname);
 433
 434       if (!base)
 435               return;
 436
 437       dso__set_short_name(dso, base, true);
 438}
 439
 440int dso__name_len(const struct dso *dso)
 441{
 442        if (!dso)
 443                return strlen("[unknown]");
 444        if (verbose)
 445                return dso->long_name_len;
 446
 447        return dso->short_name_len;
 448}
 449
 450bool dso__loaded(const struct dso *dso, enum map_type type)
 451{
 452        return dso->loaded & (1 << type);
 453}
 454
 455bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
 456{
 457        return dso->sorted_by_name & (1 << type);
 458}
 459
 460void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
 461{
 462        dso->sorted_by_name |= (1 << type);
 463}
 464
 465struct dso *dso__new(const char *name)
 466{
 467        struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
 468
 469        if (dso != NULL) {
 470                int i;
 471                strcpy(dso->name, name);
 472                dso__set_long_name(dso, dso->name, false);
 473                dso__set_short_name(dso, dso->name, false);
 474                for (i = 0; i < MAP__NR_TYPES; ++i)
 475                        dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
 476                dso->cache = RB_ROOT;
 477                dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
 478                dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
 479                dso->loaded = 0;
 480                dso->rel = 0;
 481                dso->sorted_by_name = 0;
 482                dso->has_build_id = 0;
 483                dso->has_srcline = 1;
 484                dso->a2l_fails = 1;
 485                dso->kernel = DSO_TYPE_USER;
 486                dso->needs_swap = DSO_SWAP__UNSET;
 487                INIT_LIST_HEAD(&dso->node);
 488        }
 489
 490        return dso;
 491}
 492
 493void dso__delete(struct dso *dso)
 494{
 495        int i;
 496        for (i = 0; i < MAP__NR_TYPES; ++i)
 497                symbols__delete(&dso->symbols[i]);
 498
 499        if (dso->short_name_allocated) {
 500                zfree((char **)&dso->short_name);
 501                dso->short_name_allocated = false;
 502        }
 503
 504        if (dso->long_name_allocated) {
 505                zfree((char **)&dso->long_name);
 506                dso->long_name_allocated = false;
 507        }
 508
 509        dso_cache__free(&dso->cache);
 510        dso__free_a2l(dso);
 511        zfree(&dso->symsrc_filename);
 512        free(dso);
 513}
 514
 515void dso__set_build_id(struct dso *dso, void *build_id)
 516{
 517        memcpy(dso->build_id, build_id, sizeof(dso->build_id));
 518        dso->has_build_id = 1;
 519}
 520
 521bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
 522{
 523        return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
 524}
 525
 526void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
 527{
 528        char path[PATH_MAX];
 529
 530        if (machine__is_default_guest(machine))
 531                return;
 532        sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
 533        if (sysfs__read_build_id(path, dso->build_id,
 534                                 sizeof(dso->build_id)) == 0)
 535                dso->has_build_id = true;
 536}
 537
 538int dso__kernel_module_get_build_id(struct dso *dso,
 539                                    const char *root_dir)
 540{
 541        char filename[PATH_MAX];
 542        /*
 543         * kernel module short names are of the form "[module]" and
 544         * we need just "module" here.
 545         */
 546        const char *name = dso->short_name + 1;
 547
 548        snprintf(filename, sizeof(filename),
 549                 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
 550                 root_dir, (int)strlen(name) - 1, name);
 551
 552        if (sysfs__read_build_id(filename, dso->build_id,
 553                                 sizeof(dso->build_id)) == 0)
 554                dso->has_build_id = true;
 555
 556        return 0;
 557}
 558
 559bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
 560{
 561        bool have_build_id = false;
 562        struct dso *pos;
 563
 564        list_for_each_entry(pos, head, node) {
 565                if (with_hits && !pos->hit)
 566                        continue;
 567                if (pos->has_build_id) {
 568                        have_build_id = true;
 569                        continue;
 570                }
 571                if (filename__read_build_id(pos->long_name, pos->build_id,
 572                                            sizeof(pos->build_id)) > 0) {
 573                        have_build_id     = true;
 574                        pos->has_build_id = true;
 575                }
 576        }
 577
 578        return have_build_id;
 579}
 580
 581void dsos__add(struct list_head *head, struct dso *dso)
 582{
 583        list_add_tail(&dso->node, head);
 584}
 585
 586struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short)
 587{
 588        struct dso *pos;
 589
 590        if (cmp_short) {
 591                list_for_each_entry(pos, head, node)
 592                        if (strcmp(pos->short_name, name) == 0)
 593                                return pos;
 594                return NULL;
 595        }
 596        list_for_each_entry(pos, head, node)
 597                if (strcmp(pos->long_name, name) == 0)
 598                        return pos;
 599        return NULL;
 600}
 601
 602struct dso *__dsos__findnew(struct list_head *head, const char *name)
 603{
 604        struct dso *dso = dsos__find(head, name, false);
 605
 606        if (!dso) {
 607                dso = dso__new(name);
 608                if (dso != NULL) {
 609                        dsos__add(head, dso);
 610                        dso__set_basename(dso);
 611                }
 612        }
 613
 614        return dso;
 615}
 616
 617size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
 618                               bool (skip)(struct dso *dso, int parm), int parm)
 619{
 620        struct dso *pos;
 621        size_t ret = 0;
 622
 623        list_for_each_entry(pos, head, node) {
 624                if (skip && skip(pos, parm))
 625                        continue;
 626                ret += dso__fprintf_buildid(pos, fp);
 627                ret += fprintf(fp, " %s\n", pos->long_name);
 628        }
 629        return ret;
 630}
 631
 632size_t __dsos__fprintf(struct list_head *head, FILE *fp)
 633{
 634        struct dso *pos;
 635        size_t ret = 0;
 636
 637        list_for_each_entry(pos, head, node) {
 638                int i;
 639                for (i = 0; i < MAP__NR_TYPES; ++i)
 640                        ret += dso__fprintf(pos, i, fp);
 641        }
 642
 643        return ret;
 644}
 645
 646size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
 647{
 648        char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 649
 650        build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
 651        return fprintf(fp, "%s", sbuild_id);
 652}
 653
 654size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
 655{
 656        struct rb_node *nd;
 657        size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
 658
 659        if (dso->short_name != dso->long_name)
 660                ret += fprintf(fp, "%s, ", dso->long_name);
 661        ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
 662                       dso__loaded(dso, type) ? "" : "NOT ");
 663        ret += dso__fprintf_buildid(dso, fp);
 664        ret += fprintf(fp, ")\n");
 665        for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
 666                struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
 667                ret += symbol__fprintf(pos, fp);
 668        }
 669
 670        return ret;
 671}
 672