Commit 45ececd2 by Melvin Klimke Committed by Enkelmann

Parse Calling Convention Register from Ghidra (#87)

parent 945cbf90
import java.io.FileNotFoundException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
...@@ -10,6 +12,7 @@ import org.apache.commons.lang3.EnumUtils; ...@@ -10,6 +12,7 @@ import org.apache.commons.lang3.EnumUtils;
import bil.*; import bil.*;
import term.*; import term.*;
import internal.*;
import symbol.ExternSymbol; import symbol.ExternSymbol;
import serializer.Serializer; import serializer.Serializer;
import ghidra.app.script.GhidraScript; import ghidra.app.script.GhidraScript;
...@@ -20,6 +23,7 @@ import ghidra.program.model.block.CodeBlockIterator; ...@@ -20,6 +23,7 @@ import ghidra.program.model.block.CodeBlockIterator;
import ghidra.program.model.block.CodeBlockReferenceIterator; import ghidra.program.model.block.CodeBlockReferenceIterator;
import ghidra.program.model.block.SimpleBlockModel; import ghidra.program.model.block.SimpleBlockModel;
import ghidra.program.model.lang.CompilerSpec; import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.PrototypeModel;
import ghidra.program.model.lang.Register; import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator; import ghidra.program.model.listing.FunctionIterator;
...@@ -28,6 +32,7 @@ import ghidra.program.model.listing.Instruction; ...@@ -28,6 +32,7 @@ import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.InstructionIterator; import ghidra.program.model.listing.InstructionIterator;
import ghidra.program.model.listing.Listing; import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.Parameter; import ghidra.program.model.listing.Parameter;
import ghidra.program.model.listing.VariableStorage;
import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.Varnode; import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.Symbol; import ghidra.program.model.symbol.Symbol;
...@@ -574,6 +579,14 @@ public class PcodeExtractor extends GhidraScript { ...@@ -574,6 +579,14 @@ public class PcodeExtractor extends GhidraScript {
project.setProgram(program); project.setProgram(program);
project.setStackPointerRegister(stackPointerVar); project.setStackPointerRegister(stackPointerVar);
project.setCpuArch(cpuArch); project.setCpuArch(cpuArch);
try {
HashMap<String, RegisterConvention> conventions = new HashMap<String, RegisterConvention>();
ParseCspecContent.parseSpecs(ghidraProgram, conventions);
addParameterRegister(conventions);
project.setRegisterConvention(new ArrayList<RegisterConvention>(conventions.values()));
} catch (FileNotFoundException e) {
System.out.println(e);
}
return project; return project;
} }
...@@ -1066,4 +1079,20 @@ public class PcodeExtractor extends GhidraScript { ...@@ -1066,4 +1079,20 @@ public class PcodeExtractor extends GhidraScript {
return ""; return "";
} }
/**
* Adds parameter register to the RegisterCallingConvention object
*/
protected void addParameterRegister(HashMap<String, RegisterConvention> conventions) {
PrototypeModel[] models = ghidraProgram.getCompilerSpec().getCallingConventions();
for(PrototypeModel model : models) {
String cconv = model.getName();
if(conventions.get(cconv) != null) {
ArrayList<String> parameters = conventions.get(cconv).getParameter();
for(VariableStorage storage : model.getPotentialInputRegisterStorage(ghidraProgram)) {
parameters.add(storage.getRegister().getName());
}
}
}
}
} }
package internal;
import java.util.ArrayList; import java.util.ArrayList;
import ghidra.program.model.listing.Instruction; import ghidra.program.model.listing.Instruction;
......
package internal;
import java.util.ArrayList;
import com.google.gson.annotations.SerializedName;
public class RegisterConvention {
@SerializedName("calling_convention")
private String cconv;
@SerializedName("parameter_register")
private ArrayList<String> parameter;
@SerializedName("return_register")
private ArrayList<String> return_;
@SerializedName("unaffected_register")
private ArrayList<String> unaffected;
@SerializedName("killed_by_call_register")
private ArrayList<String> killedByCall;
public RegisterConvention() {
this.setParameter(new ArrayList<String>());
this.setReturn(new ArrayList<String>());
this.setUnaffected(new ArrayList<String>());
this.setKilledByCall(new ArrayList<String>());
}
public RegisterConvention(String cconv, ArrayList<String> parameter, ArrayList<String> return_, ArrayList<String> unaffected, ArrayList<String> killedByCall) {
this.setCconv(cconv);
this.setParameter(parameter);
this.setReturn(return_);
this.setUnaffected(unaffected);
this.setKilledByCall(killedByCall);
}
public String getCconv() {
return cconv;
}
public void setCconv(String cconv) {
this.cconv = cconv;
}
public ArrayList<String> getParameter() {
return parameter;
}
public void setParameter(ArrayList<String> parameter) {
this.parameter = parameter;
}
public ArrayList<String> getReturn() {
return return_;
}
public void setReturn(ArrayList<String> return_) {
this.return_ = return_;
}
public ArrayList<String> getUnaffected() {
return unaffected;
}
public void setUnaffected(ArrayList<String> unaffected) {
this.unaffected = unaffected;
}
public ArrayList<String> getKilledByCall() {
return killedByCall;
}
public void setKilledByCall(ArrayList<String> killedByCall) {
this.killedByCall = killedByCall;
}
}
package term; package term;
import bil.Variable; import bil.Variable;
import internal.RegisterConvention;
import java.util.ArrayList;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
public class Project { public class Project {
...@@ -10,14 +14,17 @@ public class Project { ...@@ -10,14 +14,17 @@ public class Project {
private Variable stackPointerRegister; private Variable stackPointerRegister;
@SerializedName("cpu_architecture") @SerializedName("cpu_architecture")
private String cpuArch; private String cpuArch;
@SerializedName("register_calling_convention")
private ArrayList<RegisterConvention> conventions;
public Project() { public Project() {
} }
public Project(Term<Program> program, String cpuArch, Variable stackPointerRegister) { public Project(Term<Program> program, String cpuArch, Variable stackPointerRegister, ArrayList<RegisterConvention> conventions) {
this.setProgram(program); this.setProgram(program);
this.setCpuArch(cpuArch); this.setCpuArch(cpuArch);
this.setStackPointerRegister(stackPointerRegister); this.setStackPointerRegister(stackPointerRegister);
this.setRegisterConvention(conventions);
} }
public Term<Program> getProgram() { public Term<Program> getProgram() {
...@@ -43,4 +50,12 @@ public class Project { ...@@ -43,4 +50,12 @@ public class Project {
public void setCpuArch(String cpuArch) { public void setCpuArch(String cpuArch) {
this.cpuArch = cpuArch; this.cpuArch = cpuArch;
} }
public ArrayList<RegisterConvention> getRegisterConvention() {
return conventions;
}
public void setRegisterConvention(ArrayList<RegisterConvention> conventions) {
this.conventions = conventions;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment