diff options
Diffstat (limited to '')
-rw-r--r-- | mld/obj.c | 103 |
1 files changed, 90 insertions, 13 deletions
@@ -49,10 +49,10 @@ static int load_ehdr(struct object *object) EHDR_ASSERT(type, sizeof(Elf32_Half)); EHDR_ASSERT(machine, sizeof(Elf32_Half)); EHDR_ASSERT(version, sizeof(Elf32_Word)); - EHDR_ASSERT(flags, sizeof(Elf32_Word)); + // EHDR_ASSERT(flags, sizeof(Elf32_Word)); EHDR_ASSERT(ehsize, sizeof(Elf32_Half)); - EHDR_ASSERT(phentsize, sizeof(Elf32_Half)); - EHDR_ASSERT(shentsize, sizeof(Elf32_Half)); + // EHDR_ASSERT(phentsize, sizeof(Elf32_Half)); + // EHDR_ASSERT(shentsize, sizeof(Elf32_Half)); #undef EHDR_ASSERT @@ -82,25 +82,96 @@ static int load_shdr(struct object *object) } /** - * Map the phdr + * Create the phdr */ -static int load_phdr(struct object *object) +static int create_phdr(struct object *object) { - size_t phdr_len = B16(object->ehdr->e_phentsize) * - B16(object->ehdr->e_phnum); - size_t phdr_off = B32(object->ehdr->e_phoff); - object->phdr = (Elf32_Phdr *) (object->mapped + phdr_off); - object->phdr_len = B16(object->ehdr->e_phnum); + uint32_t entries = 0; + for (uint32_t i = 0; i < object->shdr_len; i++) { + Elf32_Shdr *hdr = &object->shdr[i]; + uint32_t type = B32(hdr->sh_type); + + if (type != SHT_PROGBITS && type != SHT_NOBITS) + continue; + + entries += 1; + } - if (BOUND_CHK(object, phdr_len, phdr_off)) { - ERROR("cannot read phdr"); + Elf32_Phdr *phdr = malloc(entries * sizeof(Elf32_Phdr)); + if (phdr == NULL) { + PERROR("cannot alloc"); return M_ERROR; } + object->phdr = phdr; + object->phdr_len = entries; + object->phdr_local = true; + + uint32_t *mapping = malloc(entries * sizeof(uint32_t)); + if (mapping == NULL) { + PERROR("cannot alloc"); + return M_ERROR; + } + + object->phdr_to_shdr_mapping = mapping; + + uint32_t index = 0; + for (uint32_t i = 0; i < object->shdr_len; i++) { + Elf32_Shdr *hdr = &object->shdr[i]; + uint32_t type = B32(hdr->sh_type); + + if (type != SHT_PROGBITS && type != SHT_NOBITS) + continue; + mapping[index] = i; + phdr[index++] = (Elf32_Phdr) { + .p_type = B32(PT_LOAD), + .p_flags = B32( + // execute + ((B32(hdr->sh_flags) & SHF_EXECINSTR) + ? PF_X : 0) | + // write + ((B32(hdr->sh_flags) & SHF_WRITE) + ? PF_W : 0) | + // read + ((B32(hdr->sh_flags) & SHF_ALLOC) + ? PF_R : 0) + ), + .p_offset = hdr->sh_offset, + .p_vaddr = hdr->sh_addr, + .p_paddr = hdr->sh_addr, + .p_filesz = hdr->sh_size, + .p_memsz = hdr->sh_size, + .p_align = B32(SEC_ALIGN), + }; + } + return M_SUCCESS; } /** + * Map the phdr + */ +static int load_phdr(struct object *object) +{ + //size_t phdr_len = B16(object->ehdr->e_phentsize) * + // B16(object->ehdr->e_phnum); + + //if (phdr_len < 1) + return create_phdr(object); + + //size_t phdr_off = B32(object->ehdr->e_phoff); + //object->phdr = (Elf32_Phdr *) (object->mapped + phdr_off); + //object->phdr_len = B16(object->ehdr->e_phnum); + + //if (BOUND_CHK(object, phdr_len, phdr_off)) { + // ERROR("cannot read phdr"); + // return M_ERROR; + //} + + //return M_SUCCESS; +} + +/** * Load the strtabs */ static int load_strtabs(struct object *object) @@ -231,7 +302,7 @@ static int load_shstrtab(struct object *object) */ static int load_segments(struct object *object) { - object->segment_len = B16(object->ehdr->e_phnum); + object->segment_len = object->phdr_len; object->segments = malloc(sizeof(struct segment) * object->segment_len); @@ -287,6 +358,8 @@ int object_load(struct object *object, char *path, uint32_t index) object->mapped = NULL; object->name = path; object->index = index; + object->phdr_local = false; + object->phdr_to_shdr_mapping = NULL; /** load the file */ if (map_file(object, path)) @@ -331,6 +404,10 @@ void object_free(struct object *obj) free(obj->strtabs); if (obj->segments != NULL) free(obj->segments); + if (obj->phdr_local) + free(obj->phdr); + if (obj->phdr_to_shdr_mapping) + free(obj->phdr_to_shdr_mapping); if (obj->fd > 0) close(obj->fd); if (obj->mapped != NULL && obj->mapped != MAP_FAILED) |