linux/tools/perf/util/symbol-elf.c
<<
>>
Prefs
   1#include <fcntl.h>
   2#include <stdio.h>
   3#include <errno.h>
   4#include <string.h>
   5#include <unistd.h>
   6#include <inttypes.h>
   7
   8#include "symbol.h"
   9#include "machine.h"
  10#include "vdso.h"
  11#include <symbol/kallsyms.h>
  12#include "debug.h"
  13
  14#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
  15static int elf_getphdrnum(Elf *elf, size_t *dst)
  16{
  17        GElf_Ehdr gehdr;
  18        GElf_Ehdr *ehdr;
  19
  20        ehdr = gelf_getehdr(elf, &gehdr);
  21        if (!ehdr)
  22                return -1;
  23
  24        *dst = ehdr->e_phnum;
  25
  26        return 0;
  27}
  28#endif
  29
  30#ifndef NT_GNU_BUILD_ID
  31#define NT_GNU_BUILD_ID 3
  32#endif
  33
  34/**
  35 * elf_symtab__for_each_symbol - iterate thru all the symbols
  36 *
  37 * @syms: struct elf_symtab instance to iterate
  38 * @idx: uint32_t idx
  39 * @sym: GElf_Sym iterator
  40 */
  41#define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \
  42        for (idx = 0, gelf_getsym(syms, idx, &sym);\
  43             idx < nr_syms; \
  44             idx++, gelf_getsym(syms, idx, &sym))
  45
  46static inline uint8_t elf_sym__type(const GElf_Sym *sym)
  47{
  48        return GELF_ST_TYPE(sym->st_info);
  49}
  50
  51static inline int elf_sym__is_function(const GElf_Sym *sym)
  52{
  53        return (elf_sym__type(sym) == STT_FUNC ||
  54                elf_sym__type(sym) == STT_GNU_IFUNC) &&
  55               sym->st_name != 0 &&
  56               sym->st_shndx != SHN_UNDEF;
  57}
  58
  59static inline bool elf_sym__is_object(const GElf_Sym *sym)
  60{
  61        return elf_sym__type(sym) == STT_OBJECT &&
  62                sym->st_name != 0 &&
  63                sym->st_shndx != SHN_UNDEF;
  64}
  65
  66static inline int elf_sym__is_label(const GElf_Sym *sym)
  67{
  68        return elf_sym__type(sym) == STT_NOTYPE &&
  69                sym->st_name != 0 &&
  70                sym->st_shndx != SHN_UNDEF &&
  71                sym->st_shndx != SHN_ABS;
  72}
  73
  74static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type)
  75{
  76        switch (type) {
  77        case MAP__FUNCTION:
  78                return elf_sym__is_function(sym);
  79        case MAP__VARIABLE:
  80                return elf_sym__is_object(sym);
  81        default:
  82                return false;
  83        }
  84}
  85
  86static inline const char *elf_sym__name(const GElf_Sym *sym,
  87                                        const Elf_Data *symstrs)
  88{
  89        return symstrs->d_buf + sym->st_name;
  90}
  91
  92static inline const char *elf_sec__name(const GElf_Shdr *shdr,
  93                                        const Elf_Data *secstrs)
  94{
  95        return secstrs->d_buf + shdr->sh_name;
  96}
  97
  98static inline int elf_sec__is_text(const GElf_Shdr *shdr,
  99                                        const Elf_Data *secstrs)
 100{
 101        return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
 102}
 103
 104static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
 105                                    const Elf_Data *secstrs)
 106{
 107        return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
 108}
 109
 110static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs,
 111                          enum map_type type)
 112{
 113        switch (type) {
 114        case MAP__FUNCTION:
 115                return elf_sec__is_text(shdr, secstrs);
 116        case MAP__VARIABLE:
 117                return elf_sec__is_data(shdr, secstrs);
 118        default:
 119                return false;
 120        }
 121}
 122
 123static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
 124{
 125        Elf_Scn *sec = NULL;
 126        GElf_Shdr shdr;
 127        size_t cnt = 1;
 128
 129        while ((sec = elf_nextscn(elf, sec)) != NULL) {
 130                gelf_getshdr(sec, &shdr);
 131
 132                if ((addr >= shdr.sh_addr) &&
 133                    (addr < (shdr.sh_addr + shdr.sh_size)))
 134                        return cnt;
 135
 136                ++cnt;
 137        }
 138
 139        return -1;
 140}
 141
 142Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
 143                             GElf_Shdr *shp, const char *name, size_t *idx)
 144{
 145        Elf_Scn *sec = NULL;
 146        size_t cnt = 1;
 147
 148        /* Elf is corrupted/truncated, avoid calling elf_strptr. */
 149        if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL))
 150                return NULL;
 151
 152        while ((sec = elf_nextscn(elf, sec)) != NULL) {
 153                char *str;
 154
 155                gelf_getshdr(sec, shp);
 156                str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
 157                if (str && !strcmp(name, str)) {
 158                        if (idx)
 159                                *idx = cnt;
 160                        return sec;
 161                }
 162                ++cnt;
 163        }
 164
 165        return NULL;
 166}
 167
 168#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
 169        for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
 170             idx < nr_entries; \
 171             ++idx, pos = gelf_getrel(reldata, idx, &pos_mem))
 172
 173#define elf_section__for_each_rela(reldata, pos, pos_mem, idx, nr_entries) \
 174        for (idx = 0, pos = gelf_getrela(reldata, 0, &pos_mem); \
 175             idx < nr_entries; \
 176             ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
 177
 178/*
 179 * We need to check if we have a .dynsym, so that we can handle the
 180 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
 181 * .dynsym or .symtab).
 182 * And always look at the original dso, not at debuginfo packages, that
 183 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
 184 */
 185int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map,
 186                                symbol_filter_t filter)
 187{
 188        uint32_t nr_rel_entries, idx;
 189        GElf_Sym sym;
 190        u64 plt_offset;
 191        GElf_Shdr shdr_plt;
 192        struct symbol *f;
 193        GElf_Shdr shdr_rel_plt, shdr_dynsym;
 194        Elf_Data *reldata, *syms, *symstrs;
 195        Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
 196        size_t dynsym_idx;
 197        GElf_Ehdr ehdr;
 198        char sympltname[1024];
 199        Elf *elf;
 200        int nr = 0, symidx, err = 0;
 201
 202        if (!ss->dynsym)
 203                return 0;
 204
 205        elf = ss->elf;
 206        ehdr = ss->ehdr;
 207
 208        scn_dynsym = ss->dynsym;
 209        shdr_dynsym = ss->dynshdr;
 210        dynsym_idx = ss->dynsym_idx;
 211
 212        if (scn_dynsym == NULL)
 213                goto out_elf_end;
 214
 215        scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
 216                                          ".rela.plt", NULL);
 217        if (scn_plt_rel == NULL) {
 218                scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
 219                                                  ".rel.plt", NULL);
 220                if (scn_plt_rel == NULL)
 221                        goto out_elf_end;
 222        }
 223
 224        err = -1;
 225
 226        if (shdr_rel_plt.sh_link != dynsym_idx)
 227                goto out_elf_end;
 228
 229        if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
 230                goto out_elf_end;
 231
 232        /*
 233         * Fetch the relocation section to find the idxes to the GOT
 234         * and the symbols in the .dynsym they refer to.
 235         */
 236        reldata = elf_getdata(scn_plt_rel, NULL);
 237        if (reldata == NULL)
 238                goto out_elf_end;
 239
 240        syms = elf_getdata(scn_dynsym, NULL);
 241        if (syms == NULL)
 242                goto out_elf_end;
 243
 244        scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
 245        if (scn_symstrs == NULL)
 246                goto out_elf_end;
 247
 248        symstrs = elf_getdata(scn_symstrs, NULL);
 249        if (symstrs == NULL)
 250                goto out_elf_end;
 251
 252        if (symstrs->d_size == 0)
 253                goto out_elf_end;
 254
 255        nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
 256        plt_offset = shdr_plt.sh_offset;
 257
 258        if (shdr_rel_plt.sh_type == SHT_RELA) {
 259                GElf_Rela pos_mem, *pos;
 260
 261                elf_section__for_each_rela(reldata, pos, pos_mem, idx,
 262                                           nr_rel_entries) {
 263                        symidx = GELF_R_SYM(pos->r_info);
 264                        plt_offset += shdr_plt.sh_entsize;
 265                        gelf_getsym(syms, symidx, &sym);
 266                        snprintf(sympltname, sizeof(sympltname),
 267                                 "%s@plt", elf_sym__name(&sym, symstrs));
 268
 269                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
 270                                        STB_GLOBAL, sympltname);
 271                        if (!f)
 272                                goto out_elf_end;
 273
 274                        if (filter && filter(map, f))
 275                                symbol__delete(f);
 276                        else {
 277                                symbols__insert(&dso->symbols[map->type], f);
 278                                ++nr;
 279                        }
 280                }
 281        } else if (shdr_rel_plt.sh_type == SHT_REL) {
 282                GElf_Rel pos_mem, *pos;
 283                elf_section__for_each_rel(reldata, pos, pos_mem, idx,
 284                                          nr_rel_entries) {
 285                        symidx = GELF_R_SYM(pos->r_info);
 286                        plt_offset += shdr_plt.sh_entsize;
 287                        gelf_getsym(syms, symidx, &sym);
 288                        snprintf(sympltname, sizeof(sympltname),
 289                                 "%s@plt", elf_sym__name(&sym, symstrs));
 290
 291                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
 292                                        STB_GLOBAL, sympltname);
 293                        if (!f)
 294                                goto out_elf_end;
 295
 296                        if (filter && filter(map, f))
 297                                symbol__delete(f);
 298                        else {
 299                                symbols__insert(&dso->symbols[map->type], f);
 300                                ++nr;
 301                        }
 302                }
 303        }
 304
 305        err = 0;
 306out_elf_end:
 307        if (err == 0)
 308                return nr;
 309        pr_debug("%s: problems reading %s PLT info.\n",
 310                 __func__, dso->long_name);
 311        return 0;
 312}
 313
 314/*
 315 * Align offset to 4 bytes as needed for note name and descriptor data.
 316 */
 317#define NOTE_ALIGN(n) (((n) + 3) & -4U)
 318
 319static int elf_read_build_id(Elf *elf, void *bf, size_t size)
 320{
 321        int err = -1;
 322        GElf_Ehdr ehdr;
 323        GElf_Shdr shdr;
 324        Elf_Data *data;
 325        Elf_Scn *sec;
 326        Elf_Kind ek;
 327        void *ptr;
 328
 329        if (size < BUILD_ID_SIZE)
 330                goto out;
 331
 332        ek = elf_kind(elf);
 333        if (ek != ELF_K_ELF)
 334                goto out;
 335
 336        if (gelf_getehdr(elf, &ehdr) == NULL) {
 337                pr_err("%s: cannot get elf header.\n", __func__);
 338                goto out;
 339        }
 340
 341        /*
 342         * Check following sections for notes:
 343         *   '.note.gnu.build-id'
 344         *   '.notes'
 345         *   '.note' (VDSO specific)
 346         */
 347        do {
 348                sec = elf_section_by_name(elf, &ehdr, &shdr,
 349                                          ".note.gnu.build-id", NULL);
 350                if (sec)
 351                        break;
 352
 353                sec = elf_section_by_name(elf, &ehdr, &shdr,
 354                                          ".notes", NULL);
 355                if (sec)
 356                        break;
 357
 358                sec = elf_section_by_name(elf, &ehdr, &shdr,
 359                                          ".note", NULL);
 360                if (sec)
 361                        break;
 362
 363                return err;
 364
 365        } while (0);
 366
 367        data = elf_getdata(sec, NULL);
 368        if (data == NULL)
 369                goto out;
 370
 371        ptr = data->d_buf;
 372        while (ptr < (data->d_buf + data->d_size)) {
 373                GElf_Nhdr *nhdr = ptr;
 374                size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
 375                       descsz = NOTE_ALIGN(nhdr->n_descsz);
 376                const char *name;
 377
 378                ptr += sizeof(*nhdr);
 379                name = ptr;
 380                ptr += namesz;
 381                if (nhdr->n_type == NT_GNU_BUILD_ID &&
 382                    nhdr->n_namesz == sizeof("GNU")) {
 383                        if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
 384                                size_t sz = min(size, descsz);
 385                                memcpy(bf, ptr, sz);
 386                                memset(bf + sz, 0, size - sz);
 387                                err = descsz;
 388                                break;
 389                        }
 390                }
 391                ptr += descsz;
 392        }
 393
 394out:
 395        return err;
 396}
 397
 398int filename__read_build_id(const char *filename, void *bf, size_t size)
 399{
 400        int fd, err = -1;
 401        Elf *elf;
 402
 403        if (size < BUILD_ID_SIZE)
 404                goto out;
 405
 406        fd = open(filename, O_RDONLY);
 407        if (fd < 0)
 408                goto out;
 409
 410        elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
 411        if (elf == NULL) {
 412                pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
 413                goto out_close;
 414        }
 415
 416        err = elf_read_build_id(elf, bf, size);
 417
 418        elf_end(elf);
 419out_close:
 420        close(fd);
 421out:
 422        return err;
 423}
 424
 425int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
 426{
 427        int fd, err = -1;
 428
 429        if (size < BUILD_ID_SIZE)
 430                goto out;
 431
 432        fd = open(filename, O_RDONLY);
 433        if (fd < 0)
 434                goto out;
 435
 436        while (1) {
 437                char bf[BUFSIZ];
 438                GElf_Nhdr nhdr;
 439                size_t namesz, descsz;
 440
 441                if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
 442                        break;
 443
 444                namesz = NOTE_ALIGN(nhdr.n_namesz);
 445                descsz = NOTE_ALIGN(nhdr.n_descsz);
 446                if (nhdr.n_type == NT_GNU_BUILD_ID &&
 447                    nhdr.n_namesz == sizeof("GNU")) {
 448                        if (read(fd, bf, namesz) != (ssize_t)namesz)
 449                                break;
 450                        if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
 451                                size_t sz = min(descsz, size);
 452                                if (read(fd, build_id, sz) == (ssize_t)sz) {
 453                                        memset(build_id + sz, 0, size - sz);
 454                                        err = 0;
 455                                        break;
 456                                }
 457                        } else if (read(fd, bf, descsz) != (ssize_t)descsz)
 458                                break;
 459                } else {
 460                        int n = namesz + descsz;
 461                        if (read(fd, bf, n) != n)
 462                                break;
 463                }
 464        }
 465        close(fd);
 466out:
 467        return err;
 468}
 469
 470int filename__read_debuglink(const char *filename, char *debuglink,
 471                             size_t size)
 472{
 473        int fd, err = -1;
 474        Elf *elf;
 475        GElf_Ehdr ehdr;
 476        GElf_Shdr shdr;
 477        Elf_Data *data;
 478        Elf_Scn *sec;
 479        Elf_Kind ek;
 480
 481        fd = open(filename, O_RDONLY);
 482        if (fd < 0)
 483                goto out;
 484
 485        elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
 486        if (elf == NULL) {
 487                pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
 488                goto out_close;
 489        }
 490
 491        ek = elf_kind(elf);
 492        if (ek != ELF_K_ELF)
 493                goto out_elf_end;
 494
 495        if (gelf_getehdr(elf, &ehdr) == NULL) {
 496                pr_err("%s: cannot get elf header.\n", __func__);
 497                goto out_elf_end;
 498        }
 499
 500        sec = elf_section_by_name(elf, &ehdr, &shdr,
 501                                  ".gnu_debuglink", NULL);
 502        if (sec == NULL)
 503                goto out_elf_end;
 504
 505        data = elf_getdata(sec, NULL);
 506        if (data == NULL)
 507                goto out_elf_end;
 508
 509        /* the start of this section is a zero-terminated string */
 510        strncpy(debuglink, data->d_buf, size);
 511
 512        err = 0;
 513
 514out_elf_end:
 515        elf_end(elf);
 516out_close:
 517        close(fd);
 518out:
 519        return err;
 520}
 521
 522static int dso__swap_init(struct dso *dso, unsigned char eidata)
 523{
 524        static unsigned int const endian = 1;
 525
 526        dso->needs_swap = DSO_SWAP__NO;
 527
 528        switch (eidata) {
 529        case ELFDATA2LSB:
 530                /* We are big endian, DSO is little endian. */
 531                if (*(unsigned char const *)&endian != 1)
 532                        dso->needs_swap = DSO_SWAP__YES;
 533                break;
 534
 535        case ELFDATA2MSB:
 536                /* We are little endian, DSO is big endian. */
 537                if (*(unsigned char const *)&endian != 0)
 538                        dso->needs_swap = DSO_SWAP__YES;
 539                break;
 540
 541        default:
 542                pr_err("unrecognized DSO data encoding %d\n", eidata);
 543                return -EINVAL;
 544        }
 545
 546        return 0;
 547}
 548
 549bool symsrc__possibly_runtime(struct symsrc *ss)
 550{
 551        return ss->dynsym || ss->opdsec;
 552}
 553
 554bool symsrc__has_symtab(struct symsrc *ss)
 555{
 556        return ss->symtab != NULL;
 557}
 558
 559void symsrc__destroy(struct symsrc *ss)
 560{
 561        zfree(&ss->name);
 562        elf_end(ss->elf);
 563        close(ss->fd);
 564}
 565
 566int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
 567                 enum dso_binary_type type)
 568{
 569        int err = -1;
 570        GElf_Ehdr ehdr;
 571        Elf *elf;
 572        int fd;
 573
 574        fd = open(name, O_RDONLY);
 575        if (fd < 0)
 576                return -1;
 577
 578        elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
 579        if (elf == NULL) {
 580                pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
 581                goto out_close;
 582        }
 583
 584        if (gelf_getehdr(elf, &ehdr) == NULL) {
 585                pr_debug("%s: cannot get elf header.\n", __func__);
 586                goto out_elf_end;
 587        }
 588
 589        if (dso__swap_init(dso, ehdr.e_ident[EI_DATA]))
 590                goto out_elf_end;
 591
 592        /* Always reject images with a mismatched build-id: */
 593        if (dso->has_build_id) {
 594                u8 build_id[BUILD_ID_SIZE];
 595
 596                if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
 597                        goto out_elf_end;
 598
 599                if (!dso__build_id_equal(dso, build_id))
 600                        goto out_elf_end;
 601        }
 602
 603        ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
 604
 605        ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab",
 606                        NULL);
 607        if (ss->symshdr.sh_type != SHT_SYMTAB)
 608                ss->symtab = NULL;
 609
 610        ss->dynsym_idx = 0;
 611        ss->dynsym = elf_section_by_name(elf, &ehdr, &ss->dynshdr, ".dynsym",
 612                        &ss->dynsym_idx);
 613        if (ss->dynshdr.sh_type != SHT_DYNSYM)
 614                ss->dynsym = NULL;
 615
 616        ss->opdidx = 0;
 617        ss->opdsec = elf_section_by_name(elf, &ehdr, &ss->opdshdr, ".opd",
 618                        &ss->opdidx);
 619        if (ss->opdshdr.sh_type != SHT_PROGBITS)
 620                ss->opdsec = NULL;
 621
 622        if (dso->kernel == DSO_TYPE_USER) {
 623                GElf_Shdr shdr;
 624                ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
 625                                ehdr.e_type == ET_REL ||
 626                                dso__is_vdso(dso) ||
 627                                elf_section_by_name(elf, &ehdr, &shdr,
 628                                                     ".gnu.prelink_undo",
 629                                                     NULL) != NULL);
 630        } else {
 631                ss->adjust_symbols = ehdr.e_type == ET_EXEC ||
 632                                     ehdr.e_type == ET_REL;
 633        }
 634
 635        ss->name   = strdup(name);
 636        if (!ss->name)
 637                goto out_elf_end;
 638
 639        ss->elf    = elf;
 640        ss->fd     = fd;
 641        ss->ehdr   = ehdr;
 642        ss->type   = type;
 643
 644        return 0;
 645
 646out_elf_end:
 647        elf_end(elf);
 648out_close:
 649        close(fd);
 650        return err;
 651}
 652
 653/**
 654 * ref_reloc_sym_not_found - has kernel relocation symbol been found.
 655 * @kmap: kernel maps and relocation reference symbol
 656 *
 657 * This function returns %true if we are dealing with the kernel maps and the
 658 * relocation reference symbol has not yet been found.  Otherwise %false is
 659 * returned.
 660 */
 661static bool ref_reloc_sym_not_found(struct kmap *kmap)
 662{
 663        return kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
 664               !kmap->ref_reloc_sym->unrelocated_addr;
 665}
 666
 667/**
 668 * ref_reloc - kernel relocation offset.
 669 * @kmap: kernel maps and relocation reference symbol
 670 *
 671 * This function returns the offset of kernel addresses as determined by using
 672 * the relocation reference symbol i.e. if the kernel has not been relocated
 673 * then the return value is zero.
 674 */
 675static u64 ref_reloc(struct kmap *kmap)
 676{
 677        if (kmap && kmap->ref_reloc_sym &&
 678            kmap->ref_reloc_sym->unrelocated_addr)
 679                return kmap->ref_reloc_sym->addr -
 680                       kmap->ref_reloc_sym->unrelocated_addr;
 681        return 0;
 682}
 683
 684static bool want_demangle(bool is_kernel_sym)
 685{
 686        return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
 687}
 688
 689int dso__load_sym(struct dso *dso, struct map *map,
 690                  struct symsrc *syms_ss, struct symsrc *runtime_ss,
 691                  symbol_filter_t filter, int kmodule)
 692{
 693        struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
 694        struct map *curr_map = map;
 695        struct dso *curr_dso = dso;
 696        Elf_Data *symstrs, *secstrs;
 697        uint32_t nr_syms;
 698        int err = -1;
 699        uint32_t idx;
 700        GElf_Ehdr ehdr;
 701        GElf_Shdr shdr;
 702        Elf_Data *syms, *opddata = NULL;
 703        GElf_Sym sym;
 704        Elf_Scn *sec, *sec_strndx;
 705        Elf *elf;
 706        int nr = 0;
 707        bool remap_kernel = false, adjust_kernel_syms = false;
 708
 709        dso->symtab_type = syms_ss->type;
 710        dso->is_64_bit = syms_ss->is_64_bit;
 711        dso->rel = syms_ss->ehdr.e_type == ET_REL;
 712
 713        /*
 714         * Modules may already have symbols from kallsyms, but those symbols
 715         * have the wrong values for the dso maps, so remove them.
 716         */
 717        if (kmodule && syms_ss->symtab)
 718                symbols__delete(&dso->symbols[map->type]);
 719
 720        if (!syms_ss->symtab) {
 721                /*
 722                 * If the vmlinux is stripped, fail so we will fall back
 723                 * to using kallsyms. The vmlinux runtime symbols aren't
 724                 * of much use.
 725                 */
 726                if (dso->kernel)
 727                        goto out_elf_end;
 728
 729                syms_ss->symtab  = syms_ss->dynsym;
 730                syms_ss->symshdr = syms_ss->dynshdr;
 731        }
 732
 733        elf = syms_ss->elf;
 734        ehdr = syms_ss->ehdr;
 735        sec = syms_ss->symtab;
 736        shdr = syms_ss->symshdr;
 737
 738        if (runtime_ss->opdsec)
 739                opddata = elf_rawdata(runtime_ss->opdsec, NULL);
 740
 741        syms = elf_getdata(sec, NULL);
 742        if (syms == NULL)
 743                goto out_elf_end;
 744
 745        sec = elf_getscn(elf, shdr.sh_link);
 746        if (sec == NULL)
 747                goto out_elf_end;
 748
 749        symstrs = elf_getdata(sec, NULL);
 750        if (symstrs == NULL)
 751                goto out_elf_end;
 752
 753        sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx);
 754        if (sec_strndx == NULL)
 755                goto out_elf_end;
 756
 757        secstrs = elf_getdata(sec_strndx, NULL);
 758        if (secstrs == NULL)
 759                goto out_elf_end;
 760
 761        nr_syms = shdr.sh_size / shdr.sh_entsize;
 762
 763        memset(&sym, 0, sizeof(sym));
 764
 765        /*
 766         * The kernel relocation symbol is needed in advance in order to adjust
 767         * kernel maps correctly.
 768         */
 769        if (ref_reloc_sym_not_found(kmap)) {
 770                elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
 771                        const char *elf_name = elf_sym__name(&sym, symstrs);
 772
 773                        if (strcmp(elf_name, kmap->ref_reloc_sym->name))
 774                                continue;
 775                        kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
 776                        map->reloc = kmap->ref_reloc_sym->addr -
 777                                     kmap->ref_reloc_sym->unrelocated_addr;
 778                        break;
 779                }
 780        }
 781
 782        dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap);
 783        /*
 784         * Initial kernel and module mappings do not map to the dso.  For
 785         * function mappings, flag the fixups.
 786         */
 787        if (map->type == MAP__FUNCTION && (dso->kernel || kmodule)) {
 788                remap_kernel = true;
 789                adjust_kernel_syms = dso->adjust_symbols;
 790        }
 791        elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
 792                struct symbol *f;
 793                const char *elf_name = elf_sym__name(&sym, symstrs);
 794                char *demangled = NULL;
 795                int is_label = elf_sym__is_label(&sym);
 796                const char *section_name;
 797                bool used_opd = false;
 798
 799                if (!is_label && !elf_sym__is_a(&sym, map->type))
 800                        continue;
 801
 802                /* Reject ARM ELF "mapping symbols": these aren't unique and
 803                 * don't identify functions, so will confuse the profile
 804                 * output: */
 805                if (ehdr.e_machine == EM_ARM) {
 806                        if (!strcmp(elf_name, "$a") ||
 807                            !strcmp(elf_name, "$d") ||
 808                            !strcmp(elf_name, "$t"))
 809                                continue;
 810                }
 811
 812                if (runtime_ss->opdsec && sym.st_shndx == runtime_ss->opdidx) {
 813                        u32 offset = sym.st_value - syms_ss->opdshdr.sh_addr;
 814                        u64 *opd = opddata->d_buf + offset;
 815                        sym.st_value = DSO__SWAP(dso, u64, *opd);
 816                        sym.st_shndx = elf_addr_to_index(runtime_ss->elf,
 817                                        sym.st_value);
 818                        used_opd = true;
 819                }
 820                /*
 821                 * When loading symbols in a data mapping, ABS symbols (which
 822                 * has a value of SHN_ABS in its st_shndx) failed at
 823                 * elf_getscn().  And it marks the loading as a failure so
 824                 * already loaded symbols cannot be fixed up.
 825                 *
 826                 * I'm not sure what should be done. Just ignore them for now.
 827                 * - Namhyung Kim
 828                 */
 829                if (sym.st_shndx == SHN_ABS)
 830                        continue;
 831
 832                sec = elf_getscn(runtime_ss->elf, sym.st_shndx);
 833                if (!sec)
 834                        goto out_elf_end;
 835
 836                gelf_getshdr(sec, &shdr);
 837
 838                if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type))
 839                        continue;
 840
 841                section_name = elf_sec__name(&shdr, secstrs);
 842
 843                /* On ARM, symbols for thumb functions have 1 added to
 844                 * the symbol address as a flag - remove it */
 845                if ((ehdr.e_machine == EM_ARM) &&
 846                    (map->type == MAP__FUNCTION) &&
 847                    (sym.st_value & 1))
 848                        --sym.st_value;
 849
 850                if (dso->kernel || kmodule) {
 851                        char dso_name[PATH_MAX];
 852
 853                        /* Adjust symbol to map to file offset */
 854                        if (adjust_kernel_syms)
 855                                sym.st_value -= shdr.sh_addr - shdr.sh_offset;
 856
 857                        if (strcmp(section_name,
 858                                   (curr_dso->short_name +
 859                                    dso->short_name_len)) == 0)
 860                                goto new_symbol;
 861
 862                        if (strcmp(section_name, ".text") == 0) {
 863                                /*
 864                                 * The initial kernel mapping is based on
 865                                 * kallsyms and identity maps.  Overwrite it to
 866                                 * map to the kernel dso.
 867                                 */
 868                                if (remap_kernel && dso->kernel) {
 869                                        remap_kernel = false;
 870                                        map->start = shdr.sh_addr +
 871                                                     ref_reloc(kmap);
 872                                        map->end = map->start + shdr.sh_size;
 873                                        map->pgoff = shdr.sh_offset;
 874                                        map->map_ip = map__map_ip;
 875                                        map->unmap_ip = map__unmap_ip;
 876                                        /* Ensure maps are correctly ordered */
 877                                        map_groups__remove(kmap->kmaps, map);
 878                                        map_groups__insert(kmap->kmaps, map);
 879                                }
 880
 881                                /*
 882                                 * The initial module mapping is based on
 883                                 * /proc/modules mapped to offset zero.
 884                                 * Overwrite it to map to the module dso.
 885                                 */
 886                                if (remap_kernel && kmodule) {
 887                                        remap_kernel = false;
 888                                        map->pgoff = shdr.sh_offset;
 889                                }
 890
 891                                curr_map = map;
 892                                curr_dso = dso;
 893                                goto new_symbol;
 894                        }
 895
 896                        if (!kmap)
 897                                goto new_symbol;
 898
 899                        snprintf(dso_name, sizeof(dso_name),
 900                                 "%s%s", dso->short_name, section_name);
 901
 902                        curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
 903                        if (curr_map == NULL) {
 904                                u64 start = sym.st_value;
 905
 906                                if (kmodule)
 907                                        start += map->start + shdr.sh_offset;
 908
 909                                curr_dso = dso__new(dso_name);
 910                                if (curr_dso == NULL)
 911                                        goto out_elf_end;
 912                                curr_dso->kernel = dso->kernel;
 913                                curr_dso->long_name = dso->long_name;
 914                                curr_dso->long_name_len = dso->long_name_len;
 915                                curr_map = map__new2(start, curr_dso,
 916                                                     map->type);
 917                                if (curr_map == NULL) {
 918                                        dso__delete(curr_dso);
 919                                        goto out_elf_end;
 920                                }
 921                                if (adjust_kernel_syms) {
 922                                        curr_map->start = shdr.sh_addr +
 923                                                          ref_reloc(kmap);
 924                                        curr_map->end = curr_map->start +
 925                                                        shdr.sh_size;
 926                                        curr_map->pgoff = shdr.sh_offset;
 927                                } else {
 928                                        curr_map->map_ip = identity__map_ip;
 929                                        curr_map->unmap_ip = identity__map_ip;
 930                                }
 931                                curr_dso->symtab_type = dso->symtab_type;
 932                                map_groups__insert(kmap->kmaps, curr_map);
 933                                /*
 934                                 * The new DSO should go to the kernel DSOS
 935                                 */
 936                                dsos__add(&map->groups->machine->kernel_dsos,
 937                                          curr_dso);
 938                                dso__set_loaded(curr_dso, map->type);
 939                        } else
 940                                curr_dso = curr_map->dso;
 941
 942                        goto new_symbol;
 943                }
 944
 945                if ((used_opd && runtime_ss->adjust_symbols)
 946                                || (!used_opd && syms_ss->adjust_symbols)) {
 947                        pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
 948                                  "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
 949                                  (u64)sym.st_value, (u64)shdr.sh_addr,
 950                                  (u64)shdr.sh_offset);
 951                        sym.st_value -= shdr.sh_addr - shdr.sh_offset;
 952                }
 953new_symbol:
 954                /*
 955                 * We need to figure out if the object was created from C++ sources
 956                 * DWARF DW_compile_unit has this, but we don't always have access
 957                 * to it...
 958                 */
 959                if (want_demangle(dso->kernel || kmodule)) {
 960                        int demangle_flags = DMGL_NO_OPTS;
 961                        if (verbose)
 962                                demangle_flags = DMGL_PARAMS | DMGL_ANSI;
 963
 964                        demangled = bfd_demangle(NULL, elf_name, demangle_flags);
 965                        if (demangled != NULL)
 966                                elf_name = demangled;
 967                }
 968                f = symbol__new(sym.st_value, sym.st_size,
 969                                GELF_ST_BIND(sym.st_info), elf_name);
 970                free(demangled);
 971                if (!f)
 972                        goto out_elf_end;
 973
 974                if (filter && filter(curr_map, f))
 975                        symbol__delete(f);
 976                else {
 977                        symbols__insert(&curr_dso->symbols[curr_map->type], f);
 978                        nr++;
 979                }
 980        }
 981
 982        /*
 983         * For misannotated, zeroed, ASM function sizes.
 984         */
 985        if (nr > 0) {
 986                symbols__fixup_duplicate(&dso->symbols[map->type]);
 987                symbols__fixup_end(&dso->symbols[map->type]);
 988                if (kmap) {
 989                        /*
 990                         * We need to fixup this here too because we create new
 991                         * maps here, for things like vsyscall sections.
 992                         */
 993                        __map_groups__fixup_end(kmap->kmaps, map->type);
 994                }
 995        }
 996        err = nr;
 997out_elf_end:
 998        return err;
 999}
1000
1001static int elf_read_maps(Elf *elf, bool exe, mapfn_t mapfn, void *data)
1002{
1003        GElf_Phdr phdr;
1004        size_t i, phdrnum;
1005        int err;
1006        u64 sz;
1007
1008        if (elf_getphdrnum(elf, &phdrnum))
1009                return -1;
1010
1011        for (i = 0; i < phdrnum; i++) {
1012                if (gelf_getphdr(elf, i, &phdr) == NULL)
1013                        return -1;
1014                if (phdr.p_type != PT_LOAD)
1015                        continue;
1016                if (exe) {
1017                        if (!(phdr.p_flags & PF_X))
1018                                continue;
1019                } else {
1020                        if (!(phdr.p_flags & PF_R))
1021                                continue;
1022                }
1023                sz = min(phdr.p_memsz, phdr.p_filesz);
1024                if (!sz)
1025                        continue;
1026                err = mapfn(phdr.p_vaddr, sz, phdr.p_offset, data);
1027                if (err)
1028                        return err;
1029        }
1030        return 0;
1031}
1032
1033int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
1034                    bool *is_64_bit)
1035{
1036        int err;
1037        Elf *elf;
1038
1039        elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1040        if (elf == NULL)
1041                return -1;
1042
1043        if (is_64_bit)
1044                *is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
1045
1046        err = elf_read_maps(elf, exe, mapfn, data);
1047
1048        elf_end(elf);
1049        return err;
1050}
1051
1052enum dso_type dso__type_fd(int fd)
1053{
1054        enum dso_type dso_type = DSO__TYPE_UNKNOWN;
1055        GElf_Ehdr ehdr;
1056        Elf_Kind ek;
1057        Elf *elf;
1058
1059        elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1060        if (elf == NULL)
1061                goto out;
1062
1063        ek = elf_kind(elf);
1064        if (ek != ELF_K_ELF)
1065                goto out_end;
1066
1067        if (gelf_getclass(elf) == ELFCLASS64) {
1068                dso_type = DSO__TYPE_64BIT;
1069                goto out_end;
1070        }
1071
1072        if (gelf_getehdr(elf, &ehdr) == NULL)
1073                goto out_end;
1074
1075        if (ehdr.e_machine == EM_X86_64)
1076                dso_type = DSO__TYPE_X32BIT;
1077        else
1078                dso_type = DSO__TYPE_32BIT;
1079out_end:
1080        elf_end(elf);
1081out:
1082        return dso_type;
1083}
1084
1085static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
1086{
1087        ssize_t r;
1088        size_t n;
1089        int err = -1;
1090        char *buf = malloc(page_size);
1091
1092        if (buf == NULL)
1093                return -1;
1094
1095        if (lseek(to, to_offs, SEEK_SET) != to_offs)
1096                goto out;
1097
1098        if (lseek(from, from_offs, SEEK_SET) != from_offs)
1099                goto out;
1100
1101        while (len) {
1102                n = page_size;
1103                if (len < n)
1104                        n = len;
1105                /* Use read because mmap won't work on proc files */
1106                r = read(from, buf, n);
1107                if (r < 0)
1108                        goto out;
1109                if (!r)
1110                        break;
1111                n = r;
1112                r = write(to, buf, n);
1113                if (r < 0)
1114                        goto out;
1115                if ((size_t)r != n)
1116                        goto out;
1117                len -= n;
1118        }
1119
1120        err = 0;
1121out:
1122        free(buf);
1123        return err;
1124}
1125
1126struct kcore {
1127        int fd;
1128        int elfclass;
1129        Elf *elf;
1130        GElf_Ehdr ehdr;
1131};
1132
1133static int kcore__open(struct kcore *kcore, const char *filename)
1134{
1135        GElf_Ehdr *ehdr;
1136
1137        kcore->fd = open(filename, O_RDONLY);
1138        if (kcore->fd == -1)
1139                return -1;
1140
1141        kcore->elf = elf_begin(kcore->fd, ELF_C_READ, NULL);
1142        if (!kcore->elf)
1143                goto out_close;
1144
1145        kcore->elfclass = gelf_getclass(kcore->elf);
1146        if (kcore->elfclass == ELFCLASSNONE)
1147                goto out_end;
1148
1149        ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1150        if (!ehdr)
1151                goto out_end;
1152
1153        return 0;
1154
1155out_end:
1156        elf_end(kcore->elf);
1157out_close:
1158        close(kcore->fd);
1159        return -1;
1160}
1161
1162static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
1163                       bool temp)
1164{
1165        GElf_Ehdr *ehdr;
1166
1167        kcore->elfclass = elfclass;
1168
1169        if (temp)
1170                kcore->fd = mkstemp(filename);
1171        else
1172                kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400);
1173        if (kcore->fd == -1)
1174                return -1;
1175
1176        kcore->elf = elf_begin(kcore->fd, ELF_C_WRITE, NULL);
1177        if (!kcore->elf)
1178                goto out_close;
1179
1180        if (!gelf_newehdr(kcore->elf, elfclass))
1181                goto out_end;
1182
1183        ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1184        if (!ehdr)
1185                goto out_end;
1186
1187        return 0;
1188
1189out_end:
1190        elf_end(kcore->elf);
1191out_close:
1192        close(kcore->fd);
1193        unlink(filename);
1194        return -1;
1195}
1196
1197static void kcore__close(struct kcore *kcore)
1198{
1199        elf_end(kcore->elf);
1200        close(kcore->fd);
1201}
1202
1203static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
1204{
1205        GElf_Ehdr *ehdr = &to->ehdr;
1206        GElf_Ehdr *kehdr = &from->ehdr;
1207
1208        memcpy(ehdr->e_ident, kehdr->e_ident, EI_NIDENT);
1209        ehdr->e_type      = kehdr->e_type;
1210        ehdr->e_machine   = kehdr->e_machine;
1211        ehdr->e_version   = kehdr->e_version;
1212        ehdr->e_entry     = 0;
1213        ehdr->e_shoff     = 0;
1214        ehdr->e_flags     = kehdr->e_flags;
1215        ehdr->e_phnum     = count;
1216        ehdr->e_shentsize = 0;
1217        ehdr->e_shnum     = 0;
1218        ehdr->e_shstrndx  = 0;
1219
1220        if (from->elfclass == ELFCLASS32) {
1221                ehdr->e_phoff     = sizeof(Elf32_Ehdr);
1222                ehdr->e_ehsize    = sizeof(Elf32_Ehdr);
1223                ehdr->e_phentsize = sizeof(Elf32_Phdr);
1224        } else {
1225                ehdr->e_phoff     = sizeof(Elf64_Ehdr);
1226                ehdr->e_ehsize    = sizeof(Elf64_Ehdr);
1227                ehdr->e_phentsize = sizeof(Elf64_Phdr);
1228        }
1229
1230        if (!gelf_update_ehdr(to->elf, ehdr))
1231                return -1;
1232
1233        if (!gelf_newphdr(to->elf, count))
1234                return -1;
1235
1236        return 0;
1237}
1238
1239static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
1240                           u64 addr, u64 len)
1241{
1242        GElf_Phdr gphdr;
1243        GElf_Phdr *phdr;
1244
1245        phdr = gelf_getphdr(kcore->elf, idx, &gphdr);
1246        if (!phdr)
1247                return -1;
1248
1249        phdr->p_type    = PT_LOAD;
1250        phdr->p_flags   = PF_R | PF_W | PF_X;
1251        phdr->p_offset  = offset;
1252        phdr->p_vaddr   = addr;
1253        phdr->p_paddr   = 0;
1254        phdr->p_filesz  = len;
1255        phdr->p_memsz   = len;
1256        phdr->p_align   = page_size;
1257
1258        if (!gelf_update_phdr(kcore->elf, idx, phdr))
1259                return -1;
1260
1261        return 0;
1262}
1263
1264static off_t kcore__write(struct kcore *kcore)
1265{
1266        return elf_update(kcore->elf, ELF_C_WRITE);
1267}
1268
1269struct phdr_data {
1270        off_t offset;
1271        u64 addr;
1272        u64 len;
1273};
1274
1275struct kcore_copy_info {
1276        u64 stext;
1277        u64 etext;
1278        u64 first_symbol;
1279        u64 last_symbol;
1280        u64 first_module;
1281        u64 last_module_symbol;
1282        struct phdr_data kernel_map;
1283        struct phdr_data modules_map;
1284};
1285
1286static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
1287                                        u64 start)
1288{
1289        struct kcore_copy_info *kci = arg;
1290
1291        if (!symbol_type__is_a(type, MAP__FUNCTION))
1292                return 0;
1293
1294        if (strchr(name, '[')) {
1295                if (start > kci->last_module_symbol)
1296                        kci->last_module_symbol = start;
1297                return 0;
1298        }
1299
1300        if (!kci->first_symbol || start < kci->first_symbol)
1301                kci->first_symbol = start;
1302
1303        if (!kci->last_symbol || start > kci->last_symbol)
1304                kci->last_symbol = start;
1305
1306        if (!strcmp(name, "_stext")) {
1307                kci->stext = start;
1308                return 0;
1309        }
1310
1311        if (!strcmp(name, "_etext")) {
1312                kci->etext = start;
1313                return 0;
1314        }
1315
1316        return 0;
1317}
1318
1319static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
1320                                      const char *dir)
1321{
1322        char kallsyms_filename[PATH_MAX];
1323
1324        scnprintf(kallsyms_filename, PATH_MAX, "%s/kallsyms", dir);
1325
1326        if (symbol__restricted_filename(kallsyms_filename, "/proc/kallsyms"))
1327                return -1;
1328
1329        if (kallsyms__parse(kallsyms_filename, kci,
1330                            kcore_copy__process_kallsyms) < 0)
1331                return -1;
1332
1333        return 0;
1334}
1335
1336static int kcore_copy__process_modules(void *arg,
1337                                       const char *name __maybe_unused,
1338                                       u64 start)
1339{
1340        struct kcore_copy_info *kci = arg;
1341
1342        if (!kci->first_module || start < kci->first_module)
1343                kci->first_module = start;
1344
1345        return 0;
1346}
1347
1348static int kcore_copy__parse_modules(struct kcore_copy_info *kci,
1349                                     const char *dir)
1350{
1351        char modules_filename[PATH_MAX];
1352
1353        scnprintf(modules_filename, PATH_MAX, "%s/modules", dir);
1354
1355        if (symbol__restricted_filename(modules_filename, "/proc/modules"))
1356                return -1;
1357
1358        if (modules__parse(modules_filename, kci,
1359                           kcore_copy__process_modules) < 0)
1360                return -1;
1361
1362        return 0;
1363}
1364
1365static void kcore_copy__map(struct phdr_data *p, u64 start, u64 end, u64 pgoff,
1366                            u64 s, u64 e)
1367{
1368        if (p->addr || s < start || s >= end)
1369                return;
1370
1371        p->addr = s;
1372        p->offset = (s - start) + pgoff;
1373        p->len = e < end ? e - s : end - s;
1374}
1375
1376static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data)
1377{
1378        struct kcore_copy_info *kci = data;
1379        u64 end = start + len;
1380
1381        kcore_copy__map(&kci->kernel_map, start, end, pgoff, kci->stext,
1382                        kci->etext);
1383
1384        kcore_copy__map(&kci->modules_map, start, end, pgoff, kci->first_module,
1385                        kci->last_module_symbol);
1386
1387        return 0;
1388}
1389
1390static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf)
1391{
1392        if (elf_read_maps(elf, true, kcore_copy__read_map, kci) < 0)
1393                return -1;
1394
1395        return 0;
1396}
1397
1398static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
1399                                 Elf *elf)
1400{
1401        if (kcore_copy__parse_kallsyms(kci, dir))
1402                return -1;
1403
1404        if (kcore_copy__parse_modules(kci, dir))
1405                return -1;
1406
1407        if (kci->stext)
1408                kci->stext = round_down(kci->stext, page_size);
1409        else
1410                kci->stext = round_down(kci->first_symbol, page_size);
1411
1412        if (kci->etext) {
1413                kci->etext = round_up(kci->etext, page_size);
1414        } else if (kci->last_symbol) {
1415                kci->etext = round_up(kci->last_symbol, page_size);
1416                kci->etext += page_size;
1417        }
1418
1419        kci->first_module = round_down(kci->first_module, page_size);
1420
1421        if (kci->last_module_symbol) {
1422                kci->last_module_symbol = round_up(kci->last_module_symbol,
1423                                                   page_size);
1424                kci->last_module_symbol += page_size;
1425        }
1426
1427        if (!kci->stext || !kci->etext)
1428                return -1;
1429
1430        if (kci->first_module && !kci->last_module_symbol)
1431                return -1;
1432
1433        return kcore_copy__read_maps(kci, elf);
1434}
1435
1436static int kcore_copy__copy_file(const char *from_dir, const char *to_dir,
1437                                 const char *name)
1438{
1439        char from_filename[PATH_MAX];
1440        char to_filename[PATH_MAX];
1441
1442        scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1443        scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1444
1445        return copyfile_mode(from_filename, to_filename, 0400);
1446}
1447
1448static int kcore_copy__unlink(const char *dir, const char *name)
1449{
1450        char filename[PATH_MAX];
1451
1452        scnprintf(filename, PATH_MAX, "%s/%s", dir, name);
1453
1454        return unlink(filename);
1455}
1456
1457static int kcore_copy__compare_fds(int from, int to)
1458{
1459        char *buf_from;
1460        char *buf_to;
1461        ssize_t ret;
1462        size_t len;
1463        int err = -1;
1464
1465        buf_from = malloc(page_size);
1466        buf_to = malloc(page_size);
1467        if (!buf_from || !buf_to)
1468                goto out;
1469
1470        while (1) {
1471                /* Use read because mmap won't work on proc files */
1472                ret = read(from, buf_from, page_size);
1473                if (ret < 0)
1474                        goto out;
1475
1476                if (!ret)
1477                        break;
1478
1479                len = ret;
1480
1481                if (readn(to, buf_to, len) != (int)len)
1482                        goto out;
1483
1484                if (memcmp(buf_from, buf_to, len))
1485                        goto out;
1486        }
1487
1488        err = 0;
1489out:
1490        free(buf_to);
1491        free(buf_from);
1492        return err;
1493}
1494
1495static int kcore_copy__compare_files(const char *from_filename,
1496                                     const char *to_filename)
1497{
1498        int from, to, err = -1;
1499
1500        from = open(from_filename, O_RDONLY);
1501        if (from < 0)
1502                return -1;
1503
1504        to = open(to_filename, O_RDONLY);
1505        if (to < 0)
1506                goto out_close_from;
1507
1508        err = kcore_copy__compare_fds(from, to);
1509
1510        close(to);
1511out_close_from:
1512        close(from);
1513        return err;
1514}
1515
1516static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
1517                                    const char *name)
1518{
1519        char from_filename[PATH_MAX];
1520        char to_filename[PATH_MAX];
1521
1522        scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1523        scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1524
1525        return kcore_copy__compare_files(from_filename, to_filename);
1526}
1527
1528/**
1529 * kcore_copy - copy kallsyms, modules and kcore from one directory to another.
1530 * @from_dir: from directory
1531 * @to_dir: to directory
1532 *
1533 * This function copies kallsyms, modules and kcore files from one directory to
1534 * another.  kallsyms and modules are copied entirely.  Only code segments are
1535 * copied from kcore.  It is assumed that two segments suffice: one for the
1536 * kernel proper and one for all the modules.  The code segments are determined
1537 * from kallsyms and modules files.  The kernel map starts at _stext or the
1538 * lowest function symbol, and ends at _etext or the highest function symbol.
1539 * The module map starts at the lowest module address and ends at the highest
1540 * module symbol.  Start addresses are rounded down to the nearest page.  End
1541 * addresses are rounded up to the nearest page.  An extra page is added to the
1542 * highest kernel symbol and highest module symbol to, hopefully, encompass that
1543 * symbol too.  Because it contains only code sections, the resulting kcore is
1544 * unusual.  One significant peculiarity is that the mapping (start -> pgoff)
1545 * is not the same for the kernel map and the modules map.  That happens because
1546 * the data is copied adjacently whereas the original kcore has gaps.  Finally,
1547 * kallsyms and modules files are compared with their copies to check that
1548 * modules have not been loaded or unloaded while the copies were taking place.
1549 *
1550 * Return: %0 on success, %-1 on failure.
1551 */
1552int kcore_copy(const char *from_dir, const char *to_dir)
1553{
1554        struct kcore kcore;
1555        struct kcore extract;
1556        size_t count = 2;
1557        int idx = 0, err = -1;
1558        off_t offset = page_size, sz, modules_offset = 0;
1559        struct kcore_copy_info kci = { .stext = 0, };
1560        char kcore_filename[PATH_MAX];
1561        char extract_filename[PATH_MAX];
1562
1563        if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms"))
1564                return -1;
1565
1566        if (kcore_copy__copy_file(from_dir, to_dir, "modules"))
1567                goto out_unlink_kallsyms;
1568
1569        scnprintf(kcore_filename, PATH_MAX, "%s/kcore", from_dir);
1570        scnprintf(extract_filename, PATH_MAX, "%s/kcore", to_dir);
1571
1572        if (kcore__open(&kcore, kcore_filename))
1573                goto out_unlink_modules;
1574
1575        if (kcore_copy__calc_maps(&kci, from_dir, kcore.elf))
1576                goto out_kcore_close;
1577
1578        if (kcore__init(&extract, extract_filename, kcore.elfclass, false))
1579                goto out_kcore_close;
1580
1581        if (!kci.modules_map.addr)
1582                count -= 1;
1583
1584        if (kcore__copy_hdr(&kcore, &extract, count))
1585                goto out_extract_close;
1586
1587        if (kcore__add_phdr(&extract, idx++, offset, kci.kernel_map.addr,
1588                            kci.kernel_map.len))
1589                goto out_extract_close;
1590
1591        if (kci.modules_map.addr) {
1592                modules_offset = offset + kci.kernel_map.len;
1593                if (kcore__add_phdr(&extract, idx, modules_offset,
1594                                    kci.modules_map.addr, kci.modules_map.len))
1595                        goto out_extract_close;
1596        }
1597
1598        sz = kcore__write(&extract);
1599        if (sz < 0 || sz > offset)
1600                goto out_extract_close;
1601
1602        if (copy_bytes(kcore.fd, kci.kernel_map.offset, extract.fd, offset,
1603                       kci.kernel_map.len))
1604                goto out_extract_close;
1605
1606        if (modules_offset && copy_bytes(kcore.fd, kci.modules_map.offset,
1607                                         extract.fd, modules_offset,
1608                                         kci.modules_map.len))
1609                goto out_extract_close;
1610
1611        if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
1612                goto out_extract_close;
1613
1614        if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
1615                goto out_extract_close;
1616
1617        err = 0;
1618
1619out_extract_close:
1620        kcore__close(&extract);
1621        if (err)
1622                unlink(extract_filename);
1623out_kcore_close:
1624        kcore__close(&kcore);
1625out_unlink_modules:
1626        if (err)
1627                kcore_copy__unlink(to_dir, "modules");
1628out_unlink_kallsyms:
1629        if (err)
1630                kcore_copy__unlink(to_dir, "kallsyms");
1631
1632        return err;
1633}
1634
1635int kcore_extract__create(struct kcore_extract *kce)
1636{
1637        struct kcore kcore;
1638        struct kcore extract;
1639        size_t count = 1;
1640        int idx = 0, err = -1;
1641        off_t offset = page_size, sz;
1642
1643        if (kcore__open(&kcore, kce->kcore_filename))
1644                return -1;
1645
1646        strcpy(kce->extract_filename, PERF_KCORE_EXTRACT);
1647        if (kcore__init(&extract, kce->extract_filename, kcore.elfclass, true))
1648                goto out_kcore_close;
1649
1650        if (kcore__copy_hdr(&kcore, &extract, count))
1651                goto out_extract_close;
1652
1653        if (kcore__add_phdr(&extract, idx, offset, kce->addr, kce->len))
1654                goto out_extract_close;
1655
1656        sz = kcore__write(&extract);
1657        if (sz < 0 || sz > offset)
1658                goto out_extract_close;
1659
1660        if (copy_bytes(kcore.fd, kce->offs, extract.fd, offset, kce->len))
1661                goto out_extract_close;
1662
1663        err = 0;
1664
1665out_extract_close:
1666        kcore__close(&extract);
1667        if (err)
1668                unlink(kce->extract_filename);
1669out_kcore_close:
1670        kcore__close(&kcore);
1671
1672        return err;
1673}
1674
1675void kcore_extract__delete(struct kcore_extract *kce)
1676{
1677        unlink(kce->extract_filename);
1678}
1679
1680void symbol__elf_init(void)
1681{
1682        elf_version(EV_CURRENT);
1683}
1684