mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-20 10:37:27 +08:00
Merge branch 'GP-804_GhidraKnight_NewAndroidSupport'
This commit is contained in:
@@ -23,6 +23,7 @@ import ghidra.app.util.Option;
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.file.formats.android.dex.DexHeaderFactory;
|
||||
import ghidra.file.formats.android.dex.format.*;
|
||||
import ghidra.file.formats.android.dex.util.DexUtil;
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -46,7 +47,7 @@ public class DexLoader extends AbstractLibrarySupportLoader {
|
||||
|
||||
BinaryReader reader = new BinaryReader(provider, true);
|
||||
try {
|
||||
DexHeader header = new DexHeader(reader);
|
||||
DexHeader header = DexHeaderFactory.getDexHeader(reader);
|
||||
if (DexConstants.DEX_MAGIC_BASE.equals(new String(header.getMagic()))) {
|
||||
List<QueryResult> queries =
|
||||
QueryOpinionService.query(getName(), DexConstants.MACHINE, null);
|
||||
@@ -80,7 +81,7 @@ public class DexLoader extends AbstractLibrarySupportLoader {
|
||||
}
|
||||
|
||||
BinaryReader reader = new BinaryReader( provider, true );
|
||||
DexHeader header = new DexHeader( reader );
|
||||
DexHeader header = DexHeaderFactory.getDexHeader( reader );
|
||||
|
||||
monitor.setMessage( "DEX Loader: creating method byte code" );
|
||||
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.apex;
|
||||
|
||||
/**
|
||||
* Android Pony EXpress (ApexContants)
|
||||
*
|
||||
* https://source.android.com/devices/tech/ota/apex
|
||||
*
|
||||
* https://android.googlesource.com/platform/system/apex/+/refs/heads/master/apexd/apex_constants.h
|
||||
*/
|
||||
public class ApexContants {
|
||||
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.app.util.opinion.BinaryLoader;
|
||||
import ghidra.file.analyzers.FileFormatAnalyzer;
|
||||
import ghidra.file.formats.android.oat.OatConstants;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class ArtAnalyzer extends FileFormatAnalyzer {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Android ART Header Format";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getDefaultEnablement(Program program) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Analyzes the Android ART information in this program.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
return ArtConstants.isART(program)
|
||||
//HACK:
|
||||
//Make analyzer appear after ART is merged with OAT program
|
||||
//Currently, analyzers will not recognize the new ART block being added
|
||||
|| OatConstants.isOAT(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrototype() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean analyze(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws Exception {
|
||||
Address address = ArtConstants.findART(program);
|
||||
|
||||
if (address == null) {//ART does not exist so quit, could be OAT
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteProvider provider = new MemoryByteProvider(program.getMemory(), address);
|
||||
BinaryReader reader = new BinaryReader(provider, !program.getLanguage().isBigEndian());
|
||||
|
||||
try {
|
||||
ArtHeader header = ArtFactory.newArtHeader(reader);
|
||||
|
||||
DataType headerDataType = header.toDataType();
|
||||
|
||||
//only set "image base" when ART header not defined at "image begin"
|
||||
//---this really only opens when ART is "added to" OAT program
|
||||
Address imageBase = toAddr(program, header.getImageBegin());
|
||||
|
||||
if (BinaryLoader.BINARY_NAME.equals(program.getExecutableFormat())) {
|
||||
program.setImageBase(imageBase, true);
|
||||
createData(program, imageBase, headerDataType);
|
||||
}
|
||||
else {
|
||||
createData(program, address, headerDataType);
|
||||
}
|
||||
|
||||
header.markup(program, monitor);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (UnsupportedArtVersionException e) {
|
||||
log.appendException(e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/image.h
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ArtBlock implements StructConverter, ArtCompression {
|
||||
|
||||
private ArtStorageMode storage_mode_ = ArtStorageMode.kDefaultStorageMode;
|
||||
private int data_offset_;
|
||||
private int data_size_;
|
||||
private int image_offset_;
|
||||
private int image_size_;
|
||||
|
||||
public ArtBlock(BinaryReader reader) throws IOException {
|
||||
storage_mode_ = ArtStorageMode.get(reader.readNextInt());
|
||||
data_offset_ = reader.readNextInt();
|
||||
data_size_ = reader.readNextInt();
|
||||
image_offset_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArtStorageMode getStorageMode() {
|
||||
return storage_mode_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCompressedOffset() {
|
||||
return Integer.toUnsignedLong(data_offset_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompressedSize() {
|
||||
return data_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDecompressedOffset() {
|
||||
return Integer.toUnsignedLong(image_offset_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecompressedSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
public int getDataOffset() {
|
||||
return data_offset_;
|
||||
}
|
||||
|
||||
public int getDataSize() {
|
||||
return data_size_;
|
||||
}
|
||||
|
||||
public int getImageOffset() {
|
||||
return image_offset_;
|
||||
}
|
||||
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
String name = StructConverterUtil.parseName(ArtBlock.class);
|
||||
Structure structure = new StructureDataType(name, 0);
|
||||
structure.setCategoryPath(new CategoryPath("/art"));
|
||||
structure.add(DWORD, "storage_mode_", storage_mode_.name());
|
||||
structure.add(DWORD, "data_offset_", null);
|
||||
structure.add(DWORD, "data_size_", null);
|
||||
structure.add(DWORD, "image_offset_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
public interface ArtCompression {
|
||||
|
||||
/**
|
||||
* Storage method for the image, the image may be compressed.
|
||||
* @return the storage method
|
||||
* @throws UnknownArtStorageModeException when an unknown storage mode is encountered
|
||||
*/
|
||||
public ArtStorageMode getStorageMode() throws UnknownArtStorageModeException;
|
||||
|
||||
/**
|
||||
* Data size for the image data excluding the bitmap and the header.
|
||||
* For compressed images, this is the compressed size in the file.
|
||||
* @return the compressed size
|
||||
*/
|
||||
public int getCompressedSize();
|
||||
|
||||
/**
|
||||
* Offset to the start of the compressed bytes.
|
||||
* Also, offset of where to place the decompressed bytes.
|
||||
* @return the offset to the compressed bytes
|
||||
*/
|
||||
public long getCompressedOffset();
|
||||
|
||||
/**
|
||||
* Expected size of the decompressed bytes.
|
||||
* @return the expected decompressed size
|
||||
*/
|
||||
public int getDecompressedSize();
|
||||
|
||||
/**
|
||||
* Offset to the start of the decompressed bytes.
|
||||
* @return the offset to the dcompressed bytes
|
||||
*/
|
||||
public long getDecompressedOffset();
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/master/runtime/image.cc
|
||||
*/
|
||||
public final class ArtConstants {
|
||||
|
||||
public final static String ART_NAME = "Android Runtime (ART)";
|
||||
|
||||
public final static String MAGIC = "art\n";
|
||||
|
||||
public final static int VERSION_LENGTH = 4;
|
||||
|
||||
public final static String VERSION_KITKAT_RELEASE = "005";
|
||||
public final static String VERSION_LOLLIPOP_RELEASE = "009";
|
||||
public final static String VERSION_LOLLIPOP_MR1_WFC_RELEASE = "012";
|
||||
public final static String VERSION_MARSHMALLOW_RELEASE = "017";
|
||||
public final static String VERSION_NOUGAT_RELEASE = "029";
|
||||
public final static String VERSION_NOUGAT_MR2_PIXEL_RELEASE = "030";
|
||||
public final static String VERSION_OREO_RELEASE = "043";
|
||||
public final static String VERSION_OREO_DR1_RELEASE = "044";
|
||||
public final static String VERSION_OREO_MR1_RELEASE = "046";
|
||||
public final static String VERSION_PIE_RELEASE = "056";
|
||||
public final static String VERSION_10_RELEASE = "074";//Q
|
||||
public final static String VERSION_11_RELEASE = "085";//R
|
||||
|
||||
// "005",// kitkat-release
|
||||
// "009",// lollipop-release
|
||||
// "012",// lollipop-mr1-wfc-release
|
||||
// "017",// marshmallow-release
|
||||
// "029",// nougat-release
|
||||
// "030",// nougat-mr2-pixel-release
|
||||
// "043",// oreo-release
|
||||
// "044",// taimen-op1
|
||||
// "046",// oreo-mr1-release
|
||||
// "051",//
|
||||
// "056",// pie-release
|
||||
// "059",// android-o-mr1-iot-release-1.0.0
|
||||
// "060",// android-o-mr1-iot-release-1.0.1
|
||||
// "061",// android-n-iot-release-polk-at1
|
||||
|
||||
/**
|
||||
* NOTE: only going to support RELEASE versions
|
||||
*/
|
||||
public final static String[] SUPPORTED_VERSIONS = new String[] {
|
||||
//@formatter:off
|
||||
VERSION_KITKAT_RELEASE,
|
||||
VERSION_LOLLIPOP_RELEASE,
|
||||
VERSION_LOLLIPOP_MR1_WFC_RELEASE,
|
||||
VERSION_MARSHMALLOW_RELEASE,
|
||||
VERSION_NOUGAT_RELEASE,
|
||||
VERSION_NOUGAT_MR2_PIXEL_RELEASE,
|
||||
VERSION_OREO_RELEASE,
|
||||
VERSION_OREO_DR1_RELEASE,
|
||||
VERSION_OREO_MR1_RELEASE,
|
||||
VERSION_PIE_RELEASE,
|
||||
VERSION_10_RELEASE,
|
||||
VERSION_11_RELEASE,
|
||||
//@formatter:on
|
||||
};
|
||||
|
||||
public final static boolean isSupportedVersion(String version) {
|
||||
for (String supportedVersion : SUPPORTED_VERSIONS) {
|
||||
if (supportedVersion.equals(version)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final static boolean isART(Program program) {
|
||||
if (program != null) {
|
||||
for (MemoryBlock block : program.getMemory().getBlocks()) {
|
||||
try {
|
||||
byte[] bytes = new byte[ArtConstants.MAGIC.length()];
|
||||
block.getBytes(block.getStart(), bytes);
|
||||
String magic = new String(bytes);
|
||||
if (ArtConstants.MAGIC.equals(magic)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final static Address findART(Program program) {
|
||||
if (program != null) {
|
||||
for (MemoryBlock block : program.getMemory().getBlocks()) {
|
||||
try {
|
||||
byte[] bytes = new byte[ArtConstants.MAGIC.length()];
|
||||
block.getBytes(block.getStart(), bytes);
|
||||
String magic = new String(bytes);
|
||||
if (ArtConstants.MAGIC.equals(magic)) {
|
||||
return block.getStart();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.file.formats.android.art.android10.ArtHeader_10;
|
||||
import ghidra.file.formats.android.art.android11.ArtHeader_11;
|
||||
import ghidra.file.formats.android.art.kitkat.ArtHeader_KitKat;
|
||||
import ghidra.file.formats.android.art.lollipop.ArtHeader_Lollipop;
|
||||
import ghidra.file.formats.android.art.lollipop.ArtHeader_LollipopMR1WFC;
|
||||
import ghidra.file.formats.android.art.marshmallow.ArtHeader_Marshmallow;
|
||||
import ghidra.file.formats.android.art.nougat.ArtHeader_Nougat;
|
||||
import ghidra.file.formats.android.art.nougat.ArtHeader_NougatMR2Pixel;
|
||||
import ghidra.file.formats.android.art.oreo.ArtHeader_Oreo;
|
||||
import ghidra.file.formats.android.art.oreo.ArtHeader_OreoMR1;
|
||||
import ghidra.file.formats.android.art.pie.ArtHeader_Pie;
|
||||
|
||||
public final class ArtFactory {
|
||||
|
||||
/**
|
||||
* Returns an ArtHeader of the correct version.
|
||||
* @param reader the BinaryReader to the ART header
|
||||
* @return the specific version of the ART header
|
||||
* @throws IOException should an error occur during reading or parsing
|
||||
* @throws UnsupportedArtVersionException when the provided version is invalid or not yet implemented.
|
||||
*/
|
||||
public final static ArtHeader newArtHeader(BinaryReader reader)
|
||||
throws IOException, UnsupportedArtVersionException {
|
||||
String magic = new String(reader.readByteArray(0, ArtConstants.MAGIC.length()));
|
||||
String version = reader.readAsciiString(4, 4);
|
||||
if (magic.equals(ArtConstants.MAGIC)) {
|
||||
if (ArtConstants.isSupportedVersion(version)) {
|
||||
switch (version ) {
|
||||
case ArtConstants.VERSION_KITKAT_RELEASE:
|
||||
return new ArtHeader_KitKat(reader);
|
||||
case ArtConstants.VERSION_LOLLIPOP_RELEASE:
|
||||
return new ArtHeader_Lollipop(reader);
|
||||
case ArtConstants.VERSION_LOLLIPOP_MR1_WFC_RELEASE:
|
||||
return new ArtHeader_LollipopMR1WFC(reader);
|
||||
case ArtConstants.VERSION_MARSHMALLOW_RELEASE:
|
||||
return new ArtHeader_Marshmallow(reader);
|
||||
case ArtConstants.VERSION_NOUGAT_RELEASE:
|
||||
return new ArtHeader_Nougat(reader);
|
||||
case ArtConstants.VERSION_NOUGAT_MR2_PIXEL_RELEASE:
|
||||
return new ArtHeader_NougatMR2Pixel(reader);
|
||||
case ArtConstants.VERSION_OREO_RELEASE:
|
||||
return new ArtHeader_Oreo(reader);
|
||||
case ArtConstants.VERSION_OREO_DR1_RELEASE:
|
||||
return new ArtHeader_Oreo(reader);//v043 and v044 are same format
|
||||
case ArtConstants.VERSION_OREO_MR1_RELEASE:
|
||||
return new ArtHeader_OreoMR1(reader);
|
||||
case ArtConstants.VERSION_PIE_RELEASE:
|
||||
return new ArtHeader_Pie(reader);
|
||||
case ArtConstants.VERSION_10_RELEASE:
|
||||
return new ArtHeader_10(reader);
|
||||
case ArtConstants.VERSION_11_RELEASE:
|
||||
return new ArtHeader_11(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new UnsupportedArtVersionException(magic, version);
|
||||
}
|
||||
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/art_field.h
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ArtField implements StructConverter {
|
||||
|
||||
private int declaring_class_;
|
||||
private int access_flags_;
|
||||
private int field_dex_idx_;
|
||||
private int offset_;
|
||||
|
||||
public ArtField(BinaryReader reader) throws IOException {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
field_dex_idx_ = reader.readNextInt();
|
||||
offset_ = reader.readNextInt();
|
||||
}
|
||||
|
||||
public int getDeclaringClass() {
|
||||
return declaring_class_;
|
||||
}
|
||||
|
||||
public int getAccessFlags() {
|
||||
return access_flags_;
|
||||
}
|
||||
|
||||
public int getFieldDexIndex() {
|
||||
return field_dex_idx_;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
String name = StructConverterUtil.parseName(ArtField.class);
|
||||
Structure structure = new StructureDataType(name, 0);
|
||||
structure.setCategoryPath(new CategoryPath("/art"));
|
||||
structure.add(new Pointer32DataType(), "declaring_class_", null);
|
||||
structure.add(DWORD, "access_flags_", null);
|
||||
structure.add(DWORD, "field_dex_idx_", null);
|
||||
structure.add(DWORD, "offset_", null);
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/art_field.h
|
||||
*
|
||||
* NOTE: this class does not exist, was created to make field reading easier.
|
||||
*/
|
||||
public class ArtFieldGroup implements StructConverter {
|
||||
|
||||
private int fieldCount;
|
||||
private List<ArtField> fieldList = new ArrayList<>();
|
||||
|
||||
public ArtFieldGroup(BinaryReader reader) throws IOException {
|
||||
fieldCount = reader.readNextInt();
|
||||
if (fieldCount > 0xffff) {//sanity check...
|
||||
throw new IOException("Too many ART fields: " + fieldCount);
|
||||
}
|
||||
for (int i = 0; i < fieldCount; ++i) {
|
||||
fieldList.add(new ArtField(reader));
|
||||
}
|
||||
}
|
||||
|
||||
public int getFieldCount() {
|
||||
return fieldCount;
|
||||
}
|
||||
|
||||
public List<ArtField> getFieldList() {
|
||||
return fieldList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
String name = StructConverterUtil.parseName(ArtFieldGroup.class);
|
||||
Structure structure = new StructureDataType(name + "_" + fieldCount, 0);
|
||||
structure.setCategoryPath(new CategoryPath("/art"));
|
||||
structure.add(DWORD, "fieldCount", null);
|
||||
for (int i = 0; i < fieldCount; ++i) {
|
||||
structure.add(fieldList.get(i).toDataType(), "field_" + i, null);
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/marshmallow-release/runtime/image.h
|
||||
*/
|
||||
public abstract class ArtHeader implements StructConverter {
|
||||
|
||||
protected String magic_;
|
||||
protected String version_;
|
||||
|
||||
protected List<Long> imageMethodsList = new ArrayList<>();
|
||||
|
||||
protected ArtHeader(BinaryReader reader) throws IOException {
|
||||
magic_ = new String(reader.readNextByteArray(ArtConstants.MAGIC.length()));
|
||||
version_ = reader.readNextAsciiString(ArtConstants.VERSION_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the magic string: "art\n".
|
||||
* @return the magic string
|
||||
*/
|
||||
public final String getMagic() {
|
||||
return magic_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version string: eg, "001", "017"
|
||||
* @return the version
|
||||
*/
|
||||
public final String getVersion() {
|
||||
return version_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required base address for mapping the image.
|
||||
*
|
||||
* Base address of the ART file.
|
||||
* -1 indicates unsupported
|
||||
* @return image base address
|
||||
*/
|
||||
abstract public int getImageBegin();
|
||||
|
||||
/**
|
||||
* Required base size for mapping the image.
|
||||
* -1 indicates unsupported
|
||||
* @return image size
|
||||
*/
|
||||
abstract public int getImageSize();
|
||||
|
||||
/**
|
||||
* Returns the checksum of the matching OAT file.
|
||||
* The checksum is stored in the OAT header and is generated using Adler32.
|
||||
* -1 indicates unsupported
|
||||
* @return oat checksum
|
||||
*/
|
||||
abstract public int getOatChecksum();
|
||||
|
||||
/**
|
||||
* -1 indicates unsupported
|
||||
* @return the oat file begin address
|
||||
*/
|
||||
abstract public int getOatFileBegin();
|
||||
|
||||
/**
|
||||
* -1 indicates unsupported
|
||||
* @return the oat file end address
|
||||
*/
|
||||
abstract public int getOatFileEnd();
|
||||
|
||||
/**
|
||||
* Returns the offset to the start of the .oatdata section,
|
||||
* usually defined within the ".rodata" section.
|
||||
* -1 indicates unsupported
|
||||
* @return the oat data begin address
|
||||
*/
|
||||
abstract public int getOatDataBegin();
|
||||
|
||||
/**
|
||||
* -1 indicates unsupported
|
||||
* @return the oat data end address
|
||||
*/
|
||||
abstract public int getOatDataEnd();
|
||||
|
||||
/**
|
||||
* Pointer size (in bytes).
|
||||
* @return the pointer size
|
||||
*/
|
||||
abstract public int getPointerSize();
|
||||
|
||||
abstract public int getArtMethodCountForVersion();
|
||||
|
||||
/**
|
||||
* Parses the ART header data.
|
||||
* @param reader the binary reader
|
||||
* @throws IOException if an error occurs parsing the header
|
||||
*/
|
||||
abstract protected void parse(BinaryReader reader) throws IOException;
|
||||
|
||||
protected final void parseImageMethods(BinaryReader reader) throws IOException {
|
||||
for (int i = 0; i < getArtMethodCountForVersion(); ++i) {
|
||||
imageMethodsList.add(reader.readNextLong());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows each specific version to mark-up the specified program.
|
||||
* @param program the program to markup
|
||||
* @param monitor the task monitor
|
||||
* @throws Exception if an error occurs while marking up the program
|
||||
*/
|
||||
abstract public void markup(Program program, TaskMonitor monitor) throws Exception;
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
String className = StructConverterUtil.parseName(ArtHeader.class);
|
||||
Structure structure = new StructureDataType(className, 0);
|
||||
structure.add(STRING, 4, "magic_", null);
|
||||
structure.add(STRING, 4, "version_", null);
|
||||
structure.setCategoryPath(new CategoryPath("/art"));
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.CategoryPath;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class ArtImageSection implements StructConverter {
|
||||
private int offset_;
|
||||
private int size_;
|
||||
|
||||
public ArtImageSection(BinaryReader reader) throws IOException {
|
||||
offset_ = reader.readNextInt();
|
||||
size_ = reader.readNextInt();
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset_;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size_;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return offset_ + size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
DataType dataType = StructConverterUtil.toDataType(ArtImageSection.class);
|
||||
dataType.setCategoryPath(new CategoryPath("/art"));
|
||||
return dataType;
|
||||
}
|
||||
|
||||
}
|
||||
+522
File diff suppressed because it is too large
Load Diff
+402
@@ -0,0 +1,402 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/art_method.h
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ArtMethod implements StructConverter {
|
||||
private final int pointerSize;
|
||||
private final String artVersion;
|
||||
|
||||
private int declaring_class_;
|
||||
private int access_flags_;
|
||||
private int dex_code_item_offset_;
|
||||
private int dex_method_index_;
|
||||
private short method_index_;
|
||||
private short hotness_count_;
|
||||
private short imt_index_;
|
||||
private short padding_;
|
||||
|
||||
private long dex_cache_resolved_methods_;
|
||||
private long dex_cache_resolved_types_;
|
||||
private long entry_point_from_interpreter_;
|
||||
private long entry_point_from_jni_;
|
||||
private long data_;
|
||||
private long unknown1_;
|
||||
private long entry_point_from_quick_compiled_code_;
|
||||
private int unknown2_;
|
||||
|
||||
public ArtMethod(BinaryReader reader, int pointerSize, String artVersion) throws IOException {
|
||||
this.pointerSize = pointerSize;
|
||||
this.artVersion = artVersion;
|
||||
|
||||
if (ArtConstants.VERSION_MARSHMALLOW_RELEASE.equals(artVersion)) {
|
||||
if (pointerSize == 4) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
dex_cache_resolved_methods_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
dex_cache_resolved_types_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
padding_ = reader.readNextShort();
|
||||
entry_point_from_interpreter_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
entry_point_from_jni_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
entry_point_from_quick_compiled_code_ =
|
||||
Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
throw new IOException("Unsupported 64-bit ART method format: " + artVersion);
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_NOUGAT_RELEASE.equals(artVersion) ||
|
||||
ArtConstants.VERSION_NOUGAT_MR2_PIXEL_RELEASE.equals(artVersion)) {
|
||||
|
||||
if (pointerSize == 4) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
hotness_count_ = reader.readNextShort();
|
||||
dex_cache_resolved_methods_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
dex_cache_resolved_types_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
entry_point_from_jni_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
entry_point_from_quick_compiled_code_ =
|
||||
Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
hotness_count_ = reader.readNextShort();
|
||||
imt_index_ = reader.readNextShort();
|
||||
padding_ = reader.readNextShort();
|
||||
dex_cache_resolved_methods_ = reader.readNextLong();
|
||||
dex_cache_resolved_types_ = reader.readNextLong();
|
||||
entry_point_from_jni_ = reader.readNextLong();
|
||||
entry_point_from_quick_compiled_code_ = reader.readNextLong();
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_OREO_RELEASE.equals(artVersion) ||
|
||||
ArtConstants.VERSION_OREO_DR1_RELEASE.equals(artVersion) ||
|
||||
ArtConstants.VERSION_OREO_MR1_RELEASE.equals(artVersion)) {
|
||||
|
||||
if (pointerSize == 4) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
hotness_count_ = reader.readNextShort();
|
||||
data_ = reader.readNextLong();
|
||||
entry_point_from_quick_compiled_code_ =
|
||||
Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
hotness_count_ = reader.readNextShort();
|
||||
imt_index_ = reader.readNextShort();
|
||||
padding_ = reader.readNextShort();
|
||||
data_ = reader.readNextLong();
|
||||
unknown1_ = reader.readNextLong();
|
||||
entry_point_from_quick_compiled_code_ = reader.readNextLong();
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_PIE_RELEASE.equals(artVersion)) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
hotness_count_ = reader.readNextShort();
|
||||
imt_index_ = reader.readNextShort();
|
||||
padding_ = reader.readNextShort();
|
||||
|
||||
if (pointerSize == 4) {
|
||||
data_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
data_ = reader.readNextLong();
|
||||
entry_point_from_quick_compiled_code_ = reader.readNextLong();
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_10_RELEASE.equals(artVersion)) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
hotness_count_ = reader.readNextShort();
|
||||
imt_index_ = reader.readNextShort();
|
||||
padding_ = reader.readNextShort();
|
||||
|
||||
if (pointerSize == 4) {
|
||||
data_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
data_ = reader.readNextLong();
|
||||
entry_point_from_quick_compiled_code_ = reader.readNextLong();
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_11_RELEASE.equals(artVersion)) {
|
||||
declaring_class_ = reader.readNextInt();
|
||||
access_flags_ = reader.readNextInt();
|
||||
dex_code_item_offset_ = reader.readNextInt();
|
||||
dex_method_index_ = reader.readNextInt();
|
||||
method_index_ = reader.readNextShort();
|
||||
hotness_count_ = reader.readNextShort();
|
||||
imt_index_ = reader.readNextShort();
|
||||
padding_ = reader.readNextShort();
|
||||
|
||||
if (pointerSize == 4) {
|
||||
data_ = Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
data_ = reader.readNextLong();
|
||||
entry_point_from_quick_compiled_code_ = reader.readNextLong();
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IOException("Unsupported ART method format: " + artVersion);
|
||||
}
|
||||
}
|
||||
|
||||
public int getDeclaringClass() {
|
||||
return declaring_class_;
|
||||
}
|
||||
|
||||
public int getAccessFlags() {
|
||||
return access_flags_;
|
||||
}
|
||||
|
||||
public int getDexCodeItemOffset() {
|
||||
return dex_code_item_offset_;
|
||||
}
|
||||
|
||||
public int getDexMethodIndex() {
|
||||
return dex_method_index_;
|
||||
}
|
||||
|
||||
public short getMethodIndex() {
|
||||
return method_index_;
|
||||
}
|
||||
|
||||
public short getHotnessCount() {
|
||||
return hotness_count_;
|
||||
}
|
||||
|
||||
public short getImtIndex() {
|
||||
return imt_index_;
|
||||
}
|
||||
|
||||
public short getPadding() {
|
||||
return padding_;
|
||||
}
|
||||
|
||||
public long getData() {
|
||||
return data_;
|
||||
}
|
||||
|
||||
public long getEntryPointFromInterpreter() {
|
||||
return entry_point_from_interpreter_;
|
||||
}
|
||||
|
||||
public long getEntryPointFromQuickCompiledCode() {
|
||||
return entry_point_from_quick_compiled_code_;
|
||||
}
|
||||
|
||||
public long getDexCacheResolvedMethods() {
|
||||
return dex_cache_resolved_methods_;
|
||||
}
|
||||
|
||||
public long getDexCacheResolvedTypes() {
|
||||
return dex_cache_resolved_types_;
|
||||
}
|
||||
|
||||
public long getEntryPointFromJNI() {
|
||||
return entry_point_from_jni_;
|
||||
}
|
||||
|
||||
public long getUnknown1() {
|
||||
return unknown1_;
|
||||
}
|
||||
|
||||
public int getUnknown2() {
|
||||
return unknown2_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
DataType ptr32 = new Pointer32DataType();
|
||||
DataType ptr64 = new Pointer64DataType();
|
||||
|
||||
String name = StructConverterUtil.parseName(ArtMethod.class);
|
||||
Structure struct = new StructureDataType(name, 0);
|
||||
struct.setCategoryPath(new CategoryPath("/art"));
|
||||
|
||||
if (ArtConstants.VERSION_MARSHMALLOW_RELEASE.equals(artVersion)) {
|
||||
if (pointerSize == 4) {
|
||||
struct.add(DWORD, "declaring_class_", null);
|
||||
struct.add(DWORD, "dex_cache_resolved_methods_", null);
|
||||
struct.add(DWORD, "dex_cache_resolved_types_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "padding_", null);
|
||||
struct.add(DWORD, "entry_point_from_interpreter_", null);
|
||||
struct.add(DWORD, "entry_point_from_jni_", null);
|
||||
struct.add(DWORD, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
throw new IOException("Unsupported 64-bit ART method format: " + artVersion);
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_NOUGAT_RELEASE.equals(artVersion) ||
|
||||
ArtConstants.VERSION_NOUGAT_MR2_PIXEL_RELEASE.equals(artVersion)) {
|
||||
|
||||
if (pointerSize == 4) {
|
||||
struct.add(ptr32, "declaring_class_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "hotness_count_", null);
|
||||
struct.add(DWORD, "dex_cache_resolved_methods_", null);
|
||||
struct.add(DWORD, "dex_cache_resolved_types_", null);
|
||||
struct.add(ptr32, "entry_point_from_jni_", null);
|
||||
struct.add(ptr32, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
struct.add(ptr32, "declaring_class_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "hotness_count_", null);
|
||||
struct.add(WORD, "imt_index_", null);
|
||||
struct.add(WORD, "padding", null);
|
||||
struct.add(QWORD, "dex_cache_resolved_methods_", null);
|
||||
struct.add(QWORD, "dex_cache_resolved_types_", null);
|
||||
struct.add(ptr64, "entry_point_from_jni_", null);
|
||||
struct.add(ptr64, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_OREO_RELEASE.equals(artVersion) ||
|
||||
ArtConstants.VERSION_OREO_DR1_RELEASE.equals(artVersion) ||
|
||||
ArtConstants.VERSION_OREO_MR1_RELEASE.equals(artVersion)) {
|
||||
|
||||
if (pointerSize == 4) {
|
||||
struct.add(ptr32, "declaring_class_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "hotness_count_", null);
|
||||
struct.add(QWORD, "data", null);
|
||||
struct.add(ptr32, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
struct.add(ptr32, "declaring_class_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "hotness_count_", null);
|
||||
struct.add(WORD, "imt_index_", null);
|
||||
struct.add(WORD, "padding", null);
|
||||
struct.add(QWORD, "data", null);
|
||||
struct.add(QWORD, "unknown1_", null);
|
||||
struct.add(ptr64, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_PIE_RELEASE.equals(artVersion)) {
|
||||
struct.add(ptr32, "declaring_class_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "hotness_count_", null);
|
||||
struct.add(WORD, "imt_index_", null);
|
||||
struct.add(WORD, "padding", null);
|
||||
|
||||
if (pointerSize == 4) {
|
||||
struct.add(DWORD, "data", null);
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
struct.add(QWORD, "data", null);
|
||||
struct.add(QWORD, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_10_RELEASE.equals(artVersion)) {
|
||||
struct.add(ptr32, "declaring_class_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "hotness_count_", null);
|
||||
struct.add(WORD, "imt_index_", null);
|
||||
struct.add(WORD, "padding", null);
|
||||
|
||||
if (pointerSize == 4) {
|
||||
struct.add(DWORD, "data", null);
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
struct.add(QWORD, "data", null);
|
||||
struct.add(ptr64, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
}
|
||||
else if (ArtConstants.VERSION_11_RELEASE.equals(artVersion)) {
|
||||
struct.add(ptr32, "declaring_class_", null);
|
||||
struct.add(DWORD, "access_flags_", null);
|
||||
struct.add(DWORD, "dex_code_item_offset_", null);
|
||||
struct.add(DWORD, "dex_method_index_", null);
|
||||
struct.add(WORD, "method_index_", null);
|
||||
struct.add(WORD, "hotness_count_", null);
|
||||
struct.add(WORD, "imt_index_", null);
|
||||
struct.add(WORD, "padding", null);
|
||||
|
||||
if (pointerSize == 4) {
|
||||
struct.add(DWORD, "data", null);
|
||||
}
|
||||
else if (pointerSize == 8) {
|
||||
struct.add(QWORD, "data", null);
|
||||
struct.add(QWORD, "entry_point_from_quick_compiled_code_", null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IOException("Unsupported ART method format: " + artVersion);
|
||||
}
|
||||
return struct;
|
||||
}
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/art_method.h
|
||||
*
|
||||
* NOTE: this class does not exist, was created to make method reading easier.
|
||||
*/
|
||||
public class ArtMethodGroup implements StructConverter {
|
||||
|
||||
private int pointerSize;
|
||||
|
||||
private long methodCount;
|
||||
private List<ArtMethod> methodList = new ArrayList<>();
|
||||
|
||||
public ArtMethodGroup(BinaryReader reader, int pointerSize, String artVersion)
|
||||
throws IOException {
|
||||
this.pointerSize = pointerSize;
|
||||
|
||||
if (pointerSize == 8) {
|
||||
methodCount = reader.readNextLong();
|
||||
}
|
||||
else if (pointerSize == 4) {
|
||||
methodCount = Integer.toUnsignedLong(reader.readNextInt());
|
||||
}
|
||||
|
||||
if (methodCount > 0xffff) {//sanity check...
|
||||
throw new IOException("Too many ART methods: " + methodCount);
|
||||
}
|
||||
|
||||
for (int i = 0; i < methodCount; ++i) {
|
||||
methodList.add(new ArtMethod(reader, pointerSize, artVersion));
|
||||
}
|
||||
}
|
||||
|
||||
public long getMethodCount() {
|
||||
return methodCount;
|
||||
}
|
||||
|
||||
public List<ArtMethod> getMethodList() {
|
||||
return methodList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
String name = StructConverterUtil.parseName(ArtMethodGroup.class);
|
||||
Structure structure = new StructureDataType(name + "_" + methodCount, 0);
|
||||
structure.setCategoryPath(new CategoryPath("/art"));
|
||||
if (pointerSize == 8) {
|
||||
structure.add(QWORD, "methodCount", null);
|
||||
}
|
||||
else if (pointerSize == 4) {
|
||||
structure.add(DWORD, "methodCount", null);
|
||||
}
|
||||
for (int i = 0; i < methodCount; ++i) {
|
||||
structure.add(methodList.get(i).toDataType(), "method_" + i, null);
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/pie-release/runtime/image.h
|
||||
*/
|
||||
public enum ArtStorageMode {
|
||||
kStorageModeUncompressed, kStorageModeLZ4, kStorageModeLZ4HC, kStorageModeCount; // Number of elements in enum.
|
||||
|
||||
public final static ArtStorageMode kDefaultStorageMode = kStorageModeUncompressed;
|
||||
|
||||
public final static int SIZE = 32;//bits
|
||||
|
||||
public static ArtStorageMode get(int value) throws UnknownArtStorageModeException {
|
||||
for (ArtStorageMode mode : values()) {
|
||||
if (mode.ordinal() == value) {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
throw new UnknownArtStorageModeException(value);
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
|
||||
public final class ArtUtilities {
|
||||
|
||||
static void createFragment(Program program, String fragmentName, Address start,
|
||||
Address end) throws Exception {
|
||||
ProgramModule module = program.getListing().getRootModule(0);
|
||||
ProgramFragment fragment = getFragment(module, fragmentName);
|
||||
if (fragment == null) {
|
||||
fragment = module.createFragment(fragmentName);
|
||||
}
|
||||
fragment.move(start, end.subtract(1));
|
||||
}
|
||||
|
||||
static ProgramFragment getFragment(ProgramModule module, String fragmentName) {
|
||||
Group[] groups = module.getChildren();
|
||||
for (Group group : groups) {
|
||||
if (group.getName().equals(fragmentName)) {
|
||||
return (ProgramFragment) group;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Address adjustForThumbAsNeeded(ArtHeader artHeader, Program program,
|
||||
Address address) {
|
||||
long displacement = address.getOffset();
|
||||
if (program.getLanguage()
|
||||
.getProcessor()
|
||||
.equals(Processor.findOrPossiblyCreateProcessor("ARM"))) {
|
||||
if ((displacement & 0x1) == 0x1) {//thumb code?
|
||||
address = address.subtract(1);
|
||||
|
||||
Register register = program.getLanguage().getRegister("TMode");
|
||||
RegisterValue value = new RegisterValue(register, BigInteger.valueOf(1));
|
||||
try {
|
||||
program.getProgramContext().setRegisterValue(address, address, value);
|
||||
}
|
||||
catch (ContextChangeException e) {
|
||||
//log.appendException( e );
|
||||
//ignore...
|
||||
}
|
||||
}
|
||||
}
|
||||
return address;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UnknownArtStorageModeException extends IOException {
|
||||
|
||||
public UnknownArtStorageModeException(int storageMode) {
|
||||
super("Unrecognized storage mode: 0x" + Integer.toHexString(storageMode));
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art;
|
||||
|
||||
final class UnsupportedArtVersionException extends Exception {
|
||||
|
||||
UnsupportedArtVersionException(String magic, String version) {
|
||||
super("Unsupported ART version: " + version);
|
||||
}
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.android10;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.*;
|
||||
import ghidra.file.formats.android.util.DecompressionManager;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_10 extends ArtHeader {
|
||||
|
||||
private int image_reservation_size_;
|
||||
private int component_count_;
|
||||
private int image_begin_;
|
||||
private int image_size_;
|
||||
private int image_checksum_;
|
||||
private int oat_checksum_;
|
||||
private int oat_file_begin_;
|
||||
private int oat_data_begin_;
|
||||
private int oat_data_end_;
|
||||
private int oat_file_end_;
|
||||
private int boot_image_begin_;
|
||||
private int boot_image_size_;
|
||||
private int image_roots_;
|
||||
private int pointer_size_;
|
||||
private long[] image_methods_ = new long[ImageMethod_10.kImageMethodsCount.ordinal()];
|
||||
private int data_size_;
|
||||
private int blocks_offset_;
|
||||
private int blocks_count_;
|
||||
private List<ArtBlock> blocks = new ArrayList<>();
|
||||
|
||||
private ArtImageSections sections;
|
||||
|
||||
public ArtHeader_10(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_reservation_size_ = reader.readNextInt();
|
||||
component_count_ = reader.readNextInt();
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
image_checksum_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
boot_image_begin_ = reader.readNextInt();
|
||||
boot_image_size_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
pointer_size_ = reader.readNextInt();
|
||||
|
||||
sections = new ImageSections_10(reader, this);
|
||||
sections.parseSections(reader);
|
||||
|
||||
parseImageMethods(reader);
|
||||
|
||||
data_size_ = reader.readNextInt();
|
||||
blocks_offset_ = reader.readNextInt();
|
||||
blocks_count_ = reader.readNextInt();
|
||||
|
||||
if (blocks_offset_ > 0 && blocks_count_ > 0) {
|
||||
reader.setPointerIndex(blocks_offset_);
|
||||
for (int i = 0; i < blocks_count_; ++i) {
|
||||
blocks.add(new ArtBlock(reader));
|
||||
}
|
||||
}
|
||||
|
||||
reader = DecompressionManager.decompress(reader, blocks, TaskMonitor.DUMMY);
|
||||
|
||||
// NOTE:
|
||||
// cannot parse the sections until after the blocks are decompressed!
|
||||
|
||||
sections.parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
return ImageMethod_10.kImageMethodsCount.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
public int getImageChecksum_() {
|
||||
return image_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return pointer_size_;
|
||||
}
|
||||
|
||||
public int getBootImageBegin() {
|
||||
return boot_image_begin_;
|
||||
}
|
||||
|
||||
/**
|
||||
* App images currently require a boot image,
|
||||
* if the size is non zero then it is an app image header.
|
||||
* @return true if this header represents an app image
|
||||
*/
|
||||
public boolean isAppImage() {
|
||||
return boot_image_size_ != 0x0;
|
||||
}
|
||||
|
||||
public int getImageReservationSize() {
|
||||
return image_reservation_size_;
|
||||
}
|
||||
|
||||
public int getComponentCount() {
|
||||
return component_count_;
|
||||
}
|
||||
|
||||
public int getImageRoots() {
|
||||
return image_roots_;
|
||||
}
|
||||
|
||||
public int getDataSize() {
|
||||
return data_size_;
|
||||
}
|
||||
|
||||
public List<ArtBlock> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
DecompressionManager.decompressOverMemory(program, blocks, monitor);
|
||||
|
||||
sections.markup(program, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_10.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
//ignore, just use original name should this fail
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_reservation_size_", null);
|
||||
structure.add(DWORD, "component_count_", null);
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "image_checksum_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "boot_image_begin_", null);
|
||||
structure.add(DWORD, "boot_image_size_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
structure.add(DWORD, "pointer_size_", null);
|
||||
|
||||
for (int i = 0; i < sections.getSectionList().size(); ++i) {
|
||||
structure.add(sections.getSectionList().get(i).toDataType(), "section_" + i, null);
|
||||
}
|
||||
for (int i = 0; i < image_methods_.length; ++i) {
|
||||
structure.add(QWORD, "image_method_" + i, null);
|
||||
}
|
||||
|
||||
structure.add(DWORD, "data_size_", null);
|
||||
structure.add(DWORD, "blocks_offset_", null);
|
||||
structure.add(DWORD, "blocks_count_", null);
|
||||
return structure;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.android10;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageMethod_10 {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kImtUnimplementedMethod,
|
||||
kSaveAllCalleeSavesMethod,
|
||||
kSaveRefsOnlyMethod,
|
||||
kSaveRefsAndArgsMethod,
|
||||
kSaveEverythingMethod,
|
||||
kSaveEverythingMethodForClinit,
|
||||
kSaveEverythingMethodForSuspendCheck,
|
||||
kImageMethodsCount, // Number of elements in enum.
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.android10;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_10 {
|
||||
kDexCaches,
|
||||
kClassRoots,
|
||||
/** Pre-allocated OOME when throwing exception.*/
|
||||
kOomeWhenThrowingException,
|
||||
/** Pre-allocated OOME when throwing OOME. */
|
||||
kOomeWhenThrowingOome,
|
||||
/** Pre-allocated OOME when handling StackOverflowError. */
|
||||
kOomeWhenHandlingStackOverflow,
|
||||
/** Pre-allocated NoClassDefFoundError. */
|
||||
kNoClassDefFoundError,
|
||||
/** Different for boot image and app image, see aliases below. */
|
||||
kSpecialRoots,
|
||||
kImageRootsMax;
|
||||
|
||||
//Aliases
|
||||
|
||||
/** The class loader used to build the app image.*/
|
||||
public final static ImageRoot_10 kAppImageClassLoader = kSpecialRoots;
|
||||
|
||||
/** Array of boot image objects that must be kept live. */
|
||||
public final static ImageRoot_10 kBootImageLiveObjects = kSpecialRoots;
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.android10;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/image.h
|
||||
*/
|
||||
public class ImageSections_10 extends ArtImageSections {
|
||||
public final static int kSectionObjects = 0;
|
||||
public final static int kSectionArtFields = 1;
|
||||
public final static int kSectionArtMethods = 2;
|
||||
public final static int kSectionRuntimeMethods = 3;
|
||||
public final static int kSectionImTables = 4;
|
||||
public final static int kSectionIMTConflictTables = 5;
|
||||
public final static int kSectionDexCacheArrays = 6;
|
||||
public final static int kSectionInternedStrings = 7;
|
||||
public final static int kSectionClassTable = 8;
|
||||
public final static int kSectionStringReferenceOffsets = 9;
|
||||
public final static int kSectionMetadata = 10;
|
||||
public final static int kSectionImageBitmap = 11;
|
||||
public final static int kSectionCount = 12; // Number of elements in enum.
|
||||
|
||||
public ImageSections_10(BinaryReader reader, ArtHeader header) {
|
||||
super(reader, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionObjects() {
|
||||
return kSectionObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtFields() {
|
||||
return kSectionArtFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtMethods() {
|
||||
return kSectionArtMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionRuntimeMethods() {
|
||||
return kSectionRuntimeMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImTables() {
|
||||
return kSectionImTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionIMTConflictTables() {
|
||||
return kSectionIMTConflictTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionDexCacheArrays() {
|
||||
return kSectionDexCacheArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionInternedStrings() {
|
||||
return kSectionInternedStrings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionClassTable() {
|
||||
return kSectionClassTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionStringReferenceOffsets() {
|
||||
return kSectionStringReferenceOffsets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionMetadata() {
|
||||
return kSectionMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImageBitmap() {
|
||||
return kSectionImageBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionCount() {
|
||||
return kSectionCount;
|
||||
}
|
||||
|
||||
}
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.android11;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.*;
|
||||
import ghidra.file.formats.android.art.android10.ImageMethod_10;
|
||||
import ghidra.file.formats.android.art.android10.ImageSections_10;
|
||||
import ghidra.file.formats.android.util.DecompressionManager;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android10-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_11 extends ArtHeader {
|
||||
|
||||
private int image_reservation_size_;
|
||||
private int component_count_;
|
||||
private int image_begin_;
|
||||
private int image_size_;
|
||||
private int image_checksum_;
|
||||
private int oat_checksum_;
|
||||
private int oat_file_begin_;
|
||||
private int oat_data_begin_;
|
||||
private int oat_data_end_;
|
||||
private int oat_file_end_;
|
||||
private int boot_image_begin_;
|
||||
private int boot_image_size_;
|
||||
private int boot_image_component_count_;
|
||||
private int boot_image_checksum_;
|
||||
private int image_roots_;
|
||||
private int pointer_size_;
|
||||
private long[] image_methods_ = new long[ImageMethod_10.kImageMethodsCount.ordinal()];
|
||||
private int data_size_;
|
||||
private int blocks_offset_;
|
||||
private int blocks_count_;
|
||||
private List<ArtBlock> blocks = new ArrayList<>();
|
||||
|
||||
private ArtImageSections sections;
|
||||
|
||||
public ArtHeader_11(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_reservation_size_ = reader.readNextInt();
|
||||
component_count_ = reader.readNextInt();
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
image_checksum_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
boot_image_begin_ = reader.readNextInt();
|
||||
boot_image_size_ = reader.readNextInt();
|
||||
boot_image_component_count_ = reader.readNextInt();
|
||||
boot_image_checksum_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
pointer_size_ = reader.readNextInt();
|
||||
|
||||
sections = new ImageSections_10(reader, this);
|
||||
sections.parseSections(reader);
|
||||
|
||||
parseImageMethods(reader);
|
||||
|
||||
data_size_ = reader.readNextInt();
|
||||
blocks_offset_ = reader.readNextInt();
|
||||
blocks_count_ = reader.readNextInt();
|
||||
|
||||
if (blocks_offset_ > 0 && blocks_count_ > 0) {
|
||||
reader.setPointerIndex(blocks_offset_);
|
||||
for (int i = 0; i < blocks_count_; ++i) {
|
||||
blocks.add(new ArtBlock(reader));
|
||||
}
|
||||
}
|
||||
|
||||
reader = DecompressionManager.decompress(reader, blocks, TaskMonitor.DUMMY);
|
||||
|
||||
// NOTE:
|
||||
// cannot parse the sections until after the blocks are decompressed!
|
||||
|
||||
sections.parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
return ImageMethod_10.kImageMethodsCount.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
public int getImageChecksum_() {
|
||||
return image_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return pointer_size_;
|
||||
}
|
||||
|
||||
public int getBootImageBegin() {
|
||||
return boot_image_begin_;
|
||||
}
|
||||
|
||||
public int getBootImageComponentCount() {
|
||||
return boot_image_component_count_;
|
||||
}
|
||||
|
||||
public int getBootImageChecksum() {
|
||||
return boot_image_checksum_;
|
||||
}
|
||||
|
||||
/**
|
||||
* App images currently require a boot image,
|
||||
* if the size is non zero then it is an app image header.
|
||||
* @return true if app image
|
||||
*/
|
||||
public boolean isAppImage() {
|
||||
return boot_image_size_ != 0x0;
|
||||
}
|
||||
|
||||
public int getImageReservationSize() {
|
||||
return image_reservation_size_;
|
||||
}
|
||||
|
||||
public int getComponentCount() {
|
||||
return component_count_;
|
||||
}
|
||||
|
||||
public int getImageRoots() {
|
||||
return image_roots_;
|
||||
}
|
||||
|
||||
public int getDataSize() {
|
||||
return data_size_;
|
||||
}
|
||||
|
||||
public List<ArtBlock> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
DecompressionManager.decompressOverMemory(program, blocks, monitor);
|
||||
|
||||
sections.markup(program, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_11.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_reservation_size_", null);
|
||||
structure.add(DWORD, "component_count_", null);
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "image_checksum_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "boot_image_begin_", null);
|
||||
structure.add(DWORD, "boot_image_size_", null);
|
||||
structure.add(DWORD, "boot_image_component_count_", null);
|
||||
structure.add(DWORD, "boot_image_checksum_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
structure.add(DWORD, "pointer_size_", null);
|
||||
|
||||
for (int i = 0; i < sections.getSectionList().size(); ++i) {
|
||||
structure.add(sections.getSectionList().get(i).toDataType(), "section_" + i, null);
|
||||
}
|
||||
for (int i = 0; i < image_methods_.length; ++i) {
|
||||
structure.add(QWORD, "image_method_" + i, null);
|
||||
}
|
||||
|
||||
structure.add(DWORD, "data_size_", null);
|
||||
structure.add(DWORD, "blocks_offset_", null);
|
||||
structure.add(DWORD, "blocks_count_", null);
|
||||
return structure;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.android11;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android11-release/runtime/image.h
|
||||
*/
|
||||
public enum BootImageLiveObjects {
|
||||
|
||||
/** Pre-allocated OOME when throwing exception. */
|
||||
kOomeWhenThrowingException,
|
||||
/** Pre-allocated OOME when throwing OOME. */
|
||||
kOomeWhenThrowingOome,
|
||||
/** Pre-allocated OOME when handling StackOverflowError. */
|
||||
kOomeWhenHandlingStackOverflow,
|
||||
/** Pre-allocated NoClassDefFoundError. */
|
||||
kNoClassDefFoundError,
|
||||
/** Pre-allocated sentinel for cleared weak JNI references. */
|
||||
kClearedJniWeakSentinel,
|
||||
kIntrinsicObjectsStart;
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.android11;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/android11-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_11 {
|
||||
kDexCaches, kClassRoots, kSpecialRoots, kImageRootsMax;
|
||||
|
||||
//Aliases
|
||||
|
||||
/** The class loader used to build the app image.*/
|
||||
public final static ImageRoot_11 kAppImageClassLoader = kSpecialRoots;
|
||||
|
||||
/** Array of boot image objects that must be kept live. */
|
||||
public final static ImageRoot_11 kBootImageLiveObjects = kSpecialRoots;
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.kitkat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/refs/heads/kitkat-release/runtime/image.cc
|
||||
*/
|
||||
public class ArtHeader_KitKat extends ArtHeader {
|
||||
|
||||
protected int image_begin_;
|
||||
protected int image_size_;
|
||||
protected int image_bitmap_offset_;
|
||||
protected int image_bitmap_size_;
|
||||
protected int oat_checksum_;
|
||||
protected int oat_file_begin_;
|
||||
protected int oat_data_begin_;
|
||||
protected int oat_data_end_;
|
||||
protected int oat_file_end_;
|
||||
protected int image_roots_;
|
||||
|
||||
public ArtHeader_KitKat(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
image_bitmap_offset_ = reader.readNextInt();
|
||||
image_bitmap_size_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Image bitmap offset in the file.
|
||||
*/
|
||||
public int getImageBitmapOffset() {
|
||||
return image_bitmap_offset_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of the image bitmap.
|
||||
*/
|
||||
public int getImageBitmapSize() {
|
||||
return image_bitmap_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checksum of the oat file we link to for load time sanity check.
|
||||
*/
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start address for oat file. Will be before oat_data_begin_ for .so files.
|
||||
*/
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required oat address expected by image Method::GetCode() pointers.
|
||||
*/
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of oat data address range for this image file.
|
||||
*/
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
/**
|
||||
* End of oat file address range. will be after oat_data_end_ for
|
||||
* .so files. Used for positioning a following alloc spaces.
|
||||
*/
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute address of an Object[] of objects needed to reinitialize from an image.
|
||||
*/
|
||||
public int getImageRoots() {
|
||||
return image_roots_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return -1; //unsupported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
//do nothing for now
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_KitKat.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "image_bitmap_offset_", null);
|
||||
structure.add(DWORD, "image_bitmap_size_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.kitkat;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/refs/heads/kitkat-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_KitKat {
|
||||
kResolutionMethod,
|
||||
kCalleeSaveMethod,
|
||||
kRefsOnlySaveMethod,
|
||||
kRefsAndArgsSaveMethod,
|
||||
kOatLocation,
|
||||
kDexCaches,
|
||||
kClassRoots,
|
||||
kImageRootsMax,
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.lollipop;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/refs/heads/lollipop-release/runtime/image.cc
|
||||
*/
|
||||
public class ArtHeader_Lollipop extends ArtHeader {
|
||||
|
||||
protected int image_begin_;
|
||||
protected int image_size_;
|
||||
protected int image_bitmap_offset_;
|
||||
protected int image_bitmap_size_;
|
||||
protected int oat_checksum_;
|
||||
protected int oat_file_begin_;
|
||||
protected int oat_data_begin_;
|
||||
protected int oat_data_end_;
|
||||
protected int oat_file_end_;
|
||||
protected int patch_delta_;
|
||||
protected int image_roots_;
|
||||
|
||||
public ArtHeader_Lollipop(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
image_bitmap_offset_ = reader.readNextInt();
|
||||
image_bitmap_size_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
patch_delta_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* The total delta that this image has been patched.
|
||||
*/
|
||||
public int getPatchDelta() {
|
||||
return patch_delta_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checksum of the oat file we link to for load time sanity check.
|
||||
*/
|
||||
@Override
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return -1; //unsupported
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
//do nothing for now
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_Lollipop.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "image_bitmap_offset_", null);
|
||||
structure.add(DWORD, "image_bitmap_size_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "patch_delta_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.lollipop;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/lollipop-mr1-wfc-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_LollipopMR1WFC extends ArtHeader {
|
||||
|
||||
protected int image_begin_;
|
||||
protected int image_size_;
|
||||
protected int image_bitmap_offset_;
|
||||
protected int image_bitmap_size_;
|
||||
protected int oat_checksum_;
|
||||
protected int oat_file_begin_;
|
||||
protected int oat_data_begin_;
|
||||
protected int oat_data_end_;
|
||||
protected int oat_file_end_;
|
||||
protected int patch_delta_;
|
||||
protected int image_roots_;
|
||||
protected int compile_pic_;
|
||||
|
||||
public ArtHeader_LollipopMR1WFC(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
image_bitmap_offset_ = reader.readNextInt();
|
||||
image_bitmap_size_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
patch_delta_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
compile_pic_ = reader.readNextInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean (0 or 1) to denote if the image was compiled with --compile-pic option.
|
||||
*/
|
||||
public int getCompilePic() {
|
||||
return compile_pic_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return -1; //unsupported
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_LollipopMR1WFC.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "image_bitmap_offset_", null);
|
||||
structure.add(DWORD, "image_bitmap_size_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "patch_delta_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
structure.add(DWORD, "compile_pic_", null);
|
||||
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.lollipop;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/refs/heads/lollipop-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_Lollipop {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kDefaultImt,
|
||||
kCalleeSaveMethod,
|
||||
kRefsOnlySaveMethod,
|
||||
kRefsAndArgsSaveMethod,
|
||||
kDexCaches,
|
||||
kClassRoots,
|
||||
kImageRootsMax,
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.lollipop;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/lollipop-mr1-wfc-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_LollipopMR1WRC {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kImtUnimplementedMethod,
|
||||
kDefaultImt,
|
||||
kCalleeSaveMethod,
|
||||
kRefsOnlySaveMethod,
|
||||
kRefsAndArgsSaveMethod,
|
||||
kDexCaches,
|
||||
kClassRoots,
|
||||
kImageRootsMax,
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.marshmallow;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/marshmallow-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_Marshmallow extends ArtHeader {
|
||||
|
||||
protected int image_begin_;
|
||||
protected int image_size_;
|
||||
protected int oat_checksum_;
|
||||
protected int oat_file_begin_;
|
||||
protected int oat_data_begin_;
|
||||
protected int oat_data_end_;
|
||||
protected int oat_file_end_;
|
||||
protected int patch_delta_;
|
||||
protected int image_roots_;
|
||||
protected int pointer_size_;
|
||||
protected int compile_pic_;
|
||||
|
||||
protected long[] image_methods_ =
|
||||
new long[ImageMethod_Marshmallow.kImageMethodsCount.ordinal()];
|
||||
|
||||
protected ArtImageSections sections;
|
||||
|
||||
public ArtHeader_Marshmallow(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
patch_delta_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
pointer_size_ = reader.readNextInt();
|
||||
compile_pic_ = reader.readNextInt();
|
||||
|
||||
sections = new ImageSections_Marshmallow(reader, this);
|
||||
sections.parseSections(reader);
|
||||
|
||||
for (int i = 0; i < image_methods_.length; ++i) {
|
||||
image_methods_[i] = reader.readNextLong();
|
||||
}
|
||||
|
||||
sections.parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return pointer_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Image methods.
|
||||
*/
|
||||
public long[] getImageMethods() {
|
||||
return image_methods_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checksum of the oat file we link to for load time sanity check.
|
||||
*/
|
||||
@Override
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
|
||||
sections.markup(program, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_Marshmallow.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "patch_delta_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
structure.add(DWORD, "pointer_size_", null);
|
||||
structure.add(DWORD, "compile_pic_", null);
|
||||
|
||||
for (int i = 0; i < sections.getSectionList().size(); ++i) {
|
||||
structure.add(sections.getSectionList().get(i).toDataType(), "section_" + i, null);
|
||||
}
|
||||
for (int i = 0; i < image_methods_.length; ++i) {
|
||||
structure.add(QWORD, "image_method_" + i, null);
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.marshmallow;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/pie-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageMethod_Marshmallow {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kImtUnimplementedMethod,
|
||||
kCalleeSaveMethod,
|
||||
kRefsOnlySaveMethod,
|
||||
kRefsAndArgsSaveMethod,
|
||||
kImageMethodsCount, // Number of elements in enum.
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.marshmallow;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/marshmallow-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_Marshmallow {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kDefaultImt,
|
||||
kCalleeSaveMethod,
|
||||
kRefsOnlySaveMethod,
|
||||
kRefsAndArgsSaveMethod,
|
||||
kDexCaches,
|
||||
kClassRoots,
|
||||
kImageRootsMax,
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.marshmallow;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
|
||||
public class ImageSections_Marshmallow extends ArtImageSections {
|
||||
public final static int kSectionObjects = 0;
|
||||
public final static int kSectionArtFields = 1;
|
||||
public final static int kSectionArtMethods = 2;
|
||||
public final static int kSectionInternedStrings = 3;
|
||||
public final static int kSectionImageBitmap = 4;
|
||||
public final static int kSectionCount = 5; // Number of elements in enum.
|
||||
|
||||
public ImageSections_Marshmallow(BinaryReader reader, ArtHeader header) {
|
||||
super(reader, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionObjects() {
|
||||
return kSectionObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtFields() {
|
||||
return kSectionArtFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtMethods() {
|
||||
return kSectionArtMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionRuntimeMethods() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImTables() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionIMTConflictTables() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionDexCacheArrays() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionInternedStrings() {
|
||||
return kSectionInternedStrings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionClassTable() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionStringReferenceOffsets() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionMetadata() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImageBitmap() {
|
||||
return kSectionImageBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionCount() {
|
||||
return kSectionCount;
|
||||
}
|
||||
}
|
||||
+251
@@ -0,0 +1,251 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.nougat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.*;
|
||||
import ghidra.file.formats.android.util.DecompressionManager;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/nougat-release/runtime/image.h
|
||||
* https://android.googlesource.com/platform/art/+/nougat-release/runtime/image.cc
|
||||
*/
|
||||
public class ArtHeader_Nougat extends ArtHeader implements ArtCompression {
|
||||
|
||||
protected int image_begin_;
|
||||
protected int image_size_;
|
||||
protected int oat_checksum_;
|
||||
protected int oat_file_begin_;
|
||||
protected int oat_data_begin_;
|
||||
protected int oat_data_end_;
|
||||
protected int oat_file_end_;
|
||||
protected int boot_image_begin_;
|
||||
protected int boot_image_size_;
|
||||
protected int boot_oat_begin_;
|
||||
protected int boot_oat_size_;
|
||||
protected int patch_delta_;
|
||||
protected int image_roots_;
|
||||
protected int pointer_size_;
|
||||
protected int compile_pic_;
|
||||
protected int is_pic_;
|
||||
protected int storage_mode_;
|
||||
protected int data_size_;
|
||||
|
||||
protected ArtImageSections sections;
|
||||
|
||||
private long _compressedOffset;
|
||||
|
||||
public ArtHeader_Nougat(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
protected ArtImageSections getImageSections(BinaryReader reader) {
|
||||
return new ImageSections_Nougat(reader, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
boot_image_begin_ = reader.readNextInt();
|
||||
boot_image_size_ = reader.readNextInt();
|
||||
boot_oat_begin_ = reader.readNextInt();
|
||||
boot_oat_size_ = reader.readNextInt();
|
||||
patch_delta_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
pointer_size_ = reader.readNextInt();
|
||||
compile_pic_ = reader.readNextInt();
|
||||
is_pic_ = reader.readNextInt();
|
||||
|
||||
sections = getImageSections(reader);
|
||||
|
||||
sections.parseSections(reader);
|
||||
parseImageMethods(reader);
|
||||
|
||||
storage_mode_ = reader.readNextInt();
|
||||
data_size_ = reader.readNextInt();
|
||||
|
||||
//The compressed offset is immediately following this header.
|
||||
_compressedOffset = reader.getPointerIndex();
|
||||
|
||||
reader = DecompressionManager.decompress(reader, this, TaskMonitor.DUMMY);
|
||||
|
||||
sections.parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
return ImageMethod_Nougat.kImageMethodsCount.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot oat begin and end (app image headers only).
|
||||
* @return the boot oat begin address
|
||||
*/
|
||||
public int getBootOatBegin() {
|
||||
return boot_oat_begin_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot oat begin and end (app image headers only).
|
||||
* @return the boot oat size
|
||||
*/
|
||||
public int getBootOatSize() {
|
||||
return boot_oat_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean (0 or 1) to denote if the image can be mapped at a random address,
|
||||
* this only refers to the .art file.
|
||||
* Currently, app oat files do not depend on their app image.
|
||||
* There are no pointers from the app oat code to the app image.
|
||||
* @return true of position independent code, or false if dependent.
|
||||
*/
|
||||
public int getIsPic() {
|
||||
return is_pic_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArtStorageMode getStorageMode() throws UnknownArtStorageModeException {
|
||||
return ArtStorageMode.get(storage_mode_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCompressedOffset() {
|
||||
return _compressedOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompressedSize() {
|
||||
return data_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDecompressedOffset() {
|
||||
return getCompressedOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecompressedSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checksum of the oat file we link to for load time sanity check.
|
||||
*/
|
||||
@Override
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return pointer_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
DecompressionManager.decompressOverMemory(program, this, monitor);
|
||||
|
||||
sections.markup(program, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_Nougat.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
//ignore, just use original name should this fail
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "boot_image_begin_", null);
|
||||
structure.add(DWORD, "boot_image_size_", null);
|
||||
structure.add(DWORD, "boot_oat_begin_", null);
|
||||
structure.add(DWORD, "boot_oat_size_", null);
|
||||
structure.add(DWORD, "patch_delta_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
structure.add(DWORD, "pointer_size_", null);
|
||||
structure.add(DWORD, "compile_pic_", null);
|
||||
structure.add(DWORD, "is_pic_", null);
|
||||
|
||||
for (int i = 0; i < sections.getSectionList().size(); ++i) {
|
||||
structure.add(sections.getSectionList().get(i).toDataType(), "section_" + i, null);
|
||||
}
|
||||
for (int i = 0; i < imageMethodsList.size(); ++i) {
|
||||
structure.add(QWORD, "image_method_" + i, null);
|
||||
}
|
||||
structure.add(DWORD, "storage_mode_", null);
|
||||
structure.add(DWORD, "data_size_", null);
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.nougat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/nougat-mr2-pixel-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_NougatMR2Pixel extends ArtHeader_Nougat {
|
||||
|
||||
public ArtHeader_NougatMR2Pixel(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
protected ArtImageSections getImageSections(BinaryReader reader) {
|
||||
return new ImageSections_NougatMR2Pixel(reader, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
return ImageMethod_Nougat.kImageMethodsCount.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
String className = StructConverterUtil.parseName(ArtHeader_NougatMR2Pixel.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
//ignore
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.nougat;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/pie-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageMethod_Nougat {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kImtUnimplementedMethod,
|
||||
kCalleeSaveMethod,
|
||||
kRefsOnlySaveMethod,
|
||||
kRefsAndArgsSaveMethod,
|
||||
kImageMethodsCount, // Number of elements in enum.
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.nougat;
|
||||
|
||||
/**
|
||||
* @see https://android.googlesource.com/platform/art/+/nougat-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_Nougat {
|
||||
kDexCaches, kClassRoots, kImageRootsMax,
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.nougat;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
|
||||
public class ImageSections_Nougat extends ArtImageSections {
|
||||
public final static int kSectionObjects = 0;
|
||||
public final static int kSectionArtFields = 1;
|
||||
public final static int kSectionArtMethods = 2;
|
||||
public final static int kSectionRuntimeMethods = 3;
|
||||
public final static int kSectionIMTConflictTables = 4;
|
||||
public final static int kSectionDexCacheArrays = 5;
|
||||
public final static int kSectionInternedStrings = 6;
|
||||
public final static int kSectionClassTable = 7;
|
||||
public final static int kSectionImageBitmap = 8;
|
||||
public final static int kSectionCount = 9; // Number of elements in enum.
|
||||
|
||||
public ImageSections_Nougat(BinaryReader reader, ArtHeader header) {
|
||||
super(reader, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionObjects() {
|
||||
return kSectionObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtFields() {
|
||||
return kSectionArtFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtMethods() {
|
||||
return kSectionArtMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionRuntimeMethods() {
|
||||
return kSectionRuntimeMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImTables() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionIMTConflictTables() {
|
||||
return kSectionIMTConflictTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionDexCacheArrays() {
|
||||
return kSectionDexCacheArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionInternedStrings() {
|
||||
return kSectionInternedStrings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionClassTable() {
|
||||
return kSectionClassTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionStringReferenceOffsets() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionMetadata() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImageBitmap() {
|
||||
return kSectionImageBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionCount() {
|
||||
return kSectionCount;
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.nougat;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
|
||||
public class ImageSections_NougatMR2Pixel extends ArtImageSections {
|
||||
public final static int kSectionObjects = 0;
|
||||
public final static int kSectionArtFields = 1;
|
||||
public final static int kSectionArtMethods = 2;
|
||||
public final static int kSectionRuntimeMethods = 3;
|
||||
public final static int kSectionImTables = 4;
|
||||
public final static int kSectionIMTConflictTables = 5;
|
||||
public final static int kSectionDexCacheArrays = 6;
|
||||
public final static int kSectionInternedStrings = 7;
|
||||
public final static int kSectionClassTable = 8;
|
||||
public final static int kSectionImageBitmap = 9;
|
||||
public final static int kSectionCount = 10; // Number of elements in enum.
|
||||
|
||||
public ImageSections_NougatMR2Pixel(BinaryReader reader, ArtHeader header) {
|
||||
super(reader, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionObjects() {
|
||||
return kSectionObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtFields() {
|
||||
return kSectionArtFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtMethods() {
|
||||
return kSectionArtMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionRuntimeMethods() {
|
||||
return kSectionRuntimeMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImTables() {
|
||||
return kSectionImTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionIMTConflictTables() {
|
||||
return kSectionIMTConflictTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionDexCacheArrays() {
|
||||
return kSectionDexCacheArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionInternedStrings() {
|
||||
return kSectionInternedStrings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionClassTable() {
|
||||
return kSectionClassTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionStringReferenceOffsets() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionMetadata() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImageBitmap() {
|
||||
return kSectionImageBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionCount() {
|
||||
return kSectionCount;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.oreo;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
import ghidra.file.formats.android.art.nougat.ArtHeader_NougatMR2Pixel;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/oreo-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_Oreo extends ArtHeader_NougatMR2Pixel {
|
||||
|
||||
public ArtHeader_Oreo(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
protected ArtImageSections getImageSections(BinaryReader reader) {
|
||||
return new ImageSections_Oreo(reader, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
return ImageMethod_Oreo.kImageMethodsCount.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
String className = StructConverterUtil.parseName(ArtHeader_Oreo.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
//ignore
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.oreo;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/oreo-mr1-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_OreoMR1 extends ArtHeader_Oreo {
|
||||
|
||||
public ArtHeader_OreoMR1(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
}
|
||||
|
||||
protected ArtImageSections getImageSections(BinaryReader reader) {
|
||||
return new ImageSections_OreoMR1(reader, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
return ImageMethod_Oreo.kImageMethodsCount.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
String className = StructConverterUtil.parseName(ArtHeader_OreoMR1.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
//ignore
|
||||
}
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.oreo;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/oreo-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageMethod_Oreo {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kImtUnimplementedMethod,
|
||||
kSaveAllCalleeSavesMethod,
|
||||
kSaveRefsOnlyMethod,
|
||||
kSaveRefsAndArgsMethod,
|
||||
kSaveEverythingMethod,
|
||||
kImageMethodsCount, // Number of elements in enum.
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.oreo;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/oreo-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_Oreo {
|
||||
kDexCaches,
|
||||
kClassRoots,
|
||||
kClassLoader, // App image only.
|
||||
kImageRootsMax,
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.oreo;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
|
||||
public class ImageSections_Oreo extends ArtImageSections {
|
||||
public final static int kSectionObjects = 0;
|
||||
public final static int kSectionArtFields = 1;
|
||||
public final static int kSectionArtMethods = 2;
|
||||
public final static int kSectionRuntimeMethods = 3;
|
||||
public final static int kSectionImTables = 4;
|
||||
public final static int kSectionIMTConflictTables = 5;
|
||||
public final static int kSectionDexCacheArrays = 6;
|
||||
public final static int kSectionInternedStrings = 7;
|
||||
public final static int kSectionClassTable = 8;
|
||||
public final static int kSectionImageBitmap = 9;
|
||||
public final static int kSectionCount = 10; // Number of elements in enum.
|
||||
|
||||
enum ImageSections {
|
||||
kSectionObjects,
|
||||
kSectionArtFields,
|
||||
kSectionArtMethods,
|
||||
kSectionRuntimeMethods,
|
||||
kSectionImTables,
|
||||
kSectionIMTConflictTables,
|
||||
kSectionDexCacheArrays,
|
||||
kSectionInternedStrings,
|
||||
kSectionClassTable,
|
||||
kSectionImageBitmap,
|
||||
kSectionCount, // Number of elements in enum.
|
||||
};
|
||||
|
||||
public ImageSections_Oreo(BinaryReader reader, ArtHeader header) {
|
||||
super(reader, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionObjects() {
|
||||
return kSectionObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtFields() {
|
||||
return kSectionArtFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtMethods() {
|
||||
return kSectionArtMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionRuntimeMethods() {
|
||||
return kSectionRuntimeMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImTables() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionIMTConflictTables() {
|
||||
return kSectionIMTConflictTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionDexCacheArrays() {
|
||||
return kSectionDexCacheArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionInternedStrings() {
|
||||
return kSectionInternedStrings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionClassTable() {
|
||||
return kSectionClassTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionStringReferenceOffsets() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionMetadata() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImageBitmap() {
|
||||
return kSectionImageBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionCount() {
|
||||
return kSectionCount;
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.oreo;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.file.formats.android.art.ArtHeader;
|
||||
import ghidra.file.formats.android.art.ArtImageSections;
|
||||
|
||||
public class ImageSections_OreoMR1 extends ArtImageSections {
|
||||
public final static int kSectionObjects = 0;
|
||||
public final static int kSectionArtFields = 1;
|
||||
public final static int kSectionArtMethods = 2;
|
||||
public final static int kSectionRuntimeMethods = 3;
|
||||
public final static int kSectionImTables = 4;
|
||||
public final static int kSectionIMTConflictTables = 5;
|
||||
public final static int kSectionDexCacheArrays = 6;
|
||||
public final static int kSectionInternedStrings = 7;
|
||||
public final static int kSectionClassTable = 8;
|
||||
public final static int kSectionImageBitmap = 9;
|
||||
public final static int kSectionCount = 10; // Number of elements in enum.
|
||||
|
||||
public ImageSections_OreoMR1(BinaryReader reader, ArtHeader header) {
|
||||
super(reader, header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionObjects() {
|
||||
return kSectionObjects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtFields() {
|
||||
return kSectionArtFields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionArtMethods() {
|
||||
return kSectionArtMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionRuntimeMethods() {
|
||||
return kSectionRuntimeMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImTables() {
|
||||
return kSectionImTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionIMTConflictTables() {
|
||||
return kSectionIMTConflictTables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionDexCacheArrays() {
|
||||
return kSectionDexCacheArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionInternedStrings() {
|
||||
return kSectionInternedStrings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionClassTable() {
|
||||
return kSectionClassTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionStringReferenceOffsets() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionMetadata() {
|
||||
return UNSUPPORTED_SECTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionImageBitmap() {
|
||||
return kSectionImageBitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get_kSectionCount() {
|
||||
return kSectionCount;
|
||||
}
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.pie;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.BinaryReader;
|
||||
import ghidra.app.util.bin.StructConverterUtil;
|
||||
import ghidra.file.formats.android.art.*;
|
||||
import ghidra.file.formats.android.util.DecompressionManager;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.Structure;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/pie-release/runtime/image.h
|
||||
*/
|
||||
public class ArtHeader_Pie extends ArtHeader implements ArtCompression {
|
||||
|
||||
protected int image_begin_;
|
||||
protected int image_size_;
|
||||
protected int oat_checksum_;
|
||||
protected int oat_file_begin_;
|
||||
protected int oat_data_begin_;
|
||||
protected int oat_data_end_;
|
||||
protected int oat_file_end_;
|
||||
private int boot_image_begin_;
|
||||
private int boot_image_size_;
|
||||
private int boot_oat_begin_;
|
||||
private int boot_oat_size_;
|
||||
protected int patch_delta_;
|
||||
protected int image_roots_;
|
||||
protected int pointer_size_;
|
||||
protected int compile_pic_;
|
||||
private int is_pic_;
|
||||
|
||||
protected long[] image_methods_ = new long[ImageMethod_Pie.kImageMethodsCount.ordinal()];
|
||||
private int storage_mode_;
|
||||
private int data_size_;
|
||||
|
||||
private ArtImageSections sections;
|
||||
|
||||
private long _compressedOffset;
|
||||
|
||||
public ArtHeader_Pie(BinaryReader reader) throws IOException {
|
||||
super(reader);
|
||||
parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(BinaryReader reader) throws IOException {
|
||||
image_begin_ = reader.readNextInt();
|
||||
image_size_ = reader.readNextInt();
|
||||
oat_checksum_ = reader.readNextInt();
|
||||
oat_file_begin_ = reader.readNextInt();
|
||||
oat_data_begin_ = reader.readNextInt();
|
||||
oat_data_end_ = reader.readNextInt();
|
||||
oat_file_end_ = reader.readNextInt();
|
||||
boot_image_begin_ = reader.readNextInt();
|
||||
boot_image_size_ = reader.readNextInt();
|
||||
boot_oat_begin_ = reader.readNextInt();
|
||||
boot_oat_size_ = reader.readNextInt();
|
||||
patch_delta_ = reader.readNextInt();
|
||||
image_roots_ = reader.readNextInt();
|
||||
pointer_size_ = reader.readNextInt();
|
||||
compile_pic_ = reader.readNextInt();
|
||||
is_pic_ = reader.readNextInt();
|
||||
|
||||
sections = new ImageSections_Pie(reader, this);
|
||||
sections.parseSections(reader);
|
||||
parseImageMethods(reader);
|
||||
|
||||
storage_mode_ = reader.readNextInt();
|
||||
data_size_ = reader.readNextInt();
|
||||
|
||||
_compressedOffset = reader.getPointerIndex();
|
||||
|
||||
reader = DecompressionManager.decompress(reader, this, TaskMonitor.DUMMY);
|
||||
|
||||
// NOTE:
|
||||
// cannot parse the sections until after the blocks are decompressed!
|
||||
|
||||
sections.parse(reader);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageBegin() {
|
||||
return image_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatChecksum() {
|
||||
return oat_checksum_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileBegin() {
|
||||
return oat_file_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatFileEnd() {
|
||||
return oat_file_end_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataBegin() {
|
||||
return oat_data_begin_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOatDataEnd() {
|
||||
return oat_data_end_;
|
||||
}
|
||||
|
||||
public int getBootOatBegin() {
|
||||
return boot_oat_begin_;
|
||||
}
|
||||
|
||||
public int getBootOatSize() {
|
||||
return boot_oat_size_;
|
||||
}
|
||||
|
||||
public int getBootImageBegin() {
|
||||
return boot_image_begin_;
|
||||
}
|
||||
|
||||
public int getBootImageSize() {
|
||||
return boot_image_size_;
|
||||
}
|
||||
|
||||
public int isPIC() {
|
||||
return is_pic_;
|
||||
}
|
||||
|
||||
public int getCompilePIC() {
|
||||
return compile_pic_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArtStorageMode getStorageMode() throws UnknownArtStorageModeException {
|
||||
return ArtStorageMode.get(storage_mode_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCompressedOffset() {
|
||||
return _compressedOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompressedSize() {
|
||||
return data_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDecompressedOffset() {
|
||||
return getCompressedOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecompressedSize() {
|
||||
return image_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPointerSize() {
|
||||
return pointer_size_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markup(Program program, TaskMonitor monitor) throws Exception {
|
||||
DecompressionManager.decompressOverMemory(program, this, monitor);
|
||||
|
||||
sections.markup(program, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArtMethodCountForVersion() {
|
||||
return ImageMethod_Pie.kImageMethodsCount.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||
Structure structure = (Structure) super.toDataType();
|
||||
|
||||
String className = StructConverterUtil.parseName(ArtHeader_Pie.class);
|
||||
try {
|
||||
structure.setName(className);
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
structure.add(DWORD, "image_begin_", null);
|
||||
structure.add(DWORD, "image_size_", null);
|
||||
structure.add(DWORD, "oat_checksum_", null);
|
||||
structure.add(DWORD, "oat_file_begin_", null);
|
||||
structure.add(DWORD, "oat_data_begin_", null);
|
||||
structure.add(DWORD, "oat_data_end_", null);
|
||||
structure.add(DWORD, "oat_file_end_", null);
|
||||
structure.add(DWORD, "boot_image_begin_", null);
|
||||
structure.add(DWORD, "boot_image_size_", null);
|
||||
structure.add(DWORD, "boot_oat_begin_", null);
|
||||
structure.add(DWORD, "boot_oat_size_", null);
|
||||
structure.add(DWORD, "patch_delta_", null);
|
||||
structure.add(DWORD, "image_roots_", null);
|
||||
structure.add(DWORD, "pointer_size_", null);
|
||||
structure.add(DWORD, "compile_pic_", null);
|
||||
structure.add(DWORD, "is_pic_", null);
|
||||
|
||||
for (int i = 0; i < sections.getSectionList().size(); ++i) {
|
||||
structure.add(sections.getSectionList().get(i).toDataType(), "section_" + i, null);
|
||||
}
|
||||
for (int i = 0; i < image_methods_.length; ++i) {
|
||||
structure.add(QWORD, "image_method_" + i, null);
|
||||
}
|
||||
structure.add(DWORD, "storage_mode_", null);
|
||||
structure.add(DWORD, "data_size_", null);
|
||||
return structure;
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.pie;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/refs/heads/pie-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageMethod_Pie {
|
||||
kResolutionMethod,
|
||||
kImtConflictMethod,
|
||||
kImtUnimplementedMethod,
|
||||
kSaveAllCalleeSavesMethod,
|
||||
kSaveRefsOnlyMethod,
|
||||
kSaveRefsAndArgsMethod,
|
||||
kSaveEverythingMethod,
|
||||
kSaveEverythingMethodForClinit,
|
||||
kSaveEverythingMethodForSuspendCheck,
|
||||
kImageMethodsCount, // Number of elements in enum.
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.file.formats.android.art.pie;
|
||||
|
||||
/**
|
||||
* https://android.googlesource.com/platform/art/+/nougat-release/runtime/image.h
|
||||
*/
|
||||
public enum ImageRoot_Pie {
|
||||
kDexCaches,
|
||||
kClassRoots,
|
||||
kClassLoader, // App image only.
|
||||
kImageRootsMax,
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user