Exemplo n.º 1
0
/*
 * Retrieve the nth (where n is the `index` argument) shdr (section
 * header) from the given elf instance.
 *
 * A pointer to the shdr is returned on success, NULL on failure.
 */
static
struct lttng_ust_elf_shdr *lttng_ust_elf_get_shdr(struct lttng_ust_elf *elf,
						uint16_t index)
{
	struct lttng_ust_elf_shdr *shdr = NULL;
	off_t offset;

	if (!elf) {
		goto error;
	}

	if (index >= elf->ehdr->e_shnum) {
		goto error;
	}

	shdr = zmalloc(sizeof(struct lttng_ust_elf_shdr));
	if (!shdr) {
		goto error;
	}

	offset = (off_t) elf->ehdr->e_shoff
			+ (off_t) index * elf->ehdr->e_shentsize;
	if (lseek(elf->fd, offset, SEEK_SET) < 0) {
		goto error;
	}

	if (is_elf_32_bit(elf)) {
		Elf32_Shdr elf_shdr;

		if (lttng_ust_read(elf->fd, &elf_shdr, sizeof(elf_shdr))
				< sizeof(elf_shdr)) {
			goto error;
		}
		if (!is_elf_native_endian(elf)) {
			bswap_shdr(elf_shdr);
		}
		copy_shdr(elf_shdr, *shdr);
	} else {
		Elf64_Shdr elf_shdr;

		if (lttng_ust_read(elf->fd, &elf_shdr, sizeof(elf_shdr))
				< sizeof(elf_shdr)) {
			goto error;
		}
		if (!is_elf_native_endian(elf)) {
			bswap_shdr(elf_shdr);
		}
		copy_shdr(elf_shdr, *shdr);
	}

	return shdr;

error:
	free(shdr);
	return NULL;
}
Exemplo n.º 2
0
/* Best attempt to load symbols from this ELF object. */
static void load_symbols(struct elfhdr *hdr, int fd)
{
    unsigned int i, nsyms;
    struct elf_shdr sechdr, symtab, strtab;
    char *strings;
    struct syminfo *s;
    struct elf_sym *syms;

    lseek(fd, hdr->e_shoff, SEEK_SET);
    for (i = 0; i < hdr->e_shnum; i++) {
        if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
            return;
#ifdef BSWAP_NEEDED
        bswap_shdr(&sechdr);
#endif
        if (sechdr.sh_type == SHT_SYMTAB) {
            symtab = sechdr;
            lseek(fd, hdr->e_shoff
                  + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
            if (read(fd, &strtab, sizeof(strtab))
                != sizeof(strtab))
                return;
#ifdef BSWAP_NEEDED
            bswap_shdr(&strtab);
#endif
            goto found;
        }
    }
    return; /* Shouldn't happen... */

 found:
    /* Now know where the strtab and symtab are.  Snarf them. */
    s = malloc(sizeof(*s));
    syms = malloc(symtab.sh_size);
    if (!syms)
        return;
    s->disas_strtab = strings = malloc(strtab.sh_size);
    if (!s->disas_strtab)
        return;

    lseek(fd, symtab.sh_offset, SEEK_SET);
    if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
        return;

    nsyms = symtab.sh_size / sizeof(struct elf_sym);

    i = 0;
    while (i < nsyms) {
#ifdef BSWAP_NEEDED
        bswap_sym(syms + i);
#endif
        // Throw away entries which we do not need.
        if (syms[i].st_shndx == SHN_UNDEF ||
                syms[i].st_shndx >= SHN_LORESERVE ||
                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
            nsyms--;
            if (i < nsyms) {
                syms[i] = syms[nsyms];
            }
            continue;
        }
#if defined(TARGET_ARM) || defined (TARGET_MIPS)
        /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
        syms[i].st_value &= ~(target_ulong)1;
#endif
        i++;
    }
    syms = realloc(syms, nsyms * sizeof(*syms));

    qsort(syms, nsyms, sizeof(*syms), symcmp);

    lseek(fd, strtab.sh_offset, SEEK_SET);
    if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
        return;
    s->disas_num_syms = nsyms;
#if ELF_CLASS == ELFCLASS32
    s->disas_symtab.elf32 = syms;
    s->lookup_symbol = lookup_symbolxx;
#else
    s->disas_symtab.elf64 = syms;
    s->lookup_symbol = lookup_symbolxx;
#endif
    s->next = syminfos;
    syminfos = s;
}