Few optimizations
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Dmitry Isaenko 2025-02-16 23:18:52 +03:00
parent 80152e119c
commit 620ae15693
2 changed files with 106 additions and 77 deletions

View file

@ -25,33 +25,78 @@ import org.apache.logging.log4j.Logger;
public class KernelMap { public class KernelMap {
private final static Logger log = LogManager.getLogger(KernelMap.class); private final static Logger log = LogManager.getLogger(KernelMap.class);
private final int textStartOffset;
private final int textEndOffset;
private final int rodataStartOffset;
private final int rodataEndOffset;
private final int dataStartOffset;
private final int dataEndOffset;
private final int bssStartOffset;
private final int bssEndOffset;
private final int ini1Offset;
private final int dynamicOffset;
private final int initArrayStartOffset;
private final int initArrayEndOffset;
public KernelMap(byte[] mapBytes, int offset){ private int textStartOffset;
textStartOffset = Converter.getLEint(mapBytes, offset); private int textEndOffset;
textEndOffset = Converter.getLEint(mapBytes, offset + 0x4); private int rodataStartOffset;
rodataStartOffset = Converter.getLEint(mapBytes, offset + 0x8); private int rodataEndOffset;
rodataEndOffset = Converter.getLEint(mapBytes, offset + 0xC); private int dataStartOffset;
dataStartOffset = Converter.getLEint(mapBytes, offset + 0x10); private int dataEndOffset;
dataEndOffset = Converter.getLEint(mapBytes, offset + 0x14); private int bssStartOffset;
bssStartOffset = Converter.getLEint(mapBytes, offset + 0x18); private int bssEndOffset;
bssEndOffset = Converter.getLEint(mapBytes, offset + 0x1C); private int ini1Offset;
ini1Offset = Converter.getLEint(mapBytes, offset + 0x20); private int dynamicOffset;
dynamicOffset = Converter.getLEint(mapBytes, offset + 0x24); private int initArrayStartOffset;
initArrayStartOffset = Converter.getLEint(mapBytes, offset + 0x28); private int initArrayEndOffset;
initArrayEndOffset = Converter.getLEint(mapBytes, offset + 0x2C); private int systemRegistersOffset; // 17.0.0+
private KernelMap() { }
/**
* Construct KernelMap
*
* @return null if mapBytes is an invalid data set and KernelMap object otherwise
*/
public static KernelMap constructKernelMap(byte[] mapBytes, int offset, int maxSize) {
KernelMap kernelMap = new KernelMap();
kernelMap.textStartOffset = Converter.getLEint(mapBytes, offset);
if (kernelMap.textStartOffset != 0)
return null;
kernelMap.textEndOffset = Converter.getLEint(mapBytes, offset + 0x4);
kernelMap.rodataStartOffset = Converter.getLEint(mapBytes, offset + 0x8);
kernelMap.rodataEndOffset = Converter.getLEint(mapBytes, offset + 0xC);
kernelMap.dataStartOffset = Converter.getLEint(mapBytes, offset + 0x10);
kernelMap.dataEndOffset = Converter.getLEint(mapBytes, offset + 0x14);
kernelMap.bssStartOffset = Converter.getLEint(mapBytes, offset + 0x18);
kernelMap.bssEndOffset = Converter.getLEint(mapBytes, offset + 0x1C);
kernelMap.ini1Offset = Converter.getLEint(mapBytes, offset + 0x20); // 0x08d000
kernelMap.dynamicOffset = Converter.getLEint(mapBytes, offset + 0x24);
kernelMap.initArrayStartOffset = Converter.getLEint(mapBytes, offset + 0x28);
kernelMap.initArrayEndOffset = Converter.getLEint(mapBytes, offset + 0x2C);
kernelMap.systemRegistersOffset = Converter.getLEint(mapBytes, offset + 0x30);
// taken from hactool
if (kernelMap.textStartOffset >= kernelMap.textEndOffset)
return null;
if ((kernelMap.textEndOffset & 0xFFF) > 0)
return null;
if (kernelMap.textEndOffset > kernelMap.rodataStartOffset)
return null;
if ((kernelMap.rodataStartOffset & 0xFFF) > 0)
return null;
if (kernelMap.rodataStartOffset >= kernelMap.rodataEndOffset)
return null;
if ((kernelMap.rodataEndOffset & 0xFFF) > 0)
return null;
if (kernelMap.rodataEndOffset > kernelMap.dataStartOffset)
return null;
if ((kernelMap.dataStartOffset & 0xFFF) > 0)
return null;
if (kernelMap.dataStartOffset >= kernelMap.dataEndOffset)
return null;
if (kernelMap.dataEndOffset > kernelMap.bssStartOffset)
return null;
if (kernelMap.bssStartOffset > kernelMap.bssEndOffset)
return null;
if (kernelMap.bssEndOffset > kernelMap.ini1Offset)
return null;
/*
if (kernelMap.ini1Offset > maxSize - 0x80)
return null;
*/
System.out.println("FOUND AT:" + RainbowDump.formatDecHexString(offset));
kernelMap.printDebug();
return kernelMap;
} }
public int getTextStartOffset() { return textStartOffset; } public int getTextStartOffset() { return textStartOffset; }
@ -67,52 +112,20 @@ public class KernelMap {
public int getInitArrayStartOffset() { return initArrayStartOffset; } public int getInitArrayStartOffset() { return initArrayStartOffset; }
public int getInitArrayEndOffset() { return initArrayEndOffset; } public int getInitArrayEndOffset() { return initArrayEndOffset; }
//taken from hactool public void printDebug() {
public boolean isValid(long maxSize) { // section0 size
if (textStartOffset != 0)
return false;
if (textStartOffset >= textEndOffset)
return false;
if ((textEndOffset & 0xFFF) > 0)
return false;
if (textEndOffset > rodataStartOffset)
return false;
if ((rodataStartOffset & 0xFFF) > 0)
return false;
if (rodataStartOffset >= rodataEndOffset)
return false;
if ((rodataEndOffset & 0xFFF) > 0)
return false;
if (rodataEndOffset > dataStartOffset)
return false;
if ((dataStartOffset & 0xFFF) > 0)
return false;
if (dataStartOffset >= dataEndOffset)
return false;
if (dataEndOffset > bssStartOffset)
return false;
if (bssStartOffset > bssEndOffset)
return false;
if (bssEndOffset > ini1Offset)
return false;
if (ini1Offset > maxSize - 0x80)
return false;
return true;
}
public void printDebug(){
log.debug("_ Kernel map _\n" + log.debug("_ Kernel map _\n" +
" .text Start Offset " + RainbowDump.formatDecHexString(textStartOffset) + "\n" + " .text Start Offset " + RainbowDump.formatDecHexString(textStartOffset) + "\n" +
" .text End Offset " + RainbowDump.formatDecHexString(textEndOffset) + "\n" + " .text End Offset " + RainbowDump.formatDecHexString(textEndOffset) + "\n" +
" .rodata Start Offset " + RainbowDump.formatDecHexString(rodataStartOffset) + "\n" + " .rodata Start Offset " + RainbowDump.formatDecHexString(rodataStartOffset) + "\n" +
" .rodata End Offset " + RainbowDump.formatDecHexString(rodataEndOffset) + "\n" + " .rodata End Offset " + RainbowDump.formatDecHexString(rodataEndOffset) + "\n" +
" .data Start Offset " + RainbowDump.formatDecHexString(dataStartOffset) + "\n" + " .data Start Offset " + RainbowDump.formatDecHexString(dataStartOffset) + "\n" +
" .data End Offset " + RainbowDump.formatDecHexString(dataEndOffset) + "\n" + " .data End Offset " + RainbowDump.formatDecHexString(dataEndOffset) + "\n" +
" .bss Start Offset " + RainbowDump.formatDecHexString(bssStartOffset) + "\n" + " .bss Start Offset " + RainbowDump.formatDecHexString(bssStartOffset) + "\n" +
" .bss End Offset " + RainbowDump.formatDecHexString(bssEndOffset) + "\n" + " .bss End Offset " + RainbowDump.formatDecHexString(bssEndOffset) + "\n" +
" INI1 Offset " + RainbowDump.formatDecHexString(ini1Offset) + "\n" + " INI1 Offset " + RainbowDump.formatDecHexString(ini1Offset) + "\n" +
" Dynamic Offset " + RainbowDump.formatDecHexString(dynamicOffset) + "\n" + " Dynamic Offset " + RainbowDump.formatDecHexString(dynamicOffset) + "\n" +
" Init array Start Offset " + RainbowDump.formatDecHexString(initArrayStartOffset) + "\n" + " Init array Start Offset " + RainbowDump.formatDecHexString(initArrayStartOffset) + "\n" +
" Init array End Offset " + RainbowDump.formatDecHexString(initArrayEndOffset)); " Init array End Offset " + RainbowDump.formatDecHexString(initArrayEndOffset) + "\n" +
" System registers offset (FW 17.0.0+) " + RainbowDump.formatDecHexString(systemRegistersOffset));
} }
} }

View file

@ -18,7 +18,9 @@
*/ */
package libKonogonka.fs.other.System2; package libKonogonka.fs.other.System2;
import libKonogonka.Converter;
import libKonogonka.KeyChainHolder; import libKonogonka.KeyChainHolder;
import libKonogonka.RainbowDump;
import libKonogonka.fs.ExportAble; import libKonogonka.fs.ExportAble;
import libKonogonka.fs.other.System2.ini1.Ini1Provider; import libKonogonka.fs.other.System2.ini1.Ini1Provider;
import libKonogonka.aesctr.InFileStreamProducer; import libKonogonka.aesctr.InFileStreamProducer;
@ -112,12 +114,26 @@ public class System2Provider extends ExportAble {
throw new Exception("Read failure " + actuallyRead); throw new Exception("Read failure " + actuallyRead);
byteBuffer.put(block); byteBuffer.put(block);
} }
byte[] searchField = byteBuffer.array(); byte[] searchField = byteBuffer.array();
for (int i = 0; i < 1024; i += 4) {
kernelMap = new KernelMap(searchField, i); if (Converter.getLEint(searchField, 3) == 0x14){ // If FW 17.0.0+
if (kernelMap.isValid(header.getSection0size())) // Calculate new location of the 'kernel beginning'
return; int branchTarget = (Converter.getLEint(searchField, 0) & 0x00FFFFFF) << 2;
int toSkip = branchTarget - 0x1000;
System.out.println("To skip = " + toSkip + " ");
if (toSkip != stream.skip(toSkip))
throw new Exception("Unable to skip offset of " + toSkip);
// TODO: really cursed shit
throw new Exception("FW 17+ not supported. WIP");
}
else {
for (int i = 0; i < 0x1000; i += 4) {
kernelMap = KernelMap.constructKernelMap(searchField, i, header.getSection0size());
if (kernelMap != null)
return;
}
} }
throw new Exception("Kernel map not found"); throw new Exception("Kernel map not found");
} }