diff options
Diffstat (limited to 'src/ps3/cell_loader.cpp')
| -rw-r--r-- | src/ps3/cell_loader.cpp | 865 |
1 files changed, 865 insertions, 0 deletions
diff --git a/src/ps3/cell_loader.cpp b/src/ps3/cell_loader.cpp new file mode 100644 index 0000000..f548185 --- /dev/null +++ b/src/ps3/cell_loader.cpp @@ -0,0 +1,865 @@ +#include "cell_loader.h" + +#include <idaldr.h> +#include <struct.hpp> + +#include <memory> +#include <vector> + +cell_loader::cell_loader(elf_reader<elf64> *elf, + uint64 relocAddr, + std::string databaseFile) + : m_elf(elf) +{ + m_hasSegSym = false; + m_relocAddr = 0; + + // only PRX's contain relocations + if ( isLoadingPrx() ) + m_relocAddr = relocAddr; + + inf.demnames |= DEMNAM_GCC3; // assume gcc3 names + inf.af |= AF_PROCPTR; // Create function if data xref data->code32 exists + + char databasePath[QMAXPATH]; + + if ( getsysfile(databasePath, QMAXFILE, databaseFile.c_str(), LDR_SUBDIR) == NULL ) + loader_failure("Could not locate database file (%s).\n", databaseFile.c_str()); + + if ( m_database.LoadFile(databasePath) == false ) + loader_failure("Failed to load database file (%s).\n", databaseFile.c_str()); +} + +void cell_loader::apply() { + declareStructures(); + + applySegments(); + + swapSymbols(); + + if ( isLoadingPrx() ) { + // the only way I know to check if its a 0.85 PRX + for ( auto &segment : m_elf->getSegments() ) { + if ( segment.p_type == PT_SCE_SEGSYM ) { + m_hasSegSym = true; + break; + } + } + + // we need gpValue for relocations on 0.85 + // otherwise, I don't think newer PRX's have + // TOC based relocations. TOC is not set in + // moduleInfo. It seems to always be zero. + if ( m_hasSegSym ) { + //msg("Looking for .toc section\n"); + auto tocSection = m_elf->getSectionByName(".toc"); + if ( tocSection ) { + //msg("Found toc section!\n"); + m_gpValue = tocSection->sh_addr + m_relocAddr; + } + } + + // gpValue can be found at sceModuleInfo->gp_value + // 0.85 gpValue is base address of .toc + applyRelocations(); + + // if not a 0.85 PRX + if ( !m_hasSegSym ) { + // p_paddr is an offset into the file. + auto firstSegment = m_elf->getSegments()[0]; + m_gpValue = get_long( (firstSegment.p_vaddr + m_relocAddr) + // file offset to address + (firstSegment.p_paddr - firstSegment.p_offset) + + offsetof(_scemoduleinfo_ppu32, gp_value) ); + } + + applyModuleInfo(); + } else if ( isLoadingExec() ) { + // gpValue can be found at m_elf->entry() + 4 + // _start is actually what loads TOC which is hardcoded to lwz(entry + 4) + // there are also function stubs which set TOC to a different value + m_gpValue = get_long(m_elf->entry() + 4); + + applyProcessInfo(); + + add_entry(0, m_elf->entry(), "_start", true); + } + + msg("gpValue = %08x\n", m_gpValue); + + // set TOC in IDA + ph.notify(processor_t::idp_notify(ph.loader+1), m_gpValue); + + // we want to apply the symbols last so that symbols + // always override our own custom symbols. + applySymbols(); +} + +void cell_loader::applySegments() { + // we prefer section headers + if ( m_elf->getNumSections() > 0 ) + applySectionHeaders(); + // otherwise load program headers + else if ( m_elf->getNumSegments() > 0 ) + applyProgramHeaders(); + else + loader_failure("No segments available!"); +} + +void cell_loader::applySectionHeaders() { + msg("Applying section headers...\n"); + auto §ions = m_elf->getSections(); + const char *strTab = m_elf->getSectionStringTable()->data(); + + size_t index = 0; + for ( const auto §ion : sections ) { + // only load allocatable sections + if ( section.sh_flags & SHF_ALLOC && + section.sh_size > 0 ) { + if ( section.sh_type == SHT_NULL ) + continue; + + uchar perm = SEGPERM_READ; + char *sclass; + + if ( section.sh_flags & SHF_WRITE ) + perm |= SEGPERM_WRITE; + if ( section.sh_flags & SHF_EXECINSTR ) + perm |= SEGPERM_EXEC; + + if ( section.sh_flags & SHF_EXECINSTR ) + sclass = CLASS_CODE; + else if ( section.sh_type == SHT_NOBITS ) + sclass = CLASS_BSS; + else + sclass = CLASS_DATA; + + const char *name = NULL; + if ( section.sh_name != NULL ) + name = &strTab[section.sh_name]; + + applySegment( index, + section.sh_offset, + section.sh_addr, + section.sh_size, + name, + sclass, + perm, + m_elf->getAlignment(section.sh_addralign), + (section.sh_type == SHT_NOBITS) ? false : true ); + + ++index; + } + } +} + +void cell_loader::applyProgramHeaders() { + msg("Applying program headers...\n"); + auto &segments = m_elf->getSegments(); + + size_t index = 0; + for ( const auto &segment : segments ) { + if ( segment.p_memsz > 0 ) { + uchar perm; + char *sclass; + + if ( segment.p_flags & PF_W ) // if its writable + sclass = CLASS_DATA; + if ( (segment.p_flags & PF_R) && // if its only readable + !(segment.p_flags & PF_W) && + !(segment.p_flags & PF_X) ) + sclass = CLASS_CONST; + if ( segment.p_flags & PF_X ) // if its executable + sclass = CLASS_CODE; + + if ( segment.p_filesz == 0 && + segment.p_memsz > 0 ) + sclass = CLASS_BSS; + + if ( segment.p_flags & PF_X ) + perm |= SEGPERM_EXEC; + if ( segment.p_flags & PF_W ) + perm |= SEGPERM_WRITE; + if ( segment.p_flags & PF_R ) + perm |= SEGPERM_READ; + + applySegment( index, + segment.p_offset, + segment.p_vaddr, + segment.p_memsz, + NULL, + sclass, + perm, + m_elf->getAlignment(segment.p_align) ); + + ++index; + } + } +} + +void cell_loader::applySegment(uint32 sel, + uint64 offset, + uint64 addr, + uint64 size, + const char *name, + const char *sclass, + uchar perm, + uchar align, + bool load) { + addr += m_relocAddr; + + segment_t seg; + seg.startEA = addr; + seg.endEA = addr + size; + seg.color = DEFCOLOR; + seg.sel = sel; + seg.bitness = 1; + seg.orgbase = sel; + seg.comb = scPub; + seg.perm = perm; + seg.flags = SFL_LOADER; + seg.align = align; + + set_selector(sel, 0); + + if ( name == NULL ) + name = ""; + + add_segm_ex(&seg, name, sclass, NULL); + + if ( load == true ) + file2base(m_elf->getReader(), offset, addr, addr + size, true); +} + +void cell_loader::applyRelocations() { + if ( m_hasSegSym ) + applySectionRelocations(); // pretty much only for 0.85 + else + applySegmentRelocations(); +} + +void cell_loader::applySectionRelocations() { + msg("Applying section based relocations..\n"); + + auto §ions = m_elf->getSections(); + auto symbols = m_elf->getSymbols(); + + for ( auto §ion : sections ) { + // NOTE: the only SHT_RELA sections I see after 0.85 + // are non-allocatable so no reason to consider those + if ( section.sh_type == SHT_RELA ) { + + auto nrela = section.sh_size / sizeof(Elf64_Rela); + auto relocations = reinterpret_cast<Elf64_Rela *>(section.data()); + + for ( size_t i = 0; i < nrela; ++i ) { + auto &rela = relocations[i]; + + swap(rela.r_offset); + swap(rela.r_info); + swap(rela.r_addend); + + uint32 type = ELF64_R_TYPE(rela.r_info); + uint32 sym = ELF64_R_SYM (rela.r_info); + + //msg("r_type: %08x\n", type); + //msg("r_sym: %08x\n", sym); + + if ( type == R_PPC64_NONE ) { + msg("Skipping relocation..\n"); + continue; + } + + if ( type > R_PPC64_TLSGD ) { + msg("Invalid relocation type (%i)!\n", type); + continue; + } + + //msg("nsyms = %08x\n", m_elf->getNumSymbols()); + //msg("symsec = %04x\n", symbols[ sym ].st_shndx); + + if ( sym > m_elf->getNumSymbols() ) { + msg("Invalid symbol index!\n"); + continue; + } + + + if ( symbols[ sym ].st_shndx > m_elf->getNumSections() ) { + if ( symbols[ sym ].st_shndx != SHN_ABS ) { + msg("Invalid symbol section index!\n"); + continue; + } + } + + uint32 addr = sections[ section.sh_info ].sh_addr + + rela.r_offset; + uint32 saddr = sections[ symbols[ sym ].st_shndx ].sh_addr + + symbols[ sym ].st_value + rela.r_addend; + + applyRelocation(type, addr, saddr); + } + } + } +} + +void cell_loader::applySegmentRelocations() { + msg("Applying segment based relocations..\n"); + + auto &segments = m_elf->getSegments(); + + for ( auto &segment : segments ) { + if ( segment.p_type == PT_SCE_PPURELA ) { + auto nrela = segment.p_filesz / sizeof(Elf64_Rela); + auto relocations = reinterpret_cast<Elf64_Rela *>(segment.data()); + + for ( size_t i = 0; i < nrela; ++i ) { + auto &rela = relocations[i]; + + swap(rela.r_offset); + swap(rela.r_info); + swap(rela.r_addend); + + auto type = ELF64_R_TYPE(rela.r_info); + + if ( type == R_PPC64_NONE ) + continue; + + auto sym = ELF64_R_SYM(rela.r_info); + auto patchseg = (sym & 0x000000ff); + auto symseg = (sym & 0x7fffff00) >> 8; + + uint32 addr, saddr; + if ( patchseg == 0xFF ) + addr = 0; + else + addr = segments[patchseg].p_vaddr + rela.r_offset; + + if ( symseg == 0xFF ) + saddr = 0; + else + saddr = segments[symseg].p_vaddr + rela.r_addend; + + applyRelocation(type, addr, saddr); + } + break; // TODO: should only be one segment right? + } + } +} + +void cell_loader::applyRelocation(uint32 type, uint32 addr, uint32 saddr) { + uint32 value; + + addr += m_relocAddr; + saddr += m_relocAddr; + + //msg("Applying relocation %i (%08x -> %08x)\n", type, addr, saddr); + + switch ( type ) { + case R_PPC64_ADDR32: + value = saddr; + patch_long(addr, value); + break; + case R_PPC64_ADDR16_LO: + value = saddr & 0xFFFF; + patch_word(addr, value); + break; + case R_PPC64_ADDR16_HA: + value = (((saddr + 0x8000) >> 16) & 0xFFFF); + patch_word(addr, value); + break; + case R_PPC64_REL24: + value = get_original_long(addr); + value = (value & ~0x03fffffc) | ((saddr - addr) & 0x3fffffc); + patch_long(addr, value); + break; + case R_PPC64_TOC16: + value = saddr - m_gpValue; + patch_word(addr, value); + break; + case R_PPC64_TOC16_DS: + value = get_word(addr); + value = (value & ~0xFFFC) | ((saddr - m_gpValue) & 0xFFFC); + patch_word(addr, value); + break; + case R_PPC64_TLSGD: + value = m_gpValue; + patch_long(addr, value); + break; + default: + msg("Unsupported relocation (%i).\n", type); + break; + } +} + +void cell_loader::loadExports(uint32 entTop, uint32 entEnd) { + msg("Loading exports...\n"); + + tid_t tid = get_struc_id("_scelibent_ppu32"); + do_name_anyway(entTop - 4, "__begin_of_section_lib_ent"); + do_name_anyway(entEnd, "__end_of_section_lib_ent"); + + uchar structsize; + + for ( ea_t ea = entTop; ea < entEnd; ea += structsize ) { + structsize = get_byte(ea); + + auto nfunc = get_word(ea + offsetof(_scelibent_common, nfunc)); + auto nvar = get_word(ea + offsetof(_scelibent_common, nvar)); + auto ntlsvar = get_word(ea + offsetof(_scelibent_common, ntlsvar)); + auto count = nfunc + nvar + ntlsvar; + + //msg("Num Functions: %i\n", nfunc); + //msg("Num Variables: %i\n", nvar); + //msg("Num TLS Variables: %i\n", ntlsvar); + + if ( structsize == sizeof(_scelibent_ppu32) ) { + doStruct(ea, sizeof(_scelibent_ppu32), tid); + + auto libNamePtr = get_long(ea + offsetof(_scelibent_ppu32, libname)); + auto nidTable = get_long(ea + offsetof(_scelibent_ppu32, nidtable)); + auto addTable = get_long(ea + offsetof(_scelibent_ppu32, addtable)); + + char libName[256]; + char symName[MAXNAMELEN]; + if ( libNamePtr == NULL ) { + do_name_anyway(nidTable, "_NONAMEnid_table"); + do_name_anyway(addTable, "_NONAMEentry_table"); + } else { + get_ascii_contents(libNamePtr, get_max_ascii_length(libNamePtr, ASCSTR_C), ASCSTR_C, libName, 256); + + qsnprintf(symName, MAXNAMELEN, "_%s_str", libName); + do_name_anyway(libNamePtr, symName); + + qsnprintf(symName, MAXNAMELEN, "__%s_Functions_NID_table", libName); + do_name_anyway(nidTable, symName); + + qsnprintf(symName, MAXNAMELEN, "__%s_Functions_table", libName); + do_name_anyway(addTable, symName); + } + + //msg("Processing entries..\n"); + if ( nidTable != NULL && addTable != NULL ) { + for ( int i = 0; i < count; ++i ) { + const char *resolvedNid; + ea_t nidOffset = nidTable + (i * 4); + ea_t addOffset = addTable + (i * 4); + + uint32 nid = get_long(nidOffset); + uint32 add = get_long(addOffset); + + if ( libNamePtr ) { + uint32 addToc = get_long(add); + resolvedNid = getNameFromDatabase(libName, nid); + if ( resolvedNid ) { + set_cmt(nidOffset, resolvedNid, false); + do_name_anyway(add, resolvedNid); + + // only label functions this way + if ( i < nfunc ) { + qsnprintf(symName, MAXNAMELEN, ".%s", resolvedNid); + do_name_anyway(addToc, symName); + } + } + + if ( i < nfunc ) + auto_make_proc(addToc); + } + + //msg("doDwrd: %08x\n", nidOffset); + //msg("doDwrd: %08x\n", addOffset); + doDwrd(nidOffset, 4); + doDwrd(addOffset, 4); + } + } + } else { + msg("Unknown export structure at %08x.\n", ea); + continue; + } + } +} + +void cell_loader::loadImports(uint32 stubTop, uint32 stubEnd) { + msg("Loading imports...\n"); + + tid_t tid = get_struc_id("_scelibstub_ppu32"); + + do_name_anyway(stubTop - 4, "__begin_of_section_lib_stub"); + do_name_anyway(stubEnd, "__end_of_section_lib_stub"); + + uchar structsize; + + // define data for lib stub + for ( ea_t ea = stubTop; ea < stubEnd; ea += structsize ) { + structsize = get_byte(ea); + + auto nFunc = get_word(ea + offsetof(_scelibstub_common, nfunc)); + auto nVar = get_word(ea + offsetof(_scelibstub_common, nvar)); + auto nTlsVar = get_word(ea + offsetof(_scelibstub_common, ntlsvar)); + + //msg("Num Functions: %i\n", nFunc); + //msg("Num Variables: %i\n", nVar); + //msg("Num TLS Variables: %i\n", nTlsVar); + + if (structsize == sizeof(_scelibstub_ppu32)) { + doStruct(ea, sizeof(_scelibstub_ppu32), tid); + + ea_t libNamePtr = get_long(ea + offsetof(_scelibstub_ppu32, libname)); + ea_t funcNidTable = get_long(ea + offsetof(_scelibstub_ppu32, func_nidtable)); + ea_t funcTable = get_long(ea + offsetof(_scelibstub_ppu32, func_table)); + ea_t varNidTable = get_long(ea + offsetof(_scelibstub_ppu32, var_nidtable)); + ea_t varTable = get_long(ea + offsetof(_scelibstub_ppu32, var_table)); + ea_t tlsNidTable = get_long(ea + offsetof(_scelibstub_ppu32, tls_nidtable)); + ea_t tlsTable = get_long(ea + offsetof(_scelibstub_ppu32, tls_table)); + + char libName[256]; + char symName[MAXNAMELEN]; + get_ascii_contents(libNamePtr, get_max_ascii_length(libNamePtr, ASCSTR_C), ASCSTR_C, libName, 256); + + qsnprintf(symName, MAXNAMELEN, "_%s_0001_stub_head", libName); + do_name_anyway(ea, symName); + + qsnprintf(symName, MAXNAMELEN, "_%s_stub_str", libName); + do_name_anyway(libNamePtr, symName); + + qsnprintf(symName, MAXNAMELEN, "_sce_package_version_%s", libName); + do_name_anyway(libNamePtr - 4, symName); + + //msg("Processing %i exported functions...\n", nFunc); + if ( funcNidTable != NULL && funcTable != NULL ) { + for ( int i = 0; i < nFunc; ++i ) { + const char *resolvedNid; + + ea_t nidOffset = funcNidTable + (i * 4); + ea_t funcOffset = funcTable + (i * 4); + + uint32 nid = get_long(nidOffset); + uint32 func = get_long(funcOffset); + + resolvedNid = getNameFromDatabase(libName, nid); + if ( resolvedNid ) { + set_cmt(nidOffset, resolvedNid, false); + qsnprintf(symName, MAXNAMELEN, "%s.stub_entry", resolvedNid); + do_name_anyway(funcOffset, symName); + qsnprintf(symName, MAXNAMELEN, ".%s", resolvedNid); + do_name_anyway(func, symName); + } + + //msg("doDwrd: %08x\n", nidOffset); + //msg("doDwrd: %08x\n", funcOffset); + doDwrd(nidOffset, 4); // nid + doDwrd(funcOffset, 4); // func + if ( add_func(func, BADADDR) ) { + get_func(func)->flags |= FUNC_LIB; + //add_entry(func, func, ...) + } + } + } + + //msg("Processing exported variables...\n"); + if ( varNidTable != NULL && varTable ) { + for ( int i = 0; i < nVar; ++i ) { + const char *resolvedNid; + + ea_t nidOffset = varNidTable + (i * 4); + ea_t varOffset = varTable + (i * 4); + + uint32 nid = get_long(nidOffset); + uint32 func = get_long(varOffset); + + resolvedNid = getNameFromDatabase(libName, nid); + if ( resolvedNid ) { + set_cmt(nidOffset, resolvedNid, false); + do_name_anyway(varOffset, resolvedNid); + } + + //msg("doDwrd: %08x\n", nidOffset); + //msg("doDwrd: %08x\n", varOffset); + doDwrd(nidOffset, 4); + doDwrd(varOffset, 4); + } + } + + //msg("Processing exported TLS variables...\n"); + if ( tlsNidTable != NULL && tlsTable != NULL ) { + for ( int i = 0; i < nVar; ++i ) { + const char *resolvedNid; + + ea_t nidOffset = tlsNidTable + (i * 4); + ea_t tlsOffset = tlsTable + (i * 4); + + uint32 nid = get_long(nidOffset); + uint32 func = get_long(tlsOffset); + + resolvedNid = getNameFromDatabase(libName, nid); + if ( resolvedNid ) { + set_cmt(nidOffset, resolvedNid, false); + do_name_anyway(tlsOffset, resolvedNid); + } + + //msg("doDwrd: %08x\n", nidOffset); + //msg("doDwrd: %08x\n", tlsOffset); + doDwrd(nidOffset, 4); + doDwrd(tlsOffset, 4); + } + } + } else { + msg("Unknown import structure at %08x.\n", ea); + continue; + } + } +} + +const char *cell_loader::getNameFromDatabase( + const char *library, unsigned int nid) { + auto header = m_database.FirstChildElement(); + + if ( header ) { + auto group = header->FirstChildElement(); + if ( group ) { + // find library in xml + do { + if ( !strcmp(library, group->Attribute("name")) ) { + auto entry = group->FirstChildElement(); + if ( entry ) { + // find NID in library group + do { + if ( strtoul(entry->Attribute("id"),0,0) == nid ) + return entry->Attribute("name"); + } while ( entry = entry->NextSiblingElement() ); + } + } + } while ( group = group->NextSiblingElement() ); + } + } + + return nullptr; +} + +void cell_loader::applyModuleInfo() { + auto firstSegment = m_elf->getSegments()[0]; + + ea_t modInfoEa = (firstSegment.p_vaddr + m_relocAddr) + + (firstSegment.p_paddr - firstSegment.p_offset); + + tid_t tid = get_struc_id("_scemoduleinfo"); + doStruct(modInfoEa, sizeof(_scemoduleinfo_ppu32), tid); + + loadExports( get_long(modInfoEa + offsetof(_scemoduleinfo_ppu32, ent_top)), + get_long(modInfoEa + offsetof(_scemoduleinfo_ppu32, ent_end)) ); + + loadImports( get_long(modInfoEa + offsetof(_scemoduleinfo_ppu32, stub_top)), + get_long(modInfoEa + offsetof(_scemoduleinfo_ppu32, stub_end)) ); + + add_entry(0, modInfoEa, "module_info", false); + +} + +void cell_loader::applyProcessInfo() { + for ( auto segment : m_elf->getSegments() ) { + if ( segment.p_type == PT_PROC_PARAM ) { + tid_t tid = get_struc_id("sys_process_param_t"); + doStruct(segment.p_vaddr, sizeof(sys_process_param_t), tid); + } else if ( segment.p_type == PT_PROC_PRX ) { + tid_t tid = get_struc_id("sys_process_prx_info_t"); + doStruct(segment.p_vaddr, sizeof(sys_process_prx_info_t), tid); + + loadExports( get_long(segment.p_vaddr + offsetof(sys_process_prx_info_t, libent_start)), + get_long(segment.p_vaddr + offsetof(sys_process_prx_info_t, libent_end)) ); + + loadImports( get_long(segment.p_vaddr + offsetof(sys_process_prx_info_t, libstub_start)), + get_long(segment.p_vaddr + offsetof(sys_process_prx_info_t, libstub_end)) ); + } + } +} + +void cell_loader::swapSymbols() { + // Since section based relocations depend on symbols + // we need to swap symbols before we get to relocations. + // Pretty much only for 0.85 PRX's but we still need to + // swap them anyway. + auto section = m_elf->getSymbolsSection(); + + if (section == NULL) + return; + + //msg("Swapping symbols...\n"); + + auto symbols = m_elf->getSymbols(); + + for ( size_t i = 0; i < m_elf->getNumSymbols(); ++i ) { + auto symbol = &symbols[i]; + + swap(symbol->st_name); + swap(symbol->st_shndx); + swap(symbol->st_size); + swap(symbol->st_value); + } +} + +void cell_loader::applySymbols() { + auto section = m_elf->getSymbolsSection(); + + if (section == NULL) + return; + + msg("Applying symbols...\n"); + + auto nsym = m_elf->getNumSymbols(); + auto symbols = m_elf->getSymbols(); + + const char *stringTable = m_elf->getSections().at(section->sh_link).data(); + + for ( size_t i = 0; i < nsym; ++i ) { + auto &symbol = symbols[i]; + + auto type = ELF64_ST_TYPE(symbol.st_info), + bind = ELF64_ST_BIND(symbol.st_info); + auto value = symbol.st_value; + + //msg("st_name: %08x\n", symbol.st_name); + //msg("st_type: %08x\n", type); + //msg("st_bind: %08x\n", bind); + + if ( symbol.st_shndx > m_elf->getNumSections() || + !(m_elf->getSections()[ symbol.st_shndx ].sh_flags & SHF_ALLOC) ) + continue; + + if ( symbol.st_shndx == SHN_ABS ) + continue; + + if ( isLoadingPrx() ) + value += m_elf->getSections()[ symbol.st_shndx ].sh_addr + m_relocAddr; + + switch ( type ) { + case STT_OBJECT: + do_name_anyway(value, &stringTable[ symbol.st_name ]); + break; + case STT_FILE: + describe(value, true, "Source File: %s", &stringTable[ symbol.st_name ]); + break; + case STT_FUNC: + do_name_anyway(value, &stringTable[ symbol.st_name ]); + auto_make_proc(value); + break; + default: + break; + } + } +} + +void cell_loader::declareStructures() { + struc_t *sptr; + + // offset type + typeinfo_t ot; + ot.ri.flags = REF_OFF32; + ot.ri.target = BADADDR; + ot.ri.base = 0; + ot.ri.tdelta = 0; + + tid_t modInfoCommon = add_struc(BADADDR, "_scemoduleinfo_common"); + sptr = get_struc(modInfoCommon); + if ( sptr != NULL ) { + add_struc_member(sptr, "modattribute", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "modversion", BADADDR, byteflag(), NULL, 2); + add_struc_member(sptr, "modname", BADADDR, byteflag(), NULL, SYS_MODULE_NAME_LEN); + add_struc_member(sptr, "terminal", BADADDR, byteflag(), NULL, 1); + + sptr = get_struc(add_struc(BADADDR, "_scemoduleinfo")); + if ( sptr != NULL ) { + typeinfo_t mt; + mt.tid = modInfoCommon; + add_struc_member(sptr, "c", BADADDR, struflag(), &mt, get_struc_size(mt.tid)); + + add_struc_member(sptr, "gp_value", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "ent_top", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "ent_end", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "stub_top", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "stub_end", BADADDR, offflag() | dwrdflag(), &ot, 4); + } + } + + tid_t libStubCommon = add_struc(BADADDR, "_scelibstub_ppu_common"); + sptr = get_struc(libStubCommon); + if ( sptr != NULL ) { + add_struc_member(sptr, "structsize", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "reserved1", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "version", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "attribute", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "nfunc", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "nvar", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "ntlsvar", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "reserved2", BADADDR, byteflag(), NULL, 4); + + sptr = get_struc(add_struc(BADADDR, "_scelibstub_ppu32")); + if ( sptr != NULL ) { + typeinfo_t mt; + mt.tid = libStubCommon; + add_struc_member(sptr, "c", BADADDR, struflag(), &mt, get_struc_size(mt.tid)); + + add_struc_member(sptr, "libname", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "func_nidtable", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "func_table", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "var_nidtable", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "var_table", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "tls_nidtable", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "tls_table", BADADDR, offflag() | dwrdflag(), &ot, 4); + } + } + + tid_t libEntCommon = add_struc(BADADDR, "_scelibent_ppu_common"); + sptr = get_struc(libEntCommon); + if ( sptr != NULL ) { + add_struc_member(sptr, "structsize", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "reserved1", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "version", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "attribute", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "nfunc", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "nvar", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "ntlsvar", BADADDR, wordflag(), NULL, 2); + add_struc_member(sptr, "hashinfo", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "hashinfotls", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "reserved2", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "nidaltsets", BADADDR, byteflag(), NULL, 1); + + sptr = get_struc(add_struc(BADADDR, "_scelibent_ppu32")); + if ( sptr != NULL ) { + typeinfo_t mt; + mt.tid = libEntCommon; + add_struc_member(sptr, "c", BADADDR, struflag(), &mt, get_struc_size(mt.tid)); + + add_struc_member(sptr, "libname", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "nidtable", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "addtable", BADADDR, offflag() | dwrdflag(), &ot, 4); + } + } + + tid_t procParamInfo = add_struc(BADADDR, "sys_process_param_t"); + sptr = get_struc(procParamInfo); + if ( sptr != NULL ) { + add_struc_member(sptr, "size", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "magic", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "version", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "sdk_version", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "primary_prio", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "primary_stacksize", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "malloc_pagesize", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "ppc_seg", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "crash_dump_param_addr", BADADDR, dwrdflag(), NULL, 4); + } + + tid_t procPrxInfo = add_struc(BADADDR, "sys_process_prx_info_t"); + sptr = get_struc(procPrxInfo); + if ( sptr != NULL ) { + add_struc_member(sptr, "size", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "magic", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "version", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "sdk_version", BADADDR, dwrdflag(), NULL, 4); + add_struc_member(sptr, "libent_start", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "libent_end", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "libstub_start", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "libstub_end", BADADDR, offflag() | dwrdflag(), &ot, 4); + add_struc_member(sptr, "major_version", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "minor_version", BADADDR, byteflag(), NULL, 1); + add_struc_member(sptr, "reserved", BADADDR, byteflag(), NULL, 6); + } +} |
