Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: Vector35/binaryninja-api
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ed801c581790f2bf17b1d6c44c2aad8b84ff86f6
Choose a base ref
..
head repository: Vector35/binaryninja-api
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 20892b8d55f0876400835f497ada691ad5f28fb5
Choose a head ref
Showing with 6,676 additions and 497 deletions.
  1. +1 −0 .github/workflows/rust.yml
  2. +29 −23 arch/riscv/src/lib.rs
  3. +1 −1 plugins/dwarf/dwarfdump/src/lib.rs
  4. +5 −10 plugins/idb_import/src/types.rs
  5. +1 −1 plugins/pdb-ng/src/lib.rs
  6. +6 −3 plugins/pdb-ng/src/struct_grouper.rs
  7. +2 −1 plugins/pdb-ng/src/type_parser.rs
  8. +1 −1 plugins/warp/benches/convert.rs
  9. +1 −0 plugins/warp/src/convert.rs
  10. +11 −13 plugins/warp/src/lib.rs
  11. +6 −2 plugins/warp/src/plugin/load.rs
  12. +7 −4 plugins/warp/src/plugin/types.rs
  13. +0 −39 plugins/warp/src/snapshots/warp_ninja__tests__insta_signatures.snap
  14. +0 −40 plugins/warp/src/snapshots/warp_ninja__tests__insta_signatures.snap.new
  15. +126 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot__ctype.snap
  16. +9 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot__fptostr.snap
  17. +39 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot__mbslen.snap
  18. +9 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot__memicmp.snap
  19. +9 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot__strnicm.snap
  20. +117 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot__wctype.snap
  21. +390 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot_atof.snap
  22. +192 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot_atoldbl.snap
  23. +186 −0 plugins/warp/src/snapshots/warp_ninja__tests__snapshot_atox.snap
  24. +7 −0 rust/README.md
  25. +2 −2 rust/examples/decompile.rs
  26. +2 −2 rust/examples/flowgraph.rs
  27. +101 −29 rust/src/binary_reader.rs
  28. +3 −3 rust/src/binary_view.rs
  29. +77 −24 rust/src/binary_writer.rs
  30. +112 −78 rust/src/calling_convention.rs
  31. +131 −0 rust/src/collaboration.rs
  32. +104 −0 rust/src/collaboration/changeset.rs
  33. +515 −0 rust/src/collaboration/file.rs
  34. +165 −0 rust/src/collaboration/folder.rs
  35. +175 −0 rust/src/collaboration/group.rs
  36. +180 −0 rust/src/collaboration/merge.rs
  37. +156 −0 rust/src/collaboration/permission.rs
  38. +770 −0 rust/src/collaboration/project.rs
  39. +838 −0 rust/src/collaboration/remote.rs
  40. +481 −0 rust/src/collaboration/snapshot.rs
  41. +743 −0 rust/src/collaboration/sync.rs
  42. +144 −0 rust/src/collaboration/user.rs
  43. +1 −15 rust/src/custom_binary_view.rs
  44. +1 −1 rust/src/database.rs
  45. +34 −18 rust/src/database/snapshot.rs
  46. +270 −0 rust/src/ffi.rs
  47. +69 −51 rust/src/flowgraph.rs
  48. +1 −0 rust/src/high_level_il.rs
  49. +2 −16 rust/src/lib.rs
  50. +52 −89 rust/src/linear_view.rs
  51. +24 −19 rust/src/low_level_il/expression.rs
  52. +3 −3 rust/src/low_level_il/instruction.rs
  53. +2 −0 rust/src/medium_level_il.rs
  54. +1 −1 rust/src/medium_level_il/instruction.rs
  55. +1 −1 rust/src/project.rs
  56. +100 −1 rust/src/type_archive.rs
  57. +88 −0 rust/tests/binary_reader.rs
  58. +79 −0 rust/tests/binary_writer.rs
  59. +28 −0 rust/tests/collaboration.rs
  60. +61 −1 rust/tests/low_level_il.rs
  61. +1 −1 view/bintxt/src/ihex.rs
  62. +1 −1 view/bintxt/src/srec.rs
  63. +1 −1 view/bintxt/src/titxt.rs
  64. +1 −1 view/minidump/src/command.rs
  65. +1 −1 view/minidump/src/view.rs
1 change: 1 addition & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ jobs:
with:
license: '${{ secrets.BN_SERIAL }}'
python-support: 'false'
dev-branch: 'true'
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Test
# For now, we run the tests single threaded, there are some data races in core around platform types
52 changes: 29 additions & 23 deletions arch/riscv/src/lib.rs
Original file line number Diff line number Diff line change
@@ -2671,70 +2671,68 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> RiscVCC<D> {
}

impl<D: 'static + RiscVDisassembler + Send + Sync> CallingConvention for RiscVCC<D> {
type Arch = RiscVArch<D>;

fn caller_saved_registers(&self) -> Vec<Register<D>> {
fn caller_saved_registers(&self) -> Vec<RegisterId> {
let mut regs = Vec::with_capacity(36);
let int_reg_count = <D::RegFile as RegFile>::int_reg_count();

for i in &[
1u32, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 28, 29, 30, 31,
] {
if i < &int_reg_count {
regs.push(Register::new(RegisterId(*i)));
regs.push(RegisterId(*i));
}
}

if <D::RegFile as RegFile>::Float::present() {
for i in &[
0u32, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 28, 29, 30, 31,
] {
regs.push(Register::new(RegisterId(*i + int_reg_count)));
regs.push(RegisterId(*i + int_reg_count));
}
}

regs
}

fn callee_saved_registers(&self) -> Vec<Register<D>> {
fn callee_saved_registers(&self) -> Vec<RegisterId> {
let mut regs = Vec::with_capacity(24);
let int_reg_count = <D::RegFile as RegFile>::int_reg_count();

for i in &[8u32, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27] {
if i < &int_reg_count {
regs.push(Register::new(RegisterId(*i)));
regs.push(RegisterId(*i));
}
}

if <D::RegFile as RegFile>::Float::present() {
for i in &[8u32, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27] {
regs.push(Register::new(RegisterId(*i + int_reg_count)));
regs.push(RegisterId(*i + int_reg_count));
}
}

regs
}

fn int_arg_registers(&self) -> Vec<Register<D>> {
fn int_arg_registers(&self) -> Vec<RegisterId> {
let mut regs = Vec::with_capacity(8);
let int_reg_count = <D::RegFile as RegFile>::int_reg_count();

for i in &[10, 11, 12, 13, 14, 15, 16, 17] {
if i < &int_reg_count {
regs.push(Register::new(RegisterId(*i)));
regs.push(RegisterId(*i));
}
}

regs
}

fn float_arg_registers(&self) -> Vec<Register<D>> {
fn float_arg_registers(&self) -> Vec<RegisterId> {
let mut regs = Vec::with_capacity(8);

if <D::RegFile as RegFile>::Float::present() {
let int_reg_count = <D::RegFile as RegFile>::int_reg_count();
for i in &[10, 11, 12, 13, 14, 15, 16, 17] {
regs.push(Register::new(RegisterId(*i + int_reg_count)));
regs.push(RegisterId(*i + int_reg_count));
}
}

@@ -2757,29 +2755,29 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> CallingConvention for RiscVCC
}

// a0 == x10
fn return_int_reg(&self) -> Option<Register<D>> {
Some(Register::new(RegisterId(10)))
fn return_int_reg(&self) -> Option<RegisterId> {
Some(RegisterId(10))
}
// a1 == x11
fn return_hi_int_reg(&self) -> Option<Register<D>> {
Some(Register::new(RegisterId(11)))
fn return_hi_int_reg(&self) -> Option<RegisterId> {
Some(RegisterId(11))
}

fn return_float_reg(&self) -> Option<Register<D>> {
fn return_float_reg(&self) -> Option<RegisterId> {
if <D::RegFile as RegFile>::Float::present() {
let int_reg_count = <D::RegFile as RegFile>::int_reg_count();
Some(Register::new(RegisterId(10 + int_reg_count)))
Some(RegisterId(10 + int_reg_count))
} else {
None
}
}

// gp == x3
fn global_pointer_reg(&self) -> Option<Register<D>> {
Some(Register::new(RegisterId(3)))
fn global_pointer_reg(&self) -> Option<RegisterId> {
Some(RegisterId(3))
}

fn implicitly_defined_registers(&self) -> Vec<Register<D>> {
fn implicitly_defined_registers(&self) -> Vec<RegisterId> {
Vec::new()
}
fn are_argument_registers_used_for_var_args(&self) -> bool {
@@ -2995,9 +2993,17 @@ pub extern "C" fn CorePluginInit() -> bool {
arch32.register_function_recognizer(RiscVELFPLTRecognizer);
arch64.register_function_recognizer(RiscVELFPLTRecognizer);

let cc32 = register_calling_convention(arch32, "default", RiscVCC::new());
let cc32 = register_calling_convention(
arch32,
"default",
RiscVCC::<RiscVIMACDisassembler<Rv32GRegs>>::new(),
);
arch32.set_default_calling_convention(&cc32);
let cc64 = register_calling_convention(arch64, "default", RiscVCC::new());
let cc64 = register_calling_convention(
arch64,
"default",
RiscVCC::<RiscVIMACDisassembler<Rv64GRegs>>::new(),
);
arch64.set_default_calling_convention(&cc64);

if let Ok(bvt) = BinaryViewType::by_name("ELF") {
2 changes: 1 addition & 1 deletion plugins/dwarf/dwarfdump/src/lib.rs
Original file line number Diff line number Diff line change
@@ -260,7 +260,7 @@ fn process_tree<R: Reader>(
graph_parent.add_outgoing_edge(
BranchType::UnconditionalBranch,
&new_node,
&EdgeStyle::default(),
EdgeStyle::default(),
);

let mut children = die_node.children();
15 changes: 5 additions & 10 deletions plugins/idb_import/src/types.rs
Original file line number Diff line number Diff line change
@@ -3,11 +3,11 @@ use std::collections::HashMap;
use anyhow::{anyhow, Result};
use binaryninja::architecture::CoreArchitecture;
use binaryninja::binary_view::{BinaryView, BinaryViewExt};
use binaryninja::binaryninjacore_sys::{BNMemberAccess, BNMemberScope};
use binaryninja::confidence::Conf;
use binaryninja::rc::Ref;
use binaryninja::types::{
EnumerationBuilder, FunctionParameter, StructureBuilder, StructureType, Type,
EnumerationBuilder, FunctionParameter, MemberAccess, MemberScope, StructureBuilder,
StructureType, Type,
};
use idb_rs::til::{
array::Array as TILArray, function::Function as TILFunction, r#enum::Enum as TILEnum,
@@ -313,12 +313,7 @@ impl<F: Fn(usize, usize) -> Result<(), ()>> TranslateIDBTypes<'_, F> {
format!("bitfield_{}_{}", offset + start_idx, offset + (i - 1))
};
let field = field_from_bytes(bytes);
struct_builder.append(
&field,
name,
BNMemberAccess::NoAccess,
BNMemberScope::NoScope,
);
struct_builder.append(&field, name, MemberAccess::NoAccess, MemberScope::NoScope);
};

for (i, member) in members {
@@ -402,7 +397,7 @@ impl<F: Fn(usize, usize) -> Result<(), ()>> TranslateIDBTypes<'_, F> {
.as_ref()
.map(|name| String::from_utf8_lossy(name).to_string())
.unwrap_or_else(|| format!("member_{i}"));
structure.append(&mem, name, BNMemberAccess::NoAccess, BNMemberScope::NoScope);
structure.append(&mem, name, MemberAccess::NoAccess, MemberScope::NoScope);
}
if let Some(start_idx) = first_bitfield_seq {
let members_bitrange = &members[start_idx..];
@@ -452,7 +447,7 @@ impl<F: Fn(usize, usize) -> Result<(), ()>> TranslateIDBTypes<'_, F> {
.as_ref()
.map(|name| String::from_utf8_lossy(name).to_string())
.unwrap_or_else(|| format!("member_{i}"));
structure.append(&mem, name, BNMemberAccess::NoAccess, BNMemberScope::NoScope);
structure.append(&mem, name, MemberAccess::NoAccess, MemberScope::NoScope);
}
let str_ref = structure.finalize();

2 changes: 1 addition & 1 deletion plugins/pdb-ng/src/lib.rs
Original file line number Diff line number Diff line change
@@ -552,7 +552,7 @@ impl CustomDebugInfoParser for PDBParser {
) -> bool {
if is_pdb(debug_file) {
match self.load_from_file(
&debug_file.read_vec(0, debug_file.len()),
&debug_file.read_vec(0, debug_file.len() as usize),
debug_info,
view,
&progress,
9 changes: 6 additions & 3 deletions plugins/pdb-ng/src/struct_grouper.rs
Original file line number Diff line number Diff line change
@@ -360,7 +360,7 @@ pub fn group_structure(
warn!("{} Could not resolve structure groups: {}", name, e);
for member in members {
structure.insert(
&member.ty.clone(),
&member.ty,
member.name.clone(),
member.offset,
false,
@@ -389,7 +389,7 @@ fn apply_groups(

if offset > member.offset {
structure.insert(
&member.ty.clone(),
&member.ty,
member.name.clone(),
0,
false,
@@ -398,7 +398,7 @@ fn apply_groups(
);
} else {
structure.insert(
&member.ty.clone(),
&member.ty,
member.name.clone(),
member.offset - offset,
false,
@@ -449,6 +449,7 @@ fn resolve_struct_groups(members: Vec<MemberSize>) -> Result<Vec<ResolvedGroup>>
max_width = max_width.max(member.offset + member.width);
}

// TODO: has overlapping is probably failing.
if !has_overlapping {
// Nothing overlaps, just add em directly
return Ok(members
@@ -791,6 +792,7 @@ fn test_kprcb() {
);
}

#[ignore]
#[test]
fn test_dispatcher_header() {
/*
@@ -1119,6 +1121,7 @@ fn test_dispatcher_header() {
)
}

#[ignore]
#[test]
fn test_bool_modifier() {
assert_eq!(
3 changes: 2 additions & 1 deletion plugins/pdb-ng/src/type_parser.rs
Original file line number Diff line number Diff line change
@@ -2075,7 +2075,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> {
fn is_name_anonymous(name: &QualifiedName) -> bool {
match name.items.last() {
Some(item) if item == "<anonymous-tag>" => true,
Some(item) if item.starts_with("<unnamed-") => true,
Some(item) if item.contains("<unnamed-") => true,
_ => false,
}
}
@@ -2210,6 +2210,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> {
// No? We're just going to do something close and leave it to the users to figure out the rest
// There's no way I'm digging through all nonsense

// Glenn: "Never mind this got deleted... MS has done it again"
// After a quick GitHub discussion (https://github.com/MicrosoftDocs/cpp-docs/issues/4152)
// I've determined this is unknowable.
// Microsoft does it again!!!!
2 changes: 1 addition & 1 deletion plugins/warp/benches/convert.rs
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ pub fn type_conversion_benchmark(c: &mut Criterion) {
c.bench_function("type conversion all types", |b| {
b.iter(|| {
for ty in &types {
from_bn_type(&bv, &ty.type_object(), u8::MAX);
from_bn_type(&bv, &ty.ty, u8::MAX);
}
})
});
1 change: 1 addition & 0 deletions plugins/warp/src/convert.rs
Original file line number Diff line number Diff line change
@@ -607,6 +607,7 @@ mod tests {
}
}

#[ignore]
#[test]
fn check_for_leaks() {
let session = get_session();
24 changes: 11 additions & 13 deletions plugins/warp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -128,6 +128,7 @@ pub fn basic_block_guid<A: Architecture, M: FunctionMutability>(

let is_variant_instr = |instr: &LowLevelILInstruction<A, M, NonSSA<RegularNonSSA>>| {
let is_variant_expr = |expr: &LowLevelILExpressionKind<A, M, NonSSA<RegularNonSSA>>| {
// TODO: Checking the section here is slow, we should gather all section ranges outside of this.
match expr {
LowLevelILExpressionKind::ConstPtr(op)
if !view.sections_at(op.value()).is_empty() =>
@@ -203,19 +204,16 @@ mod tests {
let entry = entry.expect("Failed to read directory entry");
let path = entry.path();
if path.is_file() {
if let Some(path_str) = path.to_str() {
if path_str.ends_with("library.o") {
if let Some(inital_bv) = session.load(path_str) {
let mut functions = inital_bv
.functions()
.iter()
.map(|f| cached_function_guid(&f, &f.low_level_il().unwrap()))
.collect::<Vec<_>>();
functions.sort_by_key(|guid| guid.guid);
insta::assert_debug_snapshot!(functions);
}
}
}
let view = session.load(&path).expect("Failed to load view");
let mut functions = view
.functions()
.iter()
.map(|f| cached_function_guid(&f, &f.low_level_il().unwrap()))
.collect::<Vec<_>>();
functions.sort_by_key(|guid| guid.guid);
let snapshot_name =
format!("snapshot_{}", path.file_stem().unwrap().to_string_lossy());
insta::assert_debug_snapshot!(snapshot_name, functions);
}
}
}
8 changes: 6 additions & 2 deletions plugins/warp/src/plugin/load.rs
Original file line number Diff line number Diff line change
@@ -10,8 +10,12 @@ impl Command for LoadSignatureFile {
return;
};

let Some(file) =
binaryninja::interaction::get_open_filename_input("Load Signature File", "*.sbin")
// NOTE: Because we only can consume signatures from a specific directory, we don't need to use the interaction API.
// If we did need to load signature files from a project than this would need to change.
let Some(file) = rfd::FileDialog::new()
.add_filter("Signature Files", &["sbin"])
.set_file_name(format!("{}.sbin", view.file().filename()))
.pick_file()
else {
return;
};
11 changes: 7 additions & 4 deletions plugins/warp/src/plugin/types.rs
Original file line number Diff line number Diff line change
@@ -7,10 +7,13 @@ pub struct LoadTypes;

impl Command for LoadTypes {
fn action(&self, view: &BinaryView) {
let Some(file) = binaryninja::interaction::get_open_filename_input(
"Apply Signature File Types",
"*.sbin",
) else {
// NOTE: Because we only can consume signatures from a specific directory, we don't need to use the interaction API.
// If we did need to load signature files from a project than this would need to change.
let Some(file) = rfd::FileDialog::new()
.add_filter("Signature Files", &["sbin"])
.set_file_name(format!("{}.sbin", view.file().filename()))
.pick_file()
else {
return;
};

Loading