www.pudn.com > potemkin_sourceforPSP.rar > ElfReader.cpp
#include "stdafx.h"
#include "../MemMap.h"
#include "../Host.h"
#include "../MIPS/MIPSTables.h"
#include "ElfReader.h"
#include "../PSP/HLE/sceKernelMemory.h"
const char *ElfReader::GetSectionName(int section)
{
if (sections[section].sh_type == SHT_NULL)
return 0;
int nameOffset = sections[section].sh_name;
char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
if (ptr)
return ptr + nameOffset;
else
return 0;
}
void addrToHiLo(u32 addr, u16 &hi, s16 &lo)
{
lo = (addr & 0xFFFF);
u32 naddr = addr - lo;
hi = naddr>>16;
u32 test = (hi<<16) + lo;
if (test != addr)
{
DebugBreak();
}
}
bool ElfReader::LoadInto(u32 vaddr)
{
LOG(LOADER,"String section: %i", header->e_shstrndx);
//TODO - Check header->e_ident here
//let's dump string section
/*
char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
if (*ptr == 0)
ptr++;
ptr+=513;
while (*ptr != 0)
{
int len = strlen(ptr);
LOG(LOADER,"XX %s",ptr);
ptr+=len;
ptr++;
}*/
sectionOffsets = new u32[GetNumSections()];
sectionAddrs = new u32[GetNumSections()];
// Should we relocate?
bRelocate = (header->e_type != ET_EXEC);
entryPoint = header->e_entry;
if (bRelocate)
{
LOG(LOADER,"Relocatable module");
entryPoint += vaddr;
}
else
{
LOG(LOADER,"Prerelocated executable");
}
LOG(LOADER,"%i segments:", header->e_phnum);
// First pass : Get the damn bits into RAM
u32 segmentVAddr[32];
u32 baseAddress = bRelocate?vaddr:0;
for (int i=0; ie_phnum; i++)
{
Elf32_Phdr *p = segments + i;
LOG(LOADER, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr, p->p_filesz, p->p_memsz);
if (p->p_type == PT_LOAD)
{
segmentVAddr[i] = baseAddress + p->p_vaddr;
u32 writeAddr = segmentVAddr[i];
u8 *src = GetSegmentPtr(i);
u8 *dst = GetMemPointer(writeAddr);
u32 srcSize = p->p_filesz;
u32 dstSize = p->p_memsz;
PSPHLE::userMemory.AllocAt(writeAddr, dstSize, "ELF");
memcpy(dst, src, srcSize);
if (srcSize < dstSize)
{
//memset(dst + srcSize, 0, dstSize-srcSize); //zero out bss
}
LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, p->p_memsz);
}
}
PSPHLE::userMemory.ListBlocks();
LOG(LOADER,"%i sections:", header->e_shnum);
for (int i=0; ish_addr + baseAddress;
sectionOffsets[i] = writeAddr - vaddr;
sectionAddrs[i] = writeAddr;
if (s->sh_flags & SHF_ALLOC)
{
LOG(LOADER,"Data Section found: %s Sitting at %08x, size %08x", name, writeAddr, s->sh_size);
}
else
{
LOG(LOADER,"NonData Section found: %s Ignoring (size=%08x) (flags=%08x)", name, s->sh_size, s->sh_flags);
}
}
LOG(LOADER,"Relocations:");
// Second pass: Do necessary relocations
for (int i=0; ish_type == SHT_PSPREL)
{
//We have a relocation table!
int symbolSection = s->sh_link;
int sectionToModify = s->sh_info;
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
{
LOG(LOADER,"Trying to relocate non-loaded section %s",GetSectionName(sectionToModify));
continue;
}
int numRelocs = s->sh_size / sizeof(Elf32_Rel);
Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i);
LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify));
for (int r = 0; r < numRelocs; r++)
{
u32 info = rels[r].r_info;
u32 addr = rels[r].r_offset;
int type = info & 0xf;
int readwrite = (info>>8) & 0xff;
int relative = (info>>16) & 0xff;
//0 = code
//1 = data
addr += segmentVAddr[readwrite];
u32 op = ReadMem32(addr);
const bool log = false;
//log=true;
if (log)
{
LOG(LOADER,"rel at: %08x type: %08x",addr,info);
}
u32 relocateTo = segmentVAddr[relative];
#define R_MIPS32 2
#define R_MIPS26 4
#define R_MIPS16_HI 5
#define R_MIPS16_LO 6
switch (type)
{
case R_MIPS32:
if (log)
LOG(LOADER,"Full address reloc %08x", addr);
//full address, no problemo
//if (readwrite != 0)
op += relocateTo;
break;
case R_MIPS26: //j, jal
//add on to put in correct address space
if (log)
LOG(LOADER,"j/jal reloc %08x", addr);
op = op & 0xFC000000 | (((op&0x03FFFFFF)+(relocateTo>>2))&0x03FFFFFFF);
break;
case R_MIPS16_HI: //lui part of lui-addiu pairs
{
if (log)
LOG(LOADER,"HI reloc %08x", addr);
u32 cur = (op & 0xFFFF) << 16;
u16 hi = 0;
s16 lo;
bool found = false;
for (int t = r + 1; tsh_type == SHT_REL)
{
LOG(LOADER, "Traditional relocation section found.");
if (bRelocate)
{
LOG(LOADER, "Binary is prerelocated. Skipping relocations.");
}
else
{
//We have a relocation table!
int symbolSection = s->sh_link;
int sectionToModify = s->sh_info;
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
{
LOG(LOADER,"Trying to relocate non-loaded section %s, ignoring",GetSectionName(sectionToModify));
continue;
}
LOG(LOADER,"Traditional relocations unsupported.");
}
}
}
LOG(LOADER,"Done.");
return true;
}
SectionID ElfReader::GetSectionByName(const char *name, int firstSection)
{
for (int i = firstSection; i < header->e_shnum; i++)
{
const char *secname = GetSectionName(i);
if (secname != 0 && strcmp(name, secname) == 0)
{
return i;
}
}
return -1;
}
bool ElfReader::LoadSymbols()
{
bool hasSymbols = false;
SectionID sec = GetSectionByName(".symtab");
if (sec != -1)
{
int stringSection = sections[sec].sh_link;
const char *stringBase = (const char*)GetSectionDataPtr(stringSection);
//We have a symbol table!
Elf32_Sym *symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
for (int sym = 0; sym> 4;
int type = symtab[sym].st_info & 0xF;
int sectionIndex = symtab[sym].st_shndx;
int value = symtab[sym].st_value;
const char *name = stringBase + symtab[sym].st_name;
if (bRelocate)
value += sectionAddrs[sectionIndex];
SymbolType symtype = ST_DATA;
switch (type)
{
case STT_OBJECT:
symtype = ST_DATA; break;
case STT_FUNC:
symtype = ST_FUNCTION; break;
default:
continue;
}
host->AddSymbol(name, value, size, symtype);
hasSymbols = true;
//...
}
}
return hasSymbols;
}