Skip to content

Commit

Permalink
lldb/ObjectFile,Disassembler: read some state from the executable
Browse files Browse the repository at this point in the history
Add support to inspect the ELF headers for RISCV targets to determine if
RVC or RVE are enabled and the floating point support to enable.  As per
the RISCV specification, d implies f, q implies d implies f, which gives
us the cascading effect that is used to enable the features when setting
up the disassembler.  With this change, it is now possible to attach the
debugger to a remote process and be able to disassemble the instruction
stream.

~~~
$ bin/lldb tmp/reduced
(lldb) target create "reduced"
Current executable set to '/tmp/reduced' (riscv64).
(lldb) gdb-remote localhost:1234
(lldb) Process 5737 stopped
* thread #1, name = 'reduced', stop reason = signal SIGTRAP
    frame #0: 0x0000003ff7fe1b20
->  0x3ff7fe1b20: mv     a0, sp
    0x3ff7fe1b22: jal    1936
    0x3ff7fe1b26: mv     s0, a0
    0x3ff7fe1b28: auipc  a0, 27
~~~
  • Loading branch information
compnerd committed Mar 10, 2022
1 parent 1f45a10 commit c604207
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
11 changes: 11 additions & 0 deletions lldb/include/lldb/Utility/ArchSpec.h
Expand Up @@ -92,6 +92,17 @@ class ArchSpec {
eARM_abi_hard_float = 0x00000400
};

enum RISCVeflags {
eRISCV_rvc = 0x00000001, /// RVC, +c
eRISCV_float_abi_soft = 0x00000000, /// soft float
eRISCV_float_abi_single = 0x00000002, /// single precision floating point, +f
eRISCV_float_abi_double = 0x00000004, /// double precision floating point, +d
eRISCV_float_abi_quad = 0x00000006, /// quad precision floating point, +q
eRISCV_float_abi_mask = 0x00000006,
eRISCV_rve = 0x00000008, /// RVE, +e
eRISCV_tso = 0x00000010, /// RVTSO (total store ordering)
};

enum RISCVSubType {
eRISCVSubType_unknown,
eRISCVSubType_riscv32,
Expand Down
18 changes: 18 additions & 0 deletions lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
Expand Up @@ -1187,6 +1187,24 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
cpu = "apple-latest";
}

if (triple.isRISCV()) {
uint32_t arch_flags = arch.GetFlags();
if (arch_flags & ArchSpec::eRISCV_rvc)
features_str += "+c,";
if (arch_flags & ArchSpec::eRISCV_rve)
features_str += "+e,";
if ((arch_flags & ArchSpec::eRISCV_float_abi_single) ==
ArchSpec::eRISCV_float_abi_single)
features_str += "+f,";
if ((arch_flags & ArchSpec::eRISCV_float_abi_double) ==
ArchSpec::eRISCV_float_abi_double)
features_str += "+f,+d,";
if ((arch_flags & ArchSpec::eRISCV_float_abi_quad) ==
ArchSpec::eRISCV_float_abi_quad)
features_str += "+f,+d,+q,";
// FIXME: how do we detect features such as `+a`, `+m`?
}

// We use m_disasm_up.get() to tell whether we are valid or not, so if this
// isn't good for some reason, we won't be valid and FindPlugin will fail and
// we won't get used.
Expand Down
22 changes: 22 additions & 0 deletions lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Expand Up @@ -1364,6 +1364,28 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float);
}

if (arch_spec.GetMachine() == llvm::Triple::riscv32 ||
arch_spec.GetMachine() == llvm::Triple::riscv64) {
uint32_t flags = arch_spec.GetFlags();

if (header.e_flags & llvm::ELF::EF_RISCV_RVC)
flags |= ArchSpec::eRISCV_rvc;
if (header.e_flags & llvm::ELF::EF_RISCV_RVE)
flags |= ArchSpec::eRISCV_rve;

if ((header.e_flags & llvm::ELF::EF_RISCV_FLOAT_ABI_SINGLE) ==
llvm::ELF::EF_RISCV_FLOAT_ABI_SINGLE)
flags |= ArchSpec::eRISCV_float_abi_single;
else if ((header.e_flags & llvm::ELF::EF_RISCV_FLOAT_ABI_DOUBLE) ==
llvm::ELF::EF_RISCV_FLOAT_ABI_DOUBLE)
flags |= ArchSpec::eRISCV_float_abi_double;
else if ((header.e_flags & llvm::ELF::EF_RISCV_FLOAT_ABI_QUAD) ==
llvm::ELF::EF_RISCV_FLOAT_ABI_QUAD)
flags |= ArchSpec::eRISCV_float_abi_quad;

arch_spec.SetFlags(flags);
}

// If there are no section headers we are done.
if (header.e_shnum == 0)
return 0;
Expand Down

0 comments on commit c604207

Please sign in to comment.