#include #include #include #include #include "link.h" /** * Read the phdr for this segment */ static int load_phdr(struct object *obj, struct segment *seg, size_t index) { if (index >= obj->phdr_len) { ERROR("phdr index [%d] out of bounds", index); return M_ERROR; } seg->phdr = &obj->phdr[index]; seg->phdr_idx = index; return M_SUCCESS; } /** * Read the shdr for this segment */ static int load_shdr(struct object *obj, struct segment *seg, size_t index) { bool found = false; for (size_t i = 0; i < obj->shdr_len; i++) { Elf32_Shdr *hdr = &obj->shdr[i]; // find shdr that matches the offset in phdr if (seg->phdr->p_offset != hdr->sh_offset) continue; // get name uint32_t name = B32(hdr->sh_name); if (name >= obj->shstrtab->len) { ERROR("section name index [%d] out of bounds", name); return M_ERROR; } seg->name = &obj->shstrtab->data[name]; // map bytes uint32_t len = B32(hdr->sh_size); uint32_t off = B32(hdr->sh_offset); seg->bytes = (unsigned char *) (obj->mapped + off); if (BOUND_CHK(obj, len, off)) { ERROR("cannot map seg %s:%d", seg->name, index); return M_ERROR; } found = true; seg->shdr = hdr; seg->shdr_idx = i; break; } if (!found) { ERROR("cannot find shdr for segment [%d]", index); return M_ERROR; } return M_SUCCESS; } /** * Read the relocation table for this segment (if one exists) */ static int load_reltab(struct object *obj, struct segment *seg) { // default to none seg->reltab.len = 0; for (size_t i = 0; i < obj->shdr_len; i++) { Elf32_Shdr *hdr = &obj->shdr[i]; uint32_t type = B32(hdr->sh_type); if (type != SHT_REL && type != SHT_RELA) continue; if (B32(hdr->sh_info) != seg->shdr_idx) continue; uint32_t symtab_idx = B32(hdr->sh_link); if (symtab_idx >= obj->shdr_len) { ERROR("reltab [%d] symtab index [%d] out of bounds", i, symtab_idx); return M_ERROR; } struct symbol_table *symtab = &obj->symtabs[symtab_idx]; if (symtab->len < 1) { ERROR("reltab [%d] symtab is empty or invalid", i); return M_ERROR; } uint32_t len = B32(hdr->sh_size); uint32_t off = B32(hdr->sh_offset); seg->reltab.symtab = symtab; seg->reltab.len = len; seg->reltab.raw = obj->mapped + off; seg->reltab.type = type; if (BOUND_CHK(obj, len, off)) { ERROR("cannot map reltab [%d] for %s", i, seg->name); return M_ERROR; } break; } return M_SUCCESS; } int segment_load(struct object *obj, struct segment *seg, size_t index) { if (load_phdr(obj, seg, index)) return M_ERROR; if (load_shdr(obj, seg, index)) return M_ERROR; if (load_reltab(obj, seg)) return M_ERROR; return M_SUCCESS; }