mips conversion to ElfLinker almost ready

This commit is contained in:
László Molnár
2006-07-06 00:54:14 +02:00
parent ee0c87f7b1
commit c026121c0e
7 changed files with 935 additions and 515 deletions
+44 -20
View File
@@ -35,6 +35,7 @@
#include "filter.h"
#include "packer.h"
#include "p_ps1.h"
#include "linker.h"
static const
#include "stub/mipsel.r3000-ps1-boot.h"
@@ -83,7 +84,7 @@ PackPs1::PackPs1(InputFile *f) :
COMPILE_TIME_ASSERT(sizeof(ps1_exe_t) == 188);
COMPILE_TIME_ASSERT(PS_HDR_SIZE > sizeof(ps1_exe_t));
COMPILE_TIME_ASSERT(SZ_IH_BKUP == 40);
#if 1 || defined(WITH_NRV)
#if 0 // 1 || defined(WITH_NRV)
COMPILE_TIME_ASSERT(sizeof(nrv_boot_loader) == 3935);
COMPILE_TIME_ASSERT(NRV_BOOT_LOADER_CRC32 == 0x0ac25782);
COMPILE_TIME_ASSERT(sizeof(nrv_con_loader) == 2829);
@@ -108,6 +109,29 @@ const int *PackPs1::getFilters() const
}
Linker* PackPs1::newLinker() const
{
class ElfLinkerMipsLE : public ElfLinker
{
typedef ElfLinker super;
virtual void relocate1(Relocation *rel, upx_byte *location,
unsigned value, const char *type)
{
if (strcmp(type, "R_MIPS_LO16") == 0)
set_le16(location, get_le16(location) + value);
else if (strcmp(type, "R_MIPS_HI16") == 0)
set_le16(location, get_le16(location) + (value >> 16));
else if (strcmp(type, "R_MIPS_32") == 0)
set_le32(location, get_le32(location) + value);
else
super::relocate1(rel, location, value, type);
}
};
return new ElfLinkerMipsLE;
}
/*************************************************************************
// util
// readFileHeader() reads ih and checks for illegal values
@@ -264,7 +288,7 @@ int PackPs1::buildLoader(const Filter *)
ih.tx_len & 3 ? "PS1MSETU" : "PS1MSETA",
NULL);
addLoader("PS1EXITC", "IDENTSTR", "PS1PAHDR",
addLoader("PS1EXITC", "IDENTSTR", "UPX1HEAD",
isCon ? "PS1SREGS" : "",
NULL);
@@ -337,8 +361,6 @@ void PackPs1::pack(OutputFile *fo)
MemBuffer loader(lsize);
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader,lsize);
unsigned pad = 0;
unsigned filelen = ALIGN_UP(ih.tx_len, 4);
unsigned pad_code = TIL_ALIGNED(ph.c_len, 4);
@@ -347,7 +369,6 @@ void PackPs1::pack(OutputFile *fo)
const unsigned comp_data_start = ((decomp_data_start + filelen + overlap) - ph.c_len);
const int h_len = lsize - getLoaderSectionStart("IDENTSTR");
const int c_len = lsize - h_len;
int d_len = 0;
int e_len = 0;
@@ -362,14 +383,10 @@ void PackPs1::pack(OutputFile *fo)
e_len = (lsize - d_len) - h_len;
}
patch_mips_le(loader,c_len,"JPEP",MIPS_JP(ih.epc));
if (sa_cnt)
patch_mips_le(loader,c_len,"SC",
MIPS_LO(sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2));
if (ih.tx_ptr & 0xffff)
patch_mips_le(loader,c_len,"DECO",decomp_data_start);
else
patch_mips_le(loader,c_len,"DE",MIPS_HI(decomp_data_start));
linker->defineSymbol("JPEP", MIPS_JP(ih.epc));
linker->defineSymbol("SC", MIPS_LO(sa_cnt > (0x10000 << 2) ?
sa_cnt >> 5 : sa_cnt >> 2));
linker->defineSymbol("DECO",decomp_data_start);
const unsigned entry = comp_data_start - e_len - pad_code;
oh.tx_ptr = entry;
@@ -389,11 +406,14 @@ void PackPs1::pack(OutputFile *fo)
if (isCon)
{
if (pad_code)
patch_mips_le(loader, c_len, "PC", pad_code);
patch_mips_le(loader, c_len, "DCRT", entry + (e_len - d_len));
patch_mips_le(loader, c_len, "LS",
d_len + get_le32(&loader[getLoaderSectionStart("PS1SREGS")]));
linker->defineSymbol("PC", pad_code);
linker->defineSymbol("DCRT", entry + (e_len - d_len));
linker->defineSymbol("LS",
d_len + get_le32(&loader[getLoaderSectionStart("PS1SREGS")]));
linker->relocate();
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader,lsize);
// ps1_exe_t structure 188 bytes
fo->write(&oh,sizeof(oh));
@@ -402,8 +422,12 @@ void PackPs1::pack(OutputFile *fo)
}
else
{
patch_mips_le(loader, c_len, "CPDO", comp_data_start);
patch_mips_le(loader, e_len, "PSVR", FIX_PSVR);
linker->defineSymbol("CPDO", comp_data_start);
linker->defineSymbol("PSVR", FIX_PSVR);
linker->relocate();
memcpy(loader, getLoader(), lsize);
patchPackHeader(loader,lsize);
// ps1_exe_t structure 188 bytes
fo->write(&oh,sizeof(oh));