Files
Project_CTR/makerom/elf.c
T
2014-08-27 00:25:01 +10:00

977 lines
31 KiB
C

#include "lib.h"
#include "ncch_build.h"
#include "elf_hdr.h"
#include "elf.h"
#include "blz.h"
int ImportPlainRegionFromFile(ncch_settings *set);
int ImportExeFsCodeBinaryFromFile(ncch_settings *set);
u32 GetPageSize(ncch_settings *set);
u32 SizeToPage(u32 memorySize, elf_context *elf);
int GetBSSFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set);
int ImportPlainRegionFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set);
int CreateExeFsCode(elf_context *elf, u8 *elfFile, ncch_settings *set);
int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u8 *elfFile, char **names, u32 nameNum);
elf_segment** GetContinuousSegments(u16 *ContinuousSegmentNum, elf_context *elf, char **names, u32 nameNum);
elf_segment** GetSegments(u16 *SegmentNum, elf_context *elf, char **names, u32 nameNum);
// ELF Functions
int GetElfContext(elf_context *elf, u8 *elfFile);
int GetElfSectionEntries(elf_context *elf, u8 *elfFile);
int GetElfProgramEntries(elf_context *elf, u8 *elfFile);
void PrintElfContext(elf_context *elf, u8 *elfFile);
int ReadElfHdr(elf_context *elf, u8 *elfFile);
int CreateElfSegments(elf_context *elf, u8 *elfFile);
bool IsIgnoreSection(elf_section_entry info);
/* ELF Section Entry Functions */
u8* GetELFSectionHeader(u16 index, elf_context *elf, u8 *elfFile);
u8* GetELFSectionEntry(u16 index, elf_context *elf, u8 *elfFile);
char* GetELFSectionEntryName(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFSectionEntryType(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFSectionEntryFlags(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFSectionEntryAddress(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFSectionEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFSectionEntrySize(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFSectionEntryAlignment(u16 index, elf_context *elf, u8 *elfFile);
u16 GetElfSectionIndexFromName(char *name, elf_context *elf, u8 *elfFile);
bool IsBss(elf_section_entry *section);
bool IsData(elf_section_entry *section);
bool IsRoData(elf_section_entry *section);
bool IsText(elf_section_entry *section);
/* ELF Program Entry Functions */
u8* GetELFProgramHeader(u16 index, elf_context *elf, u8 *elfFile);
u8* GetELFProgramEntry(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryType(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryFlags(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryFileSize(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryMemorySize(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryVAddress(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryPAddress(u16 index, elf_context *elf, u8 *elfFile);
u64 GetELFProgramEntryAlignment(u16 index, elf_context *elf, u8 *elfFile);
int BuildExeFsCode(ncch_settings *set)
{
int result = 0;
if(set->options.IsCfa)
return result;
if(set->componentFilePtrs.plainregion){ // Import PlainRegion from file
result = ImportPlainRegionFromFile(set);
if(result) return result;
}
if(!set->options.IsBuildingCodeSection){ // Import ExeFs Code from file and return
result = ImportExeFsCodeBinaryFromFile(set);
return result;
}
/* Import ELF */
u8 *elfFile = malloc(set->componentFilePtrs.elfSize);
if(!elfFile) {
fprintf(stderr,"[ELF ERROR] Not enough memory\n");
return MEM_ERROR;
}
ReadFile64(elfFile,set->componentFilePtrs.elfSize,0,set->componentFilePtrs.elf);
/* Create ELF Context */
elf_context *elf = calloc(1,sizeof(elf_context));
if(!elf) {
fprintf(stderr,"[ELF ERROR] Not enough memory\n");
free(elfFile);
return MEM_ERROR;
}
result = GetElfContext(elf,elfFile);
if(result) goto finish;
/* Setting Page Size */
elf->pageSize = GetPageSize(set);
if(!set->componentFilePtrs.plainregion){
result = ImportPlainRegionFromElf(elf,elfFile,set);
if(result) goto finish;
}
if(set->options.verbose)
PrintElfContext(elf,elfFile);
result = CreateExeFsCode(elf,elfFile,set);
if(result) goto finish;
result = GetBSSFromElf(elf,elfFile,set);
if(result) goto finish;
finish:
if(result){
if(result == NOT_ELF_FILE) fprintf(stderr,"[ELF ERROR] Not ELF File\n");
else if(result == NOT_ARM_ELF) fprintf(stderr,"[ELF ERROR] Not ARM ELF\n");
else if(result == NON_EXECUTABLE_ELF) fprintf(stderr,"[ELF ERROR] Not Executeable ELF\n");
else if(result == NOT_FIND_BSS_SIZE) fprintf(stderr,"[ELF ERROR] BSS Size Could not be found\n");
else if(result == NOT_FIND_CODE_SECTIONS) fprintf(stderr,"[ELF ERROR] Failed to retrieve code sections from ELF\n");
else fprintf(stderr,"[ELF ERROR] Failed to process ELF file (%d)\n",result);
}
for(int i = 0; i < elf->activeSegments; i++)
free(elf->segments[i].sections);
free(elfFile);
free(elf->sections);
free(elf->programHeaders);
free(elf->segments);
free(elf);
return result;
}
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);
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;
}
int ImportExeFsCodeBinaryFromFile(ncch_settings *set)
{
u32 size = set->componentFilePtrs.codeSize;
u8 *buffer = malloc(size);
if(!buffer) {fprintf(stderr,"[ELF ERROR] Not enough memory\n"); return MEM_ERROR;}
ReadFile64(buffer,size,0,set->componentFilePtrs.code);
set->exefsSections.code.size = set->componentFilePtrs.codeSize;
set->exefsSections.code.buffer = malloc(set->exefsSections.code.size);
if(!set->exefsSections.code.buffer) {fprintf(stderr,"[ELF ERROR] Not enough memory\n"); return MEM_ERROR;}
ReadFile64(set->exefsSections.code.buffer,set->exefsSections.code.size,0,set->componentFilePtrs.code);
if(set->options.CompressCode){
u32 new_len;
set->exefsSections.code.buffer = BLZ_Code(buffer,size,&new_len,BLZ_NORMAL);
set->exefsSections.code.size = new_len;
free(buffer);
}
else{
set->exefsSections.code.size = size;
set->exefsSections.code.buffer = buffer;
}
return 0;
}
u32 GetPageSize(ncch_settings *set)
{
if(set->rsfSet->Option.PageSize)
return strtoul(set->rsfSet->Option.PageSize,NULL,10);
return 0x1000;
}
u32 SizeToPage(u32 memorySize, elf_context *elf)
{
return align(memorySize,elf->pageSize)/elf->pageSize;
}
int GetBSSFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set)
{
for(int i = 0; i < elf->sectionTableEntryCount; i++){
if(IsBss(&elf->sections[i])) {
set->codeDetails.bssSize = elf->sections[i].size;
return 0;
}
}
return NOT_FIND_BSS_SIZE;
}
int ImportPlainRegionFromElf(elf_context *elf, u8 *elfFile, ncch_settings *set) // Doesn't work same as N makerom
{
if(!set->rsfSet->PlainRegionNum) return 0;
u16 *index = calloc(set->rsfSet->PlainRegionNum,sizeof(u16));
/* Getting index Values for each section */
for(int i = 0; i < set->rsfSet->PlainRegionNum; i++){
index[i] = GetElfSectionIndexFromName(set->rsfSet->PlainRegion[i],elf,elfFile);
}
// Eliminating Duplicated Sections
for(int i = set->rsfSet->PlainRegionNum - 1; i >= 0; i--){
for(int j = i-1; j >= 0; j--){
if(index[i] == index[j]) index[i] = 0;
}
}
/* Calculating Total Size of Data */
u64 totalSize = 0;
for(int i = 0; i < set->rsfSet->PlainRegionNum; i++){
totalSize += elf->sections[index[i]].size;
}
/* Creating Output Buffer */
set->sections.plainRegion.size = align(totalSize,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);
/* Storing Sections */
u64 pos = 0;
for(int i = 0; i < set->rsfSet->PlainRegionNum; i++){
memcpy((set->sections.plainRegion.buffer+pos),elf->sections[index[i]].ptr,elf->sections[index[i]].size);
pos += elf->sections[index[i]].size;
}
return 0;
}
int CreateExeFsCode(elf_context *elf, u8 *elfFile, 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,elfFile,set->rsfSet->ExeFs.Text,set->rsfSet->ExeFs.TextNum);
if(result) return result;
result = CreateCodeSegmentFromElf(&rodata,elf,elfFile,set->rsfSet->ExeFs.ReadOnly,set->rsfSet->ExeFs.ReadOnlyNum);
if(result) return result;
result = CreateCodeSegmentFromElf(&rwdata,elf,elfFile,set->rsfSet->ExeFs.ReadWrite,set->rsfSet->ExeFs.ReadWriteNum);
if(result) return result;
/* Allocating Buffer for ExeFs Code */
u32 size = (text.maxPageNum + rodata.maxPageNum + rwdata.maxPageNum)*elf->pageSize;
u8 *code = malloc(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);
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 */
if(set->options.CompressCode){
u32 new_len;
set->exefsSections.code.buffer = BLZ_Code(code,size,&new_len,BLZ_NORMAL);
set->exefsSections.code.size = new_len;
free(code);
}
else{
set->exefsSections.code.size = size;
set->exefsSections.code.buffer = code;
}
/* Setting code_segment rwdata and freeing original buffers */
set->codeDetails.textAddress = text.address;
set->codeDetails.textMaxPages = text.maxPageNum;
set->codeDetails.textSize = text.size;
if(text.size) free(text.data);
set->codeDetails.roAddress = rodata.address;
set->codeDetails.roMaxPages = rodata.maxPageNum;
set->codeDetails.roSize = rodata.size;
if(rodata.size) free(rodata.data);
set->codeDetails.rwAddress = rwdata.address;
set->codeDetails.rwMaxPages = rwdata.maxPageNum;
set->codeDetails.rwSize = rwdata.size;
if(rwdata.size) free(rwdata.data);
/* Return */
return 0;
}
int CreateCodeSegmentFromElf(code_segment *out, elf_context *elf, u8 *elfFile, char **names, u32 nameNum)
{
u16 ContinuousSegmentNum = 0;
memset(out,0,sizeof(code_segment));
elf_segment **ContinuousSegments = GetContinuousSegments(&ContinuousSegmentNum,elf,names,nameNum);
if (ContinuousSegments == NULL){
if(!ContinuousSegmentNum){// Nothing Was Found
//printf("Nothing was found\n");
return 0;
}
else // Error with found segments
return ELF_SEGMENTS_NOT_CONTINUOUS;
}
/* Getting Segment Size/Settings */
u32 vAddr = 0;
u32 memorySize = 0;
for(int i = 0; i < ContinuousSegmentNum; i++){
if (i==0){
vAddr = ContinuousSegments[i]->vAddr;
}
else{ // Add rounded size from previous segment
u32 padding = ContinuousSegments[i]->vAddr - (vAddr + memorySize);
memorySize += padding;
}
memorySize += ContinuousSegments[i]->header->sizeInMemory;
if(IsBss(&ContinuousSegments[i]->sections[ContinuousSegments[i]->sectionNum-1]))
memorySize -= ContinuousSegments[i]->sections[ContinuousSegments[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 */
//vAddr = 0;
//memorySize = 0;
for(int i = 0; i < ContinuousSegmentNum; i++){
/*
if (i==0)
vAddr = ContinuousSegments[i]->vAddr;
else{
u32 num = ContinuousSegments[i]->vAddr - (vAddr + memorySize);
memorySize += num;
}
*/
//u32 size = 0;
for (int j = 0; j < ContinuousSegments[i]->sectionNum; j++){
elf_section_entry *section = &ContinuousSegments[i]->sections[j];
if (!IsBss(section)){
u8 *pos = (out->data + (section->address - ContinuousSegments[i]->vAddr));
memcpy(pos,section->ptr,section->size);
//size += section->size;
}
//else if (j == (ContinuousSegments[i]->sectionNum-1))
//memorySize -= section->size;
//'else
//size += section->size;
}
}
free(ContinuousSegments);
return 0;
}
elf_segment** GetContinuousSegments(u16 *ContinuousSegmentNum, elf_context *elf, char **names, u32 nameNum)
{
u16 SegmentNum = 0;
elf_segment **Segments = GetSegments(&SegmentNum, elf, names, nameNum);
if (Segments == NULL || SegmentNum == 0){ // No Segments for the names were found
//printf("Not Found Segment\n");
return NULL;
}
if (SegmentNum == 1){ //Return as there is no need to check
*ContinuousSegmentNum = SegmentNum;
return Segments;
}
u32 vAddr = Segments[0]->vAddr + Segments[0]->header->sizeInMemory;
for (int i = 1; i < SegmentNum; i++){
if (Segments[i]->vAddr != (u32)align(vAddr,Segments[i]->header->alignment)){ //Each Segment must start after each other
fprintf(stderr,"[ELF ERROR] %s segment and %s segment are not continuous\n", Segments[i]->name, Segments[i - 1]->name);
free(Segments);
*ContinuousSegmentNum = 0xffff; // Signify to function that an error occured
return NULL;
}
}
*ContinuousSegmentNum = SegmentNum;
return Segments;
}
elf_segment** GetSegments(u16 *SegmentNum, elf_context *elf, char **names, u32 nameNum)
{
if (names == NULL)
{
return NULL;
}
elf_segment **Segments = calloc(nameNum,sizeof(elf_segment*));
*SegmentNum = 0; // There can be a max of nameNum Segments, however, they might not all exist
for (int i = 0; i < nameNum; i++){
for(int j = 0; j < elf->activeSegments; j++){
if(strcmp(names[i],elf->segments[j].name) == 0){ // If there is a match, store Segment data pointer & increment index
Segments[*SegmentNum] = &elf->segments[j];
*SegmentNum = *SegmentNum + 1;
}
}
}
return Segments;
}
// ELF Functions
int GetElfContext(elf_context *elf, u8 *elfFile)
{
if(u8_to_u32(elfFile,BE) != ELF_MAGIC) return NOT_ELF_FILE;
elf->Is64bit = (elfFile[4] == elf_64_bit);
elf->IsLittleEndian = (elfFile[5] == elf_little_endian);
int result = ReadElfHdr(elf,elfFile);
if(result) return result;
result = GetElfSectionEntries(elf,elfFile);
if(result) return result;
result = GetElfProgramEntries(elf,elfFile);
if(result) return result;
result = CreateElfSegments(elf,elfFile);
if(result) return result;
return 0;
}
int GetElfSectionEntries(elf_context *elf, u8 *elfFile)
{
elf->sections = calloc(elf->sectionTableEntryCount,sizeof(elf_section_entry));
if(!elf->sections) {
fprintf(stderr,"[ELF ERROR] Not enough memory\n");
return MEM_ERROR;
}
for(int i = 0; i < elf->sectionTableEntryCount; i++){
elf->sections[i].name = GetELFSectionEntryName(i,elf,elfFile);
elf->sections[i].type = GetELFSectionEntryType(i,elf,elfFile);
elf->sections[i].flags = GetELFSectionEntryFlags(i,elf,elfFile);
elf->sections[i].ptr = GetELFSectionEntry(i,elf,elfFile);
elf->sections[i].offsetInFile = GetELFSectionEntryFileOffset(i,elf,elfFile);
elf->sections[i].size = GetELFSectionEntrySize(i,elf,elfFile);
elf->sections[i].address = GetELFSectionEntryAddress(i,elf,elfFile);
elf->sections[i].alignment = GetELFSectionEntryAlignment(i,elf,elfFile);
}
return 0;
}
int GetElfProgramEntries(elf_context *elf, u8 *elfFile)
{
elf->programHeaders = calloc(elf->programTableEntryCount,sizeof(elf_program_entry));
if(!elf->programHeaders) {
fprintf(stderr,"[ELF ERROR] Not enough memory\n");
return MEM_ERROR;
}
for(int i = 0; i < elf->programTableEntryCount; i++){
elf->programHeaders[i].type = GetELFProgramEntryType(i,elf,elfFile);
elf->programHeaders[i].flags = GetELFProgramEntryFlags(i,elf,elfFile);
elf->programHeaders[i].ptr = GetELFProgramEntry(i,elf,elfFile);
elf->programHeaders[i].offsetInFile = GetELFProgramEntryFileOffset(i,elf,elfFile);
elf->programHeaders[i].sizeInFile = GetELFProgramEntryFileSize(i,elf,elfFile);
elf->programHeaders[i].physicalAddress = GetELFProgramEntryPAddress(i,elf,elfFile);
elf->programHeaders[i].virtualAddress = GetELFProgramEntryVAddress(i,elf,elfFile);
elf->programHeaders[i].sizeInMemory = GetELFProgramEntryMemorySize(i,elf,elfFile);
elf->programHeaders[i].alignment = GetELFProgramEntryAlignment(i,elf,elfFile);
}
return 0;
}
void PrintElfContext(elf_context *elf, u8 *elfFile)
{
printf("[ELF] Basic Details\n");
printf(" Class: %s\n",elf->Is64bit ? "64-bit" : "32-bit");
printf(" Data: %s\n",elf->IsLittleEndian ? "Little Endian" : "Big Endian");
printf("[ELF] Program Table Data\n");
printf(" Offset: 0x%"PRIx64"\n",elf->programTableOffset);
printf(" Size: 0x%x\n",elf->programTableEntrySize);
printf(" Count: 0x%x\n",elf->programTableEntryCount);
printf("[ELF] Section Table Data\n");
printf(" Offset: 0x%"PRIx64"\n",elf->sectionTableOffset);
printf(" Size: 0x%x\n",elf->sectionTableEntrySize);
printf(" Count: 0x%x\n",elf->sectionTableEntryCount);
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%"PRIx64"\n",elf->segments[i].header->sizeInFile);
printf(" > Address : 0x%"PRIx64"\n",elf->segments[i].vAddr);
printf(" > Sections : %d\n",elf->segments[i].sectionNum);
for(int j = 0; j < elf->segments[i].sectionNum; j++)
printf(" > Section [%d][%s]\n",j,elf->segments[i].sections[j].name);
/*
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 ReadElfHdr(elf_context *elf, u8 *elfFile)
{
if(elf->Is64bit){
elf_64_hdr *hdr = (elf_64_hdr*)elfFile;
u16 Architecture = u8_to_u16(hdr->targetArchitecture,elf->IsLittleEndian);
u16 Type = u8_to_u16(hdr->type,elf->IsLittleEndian);
if(Architecture != elf_arm) return NOT_ARM_ELF;
if(Type != elf_executeable) return NON_EXECUTABLE_ELF;
elf->programTableOffset = u8_to_u64(hdr->programHeaderTableOffset,elf->IsLittleEndian);
elf->programTableEntrySize = u8_to_u16(hdr->programHeaderEntrySize,elf->IsLittleEndian);
elf->programTableEntryCount = u8_to_u16(hdr->programHeaderEntryCount,elf->IsLittleEndian);
elf->sectionTableOffset = u8_to_u64(hdr->sectionHeaderTableOffset,elf->IsLittleEndian);
elf->sectionTableEntrySize = u8_to_u16(hdr->sectionTableEntrySize,elf->IsLittleEndian);
elf->sectionTableEntryCount = u8_to_u16(hdr->sectionHeaderEntryCount,elf->IsLittleEndian);
elf->sectionHeaderNameEntryIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex,elf->IsLittleEndian);
}
else{
elf_32_hdr *hdr = (elf_32_hdr*)elfFile;
u16 Architecture = u8_to_u16(hdr->targetArchitecture,elf->IsLittleEndian);
u16 Type = u8_to_u16(hdr->type,elf->IsLittleEndian);
if(Architecture != elf_arm) return NOT_ARM_ELF;
if(Type != elf_executeable) return NON_EXECUTABLE_ELF;
elf->programTableOffset = u8_to_u32(hdr->programHeaderTableOffset,elf->IsLittleEndian);
elf->programTableEntrySize = u8_to_u16(hdr->programHeaderEntrySize,elf->IsLittleEndian);
elf->programTableEntryCount = u8_to_u16(hdr->programHeaderEntryCount,elf->IsLittleEndian);
elf->sectionTableOffset = u8_to_u32(hdr->sectionHeaderTableOffset,elf->IsLittleEndian);
elf->sectionTableEntrySize = u8_to_u16(hdr->sectionTableEntrySize,elf->IsLittleEndian);
elf->sectionTableEntryCount = u8_to_u16(hdr->sectionHeaderEntryCount,elf->IsLittleEndian);
elf->sectionHeaderNameEntryIndex = u8_to_u16(hdr->sectionHeaderNameEntryIndex,elf->IsLittleEndian);
}
return 0;
}
/* Section Hdr Functions */
u8* GetELFSectionHeader(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return NULL;
return (elfFile + elf->sectionTableOffset + elf->sectionTableEntrySize*index);
}
u8* GetELFSectionEntry(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return NULL;
return (u8*) (elfFile + GetELFSectionEntryFileOffset(index,elf,elfFile));
}
char* GetELFSectionEntryName(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return 0;
u64 NameIndex = 0;
if(elf->Is64bit){
elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile);
NameIndex = u8_to_u64(shdr->sh_name,elf->IsLittleEndian);
}
else{
elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile);
NameIndex = u8_to_u32(shdr->sh_name,elf->IsLittleEndian);
}
u8 *NameTable = GetELFSectionEntry(elf->sectionHeaderNameEntryIndex,elf,elfFile);
return (char*)(NameTable+NameIndex);
}
u64 GetELFSectionEntryType(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u64(shdr->sh_type,elf->IsLittleEndian);
}
else{
elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u32(shdr->sh_type,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFSectionEntryFlags(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u64(shdr->sh_flags,elf->IsLittleEndian);
}
else{
elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u32(shdr->sh_flags,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFSectionEntryAddress(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u64(shdr->sh_addr,elf->IsLittleEndian);
}
else{
elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u32(shdr->sh_addr,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFSectionEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u64(shdr->sh_offset,elf->IsLittleEndian);
}
else{
elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u32(shdr->sh_offset,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFSectionEntrySize(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u64(shdr->sh_size,elf->IsLittleEndian);
}
else{
elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u32(shdr->sh_size,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFSectionEntryAlignment(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->sectionTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_shdr *shdr = (elf_64_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u64(shdr->sh_addralign,elf->IsLittleEndian);
}
else{
elf_32_shdr *shdr = (elf_32_shdr*)GetELFSectionHeader(index,elf,elfFile);
return u8_to_u32(shdr->sh_addralign,elf->IsLittleEndian);
}
return 0;
}
u16 GetElfSectionIndexFromName(char *name, elf_context *elf, u8 *elfFile)
{
for(int i = 0; i < elf->sectionTableEntryCount; i++){
if(strcmp(name,elf->sections[i].name) == 0) return i;
}
return 0; // Assuming 0 is always empty
}
bool IsBss(elf_section_entry *section)
{
if(section->type == 8 && section->flags == 3)
return true;
return false;
}
bool IsData(elf_section_entry *section)
{
if(section->type == 1 && section->flags == 3)
return true;
return false;
}
bool IsRoData(elf_section_entry *section)
{
if(section->type == 1 && section->flags == 2)
return true;
return false;
}
bool IsText(elf_section_entry *section)
{
if(section->type == 1 && section->flags == 6)
return true;
return false;
}
/* ProgramHeader Functions */
u8* GetELFProgramHeader(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return NULL;
return (elfFile + elf->programTableOffset + elf->programTableEntrySize*index);
}
u8* GetELFProgramEntry(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return NULL;
return (u8*) (elfFile + GetELFProgramEntryFileOffset(index,elf,elfFile));
return NULL;
}
u64 GetELFProgramEntryType(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_type,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_type,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFProgramEntryFlags(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_flags,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_flags,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFProgramEntryFileSize(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_filesz,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_filesz,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFProgramEntryFileOffset(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_offset,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_offset,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFProgramEntryMemorySize(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_memsz,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_memsz,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFProgramEntryVAddress(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_vaddr,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_vaddr,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFProgramEntryPAddress(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_paddr,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_paddr,elf->IsLittleEndian);
}
return 0;
}
u64 GetELFProgramEntryAlignment(u16 index, elf_context *elf, u8 *elfFile)
{
if(index >= elf->programTableEntryCount) return 0;
if(elf->Is64bit){
elf_64_phdr *phdr = (elf_64_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u64(phdr->p_align,elf->IsLittleEndian);
}
else{
elf_32_phdr *phdr = (elf_32_phdr*)GetELFProgramHeader(index,elf,elfFile);
return u8_to_u32(phdr->p_align,elf->IsLittleEndian);
}
return 0;
}
int CreateElfSegments(elf_context *elf, u8 *elfFile)
{
int num = 0;
// Interate through Each Program Header
elf->activeSegments = 0;
elf->segments = calloc(elf->programTableEntryCount,sizeof(elf_segment));
elf_segment *segment = malloc(sizeof(elf_segment)); // Temporary Buffer
for (int i = 0; i < elf->programTableEntryCount; i++){
if (elf->programHeaders[i].sizeInMemory != 0 && elf->programHeaders[i].type == 1){
memset(segment,0,sizeof(elf_segment));
bool foundFirstSection = false;
u32 size = 0;
u32 vAddr = elf->programHeaders[i].virtualAddress;
u32 memorySize = elf->programHeaders[i].sizeInMemory;
//printf("Segment Size in memory: 0x%x\n",memorySize);
//printf("Segment Alignment: 0x%x\n",elf->programHeaders[i].alignment);
u16 SectionInfoCapacity = 10;
segment->sectionNum = 0;
segment->sections = calloc(SectionInfoCapacity,sizeof(elf_section_entry));
// Itterate Through Section Headers
for (int j = num; j < elf->sectionTableEntryCount; j++){
if (!foundFirstSection){
if (elf->sections[j].address != vAddr)
continue;
while (j < (int)elf->sections[j].size && elf->sections[j].address == vAddr && !IsIgnoreSection(elf->sections[j]))
j++;
j--;
foundFirstSection = true;
segment->vAddr = elf->sections[j].address;
segment->name = elf->sections[j].name;
}
if(segment->sectionNum < SectionInfoCapacity)
memcpy(&segment->sections[segment->sectionNum],&elf->sections[j],sizeof(elf_section_entry));
else{
SectionInfoCapacity = SectionInfoCapacity*2;
elf_section_entry *tmp = calloc(SectionInfoCapacity,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],&elf->sections[j],sizeof(elf_section_entry));
}
segment->sectionNum++;
if(size == 0)
size += elf->sections[j].size;
else{
u32 padding = elf->sections[j].address - (elf->sections[j-1].address + elf->sections[j-1].size);
size += padding + elf->sections[j].size;
}
//printf("Section name: %s",elf->sections[j].name);
//printf(" 0x%lx",elf->sections[j].size);
//printf(" (Total Size: 0x%x)\n",size);
if (size == memorySize)
break;
if (size > memorySize){
fprintf(stderr,"[ELF ERROR] Too large section size.\n Segment size = 0x%x\n Section Size = 0x%x\n", memorySize, 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);
free(segment);
fprintf(stderr,"[ELF ERROR] Program Header Has no corresponding Sections, ELF Cannot be proccessed\n");
return ELF_SEGMENTS_NOT_FOUND;
}
}
}
free(segment);
return 0;
}
bool IsIgnoreSection(elf_section_entry info)
{
if (info.address)
return false;
if (info.type != 1 && info.type != 0)
return true;
char IgnoreSectionNames[7][20] = { ".debug_abbrev", ".debug_frame", ".debug_info", ".debug_line", ".debug_loc", ".debug_pubnames", ".comment" };
for (int i = 0; i < 7; i++){
if (strcmp(IgnoreSectionNames[i],info.name) == 0)
return true;
}
return false;
}