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