WUMSLoader/source/ElfUtils.cpp

63 lines
2.1 KiB
C++
Raw Normal View History

#include <stdint.h>
#include "../wumsloader/src/elfio/elf_types.hpp"
2022-02-04 21:44:03 +01:00
#include "utils/logger.h"
2020-04-28 14:43:07 +02:00
#include <coreinit/cache.h>
2020-05-17 19:05:51 +02:00
uint32_t load_loader_elf(unsigned char *baseAddress, char *elf_data, uint32_t fileSize) {
2020-04-28 14:43:07 +02:00
ELFIO::Elf32_Ehdr *ehdr;
ELFIO::Elf32_Phdr *phdrs;
uint8_t *image;
int32_t i;
ehdr = (ELFIO::Elf32_Ehdr *) elf_data;
2020-05-17 19:05:51 +02:00
if (ehdr->e_phoff == 0 || ehdr->e_phnum == 0) {
2020-04-28 14:43:07 +02:00
return 0;
}
2020-05-17 19:05:51 +02:00
if (ehdr->e_phentsize != sizeof(ELFIO::Elf32_Phdr)) {
2020-04-28 14:43:07 +02:00
return 0;
}
2020-05-17 19:05:51 +02:00
phdrs = (ELFIO::Elf32_Phdr *) (elf_data + ehdr->e_phoff);
2020-04-28 14:43:07 +02:00
2020-05-17 19:05:51 +02:00
for (i = 0; i < ehdr->e_phnum; i++) {
if (phdrs[i].p_type != ELFIO::PT_LOAD) {
2020-04-28 14:43:07 +02:00
continue;
}
2020-05-17 19:05:51 +02:00
if (phdrs[i].p_filesz > phdrs[i].p_memsz) {
2020-04-28 14:43:07 +02:00
continue;
}
2020-05-17 19:05:51 +02:00
if (!phdrs[i].p_filesz) {
2020-04-28 14:43:07 +02:00
continue;
}
2020-05-17 19:05:51 +02:00
uint32_t p_paddr = phdrs[i].p_paddr + (uint32_t) baseAddress;
2022-02-04 21:44:03 +01:00
image = (uint8_t *) (elf_data + phdrs[i].p_offset);
2020-04-28 14:43:07 +02:00
2020-05-17 19:05:51 +02:00
memcpy((void *) p_paddr, image, phdrs[i].p_filesz);
DCFlushRange((void *) p_paddr, phdrs[i].p_filesz);
2020-04-28 14:43:07 +02:00
if (phdrs[i].p_flags & ELFIO::PF_X) {
2020-05-17 19:05:51 +02:00
ICInvalidateRange((void *) p_paddr, phdrs[i].p_memsz);
2020-04-28 14:43:07 +02:00
}
}
//! clear BSS
2021-09-18 11:55:01 +02:00
auto *shdr = (ELFIO::Elf32_Shdr *) (elf_data + ehdr->e_shoff);
2020-05-17 19:05:51 +02:00
for (i = 0; i < ehdr->e_shnum; i++) {
const char *section_name = ((const char *) elf_data) + shdr[ehdr->e_shstrndx].sh_offset + shdr[i].sh_name;
if (section_name[0] == '.' && section_name[1] == 'b' && section_name[2] == 's' && section_name[3] == 's') {
memset((void *) (shdr[i].sh_addr + baseAddress), 0, shdr[i].sh_size);
DCFlushRange((void *) (shdr[i].sh_addr + baseAddress), shdr[i].sh_size);
} else if (section_name[0] == '.' && section_name[1] == 's' && section_name[2] == 'b' && section_name[3] == 's' && section_name[4] == 's') {
memset((void *) (shdr[i].sh_addr + baseAddress), 0, shdr[i].sh_size);
DCFlushRange((void *) (shdr[i].sh_addr + baseAddress), shdr[i].sh_size);
2020-04-28 14:43:07 +02:00
}
}
return ehdr->e_entry;
}