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