use std::{
ffi::{CString, c_char},
ptr::*,
};
use llvm_sys::disassembler::*;
use llvm_sys::target::*;
mod core;
#[derive(Debug)]
struct TestFieldState {
inverse: bool,
width: u32,
index: u32,
current: Option<u32>,
}
impl TestFieldState {
pub fn new(width: u32) -> Self {
Self {
inverse: false,
width,
index: 0,
current: None,
}
}
pub fn reset(&mut self) {
self.inverse = false;
self.index = 0;
self.current = None;
}
}
impl Iterator for TestFieldState {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.width <= 2 {
if self.index == 1 << self.width {
return None;
}
self.current = Some(self.index);
} else {
if self.index >= self.width + 1 {
if self.inverse {
return None;
}
self.inverse = true;
self.index = 0;
}
if self.inverse {
let value = 2_u32.pow(self.width - self.index) >> 1;
self.current = Some(!value & (2_u32.pow(self.width) - 1));
} else {
let value = 2_u32.pow(self.index) >> 1;
self.current = Some(value);
}
}
self.index += 1;
self.current
}
}
struct TestIterator<const N: usize> {
states: [TestFieldState; N],
}
impl<const N: usize> TestIterator<N> {
fn new(widths: &[u32; N]) -> Self {
let states = widths
.iter()
.map(|f| TestFieldState::new(*f))
.collect::<Vec<TestFieldState>>()
.try_into()
.unwrap();
Self { states }
}
}
impl<const N: usize> Iterator for TestIterator<N> {
type Item = [u32; N];
fn next(&mut self) -> Option<Self::Item> {
if N == 0 {
return None;
}
let mut values = [0; N];
let mut next = true;
for (i, (s, v)) in self.states.iter_mut().zip(values.iter_mut()).enumerate() {
if next {
match s.next() {
None => {
if i == N - 1 {
return None;
} else {
s.reset();
*v = s.next().unwrap();
}
}
Some(x) => {
*v = x;
next = false;
}
}
} else {
match s.current {
None => *v = s.next().unwrap(),
Some(x) => *v = x,
}
}
}
Some(values)
}
}
pub fn llvm_create_disassembler(
triple: &str,
cpu: &str,
features: &str,
) -> Option<LLVMDisasmContextRef> {
unsafe {
LLVMInitializeARMTargetInfo();
LLVMInitializeARMTargetMC();
LLVMInitializeARMDisassembler();
LLVMInitializeAArch64TargetInfo();
LLVMInitializeAArch64TargetMC();
LLVMInitializeAArch64Disassembler();
let triple = CString::new(triple).unwrap();
let cpu = CString::new(cpu).unwrap();
let features = CString::new(features).unwrap();
let d = LLVMCreateDisasmCPUFeatures(
triple.as_ptr(),
cpu.as_ptr(),
features.as_ptr(),
null_mut(),
0,
None,
None,
);
if d.is_null() { None } else { Some(d) }
}
}
pub fn llvm_dispose_disassembler(d: LLVMDisasmContextRef) {
unsafe {
LLVMDisasmDispose(d);
}
}
pub fn llvm_disassemble(d: LLVMDisasmContextRef, insn: &mut [u8], address: u64) -> Vec<String> {
let mut outdisas = [0u8; 0x100];
let mut outinsn = Vec::new();
let mut offset = 0;
let mut address = address;
unsafe {
loop {
let l = LLVMDisasmInstruction(
d,
insn[offset..].as_mut_ptr() as *mut u8,
(insn.len() - offset) as u64,
address,
outdisas.as_mut_ptr() as *mut c_char,
0x100,
);
let null_byte_pos = outdisas.iter().position(|&b| b == 0).unwrap();
if l == 0 {
break;
}
outinsn.push(
String::from_utf8(outdisas[1..null_byte_pos].to_vec())
.unwrap()
.to_string()
.replace('\t', " "),
);
address += l as u64;
offset += l as usize;
}
}
outinsn
}