Skip to content

Commit 806faed

Browse files
committed
[RISCV-LLDB] RISCV feature attribute support and allows overriding additional(default) feature
Parse ELF attributes to automatically set disassembler features. llvm-objdump calls ELFObjectFile::getFeatures, then turns that into a cstr to pass to createMCSubtargetInfo. The lldb disassembler builds features for various architectures manually and adds in the value from the command line. If this is empty, it uses the default. then it turns that into a cstr and passes it to createMCSubtargetInfo. For Hexagon and RISC-V, parse the attributes, set up features, add anything else needed. If this is empty, pick the default. Then turn into a cstr and pass to createMCSubtargetInfo (via MCDisasmInstance::Create). This patch adds RISCV feature attribute support and allows overriding additional(default) feature.
1 parent 89abca4 commit 806faed

File tree

8 files changed

+134
-3
lines changed

8 files changed

+134
-3
lines changed

lldb/include/lldb/Utility/ArchSpec.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,15 @@ class ArchSpec {
537537

538538
void SetFlags(const std::string &elf_abi);
539539

540+
// Sets the target specific disassembly feature string
541+
// for ELF disassembly.
542+
void SetAdditionalDisassemblyFeatureStr(llvm::StringRef additional_features);
543+
544+
// Get the current target disassembly feature string.
545+
llvm::StringRef GetAdditionalDisassemblyFeatureStr() const {
546+
return llvm::StringRef(m_additional_disassembly_feature_str);
547+
}
548+
540549
protected:
541550
void UpdateCore();
542551

@@ -548,6 +557,9 @@ class ArchSpec {
548557
// these are application specific extensions like micromips, mips16 etc.
549558
uint32_t m_flags = 0;
550559

560+
// Holds the additional disassembly feature string.
561+
std::string m_additional_disassembly_feature_str;
562+
551563
// Called when m_def or m_entry are changed. Fills in all remaining members
552564
// with default values.
553565
void CoreUpdated(bool update_triple);

lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,37 @@ bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated(
14361436
return InstrDesc.isAuthenticated() || IsBrkC47x;
14371437
}
14381438

1439+
void DisassemblerLLVMC::UpdateFeatureString(llvm::StringRef additional_features,
1440+
std::string &features) {
1441+
// Allow users to override default additional features.
1442+
size_t start = 0, end;
1443+
while (!additional_features.empty() && start < additional_features.size()) {
1444+
end = additional_features.find(',', start);
1445+
if (end == llvm::StringRef::npos) {
1446+
end = additional_features.size();
1447+
}
1448+
llvm::StringRef flag =
1449+
additional_features.substr(start, end - start).trim();
1450+
if (!flag.empty()) {
1451+
if (flag.starts_with('+')) {
1452+
std::string dissable_flag = "-" + flag.substr(1).str();
1453+
if (features.find(dissable_flag) == std::string::npos) {
1454+
if (flag.back() != ',') {
1455+
features = ',' + features;
1456+
}
1457+
features = flag.str() + features;
1458+
}
1459+
} else {
1460+
if (flag.back() != ',') {
1461+
features = ',' + features;
1462+
}
1463+
features = flag.str() + features;
1464+
}
1465+
}
1466+
start = end + 1;
1467+
}
1468+
}
1469+
14391470
DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
14401471
const char *flavor_string,
14411472
const char *cpu_string,
@@ -1583,6 +1614,15 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
15831614
features_str += "+a,+m,";
15841615
}
15851616

1617+
const char *additional_features =
1618+
arch.GetAdditionalDisassemblyFeatureStr().data();
1619+
// Prepend the additional_features if it's not already in the features_str to
1620+
// avoid duplicates.
1621+
if (additional_features &&
1622+
features_str.find(additional_features) == std::string::npos) {
1623+
UpdateFeatureString(additional_features, features_str);
1624+
}
1625+
15861626
// We use m_disasm_up.get() to tell whether we are valid or not, so if this
15871627
// isn't good for some reason, we won't be valid and FindPlugin will fail and
15881628
// we won't get used.
@@ -1595,9 +1635,8 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
15951635
// thumb instruction disassembler.
15961636
if (llvm_arch == llvm::Triple::arm) {
15971637
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
1598-
m_alternate_disasm_up =
1599-
MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(),
1600-
flavor, *this);
1638+
m_alternate_disasm_up = MCDisasmInstance::Create(
1639+
thumb_triple.c_str(), "", features_str.c_str(), flavor, *this);
16011640
if (!m_alternate_disasm_up)
16021641
m_disasm_up.reset();
16031642

lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
class InstructionLLVMC;
2222

2323
class DisassemblerLLVMC : public lldb_private::Disassembler {
24+
private:
25+
void UpdateFeatureString(llvm::StringRef additional_features,
26+
std::string &features);
27+
2428
public:
2529
DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor,
2630
const char *cpu, const char *features);

lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/Support/MathExtras.h"
4646
#include "llvm/Support/MemoryBuffer.h"
4747
#include "llvm/Support/MipsABIFlags.h"
48+
#include "llvm/Support/RISCVAttributes.h"
4849

4950
#define CASE_AND_STREAM(s, def, width) \
5051
case def: \
@@ -1284,6 +1285,44 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
12841285
return error;
12851286
}
12861287

1288+
void ObjectFileELF::ParseRISCVAttributes(DataExtractor &data, uint64_t length,
1289+
ArchSpec &arch_spec) {
1290+
lldb::offset_t Offset = 0;
1291+
1292+
uint8_t FormatVersion = data.GetU8(&Offset);
1293+
if (FormatVersion != llvm::ELFAttrs::Format_Version)
1294+
return;
1295+
1296+
Offset = Offset + sizeof(uint32_t); // Section Length
1297+
llvm::StringRef VendorName = data.GetCStr(&Offset);
1298+
1299+
if (VendorName != "riscv")
1300+
return;
1301+
1302+
llvm::StringRef attr = "";
1303+
1304+
while (Offset < length) {
1305+
uint8_t Tag = data.GetU8(&Offset);
1306+
uint32_t Size = data.GetU32(&Offset);
1307+
1308+
if (Tag != llvm::ELFAttrs::File || Size == 0)
1309+
continue;
1310+
1311+
while (Offset < length) {
1312+
uint64_t Tag = data.GetULEB128(&Offset);
1313+
if (Tag == llvm::RISCVAttrs::ARCH) {
1314+
attr = data.GetCStr(&Offset);
1315+
break;
1316+
} else {
1317+
data.GetULEB128(&Offset);
1318+
}
1319+
}
1320+
}
1321+
if (!attr.empty() && attr.contains("xqci")) {
1322+
arch_spec.SetAdditionalDisassemblyFeatureStr("+xqci,");
1323+
}
1324+
}
1325+
12871326
void ObjectFileELF::ParseARMAttributes(DataExtractor &data, uint64_t length,
12881327
ArchSpec &arch_spec) {
12891328
lldb::offset_t Offset = 0;
@@ -1569,6 +1608,16 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
15691608
if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 &&
15701609
data.SetData(object_data, sheader.sh_offset, section_size) == section_size)
15711610
ParseARMAttributes(data, section_size, arch_spec);
1611+
} else if (arch_spec.GetMachine() == llvm::Triple::riscv32 ||
1612+
arch_spec.GetMachine() == llvm::Triple::riscv64) {
1613+
DataExtractor data;
1614+
if (sheader.sh_type == SHT_RISCV_ATTRIBUTES && section_size != 0 &&
1615+
(data.SetData(object_data, sheader.sh_offset, section_size) ==
1616+
section_size) &&
1617+
!arch_spec.GetAdditionalDisassemblyFeatureStr().contains(
1618+
"xqci")) {
1619+
ParseRISCVAttributes(data, section_size, arch_spec);
1620+
}
15721621
}
15731622

15741623
if (name == g_sect_name_gnu_debuglink) {

lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ class ObjectFileELF : public lldb_private::ObjectFile {
269269

270270
lldb::SectionType GetSectionType(const ELFSectionHeaderInfo &H) const;
271271

272+
// Parse and ELF header section to detect the RISCV attributes.
273+
// This function traverses the section headers of the ELF object file to
274+
// verify the presence of the Xqci feature extension in the RISCV attributes.
275+
// If the extension is found, it updates the '+xqci' feature string.
276+
static void ParseRISCVAttributes(lldb_private::DataExtractor &data,
277+
uint64_t length,
278+
lldb_private::ArchSpec &arch_spec);
279+
272280
static void ParseARMAttributes(lldb_private::DataExtractor &data,
273281
uint64_t length,
274282
lldb_private::ArchSpec &arch_spec);

lldb/source/Utility/ArchSpec.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,14 @@ void ArchSpec::SetFlags(const std::string &elf_abi) {
617617
SetFlags(flag);
618618
}
619619

620+
void ArchSpec::SetAdditionalDisassemblyFeatureStr(
621+
llvm::StringRef additional_features) {
622+
if (m_additional_disassembly_feature_str.find(additional_features.str()) ==
623+
std::string::npos) {
624+
m_additional_disassembly_feature_str += additional_features.str();
625+
}
626+
}
627+
620628
std::string ArchSpec::GetClangTargetCPU() const {
621629
std::string cpu;
622630
if (IsMIPS()) {
42.5 KB
Binary file not shown.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# REQUIRES: target=riscv32-{{.*}}
2+
3+
# RUN: %lldb -b -o "disassemble -b -n main" %p/Inputs/riscv_xqci.out | FileCheck %s
4+
5+
# CHECK: 1f 05 58 00 00 00 qc.e.li a0, 0x58
6+
# CHECK: 16 15 qc.extu a0, a0, 0x6, 0x0
7+
8+
# RUN: %lldb -b -o "disassemble -b -n main -Y -xqci,+c" %p/Inputs/riscv_xqci.out | FileCheck --check-prefix=CHECK-NOXQCI %s
9+
10+
# CHECK-NOXQCI: <invalid>
11+

0 commit comments

Comments
 (0)