Skip to content

Commit

Permalink
lib: Add support for loading PE images
Browse files Browse the repository at this point in the history
  • Loading branch information
48cf committed Dec 28, 2024
1 parent 3507224 commit 153bde8
Show file tree
Hide file tree
Showing 6 changed files with 450 additions and 24 deletions.
24 changes: 18 additions & 6 deletions common/lib/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ int elf_bits(uint8_t *elf) {
struct elf64_hdr *hdr = (void *)elf;

if (strncmp((char *)hdr->ident, "\177ELF", 4)) {
printv("elf: Not a valid ELF file.\n");
return -1;
}

Expand Down Expand Up @@ -564,7 +563,9 @@ static bool elf64_apply_relocations(uint8_t *elf, struct elf64_hdr *hdr, void *b
bool elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit, uint64_t slide) {
struct elf64_hdr *hdr = (void *)elf;

elf64_validate(hdr);
if (elf_bits(elf) == -1) {
return false;
}

if (hdr->sh_num == 0) {
return false;
Expand Down Expand Up @@ -626,7 +627,7 @@ static uint64_t elf64_max_align(uint8_t *elf) {
return ret;
}

static void elf64_get_ranges(uint8_t *elf, uint64_t slide, struct elf_range **_ranges, uint64_t *_ranges_count) {
static void elf64_get_ranges(uint8_t *elf, uint64_t slide, struct mem_range **_ranges, uint64_t *_ranges_count) {
struct elf64_hdr *hdr = (void *)elf;

uint64_t ranges_count = 0;
Expand Down Expand Up @@ -657,7 +658,7 @@ static void elf64_get_ranges(uint8_t *elf, uint64_t slide, struct elf_range **_r
panic(true, "elf: No higher half PHDRs exist");
}

struct elf_range *ranges = ext_mem_alloc(ranges_count * sizeof(struct elf_range));
struct mem_range *ranges = ext_mem_alloc(ranges_count * sizeof(struct mem_range));

size_t r = 0;
for (uint16_t i = 0; i < hdr->ph_num; i++) {
Expand All @@ -678,7 +679,18 @@ static void elf64_get_ranges(uint8_t *elf, uint64_t slide, struct elf_range **_r

ranges[r].base = load_addr & ~(phdr->p_align - 1);
ranges[r].length = ALIGN_UP(this_top - ranges[r].base, phdr->p_align);
ranges[r].permissions = phdr->p_flags & 0b111;

if (phdr->p_flags & ELF_PF_X) {
ranges[r].permissions |= MEM_RANGE_X;
}

if (phdr->p_flags & ELF_PF_W) {
ranges[r].permissions |= MEM_RANGE_W;
}

if (phdr->p_flags & ELF_PF_R) {
ranges[r].permissions |= MEM_RANGE_R;
}

r++;
}
Expand All @@ -687,7 +699,7 @@ static void elf64_get_ranges(uint8_t *elf, uint64_t slide, struct elf_range **_r
*_ranges = ranges;
}

bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct elf_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *_image_size, uint64_t *_image_size_before_bss, bool *is_reloc) {
bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct mem_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *_image_size, uint64_t *_image_size_before_bss, bool *is_reloc) {
struct elf64_hdr *hdr = (void *)elf;

elf64_validate(hdr);
Expand Down
9 changes: 2 additions & 7 deletions common/lib/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@
#include <stdint.h>
#include <stdbool.h>
#include <lib/elsewhere.h>
#include <lib/misc.h>

#define FIXED_HIGHER_HALF_OFFSET_64 ((uint64_t)0xffffffff80000000)

#define ELF_PF_X 1
#define ELF_PF_W 2
#define ELF_PF_R 4

struct elf_range {
uint64_t base;
uint64_t length;
uint64_t permissions;
};

struct elf_section_hdr_info {
uint32_t section_entry_size;
uint32_t str_section_idx;
Expand All @@ -30,7 +25,7 @@ struct elf_section_hdr_info elf64_section_hdr_info(uint8_t *elf);
struct elf_section_hdr_info elf32_section_hdr_info(uint8_t *elf);

bool elf64_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit, uint64_t slide);
bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct elf_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *image_size, uint64_t *image_size_before_bss, bool *is_reloc);
bool elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t alloc_type, bool kaslr, struct mem_range **ranges, uint64_t *ranges_count, uint64_t *physical_base, uint64_t *virtual_base, uint64_t *image_size, uint64_t *image_size_before_bss, bool *is_reloc);

bool elf32_load_elsewhere(uint8_t *elf, uint64_t *entry_point,
struct elsewhere_range **ranges);
Expand Down
10 changes: 10 additions & 0 deletions common/lib/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,14 @@ noreturn void loongarch_spinup(uint64_t entry, uint64_t sp, uint64_t pgdl,

#define no_unwind __attribute__((section(".no_unwind")))

#define MEM_RANGE_X 1
#define MEM_RANGE_W 2
#define MEM_RANGE_R 4

struct mem_range {
uint64_t base;
uint64_t length;
uint64_t permissions;
};

#endif
Loading

0 comments on commit 153bde8

Please sign in to comment.