mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 22:36:48 +00:00
* feat(kprobe): Add basic kprobe support for x86_64 * feat: add ebpf support (#912) - 实现bpf()一部分命令,包括几种基本map,相关的helper函数 - 实现部分perf相关的数据结构 - 暂时为文件实现简单mmap - 实现一个使用kprobe统计syscall 调用次数的ebpf程序 对eBPF支持程度(基本): - 简单的eBPF程序(没有指定特殊的Map) - 使用内核已经实现的Map的eBPF程序 - 可以和kprobe配合使用 - 内核Map相关的接口定义已经实现,添加新的Map较为简单 不支持的功能: - 区分不同的eBPF程序类型(Network/Cgroup)并限定可调用的helper函数集 - 与内核其它跟踪机制配合(tracepoint) - 其它helper和Map todo - [ ] 修改mmap,需要讨论,因为这个和块缓存层相关 - [x] 添加文档 - [x] 修复可能的错误 - [x] 增加rbpf版本信息 * feat: add /sys/devices/system/cpu/possible file * feat: add /sys/devices/system/cpu/online
378 lines
6.8 KiB
Rust
378 lines
6.8 KiB
Rust
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
// Copyright 2017 Jan-Erik Rediger <badboy@archlinux.us>
|
|
//
|
|
// Adopted from tests in `tests/assembler.rs`
|
|
|
|
extern crate rbpf;
|
|
mod common;
|
|
|
|
use rbpf::{assembler::assemble, disassembler::to_insn_vec};
|
|
|
|
// Using a macro to keep actual line numbers in failure output
|
|
macro_rules! disasm {
|
|
($src:expr) => {{
|
|
let src = $src;
|
|
let asm = assemble(src).expect("Can't assemble from string");
|
|
let insn = to_insn_vec(&asm);
|
|
let reasm = insn
|
|
.into_iter()
|
|
.map(|ins| ins.desc)
|
|
.collect::<Vec<_>>()
|
|
.join("\n");
|
|
|
|
assert_eq!(src, reasm);
|
|
}};
|
|
}
|
|
|
|
#[test]
|
|
fn test_empty() {
|
|
disasm!("");
|
|
}
|
|
|
|
// Example for InstructionType::NoOperand.
|
|
#[test]
|
|
fn test_exit() {
|
|
disasm!("exit");
|
|
}
|
|
|
|
// Example for InstructionType::AluBinary.
|
|
#[test]
|
|
fn test_add64() {
|
|
disasm!("add64 r1, r3");
|
|
disasm!("add64 r1, 0x5");
|
|
}
|
|
|
|
// Example for InstructionType::AluUnary.
|
|
#[test]
|
|
fn test_neg64() {
|
|
disasm!("neg64 r1");
|
|
}
|
|
|
|
// Example for InstructionType::LoadReg.
|
|
#[test]
|
|
fn test_ldxw() {
|
|
disasm!("ldxw r1, [r2+0x5]");
|
|
}
|
|
|
|
// Example for InstructionType::StoreImm.
|
|
#[test]
|
|
fn test_stw() {
|
|
disasm!("stw [r2+0x5], 0x7");
|
|
}
|
|
|
|
// Example for InstructionType::StoreReg.
|
|
#[test]
|
|
fn test_stxw() {
|
|
disasm!("stxw [r2+0x5], r8");
|
|
}
|
|
|
|
// Example for InstructionType::JumpUnconditional.
|
|
#[test]
|
|
fn test_ja() {
|
|
disasm!("ja +0x8");
|
|
}
|
|
|
|
// Example for InstructionType::JumpConditional.
|
|
#[test]
|
|
fn test_jeq() {
|
|
disasm!("jeq r1, 0x4, +0x8");
|
|
disasm!("jeq r1, r3, +0x8");
|
|
}
|
|
|
|
// Example for InstructionType::Call.
|
|
#[test]
|
|
fn test_call() {
|
|
disasm!("call 0x3");
|
|
}
|
|
|
|
// Example for InstructionType::Endian.
|
|
#[test]
|
|
fn test_be32() {
|
|
disasm!("be32 r1");
|
|
}
|
|
|
|
// Example for InstructionType::LoadImm.
|
|
#[test]
|
|
fn test_lddw() {
|
|
disasm!("lddw r1, 0x1234abcd5678eeff");
|
|
disasm!("lddw r1, 0xff11ee22dd33cc44");
|
|
}
|
|
|
|
// Example for InstructionType::LoadAbs.
|
|
#[test]
|
|
fn test_ldabsw() {
|
|
disasm!("ldabsw 0x1");
|
|
}
|
|
|
|
// Example for InstructionType::LoadInd.
|
|
#[test]
|
|
fn test_ldindw() {
|
|
disasm!("ldindw r1, 0x2");
|
|
}
|
|
|
|
// Example for InstructionType::LoadReg.
|
|
#[test]
|
|
fn test_ldxdw() {
|
|
disasm!("ldxdw r1, [r2+0x3]");
|
|
}
|
|
|
|
// Example for InstructionType::StoreImm.
|
|
#[test]
|
|
fn test_sth() {
|
|
disasm!("sth [r1+0x2], 0x3");
|
|
}
|
|
|
|
// Example for InstructionType::StoreReg.
|
|
#[test]
|
|
fn test_stxh() {
|
|
disasm!("stxh [r1+0x2], r3");
|
|
}
|
|
|
|
// Test all supported AluBinary mnemonics.
|
|
#[test]
|
|
fn test_alu_binary() {
|
|
disasm!(
|
|
"add64 r1, r2
|
|
sub64 r1, r2
|
|
mul64 r1, r2
|
|
div64 r1, r2
|
|
or64 r1, r2
|
|
and64 r1, r2
|
|
lsh64 r1, r2
|
|
rsh64 r1, r2
|
|
mod64 r1, r2
|
|
xor64 r1, r2
|
|
mov64 r1, r2
|
|
arsh64 r1, r2"
|
|
);
|
|
|
|
disasm!(
|
|
"add64 r1, 0x2
|
|
sub64 r1, 0x2
|
|
mul64 r1, 0x2
|
|
div64 r1, 0x2
|
|
or64 r1, 0x2
|
|
and64 r1, 0x2
|
|
lsh64 r1, 0x2
|
|
rsh64 r1, 0x2
|
|
mod64 r1, 0x2
|
|
xor64 r1, 0x2
|
|
mov64 r1, 0x2
|
|
arsh64 r1, 0x2"
|
|
);
|
|
|
|
disasm!(
|
|
"add32 r1, r2
|
|
sub32 r1, r2
|
|
mul32 r1, r2
|
|
div32 r1, r2
|
|
or32 r1, r2
|
|
and32 r1, r2
|
|
lsh32 r1, r2
|
|
rsh32 r1, r2
|
|
mod32 r1, r2
|
|
xor32 r1, r2
|
|
mov32 r1, r2
|
|
arsh32 r1, r2"
|
|
);
|
|
|
|
disasm!(
|
|
"add32 r1, 0x2
|
|
sub32 r1, 0x2
|
|
mul32 r1, 0x2
|
|
div32 r1, 0x2
|
|
or32 r1, 0x2
|
|
and32 r1, 0x2
|
|
lsh32 r1, 0x2
|
|
rsh32 r1, 0x2
|
|
mod32 r1, 0x2
|
|
xor32 r1, 0x2
|
|
mov32 r1, 0x2
|
|
arsh32 r1, 0x2"
|
|
);
|
|
}
|
|
|
|
// Test all supported AluUnary mnemonics.
|
|
#[test]
|
|
fn test_alu_unary() {
|
|
disasm!(
|
|
"neg64 r1
|
|
neg32 r1"
|
|
);
|
|
}
|
|
|
|
// Test all supported LoadAbs mnemonics.
|
|
#[test]
|
|
fn test_load_abs() {
|
|
disasm!(
|
|
"ldabsw 0x1
|
|
ldabsh 0x1
|
|
ldabsb 0x1
|
|
ldabsdw 0x1"
|
|
);
|
|
}
|
|
|
|
// Test all supported LoadInd mnemonics.
|
|
#[test]
|
|
fn test_load_ind() {
|
|
disasm!(
|
|
"ldindw r1, 0x2
|
|
ldindh r1, 0x2
|
|
ldindb r1, 0x2
|
|
ldinddw r1, 0x2"
|
|
);
|
|
}
|
|
|
|
// Test all supported LoadReg mnemonics.
|
|
#[test]
|
|
fn test_load_reg() {
|
|
disasm!(
|
|
r"ldxw r1, [r2+0x3]
|
|
ldxh r1, [r2+0x3]
|
|
ldxb r1, [r2+0x3]
|
|
ldxdw r1, [r2+0x3]"
|
|
);
|
|
}
|
|
|
|
// Test all supported StoreImm mnemonics.
|
|
#[test]
|
|
fn test_store_imm() {
|
|
disasm!(
|
|
"stw [r1+0x2], 0x3
|
|
sth [r1+0x2], 0x3
|
|
stb [r1+0x2], 0x3
|
|
stdw [r1+0x2], 0x3"
|
|
);
|
|
}
|
|
|
|
// Test all supported StoreReg mnemonics.
|
|
#[test]
|
|
fn test_store_reg() {
|
|
disasm!(
|
|
"stxw [r1+0x2], r3
|
|
stxh [r1+0x2], r3
|
|
stxb [r1+0x2], r3
|
|
stxdw [r1+0x2], r3"
|
|
);
|
|
}
|
|
|
|
// Test all supported JumpConditional mnemonics.
|
|
#[test]
|
|
fn test_jump_conditional() {
|
|
disasm!(
|
|
"jeq r1, r2, +0x3
|
|
jgt r1, r2, +0x3
|
|
jge r1, r2, +0x3
|
|
jlt r1, r2, +0x3
|
|
jle r1, r2, +0x3
|
|
jset r1, r2, +0x3
|
|
jne r1, r2, +0x3
|
|
jsgt r1, r2, +0x3
|
|
jsge r1, r2, -0x3
|
|
jslt r1, r2, +0x3
|
|
jsle r1, r2, -0x3"
|
|
);
|
|
|
|
disasm!(
|
|
"jeq r1, 0x2, +0x3
|
|
jgt r1, 0x2, +0x3
|
|
jge r1, 0x2, +0x3
|
|
jlt r1, 0x2, +0x3
|
|
jle r1, 0x2, +0x3
|
|
jset r1, 0x2, +0x3
|
|
jne r1, 0x2, +0x3
|
|
jsgt r1, 0x2, +0x3
|
|
jsge r1, 0x2, -0x3
|
|
jslt r1, 0x2, +0x3
|
|
jsle r1, 0x2, -0x3"
|
|
);
|
|
|
|
disasm!(
|
|
"jeq32 r1, r2, +0x3
|
|
jgt32 r1, r2, +0x3
|
|
jge32 r1, r2, +0x3
|
|
jlt32 r1, r2, +0x3
|
|
jle32 r1, r2, +0x3
|
|
jset32 r1, r2, +0x3
|
|
jne32 r1, r2, +0x3
|
|
jsgt32 r1, r2, +0x3
|
|
jsge32 r1, r2, -0x3
|
|
jslt32 r1, r2, +0x3
|
|
jsle32 r1, r2, -0x3"
|
|
);
|
|
|
|
disasm!(
|
|
"jeq32 r1, 0x2, +0x3
|
|
jgt32 r1, 0x2, +0x3
|
|
jge32 r1, 0x2, +0x3
|
|
jlt32 r1, 0x2, +0x3
|
|
jle32 r1, 0x2, +0x3
|
|
jset32 r1, 0x2, +0x3
|
|
jne32 r1, 0x2, +0x3
|
|
jsgt32 r1, 0x2, +0x3
|
|
jsge32 r1, 0x2, -0x3
|
|
jslt32 r1, 0x2, +0x3
|
|
jsle32 r1, 0x2, -0x3"
|
|
);
|
|
}
|
|
|
|
// Test all supported Endian mnemonics.
|
|
#[test]
|
|
fn test_endian() {
|
|
disasm!(
|
|
"be16 r1
|
|
be32 r1
|
|
be64 r1
|
|
le16 r1
|
|
le32 r1
|
|
le64 r1"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_large_immediate() {
|
|
disasm!("add64 r1, 0x7fffffff");
|
|
disasm!("add64 r1, 0x7fffffff");
|
|
}
|
|
|
|
// Non-regression tests for overflow when trying to negate offset 0x8000i16.
|
|
#[test]
|
|
fn test_offset_overflow() {
|
|
let insns = [
|
|
0x62, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stw
|
|
0x6a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // sth
|
|
0x72, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stb
|
|
0x7a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stdw
|
|
0x61, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxw
|
|
0x69, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxh
|
|
0x71, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxb
|
|
0x79, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxdw
|
|
0x15, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq (imm)
|
|
0x1d, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq (reg)
|
|
0x16, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq32 (imm)
|
|
0x1e, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq32 (reg)
|
|
];
|
|
|
|
let expected_output = "stw [r1-0x8000], 0x1
|
|
sth [r1-0x8000], 0x1
|
|
stb [r1-0x8000], 0x1
|
|
stdw [r1-0x8000], 0x1
|
|
ldxw r1, [r0-0x8000]
|
|
ldxh r1, [r0-0x8000]
|
|
ldxb r1, [r0-0x8000]
|
|
ldxdw r1, [r0-0x8000]
|
|
jeq r1, 0x2, -0x8000
|
|
jeq r1, r2, -0x8000
|
|
jeq32 r1, 0x2, -0x8000
|
|
jeq32 r1, r2, -0x8000";
|
|
|
|
let prog = to_insn_vec(&insns);
|
|
let asm = prog
|
|
.into_iter()
|
|
.map(|ins| ins.desc)
|
|
.collect::<Vec<_>>()
|
|
.join("\n");
|
|
|
|
assert_eq!(asm, expected_output);
|
|
}
|