root/tools/perf/util/symbol-minimal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_need_swap
  2. read_build_id
  3. filename__read_debuglink
  4. filename__read_build_id
  5. sysfs__read_build_id
  6. symsrc__init
  7. symsrc__possibly_runtime
  8. symsrc__has_symtab
  9. symsrc__destroy
  10. dso__synthesize_plt_symbols
  11. fd__is_64_bit
  12. dso__type_fd
  13. dso__load_sym
  14. file__read_maps
  15. kcore_extract__create
  16. kcore_extract__delete
  17. kcore_copy
  18. symbol__elf_init
  19. dso__demangle_sym

   1 #include "dso.h"
   2 #include "symbol.h"
   3 #include "symsrc.h"
   4 
   5 #include <errno.h>
   6 #include <unistd.h>
   7 #include <stdio.h>
   8 #include <fcntl.h>
   9 #include <string.h>
  10 #include <stdlib.h>
  11 #include <byteswap.h>
  12 #include <sys/stat.h>
  13 #include <linux/zalloc.h>
  14 #include <internal/lib.h>
  15 
  16 static bool check_need_swap(int file_endian)
  17 {
  18         const int data = 1;
  19         u8 *check = (u8 *)&data;
  20         int host_endian;
  21 
  22         if (check[0] == 1)
  23                 host_endian = ELFDATA2LSB;
  24         else
  25                 host_endian = ELFDATA2MSB;
  26 
  27         return host_endian != file_endian;
  28 }
  29 
  30 #define NOTE_ALIGN(sz) (((sz) + 3) & ~3)
  31 
  32 #define NT_GNU_BUILD_ID 3
  33 
  34 static int read_build_id(void *note_data, size_t note_len, void *bf,
  35                          size_t size, bool need_swap)
  36 {
  37         struct {
  38                 u32 n_namesz;
  39                 u32 n_descsz;
  40                 u32 n_type;
  41         } *nhdr;
  42         void *ptr;
  43 
  44         ptr = note_data;
  45         while (ptr < (note_data + note_len)) {
  46                 const char *name;
  47                 size_t namesz, descsz;
  48 
  49                 nhdr = ptr;
  50                 if (need_swap) {
  51                         nhdr->n_namesz = bswap_32(nhdr->n_namesz);
  52                         nhdr->n_descsz = bswap_32(nhdr->n_descsz);
  53                         nhdr->n_type = bswap_32(nhdr->n_type);
  54                 }
  55 
  56                 namesz = NOTE_ALIGN(nhdr->n_namesz);
  57                 descsz = NOTE_ALIGN(nhdr->n_descsz);
  58 
  59                 ptr += sizeof(*nhdr);
  60                 name = ptr;
  61                 ptr += namesz;
  62                 if (nhdr->n_type == NT_GNU_BUILD_ID &&
  63                     nhdr->n_namesz == sizeof("GNU")) {
  64                         if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
  65                                 size_t sz = min(size, descsz);
  66                                 memcpy(bf, ptr, sz);
  67                                 memset(bf + sz, 0, size - sz);
  68                                 return 0;
  69                         }
  70                 }
  71                 ptr += descsz;
  72         }
  73 
  74         return -1;
  75 }
  76 
  77 int filename__read_debuglink(const char *filename __maybe_unused,
  78                              char *debuglink __maybe_unused,
  79                              size_t size __maybe_unused)
  80 {
  81         return -1;
  82 }
  83 
  84 /*
  85  * Just try PT_NOTE header otherwise fails
  86  */
  87 int filename__read_build_id(const char *filename, void *bf, size_t size)
  88 {
  89         FILE *fp;
  90         int ret = -1;
  91         bool need_swap = false;
  92         u8 e_ident[EI_NIDENT];
  93         size_t buf_size;
  94         void *buf;
  95         int i;
  96 
  97         fp = fopen(filename, "r");
  98         if (fp == NULL)
  99                 return -1;
 100 
 101         if (fread(e_ident, sizeof(e_ident), 1, fp) != 1)
 102                 goto out;
 103 
 104         if (memcmp(e_ident, ELFMAG, SELFMAG) ||
 105             e_ident[EI_VERSION] != EV_CURRENT)
 106                 goto out;
 107 
 108         need_swap = check_need_swap(e_ident[EI_DATA]);
 109 
 110         /* for simplicity */
 111         fseek(fp, 0, SEEK_SET);
 112 
 113         if (e_ident[EI_CLASS] == ELFCLASS32) {
 114                 Elf32_Ehdr ehdr;
 115                 Elf32_Phdr *phdr;
 116 
 117                 if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
 118                         goto out;
 119 
 120                 if (need_swap) {
 121                         ehdr.e_phoff = bswap_32(ehdr.e_phoff);
 122                         ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
 123                         ehdr.e_phnum = bswap_16(ehdr.e_phnum);
 124                 }
 125 
 126                 buf_size = ehdr.e_phentsize * ehdr.e_phnum;
 127                 buf = malloc(buf_size);
 128                 if (buf == NULL)
 129                         goto out;
 130 
 131                 fseek(fp, ehdr.e_phoff, SEEK_SET);
 132                 if (fread(buf, buf_size, 1, fp) != 1)
 133                         goto out_free;
 134 
 135                 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
 136                         void *tmp;
 137                         long offset;
 138 
 139                         if (need_swap) {
 140                                 phdr->p_type = bswap_32(phdr->p_type);
 141                                 phdr->p_offset = bswap_32(phdr->p_offset);
 142                                 phdr->p_filesz = bswap_32(phdr->p_filesz);
 143                         }
 144 
 145                         if (phdr->p_type != PT_NOTE)
 146                                 continue;
 147 
 148                         buf_size = phdr->p_filesz;
 149                         offset = phdr->p_offset;
 150                         tmp = realloc(buf, buf_size);
 151                         if (tmp == NULL)
 152                                 goto out_free;
 153 
 154                         buf = tmp;
 155                         fseek(fp, offset, SEEK_SET);
 156                         if (fread(buf, buf_size, 1, fp) != 1)
 157                                 goto out_free;
 158 
 159                         ret = read_build_id(buf, buf_size, bf, size, need_swap);
 160                         if (ret == 0)
 161                                 ret = size;
 162                         break;
 163                 }
 164         } else {
 165                 Elf64_Ehdr ehdr;
 166                 Elf64_Phdr *phdr;
 167 
 168                 if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
 169                         goto out;
 170 
 171                 if (need_swap) {
 172                         ehdr.e_phoff = bswap_64(ehdr.e_phoff);
 173                         ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
 174                         ehdr.e_phnum = bswap_16(ehdr.e_phnum);
 175                 }
 176 
 177                 buf_size = ehdr.e_phentsize * ehdr.e_phnum;
 178                 buf = malloc(buf_size);
 179                 if (buf == NULL)
 180                         goto out;
 181 
 182                 fseek(fp, ehdr.e_phoff, SEEK_SET);
 183                 if (fread(buf, buf_size, 1, fp) != 1)
 184                         goto out_free;
 185 
 186                 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
 187                         void *tmp;
 188                         long offset;
 189 
 190                         if (need_swap) {
 191                                 phdr->p_type = bswap_32(phdr->p_type);
 192                                 phdr->p_offset = bswap_64(phdr->p_offset);
 193                                 phdr->p_filesz = bswap_64(phdr->p_filesz);
 194                         }
 195 
 196                         if (phdr->p_type != PT_NOTE)
 197                                 continue;
 198 
 199                         buf_size = phdr->p_filesz;
 200                         offset = phdr->p_offset;
 201                         tmp = realloc(buf, buf_size);
 202                         if (tmp == NULL)
 203                                 goto out_free;
 204 
 205                         buf = tmp;
 206                         fseek(fp, offset, SEEK_SET);
 207                         if (fread(buf, buf_size, 1, fp) != 1)
 208                                 goto out_free;
 209 
 210                         ret = read_build_id(buf, buf_size, bf, size, need_swap);
 211                         if (ret == 0)
 212                                 ret = size;
 213                         break;
 214                 }
 215         }
 216 out_free:
 217         free(buf);
 218 out:
 219         fclose(fp);
 220         return ret;
 221 }
 222 
 223 int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
 224 {
 225         int fd;
 226         int ret = -1;
 227         struct stat stbuf;
 228         size_t buf_size;
 229         void *buf;
 230 
 231         fd = open(filename, O_RDONLY);
 232         if (fd < 0)
 233                 return -1;
 234 
 235         if (fstat(fd, &stbuf) < 0)
 236                 goto out;
 237 
 238         buf_size = stbuf.st_size;
 239         buf = malloc(buf_size);
 240         if (buf == NULL)
 241                 goto out;
 242 
 243         if (read(fd, buf, buf_size) != (ssize_t) buf_size)
 244                 goto out_free;
 245 
 246         ret = read_build_id(buf, buf_size, build_id, size, false);
 247 out_free:
 248         free(buf);
 249 out:
 250         close(fd);
 251         return ret;
 252 }
 253 
 254 int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
 255                  enum dso_binary_type type)
 256 {
 257         int fd = open(name, O_RDONLY);
 258         if (fd < 0)
 259                 goto out_errno;
 260 
 261         ss->name = strdup(name);
 262         if (!ss->name)
 263                 goto out_close;
 264 
 265         ss->fd = fd;
 266         ss->type = type;
 267 
 268         return 0;
 269 out_close:
 270         close(fd);
 271 out_errno:
 272         dso->load_errno = errno;
 273         return -1;
 274 }
 275 
 276 bool symsrc__possibly_runtime(struct symsrc *ss __maybe_unused)
 277 {
 278         /* Assume all sym sources could be a runtime image. */
 279         return true;
 280 }
 281 
 282 bool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
 283 {
 284         return false;
 285 }
 286 
 287 void symsrc__destroy(struct symsrc *ss)
 288 {
 289         zfree(&ss->name);
 290         close(ss->fd);
 291 }
 292 
 293 int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
 294                                 struct symsrc *ss __maybe_unused)
 295 {
 296         return 0;
 297 }
 298 
 299 static int fd__is_64_bit(int fd)
 300 {
 301         u8 e_ident[EI_NIDENT];
 302 
 303         if (lseek(fd, 0, SEEK_SET))
 304                 return -1;
 305 
 306         if (readn(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
 307                 return -1;
 308 
 309         if (memcmp(e_ident, ELFMAG, SELFMAG) ||
 310             e_ident[EI_VERSION] != EV_CURRENT)
 311                 return -1;
 312 
 313         return e_ident[EI_CLASS] == ELFCLASS64;
 314 }
 315 
 316 enum dso_type dso__type_fd(int fd)
 317 {
 318         Elf64_Ehdr ehdr;
 319         int ret;
 320 
 321         ret = fd__is_64_bit(fd);
 322         if (ret < 0)
 323                 return DSO__TYPE_UNKNOWN;
 324 
 325         if (ret)
 326                 return DSO__TYPE_64BIT;
 327 
 328         if (readn(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
 329                 return DSO__TYPE_UNKNOWN;
 330 
 331         if (ehdr.e_machine == EM_X86_64)
 332                 return DSO__TYPE_X32BIT;
 333 
 334         return DSO__TYPE_32BIT;
 335 }
 336 
 337 int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
 338                   struct symsrc *ss,
 339                   struct symsrc *runtime_ss __maybe_unused,
 340                   int kmodule __maybe_unused)
 341 {
 342         unsigned char build_id[BUILD_ID_SIZE];
 343         int ret;
 344 
 345         ret = fd__is_64_bit(ss->fd);
 346         if (ret >= 0)
 347                 dso->is_64_bit = ret;
 348 
 349         if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
 350                 dso__set_build_id(dso, build_id);
 351         }
 352         return 0;
 353 }
 354 
 355 int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
 356                     mapfn_t mapfn __maybe_unused, void *data __maybe_unused,
 357                     bool *is_64_bit __maybe_unused)
 358 {
 359         return -1;
 360 }
 361 
 362 int kcore_extract__create(struct kcore_extract *kce __maybe_unused)
 363 {
 364         return -1;
 365 }
 366 
 367 void kcore_extract__delete(struct kcore_extract *kce __maybe_unused)
 368 {
 369 }
 370 
 371 int kcore_copy(const char *from_dir __maybe_unused,
 372                const char *to_dir __maybe_unused)
 373 {
 374         return -1;
 375 }
 376 
 377 void symbol__elf_init(void)
 378 {
 379 }
 380 
 381 char *dso__demangle_sym(struct dso *dso __maybe_unused,
 382                         int kmodule __maybe_unused,
 383                         const char *elf_name __maybe_unused)
 384 {
 385         return NULL;
 386 }

/* [<][>][^][v][top][bottom][index][help] */