#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UdFile {
pub module: Module,
pub items: Vec<Item>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Module {
pub fields: Vec<Field>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Field {
pub name: String,
pub value: Value,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Value {
String(String),
Int(u64),
List(Vec<Value>),
Block(Vec<Field>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Attribute {
pub key: String,
pub value: AttrValue,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AttrValue {
String(String),
Int(u64),
ByteList(Vec<u8>),
Flag,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Item {
Comment(String),
Function(FnDecl),
Raw { addr: u64, bytes: Vec<u8> },
Strings { addr: u64, strings: Vec<String> },
Notes { addr: u64, entries: Vec<NoteEntry> },
Section {
name: String,
addr: u64,
items: Vec<Item>,
},
JumpTable {
addr: u64,
dispatch: String,
entries: Vec<JumpTableEntry>,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JumpTableEntry {
pub case: u64,
pub target: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NoteEntry {
pub note_type: u32,
pub name: String,
pub desc: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FnDecl {
pub addr: Option<u64>,
pub name: String,
pub attrs: Vec<Attribute>,
pub signature: Option<Signature>,
pub locals: Vec<LocalDecl>,
pub body: Vec<Stmt>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LocalDecl {
pub name: String,
pub ty: Type,
pub kind: LocalKind,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LocalKind {
Stack,
Register,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Signature {
pub params: Vec<Param>,
pub return_type: Type,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Param {
pub name: String,
pub ty: Type,
pub location: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Type {
Void,
I8,
I16,
I32,
I64,
U8,
U16,
U32,
U64,
F32,
F64,
Bool,
Char,
Pointer(Box<Type>),
Unknown,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct PrologueParams {
pub saves: Vec<String>,
pub saves_after: Vec<String>,
pub frame: bool,
pub sub_esp: u32,
pub cf_protect: bool,
pub frame_alt: bool,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct EpilogueParams {
pub saves: Vec<String>,
pub leave: bool,
pub pop_frame: bool,
pub add_esp: u32,
pub ret_imm: u16,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Stmt {
Asm { text: String, bytes: Vec<u8> },
Comment(String),
Return { value: u64, bytes: Vec<u8> },
Prologue {
kind: String,
params: Option<PrologueParams>,
bytes: Vec<u8>,
},
Epilogue {
kind: String,
params: Option<EpilogueParams>,
bytes: Vec<u8>,
},
Save { reg: String, bytes: Vec<u8> },
Restore { reg: String, bytes: Vec<u8> },
IfReturn {
cond_text: String,
value_text: String,
target_addr: u64,
cmp_bytes: Vec<u8>,
cond_code: u8,
wide: bool,
},
Label { addr: u64 },
Goto { target_addr: u64, wide: bool },
IfGoto {
cond_text: String,
target_addr: u64,
cmp_bytes: Vec<u8>,
cond_code: u8,
wide: bool,
},
Switch {
selector: String,
cases: Vec<u64>,
default_addr: u64,
dispatch: String,
table_va: u64,
},
SehInstall { bytes: Vec<u8> },
SehRestore { bytes: Vec<u8> },
ReturnExpr { text: String, bytes: Vec<u8> },
ArgSpill { arg_index: u32, bytes: Vec<u8> },
Call {
name: String,
args: Vec<String>,
bytes: Vec<u8>,
direct_target: Option<u64>,
},
IfBranch {
cond_text: String,
cond_bytes: Vec<u8>,
attrs: Vec<Attribute>,
pre_body: Vec<Stmt>,
then_body: Vec<Stmt>,
else_body: Option<Vec<Stmt>>,
},
LocalSet {
slot: i64,
value: i64,
bytes: Vec<u8>,
},
LocalArith {
slot: i64,
op: String,
value: i64,
bytes: Vec<u8>,
},
LocalCompound {
dst: i64,
op: String,
src: i64,
bytes: Vec<u8>,
},
Move {
dst: String,
src: String,
bytes: Vec<u8>,
},
Inc16 {
lo: String,
hi: String,
bytes: Vec<u8>,
},
Loop {
cond_text: String,
entry_jmp_bytes: Option<Vec<u8>>,
tail_bytes: Vec<u8>,
body: Vec<Stmt>,
},
}
impl Stmt {
#[must_use]
pub fn asm(text: impl Into<String>, bytes: Vec<u8>) -> Self {
Self::Asm {
text: text.into(),
bytes,
}
}
#[must_use]
pub fn asm_text(text: impl Into<String>) -> Self {
Self::Asm {
text: text.into(),
bytes: Vec::new(),
}
}
}