mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-02 16:59:03 +00:00
[makerom] Fixed ELF related code. Addresses #14
This commit is contained in:
+81
-163
@@ -5,32 +5,33 @@
|
||||
#include "exheader_read.h"
|
||||
#include "code.h"
|
||||
|
||||
const char *SDK_PLAINREGION_SEGMENT_NAME = ".module_id";
|
||||
const u32 CTR_PAGE_SIZE = 0x1000;
|
||||
const u32 DEFAULT_STACK_SIZE = 0x4000; // 10KB
|
||||
|
||||
typedef struct code_segment
|
||||
{
|
||||
u32 address;
|
||||
u32 memSize;
|
||||
u32 pageNum;
|
||||
|
||||
u32 size;
|
||||
u32 maxPageNum;
|
||||
u8 *data;
|
||||
} code_segment;
|
||||
|
||||
u32 GetPageSize(ncch_settings *set)
|
||||
u32 SizeToPage(u32 memorySize)
|
||||
{
|
||||
if (set->rsfSet->Option.PageSize)
|
||||
return strtoul(set->rsfSet->Option.PageSize, NULL, 10);
|
||||
return 0x1000;
|
||||
return align(memorySize, CTR_PAGE_SIZE) / CTR_PAGE_SIZE;
|
||||
}
|
||||
|
||||
u32 SizeToPage(u32 memorySize, elf_context *elf)
|
||||
u32 PageToSize(u32 pageNum)
|
||||
{
|
||||
return align(memorySize, elf->pageSize) / elf->pageSize;
|
||||
return pageNum * CTR_PAGE_SIZE;
|
||||
}
|
||||
|
||||
int ImportPlainRegionFromFile(ncch_settings *set)
|
||||
{
|
||||
set->sections.plainRegion.size = align(set->componentFilePtrs.plainregionSize, set->options.blockSize);
|
||||
set->sections.plainRegion.buffer = malloc(set->sections.plainRegion.size);
|
||||
set->sections.plainRegion.buffer = calloc(set->sections.plainRegion.size, 1);
|
||||
if (!set->sections.plainRegion.buffer) { fprintf(stderr, "[ELF ERROR] Not enough memory\n"); return MEM_ERROR; }
|
||||
ReadFile64(set->sections.plainRegion.buffer, set->componentFilePtrs.plainregionSize, 0, set->componentFilePtrs.plainregion);
|
||||
return 0;
|
||||
@@ -99,117 +100,61 @@ int ImportExeFsCodeBinaryFromFile(ncch_settings *set)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetBSSFromElf(elf_context *elf, ncch_settings *set)
|
||||
int ImportPlainRegionFromElf(elf_context *elf, ncch_settings *set)
|
||||
{
|
||||
set->codeDetails.bssSize = 0;
|
||||
elf_segment segment = elf_GetSegments(elf)[elf_SegmentNum(elf) - 1];
|
||||
|
||||
for (int i = 0; i < elf->sectionTableEntryCount; i++) {
|
||||
if (IsBss(&elf->sections[i]))
|
||||
set->codeDetails.bssSize = elf->sections[i].size;
|
||||
/* Check last segment
|
||||
If the last segment is RO segment, this must be an SDK .module_id segment */
|
||||
if (segment.flags != PF_RODATA) {
|
||||
/* not a RO segment */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ImportPlainRegionFromElf(elf_context *elf, ncch_settings *set) // Doesn't work same as N makerom
|
||||
{
|
||||
u64 size = 0;
|
||||
u64 offset = 0;
|
||||
for (u16 i = 0; i < elf->activeSegments; i++) {
|
||||
if (strcmp(elf->segments[i].name, SDK_PLAINREGION_SEGMENT_NAME) == 0) {
|
||||
size = elf->segments[i].header->sizeInFile;
|
||||
offset = elf->segments[i].header->offsetInFile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (size > 0) {
|
||||
if (segment.fileSize > 0) {
|
||||
/* Creating Output Buffer */
|
||||
set->sections.plainRegion.size = align(size, set->options.blockSize);
|
||||
set->sections.plainRegion.buffer = malloc(set->sections.plainRegion.size);
|
||||
if (!set->sections.plainRegion.buffer) { fprintf(stderr, "[ELF ERROR] Not enough memory\n"); return MEM_ERROR; }
|
||||
memset(set->sections.plainRegion.buffer, 0, set->sections.plainRegion.size);
|
||||
set->sections.plainRegion.size = align(segment.fileSize, set->options.blockSize);
|
||||
set->sections.plainRegion.buffer = calloc(set->sections.plainRegion.size, 1);
|
||||
if (!set->sections.plainRegion.buffer) { fprintf(stderr, "[CODE ERROR] Not enough memory\n"); return MEM_ERROR; }
|
||||
|
||||
/* Copy Plain Region */
|
||||
memcpy(set->sections.plainRegion.buffer, elf->file + offset, size);
|
||||
memcpy(set->sections.plainRegion.buffer, segment.ptr, segment.fileSize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u64 segment_flags)
|
||||
{
|
||||
memset(out, 0, sizeof(code_segment));
|
||||
u32 segmentNum = elf_SegmentNum(elf);
|
||||
const elf_segment *segments = elf_GetSegments(elf);
|
||||
|
||||
u16 seg_num = 0;
|
||||
elf_segment **seg = calloc(elf->activeSegments, sizeof(elf_segment*));
|
||||
|
||||
for (u16 i = 0; i < elf->activeSegments; i++) {
|
||||
// Skip SDK ELF plain region
|
||||
if (strcmp(elf->segments[i].name, SDK_PLAINREGION_SEGMENT_NAME) == 0)
|
||||
/* Find segment */
|
||||
for (u16 i = 0; i < segmentNum; i++) {
|
||||
/* Skip SDK ELF plain region
|
||||
The last segment should always be data in valid ELFs,
|
||||
unless this is an SDK ELF with .module_id segment */
|
||||
if (i == segmentNum-1 && segments[i].flags == PF_RODATA)
|
||||
continue;
|
||||
|
||||
//printf("SegName: %s (flags: %x)\n", elf->segments[i].name, elf->segments[i].header->flags);
|
||||
if ((elf->segments[i].header->flags & ~PF_CTRSDK) == segment_flags) {
|
||||
if (seg_num == 0) {
|
||||
seg[seg_num] = &elf->segments[i];
|
||||
seg_num++;
|
||||
}
|
||||
else if (elf->segments[i].vAddr == (u32)align(seg[seg_num - 1]->vAddr, seg[seg_num - 1]->header->alignment)) {
|
||||
seg[seg_num] = &elf->segments[i];
|
||||
seg_num++;
|
||||
}
|
||||
/* Found segment */
|
||||
if ((segments[i].flags & ~PF_CTRSDK) == segment_flags) {
|
||||
out->address = segments[i].vAddr;
|
||||
out->memSize = segments[i].memSize;
|
||||
out->pageNum = SizeToPage(out->memSize);
|
||||
out->size = segments[i].fileSize;
|
||||
out->data = malloc(out->size);
|
||||
if (!out->data) { fprintf(stderr, "[CODE ERROR] Not enough memory\n"); return MEM_ERROR; }
|
||||
memcpy(out->data, segments[i].ptr, out->size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return if there are no applicable segment */
|
||||
if (seg_num == 0)
|
||||
return 0;
|
||||
|
||||
/* Getting Segment Size/Settings */
|
||||
u32 vAddr = 0;
|
||||
u32 memorySize = 0;
|
||||
for (u16 i = 0; i < seg_num; i++) {
|
||||
if (i == 0) {
|
||||
vAddr = seg[i]->vAddr;
|
||||
}
|
||||
else { // Add rounded size from previous segment
|
||||
u32 padding = seg[i]->vAddr - (vAddr + memorySize);
|
||||
memorySize += padding;
|
||||
}
|
||||
|
||||
memorySize += seg[i]->header->sizeInMemory;
|
||||
|
||||
if (IsBss(&seg[i]->sections[seg[i]->sectionNum - 1]))
|
||||
memorySize -= seg[i]->sections[seg[i]->sectionNum - 1].size;
|
||||
}
|
||||
|
||||
// For Check
|
||||
#ifdef DEBUG
|
||||
printf("Address: 0x%x\n", vAddr);
|
||||
printf("Size: 0x%x\n", memorySize);
|
||||
#endif
|
||||
|
||||
out->address = vAddr;
|
||||
out->size = memorySize;
|
||||
out->maxPageNum = SizeToPage(memorySize, elf);
|
||||
out->data = malloc(memorySize);
|
||||
|
||||
/* Writing Segment to Buffer */
|
||||
for (int i = 0; i < seg_num; i++) {
|
||||
|
||||
for (int j = 0; j < seg[i]->sectionNum; j++) {
|
||||
elf_section_entry *section = &seg[i]->sections[j];
|
||||
if (!IsBss(section)) {
|
||||
u8 *pos = (out->data + (section->address - seg[i]->vAddr));
|
||||
memcpy(pos, section->ptr, section->size);
|
||||
//size += section->size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(seg);
|
||||
/* Stub struct data */
|
||||
out->address = 0;
|
||||
out->memSize = 0;
|
||||
out->pageNum = 0;
|
||||
out->size = 0;
|
||||
out->data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -217,37 +162,33 @@ int CreateExeFsCode(elf_context *elf, ncch_settings *set)
|
||||
{
|
||||
/* Getting Code Segments */
|
||||
code_segment text;
|
||||
memset(&text, 0, sizeof(code_segment));
|
||||
code_segment rodata;
|
||||
memset(&rodata, 0, sizeof(code_segment));
|
||||
code_segment rwdata;
|
||||
memset(&rwdata, 0, sizeof(code_segment));
|
||||
|
||||
int result = CreateCodeSegmentFromElf(&text, elf, PF_TEXT);
|
||||
if (result) return result;
|
||||
result = CreateCodeSegmentFromElf(&rodata, elf, PF_RODATA);
|
||||
if (result) return result;
|
||||
result = CreateCodeSegmentFromElf(&rwdata, elf, PF_DATA);
|
||||
if (result) return result;
|
||||
if (CreateCodeSegmentFromElf(&text, elf, PF_TEXT) == MEM_ERROR || CreateCodeSegmentFromElf(&rodata, elf, PF_RODATA) == MEM_ERROR || CreateCodeSegmentFromElf(&rwdata, elf, PF_DATA) == MEM_ERROR)
|
||||
return MEM_ERROR;
|
||||
|
||||
/* Checking the existence of essential ELF Segments */
|
||||
if (!text.size) return NOT_FIND_TEXT_SEGMENT;
|
||||
if (!rwdata.size) return NOT_FIND_DATA_SEGMENT;
|
||||
|
||||
/* Calculateing BSS size */
|
||||
set->codeDetails.bssSize = rwdata.memSize - rwdata.size;
|
||||
|
||||
/* Allocating Buffer for ExeFs Code */
|
||||
u32 size = (text.maxPageNum + rodata.maxPageNum + rwdata.maxPageNum)*elf->pageSize;
|
||||
u32 size = PageToSize(text.pageNum + rodata.pageNum + rwdata.pageNum);
|
||||
u8 *code = calloc(1, size);
|
||||
|
||||
/* Writing Code into Buffer */
|
||||
u8 *textPos = (code + 0);
|
||||
u8 *rodataPos = (code + text.maxPageNum*elf->pageSize);
|
||||
u8 *rwdataPos = (code + (text.maxPageNum + rodata.maxPageNum)*elf->pageSize);
|
||||
u8 *textPos = (code + text.address - text.address);
|
||||
u8 *rodataPos = (code + rodata.address - text.address);
|
||||
u8 *rwdataPos = (code + rwdata.address - text.address);
|
||||
if (text.size) memcpy(textPos, text.data, text.size);
|
||||
if (rodata.size) memcpy(rodataPos, rodata.data, rodata.size);
|
||||
if (rwdata.size) memcpy(rwdataPos, rwdata.data, rwdata.size);
|
||||
|
||||
|
||||
/* Compressing If needed */
|
||||
/* Compressing if needed */
|
||||
if (set->options.CompressCode) {
|
||||
if (set->options.verbose)
|
||||
printf("[CODE] Compressing code... ");
|
||||
@@ -265,31 +206,32 @@ int CreateExeFsCode(elf_context *elf, ncch_settings *set)
|
||||
|
||||
/* Setting code_segment data and freeing original buffers */
|
||||
set->codeDetails.textAddress = text.address;
|
||||
set->codeDetails.textMaxPages = text.maxPageNum;
|
||||
set->codeDetails.textSize = text.size;
|
||||
set->codeDetails.textMaxPages = text.pageNum;
|
||||
set->codeDetails.textSize = text.memSize;
|
||||
if (text.size) free(text.data);
|
||||
|
||||
set->codeDetails.roAddress = rodata.address;
|
||||
set->codeDetails.roMaxPages = rodata.maxPageNum;
|
||||
set->codeDetails.roSize = rodata.size;
|
||||
set->codeDetails.roMaxPages = rodata.pageNum;
|
||||
set->codeDetails.roSize = rodata.memSize;
|
||||
if (rodata.size) free(rodata.data);
|
||||
|
||||
set->codeDetails.rwAddress = rwdata.address;
|
||||
set->codeDetails.rwMaxPages = rwdata.maxPageNum;
|
||||
set->codeDetails.rwSize = rwdata.size;
|
||||
set->codeDetails.rwMaxPages = rwdata.pageNum;
|
||||
set->codeDetails.rwSize = rwdata.memSize;
|
||||
if (rwdata.size) free(rwdata.data);
|
||||
|
||||
if (set->rsfSet->SystemControlInfo.StackSize)
|
||||
set->codeDetails.stackSize = strtoul(set->rsfSet->SystemControlInfo.StackSize, NULL, 0);
|
||||
else {
|
||||
fprintf(stderr, "[CODE ERROR] RSF Parameter Not Found: \"SystemControlInfo/StackSize\"\n");
|
||||
return 1;
|
||||
set->codeDetails.stackSize = DEFAULT_STACK_SIZE;
|
||||
fprintf(stderr, "[CODE WARNING] \"SystemControlInfo/StackSize\" not specified, defaulting to 0x%x bytes\n", DEFAULT_STACK_SIZE);
|
||||
}
|
||||
|
||||
/* Return */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void PrintElfContext(elf_context *elf)
|
||||
{
|
||||
printf("[ELF] Program Table Data\n");
|
||||
@@ -303,27 +245,17 @@ void PrintElfContext(elf_context *elf)
|
||||
printf(" Label index: 0x%x\n", elf->sectionHeaderNameEntryIndex);
|
||||
for (int i = 0; i < elf->activeSegments; i++) {
|
||||
printf(" Segment [%d][%s]\n", i, elf->segments[i].name);
|
||||
printf(" > Size : 0x%x\n", elf->segments[i].header->sizeInFile);
|
||||
printf(" > Address : 0x%x\n", elf->segments[i].vAddr);
|
||||
printf(" > Flags: 0x%x\n", elf->segments[i].header->flags);
|
||||
printf(" > Type: 0x%x\n", elf->segments[i].header->type);
|
||||
printf(" > Sections : %d\n", elf->segments[i].sectionNum);
|
||||
printf(" > Size(Memory): 0x%x\n", elf->segments[i].header->sizeInMemory);
|
||||
printf(" > Size(File): 0x%x\n", elf->segments[i].header->sizeInFile);
|
||||
printf(" > Address: 0x%x\n", elf->segments[i].vAddr);
|
||||
printf(" > Flags: 0x%x\n", elf->segments[i].header->flags);
|
||||
printf(" > Type: 0x%x\n", elf->segments[i].header->type);
|
||||
printf(" > Sections: %d\n", elf->segments[i].sectionNum);
|
||||
for (int j = 0; j < elf->segments[i].sectionNum; j++)
|
||||
printf(" > Section [%d][%s][0x%x][0x%x]\n", j, elf->segments[i].sections[j].name, elf->segments[i].sections[j].flags, elf->segments[i].sections[j].type);
|
||||
|
||||
/*
|
||||
char outpath[100];
|
||||
memset(&outpath,0,100);
|
||||
sprintf(outpath,"%s.bin",elf->sections[i].name);
|
||||
chdir("elfsections");
|
||||
FILE *tmp = fopen(outpath,"wb");
|
||||
WriteBuffer(elf->sections[i].ptr,elf->sections[i].size,0,tmp);
|
||||
fclose(tmp);
|
||||
chdir("..");
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
int BuildExeFsCode(ncch_settings *set)
|
||||
{
|
||||
@@ -331,10 +263,11 @@ int BuildExeFsCode(ncch_settings *set)
|
||||
if (set->options.IsCfa)
|
||||
return result;
|
||||
|
||||
if (set->componentFilePtrs.plainregion) // Import PlainRegion from file
|
||||
if ((result = ImportPlainRegionFromFile(set))) return result;
|
||||
if (!set->options.IsBuildingCodeSection) // Import ExeFs Code from file and return
|
||||
if (!set->options.IsBuildingCodeSection) { // Import ExeFs Code from file and return
|
||||
if (set->componentFilePtrs.plainregion) // Import PlainRegion from file
|
||||
if ((result = ImportPlainRegionFromFile(set))) return result;
|
||||
return ImportExeFsCodeBinaryFromFile(set);
|
||||
}
|
||||
|
||||
/* Import ELF */
|
||||
u8 *elfFile = malloc(set->componentFilePtrs.elfSize);
|
||||
@@ -345,26 +278,12 @@ int BuildExeFsCode(ncch_settings *set)
|
||||
ReadFile64(elfFile, set->componentFilePtrs.elfSize, 0, set->componentFilePtrs.elf);
|
||||
|
||||
/* Create ELF Context */
|
||||
elf_context *elf = calloc(1, sizeof(elf_context));
|
||||
if (!elf) {
|
||||
fprintf(stderr, "[CODE ERROR] Not enough memory\n");
|
||||
free(elfFile);
|
||||
return MEM_ERROR;
|
||||
}
|
||||
elf_context elf;
|
||||
|
||||
if ((result = GetElfContext(elf, elfFile))) goto finish;
|
||||
if ((result = elf_Init(&elf, elfFile))) goto finish;
|
||||
|
||||
/* Setting Page Size */
|
||||
elf->pageSize = GetPageSize(set);
|
||||
|
||||
if (!set->componentFilePtrs.plainregion)
|
||||
if ((result = ImportPlainRegionFromElf(elf, set))) goto finish;
|
||||
|
||||
if (set->options.verbose)
|
||||
PrintElfContext(elf);
|
||||
|
||||
if ((result = CreateExeFsCode(elf, set))) goto finish;
|
||||
if ((result = GetBSSFromElf(elf, set))) goto finish;
|
||||
if ((result = ImportPlainRegionFromElf(&elf, set))) goto finish;
|
||||
if ((result = CreateExeFsCode(&elf, set))) goto finish;
|
||||
|
||||
finish:
|
||||
switch (result) {
|
||||
@@ -389,8 +308,7 @@ finish:
|
||||
fprintf(stderr, "[CODE ERROR] Failed to process ELF file (%d)\n", result);
|
||||
}
|
||||
|
||||
FreeElfContext(elf);
|
||||
elf_Free(&elf);
|
||||
free(elfFile);
|
||||
free(elf);
|
||||
return result;
|
||||
}
|
||||
|
||||
+65
-185
@@ -82,43 +82,12 @@ typedef struct elf_phdr
|
||||
} elf_phdr;
|
||||
|
||||
// ELF Functions
|
||||
int GetElfSectionEntries(elf_context *elf);
|
||||
int GetElfProgramEntries(elf_context *elf);
|
||||
void PrintElfContext(elf_context *elf);
|
||||
int ReadElfHdr(elf_context *elf);
|
||||
|
||||
int CreateElfSegments(elf_context *elf);
|
||||
bool IsIgnoreSection(elf_section_entry info);
|
||||
|
||||
// ELF Functions
|
||||
|
||||
int GetElfContext(elf_context *elf, const u8 *elfFile)
|
||||
{
|
||||
elf->file = elfFile;
|
||||
|
||||
int result;
|
||||
|
||||
if((result = ReadElfHdr(elf))) return result;
|
||||
if((result = GetElfSectionEntries(elf))) return result;
|
||||
if((result = GetElfProgramEntries(elf))) return result;
|
||||
if((result = CreateElfSegments(elf))) return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FreeElfContext(elf_context *elf)
|
||||
{
|
||||
for (int i = 0; i < elf->activeSegments; i++)
|
||||
free(elf->segments[i].sections);
|
||||
free(elf->sections);
|
||||
free(elf->programHeaders);
|
||||
free(elf->segments);
|
||||
}
|
||||
|
||||
int ReadElfHdr(elf_context *elf)
|
||||
int elf_ProcessHeader(elf_context *elf)
|
||||
{
|
||||
const elf_hdr *hdr = (const elf_hdr*)elf->file;
|
||||
|
||||
/* Check conditions for valid CTR ELF */
|
||||
if (u8_to_u32(hdr->magic, BE) != ELF_MAGIC)
|
||||
return NOT_ELF_FILE;
|
||||
if (hdr->bitFormat != elf_32_bit)
|
||||
@@ -130,185 +99,96 @@ int ReadElfHdr(elf_context *elf)
|
||||
if (u8_to_u16(hdr->type, LE) != elf_executeable)
|
||||
return NON_EXECUTABLE_ELF;
|
||||
|
||||
elf->programTableOffset = u8_to_u32(hdr->programHeaderTableOffset, LE);
|
||||
elf->programTableEntrySize = u8_to_u16(hdr->programHeaderEntrySize, LE);
|
||||
elf->programTableEntryCount = u8_to_u16(hdr->programHeaderEntryCount, LE);
|
||||
elf->phdrOffset = u8_to_u32(hdr->programHeaderTableOffset, LE);
|
||||
elf->segmentNum = u8_to_u16(hdr->programHeaderEntryCount, LE);
|
||||
elf->segments = calloc(elf->segmentNum, sizeof(elf_segment));
|
||||
if (!elf->segments) {
|
||||
fprintf(stderr, "[ELF ERROR] Not enough memory\n");
|
||||
return MEM_ERROR;
|
||||
}
|
||||
|
||||
elf->sectionTableOffset = u8_to_u32(hdr->sectionHeaderTableOffset, LE);
|
||||
elf->sectionTableEntrySize = u8_to_u16(hdr->sectionTableEntrySize, LE);
|
||||
elf->sectionTableEntryCount = u8_to_u16(hdr->sectionHeaderEntryCount, LE);
|
||||
|
||||
elf->sectionHeaderNameEntryIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex, LE);
|
||||
elf->shdrOffset = u8_to_u32(hdr->sectionHeaderTableOffset, LE);
|
||||
elf->shdrNameIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex, LE);
|
||||
elf->sectionNum = u8_to_u16(hdr->sectionHeaderEntryCount, LE);
|
||||
elf->sections = calloc(elf->sectionNum, sizeof(elf_section));
|
||||
if (!elf->sections) {
|
||||
fprintf(stderr, "[ELF ERROR] Not enough memory\n");
|
||||
return MEM_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetElfSectionEntries(elf_context *elf)
|
||||
void elf_PopulateSections(elf_context *elf)
|
||||
{
|
||||
elf->sections = calloc(elf->sectionTableEntryCount,sizeof(elf_section_entry));
|
||||
if(!elf->sections) {
|
||||
fprintf(stderr,"[ELF ERROR] Not enough memory\n");
|
||||
return MEM_ERROR;
|
||||
}
|
||||
const elf_shdr *shdr = (const elf_shdr *)(elf->file + elf->shdrOffset);
|
||||
const char *nameTable = (const char*)(elf->file + u8_to_u32(shdr[elf->shdrNameIndex].offset, LE));
|
||||
|
||||
const elf_shdr *shdr = (const elf_shdr *)(elf->file + elf->sectionTableOffset);
|
||||
const char *nameTable = (const char*)(elf->file + u8_to_u32(shdr[elf->sectionHeaderNameEntryIndex].offset, LE));
|
||||
|
||||
for(int i = 0; i < elf->sectionTableEntryCount; i++){
|
||||
for (int i = 0; i < elf->sectionNum; i++) {
|
||||
elf->sections[i].name = nameTable + u8_to_u32(shdr[i].name, LE);
|
||||
elf->sections[i].type = u8_to_u32(shdr[i].type, LE);
|
||||
elf->sections[i].flags = u8_to_u32(shdr[i].flags, LE);
|
||||
elf->sections[i].offsetInFile = u8_to_u32(shdr[i].offset, LE);
|
||||
elf->sections[i].fileOffset = u8_to_u32(shdr[i].offset, LE);
|
||||
elf->sections[i].size = u8_to_u32(shdr[i].size, LE);
|
||||
elf->sections[i].ptr = elf->file + elf->sections[i].offsetInFile;
|
||||
elf->sections[i].address = u8_to_u32(shdr[i].addr, LE);
|
||||
elf->sections[i].ptr = elf->file + elf->sections[i].fileOffset;
|
||||
elf->sections[i].vAddr = u8_to_u32(shdr[i].addr, LE);
|
||||
elf->sections[i].alignment = u8_to_u32(shdr[i].addralign, LE);
|
||||
}
|
||||
}
|
||||
|
||||
void elf_PopulateSegments(elf_context *elf)
|
||||
{
|
||||
const elf_phdr *phdr = (const elf_phdr *)(elf->file + elf->phdrOffset);
|
||||
|
||||
for (int i = 0; i < elf->segmentNum; i++) {
|
||||
elf->segments[i].type = u8_to_u32(phdr[i].type, LE);
|
||||
elf->segments[i].flags = u8_to_u32(phdr[i].flags, LE);
|
||||
elf->segments[i].fileOffset = u8_to_u32(phdr[i].offset, LE);
|
||||
elf->segments[i].fileSize = u8_to_u32(phdr[i].filesz, LE);
|
||||
elf->segments[i].ptr = elf->file + elf->segments[i].fileOffset;
|
||||
elf->segments[i].pAddr = u8_to_u32(phdr[i].paddr, LE);
|
||||
elf->segments[i].vAddr = u8_to_u32(phdr[i].vaddr, LE);
|
||||
elf->segments[i].memSize = u8_to_u32(phdr[i].memsz, LE);
|
||||
elf->segments[i].alignment = u8_to_u32(phdr[i].align, LE);
|
||||
}
|
||||
}
|
||||
|
||||
int elf_Init(elf_context *elf, const u8 *elfFile)
|
||||
{
|
||||
elf->file = elfFile;
|
||||
|
||||
int result;
|
||||
|
||||
if((result = elf_ProcessHeader(elf))) return result;
|
||||
|
||||
elf_PopulateSections(elf);
|
||||
elf_PopulateSegments(elf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetElfProgramEntries(elf_context *elf)
|
||||
void elf_Free(elf_context *elf)
|
||||
{
|
||||
elf->programHeaders = calloc(elf->programTableEntryCount,sizeof(elf_program_entry));
|
||||
if(!elf->programHeaders) {
|
||||
fprintf(stderr,"[ELF ERROR] Not enough memory\n");
|
||||
return MEM_ERROR;
|
||||
}
|
||||
|
||||
const elf_phdr *phdr = (const elf_phdr*)(elf->file + elf->programTableOffset);
|
||||
|
||||
for(int i = 0; i < elf->programTableEntryCount; i++){
|
||||
elf->programHeaders[i].type = u8_to_u32(phdr[i].type, LE);
|
||||
elf->programHeaders[i].flags = u8_to_u32(phdr[i].flags, LE);
|
||||
elf->programHeaders[i].offsetInFile = u8_to_u32(phdr[i].offset, LE);
|
||||
elf->programHeaders[i].sizeInFile = u8_to_u32(phdr[i].filesz, LE);
|
||||
elf->programHeaders[i].ptr = elf->file + elf->programHeaders[i].offsetInFile;
|
||||
elf->programHeaders[i].physicalAddress = u8_to_u32(phdr[i].paddr, LE);
|
||||
elf->programHeaders[i].virtualAddress = u8_to_u32(phdr[i].vaddr, LE);
|
||||
elf->programHeaders[i].sizeInMemory = u8_to_u32(phdr[i].memsz, LE);
|
||||
elf->programHeaders[i].alignment = u8_to_u32(phdr[i].align, LE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
free(elf->sections);
|
||||
free(elf->segments);
|
||||
memset(elf, 0, sizeof(elf_context));
|
||||
}
|
||||
|
||||
/* Section Hdr Functions */
|
||||
|
||||
bool IsBss(elf_section_entry *section)
|
||||
u16 elf_SectionNum(elf_context *ctx)
|
||||
{
|
||||
return (section->type == SHT_NOBITS && section->flags == (SHF_WRITE | SHF_ALLOC));
|
||||
return ctx->sectionNum;
|
||||
}
|
||||
|
||||
bool IsData(elf_section_entry *section)
|
||||
const elf_section* elf_GetSections(elf_context *ctx)
|
||||
{
|
||||
return (section->type == SHT_PROGBITS && section->flags == (SHF_WRITE | SHF_ALLOC));
|
||||
return ctx->sections;
|
||||
}
|
||||
|
||||
bool IsRoData(elf_section_entry *section)
|
||||
u16 elf_SegmentNum(elf_context *ctx)
|
||||
{
|
||||
return (section->type == SHT_PROGBITS && section->flags == SHF_ALLOC);
|
||||
return ctx->segmentNum;
|
||||
}
|
||||
|
||||
bool IsText(elf_section_entry *section)
|
||||
const elf_segment* elf_GetSegments(elf_context *ctx)
|
||||
{
|
||||
return (section->type == SHT_PROGBITS && section->flags == (SHF_ALLOC | SHF_EXECINSTR));
|
||||
return ctx->segments;
|
||||
}
|
||||
|
||||
/* Program Segment Functions */
|
||||
void InitSegment(elf_segment *segment)
|
||||
{
|
||||
memset(segment, 0, sizeof(elf_segment));
|
||||
|
||||
segment->sectionNumMax = 10;
|
||||
segment->sectionNum = 0;
|
||||
segment->sections = calloc(segment->sectionNumMax, sizeof(elf_section_entry));
|
||||
}
|
||||
|
||||
void AddSegmentSection(elf_segment *segment, elf_section_entry *section)
|
||||
{
|
||||
if (segment->sectionNum < segment->sectionNumMax)
|
||||
memcpy(&segment->sections[segment->sectionNum], section, sizeof(elf_section_entry));
|
||||
else {
|
||||
segment->sectionNumMax *= 2;
|
||||
elf_section_entry *tmp = calloc(segment->sectionNumMax, sizeof(elf_section_entry));
|
||||
for (int k = 0; k < segment->sectionNum; k++)
|
||||
memcpy(&tmp[k], &segment->sections[k], sizeof(elf_section_entry));
|
||||
free(segment->sections);
|
||||
segment->sections = tmp;
|
||||
memcpy(&segment->sections[segment->sectionNum], section, sizeof(elf_section_entry));
|
||||
}
|
||||
|
||||
segment->sectionNum++;
|
||||
}
|
||||
|
||||
bool IsIgnoreSection(elf_section_entry info)
|
||||
{
|
||||
return !(info.flags & SHF_ALLOC);//(info.type != SHT_PROGBITS && info.type != SHT_NOBITS && info.type != SHT_INIT_ARRAY && info.type != SHT_FINI_ARRAY && info.type != SHT_ARM_EXIDX);
|
||||
}
|
||||
|
||||
int CreateElfSegments(elf_context *elf)
|
||||
{
|
||||
// Interate through Each Program Header
|
||||
elf->activeSegments = 0;
|
||||
elf->segments = calloc(elf->programTableEntryCount,sizeof(elf_segment));
|
||||
|
||||
elf_segment segment;
|
||||
|
||||
bool foundFirstSection = false;
|
||||
int curr, prev;
|
||||
u32 padding, size, sizeInMemory;
|
||||
|
||||
for (int i = 0; i < elf->programTableEntryCount; i++){
|
||||
if (elf->programHeaders[i].sizeInMemory != 0 && elf->programHeaders[i].type == PF_X){
|
||||
InitSegment(&segment);
|
||||
|
||||
foundFirstSection = false;
|
||||
size = 0;
|
||||
sizeInMemory = elf->programHeaders[i].sizeInMemory;
|
||||
|
||||
// Itterate Through Section Headers
|
||||
for (curr = 0; curr < elf->sectionTableEntryCount && size != sizeInMemory; curr++){
|
||||
// Skip irrelevant sections
|
||||
if (IsIgnoreSection(elf->sections[curr]))
|
||||
continue;
|
||||
|
||||
|
||||
if (!foundFirstSection) {
|
||||
if (elf->sections[curr].address != elf->programHeaders[i].virtualAddress)
|
||||
continue;
|
||||
|
||||
foundFirstSection = true;
|
||||
segment.vAddr = elf->sections[curr].address;
|
||||
segment.name = elf->sections[curr].name;
|
||||
|
||||
AddSegmentSection(&segment, &elf->sections[curr]);
|
||||
size = elf->sections[curr].size;
|
||||
}
|
||||
else {
|
||||
AddSegmentSection(&segment, &elf->sections[curr]);
|
||||
padding = elf->sections[curr].address - (elf->sections[prev].address + elf->sections[prev].size);
|
||||
size += padding + elf->sections[curr].size;
|
||||
}
|
||||
prev = curr;
|
||||
|
||||
// Catch section parsing fails
|
||||
if (size > sizeInMemory){
|
||||
fprintf(stderr,"[ELF ERROR] Too large section size.\n Segment size = 0x%x\n Section Size = 0x%x\n", sizeInMemory, size);
|
||||
return ELF_SEGMENT_SECTION_SIZE_MISMATCH;
|
||||
}
|
||||
}
|
||||
if(segment.sectionNum){
|
||||
segment.header = &elf->programHeaders[i];
|
||||
memcpy(&elf->segments[elf->activeSegments],&segment,sizeof(elf_segment));
|
||||
elf->activeSegments++;
|
||||
}
|
||||
else{
|
||||
free(segment.sections);
|
||||
fprintf(stderr,"[ELF ERROR] Program Header Has no corresponding Sections, ELF Cannot be proccessed\n");
|
||||
return ELF_SEGMENTS_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+24
-41
@@ -56,17 +56,17 @@ typedef enum elf_section_flag
|
||||
SHF_TLS = 0x400
|
||||
} elf_section_flag;
|
||||
|
||||
typedef struct elf_section_entry
|
||||
typedef struct elf_section
|
||||
{
|
||||
const char *name;
|
||||
u32 type;
|
||||
u32 flags;
|
||||
const u8 *ptr;
|
||||
u32 offsetInFile;
|
||||
u32 fileOffset;
|
||||
u32 size;
|
||||
u32 address;
|
||||
u32 vAddr;
|
||||
u32 alignment;
|
||||
} elf_section_entry;
|
||||
} elf_section;
|
||||
|
||||
typedef enum elf_program_type
|
||||
{
|
||||
@@ -91,57 +91,40 @@ typedef enum elf_program_flag
|
||||
PF_RODATA = PF_R
|
||||
} elf_program_flag;
|
||||
|
||||
typedef struct elf_program_entry
|
||||
typedef struct elf_segment
|
||||
{
|
||||
u32 type;
|
||||
u32 flags;
|
||||
const u8 *ptr;
|
||||
u32 offsetInFile;
|
||||
u32 sizeInFile;
|
||||
u32 virtualAddress;
|
||||
u32 physicalAddress;
|
||||
u32 sizeInMemory;
|
||||
u32 alignment;
|
||||
} elf_program_entry;
|
||||
|
||||
typedef struct elf_segment
|
||||
{
|
||||
const char *name;
|
||||
u32 fileOffset;
|
||||
u32 fileSize;
|
||||
u32 memSize;
|
||||
u32 vAddr;
|
||||
|
||||
elf_program_entry *header;
|
||||
u32 sectionNum;
|
||||
u32 sectionNumMax;
|
||||
elf_section_entry *sections;
|
||||
u32 pAddr;
|
||||
u32 alignment;
|
||||
} elf_segment;
|
||||
|
||||
typedef struct elf_context
|
||||
{
|
||||
const u8 *file;
|
||||
|
||||
u32 pageSize;
|
||||
|
||||
u32 programTableOffset;
|
||||
u16 programTableEntrySize;
|
||||
u16 programTableEntryCount;
|
||||
|
||||
u32 sectionTableOffset;
|
||||
u16 sectionTableEntrySize;
|
||||
u16 sectionTableEntryCount;
|
||||
|
||||
u16 sectionHeaderNameEntryIndex;
|
||||
u32 shdrOffset;
|
||||
u16 shdrNameIndex;
|
||||
u32 phdrOffset;
|
||||
|
||||
elf_section_entry *sections;
|
||||
elf_program_entry *programHeaders;
|
||||
u16 sectionNum;
|
||||
elf_section *sections;
|
||||
|
||||
u16 activeSegments;
|
||||
u16 segmentNum;
|
||||
elf_segment *segments;
|
||||
} elf_context;
|
||||
|
||||
bool IsBss(elf_section_entry *section);
|
||||
bool IsData(elf_section_entry *section);
|
||||
bool IsRoData(elf_section_entry *section);
|
||||
bool IsText(elf_section_entry *section);
|
||||
|
||||
int GetElfContext(elf_context *elf, const u8 *elfFile);
|
||||
void FreeElfContext(elf_context *elf);
|
||||
int elf_Init(elf_context *ctx, const u8 *fp);
|
||||
void elf_Free(elf_context *ctx);
|
||||
|
||||
u16 elf_SectionNum(elf_context *ctx);
|
||||
const elf_section* elf_GetSections(elf_context *ctx);
|
||||
|
||||
u16 elf_SegmentNum(elf_context *ctx);
|
||||
const elf_segment* elf_GetSegments(elf_context *ctx);
|
||||
@@ -64,7 +64,6 @@ void GET_Option(ctr_yaml_context *ctx, rsf_settings *rsf)
|
||||
else if(cmpYamlValue("EnableCompress",ctx)) SetBoolYAMLValue(&rsf->Option.EnableCompress,"EnableCompress",ctx);
|
||||
else if(cmpYamlValue("FreeProductCode",ctx)) SetBoolYAMLValue(&rsf->Option.FreeProductCode,"FreeProductCode",ctx);
|
||||
else if(cmpYamlValue("UseOnSD",ctx)) SetBoolYAMLValue(&rsf->Option.UseOnSD,"UseOnSD",ctx);
|
||||
else if(cmpYamlValue("PageSize",ctx)) SetSimpleYAMLValue(&rsf->Option.PageSize,"PageSize",ctx,0);
|
||||
else{
|
||||
fprintf(stderr,"[RSF ERROR] Unrecognised key '%s'\n",GetYamlString(ctx));
|
||||
ctx->error = YAML_UNKNOWN_KEY;
|
||||
@@ -343,9 +342,6 @@ void GET_CommonHeaderKey(ctr_yaml_context *ctx, rsf_settings *rsf)
|
||||
|
||||
void free_RsfSettings(rsf_settings *set)
|
||||
{
|
||||
//Option
|
||||
free(set->Option.PageSize);
|
||||
|
||||
//AccessControlInfo
|
||||
free(set->AccessControlInfo.IdealProcessor);
|
||||
free(set->AccessControlInfo.Priority);
|
||||
|
||||
@@ -70,9 +70,6 @@ typedef struct
|
||||
bool EnableCompress;
|
||||
bool FreeProductCode;
|
||||
bool UseOnSD;
|
||||
|
||||
// Strings
|
||||
char *PageSize;
|
||||
} Option;
|
||||
|
||||
struct{
|
||||
|
||||
Reference in New Issue
Block a user