Skip to content

Commit

Permalink
Modify assembler and disassembler
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasSte committed Oct 10, 2024
1 parent 13a2680 commit 415fc80
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 19 deletions.
7 changes: 6 additions & 1 deletion src/assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,11 @@ fn make_instruction_map(sbpf_version: SBPFVersion) -> HashMap<String, (Instructi

// Miscellaneous.
entry("ja", JumpUnconditional, ebpf::JA);
entry("syscall", Syscall, ebpf::CALL_IMM);
if sbpf_version == SBPFVersion::V1 {
entry("syscall", Syscall, ebpf::CALL_IMM);
} else {
entry("syscall", Syscall, ebpf::SYSCALL);
}
entry("call", CallImm, ebpf::CALL_IMM);
entry("callx", CallReg, ebpf::CALL_REG);
entry("lddw", LoadDwImm, ebpf::LD_DW_IMM);
Expand Down Expand Up @@ -450,6 +454,7 @@ pub fn assemble<C: ContextObject>(
0,
ebpf::hash_symbol_name(label.as_bytes()) as i32 as i64,
),
(Syscall, [Integer(imm)]) => insn(opc, 0, 0, 0, *imm),
(CallImm, [Label(label)]) => {
let label: &str = label;
let target_pc = *labels
Expand Down
15 changes: 4 additions & 11 deletions src/disassembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,7 @@ pub fn disassemble_instruction<C: ContextObject>(
ebpf::JSLE_IMM => { name = "jsle"; desc = jmp_imm_str(name, insn, cfg_nodes); },
ebpf::JSLE_REG => { name = "jsle"; desc = jmp_reg_str(name, insn, cfg_nodes); },
ebpf::CALL_IMM => {
let mut function_name = None;
if sbpf_version.static_syscalls() {
if insn.src != 0 {
function_name = Some(resolve_label(cfg_nodes, insn.imm as usize).to_string());
}
} else {
function_name = function_registry.lookup_by_key(insn.imm as u32).map(|(function_name, _)| String::from_utf8_lossy(function_name).to_string());
}
let function_name = function_registry.lookup_by_key(insn.imm as u32).map(|(function_name, _)| String::from_utf8_lossy(function_name).to_string());
let function_name = if let Some(function_name) = function_name {
name = "call";
function_name
Expand All @@ -284,9 +277,9 @@ pub fn disassemble_instruction<C: ContextObject>(
},
ebpf::CALL_REG => { name = "callx"; desc = format!("{} r{}", name, if sbpf_version.callx_uses_src_reg() { insn.src } else { insn.imm as u8 }); },
ebpf::EXIT
| ebpf::RETURN if !sbpf_version.static_syscalls() => { name = "exit"; desc = name.to_string(); },
ebpf::EXIT
| ebpf::RETURN if sbpf_version.static_syscalls() => { name = "return"; desc = name.to_string(); },
| ebpf::RETURN if !sbpf_version.static_syscalls() => { name = "exit"; desc = name.to_string(); },
ebpf::RETURN if sbpf_version.static_syscalls() => { name = "return"; desc = name.to_string(); },
ebpf::SYSCALL if sbpf_version.static_syscalls() => { desc = format!("syscall {}", insn.imm); },

_ => { name = "unknown"; desc = format!("{} opcode={:#x}", name, insn.opc); },
};
Expand Down
10 changes: 6 additions & 4 deletions src/ebpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@ pub const BPF_JSGT: u8 = 0x60;
pub const BPF_JSGE: u8 = 0x70;
/// BPF JMP operation code: syscall function call.
pub const BPF_CALL: u8 = 0x80;
/// BPF JMP operation code: return from program.
pub const BPF_EXIT: u8 = 0x90;
/// BPF JMP operation code: return from program (V1) or syscall (V2).
pub const BPF_EXIT_SYSCALL: u8 = 0x90;
/// BPF JMP operation code: jump if lower than.
pub const BPF_JLT: u8 = 0xa0;
/// BPF JMP operation code: jump if lower or equal.
Expand Down Expand Up @@ -481,9 +481,11 @@ pub const CALL_IMM: u8 = BPF_JMP | BPF_CALL;
/// BPF opcode: tail call.
pub const CALL_REG: u8 = BPF_JMP | BPF_X | BPF_CALL;
/// BPF opcode: `exit` /// `return r0`. /// Valid only for SBPFv1
pub const EXIT: u8 = BPF_JMP | BPF_EXIT;
pub const EXIT: u8 = BPF_JMP | BPF_EXIT_SYSCALL;
/// BPF opcode: `return` /// `return r0`. /// Valid only for SBPFv2
pub const RETURN: u8 = BPF_JMP | BPF_X | BPF_EXIT;
pub const RETURN: u8 = BPF_JMP | BPF_X | BPF_EXIT_SYSCALL;
/// BPF opcode: `syscall` /// `syscall imm`. /// Valid only for SBPFv2
pub const SYSCALL: u8 = BPF_JMP | BPF_EXIT_SYSCALL;

// Used in JIT
/// Mask to extract the operation class from an operation code.
Expand Down
2 changes: 1 addition & 1 deletion src/insn_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ impl<'i> Exit<'i> {

impl Instruction for Exit<'_> {
fn opt_code_byte(&self) -> u8 {
BPF_EXIT | BPF_JMP
BPF_EXIT_SYSCALL | BPF_JMP
}

fn get_insn_mut(&mut self) -> &mut Insn {
Expand Down
3 changes: 2 additions & 1 deletion src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,8 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> {

// Do not delegate the check to the verifier, since self.registered functions can be
// changed after the program has been verified.
ebpf::CALL_IMM => {
ebpf::CALL_IMM
| ebpf::SYSCALL if insn.opc == ebpf::CALL_IMM || self.executable.get_sbpf_version().static_syscalls() => {
let mut resolved = false;
let (external, internal) = if self.executable.get_sbpf_version().static_syscalls() {
(insn.src == 0, insn.src != 0)
Expand Down
3 changes: 2 additions & 1 deletion src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,8 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
ebpf::JSLT_REG => self.emit_conditional_branch_reg(0x8c, false, src, dst, target_pc),
ebpf::JSLE_IMM => self.emit_conditional_branch_imm(0x8e, false, insn.imm, dst, target_pc),
ebpf::JSLE_REG => self.emit_conditional_branch_reg(0x8e, false, src, dst, target_pc),
ebpf::CALL_IMM => {
ebpf::CALL_IMM | ebpf::SYSCALL
if insn.opc == ebpf::CALL_IMM || self.executable.get_sbpf_version().static_syscalls() => {
// For JIT, external functions MUST be registered at compile time.

let mut resolved = false;
Expand Down
13 changes: 13 additions & 0 deletions tests/assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ fn test_exit() {
);
}

#[test]
fn test_static_syscall() {
let config = Config {
enabled_sbpf_versions: SBPFVersion::V2..=SBPFVersion::V2,
..Config::default()
};

assert_eq!(
asm_with_config("syscall 3", config),
Ok(vec![insn(0, ebpf::SYSCALL, 0, 0, 0, 3)])
);
}

#[test]
fn test_return() {
let config = Config {
Expand Down
9 changes: 9 additions & 0 deletions tests/disassembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ fn test_return() {
disasm!("entrypoint:\n return\n", config);
}

#[test]
fn test_static_syscall() {
let config = Config {
enabled_sbpf_versions: SBPFVersion::V2..=SBPFVersion::V2,
..Config::default()
};
disasm!("entrypoint:\n syscall 5\n", config);
}

// Example for InstructionType::AluBinary.
#[test]
fn test_add64() {
Expand Down

0 comments on commit 415fc80

Please sign in to comment.