Skip to content

Commit

Permalink
Major refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Adubbz committed Apr 2, 2019
1 parent 45dc141 commit dfb934b
Show file tree
Hide file tree
Showing 19 changed files with 1,454 additions and 1,074 deletions.
18 changes: 4 additions & 14 deletions src/main/java/adubbz/switchloader/SwitchLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,35 +118,25 @@ protected boolean loadProgramInto(ByteProvider provider, LoadSpec loadSpec, List
MessageLog messageLog, Program program, TaskMonitor monitor, MemoryConflictHandler memoryConflictHandler)
throws IOException
{
BinaryReader reader;

if (this.binaryType == BinaryType.SX_KIP1)
{
ByteProvider offsetProvider = new ByteProviderWrapper(provider, 0x10, provider.length() - 0x10);
reader = new BinaryReader(offsetProvider, true);

KIP1Header header = new KIP1Header(reader, 0x0);
KIP1ProgramBuilder.loadKIP1(header, offsetProvider, program, memoryConflictHandler, monitor);
KIP1ProgramBuilder.loadKIP1(offsetProvider, program, memoryConflictHandler, monitor);
}
else
{
reader = new BinaryReader(provider, true);

if (this.binaryType == BinaryType.KIP1)
{
KIP1Header header = new KIP1Header(reader, 0x0);
KIP1ProgramBuilder.loadKIP1(header, provider, program, memoryConflictHandler, monitor);
KIP1ProgramBuilder.loadKIP1(provider, program, memoryConflictHandler, monitor);
}

else if (this.binaryType == BinaryType.NSO0)
{
NSO0Header header = new NSO0Header(reader, 0x0);
NSO0ProgramBuilder.loadNSO0(header, provider, program, memoryConflictHandler, monitor);
NSO0ProgramBuilder.loadNSO0(provider, program, memoryConflictHandler, monitor);
}
else if (this.binaryType == BinaryType.NRO0)
{
NRO0Header header = new NRO0Header(reader, 0x0);
NRO0ProgramBuilder.loadNRO0(header, provider, program, memoryConflictHandler, monitor);
NRO0ProgramBuilder.loadNRO0( provider, program, memoryConflictHandler, monitor);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* Copyright 2019 Adubbz
* Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package adubbz.switchloader.common;

import java.io.IOException;
Expand Down
627 changes: 627 additions & 0 deletions src/main/java/adubbz/switchloader/common/NXProgramBuilder.java

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions src/main/java/adubbz/switchloader/common/NXRelocation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright 2019 Adubbz
* Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package adubbz.switchloader.common;

import ghidra.app.util.bin.format.elf.ElfSymbol;

public class NXRelocation
{
public NXRelocation(long offset, long r_type, ElfSymbol sym, long addend)
{
this.offset = offset;
this.r_type = r_type;
this.sym = sym;
this.addend = addend;
}

public long offset;
public long r_type;
public ElfSymbol sym;
public long addend;
}
808 changes: 0 additions & 808 deletions src/main/java/adubbz/switchloader/common/SwitchProgramBuilder.java

This file was deleted.

120 changes: 120 additions & 0 deletions src/main/java/adubbz/switchloader/kip1/KIP1Adapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/**
* Copyright 2019 Adubbz
* Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package adubbz.switchloader.kip1;

import java.io.IOException;

import adubbz.switchloader.nxo.NXOAdapter;
import adubbz.switchloader.nxo.NXOSection;
import adubbz.switchloader.nxo.NXOSectionType;
import adubbz.switchloader.util.ByteUtil;
import ghidra.app.util.bin.BinaryReader;
import ghidra.app.util.bin.ByteArrayProvider;
import ghidra.app.util.bin.ByteProvider;
import ghidra.util.Msg;

public class KIP1Adapter extends NXOAdapter
{
protected ByteProvider fileProvider;
protected BinaryReader fileReader;
protected KIP1Header kip1;

protected ByteProvider memoryProvider;
protected NXOSection[] sections;

public KIP1Adapter(ByteProvider fileProvider)
{
this.fileProvider = fileProvider;
this.fileReader = new BinaryReader(this.fileProvider, true);

try
{
this.read();
}
catch (IOException e)
{
Msg.error(this, "Failed to read KIP1");
e.printStackTrace();
}
}

private void read() throws IOException
{
this.kip1 = new KIP1Header(this.fileReader, 0x0);

KIP1SectionHeader textHeader = this.kip1.getSectionHeader(NXOSectionType.TEXT);
KIP1SectionHeader rodataHeader = this.kip1.getSectionHeader(NXOSectionType.RODATA);
KIP1SectionHeader dataHeader = this.kip1.getSectionHeader(NXOSectionType.DATA);

int textOffset = textHeader.getOutOffset();
int rodataOffset = rodataHeader.getOutOffset();
int dataOffset = dataHeader.getOutOffset();
int textSize = textHeader.getDecompressedSize();
int rodataSize = rodataHeader.getDecompressedSize();
int dataSize = dataHeader.getDecompressedSize();

// The data section is last, so we use its offset + decompressed size
byte[] full = new byte[dataOffset + dataSize];
byte[] decompressedText;
byte[] decompressedRodata;
byte[] decompressedData;

if (this.kip1.isSectionCompressed(NXOSectionType.TEXT))
{
byte[] compressedText = this.fileProvider.readBytes(this.kip1.getSectionFileOffset(NXOSectionType.TEXT), this.kip1.getCompressedSectionSize(NXOSectionType.TEXT));
decompressedText = ByteUtil.kip1BlzDecompress(compressedText, textSize);
}
else
{
decompressedText = this.fileProvider.readBytes(this.kip1.getSectionFileOffset(NXOSectionType.TEXT), textSize);
}

System.arraycopy(decompressedText, 0, full, textOffset, textSize);

if (this.kip1.isSectionCompressed(NXOSectionType.RODATA))
{
byte[] compressedRodata = this.fileProvider.readBytes(this.kip1.getSectionFileOffset(NXOSectionType.RODATA), this.kip1.getCompressedSectionSize(NXOSectionType.RODATA));
decompressedRodata = ByteUtil.kip1BlzDecompress(compressedRodata, rodataSize);
}
else
{
decompressedRodata = this.fileProvider.readBytes(this.kip1.getSectionFileOffset(NXOSectionType.RODATA), rodataSize);
}

System.arraycopy(decompressedRodata, 0, full, rodataOffset, rodataSize);

if (this.kip1.isSectionCompressed(NXOSectionType.DATA))
{
byte[] compressedData = this.fileProvider.readBytes(this.kip1.getSectionFileOffset(NXOSectionType.DATA), this.kip1.getCompressedSectionSize(NXOSectionType.DATA));
decompressedData = ByteUtil.kip1BlzDecompress(compressedData, dataSize);
}
else
{
decompressedData = this.fileProvider.readBytes(this.kip1.getSectionFileOffset(NXOSectionType.DATA), dataSize);
}

System.arraycopy(decompressedData, 0, full, dataOffset, dataSize);
this.memoryProvider = new ByteArrayProvider(full);

this.sections = new NXOSection[3];
this.sections[NXOSectionType.TEXT.ordinal()] = new NXOSection(NXOSectionType.TEXT, textOffset, textSize);
this.sections[NXOSectionType.RODATA.ordinal()] = new NXOSection(NXOSectionType.RODATA, rodataOffset, rodataSize);
this.sections[NXOSectionType.DATA.ordinal()] = new NXOSection(NXOSectionType.DATA, dataOffset, dataSize);
}

@Override
public ByteProvider getMemoryProvider()
{
return this.memoryProvider;
}

@Override
public NXOSection[] getSections()
{
return this.sections;
}
}
14 changes: 7 additions & 7 deletions src/main/java/adubbz/switchloader/kip1/KIP1Header.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.io.IOException;

import adubbz.switchloader.common.InvalidMagicException;
import adubbz.switchloader.common.SectionType;
import adubbz.switchloader.nxo.NXOSectionType;
import ghidra.app.util.bin.BinaryReader;
import ghidra.util.Msg;

Expand Down Expand Up @@ -64,29 +64,29 @@ private void readHeader(BinaryReader reader)
}
}

public KIP1SectionHeader getSectionHeader(SectionType type)
public KIP1SectionHeader getSectionHeader(NXOSectionType type)
{
return this.sectionHeaders[type.ordinal()];
}

public long getSectionFileOffset(SectionType type)
public long getSectionFileOffset(NXOSectionType type)
{
if (type == SectionType.TEXT)
if (type == NXOSectionType.TEXT)
return 0x100;
else
{
SectionType prevType = SectionType.values()[type.ordinal() - 1];
NXOSectionType prevType = NXOSectionType.values()[type.ordinal() - 1];
KIP1SectionHeader prevHeader = this.getSectionHeader(prevType);
return this.getSectionFileOffset(prevType) + prevHeader.getCompressedSize();
}
}

public int getCompressedSectionSize(SectionType type)
public int getCompressedSectionSize(NXOSectionType type)
{
return this.sectionHeaders[type.ordinal()].getCompressedSize();
}

public boolean isSectionCompressed(SectionType type)
public boolean isSectionCompressed(NXOSectionType type)
{
int index = type.ordinal();

Expand Down
89 changes: 7 additions & 82 deletions src/main/java/adubbz/switchloader/kip1/KIP1ProgramBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,22 @@

package adubbz.switchloader.kip1;

import java.io.IOException;

import adubbz.switchloader.common.SectionType;
import adubbz.switchloader.common.SwitchProgramBuilder;
import adubbz.switchloader.util.ByteUtil;
import ghidra.app.util.bin.ByteArrayProvider;
import adubbz.switchloader.common.NXProgramBuilder;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.importer.MemoryConflictHandler;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOutOfBoundsException;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
import ghidra.util.task.TaskMonitor;

public class KIP1ProgramBuilder extends SwitchProgramBuilder
public class KIP1ProgramBuilder extends NXProgramBuilder
{
private KIP1Header kip1;

protected KIP1ProgramBuilder(KIP1Header kip1, ByteProvider provider, Program program, MemoryConflictHandler handler)
protected KIP1ProgramBuilder(ByteProvider provider, Program program, MemoryConflictHandler handler)
{
super(provider, program, handler);
this.kip1 = kip1;
super(program, provider, new KIP1Adapter(provider), handler);
}

public static void loadKIP1(KIP1Header header, ByteProvider provider, Program program, MemoryConflictHandler conflictHandler, TaskMonitor monitor)
public static void loadKIP1(ByteProvider provider, Program program, MemoryConflictHandler conflictHandler, TaskMonitor monitor)
{
KIP1ProgramBuilder builder = new KIP1ProgramBuilder(header, provider, program, conflictHandler);
KIP1ProgramBuilder builder = new KIP1ProgramBuilder(provider, program, conflictHandler);
builder.load(monitor);
}

Expand All @@ -45,68 +32,6 @@ protected void load(TaskMonitor monitor)
super.load(monitor);

// KIP1s always start with a branch instruction at the start of their text
this.createEntryFunction("entry", this.baseAddress, monitor);
}

@Override
protected void loadDefaultSegments(TaskMonitor monitor) throws IOException, AddressOverflowException, AddressOutOfBoundsException
{
long baseAddress = 0x7100000000L;
AddressSpace aSpace = program.getAddressFactory().getDefaultAddressSpace();

KIP1SectionHeader textHeader = this.kip1.getSectionHeader(SectionType.TEXT);
KIP1SectionHeader rodataHeader = this.kip1.getSectionHeader(SectionType.RODATA);
KIP1SectionHeader dataHeader = this.kip1.getSectionHeader(SectionType.DATA);
KIP1SectionHeader bssHeader = this.kip1.getSectionHeader(SectionType.BSS);

this.textOffset = textHeader.getOutOffset();
this.rodataOffset = rodataHeader.getOutOffset();
this.dataOffset = dataHeader.getOutOffset();
this.textSize = textHeader.getDecompressedSize();
this.rodataSize = rodataHeader.getDecompressedSize();
this.dataSize = dataHeader.getDecompressedSize();

// The data section is last, so we use its offset + decompressed size
byte[] full = new byte[this.dataOffset + this.dataSize];
byte[] decompressedText;
byte[] decompressedRodata;
byte[] decompressedData;

if (this.kip1.isSectionCompressed(SectionType.TEXT))
{
byte[] compressedText = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.TEXT), this.kip1.getCompressedSectionSize(SectionType.TEXT));
decompressedText = ByteUtil.kip1BlzDecompress(compressedText, this.textSize);
}
else
{
decompressedText = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.TEXT), this.textSize);
}

System.arraycopy(decompressedText, 0, full, this.textOffset, this.textSize);

if (this.kip1.isSectionCompressed(SectionType.RODATA))
{
byte[] compressedRodata = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.RODATA), this.kip1.getCompressedSectionSize(SectionType.RODATA));
decompressedRodata = ByteUtil.kip1BlzDecompress(compressedRodata, this.rodataSize);
}
else
{
decompressedRodata = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.RODATA), this.rodataSize);
}

System.arraycopy(decompressedRodata, 0, full, this.rodataOffset, this.rodataSize);

if (this.kip1.isSectionCompressed(SectionType.DATA))
{
byte[] compressedData = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.DATA), this.kip1.getCompressedSectionSize(SectionType.DATA));
decompressedData = ByteUtil.kip1BlzDecompress(compressedData, this.dataSize);
}
else
{
decompressedData = this.fileByteProvider.readBytes(this.kip1.getSectionFileOffset(SectionType.DATA), this.dataSize);
}

System.arraycopy(decompressedData, 0, full, this.dataOffset, this.dataSize);
this.memoryByteProvider = new ByteArrayProvider(full);
this.createEntryFunction("entry", this.nxo.getBaseAddress(), monitor);
}
}
Loading

0 comments on commit dfb934b

Please sign in to comment.