summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MSVC/.cvsignore2
-rw-r--r--MSVC/PSX-Bundle.sln14
-rw-r--r--MSVC/PSx-Patcher/.cvsignore2
-rw-r--r--MSVC/PSx-Patcher/PSx-Patcher.vcproj181
-rw-r--r--includes/binary-elf.h98
-rw-r--r--includes/binary.h226
-rw-r--r--includes/binwriter-elf.h32
-rw-r--r--includes/binwriter.h44
-rw-r--r--lib/binary-elf.cpp436
-rw-r--r--lib/binary.cpp835
-rw-r--r--lib/binwriter-elf.cpp144
-rw-r--r--lib/binwriter.cpp189
12 files changed, 2201 insertions, 2 deletions
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
@@ -21,10 +21,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CD-Tool", "CD-Tool\CD-Tool.
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 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="PSx-Patcher"
+ ProjectGUID="{15A91021-E932-427B-9A6F-731AFBA8928B}"
+ RootNamespace="PSxPatcher"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;..\getopt&quot;;&quot;..\..\generic\include&quot;;&quot;..\..\generic\lib\zlib\include&quot;;&quot;..\..\generic\lib\lua\include&quot;;&quot;..\regex&quot;;&quot;..\..\includes&quot;;&quot;..\..\psxdev&quot;;&quot;..\..\MSVC&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;..\getopt&quot;;&quot;..\..\generic\include&quot;;&quot;..\..\generic\lib\zlib\include&quot;;&quot;..\..\generic\lib\lua\include&quot;;&quot;..\regex&quot;;&quot;..\..\includes&quot;;&quot;..\..\psxdev&quot;;&quot;..\..\MSVC&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\PSx-Patcher.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
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 <vector>
+
+#include <Exceptions.h>
+#include <BString.h>
+#include <Handle.h>
+
+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 <binwriter.h>
+
+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 <vector>
+#include <Exceptions.h>
+#include <Handle.h>
+#include <binary.h>
+
+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<struct SectionOut> 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 <vector>
+#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 *> 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 <gunnar.jansson@psyk.uu.se>
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<struct SectionOut>::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 <binwriter.h>
+#include <binary.h>
+
+void BinWriter::merge(void) {
+ Section * iter, * sub_iter;
+ std::vector<Section *> merged;
+ std::vector<Section *> to_merge;
+ std::vector<Section *>::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