Unverified Commit b9b6b6dd by Melvin Klimke Committed by GitHub

- Added C/C++ data type property information to the project struct (#173)

parent 08aa5544
...@@ -147,6 +147,7 @@ fn backward_fixpoint() { ...@@ -147,6 +147,7 @@ fn backward_fixpoint() {
is_temp: false, is_temp: false,
}, },
calling_conventions: Vec::new(), calling_conventions: Vec::new(),
datatype_properties: DatatypeProperties::mock(),
}; };
let mock_con = Context::new(&project); let mock_con = Context::new(&project);
......
use crate::intermediate_representation::DatatypeProperties;
use super::*; use super::*;
use std::collections::HashSet; use std::collections::HashSet;
...@@ -22,6 +24,7 @@ fn mock_extern_symbol(name: &str) -> ExternSymbol { ...@@ -22,6 +24,7 @@ fn mock_extern_symbol(name: &str) -> ExternSymbol {
parameters: vec![arg.clone()], parameters: vec![arg.clone()],
return_values: vec![arg], return_values: vec![arg],
no_return: false, no_return: false,
has_var_args: false,
} }
} }
...@@ -91,6 +94,7 @@ fn mock_project() -> (Project, Config) { ...@@ -91,6 +94,7 @@ fn mock_project() -> (Project, Config) {
cpu_architecture: "x86_64".to_string(), cpu_architecture: "x86_64".to_string(),
stack_pointer_register: register("RSP"), stack_pointer_register: register("RSP"),
calling_conventions: vec![cconv], calling_conventions: vec![cconv],
datatype_properties: DatatypeProperties::mock(),
}, },
Config { Config {
allocation_symbols: vec!["malloc".into()], allocation_symbols: vec!["malloc".into()],
......
...@@ -299,6 +299,7 @@ fn clear_parameters_on_the_stack_on_extern_calls() { ...@@ -299,6 +299,7 @@ fn clear_parameters_on_the_stack_on_extern_calls() {
parameters: vec![stack_param], parameters: vec![stack_param],
return_values: Vec::new(), return_values: Vec::new(),
no_return: false, no_return: false,
has_var_args: false,
}; };
// check the value before // check the value before
let pointer = PointerDomain::new(new_id("time0", "RSP"), bv(-12)).into(); let pointer = PointerDomain::new(new_id("time0", "RSP"), bv(-12)).into();
......
...@@ -410,6 +410,7 @@ mod tests { ...@@ -410,6 +410,7 @@ mod tests {
parameters: Vec::new(), parameters: Vec::new(),
return_values: vec![arg1, arg2], return_values: vec![arg1, arg2],
no_return: false, no_return: false,
has_var_args: false,
}; };
let state = State::new(&symbol, &register("RSP"), Some(&pi_state)); let state = State::new(&symbol, &register("RSP"), Some(&pi_state));
(state, pi_state) (state, pi_state)
......
...@@ -35,6 +35,7 @@ impl ExternSymbol { ...@@ -35,6 +35,7 @@ impl ExternSymbol {
parameters: vec![Arg::mock_register("RDI"), Arg::mock_register("RSI")], parameters: vec![Arg::mock_register("RDI"), Arg::mock_register("RSI")],
return_values: vec![Arg::mock_register("RAX")], return_values: vec![Arg::mock_register("RAX")],
no_return: false, no_return: false,
has_var_args: true,
} }
} }
} }
......
...@@ -6,7 +6,7 @@ use crate::{ ...@@ -6,7 +6,7 @@ use crate::{
use super::*; use super::*;
fn extern_symbol(name: &str, return_args: Vec<Arg>) -> ExternSymbol { fn extern_symbol(name: &str, return_args: Vec<Arg>, has_var_args: bool) -> ExternSymbol {
ExternSymbol { ExternSymbol {
tid: Tid::new(name.to_string()), tid: Tid::new(name.to_string()),
addresses: vec![], addresses: vec![],
...@@ -15,6 +15,7 @@ fn extern_symbol(name: &str, return_args: Vec<Arg>) -> ExternSymbol { ...@@ -15,6 +15,7 @@ fn extern_symbol(name: &str, return_args: Vec<Arg>) -> ExternSymbol {
parameters: Vec::new(), parameters: Vec::new(),
return_values: return_args, return_values: return_args,
no_return: false, no_return: false,
has_var_args,
} }
} }
...@@ -27,7 +28,7 @@ impl State { ...@@ -27,7 +28,7 @@ impl State {
let arg = Arg::Register(Variable::mock("RAX", 8 as u64)); let arg = Arg::Register(Variable::mock("RAX", 8 as u64));
let pi_state = let pi_state =
PointerInferenceState::new(&Variable::mock("RSP", 8 as u64), Tid::new("func")); PointerInferenceState::new(&Variable::mock("RSP", 8 as u64), Tid::new("func"));
let symbol = extern_symbol("system", vec![arg]); let symbol = extern_symbol("system", vec![arg], false);
let current_sub = Sub::mock("current"); let current_sub = Sub::mock("current");
let mut state = State::new( let mut state = State::new(
&symbol, &symbol,
......
...@@ -87,6 +87,29 @@ impl ByteSize { ...@@ -87,6 +87,29 @@ impl ByteSize {
} }
} }
/// Properties of C/C++ data types such as size.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)]
pub struct DatatypeProperties {
/// Holds the size of the char type
pub char_size: ByteSize,
/// Holds the size of the double type
pub double_size: ByteSize,
/// Holds the size of the float type
pub float_size: ByteSize,
/// Holds the size of the integer type
pub integer_size: ByteSize,
/// Holds the size of the long double type
pub long_double_size: ByteSize,
/// Holds the size of the long long type
pub long_long_size: ByteSize,
/// Holds the size of the long type
pub long_size: ByteSize,
/// Holds the size of the pointer type
pub pointer_size: ByteSize,
/// Holds the size of the short type
pub short_size: ByteSize,
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use apint::BitWidth; use apint::BitWidth;
......
use super::{ByteSize, CastOpType, Expression, Variable}; use super::{ByteSize, CastOpType, DatatypeProperties, Expression, Variable};
use crate::prelude::*; use crate::prelude::*;
use crate::utils::log::LogMessage; use crate::utils::log::LogMessage;
use std::collections::HashSet; use std::collections::HashSet;
...@@ -346,6 +346,8 @@ pub struct ExternSymbol { ...@@ -346,6 +346,8 @@ pub struct ExternSymbol {
pub return_values: Vec<Arg>, pub return_values: Vec<Arg>,
/// If set to `true`, the function is assumed to never return to its caller when called. /// If set to `true`, the function is assumed to never return to its caller when called.
pub no_return: bool, pub no_return: bool,
/// If the function has a variable number of parameters, this flag is set to `true`.
pub has_var_args: bool,
} }
impl ExternSymbol { impl ExternSymbol {
...@@ -444,6 +446,8 @@ pub struct Project { ...@@ -444,6 +446,8 @@ pub struct Project {
pub stack_pointer_register: Variable, pub stack_pointer_register: Variable,
/// The known calling conventions that may be used for calls to extern functions. /// The known calling conventions that may be used for calls to extern functions.
pub calling_conventions: Vec<CallingConvention>, pub calling_conventions: Vec<CallingConvention>,
/// Contains the properties of C data types. (e.g. size)
pub datatype_properties: DatatypeProperties,
} }
impl Project { impl Project {
...@@ -635,6 +639,23 @@ mod tests { ...@@ -635,6 +639,23 @@ mod tests {
parameters: vec![Arg::mock_register("RDI")], parameters: vec![Arg::mock_register("RDI")],
return_values: vec![Arg::mock_register("RAX")], return_values: vec![Arg::mock_register("RAX")],
no_return: false, no_return: false,
has_var_args: false,
}
}
}
impl DatatypeProperties {
pub fn mock() -> DatatypeProperties {
DatatypeProperties {
char_size: ByteSize::new(1),
double_size: ByteSize::new(8),
float_size: ByteSize::new(4),
integer_size: ByteSize::new(4),
long_double_size: ByteSize::new(8),
long_long_size: ByteSize::new(8),
long_size: ByteSize::new(4),
pointer_size: ByteSize::new(4),
short_size: ByteSize::new(2),
} }
} }
} }
...@@ -649,6 +670,7 @@ mod tests { ...@@ -649,6 +670,7 @@ mod tests {
cpu_architecture: "x86_64".to_string(), cpu_architecture: "x86_64".to_string(),
stack_pointer_register: Variable::mock("RSP", 8u64), stack_pointer_register: Variable::mock("RSP", 8u64),
calling_conventions: Vec::new(), calling_conventions: Vec::new(),
datatype_properties: DatatypeProperties::mock(),
} }
} }
} }
......
...@@ -5,6 +5,7 @@ use crate::intermediate_representation::Arg as IrArg; ...@@ -5,6 +5,7 @@ use crate::intermediate_representation::Arg as IrArg;
use crate::intermediate_representation::Blk as IrBlk; use crate::intermediate_representation::Blk as IrBlk;
use crate::intermediate_representation::ByteSize; use crate::intermediate_representation::ByteSize;
use crate::intermediate_representation::CallingConvention as IrCallingConvention; use crate::intermediate_representation::CallingConvention as IrCallingConvention;
use crate::intermediate_representation::DatatypeProperties;
use crate::intermediate_representation::Def as IrDef; use crate::intermediate_representation::Def as IrDef;
use crate::intermediate_representation::Expression as IrExpression; use crate::intermediate_representation::Expression as IrExpression;
use crate::intermediate_representation::ExternSymbol as IrExternSymbol; use crate::intermediate_representation::ExternSymbol as IrExternSymbol;
...@@ -387,6 +388,8 @@ pub struct ExternSymbol { ...@@ -387,6 +388,8 @@ pub struct ExternSymbol {
pub arguments: Vec<Arg>, pub arguments: Vec<Arg>,
/// If the function is assumed to never return to the caller, this flag is set to `true`. /// If the function is assumed to never return to the caller, this flag is set to `true`.
pub no_return: bool, pub no_return: bool,
/// If the function has a variable number of parameters, this flag is set to `true`.
pub has_var_args: bool,
} }
impl From<ExternSymbol> for IrExternSymbol { impl From<ExternSymbol> for IrExternSymbol {
...@@ -431,6 +434,7 @@ impl From<ExternSymbol> for IrExternSymbol { ...@@ -431,6 +434,7 @@ impl From<ExternSymbol> for IrExternSymbol {
parameters, parameters,
return_values, return_values,
no_return: symbol.no_return, no_return: symbol.no_return,
has_var_args: symbol.has_var_args,
} }
} }
} }
...@@ -525,6 +529,8 @@ pub struct Project { ...@@ -525,6 +529,8 @@ pub struct Project {
pub register_properties: Vec<RegisterProperties>, pub register_properties: Vec<RegisterProperties>,
/// Information about known calling conventions for the given CPU architecture. /// Information about known calling conventions for the given CPU architecture.
pub register_calling_convention: Vec<CallingConvention>, pub register_calling_convention: Vec<CallingConvention>,
/// Contains the properties of C data types. (e.g. size)
pub datatype_properties: DatatypeProperties,
} }
impl Project { impl Project {
...@@ -642,6 +648,7 @@ impl Project { ...@@ -642,6 +648,7 @@ impl Project {
.into_iter() .into_iter()
.map(|cconv| cconv.into()) .map(|cconv| cconv.into())
.collect(), .collect(),
datatype_properties: self.datatype_properties,
} }
} }
} }
......
...@@ -90,7 +90,18 @@ impl Setup { ...@@ -90,7 +90,18 @@ impl Setup {
"unaffected_register": [], "unaffected_register": [],
"killed_by_call_register": [] "killed_by_call_register": []
} }
] ],
"datatype_properties": {
"char_size": 1,
"double_size": 8,
"float_size": 4,
"integer_size": 4,
"long_double_size": 8,
"long_long_size": 8,
"long_size": 4,
"pointer_size": 4,
"short_size": 2
}
} }
"#, "#,
) )
...@@ -581,7 +592,8 @@ fn extern_symbol_deserialization() { ...@@ -581,7 +592,8 @@ fn extern_symbol_deserialization() {
"intent": "OUTPUT" "intent": "OUTPUT"
} }
], ],
"no_return": false "no_return": false,
"has_var_args": false
} }
"#, "#,
) )
......
...@@ -260,6 +260,7 @@ public class PcodeExtractor extends GhidraScript { ...@@ -260,6 +260,7 @@ public class PcodeExtractor extends GhidraScript {
System.out.println(e); System.out.println(e);
} }
project.setRegisterProperties(HelperFunctions.getRegisterList()); project.setRegisterProperties(HelperFunctions.getRegisterList());
project.setDatatypeProperties(HelperFunctions.createDatatypeProperties());
return project; return project;
} }
......
package bil;
import com.google.gson.annotations.SerializedName;
public class DatatypeProperties {
@SerializedName("char_size")
private int charSize;
@SerializedName("double_size")
private int doubleSize;
@SerializedName("float_size")
private int floatSize;
@SerializedName("integer_size")
private int integerSize;
@SerializedName("long_double_size")
private int longDoubleSize;
@SerializedName("long_long_size")
private int longLongSize;
@SerializedName("long_size")
private int longSize;
@SerializedName("pointer_size")
private int pointerSize;
@SerializedName("short_size")
private int shortSize;
public DatatypeProperties(
int charSize,
int doubleSize,
int floatSize,
int integerSize,
int longDoubleSize,
int longLongSize,
int longSize,
int pointerSize,
int shortSize
) {
this.setCharSize(charSize);
this.setDoubleSize(doubleSize);
this.setFloatSize(floatSize);
this.setIntegerSize(integerSize);
this.setLongDoubleSize(longDoubleSize);
this.setLongLongSize(longLongSize);
this.setLongSize(longSize);
this.setPointerSize(pointerSize);
this.setShortSize(shortSize);
}
public void setCharSize(int size) {
this.charSize = size;
}
public void setDoubleSize(int size) {
this.doubleSize = size;
}
public void setFloatSize(int size) {
this.floatSize = size;
}
public void setIntegerSize(int size) {
this.integerSize = size;
}
public void setLongDoubleSize(int size) {
this.longDoubleSize = size;
}
public void setLongLongSize(int size) {
this.longLongSize = size;
}
public void setLongSize(int size) {
this.longSize = size;
}
public void setPointerSize(int size) {
this.pointerSize = size;
}
public void setShortSize(int size) {
this.shortSize = size;
}
}
...@@ -5,6 +5,7 @@ import java.util.HashMap; ...@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import bil.DatatypeProperties;
import bil.RegisterProperties; import bil.RegisterProperties;
import bil.Variable; import bil.Variable;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
...@@ -16,6 +17,7 @@ import ghidra.program.model.listing.FunctionManager; ...@@ -16,6 +17,7 @@ import ghidra.program.model.listing.FunctionManager;
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.SymbolTable; import ghidra.program.model.symbol.SymbolTable;
import ghidra.program.model.data.DataOrganization;
import ghidra.program.util.VarnodeContext; import ghidra.program.util.VarnodeContext;
import ghidra.util.task.TaskMonitor; import ghidra.util.task.TaskMonitor;
import term.*; import term.*;
...@@ -33,6 +35,26 @@ public final class HelperFunctions { ...@@ -33,6 +35,26 @@ public final class HelperFunctions {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/**
* @return new DatatypeProperties
*
* Creates the datatype sizes from the Compiler Specifications.
*/
public static DatatypeProperties createDatatypeProperties() {
DataOrganization dataOrga = ghidraProgram.getDataTypeManager().getDataOrganization();
return new DatatypeProperties(
dataOrga.getCharSize(),
dataOrga.getDoubleSize(),
dataOrga.getFloatSize(),
dataOrga.getIntegerSize(),
dataOrga.getLongDoubleSize(),
dataOrga.getLongLongSize(),
dataOrga.getLongSize(),
dataOrga.getPointerSize(),
dataOrga.getShortSize()
);
}
/** /**
* *
......
...@@ -21,12 +21,22 @@ public class ExternSymbol { ...@@ -21,12 +21,22 @@ public class ExternSymbol {
private ArrayList<Arg> arguments; private ArrayList<Arg> arguments;
@SerializedName("no_return") @SerializedName("no_return")
private Boolean noReturn; private Boolean noReturn;
@SerializedName("has_var_args")
private Boolean hasVarArgs;
public ExternSymbol() { public ExternSymbol() {
this.setAddresses(new ArrayList<String>()); this.setAddresses(new ArrayList<String>());
} }
public ExternSymbol(Tid tid, ArrayList<String> addresses, String name, String callingConvention, ArrayList<Arg> arguments, Boolean noReturn) { public ExternSymbol(
Tid tid,
ArrayList<String> addresses,
String name,
String callingConvention,
ArrayList<Arg> arguments,
Boolean noReturn,
Boolean hasVarArgs
) {
this.setTid(tid); this.setTid(tid);
this.setAddresses(addresses); this.setAddresses(addresses);
this.setName(name); this.setName(name);
...@@ -82,4 +92,12 @@ public class ExternSymbol { ...@@ -82,4 +92,12 @@ public class ExternSymbol {
public void setNoReturn(Boolean noReturn) { public void setNoReturn(Boolean noReturn) {
this.noReturn = noReturn; this.noReturn = noReturn;
} }
public Boolean getHasVarArgs() {
return hasVarArgs;
}
public void setHasVarArgs(Boolean hasVarArgs) {
this.hasVarArgs = hasVarArgs;
}
} }
...@@ -101,6 +101,7 @@ public class ExternSymbolCreator { ...@@ -101,6 +101,7 @@ public class ExternSymbolCreator {
extSym.setNoReturn(func.hasNoReturn()); extSym.setNoReturn(func.hasNoReturn());
extSym.setArguments(createArguments(func)); extSym.setArguments(createArguments(func));
extSym.setCallingConvention(HelperFunctions.funcMan.getDefaultCallingConvention().toString()); extSym.setCallingConvention(HelperFunctions.funcMan.getDefaultCallingConvention().toString());
extSym.setHasVarArgs(func.hasVarArgs());
} }
if(!func.isExternal()) { if(!func.isExternal()) {
extSym.getAddresses().add(func.getEntryPoint().toString()); extSym.getAddresses().add(func.getEntryPoint().toString());
......
package term; package term;
import bil.DatatypeProperties;
import bil.RegisterProperties; import bil.RegisterProperties;
import bil.Variable; import bil.Variable;
import internal.RegisterConvention; import internal.RegisterConvention;
...@@ -19,15 +20,24 @@ public class Project { ...@@ -19,15 +20,24 @@ public class Project {
private String cpuArch; private String cpuArch;
@SerializedName("register_calling_convention") @SerializedName("register_calling_convention")
private ArrayList<RegisterConvention> conventions; private ArrayList<RegisterConvention> conventions;
@SerializedName("datatype_properties")
private DatatypeProperties datatype_properties;
public Project() { public Project() {
} }
public Project(Term<Program> program, String cpuArch, Variable stackPointerRegister, ArrayList<RegisterConvention> conventions) { public Project(
Term<Program> program,
String cpuArch,
Variable stackPointerRegister,
ArrayList<RegisterConvention> conventions,
DatatypeProperties datatype_properties
) {
this.setProgram(program); this.setProgram(program);
this.setCpuArch(cpuArch); this.setCpuArch(cpuArch);
this.setStackPointerRegister(stackPointerRegister); this.setStackPointerRegister(stackPointerRegister);
this.setRegisterConvention(conventions); this.setRegisterConvention(conventions);
this.setDatatypeProperties(datatype_properties);
} }
public Term<Program> getProgram() { public Term<Program> getProgram() {
...@@ -69,4 +79,12 @@ public class Project { ...@@ -69,4 +79,12 @@ public class Project {
public void setRegisterProperties(ArrayList<RegisterProperties> registerProperties) { public void setRegisterProperties(ArrayList<RegisterProperties> registerProperties) {
this.registerProperties = registerProperties; this.registerProperties = registerProperties;
} }
public DatatypeProperties getDatatypeProperties() {
return datatype_properties;
}
public void setDatatypeProperties(DatatypeProperties datatype_properties) {
this.datatype_properties = datatype_properties;
}
} }
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