From ce887d66a761c7b84ba8011d8bc47e3c83bb5488 Mon Sep 17 00:00:00 2001 From: pixel Date: Fri, 2 Dec 2005 11:28:26 +0000 Subject: Adding PSx-Patcher to the tree. --- MSVC/.cvsignore | 2 + MSVC/PSX-Bundle.sln | 14 +- MSVC/PSx-Patcher/.cvsignore | 2 + MSVC/PSx-Patcher/PSx-Patcher.vcproj | 181 ++++++++ includes/binary-elf.h | 98 +++++ includes/binary.h | 226 ++++++++++ includes/binwriter-elf.h | 32 ++ includes/binwriter.h | 44 ++ lib/binary-elf.cpp | 436 +++++++++++++++++++ lib/binary.cpp | 835 ++++++++++++++++++++++++++++++++++++ lib/binwriter-elf.cpp | 144 +++++++ lib/binwriter.cpp | 189 ++++++++ 12 files changed, 2201 insertions(+), 2 deletions(-) create mode 100644 MSVC/.cvsignore create mode 100644 MSVC/PSx-Patcher/.cvsignore create mode 100644 MSVC/PSx-Patcher/PSx-Patcher.vcproj create mode 100644 includes/binary-elf.h create mode 100644 includes/binary.h create mode 100644 includes/binwriter-elf.h create mode 100644 includes/binwriter.h create mode 100644 lib/binary-elf.cpp create mode 100644 lib/binary.cpp create mode 100644 lib/binwriter-elf.cpp create mode 100644 lib/binwriter.cpp diff --git a/MSVC/.cvsignore b/MSVC/.cvsignore new file mode 100644 index 0000000..d3f7d63 --- /dev/null +++ b/MSVC/.cvsignore @@ -0,0 +1,2 @@ +release +debug \ No newline at end of file diff --git a/MSVC/PSX-Bundle.sln b/MSVC/PSX-Bundle.sln index c59fb5a..4f2ba4a 100644 --- a/MSVC/PSX-Bundle.sln +++ b/MSVC/PSX-Bundle.sln @@ -20,11 +20,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CD-Tool", "CD-Tool\CD-Tool. EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dalos", "Dalos\Dalos.vcproj", "{CDCBA663-BC45-4C3B-87EC-3F684CFF25A8}" + ProjectSection(ProjectDependencies) = postProject + {937F3AE7-03E9-4EF5-8B59-CAB1DD6C5C58} = {937F3AE7-03E9-4EF5-8B59-CAB1DD6C5C58} + {4C08E5A7-AE14-4454-A64B-8D1A24362B87} = {4C08E5A7-AE14-4454-A64B-8D1A24362B87} + {A7C52E48-947F-4B84-84F8-B2BD1314C9B4} = {A7C52E48-947F-4B84-84F8-B2BD1314C9B4} + {BEAF9E07-6592-49AC-9DA5-0B47FAB88C96} = {BEAF9E07-6592-49AC-9DA5-0B47FAB88C96} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PSx-Patcher", "PSx-Patcher\PSx-Patcher.vcproj", "{15A91021-E932-427B-9A6F-731AFBA8928B}" ProjectSection(ProjectDependencies) = postProject {BEAF9E07-6592-49AC-9DA5-0B47FAB88C96} = {BEAF9E07-6592-49AC-9DA5-0B47FAB88C96} {A7C52E48-947F-4B84-84F8-B2BD1314C9B4} = {A7C52E48-947F-4B84-84F8-B2BD1314C9B4} - {4C08E5A7-AE14-4454-A64B-8D1A24362B87} = {4C08E5A7-AE14-4454-A64B-8D1A24362B87} - {937F3AE7-03E9-4EF5-8B59-CAB1DD6C5C58} = {937F3AE7-03E9-4EF5-8B59-CAB1DD6C5C58} EndProjectSection EndProject Global @@ -53,6 +59,10 @@ Global {CDCBA663-BC45-4C3B-87EC-3F684CFF25A8}.Debug|Win32.Build.0 = Debug|Win32 {CDCBA663-BC45-4C3B-87EC-3F684CFF25A8}.Release|Win32.ActiveCfg = Release|Win32 {CDCBA663-BC45-4C3B-87EC-3F684CFF25A8}.Release|Win32.Build.0 = Release|Win32 + {15A91021-E932-427B-9A6F-731AFBA8928B}.Debug|Win32.ActiveCfg = Debug|Win32 + {15A91021-E932-427B-9A6F-731AFBA8928B}.Debug|Win32.Build.0 = Debug|Win32 + {15A91021-E932-427B-9A6F-731AFBA8928B}.Release|Win32.ActiveCfg = Release|Win32 + {15A91021-E932-427B-9A6F-731AFBA8928B}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MSVC/PSx-Patcher/.cvsignore b/MSVC/PSx-Patcher/.cvsignore new file mode 100644 index 0000000..043d84f --- /dev/null +++ b/MSVC/PSx-Patcher/.cvsignore @@ -0,0 +1,2 @@ +Debug +Release \ No newline at end of file diff --git a/MSVC/PSx-Patcher/PSx-Patcher.vcproj b/MSVC/PSx-Patcher/PSx-Patcher.vcproj new file mode 100644 index 0000000..0b25121 --- /dev/null +++ b/MSVC/PSx-Patcher/PSx-Patcher.vcproj @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/includes/binary-elf.h b/includes/binary-elf.h new file mode 100644 index 0000000..f1ea14e --- /dev/null +++ b/includes/binary-elf.h @@ -0,0 +1,98 @@ +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2005 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: binary-elf.h,v 1.1 2005-12-02 11:28:26 pixel Exp $ */ + +#ifndef __BINARY_ELF_H__ +#define __BINARY_ELF_H__ + +#ifdef _MSC_VER +//do packing +#endif + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; + +#define PROGBITS 1 +#define NOBITS 8 +#define REL 9 +#define NOTYPE 0 +#define SECTION 3 +#define PT_LOAD 1 +#define PF_X 1 +#define PF_W 2 +#define PF_R 4 + +struct elf_header_t { + union { + u8 raw[16]; + struct e_ident_t { + u8 ei_magic[4]; + u8 ei_class; + u8 ei_data; + u8 ei_version; + } cook; + } e_ident; + u16 e_type; + u16 e_machine; + u32 e_version; + u32 e_entry; + u32 e_phoff; + u32 e_shoff; + u32 e_flags; + u16 e_ehsize; + u16 e_phentsize; + u16 e_phnum; + u16 e_shentsize; + u16 e_shnum; + u16 e_shstrndx; +} PACKED; + +struct elf_pheader_t { + u32 type; /* == 1, PT_LOAD (that is, this section will get loaded */ + u32 offset; /* offset in file, on a 4096 bytes boundary */ + u32 vaddr; /* virtual address where this section is loaded */ + u32 paddr; /* physical address where this section is loaded */ + u32 filesz; /* size of that section in the file */ + u32 memsz; /* size of that section in memory (rest is zero filled) */ + u32 flags; /* PF_X | PF_W | PF_R, that is executable, writable, readable */ + u32 align; /* == 0x1000 that is 4096 bytes */ +} PACKED; + + +struct elf_section_t { + u32 sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size; + u32 sh_link, sh_info, sh_addralign, sh_entsize; +} PACKED; + +struct elf_symbol_t { + u32 st_name, st_value, st_size; + u8 st_info, st_other; + u16 st_shndx; +} PACKED; + +struct elf_reloc_t { + u32 r_offset, r_info; +} PACKED; + +#endif diff --git a/includes/binary.h b/includes/binary.h new file mode 100644 index 0000000..576f7e8 --- /dev/null +++ b/includes/binary.h @@ -0,0 +1,226 @@ +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2005 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: binary.h,v 1.1 2005-12-02 11:28:26 pixel Exp $ */ +#ifndef __BINARY_H__ +#define __BINARY_H__ + +#define LOCAL 0 +#define GLOBAL 1 +#define WEAK 2 + +enum elf_mips_reloc_type { + R_MIPS_NONE = 0, + R_MIPS_16, + R_MIPS_32, + R_MIPS_REL32, + R_MIPS_26, + R_MIPS_HI16, + R_MIPS_LO16, + R_MIPS_GPREL16, + R_MIPS_LITERAL, + R_MIPS_GOT16, + R_MIPS_PC16, + R_MIPS_CALL16, + R_MIPS_GPREL32, + elf_mips_reloc_type_size +}; + +#include + +#include +#include +#include + +class Section; +class Export : public Base { + public: + Export(Section *, const String &, Uint32 offset, int bind); + ~Export(); + static Export * GetFirst(const Section * parent = 0); + Export * GetNext(const Section * parent = 0) const; + static Export * GetLast(const Section * parent = 0); + Export * GetPrev(const Section * parent = 0) const; + String GetName() const; + Uint32 get_offset() const; + bool is_absolute() const; + bool is_relative() const; + Uint32 get_absolute_offset() const; + static Export * find_export(const String &, int bind = -1); + Section * GetParent() const; + private: + Section * parent; + String name; + Uint32 offset; + int bind; + Export * next, * prev; + static Export * head; + static Export * tail; +}; +class Import : public Base { + public: + Import(Section *, const String &, Uint32 offset, int reloc); + ~Import(); + static Import * GetFirst(const Section * parent = 0); + Import * GetNext(const Section * parent = 0) const; + static Import * GetLast(const Section * parent = 0); + Import * GetPrev(const Section * parent = 0) const; + String GetName() const; + Uint32 get_offset() const; + bool is_absolute() const; + bool is_relative() const; + static void fix_relocs() throw (GeneralException); + Section * GetParent() const; + private: + Section * parent; + String name; + Uint32 offset; + int reloc; + Import * next, * prev; + static Import * head; + static Import * tail; +}; +class Internal : public Base { + public: + Internal(Section *, Section *, Uint32 offset, int reloc); + ~Internal(); + static Internal * GetFirst(const Section * parent = 0); + Internal * GetNext(const Section * parent = 0) const; + static Internal * GetLast(const Section * parent = 0); + Internal * GetPrev(const Section * parent = 0) const; + Section * getDest() const; + Uint32 get_offset() const; + bool is_absolute() const; + bool is_relative() const; + static void fix_relocs() throw (GeneralException); + Section * GetParent() const; + private: + Section * parent; + Section * dest; + Uint32 offset; + int reloc; + Internal * next, * prev; + static Internal * head; + static Internal * tail; +}; + +class Binary; +class Section : public Base { + public: + Section(Binary * parent, Uint32 size, Uint32 offset, bool bss = false) throw (GeneralException); + ~Section(); + char * get_bytes() const; + Uint32 get_size() const; + Uint32 get_offset() const; + Uint32 get_end_offset() const; + bool is_in(Uint32) const; + bool is_bss() const; + bool is_absolute() const; + bool is_relative() const; + Export * add_export(const String & name, Uint32 offset, int bind); + Import * add_import(const String & name, Uint32 offset, int reloc); + Internal * add_internal(Section *, Uint32 offset, int reloc); + static Section * GetFirst(const Binary * parent = 0); + Section * GetNext(const Binary * parent = 0) const; + static Section * GetLast(const Binary * parent = 0); + Section * GetPrev(const Binary * parent = 0) const; + Export * GetFirstExport() const; + Export * GetNextExport(const Export *) const; + Export * GetLastExport() const; + Export * GetPrevExport(const Export *) const; + Import * GetFirstImport() const; + Import * GetNextImport(const Import *) const; + Import * GetLastImport() const; + Import * GetPrevImport(const Import *) const; + Internal * GetFirstInternal() const; + Internal * GetNextInternal(const Internal *) const; + Internal * GetLastInternal() const; + Internal * GetPrevInternal(const Internal *) const; + static bool solve_constraints(); + void fix_reloc(Uint32 from, Uint32 to, int reloc); + Binary * GetParent() const; + private: + Export * find_export(const String &); + void solve_constraints_r(Section *); + Binary * parent; + Uint32 size, offset; + char * bytes; + Section * next, * prev; + static Section * head; + static Section * tail; +}; + +class Binary : public Base { + public: + Section * add_section(Uint32 size, Uint32 offset); + Section * add_bss(Uint32 size, Uint32 offset); + Section * GetFirstSection() const; + Section * GetNextSection(const Section *) const; + Section * GetLastSection() const; + Section * GetPrevSection(const Section *) const; + Export * add_export(const String & name, Uint32 offset, int bind) throw (GeneralException); + Uint32 getEntryPoint() const; + String GetName() const; + void loadSymbolMap(Handle * map); + void create_jhook(Uint32 from, Uint32 to, int size = 0); + void create_jhook(Uint32 from, const String & to, int size = 0); + void create_jhook(const String & from, Uint32 to, int size = 0); + void create_jhook(const String & from, const String & to, int size = 0); + void create_jalhook(Uint32 from, Uint32 to, int size = 0); + void create_jalhook(Uint32 from, const String & to, int size = 0); + void create_jalhook(const String & from, Uint32 to, int size = 0); + void create_jalhook(const String & from, const String & to, int size = 0); + protected: + Binary(const String &); + void setEntryPoint(Uint32); + private: + Section * create_hook(Uint32, int); + String name; + Binary * next, * prev; + static Binary * head; + static Binary * tail; + Uint32 EntryPoint; +}; + +class Binary_elf : public Binary { + public: + Binary_elf(Handle * elf) throw (GeneralException); +}; + +#ifdef s_addr +#undef s_addr +#endif + +struct psyq_header_t { + struct psyq_details_t { + Uint8 id[8]; + Uint32 text, data, pc0, gp0, t_addr, t_size; + Uint32 d_addr, d_size, b_addr, b_size, s_addr, s_size; + Uint32 sp, fp, gp, ra, s0; + } details; + Uint8 psyqhead[0x800]; +}; + +class Binary_psexe : public Binary { + public: + Binary_psexe(Handle * psexe) throw (GeneralException); + static struct psyq_header_t header; +}; + +#endif diff --git a/includes/binwriter-elf.h b/includes/binwriter-elf.h new file mode 100644 index 0000000..e3f0bae --- /dev/null +++ b/includes/binwriter-elf.h @@ -0,0 +1,32 @@ +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2005 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: binwriter-elf.h,v 1.1 2005-12-02 11:28:27 pixel Exp $ */ + +#ifndef __BINWRITER_ELF_H__ +#define __BINWRITER_ELF_H__ + +#include + +class BinWriter_elf : public BinWriter { + public: + virtual void dump(Handle *); +}; + +#endif diff --git a/includes/binwriter.h b/includes/binwriter.h new file mode 100644 index 0000000..1e73ac0 --- /dev/null +++ b/includes/binwriter.h @@ -0,0 +1,44 @@ +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2005 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: binwriter.h,v 1.1 2005-12-02 11:28:27 pixel Exp $ */ + +#ifndef __BINWRITER_H__ +#define __BINWRITER_H__ + +#include +#include +#include +#include + +struct SectionOut { + char * data; + Uint32 base, real_size, whole_size; +}; + +class BinWriter : public Base { + public: + void merge(); + virtual void dump(Handle *) = 0; + protected: + Uint32 epc; + std::vector sections; +}; + +#endif diff --git a/lib/binary-elf.cpp b/lib/binary-elf.cpp new file mode 100644 index 0000000..a1ea831 --- /dev/null +++ b/lib/binary-elf.cpp @@ -0,0 +1,436 @@ +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2005 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: binary-elf.cpp,v 1.1 2005-12-02 11:28:27 pixel Exp $ */ + +#include +#include "binary.h" +#include "binary-elf.h" + +#ifdef WORDS_BIGENDIAN +static void sw32(u32 & x) { + x = (x >> 24) | ((x >> 8) & 0x0000ff00) | ((x << 8) & 0x00ff0000) | (x << 24); +} +static void sw16(u16 & x) { + x = (x >> 8) | ((x << 8); +} +#else +#define sw32(x) while(0) +#define sw16(x) while(0) +#endif + +static String elf_classes[] = { + "Invalid class", + "32-bit objects", + "64-bit objects", +}; + +static String elf_encodings[] = { + "Invalid encoding", + "Little endian", + "Big endian", +}; + +static String elf_types[] = { + "No file type", + "Relocatable file", + "Executable file", + "Shared object file", + "Core file", +}; + +static String elf_machines[] = { + "No machine", + "AT&T WE 32100", + "SPARC", + "Intel Architecture", + "Motorola 68000", + "Motorola 88000", + "Intel 80860", + "MIPS RS3000 Big-Endian", + "MIPS RS4000 Big-Endian", +}; + +static String section_types[] = { + "Null", + "Progbits", + "Symtab", + "Strtab", + "Rela", + "Hash", + "Dynamic", + "Note", + "Nobits", + "Rel", + "Shlib", + "Dynsym", +}; + +static String section_flags[] = { + "---", + "--W", + "-R-", + "-RW", + "X--", + "X-W", + "XR-", + "XRW", +}; + +static String symbol_types[] = { + "NoType", + "Object", + "Func", + "Section", + "File", + "?? (5)", + "?? (6)", + "?? (7)", + "?? (8)", + "?? (9)", + "?? (10)", + "?? (11)", + "?? (12)", + "LoProc", + "?? (14)", + "HiProc", +}; + +static String binding_types[] = { + "Local", + "Global", + "Weak", + "?? (3)", + "?? (4)", + "?? (5)", + "?? (6)", + "?? (7)", + "?? (8)", + "?? (9)", + "?? (10)", + "?? (11)", + "?? (12)", + "LoProc", + "?? (14)", + "HiProc", +}; + +static String reloc_types[] = { + "R_MIPS_NONE", + "R_MIPS_16", + "R_MIPS_32", + "R_MIPS_REL32", + "R_MIPS_26", + "R_MIPS_HI16", + "R_MIPS_LO16", + "R_MIPS_GPREL16", + "R_MIPS_LITERAL", + "R_MIPS_GOT16", + "R_MIPS_PC16", + "R_MIPS_CALL16", + "R_MIPS_GPREL32" +}; + +struct elf_header_t read_elf_header(Handle * elf) throw (GeneralException) { + struct elf_header_t eh; + u8 * magic; + + elf->read(&eh, sizeof(eh)); + + magic = eh.e_ident.cook.ei_magic; + + if ((magic[0] != 0x7f) || (magic[1] != 'E') || (magic[2] != 'L') || (magic[3] != 'F')) + throw GeneralException("Not an ELF file."); + sw16(eh.e_type); + sw16(eh.e_machine); + sw32(eh.e_version); + sw32(eh.e_entry); + sw32(eh.e_phoff); + sw32(eh.e_shoff); + sw32(eh.e_flags); + sw16(eh.e_ehsize); + sw16(eh.e_phentsize); + sw16(eh.e_phnum); + sw16(eh.e_shentsize); + sw16(eh.e_shnum); + sw16(eh.e_shstrndx); + + return eh; +} + +struct elf_section_t read_elf_section(Handle * elf) { + struct elf_section_t es; + + elf->read(&es, sizeof(es)); + + sw32(es.sh_name); + sw32(es.sh_type); + sw32(es.sh_flags); + sw32(es.sh_addr); + sw32(es.sh_offset); + sw32(es.sh_size); + sw32(es.sh_link); + sw32(es.sh_info); + sw32(es.sh_addralign); + sw32(es.sh_entsize); + + return es; +} + +struct elf_symbol_t read_elf_symbol(Handle * elf) { + struct elf_symbol_t es; + + elf->read(&es, sizeof(es)); + + sw32(es.st_name); + sw32(es.st_value); + sw32(es.st_size); + sw16(es.st_shndx); + + return es; +} + +struct elf_reloc_t read_elf_reloc(Handle * elf) { + struct elf_reloc_t er; + + elf->read(&er, sizeof(er)); + + sw32(er.r_offset); + sw32(er.r_info); + + return er; +} + +Binary_elf::Binary_elf(Handle * elf) throw (GeneralException) : Binary(elf->GetName()) { + int i, j; + + struct elf_header_t head; + struct elf_section_t * sec = 0; + char * names = 0, * strtab_names = 0; + int symtab = 0, strtab = 0, linked_strtab = 0; + struct elf_symbol_t * sym = 0; + struct elf_reloc_t reloc; + + verbosity = M_INFO; + + printm(M_INFO, "Loading elf file '" + elf->GetName() + "'\n"); + + head = read_elf_header(elf); + + printm(M_INFO, "ELF Class : " + elf_classes[head.e_ident.cook.ei_class] + "\n"); + printm(M_INFO, "Data encoding: " + elf_encodings[head.e_ident.cook.ei_data] + "\n"); + printm(M_INFO, "Elf version : %i\n", head.e_ident.cook.ei_version); + if (head.e_type == 0xffff) { + printm(M_INFO, "Object type : Processor specific (hi)\n"); + } else if (head.e_type == 0xff00) { + printm(M_INFO, "Object type : Processor specific (lo)\n"); + } else { + printm(M_INFO, "Object type : " + elf_types[head.e_type] + "\n"); + } + printm(M_INFO, "Machine type : " + elf_machines[head.e_machine] + "\n"); + printm(M_INFO, "Object ver. : %i\n", head.e_version); + printm(M_INFO, "Elf entry : %08X\n", head.e_entry); + printm(M_INFO, "PH offset : %08X\n", head.e_phoff); + printm(M_INFO, "SH offset : %08X\n", head.e_shoff); + printm(M_INFO, "Flags : %08X\n", head.e_flags); + printm(M_INFO, "Header size : %04X\n", head.e_ehsize); + printm(M_INFO, "PH ent. size : %04X\n", head.e_phentsize); + printm(M_INFO, "PH number : %04X\n", head.e_phnum); + printm(M_INFO, "SH ent. size : %04X\n", head.e_shentsize); + printm(M_INFO, "SH number : %04X\n", head.e_shnum); + printm(M_INFO, "SH str index : %04X\n", head.e_shstrndx); + + setEntryPoint(head.e_entry); + + if (sizeof(struct elf_section_t) != head.e_shentsize) + throw GeneralException("Inconsistancy in section table entries."); + + sec = (struct elf_section_t *) malloc(sizeof(struct elf_section_t) * head.e_shnum); + elf->seek(head.e_shoff); + for (i = 0; i < head.e_shnum; i++) + sec[i] = read_elf_section(elf); + + if (sec[head.e_shstrndx].sh_size != 0) { + names = (char *) malloc(sec[head.e_shstrndx].sh_size); + elf->seek(sec[head.e_shstrndx].sh_offset); + elf->read(names, sec[head.e_shstrndx].sh_size); + } else { + // no section table names... huh... ? Most probably a quite bugged .elf file. + throw GeneralException("No section table name."); + } + + std::vector
section_ptrs; + section_ptrs.push_back(0); + + printm(M_INFO, "##: type flags address offset size link info align entsize name\n"); + for (i = 1; i < head.e_shnum; i++) { + if (!strcmp(names + sec[i].sh_name, ".symtab")) { + symtab = i; + linked_strtab = sec[i].sh_link; + } else if (!strcmp(names + sec[i].sh_name, ".strtab")) { + strtab = i; + } + + printm(M_INFO, "%2i: ", i); + if (sec[i].sh_type <= 0xff) { + printm(-M_INFO, "%-8s ", section_types[sec[i].sh_type].to_charp()); + } else if (sec[i].sh_type == 0x70000006) { + printm(-M_INFO, "Reginfo "); + } else { + printm(-M_INFO, "UNKNOW "); + } + + printm(-M_INFO, "%3s ", section_flags[sec[i].sh_flags & 7].to_charp()); + printm(-M_INFO, "%08X ", sec[i].sh_addr); + printm(-M_INFO, "%08X ", sec[i].sh_offset); + printm(-M_INFO, "%08X ", sec[i].sh_size); + printm(-M_INFO, "%5i ", sec[i].sh_link); + printm(-M_INFO, "%5i ", sec[i].sh_info); + printm(-M_INFO, "%5i ", sec[i].sh_addralign); + printm(-M_INFO, "%5i ", sec[i].sh_entsize); + printm(-M_INFO, "%s\n", names + sec[i].sh_name); + + section_ptrs.push_back(0); + + if (sec[i].sh_size == 0) + continue; + + if (!strcmp(names + sec[i].sh_name, ".comment")) // crude hack, but, well... + continue; + + switch (sec[i].sh_type) { + case PROGBITS: + printm(M_INFO, "Adding %i bytes from offset %i at address %i.\n", sec[i].sh_size, sec[i].sh_offset, sec[i].sh_addr); + elf->seek(sec[i].sh_offset); + elf->read((section_ptrs[i] = add_section(sec[i].sh_size, sec[i].sh_addr))->get_bytes(), sec[i].sh_size); + break; + case NOBITS: + printm(M_INFO, "Adding %i bytes at address %i.\n", sec[i].sh_size, sec[i].sh_addr); + section_ptrs[i] = add_bss(sec[i].sh_size, sec[i].sh_addr); + break; + } + } + + if (symtab) { + printm(M_INFO, "Discovered symtab = %i\n", symtab); + } else { + printm(M_INFO, "No symbol table.\n"); + } + + if (strtab) { + printm(M_INFO, "Discovered strtab = %i\n", strtab); + } else { + printm(M_INFO, "No string table.\n"); + } + + if (strtab != linked_strtab) { + throw GeneralException(String("Warning, inconsistancy: strtab != symtab.sh_link ") + strtab + " != " + linked_strtab + ")\n"); + } + + if (symtab) + if (sizeof(struct elf_symbol_t) != sec[symtab].sh_entsize) + throw GeneralException("Symbol entries not consistant.\n"); + + if ((symtab ? 1 : 0) ^ (strtab ? 1 : 0)) { + throw GeneralException(String("Inconsistancy: symtab is") + (symtab ? "" : "n't") + " available, while strtab is" + (strtab ? "" : "n't") + "."); + } + + if (!strtab) { + if (sec) + free(sec); + + if (names) + free(names); + + return; + } + + strtab_names = (char *) malloc(sec[strtab].sh_size); + elf->seek(sec[strtab].sh_offset); + elf->read(strtab_names, sec[strtab].sh_size); + + sym = (struct elf_symbol_t *) malloc(sec[symtab].sh_size); + elf->seek(sec[symtab].sh_offset); + for (i = 0; i < sec[symtab].sh_size / sec[symtab].sh_entsize; i++) + sym[i] = read_elf_symbol(elf); + + printm(M_INFO, " Num: Value Size Type Bind Ndx Name\n"); + for (i = 0; i < sec[symtab].sh_size / sec[symtab].sh_entsize; i++) { + if (((sym[i].st_info >> 4) == GLOBAL) || ((sym[i].st_info >> 4) == WEAK)) { + if ((sym[i].st_info & 15) != NOTYPE) { + printm(M_INFO, "Export symbol (section %i):\n", sym[i].st_shndx); + section_ptrs[sym[i].st_shndx]->add_export(strtab_names + sym[i].st_name, sym[i].st_value - sec[sym[i].st_shndx].sh_addr, sym[i].st_info >> 4); + } + } + + printm(M_INFO, "%6i: %08X %08X %-7s %-6s %6i %-10s : %s\n", i, + sym[i].st_value, sym[i].st_size, symbol_types[sym[i].st_info & 15].to_charp(), + binding_types[sym[i].st_info >> 4].to_charp(), sym[i].st_shndx, + sym[i].st_name ? strtab_names + sym[i].st_name : "(null)", + sym[i].st_shndx ? names + sec[sym[i].st_shndx].sh_name : "(null)"); + } + + for (i = 0; i < head.e_shnum; i++) { + if (sec[i].sh_type != REL) + continue; + printm(M_INFO, "Section %i (%s) contains relocations for section %i (%s):\n", + i, names + sec[i].sh_name, sec[i].sh_info, names + sec[sec[i].sh_info].sh_name); + + if (sec[i].sh_entsize != sizeof(struct elf_reloc_t)) + throw GeneralException("Warning: inconsistancy in relocation table.\n"); + + elf->seek(sec[i].sh_offset); + + printm(M_INFO, " Num: Offset Type Symbol\n"); + + for (j = 0; j < (sec[i].sh_size / sec[i].sh_entsize); j++) { + int sym_n; + + reloc = read_elf_reloc(elf); + + sym_n = reloc.r_info >> 8; + printm(M_INFO, "%6i: %08X %-14s %3i: ", j, reloc.r_offset, reloc_types[reloc.r_info & 255].to_charp(), sym_n); + + switch(sym[sym_n].st_info & 15) { + case NOTYPE: + printm(-M_INFO, "external symbol reloc to symbol %s\n", strtab_names + sym[sym_n].st_name); + section_ptrs[sec[i].sh_info]->add_import(strtab_names + sym[sym_n].st_name, reloc.r_offset, reloc.r_info & 255); + break; + case SECTION: + printm(-M_INFO, "internal section reloc to section %i (%s)\n", sym[sym_n].st_shndx, names + sec[sym[sym_n].st_shndx].sh_name); + section_ptrs[sec[i].sh_info]->add_internal(section_ptrs[sym[sym_n].st_shndx], reloc.r_offset, reloc.r_info & 255); + break; + default: + throw GeneralException("Internal relocation symbol. Bug inside."); + } + } + } + + if (sec) + free(sec); + + if (names) + free(names); + + if (strtab_names) + free(strtab_names); + + if (sym) + free(sym); +} diff --git a/lib/binary.cpp b/lib/binary.cpp new file mode 100644 index 0000000..0a4922f --- /dev/null +++ b/lib/binary.cpp @@ -0,0 +1,835 @@ +/* +* PSX-Tools Bundle Pack +* Copyright (C) 2002-2005 Nicolas "Pixel" Noble +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* $Id: binary.cpp,v 1.1 2005-12-02 11:28:27 pixel Exp $ */ + +#include "binary.h" + +Export * Export::head = 0; +Export * Export::tail = 0; +Export::Export(Section * _parent, const String & _name, Uint32 _offset, int _bind) : parent(_parent), name(_name), offset(_offset), bind(_bind) { + if (tail) { + next = 0; + prev = tail; + prev->next = tail = this; + } else { + head = tail = this; + next = prev = 0; + } +} +Export::~Export() { + if (next) { + next->prev = prev; + } else { + tail = prev; + } + + if (prev) { + prev->next = next; + } else { + head = next; + } +} + +Export * Export::GetFirst(const Section * _parent) { + if (!head) + return 0; + + if (_parent) + if (head->parent != _parent) + return head->GetNext(_parent); + + return head; +} + +Export * Export::GetNext(const Section * _parent) const { + if (!next) + return 0; + + if (_parent) + if (next->parent != _parent) + return next->GetNext(_parent); + + return next; +} + +Export * Export::GetLast(const Section * _parent) { + if (!tail) + return 0; + + if (_parent) + if (tail->parent != _parent) + return tail->GetPrev(_parent); + + return tail; +} + +Export * Export::GetPrev(const Section * _parent) const { + if (!prev) + return 0; + + if (_parent) + if (prev->parent != _parent) + return prev->GetPrev(_parent); + + return prev; +} + +bool Export::is_absolute() const { + return !is_relative(); +} + +bool Export::is_relative() const { + return parent->is_relative(); +} + +String Export::GetName() const { + return name; +} + +Uint32 Export::get_offset() const { + return offset; +} + +Export * Export::find_export(const String & name, int bind) { + Export * ptr; + + for (ptr = GetFirst(); ptr; ptr = ptr->GetNext()) { + if ((ptr->GetName() == name) && ((bind < 0) || (ptr->bind == bind))) + return ptr; + } + + return 0; +} + +Section * Export::GetParent() const { + return parent; +} + +Uint32 Export::get_absolute_offset() const { + return get_offset() + GetParent()->get_offset(); +} + +Import * Import::head = 0; +Import * Import::tail = 0; +Import::Import(Section * _parent, const String & _name, Uint32 _offset, int _reloc) : parent(_parent), name(_name), offset(_offset), reloc(_reloc) { + if (tail) { + next = 0; + prev = tail; + prev->next = tail = this; + } else { + head = tail = this; + next = prev = 0; + } +} +Import::~Import() { + if (next) { + next->prev = prev; + } else { + tail = prev; + } + + if (prev) { + prev->next = next; + } else { + head = next; + } +} + +Import * Import::GetFirst(const Section * _parent) { + if (!head) + return 0; + + if (_parent) + if (head->parent != _parent) + return head->GetNext(_parent); + + return head; +} + +Import * Import::GetNext(const Section * _parent) const { + if (!next) + return 0; + + if (_parent) + if (next->parent != _parent) + return next->GetNext(_parent); + + return next; +} + +Import * Import::GetLast(const Section * _parent) { + if (!tail) + return 0; + + if (_parent) + if (tail->parent != _parent) + return tail->GetPrev(_parent); + + return tail; +} + +Import * Import::GetPrev(const Section * _parent) const { + if (!prev) + return 0; + + if (_parent) + if (prev->parent != _parent) + return prev->GetPrev(_parent); + + return prev; +} + +bool Import::is_absolute() const { + return !is_relative(); +} + +bool Import::is_relative() const { + return parent->is_relative(); +} + +String Import::GetName() const { + return name; +} + +Uint32 Import::get_offset() const { + return offset; +} + +void Import::fix_relocs() throw (GeneralException) { + Import * imp; + Export * exp; + + for (imp = GetFirst(); imp; imp = imp->GetNext()) { + if (!(exp = Export::find_export(imp->GetName(), GLOBAL))) + if (!(exp = Export::find_export(imp->GetName(), WEAK))) + throw GeneralException("Couldn't find export symbol to solve import " + imp->GetName() + " in module " + imp->GetParent()->GetParent()->GetName()); + + if (!exp->is_absolute()) + throw GeneralException("Relocation fixing can't be done until all sections are constrained."); + + imp->GetParent()->fix_reloc(imp->get_offset(), exp->get_absolute_offset(), imp->reloc); + } +} + +Section * Import::GetParent() const { + return parent; +} + +Internal * Internal::head = 0; +Internal * Internal::tail = 0; +Internal::Internal(Section * _parent, Section * _dest, Uint32 _offset, int _reloc) : parent(_parent), dest(_dest), offset(_offset), reloc(_reloc) { + if (tail) { + next = 0; + prev = tail; + prev->next = tail = this; + } else { + head = tail = this; + next = prev = 0; + } +} +Internal::~Internal() { + if (next) { + next->prev = prev; + } else { + tail = prev; + } + + if (prev) { + prev->next = next; + } else { + head = next; + } +} + +Internal * Internal::GetFirst(const Section * _parent) { + if (!head) + return 0; + + if (_parent) + if (head->parent != _parent) + return head->GetNext(_parent); + + return head; +} + +Internal * Internal::GetNext(const Section * _parent) const { + if (!next) + return 0; + + if (_parent) + if (next->parent != _parent) + return next->GetNext(_parent); + + return next; +} + +Internal * Internal::GetLast(const Section * _parent) { + if (!tail) + return 0; + + if (_parent) + if (tail->parent != _parent) + return tail->GetPrev(_parent); + + return tail; +} + +Internal * Internal::GetPrev(const Section * _parent) const { + if (!prev) + return 0; + + if (_parent) + if (prev->parent != _parent) + return prev->GetPrev(_parent); + + return prev; +} + +bool Internal::is_absolute() const { + return !is_relative(); +} + +bool Internal::is_relative() const { + return parent->is_relative(); +} + +Section * Internal::getDest() const { + return dest; +} + +Uint32 Internal::get_offset() const { + return offset; +} + +void Internal::fix_relocs() throw (GeneralException) { + Internal * inter; + + for (inter = GetFirst(); inter; inter = inter->GetNext()) { + if (!inter->GetParent()->is_absolute()) + throw GeneralException("Relocation fixing can't be done until all sections are constrained."); + + inter->GetParent()->fix_reloc(inter->get_offset(), inter->dest->get_offset(), inter->reloc); + } +} + +Section * Internal::GetParent() const { + return parent; +} + +Section * Section::head = 0; +Section * Section::tail = 0; +Section::Section(Binary * _parent, Uint32 _size, Uint32 _offset, bool bss) : parent(_parent), size(_size), offset(_offset), bytes(0) { + if (tail) { + next = 0; + prev = tail; + prev->next = tail = this; + } else { + head = tail = this; + next = prev = 0; + } + + if (!bss) + bytes = (char *) malloc(size); +} + +Section::~Section() { + if (next) { + next->prev = prev; + } else { + tail = prev; + } + + if (prev) { + prev->next = next; + } else { + head = next; + } + + if (bytes) + free(bytes); +} + +Section * Section::GetFirst(const Binary * _parent) { + if (!head) + return 0; + + if (_parent) + if (head->parent != _parent) + return head->GetNext(_parent); + + return head; +} + +Section * Section::GetNext(const Binary * _parent) const { + if (!next) + return 0; + + if (_parent) + if (next->parent != _parent) + return next->GetNext(_parent); + + return next; +} + +Section * Section::GetLast(const Binary * _parent) { + if (!tail) + return 0; + + if (_parent) + if (tail->parent != _parent) + return tail->GetPrev(_parent); + + return tail; +} + +Section * Section::GetPrev(const Binary * _parent) const { + if (!prev) + return 0; + + if (_parent) + if (prev->parent != _parent) + return prev->GetPrev(_parent); + + return prev; +} + +char * Section::get_bytes() const { + return bytes; +} + +Uint32 Section::get_size() const { + return size; +} + +Uint32 Section::get_offset() const { + return offset; +} + +Uint32 Section::get_end_offset() const { + return offset + size; +} + +bool Section::is_in(Uint32 _offset) const { + return ((offset >= _offset) && ((offset + size) <= _offset)); +} + +bool Section::is_bss() const { + return bytes == 0; +} + +Export * Section::add_export(const String & name, Uint32 offset, int bind) { + return new Export(this, name, offset, bind); +} + +Import * Section::add_import(const String & name, Uint32 offset, int reloc) { + return new Import(this, name, offset, reloc); +} + +Internal * Section::add_internal(Section * dest, Uint32 offset, int reloc) { + return new Internal(this, dest, offset, reloc); +} + +Export * Section::GetFirstExport() const { + return Export::GetFirst(this); +} + +Export * Section::GetNextExport(const Export * ex) const { + return ex->GetNext(this); +} + +Export * Section::GetLastExport() const { + return Export::GetLast(this); +} + +Export * Section::GetPrevExport(const Export * ex) const { + return ex->GetPrev(this); +} + +Import * Section::GetFirstImport() const { + return Import::GetFirst(this); +} + +Import * Section::GetNextImport(const Import * im) const { + return im->GetNext(this); +} + +Import * Section::GetLastImport() const { + return Import::GetLast(this); +} + +Import * Section::GetPrevImport(const Import * im) const { + return im->GetPrev(this); +} + +Internal * Section::GetFirstInternal() const { + return Internal::GetFirst(this); +} + +Internal * Section::GetNextInternal(const Internal * in) const { + return in->GetNext(this); +} + +Internal * Section::GetLastInternal() const { + return Internal::GetLast(this); +} + +Internal * Section::GetPrevInternal(const Internal * in) const { + return in->GetPrev(this); +} + +bool Section::is_absolute() const { + return !is_relative(); +} + +bool Section::is_relative() const { + return offset == 0; +} + +bool Section::solve_constraints() { + bool solved_one; + bool solved_all; + Section * ptr; + + do { + solved_one = false; + solved_all = true; + for (ptr = GetFirst(); ptr; ptr = ptr->GetNext()) { + if (ptr->is_relative()) { + solved_all = false; + ptr->solve_constraints_r(GetFirst()); + solved_one = solved_one ? true : ptr->is_absolute(); + } + } + } while (!solved_one && !solved_all); + + return solved_all; +} + +void Section::solve_constraints_r(Section * to) throw (GeneralException) { + Export * exp, * to_exp; + Uint32 origin; + + if (to != this) { + for (exp = GetFirstExport(); exp; exp = GetNextExport(exp)) { + if (to_exp = to->find_export(exp->GetName())) { + origin = to->get_offset() + to_exp->get_offset() - exp->get_offset(); + if (is_absolute() && (origin != get_offset())) + throw GeneralException("Constraints are not matching for files " + parent->GetName() + " and " + to->parent->GetName() + " with symbol " + exp->GetName()); + offset = origin; + } + } + } + + to = to->GetNext(); + while (to && to->is_relative()) + to = to->GetNext(); + + if (to) + solve_constraints_r(to); +} + +Export * Section::find_export(const String & name) { + Export * exp; + + for (exp = GetFirstExport(); exp; exp = GetNextExport(exp)) { + if (exp->GetName() == name) + return exp; + } + + return 0; +} + +void Section::fix_reloc(Uint32 from, Uint32 to, int reloc) throw (GeneralException) { + Uint32 word = bytes[from] | (bytes[from + 1] << 8) | (bytes[from + 2] << 16) | (bytes[from + 3] << 24); + switch (reloc) { + case R_MIPS_32: + word = to; + break; + case R_MIPS_26: + word = (word & 0xfc000000) | (((word & 0x03ffffff) + (to >> 2)) & 0x3ffffff); + break; + case R_MIPS_HI16: + word = (word & 0xffff0000) | ((((*(int32 *)(&word) >> 16) << 16) + (to >> 16) + ((to & 0xffff) >= 0x8000 ? 1 : 0)) & 0xffff); + break; + case R_MIPS_LO16: + word = (word & 0xffff0000) | ((((*(int32 *)(&word) >> 16) << 16) + (to & 0xffff)) & 0xffff); + break; + default: + throw GeneralException(String("Relocation type ") + reloc + " unknown."); + } + bytes[from + 0] = (word >> 0) & 0xff; + bytes[from + 1] = (word >> 8) & 0xff; + bytes[from + 2] = (word >> 16) & 0xff; + bytes[from + 3] = (word >> 24) & 0xff; +} + +Binary * Section::GetParent() const { + return parent; +} + +Section * Binary::GetFirstSection() const { + return Section::GetFirst(this); +} + +Section * Binary::GetNextSection(const Section * se) const { + return se->GetNext(this); +} + +Section * Binary::GetLastSection() const { + return Section::GetLast(this); +} + +Section * Binary::GetPrevSection(const Section * se) const { + return se->GetPrev(this); +} + +Section * Binary::add_section(Uint32 size, Uint32 offset) { + return new Section(this, size, offset, false); +} + +Section * Binary::add_bss(Uint32 size, Uint32 offset) { + return new Section(this, size, offset, true); +} + +Export * Binary::add_export(const String & name, Uint32 offset, int bind) throw (GeneralException) { + Section * se = 0, * abs_se = 0; + + // Let's try to find a proper section for this symbol. + for (se = GetFirstSection(); se; se = GetNextSection(se)) { + if (se->is_absolute()) { + abs_se = se; + if (se->is_in(offset)) + break; + } + } + + // no section found... ? dammit. Let's add it to the first absolute section of that binary then... + if (!se) + se = abs_se; + + if (!se) + throw GeneralException("This binary has no absolute sections, yet we want to add absolute symbols."); + + return se->add_export(name, offset - se->get_offset(), bind); +} + +Binary::Binary(const String & _name) : name(_name), EntryPoint(0) { +} + +Uint32 Binary::getEntryPoint() const { + return EntryPoint; +} + +void Binary::setEntryPoint(Uint32 ep) { + EntryPoint = ep; +} + +void Binary::loadSymbolMap(Handle * map) { + String line; + const char * buffer; + char symbol[1024]; + Uint32 address; + + while (!map->IsClosed()) { + *map >> line; + buffer = line.to_charp(); + if (buffer[0] == '#') + continue; + + if (sscanf(buffer, "%s %X\n", symbol, &address) != 2) + if (sscanf(buffer, "%s %x\n", symbol, &address) != 2) + if (sscanf(buffer, "%s 0x%X\n", symbol, &address) != 2) + if (sscanf(buffer, "%s 0x%x\n", symbol, &address) != 2) + continue; + + printm(M_INFO, "Got symbol from map: %s @ %X\n", symbol, address); + add_export(symbol, address, GLOBAL); + } +} + +#if 0 +void Binary::loadHookMap(Handle * map) { + String line; + const char * buffer; + char s_from[1024], s_to[1024]; + Uint32 s_from, s_to; + int size; + while (!map->IsClosed()) { + *map >> line; + buffer = line.to_charp(); + if (buffer[0] == '#') + continue; + + if (sscanf(buffer, "%X %X + } +} +#endif + +String Binary::GetName() const { + return name; +} + +Section * Binary::create_hook(Uint32 offset, int size) { + Section * r; + + size = (size << 2) + 4; + + r = add_section(size, offset); + memset(r->get_bytes(), 0, size); + + return r; +} + +void Binary::create_jhook(Uint32 from, Uint32 to, int size) { + Section * sec = create_hook(from, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = (to >> 0) & 0xff; + bytes[1] = (to >> 8) & 0xff; + bytes[2] = (to >> 16) & 0xff; + bytes[3] = (to >> 24) & 0x3f | 0x80; +} + +void Binary::create_jhook(const String & from, Uint32 to, int size) { + Section * sec = create_hook(0, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = (to >> 0) & 0xff; + bytes[1] = (to >> 8) & 0xff; + bytes[2] = (to >> 16) & 0xff; + bytes[3] = (to >> 24) & 0x3f | 0x80; + + sec->add_export(from, 0, GLOBAL); +} + +void Binary::create_jhook(Uint32 from, const String & to, int size) { + Section * sec = create_hook(from, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = bytes[1] = bytes[2] = 0; + bytes[3] = 0x80; + + sec->add_import(to, 0, R_MIPS_26); +} + +void Binary::create_jhook(const String & from, const String & to, int size) { + Section * sec = create_hook(0, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = bytes[1] = bytes[2] = 0; + bytes[3] = 0x80; + + sec->add_export(from, 0, GLOBAL); + sec->add_import(to, 0, R_MIPS_26); +} + +void Binary::create_jalhook(Uint32 from, Uint32 to, int size) { + Section * sec = create_hook(from, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = (to >> 0) & 0xff; + bytes[1] = (to >> 8) & 0xff; + bytes[2] = (to >> 16) & 0xff; + bytes[3] = (to >> 24) & 0x3f | 0xc0; +} + +void Binary::create_jalhook(const String & from, Uint32 to, int size) { + Section * sec = create_hook(0, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = (to >> 0) & 0xff; + bytes[1] = (to >> 8) & 0xff; + bytes[2] = (to >> 16) & 0xff; + bytes[3] = (to >> 24) & 0x3f | 0xc0; + + sec->add_export(from, 0, GLOBAL); +} + +void Binary::create_jalhook(Uint32 from, const String & to, int size) { + Section * sec = create_hook(from, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = bytes[1] = bytes[2] = 0; + bytes[3] = 0xc0; + + sec->add_import(to, 0, R_MIPS_26); +} + +void Binary::create_jalhook(const String & from, const String & to, int size) { + Section * sec = create_hook(0, size); + char * bytes; + bytes = sec->get_bytes(); + + bytes[0] = bytes[1] = bytes[2] = 0; + bytes[3] = 0xc0; + + sec->add_export(from, 0, GLOBAL); + sec->add_import(to, 0, R_MIPS_26); +} + +#ifdef WORDS_BIGENDIAN +static void sw32(u32 & x) { + x = (x >> 24) | ((x >> 8) & 0x0000ff00) | ((x << 8) & 0x00ff0000) | (x << 24); +} +static void sw16(u16 & x) { + x = (x >> 8) | ((x << 8); +} +#else +#define sw32(x) while(0) +#define sw16(x) while(0) +#endif + +struct psyq_header_t Binary_psexe::header; + +Binary_psexe::Binary_psexe(Handle * psexe) : Binary(psexe->GetName()) { + psexe->read(&header, sizeof(header)); + if (strncmp((char *) header.details.id, "PS-X EXE", 8)) + throw GeneralException("The file " + psexe->GetName() + " is not a Psy-Q file."); + + sw32(header.details.text); + sw32(header.details.data); + sw32(header.details.pc0); + sw32(header.details.gp0); + sw32(header.details.t_addr); + sw32(header.details.t_size); + sw32(header.details.d_addr); + sw32(header.details.d_size); + sw32(header.details.b_addr); + sw32(header.details.b_size); + sw32(header.details.s_addr); + sw32(header.details.s_size); + sw32(header.details.sp); + sw32(header.details.fp); + sw32(header.details.gp); + sw32(header.details.ra); + sw32(header.details.s0); + + psexe->read(add_section(header.details.t_size, header.details.t_addr)->get_bytes(), header.details.t_size); + setEntryPoint(header.details.pc0); +} + +// gunnar jansson diff --git a/lib/binwriter-elf.cpp b/lib/binwriter-elf.cpp new file mode 100644 index 0000000..81755d7 --- /dev/null +++ b/lib/binwriter-elf.cpp @@ -0,0 +1,144 @@ +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2005 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: binwriter-elf.cpp,v 1.1 2005-12-02 11:28:27 pixel Exp $ */ + +#include "binwriter-elf.h" +#include "binary-elf.h" + +#ifdef WORDS_BIGENDIAN +static void sw32(u32 & x) { + x = (x >> 24) | ((x >> 8) & 0x0000ff00) | ((x << 8) & 0x00ff0000) | (x << 24); +} +static void sw16(u16 & x) { + x = (x >> 8) | ((x << 8); +} +#else +#define sw32(x) while(0) +#define sw16(x) while(0) +#endif + +static u8 elf_ident[] = { + 0x7F, 0x45, 0x4C, 0x46, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +// works only with align == 2^n +static Uint32 align_it(Uint32 address, int align) { + if (address & (--align)) { + address |= align; + address++; + } + + return address; +} + +void BinWriter_elf::dump(Handle * elf) { + struct elf_header_t weh; + struct elf_pheader_t weph; + int i; + std::vector::iterator iter; + Uint32 offset = 0x1000; + + for (i = 0; i < 16; i++) { + weh.e_ident.raw[i] = elf_ident[i]; + } + weh.e_type = 2; + weh.e_machine = 8; + weh.e_version = 1; + weh.e_phoff = sizeof(weh); + weh.e_shoff = 0; + weh.e_flags = 0; + weh.e_ehsize = sizeof(weh); + weh.e_phentsize = sizeof(weph); + weh.e_phnum = sections.size(); + weh.e_shoff = 0; + weh.e_shnum = 0; + weh.e_shentsize = 0; + weh.e_entry = epc; + weh.e_shstrndx = 0; + + sw16(weh.e_type); + sw16(weh.e_machine); + sw32(weh.e_version); + sw32(weh.e_entry); + sw32(weh.e_phoff); + sw32(weh.e_shoff); + sw32(weh.e_flags); + sw16(weh.e_ehsize); + sw16(weh.e_phentsize); + sw16(weh.e_phnum); + sw16(weh.e_shentsize); + sw16(weh.e_shnum); + sw16(weh.e_shstrndx); + + elf->write(&weh, sizeof(weh)); + + + for (iter = sections.begin(); iter != sections.end(); iter++) { + weph.type = PT_LOAD; + weph.flags = PF_R | PF_W | PF_X; + weph.offset = offset; + weph.vaddr = iter->base; + weph.paddr = iter->base; + weph.filesz = iter->real_size; + weph.memsz = iter->whole_size; + weph.align = 0x1000; + + offset += iter->real_size; + offset = align_it(offset, 0x1000); + + sw32(weph.type); + sw32(weph.flags); + sw32(weph.offset); + sw32(weph.vaddr); + sw32(weph.paddr); + sw32(weph.filesz); + sw32(weph.memsz); + sw32(weph.align); + + elf->write(&weph, sizeof(weph)); + } + + offset = 0x1000; + + for (iter = sections.begin(); iter != sections.end(); iter++) { + elf->seek(offset); + if (iter->data) { + elf->write(iter->data, iter->real_size); + offset += iter->real_size; + } else { + offset++; + } + offset = align_it(offset, 0x1000); + } +} + +#if 0 +static Uint32 elf_hash(const unsigned char * name) { + Uint31 h = 0, g; + + while (*name) { + h = (h << 4) + *name++; + if ((g = h & 0xf0000000) + h ^= g >> 24; + h &= ~g; + } +} +#endif diff --git a/lib/binwriter.cpp b/lib/binwriter.cpp new file mode 100644 index 0000000..5896315 --- /dev/null +++ b/lib/binwriter.cpp @@ -0,0 +1,189 @@ +/* + * PSX-Tools Bundle Pack + * Copyright (C) 2002-2005 Nicolas "Pixel" Noble + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* $Id: binwriter.cpp,v 1.1 2005-12-02 11:28:27 pixel Exp $ */ + +#include +#include + +void BinWriter::merge(void) { + Section * iter, * sub_iter; + std::vector
merged; + std::vector
to_merge; + std::vector
::iterator i; + bool is_in, did_merge, pure_bss, is_before_us; + Uint32 base, real_size, whole_size, end_address, sub_size; + + for (iter = Section::GetFirst(); iter; iter = iter->GetNext()) { + is_in = false; + for (i = merged.begin(); i != merged.end(); i++) { + if (*i == iter) { + is_in = true; + break; + } + } + if (is_in) + continue; + + merged.push_back(iter); + to_merge.clear(); + if (!iter->is_bss()) { + to_merge.push_back(iter); + } + + base = iter->get_offset(); + if (iter->is_bss()) { + real_size = 0; + whole_size = iter->get_size(); + pure_bss = true; + } else { + real_size = whole_size = iter->get_size(); + pure_bss = false; + } + + end_address = base + whole_size; + +#if 0 + do { + did_merge = false; + is_before_us = true; + for (sub_iter = Section::GetFirst(); sub_iter; iter = sub_iter->GetNext()) { + is_in = false; + if (sub_iter == iter) { + is_before_us = false; + continue; + } + for (i = merged.begin(); i != merged.end(); i++) { + if (*i == sub_iter) { + is_in = true; + break; + } + } + if (is_in) + continue; + + // ***** CHECK AND/OR REWRITE THAT FUCKING CRAP ***** + + if (base >= sub_iter->get_offset()) { + // The current sub-iter is below our base + if (base > sub_iter->get_end_offset()) { + // but it doesn't reach it... next! + continue; + } + if ((base == sub_iter->get_end_offset()) && sub_iter->is_bss() && !pure_bss) { + // they do not overlap, we are not a bss, and it's a bss. Skip! + continue; + } + sub_size = base - sub_iter->get_offset(); + if (sub_iter->is_bss() && !pure_bss) { + // Worst case: it's overlapping, we're not a bss, and it's a bss... + // We'll have to transform it into plain memory. + if ((base + whole_size) < sub_iter->get_end_offset()) { + // it's so big it goes beyond our end... let's extend our bss size then. + whole_size = sub_iter->get_size(); + end_address = sub_iter->get_end_offset(); + } else { + whole_size += sub_size; + } + base = sub_iter->get_offset(); + real_size += sub_size; + did_merge = true; + merged.push_back(sub_iter); + continue; + } + if (pure_bss && !sub_iter->is_bss()) { + // we're a bss, and this is not. Let's transform ourselves. + pure_bss = false; + base = sub_iter->get_offset(); + real_size = sub_iter->get_size(); + if ((base + whole_size) < sub_iter->get_end_offset()) { + // it's so big we don't have any bss anymore. + whole_size = real_size; + end_address = sub_iter->get_end_offset(); + } else { + whole_size += sub_size; + } + if (is_before_us) { + to_merge.insert(to_merge.begin(), sub_iter); + } else { + to_merge.push_back(sub_iter); + } + did_merge = true; + merged.push_back(sub_iter); + continue; + } + if (pure_bss && sub_iter->is_bss()) { + // we're both bss. + if ((base + whole_size) < sub_iter->get_end_offset()) { + // it's so big we are somewhat absorbed here. + whole_size = real_size; + end_address = sub_iter->get_end_offset(); + } else { + whole_size += sub_size; + } + base = sub_iter->get_offset(); + did_merge = true; + merged.push_back(sub_iter); + continue; + } + if (!pure_bss && !sub_iter->is_bss()) { + // we both have data + if ((base + whole_size) < sub_iter->get_end_offset()) { + // it's so big we are somewhat absorbed here. + whole_size = real_size; + end_address = sub_iter->get_end_offset(); + } else { + whole_size += sub_size; + } + base = sub_iter->get_offset(); + real_size += sub_size; + if (is_before_us) { + to_merge.insert(to_merge.begin(), sub_iter); + } else { + to_merge.push_back(sub_iter); + } + } + + // lots of other conditions here... + } else { + // even more conditions here... + } + } + } while (did_merge); + +#endif + struct SectionOut so; + + if (!pure_bss) + so.data = (char *) malloc(real_size); + else + so.data = NULL; + so.base = base; + so.real_size = real_size; + so.whole_size = whole_size; + + for (i = to_merge.begin(); i != to_merge.end(); i++) { + memcpy(so.data + (*i)->get_offset() - base, (*i)->get_bytes(), (*i)->get_size()); + } + + sections.push_back(so); + } +} + +// Hubbold Roger - network latency. \ No newline at end of file -- cgit v1.2.3