mirror of
https://github.com/revanced/smali.git
synced 2025-05-20 16:07:05 +02:00
Add support for 64-bit oat files
This commit is contained in:
parent
e202aeede5
commit
b8e255f389
@ -97,6 +97,23 @@ public class BaseDexBuffer {
|
|||||||
(((long)buf[offset+7]) << 56);
|
(((long)buf[offset+7]) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int readLongAsSmallUint(int offset) {
|
||||||
|
byte[] buf = this.buf;
|
||||||
|
offset += baseOffset;
|
||||||
|
long result = (buf[offset] & 0xff) |
|
||||||
|
((buf[offset+1] & 0xff) << 8) |
|
||||||
|
((buf[offset+2] & 0xff) << 16) |
|
||||||
|
((buf[offset+3] & 0xffL) << 24) |
|
||||||
|
((buf[offset+4] & 0xffL) << 32) |
|
||||||
|
((buf[offset+5] & 0xffL) << 40) |
|
||||||
|
((buf[offset+6] & 0xffL) << 48) |
|
||||||
|
(((long)buf[offset+7]) << 56);
|
||||||
|
if (result < 0 || result > Integer.MAX_VALUE) {
|
||||||
|
throw new ExceptionWithContext("Encountered out-of-range ulong at offset 0x%x", offset);
|
||||||
|
}
|
||||||
|
return (int)result;
|
||||||
|
}
|
||||||
|
|
||||||
public int readInt(int offset) {
|
public int readInt(int offset) {
|
||||||
byte[] buf = this.buf;
|
byte[] buf = this.buf;
|
||||||
offset += baseOffset;
|
offset += baseOffset;
|
||||||
|
@ -49,7 +49,7 @@ import java.util.List;
|
|||||||
public class OatFile extends BaseDexBuffer {
|
public class OatFile extends BaseDexBuffer {
|
||||||
private static final byte[] ELF_MAGIC = new byte[] { 0x7f, 'E', 'L', 'F' };
|
private static final byte[] ELF_MAGIC = new byte[] { 0x7f, 'E', 'L', 'F' };
|
||||||
private static final byte[] OAT_MAGIC = new byte[] { 'o', 'a', 't', '\n' };
|
private static final byte[] OAT_MAGIC = new byte[] { 'o', 'a', 't', '\n' };
|
||||||
private static final int ELF_HEADER_SIZE = 52;
|
private static final int MIN_ELF_HEADER_SIZE = 52;
|
||||||
|
|
||||||
// These are the "known working" versions that I have manually inspected the source for.
|
// These are the "known working" versions that I have manually inspected the source for.
|
||||||
// Later version may or may not work, depending on what changed.
|
// Later version may or may not work, depending on what changed.
|
||||||
@ -60,18 +60,27 @@ public class OatFile extends BaseDexBuffer {
|
|||||||
public static final int SUPPORTED = 1;
|
public static final int SUPPORTED = 1;
|
||||||
public static final int UNKNOWN = 2;
|
public static final int UNKNOWN = 2;
|
||||||
|
|
||||||
|
private final boolean is64bit;
|
||||||
@Nonnull private final OatHeader oatHeader;
|
@Nonnull private final OatHeader oatHeader;
|
||||||
@Nonnull private final Opcodes opcodes;
|
@Nonnull private final Opcodes opcodes;
|
||||||
|
|
||||||
public OatFile(@Nonnull byte[] buf) {
|
public OatFile(@Nonnull byte[] buf) {
|
||||||
super(buf);
|
super(buf);
|
||||||
|
|
||||||
if (buf.length < ELF_HEADER_SIZE) {
|
if (buf.length < MIN_ELF_HEADER_SIZE) {
|
||||||
throw new NotAnOatFileException();
|
throw new NotAnOatFileException();
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyMagic(buf);
|
verifyMagic(buf);
|
||||||
|
|
||||||
|
if (buf[4] == 1) {
|
||||||
|
is64bit = false;
|
||||||
|
} else if (buf[4] == 2) {
|
||||||
|
is64bit = true;
|
||||||
|
} else {
|
||||||
|
throw new InvalidOatFileException(String.format("Invalid word-size value: %x", buf[5]));
|
||||||
|
}
|
||||||
|
|
||||||
OatHeader oatHeader = null;
|
OatHeader oatHeader = null;
|
||||||
SymbolTable symbolTable = getSymbolTable();
|
SymbolTable symbolTable = getSymbolTable();
|
||||||
for (Symbol symbol: symbolTable.getSymbols()) {
|
for (Symbol symbol: symbolTable.getSymbols()) {
|
||||||
@ -258,9 +267,18 @@ public class OatFile extends BaseDexBuffer {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private List<SectionHeader> getSections() {
|
private List<SectionHeader> getSections() {
|
||||||
final int offset = readSmallUint(32);
|
final int offset;
|
||||||
final int entrySize = readUshort(46);
|
final int entrySize;
|
||||||
final int entryCount = readUshort(48);
|
final int entryCount;
|
||||||
|
if (is64bit) {
|
||||||
|
offset = readLongAsSmallUint(40);
|
||||||
|
entrySize = readUshort(58);
|
||||||
|
entryCount = readUshort(60);
|
||||||
|
} else {
|
||||||
|
offset = readSmallUint(32);
|
||||||
|
entrySize = readUshort(46);
|
||||||
|
entryCount = readUshort(48);
|
||||||
|
}
|
||||||
|
|
||||||
if (offset + (entrySize * entryCount) > buf.length) {
|
if (offset + (entrySize * entryCount) > buf.length) {
|
||||||
throw new InvalidOatFileException("The ELF section headers extend past the end of the file");
|
throw new InvalidOatFileException("The ELF section headers extend past the end of the file");
|
||||||
@ -271,7 +289,11 @@ public class OatFile extends BaseDexBuffer {
|
|||||||
if (index < 0 || index >= entryCount) {
|
if (index < 0 || index >= entryCount) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return new SectionHeader(offset + (index * entrySize));
|
if (is64bit) {
|
||||||
|
return new SectionHeader64Bit(offset + (index * entrySize));
|
||||||
|
} else {
|
||||||
|
return new SectionHeader32Bit(offset + (index * entrySize));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int size() {
|
@Override public int size() {
|
||||||
@ -304,43 +326,35 @@ public class OatFile extends BaseDexBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SectionHeader {
|
private abstract class SectionHeader {
|
||||||
private final int offset;
|
protected final int offset;
|
||||||
|
|
||||||
public static final int TYPE_DYNAMIC_SYMBOL_TABLE = 11;
|
public static final int TYPE_DYNAMIC_SYMBOL_TABLE = 11;
|
||||||
|
public SectionHeader(int offset) { this.offset = offset; }
|
||||||
|
@Nonnull public String getName() { return getSectionNameStringTable().getString(readSmallUint(offset)); }
|
||||||
|
public int getType() { return readInt(offset + 4); }
|
||||||
|
public abstract long getAddress();
|
||||||
|
public abstract int getOffset();
|
||||||
|
public abstract int getSize();
|
||||||
|
public abstract int getLink();
|
||||||
|
public abstract int getEntrySize();
|
||||||
|
}
|
||||||
|
|
||||||
public SectionHeader(int offset) {
|
private class SectionHeader32Bit extends SectionHeader {
|
||||||
this.offset = offset;
|
public SectionHeader32Bit(int offset) { super(offset); }
|
||||||
}
|
@Override public long getAddress() { return readInt(offset + 12) & 0xFFFFFFFFL; }
|
||||||
|
@Override public int getOffset() { return readSmallUint(offset + 16); }
|
||||||
|
@Override public int getSize() { return readSmallUint(offset + 20); }
|
||||||
|
@Override public int getLink() { return readSmallUint(offset + 24); }
|
||||||
|
@Override public int getEntrySize() { return readSmallUint(offset + 36); }
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
private class SectionHeader64Bit extends SectionHeader {
|
||||||
public String getName() {
|
public SectionHeader64Bit(int offset) { super(offset); }
|
||||||
return getSectionNameStringTable().getString(readSmallUint(offset));
|
@Override public long getAddress() { return readLong(offset + 16); }
|
||||||
}
|
@Override public int getOffset() { return readLongAsSmallUint(offset + 24); }
|
||||||
|
@Override public int getSize() { return readLongAsSmallUint(offset + 32); }
|
||||||
public int getType() {
|
@Override public int getLink() { return readSmallUint(offset + 40); }
|
||||||
return readInt(offset + 4);
|
@Override public int getEntrySize() { return readLongAsSmallUint(offset + 56); }
|
||||||
}
|
|
||||||
|
|
||||||
public long getAddress() {
|
|
||||||
return readInt(offset + 12) & 0xFFFFFFFFL;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOffset() {
|
|
||||||
return readSmallUint(offset + 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
return readSmallUint(offset + 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLink() {
|
|
||||||
return readSmallUint(offset + 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getEntrySize() {
|
|
||||||
return readSmallUint(offset + 36);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SymbolTable {
|
class SymbolTable {
|
||||||
@ -371,7 +385,11 @@ public class OatFile extends BaseDexBuffer {
|
|||||||
if (index < 0 || index >= entryCount) {
|
if (index < 0 || index >= entryCount) {
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
return new Symbol(offset + index * entrySize);
|
if (is64bit) {
|
||||||
|
return new Symbol64(offset + index * entrySize);
|
||||||
|
} else {
|
||||||
|
return new Symbol32(offset + index * entrySize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int size() {
|
@Override public int size() {
|
||||||
@ -380,29 +398,13 @@ public class OatFile extends BaseDexBuffer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Symbol {
|
public abstract class Symbol {
|
||||||
private final int offset;
|
protected final int offset;
|
||||||
|
public Symbol(int offset) { this.offset = offset; }
|
||||||
public Symbol(int offset) {
|
@Nonnull public abstract String getName();
|
||||||
this.offset = offset;
|
public abstract long getValue();
|
||||||
}
|
public abstract int getSize();
|
||||||
|
public abstract int getSectionIndex();
|
||||||
@Nonnull
|
|
||||||
public String getName() {
|
|
||||||
return stringTable.getString(readSmallUint(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValue() {
|
|
||||||
return readSmallUint(offset + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
return readSmallUint(offset + 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSectionIndex() {
|
|
||||||
return readUshort(offset + 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFileOffset() {
|
public int getFileOffset() {
|
||||||
SectionHeader sectionHeader;
|
SectionHeader sectionHeader;
|
||||||
@ -427,6 +429,26 @@ public class OatFile extends BaseDexBuffer {
|
|||||||
return (int)fileOffset;
|
return (int)fileOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Symbol32 extends Symbol {
|
||||||
|
public Symbol32(int offset) { super(offset); }
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public String getName() { return stringTable.getString(readSmallUint(offset)); }
|
||||||
|
public long getValue() { return readSmallUint(offset + 4); }
|
||||||
|
public int getSize() { return readSmallUint(offset + 8); }
|
||||||
|
public int getSectionIndex() { return readUshort(offset + 14); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Symbol64 extends Symbol {
|
||||||
|
public Symbol64(int offset) { super(offset); }
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public String getName() { return stringTable.getString(readSmallUint(offset)); }
|
||||||
|
public long getValue() { return readLong(offset + 8); }
|
||||||
|
public int getSize() { return readLongAsSmallUint(offset + 16); }
|
||||||
|
public int getSectionIndex() { return readUshort(offset + 6); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StringTable {
|
private class StringTable {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user