mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
aa333c1d2f
8 changed files with 154 additions and 98 deletions
|
@ -36,7 +36,7 @@ public class ObjectiveC2_Method extends ObjectiveC_Method {
|
||||||
isSmall = isSmallList;
|
isSmall = isSmallList;
|
||||||
|
|
||||||
if (isSmallList) {
|
if (isSmallList) {
|
||||||
int nameOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true);
|
int nameOffset = (int) ObjectiveC1_Utilities.readNextIndex(reader, true);
|
||||||
long namePtr;
|
long namePtr;
|
||||||
if (state.is32bit) {
|
if (state.is32bit) {
|
||||||
namePtr = reader.readInt(_index + nameOffset);
|
namePtr = reader.readInt(_index + nameOffset);
|
||||||
|
@ -47,12 +47,12 @@ public class ObjectiveC2_Method extends ObjectiveC_Method {
|
||||||
|
|
||||||
name = reader.readAsciiString(namePtr);
|
name = reader.readAsciiString(namePtr);
|
||||||
|
|
||||||
int typesOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true);
|
int typesOffset = (int) ObjectiveC1_Utilities.readNextIndex(reader, true);
|
||||||
types = reader.readAsciiString(_index + 4 + typesOffset);
|
types = reader.readAsciiString(_index + 4 + typesOffset);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
long nameIndex = ObjectiveC1_Utilities.readNextIndex(reader, state.is32bit);
|
long nameIndex = ObjectiveC1_Utilities.readNextIndex(reader, state.is32bit);
|
||||||
name = reader.readAsciiString(nameIndex);
|
name = reader.readAsciiString(nameIndex);
|
||||||
|
|
||||||
long typesIndex = ObjectiveC1_Utilities.readNextIndex(reader, state.is32bit);
|
long typesIndex = ObjectiveC1_Utilities.readNextIndex(reader, state.is32bit);
|
||||||
types = reader.readAsciiString(typesIndex);
|
types = reader.readAsciiString(typesIndex);
|
||||||
|
@ -65,17 +65,20 @@ public class ObjectiveC2_Method extends ObjectiveC_Method {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTypes() {
|
public String getTypes() {
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getImplementation() {
|
public long getImplementation() {
|
||||||
return imp.getImplementation();
|
return imp.getImplementation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
Structure struct = new StructureDataType("method_t", 0);
|
Structure struct = new StructureDataType("method" + (isSmall ? "_small" : "") + "_t", 0);
|
||||||
if (isSmall) {
|
if (isSmall) {
|
||||||
DataType sdw = SignedDWordDataType.dataType;
|
DataType sdw = SignedDWordDataType.dataType;
|
||||||
String comment = "offset from this address";
|
String comment = "offset from this address";
|
||||||
|
@ -84,9 +87,9 @@ public class ObjectiveC2_Method extends ObjectiveC_Method {
|
||||||
struct.add(sdw, sdw.getLength(), "imp", comment);
|
struct.add(sdw, sdw.getLength(), "imp", comment);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct.add(new PointerDataType(STRING), _state.pointerSize, "name", null);
|
struct.add(new PointerDataType(STRING), _state.pointerSize, "name", null);
|
||||||
struct.add(new PointerDataType(STRING), _state.pointerSize, "types", null);
|
struct.add(new PointerDataType(STRING), _state.pointerSize, "types", null);
|
||||||
struct.add(new PointerDataType(VOID), _state.pointerSize, "imp", null);
|
struct.add(new PointerDataType(VOID), _state.pointerSize, "imp", null);
|
||||||
}
|
}
|
||||||
struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH);
|
struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH);
|
||||||
return struct;
|
return struct;
|
||||||
|
|
|
@ -29,7 +29,8 @@ public class ObjectiveC2_MethodList extends ObjectiveC_MethodList {
|
||||||
private int entsizeAndFlags;
|
private int entsizeAndFlags;
|
||||||
private int count;
|
private int count;
|
||||||
|
|
||||||
public ObjectiveC2_MethodList(ObjectiveC2_State state, BinaryReader reader, ObjectiveC_MethodType methodType) throws IOException {
|
public ObjectiveC2_MethodList(ObjectiveC2_State state, BinaryReader reader,
|
||||||
|
ObjectiveC_MethodType methodType) throws IOException {
|
||||||
super(state, reader, NAME);
|
super(state, reader, NAME);
|
||||||
|
|
||||||
if (_index == 0) {
|
if (_index == 0) {
|
||||||
|
@ -37,15 +38,19 @@ public class ObjectiveC2_MethodList extends ObjectiveC_MethodList {
|
||||||
}
|
}
|
||||||
|
|
||||||
entsizeAndFlags = reader.readNextInt();
|
entsizeAndFlags = reader.readNextInt();
|
||||||
count = reader.readNextInt();
|
count = reader.readNextInt();
|
||||||
|
|
||||||
boolean isSmallList = (entsizeAndFlags & 0x80000000) != 0;
|
boolean isSmallList = isSmallMethods();
|
||||||
|
|
||||||
for (int i = 0 ; i < count ; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
methods.add( new ObjectiveC2_Method(state, reader, methodType, isSmallList) );
|
methods.add(new ObjectiveC2_Method(state, reader, methodType, isSmallList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isSmallMethods() {
|
||||||
|
return (entsizeAndFlags & 0x80000000) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public long getEntsizeAndFlags() {
|
public long getEntsizeAndFlags() {
|
||||||
return entsizeAndFlags;
|
return entsizeAndFlags;
|
||||||
}
|
}
|
||||||
|
@ -57,19 +62,21 @@ public class ObjectiveC2_MethodList extends ObjectiveC_MethodList {
|
||||||
public static DataType toGenericDataType() throws DuplicateNameException {
|
public static DataType toGenericDataType() throws DuplicateNameException {
|
||||||
Structure struct = new StructureDataType(NAME, 0);
|
Structure struct = new StructureDataType(NAME, 0);
|
||||||
struct.add(DWORD, "entsizeAndFlags", null);
|
struct.add(DWORD, "entsizeAndFlags", null);
|
||||||
struct.add(DWORD, "count", null);
|
struct.add(DWORD, "count", null);
|
||||||
struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH);
|
struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH);
|
||||||
return struct;
|
return struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
Structure struct = new StructureDataType(NAME+'_'+count+'_', 0);
|
Structure struct =
|
||||||
|
new StructureDataType(NAME + (isSmallMethods() ? "_small" : "") + '_' + count + '_', 0);
|
||||||
|
|
||||||
struct.add(DWORD, "entsizeAndFlags", null);
|
struct.add(DWORD, "entsizeAndFlags", null);
|
||||||
struct.add(DWORD, "count", null);
|
struct.add(DWORD, "count", null);
|
||||||
|
|
||||||
for (int i = 0 ; i < methods.size() ; ++i) {
|
for (int i = 0; i < methods.size(); ++i) {
|
||||||
struct.add(methods.get(i).toDataType(), "method"+i, null);
|
struct.add(methods.get(i).toDataType(), "method" + i, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH);
|
struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,14 +15,16 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.objectiveC;
|
package ghidra.app.util.bin.format.objectiveC;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class ObjectiveC1_Module implements StructConverter {
|
public class ObjectiveC1_Module implements StructConverter {
|
||||||
private ObjectiveC1_State _state;
|
private ObjectiveC1_State _state;
|
||||||
private long _index;
|
private long _index;
|
||||||
|
@ -74,9 +75,11 @@ public class ObjectiveC1_Module implements StructConverter {
|
||||||
_state.program.getAddressFactory().getDefaultAddressSpace().getAddress(_index);
|
_state.program.getAddressFactory().getDefaultAddressSpace().getAddress(_index);
|
||||||
DataType dt = toDataType();
|
DataType dt = toDataType();
|
||||||
try {
|
try {
|
||||||
_state.program.getListing().createData(address, dt);
|
DataUtilities.createData(_state.program, address, dt, -1, false,
|
||||||
|
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
Msg.warn(this, "Could not create " + dt.getName() + " @" + address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (symbolTable != null) {
|
if (symbolTable != null) {
|
||||||
|
@ -84,6 +87,7 @@ public class ObjectiveC1_Module implements StructConverter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType struct = new StructureDataType("objc_module", 0);
|
StructureDataType struct = new StructureDataType("objc_module", 0);
|
||||||
struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH);
|
struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH);
|
||||||
|
|
|
@ -23,6 +23,8 @@ import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
public class ObjectiveC1_SymbolTable implements StructConverter {
|
public class ObjectiveC1_SymbolTable implements StructConverter {
|
||||||
|
@ -42,12 +44,12 @@ public class ObjectiveC1_SymbolTable implements StructConverter {
|
||||||
this._state = state;
|
this._state = state;
|
||||||
this._index = reader.getPointerIndex();
|
this._index = reader.getPointerIndex();
|
||||||
|
|
||||||
sel_ref_cnt = reader.readNextInt();
|
sel_ref_cnt = reader.readNextInt();
|
||||||
refs = reader.readNextInt();
|
refs = reader.readNextInt();
|
||||||
cls_def_cnt = reader.readNextShort();
|
cls_def_cnt = reader.readNextShort();
|
||||||
cat_def_cnt = reader.readNextShort();
|
cat_def_cnt = reader.readNextShort();
|
||||||
|
|
||||||
for (int i = 0 ; i < cls_def_cnt ; ++i) {
|
for (int i = 0; i < cls_def_cnt; ++i) {
|
||||||
long classIndex = reader.readNextInt();
|
long classIndex = reader.readNextInt();
|
||||||
long oldClassIndex = reader.getPointerIndex();
|
long oldClassIndex = reader.getPointerIndex();
|
||||||
reader.setPointerIndex(classIndex);
|
reader.setPointerIndex(classIndex);
|
||||||
|
@ -55,7 +57,7 @@ public class ObjectiveC1_SymbolTable implements StructConverter {
|
||||||
reader.setPointerIndex(oldClassIndex);
|
reader.setPointerIndex(oldClassIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0 ; i < cat_def_cnt ; ++i) {
|
for (int i = 0; i < cat_def_cnt; ++i) {
|
||||||
long categoryIndex = reader.readNextInt();
|
long categoryIndex = reader.readNextInt();
|
||||||
long oldCategoryIndex = reader.getPointerIndex();
|
long oldCategoryIndex = reader.getPointerIndex();
|
||||||
reader.setPointerIndex(categoryIndex);
|
reader.setPointerIndex(categoryIndex);
|
||||||
|
@ -67,12 +69,15 @@ public class ObjectiveC1_SymbolTable implements StructConverter {
|
||||||
public int getSelectorReferenceCount() {
|
public int getSelectorReferenceCount() {
|
||||||
return sel_ref_cnt;
|
return sel_ref_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRefs() {
|
public int getRefs() {
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getClassDefinitionCount() {
|
public short getClassDefinitionCount() {
|
||||||
return cls_def_cnt;
|
return cls_def_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getCategoryDefinitionCount() {
|
public short getCategoryDefinitionCount() {
|
||||||
return cat_def_cnt;
|
return cat_def_cnt;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +85,7 @@ public class ObjectiveC1_SymbolTable implements StructConverter {
|
||||||
public List<ObjectiveC1_Class> getClasses() {
|
public List<ObjectiveC1_Class> getClasses() {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ObjectiveC1_Category> getCategories() {
|
public List<ObjectiveC1_Category> getCategories() {
|
||||||
return categories;
|
return categories;
|
||||||
}
|
}
|
||||||
|
@ -89,23 +95,28 @@ public class ObjectiveC1_SymbolTable implements StructConverter {
|
||||||
struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH);
|
struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH);
|
||||||
struct.add(DWORD, "sel_ref_cnt", null);
|
struct.add(DWORD, "sel_ref_cnt", null);
|
||||||
struct.add(DWORD, "refs", null);
|
struct.add(DWORD, "refs", null);
|
||||||
struct.add( WORD, "cls_def_cnt", null);
|
struct.add(WORD, "cls_def_cnt", null);
|
||||||
struct.add( WORD, "cat_def_cnt", null);
|
struct.add(WORD, "cat_def_cnt", null);
|
||||||
return struct;
|
return struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
StructureDataType struct = new StructureDataType(NAME+"_"+cls_def_cnt+"_"+cat_def_cnt+"_", 0);
|
StructureDataType struct =
|
||||||
|
new StructureDataType(NAME + "_" + cls_def_cnt + "_" + cat_def_cnt + "_", 0);
|
||||||
struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH);
|
struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH);
|
||||||
struct.add(DWORD, "sel_ref_cnt", null);
|
struct.add(DWORD, "sel_ref_cnt", null);
|
||||||
struct.add(DWORD, "refs", null);
|
struct.add(DWORD, "refs", null);
|
||||||
struct.add( WORD, "cls_def_cnt", null);
|
struct.add(WORD, "cls_def_cnt", null);
|
||||||
struct.add( WORD, "cat_def_cnt", null);
|
struct.add(WORD, "cat_def_cnt", null);
|
||||||
for (int i = 0 ; i < cls_def_cnt ; ++i) {
|
for (int i = 0; i < cls_def_cnt; ++i) {
|
||||||
struct.add(PointerDataType.getPointer(classes.get(i).toDataType(), _state.pointerSize), "class"+i, null);
|
struct.add(PointerDataType.getPointer(classes.get(i).toDataType(), _state.pointerSize),
|
||||||
|
"class" + i, null);
|
||||||
}
|
}
|
||||||
for (int i = 0 ; i < cat_def_cnt ; ++i) {
|
for (int i = 0; i < cat_def_cnt; ++i) {
|
||||||
struct.add(PointerDataType.getPointer(categories.get(i).toDataType(), _state.pointerSize), "category"+i, null);
|
struct.add(
|
||||||
|
PointerDataType.getPointer(categories.get(i).toDataType(), _state.pointerSize),
|
||||||
|
"category" + i, null);
|
||||||
}
|
}
|
||||||
return struct;
|
return struct;
|
||||||
}
|
}
|
||||||
|
@ -116,11 +127,16 @@ public class ObjectiveC1_SymbolTable implements StructConverter {
|
||||||
}
|
}
|
||||||
_state.beenApplied.add(_index);
|
_state.beenApplied.add(_index);
|
||||||
|
|
||||||
Address address = _state.program.getAddressFactory().getDefaultAddressSpace().getAddress(_index);
|
Address address =
|
||||||
|
_state.program.getAddressFactory().getDefaultAddressSpace().getAddress(_index);
|
||||||
|
DataType dt = toDataType();
|
||||||
try {
|
try {
|
||||||
_state.program.getListing().createData(address, toDataType());
|
DataUtilities.createData(_state.program, address, dt, -1, false,
|
||||||
|
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Msg.warn(this, "Could not create " + dt.getName() + " @" + address);
|
||||||
}
|
}
|
||||||
catch (Exception e) {}
|
|
||||||
|
|
||||||
_state.program.getListing().getDefinedDataAt(address);
|
_state.program.getListing().getDefinedDataAt(address);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import ghidra.framework.cmd.Command;
|
||||||
import ghidra.program.database.symbol.ClassSymbol;
|
import ghidra.program.database.symbol.ClassSymbol;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
import ghidra.program.model.lang.Processor;
|
import ghidra.program.model.lang.Processor;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
|
@ -48,8 +49,8 @@ public final class ObjectiveC1_Utilities {
|
||||||
* Clears the code units defined in the given memory block.
|
* Clears the code units defined in the given memory block.
|
||||||
*/
|
*/
|
||||||
public static void clear(ObjectiveC2_State state, MemoryBlock block) throws Exception {
|
public static void clear(ObjectiveC2_State state, MemoryBlock block) throws Exception {
|
||||||
state.program.getListing().clearCodeUnits(block.getStart(), block.getEnd(), false,
|
state.program.getListing()
|
||||||
state.monitor);
|
.clearCodeUnits(block.getStart(), block.getEnd(), false, state.monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,9 +144,11 @@ public final class ObjectiveC1_Utilities {
|
||||||
if (data != null && data.getDataType().isEquivalent(dt)) {
|
if (data != null && data.getDataType().isEquivalent(dt)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//program.getListing().clearCodeUnits(address, address.add(dt.getLength()-1));
|
|
||||||
|
|
||||||
program.getListing().createData(address, dt);
|
// need to clear, as pointers could have been created on import
|
||||||
|
// from following pointer chains
|
||||||
|
DataUtilities.createData(program, address, dt, -1, false,
|
||||||
|
ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -230,8 +233,8 @@ public final class ObjectiveC1_Utilities {
|
||||||
*/
|
*/
|
||||||
public static Symbol createSymbol(Program program, Namespace parentNamespace, String symbolName,
|
public static Symbol createSymbol(Program program, Namespace parentNamespace, String symbolName,
|
||||||
Address symbolAddress) throws InvalidInputException {
|
Address symbolAddress) throws InvalidInputException {
|
||||||
Symbol symbol = program.getSymbolTable().createLabel(symbolAddress, symbolName,
|
Symbol symbol = program.getSymbolTable()
|
||||||
parentNamespace, SourceType.IMPORTED);
|
.createLabel(symbolAddress, symbolName, parentNamespace, SourceType.IMPORTED);
|
||||||
symbol.setPrimary();
|
symbol.setPrimary();
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,13 +15,15 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.bin.format.objectiveC;
|
package ghidra.app.util.bin.format.objectiveC;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.util.bin.BinaryReader;
|
import ghidra.app.util.bin.BinaryReader;
|
||||||
import ghidra.app.util.bin.StructConverter;
|
import ghidra.app.util.bin.StructConverter;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.symbol.Namespace;
|
import ghidra.program.model.symbol.Namespace;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public abstract class ObjectiveC_MethodList implements StructConverter {
|
public abstract class ObjectiveC_MethodList implements StructConverter {
|
||||||
private String _className;
|
private String _className;
|
||||||
|
@ -31,7 +32,8 @@ public abstract class ObjectiveC_MethodList implements StructConverter {
|
||||||
|
|
||||||
protected List<ObjectiveC_Method> methods = new ArrayList<ObjectiveC_Method>();
|
protected List<ObjectiveC_Method> methods = new ArrayList<ObjectiveC_Method>();
|
||||||
|
|
||||||
protected ObjectiveC_MethodList(ObjectiveC1_State state, BinaryReader reader, String className) {
|
protected ObjectiveC_MethodList(ObjectiveC1_State state, BinaryReader reader,
|
||||||
|
String className) {
|
||||||
this._state = state;
|
this._state = state;
|
||||||
this._index = reader.getPointerIndex();
|
this._index = reader.getPointerIndex();
|
||||||
this._className = className;
|
this._className = className;
|
||||||
|
@ -51,17 +53,23 @@ public abstract class ObjectiveC_MethodList implements StructConverter {
|
||||||
_state.beenApplied.add(_index);
|
_state.beenApplied.add(_index);
|
||||||
|
|
||||||
Address address = ObjectiveC1_Utilities.toAddress(_state.program, _index);
|
Address address = ObjectiveC1_Utilities.toAddress(_state.program, _index);
|
||||||
|
DataType dt = toDataType();
|
||||||
try {
|
try {
|
||||||
ObjectiveC1_Utilities.applyData(_state.program, toDataType(), address);
|
ObjectiveC1_Utilities.applyData(_state.program, dt, address);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Msg.warn(this, "Could not create " + dt.getName() + " @" + address);
|
||||||
}
|
}
|
||||||
catch (Exception e) {}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//creates a symbol on the method list data structure
|
//creates a symbol on the method list data structure
|
||||||
Namespace methodListNamespace = ObjectiveC1_Utilities.createNamespace(_state.program, ObjectiveC1_Constants.NAMESPACE, _className);
|
Namespace methodListNamespace = ObjectiveC1_Utilities.createNamespace(_state.program,
|
||||||
ObjectiveC1_Utilities.createSymbol(_state.program, methodListNamespace, namespace.getName(), address);
|
ObjectiveC1_Constants.NAMESPACE, _className);
|
||||||
|
ObjectiveC1_Utilities.createSymbol(_state.program, methodListNamespace,
|
||||||
|
namespace.getName(), address);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
}
|
}
|
||||||
catch (Exception e) {}
|
|
||||||
|
|
||||||
for (ObjectiveC_Method method : getMethods()) {
|
for (ObjectiveC_Method method : getMethods()) {
|
||||||
method.applyTo(namespace);
|
method.applyTo(namespace);
|
||||||
|
|
|
@ -191,6 +191,9 @@ public class ObjectiveC2_DecompilerMessageAnalyzer extends AbstractAnalyzer {
|
||||||
}
|
}
|
||||||
setReference(objcCallAddress, program, currentClassName, currentMethodName);
|
setReference(objcCallAddress, program, currentClassName, currentMethodName);
|
||||||
|
|
||||||
|
if (instruction == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (instruction.getComment(CodeUnit.EOL_COMMENT) != null) {
|
if (instruction.getComment(CodeUnit.EOL_COMMENT) != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,21 +70,57 @@ public final class DataUtilities {
|
||||||
*/
|
*/
|
||||||
CLEAR_SINGLE_DATA,
|
CLEAR_SINGLE_DATA,
|
||||||
/**
|
/**
|
||||||
* Clear all conflicting Undefined data provided data will
|
* Clear all conflicting Undefined Data provided new data will
|
||||||
* fit within memory and not conflict with an
|
* fit within memory and not conflict with an
|
||||||
* instruction or other defined data. Undefined refers to defined
|
* instruction or other defined data. Undefined refers to defined
|
||||||
* data with the Undefined data-type.
|
* data with the Undefined data-type (see {@link Undefined#isUndefined(DataType)}).
|
||||||
* @see Undefined#isUndefined(DataType)
|
|
||||||
*/
|
*/
|
||||||
CLEAR_ALL_UNDEFINED_CONFLICT_DATA,
|
CLEAR_ALL_UNDEFINED_CONFLICT_DATA,
|
||||||
/**
|
/**
|
||||||
* Clear all conflicting data provided data will
|
* Clear all Default Data provided new data will fit within memory and
|
||||||
* fit within memory and not conflict with an
|
* not conflict with an instruction or other defined data. In this
|
||||||
* instruction.
|
* context Default Data refers to all defined data with either an
|
||||||
|
* Undefined data-type (see {@link Undefined#isUndefined(DataType)}) or
|
||||||
|
* is considered a default pointer which is either:
|
||||||
|
* <ol>
|
||||||
|
* <li>A pointer without a referenced datatype (i.e., <i>addr</i>), or</li>
|
||||||
|
* <li>An auto-named pointer-typedef without a referenced datatype
|
||||||
|
* (e.g., <i>pointer __((offset(0x8)))</i>.</li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
CLEAR_ALL_DEFAULT_CONFLICT_DATA,
|
||||||
|
/**
|
||||||
|
* Clear all conflicting data provided new data will fit within memory and
|
||||||
|
* not conflict with an instruction.
|
||||||
*/
|
*/
|
||||||
CLEAR_ALL_CONFLICT_DATA
|
CLEAR_ALL_CONFLICT_DATA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isDefaultData(DataType dt) {
|
||||||
|
// see ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA
|
||||||
|
if (Undefined.isUndefined(dt)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (dt instanceof Pointer) {
|
||||||
|
Pointer p = (Pointer) dt;
|
||||||
|
dt = p.getDataType();
|
||||||
|
return dt == null || dt == DataType.DEFAULT;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDataClearingDenied(DataType dt, ClearDataMode clearMode) {
|
||||||
|
if ((clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
||||||
|
!Undefined.isUndefined(dt))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (clearMode == ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA &&
|
||||||
|
!isDefaultData(dt)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create data where existing data may already exist.
|
* Create data where existing data may already exist.
|
||||||
* @param program the program
|
* @param program the program
|
||||||
|
@ -113,8 +149,7 @@ public final class DataUtilities {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stackPointers && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
if (!stackPointers && isDataClearingDenied(existingType, clearMode)) {
|
||||||
!Undefined.isUndefined(existingType)) {
|
|
||||||
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,12 +211,12 @@ public final class DataUtilities {
|
||||||
|
|
||||||
// null data; see if we are in a composite
|
// null data; see if we are in a composite
|
||||||
if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA ||
|
if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA ||
|
||||||
clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA) {
|
clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA ||
|
||||||
|
clearMode == ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA) {
|
||||||
|
|
||||||
// allow offcut addr if CLEAR_ALL_CONFLICT_DATA
|
// allow offcut addr if CLEAR_ALL_CONFLICT_DATA
|
||||||
data = listing.getDataContaining(addr);
|
data = listing.getDataContaining(addr);
|
||||||
if (data != null && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
if (data != null && isDataClearingDenied(data.getDataType(), clearMode)) {
|
||||||
!Undefined.isUndefined(data.getDataType())) {
|
|
||||||
data = null; // force error
|
data = null; // force error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,32 +302,8 @@ public final class DataUtilities {
|
||||||
return extRef;
|
return extRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validateCanCreateData(Address addr, ClearDataMode clearMode,
|
|
||||||
Listing listing, Data data) throws CodeUnitInsertionException {
|
|
||||||
|
|
||||||
if (data != null) {
|
|
||||||
return; // existing data; it us possible to create data
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA ||
|
|
||||||
clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA) {
|
|
||||||
|
|
||||||
// allow offcut addr if CLEAR_ALL_CONFLICT_DATA
|
|
||||||
data = listing.getDataContaining(addr);
|
|
||||||
if (data != null && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
|
||||||
!Undefined.isUndefined(data.getDataType())) {
|
|
||||||
data = null; // force error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// null data implies that we cannot create data at this address
|
|
||||||
if (data == null) {
|
|
||||||
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkEnoughSpace(Program program, Address addr, int existingDataLen,
|
private static void checkEnoughSpace(Program program, Address addr, int existingDataLen,
|
||||||
DataTypeInstance dti, ClearDataMode mode) throws CodeUnitInsertionException {
|
DataTypeInstance dti, ClearDataMode clearMode) throws CodeUnitInsertionException {
|
||||||
// NOTE: method not invoked when clearMode == ClearDataMode.CLEAR_SINGLE_DATA
|
// NOTE: method not invoked when clearMode == ClearDataMode.CLEAR_SINGLE_DATA
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
Address end = null;
|
Address end = null;
|
||||||
|
@ -318,11 +329,12 @@ public final class DataUtilities {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
if ((clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA ||
|
||||||
Undefined.isUndefined(definedData.getDataType())) {
|
clearMode == ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA) &&
|
||||||
checkForDefinedData(dti, listing, newEnd, definedData.getMaxAddress());
|
!isDataClearingDenied(definedData.getDataType(), clearMode)) {
|
||||||
|
checkForDefinedData(dti, listing, newEnd, definedData.getMaxAddress(), clearMode);
|
||||||
}
|
}
|
||||||
else if (mode != ClearDataMode.CLEAR_ALL_CONFLICT_DATA) {
|
else if (clearMode != ClearDataMode.CLEAR_ALL_CONFLICT_DATA) {
|
||||||
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
||||||
dti.getDataType().getDisplayName());
|
dti.getDataType().getDisplayName());
|
||||||
}
|
}
|
||||||
|
@ -330,9 +342,9 @@ public final class DataUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkForDefinedData(DataTypeInstance dti, Listing listing, Address address,
|
private static void checkForDefinedData(DataTypeInstance dti, Listing listing, Address address,
|
||||||
Address end) throws CodeUnitInsertionException {
|
Address end, ClearDataMode clearMode) throws CodeUnitInsertionException {
|
||||||
|
|
||||||
// ignore all defined data which is considered Undefined and may be cleared
|
// ignore all defined data which may be cleared
|
||||||
while (end.compareTo(address) <= 0) {
|
while (end.compareTo(address) <= 0) {
|
||||||
Data definedData = listing.getDefinedDataAfter(end);
|
Data definedData = listing.getDefinedDataAfter(end);
|
||||||
if (definedData == null ||
|
if (definedData == null ||
|
||||||
|
@ -340,7 +352,7 @@ public final class DataUtilities {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Undefined.isUndefined(definedData.getDataType())) {
|
if (isDataClearingDenied(definedData.getDataType(), clearMode)) {
|
||||||
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
||||||
dti.getDataType().getDisplayName());
|
dti.getDataType().getDisplayName());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue