[BPF] Mark FI_ri as isPseudo to avoid assertion during disassembly
authorEduard Zingerman <eddyz87@gmail.com>
Wed, 11 May 2022 00:04:58 +0000 (17:04 -0700)
committerYonghong Song <yhs@fb.com>
Wed, 11 May 2022 00:07:52 +0000 (17:07 -0700)
commit8a63326150ee7e3e67e019ac8fe90fe420cd5162
tree15bc7a566ed03f449d75c5bac2de8193b1d5bd74
parentde67bc8edb816a0a294f75d166efd745e5c6a465
[BPF] Mark FI_ri as isPseudo to avoid assertion during disassembly

When a specific sequence of bytes is present in the file during
disassembly the disassembler fails with the following assertion:

  ...
       0: 18 20 00 00 00 00 00 00 lea
  ... Assertion `idx < size()' failed.
  ...
  llvm::SmallVectorTemplateCommon<...>::operator[](...) ...
  llvm::MCInst::getOperand(unsigned int) ...
  llvm::BPFInstPrinter::printOperand(...) ...
  llvm::BPFInstPrinter::printInstruction() ...
  llvm::BPFInstPrinter::printInst(...) ...
  ...

The byte sequence causing the error is (little endian):

18 20 00 00  00 00 00 00  00 00 00 00  00 00 00 00

The issue could be reproduced using the program bellow:

  test.ir:

  @G = constant
         [16 x i8]
         [i8 u0x18, i8 u0x20, i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00,
          i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00, i8 u0x00],
         section "foo", align 8

Compiled and disassembled as follows:

  cat test.ir | llc -march=bpfel -filetype=obj -o - \
              | llvm-objdump --arch=bpfel --section=foo -d -

This byte sequence corresponds to FI_ri instruction declared in the
BPFInstrInfo.td as follows:

  def FI_ri
      : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
                   (outs GPR:$dst),
                   (ins MEMri:$addr),
                   "lea\t$dst, $addr",
                   [(set i64:$dst, FIri:$addr)]> {
    // This is a tentative instruction, and will be replaced
    // with MOV_rr and ADD_ri in PEI phase
    let Inst{51-48} = 0;
    let Inst{55-52} = 2;
    let Inst{47-32} = 0;
    let Inst{31-0} = 0;
    let BPFClass = BPF_LD;
  }

Notes:
- First byte (opcode) is formed as follows:
  - BPF_IMM.Value is 0x00
  - BPF_DW.Value  is 0x18
  - BPF_LD        is 0x00
- Second byte (registers) is formed as follows:
  - let Inst{55-52} = 2;
  - let Inst{51-48} = 0;

The FI_ri instruction is always replaced by MOV_rr ADD_ri instructions
pair in the BPFRegisterInfo::eliminateFrameIndex method. Thus, this
instruction should be invisible to disassembler. This patch achieves
this by adding "isPseudo" flag for this instruction.

The bug was found by decompiling of one of the BPF tests from Linux
kernel (llvm-objdump -D tools/testing/selftests/bpf/bpf_iter_sockmap.o)

Differential Revision: https://reviews.llvm.org/D125185
llvm/lib/Target/BPF/BPFInstrInfo.td