mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-04-24 03:00:42 -04:00
Fix disassembly of eBPF atomic instructions
eBPF ISA v3 introduced atomic instructions: https://www.kernel.org/doc/html/v6.0/bpf/instruction-set.html#atomic-operations These instructions are encoded using BPF_ATOMIC | BPF_W | BPF_STX and BPF_ATOMIC | BPF_DW | BPF_STX for 32-bit and 64-bit operations, with: BPF_ATOMIC = 0xc0 BPF_DW = 0x18 BPF_W = 0 BPF_STX = 0x03 While Ghidra's semantic section is constructed correctly (atomic add uses an addition ; atomic or uses or ; ...), the disassembly always displays STXXADDW and STXXADDDW. These mnemonics come from the deprecated name BPF_XADD = BPF_ATOMIC | BPF_ADD = 0xc0. Replace the confusing mnemonics with the ones used by binutils and documented in https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gas/doc/c-bpf.texi;h=003cb92a457985038a9abc1ffbf347f636eb0586;hb=2bc7af1ff7732451b6a7b09462a815c3284f9613#l745
This commit is contained in:
committed by
ghidorahrex
parent
105651b2b9
commit
ff6eb2213b
@@ -272,38 +272,38 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; }
|
||||
# BPF_ADD:
|
||||
|
||||
# BPF_STX | BPF_ATOMIC | BPF_W
|
||||
:STXXADDW [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) + src:4; }
|
||||
:AADD32 [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) + src:4; }
|
||||
|
||||
# BPF_STX | BPF_ATOMIC | BPF_DW
|
||||
:STXXADDDW [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) + src; }
|
||||
:AADD [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) + src; }
|
||||
|
||||
# BPF_OR:
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) | src:4; }
|
||||
:AOR32 [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) | src:4; }
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) | src; }
|
||||
:AOR [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) | src; }
|
||||
|
||||
# BPF_AND:
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) & src:4; }
|
||||
:AAND32 [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) & src:4; }
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) & src; }
|
||||
:AAND [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) & src; }
|
||||
|
||||
# BPF_XOR:
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) ^ src:4; }
|
||||
:AXOR32 [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) ^ src:4; }
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) ^ src; }
|
||||
:AXOR [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) ^ src; }
|
||||
|
||||
# BPF_ADD | BPF_FETCH -> src = atomic_fetch_add(dst + off, src):
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
:AFADD32 [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
local tmp:4 = *:4 (dst + off);
|
||||
*:4 (dst + off) = *:4 (dst + off) + src:4;
|
||||
src = zext(tmp);
|
||||
}
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
:AFADD [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
local tmp:8 = *:8 (dst + off);
|
||||
*:8 (dst + off) = *:8 (dst + off) + src;
|
||||
src = tmp;
|
||||
@@ -311,13 +311,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; }
|
||||
|
||||
# BPF_OR | BPF_FETCH -> src = atomic_fetch_or(dst + off, src):
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
:AFOR32 [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
local tmp:4 = *:4 (dst + off);
|
||||
*:4 (dst + off) = *:4 (dst + off) | src:4;
|
||||
src = zext(tmp);
|
||||
}
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
:AFOR [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
local tmp:8 = *:8 (dst + off);
|
||||
*:8 (dst + off) = *:8 (dst + off) | src;
|
||||
src = tmp;
|
||||
@@ -325,13 +325,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; }
|
||||
|
||||
# BPF_AND | BPF_FETCH -> src = atomic_fetch_and(dst + off, src):
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
:AFAND32 [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
local tmp:4 = *:4 (dst + off);
|
||||
*:4 (dst + off) = *:4 (dst + off) & src:4;
|
||||
src = zext(tmp);
|
||||
}
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
:AFAND [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
local tmp:8 = *:8 (dst + off);
|
||||
*:8 (dst + off) = *:8 (dst + off) & src;
|
||||
src = tmp;
|
||||
@@ -339,13 +339,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; }
|
||||
|
||||
# BPF_XOR | BPF_FETCH -> src = atomic_fetch_xor(dst + off, src):
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
:AFXOR32 [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
local tmp:4 = *:4 (dst + off);
|
||||
*:4 (dst + off) = *:4 (dst + off) ^ src:4;
|
||||
src = zext(tmp);
|
||||
}
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
:AFXOR [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
local tmp:8 = *:8 (dst + off);
|
||||
*:8 (dst + off) = *:8 (dst + off) ^ src;
|
||||
src = tmp;
|
||||
@@ -353,13 +353,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; }
|
||||
|
||||
# BPF_XCHG -> src_reg = atomic_xchg(dst + off, src):
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
:AXCHG32 [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
local tmp:4 = *:4 (dst + off);
|
||||
*:4 (dst + off) = src:4;
|
||||
src = zext(tmp);
|
||||
}
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
:AXCHG [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
local tmp:8 = *:8 (dst + off);
|
||||
*:8 (dst + off) = src;
|
||||
src = tmp;
|
||||
@@ -367,18 +367,18 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; }
|
||||
|
||||
# BPF_CMPXCHG -> R0 = atomic_cmpxchg(dst + off, R0, src):
|
||||
|
||||
:STXXADDW [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
:ACMP32 [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 {
|
||||
local tmp:4 = *:4 (dst + off);
|
||||
if (R0:4 == tmp) goto <equal>;
|
||||
R0 = zext(tmp);
|
||||
R0 = zext(tmp);
|
||||
<equal>
|
||||
*:4 (dst + off) = src:4;
|
||||
}
|
||||
|
||||
:STXXADDDW [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
:ACMP [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 {
|
||||
local tmp:8 = *:8 (dst + off);
|
||||
if (R0 == tmp) goto <equal>;
|
||||
R0 = tmp;
|
||||
R0 = tmp;
|
||||
<equal>
|
||||
*:8 (dst + off) = src;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user