Back to home page

OSCL-LXR

 
 

    


0001 #include "dso.h"
0002 #include "symbol.h"
0003 #include "symsrc.h"
0004 
0005 #include <errno.h>
0006 #include <unistd.h>
0007 #include <stdio.h>
0008 #include <fcntl.h>
0009 #include <string.h>
0010 #include <stdlib.h>
0011 #include <byteswap.h>
0012 #include <sys/stat.h>
0013 #include <linux/zalloc.h>
0014 #include <internal/lib.h>
0015 
0016 static bool check_need_swap(int file_endian)
0017 {
0018     const int data = 1;
0019     u8 *check = (u8 *)&data;
0020     int host_endian;
0021 
0022     if (check[0] == 1)
0023         host_endian = ELFDATA2LSB;
0024     else
0025         host_endian = ELFDATA2MSB;
0026 
0027     return host_endian != file_endian;
0028 }
0029 
0030 #define NOTE_ALIGN(sz) (((sz) + 3) & ~3)
0031 
0032 #define NT_GNU_BUILD_ID 3
0033 
0034 static int read_build_id(void *note_data, size_t note_len, struct build_id *bid,
0035              bool need_swap)
0036 {
0037     size_t size = sizeof(bid->data);
0038     struct {
0039         u32 n_namesz;
0040         u32 n_descsz;
0041         u32 n_type;
0042     } *nhdr;
0043     void *ptr;
0044 
0045     ptr = note_data;
0046     while (ptr < (note_data + note_len)) {
0047         const char *name;
0048         size_t namesz, descsz;
0049 
0050         nhdr = ptr;
0051         if (need_swap) {
0052             nhdr->n_namesz = bswap_32(nhdr->n_namesz);
0053             nhdr->n_descsz = bswap_32(nhdr->n_descsz);
0054             nhdr->n_type = bswap_32(nhdr->n_type);
0055         }
0056 
0057         namesz = NOTE_ALIGN(nhdr->n_namesz);
0058         descsz = NOTE_ALIGN(nhdr->n_descsz);
0059 
0060         ptr += sizeof(*nhdr);
0061         name = ptr;
0062         ptr += namesz;
0063         if (nhdr->n_type == NT_GNU_BUILD_ID &&
0064             nhdr->n_namesz == sizeof("GNU")) {
0065             if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
0066                 size_t sz = min(size, descsz);
0067                 memcpy(bid->data, ptr, sz);
0068                 memset(bid->data + sz, 0, size - sz);
0069                 bid->size = sz;
0070                 return 0;
0071             }
0072         }
0073         ptr += descsz;
0074     }
0075 
0076     return -1;
0077 }
0078 
0079 int filename__read_debuglink(const char *filename __maybe_unused,
0080                  char *debuglink __maybe_unused,
0081                  size_t size __maybe_unused)
0082 {
0083     return -1;
0084 }
0085 
0086 /*
0087  * Just try PT_NOTE header otherwise fails
0088  */
0089 int filename__read_build_id(const char *filename, struct build_id *bid)
0090 {
0091     FILE *fp;
0092     int ret = -1;
0093     bool need_swap = false;
0094     u8 e_ident[EI_NIDENT];
0095     size_t buf_size;
0096     void *buf;
0097     int i;
0098 
0099     fp = fopen(filename, "r");
0100     if (fp == NULL)
0101         return -1;
0102 
0103     if (fread(e_ident, sizeof(e_ident), 1, fp) != 1)
0104         goto out;
0105 
0106     if (memcmp(e_ident, ELFMAG, SELFMAG) ||
0107         e_ident[EI_VERSION] != EV_CURRENT)
0108         goto out;
0109 
0110     need_swap = check_need_swap(e_ident[EI_DATA]);
0111 
0112     /* for simplicity */
0113     fseek(fp, 0, SEEK_SET);
0114 
0115     if (e_ident[EI_CLASS] == ELFCLASS32) {
0116         Elf32_Ehdr ehdr;
0117         Elf32_Phdr *phdr;
0118 
0119         if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
0120             goto out;
0121 
0122         if (need_swap) {
0123             ehdr.e_phoff = bswap_32(ehdr.e_phoff);
0124             ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
0125             ehdr.e_phnum = bswap_16(ehdr.e_phnum);
0126         }
0127 
0128         buf_size = ehdr.e_phentsize * ehdr.e_phnum;
0129         buf = malloc(buf_size);
0130         if (buf == NULL)
0131             goto out;
0132 
0133         fseek(fp, ehdr.e_phoff, SEEK_SET);
0134         if (fread(buf, buf_size, 1, fp) != 1)
0135             goto out_free;
0136 
0137         for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
0138             void *tmp;
0139             long offset;
0140 
0141             if (need_swap) {
0142                 phdr->p_type = bswap_32(phdr->p_type);
0143                 phdr->p_offset = bswap_32(phdr->p_offset);
0144                 phdr->p_filesz = bswap_32(phdr->p_filesz);
0145             }
0146 
0147             if (phdr->p_type != PT_NOTE)
0148                 continue;
0149 
0150             buf_size = phdr->p_filesz;
0151             offset = phdr->p_offset;
0152             tmp = realloc(buf, buf_size);
0153             if (tmp == NULL)
0154                 goto out_free;
0155 
0156             buf = tmp;
0157             fseek(fp, offset, SEEK_SET);
0158             if (fread(buf, buf_size, 1, fp) != 1)
0159                 goto out_free;
0160 
0161             ret = read_build_id(buf, buf_size, bid, need_swap);
0162             if (ret == 0)
0163                 ret = bid->size;
0164             break;
0165         }
0166     } else {
0167         Elf64_Ehdr ehdr;
0168         Elf64_Phdr *phdr;
0169 
0170         if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
0171             goto out;
0172 
0173         if (need_swap) {
0174             ehdr.e_phoff = bswap_64(ehdr.e_phoff);
0175             ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
0176             ehdr.e_phnum = bswap_16(ehdr.e_phnum);
0177         }
0178 
0179         buf_size = ehdr.e_phentsize * ehdr.e_phnum;
0180         buf = malloc(buf_size);
0181         if (buf == NULL)
0182             goto out;
0183 
0184         fseek(fp, ehdr.e_phoff, SEEK_SET);
0185         if (fread(buf, buf_size, 1, fp) != 1)
0186             goto out_free;
0187 
0188         for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
0189             void *tmp;
0190             long offset;
0191 
0192             if (need_swap) {
0193                 phdr->p_type = bswap_32(phdr->p_type);
0194                 phdr->p_offset = bswap_64(phdr->p_offset);
0195                 phdr->p_filesz = bswap_64(phdr->p_filesz);
0196             }
0197 
0198             if (phdr->p_type != PT_NOTE)
0199                 continue;
0200 
0201             buf_size = phdr->p_filesz;
0202             offset = phdr->p_offset;
0203             tmp = realloc(buf, buf_size);
0204             if (tmp == NULL)
0205                 goto out_free;
0206 
0207             buf = tmp;
0208             fseek(fp, offset, SEEK_SET);
0209             if (fread(buf, buf_size, 1, fp) != 1)
0210                 goto out_free;
0211 
0212             ret = read_build_id(buf, buf_size, bid, need_swap);
0213             if (ret == 0)
0214                 ret = bid->size;
0215             break;
0216         }
0217     }
0218 out_free:
0219     free(buf);
0220 out:
0221     fclose(fp);
0222     return ret;
0223 }
0224 
0225 int sysfs__read_build_id(const char *filename, struct build_id *bid)
0226 {
0227     int fd;
0228     int ret = -1;
0229     struct stat stbuf;
0230     size_t buf_size;
0231     void *buf;
0232 
0233     fd = open(filename, O_RDONLY);
0234     if (fd < 0)
0235         return -1;
0236 
0237     if (fstat(fd, &stbuf) < 0)
0238         goto out;
0239 
0240     buf_size = stbuf.st_size;
0241     buf = malloc(buf_size);
0242     if (buf == NULL)
0243         goto out;
0244 
0245     if (read(fd, buf, buf_size) != (ssize_t) buf_size)
0246         goto out_free;
0247 
0248     ret = read_build_id(buf, buf_size, bid, false);
0249 out_free:
0250     free(buf);
0251 out:
0252     close(fd);
0253     return ret;
0254 }
0255 
0256 int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
0257              enum dso_binary_type type)
0258 {
0259     int fd = open(name, O_RDONLY);
0260     if (fd < 0)
0261         goto out_errno;
0262 
0263     ss->name = strdup(name);
0264     if (!ss->name)
0265         goto out_close;
0266 
0267     ss->fd = fd;
0268     ss->type = type;
0269 
0270     return 0;
0271 out_close:
0272     close(fd);
0273 out_errno:
0274     dso->load_errno = errno;
0275     return -1;
0276 }
0277 
0278 bool symsrc__possibly_runtime(struct symsrc *ss __maybe_unused)
0279 {
0280     /* Assume all sym sources could be a runtime image. */
0281     return true;
0282 }
0283 
0284 bool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
0285 {
0286     return false;
0287 }
0288 
0289 void symsrc__destroy(struct symsrc *ss)
0290 {
0291     zfree(&ss->name);
0292     close(ss->fd);
0293 }
0294 
0295 int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
0296                 struct symsrc *ss __maybe_unused)
0297 {
0298     return 0;
0299 }
0300 
0301 static int fd__is_64_bit(int fd)
0302 {
0303     u8 e_ident[EI_NIDENT];
0304 
0305     if (lseek(fd, 0, SEEK_SET))
0306         return -1;
0307 
0308     if (readn(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident))
0309         return -1;
0310 
0311     if (memcmp(e_ident, ELFMAG, SELFMAG) ||
0312         e_ident[EI_VERSION] != EV_CURRENT)
0313         return -1;
0314 
0315     return e_ident[EI_CLASS] == ELFCLASS64;
0316 }
0317 
0318 enum dso_type dso__type_fd(int fd)
0319 {
0320     Elf64_Ehdr ehdr;
0321     int ret;
0322 
0323     ret = fd__is_64_bit(fd);
0324     if (ret < 0)
0325         return DSO__TYPE_UNKNOWN;
0326 
0327     if (ret)
0328         return DSO__TYPE_64BIT;
0329 
0330     if (readn(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
0331         return DSO__TYPE_UNKNOWN;
0332 
0333     if (ehdr.e_machine == EM_X86_64)
0334         return DSO__TYPE_X32BIT;
0335 
0336     return DSO__TYPE_32BIT;
0337 }
0338 
0339 int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
0340           struct symsrc *ss,
0341           struct symsrc *runtime_ss __maybe_unused,
0342           int kmodule __maybe_unused)
0343 {
0344     struct build_id bid;
0345     int ret;
0346 
0347     ret = fd__is_64_bit(ss->fd);
0348     if (ret >= 0)
0349         dso->is_64_bit = ret;
0350 
0351     if (filename__read_build_id(ss->name, &bid) > 0)
0352         dso__set_build_id(dso, &bid);
0353     return 0;
0354 }
0355 
0356 int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
0357             mapfn_t mapfn __maybe_unused, void *data __maybe_unused,
0358             bool *is_64_bit __maybe_unused)
0359 {
0360     return -1;
0361 }
0362 
0363 int kcore_extract__create(struct kcore_extract *kce __maybe_unused)
0364 {
0365     return -1;
0366 }
0367 
0368 void kcore_extract__delete(struct kcore_extract *kce __maybe_unused)
0369 {
0370 }
0371 
0372 int kcore_copy(const char *from_dir __maybe_unused,
0373            const char *to_dir __maybe_unused)
0374 {
0375     return -1;
0376 }
0377 
0378 void symbol__elf_init(void)
0379 {
0380 }
0381 
0382 char *dso__demangle_sym(struct dso *dso __maybe_unused,
0383             int kmodule __maybe_unused,
0384             const char *elf_name __maybe_unused)
0385 {
0386     return NULL;
0387 }