Пример #1
0
static int
shdr_read(const struct buffer *in, struct parsed_elf *pelf,
          struct xdr *xdr, int bit64)
{
	struct buffer b;
	Elf64_Shdr *shdr;
	Elf64_Ehdr *ehdr;
	int i;

	ehdr = &pelf->ehdr;

	/* cons up an input buffer for the section headers.
	 * Note that the section headers can be anywhere,
	 * per the ELF spec, You'd be surprised how many ELF
	 * readers miss this little detail.
	 */
	buffer_splice(&b, in, ehdr->e_shoff, ehdr->e_shentsize * ehdr->e_shnum);
	if (check_size(in, ehdr->e_shoff, buffer_size(&b), "section headers"))
		return -1;

	/* gather up all the shdrs. */
	shdr = calloc(ehdr->e_shnum, sizeof(*shdr));
	for (i = 0; i < ehdr->e_shnum; i++) {
		DEBUG("Parsing section %d\n", i);
		elf_shdr(&b, &shdr[i], ehdr->e_shentsize, xdr, bit64);
	}

	pelf->shdr = shdr;

	return 0;
}
Пример #2
0
void *elf_get_section_ptr(size_t shndx, Elf32_Word address, size_t size)
{
    Elf32_Shdr *shdr = elf_shdr(shndx);
    if(shdr == nullptr)
        return nullptr;
    if(address + size > shdr->sh_size)
        return nullptr;
    if(shdr->sh_offset + shdr->sh_size > g_elf_size)
        return nullptr;
    return g_elf_buf + shdr->sh_offset + address;
}
Пример #3
0
size_t elf_find_reloc_section(size_t shndx)
{
    /* find the relocation section */
    for(size_t i = 0; i < elf_ehdr()->e_shnum; i++)
    {
        Elf32_Shdr *shdr = elf_shdr(i);
        if(shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA)
            continue;
        if(shdr->sh_info != shndx)
            continue;
        return i;
    }
    return 0;
}
Пример #4
0
size_t elf_map_virt_addr(uint32_t address, Elf32_Word& out_off)
{
    /* for relocatable file, this is trivial */
    for(size_t i = 0; i < elf_ehdr()->e_shnum; i++)
    {
        Elf32_Shdr *shdr = elf_shdr(i);
        if(shdr->sh_offset <= address && address < shdr->sh_offset + shdr->sh_size)
        {
            out_off = address - shdr->sh_offset;
            if(g_verbose)
            {
                printf("[map %#x to section %zi (%s) at %#x]\n", address, i,
                    elf_get_section_name(i), out_off);
            }
            return i;
        }
    }
    return 0; /* section 0 is always invalid */
}
Пример #5
0
/* make sure the string has a final zero in the section, optionally check characters
 * are printable */
const char *elf_get_string_ptr_safe(size_t shndx, Elf32_Word offset, bool want_print = true)
{
    Elf32_Shdr *shdr = elf_shdr(shndx);
    if(shdr == nullptr)
        return nullptr;
    /* address must be in the section */
    if(offset >= shdr->sh_size)
        return nullptr;
    /* determine maximum size */
    size_t max_sz = shdr->sh_size - offset;
    const char *ptr = (const char *)(g_elf_buf + shdr->sh_offset + offset);
    for(size_t i = 0; i < max_sz; i++)
    {
        if(ptr[i] == 0) /* found final 0, everything is fine */
            return ptr;
        if(want_print && !isprint(ptr[i]))
            return nullptr;
    }
    return nullptr;
}
Пример #6
0
bool elf_init()
{
    if(g_elf_size < sizeof(Elf32_Ehdr))
    {
        printf("Invalid ELF file: too small\n");
        return false;
    }
    Elf32_Ehdr *ehdr = elf_ehdr();
    if(ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
            ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
            ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
            ehdr->e_ident[EI_MAG3] != ELFMAG3)
    {
        printf("Invalid ELF file: invalid ident\n");
        return false;
    }
    /* we only support relocatable files */
    if(ehdr->e_type != ET_REL)
    {
        printf("Unsupported ELF file: this is not a relocatable file\n");
        return false;
    }
    if(ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_machine != EM_ARM)
    {
        printf("Unsupported ELF file: this is not a 32-bit ARM ELF file\n");
        return false;
    }
    /* go through sections */
    if(ehdr->e_shoff == 0)
    {
        printf("Invalid ELF file: no sections\n");
        return false;
    }
    if(ehdr->e_shentsize < sizeof(Elf32_Shdr))
    {
        printf("Invalid ELF file: section entry size too small\n");
        return false;
    }
    if(NTH_SHDR_OFF(ehdr->e_shnum) > g_elf_size)
    {
        printf("Invalid ELF file: sections header does not fit in the file\n");
        return false;
    }
    for(size_t i = 0; i < ehdr->e_shnum; i++)
    {
        Elf32_Shdr *shdr = (Elf32_Shdr *)(g_elf_buf + NTH_SHDR_OFF(i));
        if(shdr->sh_type == SHT_SYMTAB)
            g_elf_symtab = shdr;
    }
    /* handle symbol table */
    if(g_elf_symtab)
    {
        if(g_elf_symtab->sh_offset + g_elf_symtab->sh_size > g_elf_size)
        {
            printf("Invalid ELF file: symtab does not file in the file\n");
            return false;
        }
        g_elf_symtab_strtab = elf_shdr(g_elf_symtab->sh_link);
        if(g_elf_symtab_strtab == nullptr)
        {
            printf("Invalid ELF file: symtab's strtab is not valid\n");
        }
        if(g_elf_symtab_strtab->sh_type != SHT_STRTAB)
        {
            printf("Invalid ELF file: symtab's strtab is not a string table\n");
            return false;
        }
    }
    /* handle section string table */
    if(ehdr->e_shstrndx != SHN_UNDEF)
    {
        g_elf_shstrtab = elf_shdr(ehdr->e_shstrndx);
        if(g_elf_shstrtab == nullptr)
        {
            printf("Invalid ELF file: section string table is invalid\n");
            return false;
        }
    }

    return true;
}
Пример #7
0
/* take the position of a 32-bit address in the section and apply relocation if
 * any */
void *elf_reloc_addr32(size_t shndx, Elf32_Word offset)
{
    /* read value */
    uint32_t *val = (uint32_t *)elf_get_section_ptr(shndx, offset, 4);
    if(val == nullptr)
        return 0; /* invalid */
    /* find reloc section if any */
    size_t relshndx = elf_find_reloc_section(shndx);
    if(relshndx == 0)
        return g_elf_buf + *val; /* no relocation applies */
    Elf32_Shdr *shdr = elf_shdr(relshndx);
    /* find relocation that applies */
    if(shdr->sh_type == SHT_RELA)
    {
        printf("Warning: unsupported RELA relocation type\n");
        return 0;
    }
    Elf32_Rel *rel = (Elf32_Rel *)elf_get_section_ptr(relshndx, 0, shdr->sh_size);
    if(rel == nullptr)
    {
        printf("Warning: invalid relocation section\n");
        return 0;
    }
    size_t sym_count = shdr->sh_size / sizeof(Elf32_Rel);
    for(size_t i = 0; i < sym_count; i++)
    {
        /* for relocatable files, r_offset is the offset in the section */
        if(rel[i].r_offset != offset)
            continue;
        /* find symbol, ignore shdr->sh_link and assume it is g_elf_symtab
         * since the file should have only one symbol table anyway */
        Elf32_Sym *sym = elf_get_symbol_by_index(ELF32_R_SYM(rel[i].r_info));
        /* found it! */
        if(g_verbose)
        {
            printf("[section %zu (%s) offset %#x reloc val %#x type %d sym %d (%s)]\n",
                shndx, elf_get_section_name(shndx), offset, *val,
                ELF32_R_TYPE(rel[i].r_info), ELF32_R_SYM(rel[i].r_info),
                sym ? elf_get_symbol_name(sym) : "<undef>");
        }
        /* apply reloc */
        if(ELF32_R_TYPE(rel[i].r_info) == R_ARM_ABS32)
        {
            if(sym == nullptr)
            {
                printf("Warning: R_ARM_ABS32 reloc with invalid symbol reference\n");
                return 0;
            }
            return *val + (uint8_t *)elf_get_symbol_ptr(sym, 0);
        }
        else
        {
            printf("Warning: unsupported relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
            return 0;
        }
    }
    /* no reloc applies */
    if(g_verbose)
    {
        printf("[section %zu (%s) offset %#x no reloc found]\n", shndx,
            elf_get_section_name(shndx), offset);
    }
    return g_elf_buf + *val; /* no relocation applies */
}
Пример #8
0
const char *elf_get_section_name(size_t index)
{
    Elf32_Shdr *shdr = elf_shdr(index);
    return shdr ? elf_get_str(g_elf_shstrtab, shdr->sh_name) : nullptr;
}