static bfelf64_sword private_get_relocation_tables(struct bfelf_file_t *ef) { bfelf64_sword i = 0; bfelf64_sword ret = 0; for (i = 0; i < ef->ehdr->e_shnum; i++) { struct bfelf_shdr *shdr = private_get_section(ef, i); if (shdr->sh_type == bfsht_rel) unsupported_rel("the ELF loader does not support modules with REL " "type relocation sections"); if (shdr->sh_type == bfsht_rela) { if (ef->num_rela >= BFELF_MAX_RELATAB) return loader_full("increase BFELF_MAX_RELATAB"); ret = private_check_section(shdr, bfsht_rela, bfshf_ai, 8, sizeof(struct bfelf_rela)); if (ret != BFELF_SUCCESS) return ret; ef->relatab[ef->num_rela].num = shdr->sh_size / sizeof(struct bfelf_rela); ef->relatab[ef->num_rela].tab = (struct bfelf_rela *)(ef->file + shdr->sh_offset); ef->num_rela++; } } return BFELF_SUCCESS; }
int64_t private_check_segments(struct bfelf_file_t *ef) { bfelf64_xword i = 0; for (i = 0; i < ef->ehdr->e_phnum; i++) { struct bfelf_phdr *phdr = private_get_segment(ef, i); if (phdr->p_type != bfpt_load) continue; if (ef->num_loadable_segments >= BFELF_MAX_SEGMENTS) return loader_full("increase BFELF_MAX_SEGMENTS"); if (phdr->p_memsz < phdr->p_filesz) return invalid_segment("segment mem size is less then file size"); if (phdr->p_vaddr != phdr->p_paddr) return invalid_segment("expect p_vaddr == p_paddr"); if (phdr->p_align != 0x1000 && phdr->p_align != 0x200000) return invalid_segment("expect 4k or 2M alignment"); if (phdr->p_offset >= ef->fsize) return invalid_segment("segment offset out of bounds"); ef->loadable_segments[ef->num_loadable_segments] = phdr; ef->num_loadable_segments++; } return BFELF_SUCCESS; }
bfelf64_sword bfelf_loader_add(struct bfelf_loader_t *loader, struct bfelf_file_t *ef, char *exec) { if (!loader) return invalid_argument("loader == NULL"); if (!ef) return invalid_argument("ef == NULL"); if (loader->num >= BFELF_MAX_MODULES) return loader_full("increase BFELF_MAX_MODULES"); ef->exec = exec; loader->efs[loader->num++] = ef; return BFELF_SUCCESS; }
static bfelf64_sword private_check_segments(struct bfelf_file_t *ef) { bfelf64_sword i = 0; for (i = 0; i < ef->ehdr->e_phnum; i++) { struct bfelf_phdr *phdr = private_get_segment(ef, i); if (phdr->p_type != bfpt_load) continue; if (ef->num_loadable_segments >= BFELF_MAX_SEGMENTS) return loader_full("increase BFELF_MAX_SEGMENTS"); if (phdr->p_memsz < phdr->p_filesz) return invalid_segment("segment mem size is less then file size"); if (phdr->p_vaddr != phdr->p_paddr) return invalid_segment("expect p_vaddr == p_paddr"); /* * At the moment, libc++.so has an alignment of 20, which is really * strange. Will need to find out why at some point * * if (phdr->p_align != 0x1000 && phdr->p_align != 0x200000) * return invalid_segment("expect 4k or 2M alignment"); */ if (phdr->p_offset >= ef->fsize) return invalid_segment("segment offset out of bounds"); ef->loadable_segments[ef->num_loadable_segments] = phdr; ef->num_loadable_segments++; } return BFELF_SUCCESS; }