diff --git a/loader/src/elf_utils.cpp b/loader/src/elf_utils.cpp index 2f03c6e..0d00fc9 100644 --- a/loader/src/elf_utils.cpp +++ b/loader/src/elf_utils.cpp @@ -36,7 +36,6 @@ #include int Module_ElfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr, void *destination) { - DEBUG_FUNCTION_LINE("\n"); assert(destination != NULL); switch (shdr->sh_type) { @@ -77,17 +76,6 @@ int Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,size if (shdr->sh_type == SHT_SYMTAB) { size_t shstrndx; - if (elf_getshdrstrndx(elf, &shstrndx) == 0) { - char* name = elf_strptr(elf, shstrndx, shdr->sh_name); - if (name != NULL){ - DEBUG_FUNCTION_LINE("SHT_SYMTAB name: %s\n",name); - }else{ - DEBUG_FUNCTION_LINE("Name null\n"); - } - }else{ - DEBUG_FUNCTION_LINE("Couldn't find shstrndx\n"); - } - size_t sym; @@ -134,7 +122,6 @@ void Module_ElfLoadSymbols(size_t shndx, const void *destination, Elf32_Sym *sym } bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t shndx, void *destination,Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx,int allow_globals) { - DEBUG_FUNCTION_LINE("In Module_ElfLink\n"); Elf_Scn *scn; for (scn = elf_nextscn(elf, NULL); @@ -146,7 +133,6 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t shdr = elf32_getshdr(scn); if (shdr == NULL) continue; - DEBUG_FUNCTION_LINE("shdr->sh_type: %d\n",shdr->sh_type); switch (shdr->sh_type) { case SHT_REL: { const Elf32_Rel *rel; @@ -178,7 +164,6 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t } case SHN_COMMON: { return false; } case SHN_UNDEF: { - DEBUG_FUNCTION_LINE("SHN_UNDEF\n"); if (allow_globals) { module_unresolved_relocation_t *reloc; char *name; @@ -209,9 +194,6 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t *(int *)((char *)destination + rel[i].r_offset); - - DEBUG_FUNCTION_LINE("Relocate push_back!.\n"); - module_information->rel.push_back(reloc); continue; @@ -263,7 +245,6 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t } case SHN_COMMON: { return false; } case SHN_UNDEF: { - DEBUG_FUNCTION_LINE("SHN_UNDEF2\n"); if (allow_globals) { module_unresolved_relocation_t *reloc; char *name; @@ -293,8 +274,6 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t reloc->type = ELF32_R_TYPE(rela[i].r_info); reloc->addend = rela[i].r_addend; - DEBUG_FUNCTION_LINE("Relocate push_back!.\n"); - module_information->rel.push_back(reloc); continue; @@ -323,7 +302,6 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t } int Module_ElfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr) { - DEBUG_FUNCTION_LINE("Module_ElfLinkOne\n"); int value; char *target = (char *)destination + offset; int result = 0; diff --git a/loader/src/link_utils.cpp b/loader/src/link_utils.cpp new file mode 100644 index 0000000..50673c1 --- /dev/null +++ b/loader/src/link_utils.cpp @@ -0,0 +1,204 @@ +/* link_utils.cpp + * by Alex Chadwick + * + * Copyright (C) 2014, Alex Chadwick + * Modified 2018, Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "link_utils.h" +#include "elf_utils.h" +#include "utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool Module_LinkModule(module_information_t * module_information, uint8_t **space) { + if(module_information == NULL){ + DEBUG_FUNCTION_LINE("module_information is null\n"); + } + module_metadata_t * metadata = module_information->metadata; + const char * path = NULL; + if(metadata != NULL && metadata->path != NULL){ + path = metadata->path; + }else{ + DEBUG_FUNCTION_LINE("metadata is null\n"); + return false; + } + + int fd = -1; + Elf *elf = NULL; + bool result = false; + + /* check for compile errors */ + assert(elf_version(EV_CURRENT) != EV_NONE); + + fd = open(path, O_RDONLY, 0); + + if (fd == -1) + goto exit_error; + + elf = elf_begin(fd, ELF_C_READ, NULL); + + if (elf == NULL) + goto exit_error; + + switch (elf_kind(elf)) { + case ELF_K_AR: + /* TODO */ + goto exit_error; + case ELF_K_ELF: + if (!Module_LinkModuleElf(module_information, elf, space)) + goto exit_error; + break; + default: + goto exit_error; + } + + result = true; +exit_error: + if (!result) DEBUG_FUNCTION_LINE("Module_LinkModule: exit_error\n"); + if (elf != NULL) + elf_end(elf); + if (fd != -1) + close(fd); + return result; +} + +bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, uint8_t **space) { + Elf_Scn *scn; + size_t symtab_count, section_count, shstrndx, symtab_strndx, entries_count; + Elf32_Sym *symtab = NULL; + uint8_t **destinations = NULL; + wups_loader_entry_t *entries = NULL; + bool result = false; + + if (!Module_LoadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)) + goto exit_error; + + assert(symtab != NULL); + + if (elf_getshdrnum(elf, §ion_count) != 0) + goto exit_error; + if (elf_getshdrstrndx(elf, &shstrndx) != 0) + goto exit_error; + + destinations = (uint8_t **) malloc(sizeof(uint8_t *) * section_count); + + for (scn = elf_nextscn(elf, NULL); + scn != NULL; + scn = elf_nextscn(elf, scn)) { + + Elf32_Shdr *shdr; + + shdr = elf32_getshdr(scn); + if (shdr == NULL) + continue; + + if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && + (shdr->sh_flags & SHF_ALLOC)) { + + const char *name; + + destinations[elf_ndxscn(scn)] = NULL; + + name = elf_strptr(elf, shstrndx, shdr->sh_name); + if (name == NULL) + continue; + + if (strcmp(name, ".wups.meta") == 0) { + continue; + } else if (strcmp(name, ".wups.load") == 0) { + if (entries != NULL) + goto exit_error; + + entries_count = shdr->sh_size / sizeof(wups_loader_entry_t); + entries = (wups_loader_entry_t*) malloc(sizeof(wups_loader_entry_t)*entries_count); + + if (entries == NULL) + goto exit_error; + + destinations[elf_ndxscn(scn)] = (uint8_t *)entries; + if (!Module_ElfLoadSection(elf, scn, shdr, entries)) + goto exit_error; + Module_ElfLoadSymbols(elf_ndxscn(scn), entries, symtab, symtab_count); + for(int i = 0;ientries.push_back(curEntry); + } + + } else { + DEBUG_FUNCTION_LINE("Copy the function to %08X\n",*space); + *space -= shdr->sh_size; + if (shdr->sh_addralign > 3) + *space = (uint8_t *)((int)*space & + ~(shdr->sh_addralign - 1)); + else + *space = (uint8_t *)((int)*space & ~3); + + destinations[elf_ndxscn(scn)] = *space; + + assert(*space != NULL); + if (!Module_ElfLoadSection(elf, scn, shdr, *space)) + goto exit_error; + Module_ElfLoadSymbols(elf_ndxscn(scn), *space, symtab, symtab_count); + } + } + } + + if (entries == NULL) + goto exit_error; + + for (scn = elf_nextscn(elf, NULL); + scn != NULL; + scn = elf_nextscn(elf, scn)) { + + Elf32_Shdr *shdr; + + shdr = elf32_getshdr(scn); + if (shdr == NULL) + continue; + + if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && + (shdr->sh_flags & SHF_ALLOC) && + destinations[elf_ndxscn(scn)] != NULL) { + + if (!Module_ElfLink(module_information, elf, elf_ndxscn(scn), destinations[elf_ndxscn(scn)], + symtab, symtab_count, symtab_strndx, true)) + goto exit_error; + } + } + + result = true; +exit_error: + if (!result) DEBUG_FUNCTION_LINE("Module_LinkModuleElf: exit_error\n"); + if (destinations != NULL) + free(destinations); + if (symtab != NULL) + free(symtab); + return result; +} diff --git a/loader/src/link_utils.h b/loader/src/link_utils.h new file mode 100644 index 0000000..b3033c7 --- /dev/null +++ b/loader/src/link_utils.h @@ -0,0 +1,19 @@ +#ifndef _LINK_UTILS_H_ +#define _LINK_UTILS_H_ + +/* Main */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +} +#endif + +#include "module_parser.h" + +bool Module_LinkModule(module_information_t * module_information, uint8_t **space); +bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, uint8_t **space); +#endif diff --git a/loader/src/main.cpp b/loader/src/main.cpp index aa62251..b7eb818 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -20,6 +20,7 @@ #include "main.h" #include "utils.h" #include "module_parser.h" +#include "link_utils.h" /* Entry point */ extern "C" int Menu_Main(int argc, char **argv){ @@ -69,6 +70,8 @@ void loadAndProcessElf(const char * elfPath){ if(Module_CheckFile(elfPath)){ module_information_t * moduleInformation = Module_LoadModuleInformation(elfPath); if(moduleInformation != NULL){ + uint8_t * space = (uint8_t *)0x880000; + Module_LinkModule(moduleInformation,&space); printModuleInformation(moduleInformation); } } diff --git a/loader/src/module_parser.cpp b/loader/src/module_parser.cpp index 2eb999b..86164eb 100644 --- a/loader/src/module_parser.cpp +++ b/loader/src/module_parser.cpp @@ -35,6 +35,7 @@ #include #include #include +#include "utils.h" static module_information_t* Module_LoadMetaDataFromElf(const char *path, Elf *elf); static module_information_t* Module_ModuleInformationRead(const char *path, Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx); @@ -49,9 +50,32 @@ void printModuleInformation(module_information_t* module_information){ DEBUG_FUNCTION_LINE("relocations size: %d\n",relocations.size()); for (std::vector::iterator it = relocations.begin() ; it != relocations.end(); ++it){ module_unresolved_relocation_t * relo = *it; - DEBUG_FUNCTION_LINE("RELOCATION INFO %08X\n",relo); + DEBUG_FUNCTION_LINE("----\n",relo); + DEBUG_FUNCTION_LINE("name %s\n",relo->name); + DEBUG_FUNCTION_LINE("offset %d\n",relo->offset); + DEBUG_FUNCTION_LINE("type %d\n",relo->type); + DEBUG_FUNCTION_LINE("address %08X\n",relo->address); + DEBUG_FUNCTION_LINE("append %d\n",relo->addend); } + DEBUG_FUNCTION_LINE("entries size: %d\n",relocations.size()); + std::vector entries = module_information->entries; + for (std::vector::iterator it = entries.begin() ; it != entries.end(); ++it){ + //Added entry. + wups_loader_entry_t * curEntry = *it; + DEBUG_FUNCTION_LINE("Found entry @ %08X\n",curEntry); + dumpHex(curEntry,sizeof(wups_loader_entry_t)); + + DEBUG_FUNCTION_LINE("type %d\n",curEntry->type); + if( curEntry->type == WUPS_LOADER_ENTRY_FUNCTION || + curEntry->type == WUPS_LOADER_ENTRY_FUNCTION_MANDATORY){ + + DEBUG_FUNCTION_LINE("library %d \n",curEntry->data._function.library); + DEBUG_FUNCTION_LINE("function %s \n",curEntry->data._function.name); + DEBUG_FUNCTION_LINE("target pointer %08X \n",curEntry->data._function.target); + dumpHex(curEntry->data._function.target,0x100); + } + } if(metadata != NULL){ if(metadata->author != NULL){ @@ -69,8 +93,11 @@ void printModuleInformation(module_information_t* module_information){ }else{ DEBUG_FUNCTION_LINE("Name: is null\n"); } - DEBUG_FUNCTION_LINE("Path: %s \n",metadata->path); - DEBUG_FUNCTION_LINE("Size: %d \n",metadata->size); + if(metadata->path != NULL){ + DEBUG_FUNCTION_LINE("Path: %s.\n", metadata->path); + }else{ + DEBUG_FUNCTION_LINE("Path: is null\n"); + } DEBUG_FUNCTION_LINE("entries_count: %d \n",metadata->entries_count); }else{ DEBUG_FUNCTION_LINE("metadata is null\n"); diff --git a/loader/src/module_parser.h b/loader/src/module_parser.h index d34df4e..ce7bd5d 100644 --- a/loader/src/module_parser.h +++ b/loader/src/module_parser.h @@ -11,6 +11,7 @@ extern "C" { } #endif +#include #include #include @@ -35,6 +36,7 @@ typedef struct { typedef struct { std::vector rel; + std::vector entries; module_metadata_t * metadata; } module_information_t;