Skip to content

Commit da38faf

Browse files
JDevlieghereGroverkss
authored andcommitted
[lldb] Support overriding the disassembly CPU & features (llvm#115382)
Add the ability to override the disassembly CPU and CPU features through a target setting (`target.disassembly-cpu` and `target.disassembly-features`) and a `disassemble` command option (`--cpu` and `--features`). This is especially relevant for architectures like RISC-V which relies heavily on CPU extensions. The majority of this patch is plumbing the options through. I recommend looking at DisassemblerLLVMC and the test for the observable change in behavior.
1 parent f328495 commit da38faf

34 files changed

+493
-152
lines changed

lldb/include/lldb/Core/Disassembler.h

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -409,35 +409,37 @@ class Disassembler : public std::enable_shared_from_this<Disassembler>,
409409
// flavor string gets set wrong. Instead, if you get a flavor string you
410410
// don't understand, use the default. Folks who care to check can use the
411411
// FlavorValidForArchSpec method on the disassembler they got back.
412-
static lldb::DisassemblerSP
413-
FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name);
412+
static lldb::DisassemblerSP FindPlugin(const ArchSpec &arch,
413+
const char *flavor, const char *cpu,
414+
const char *features,
415+
const char *plugin_name);
414416

415417
// This version will use the value in the Target settings if flavor is NULL;
416-
static lldb::DisassemblerSP FindPluginForTarget(const Target &target,
417-
const ArchSpec &arch,
418-
const char *flavor,
419-
const char *plugin_name);
418+
static lldb::DisassemblerSP
419+
FindPluginForTarget(const Target &target, const ArchSpec &arch,
420+
const char *flavor, const char *cpu, const char *features,
421+
const char *plugin_name);
420422

421423
struct Limit {
422424
enum { Bytes, Instructions } kind;
423425
lldb::addr_t value;
424426
};
425427

426-
static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch,
427-
const char *plugin_name,
428-
const char *flavor,
429-
Target &target,
430-
const AddressRange &disasm_range,
431-
bool force_live_memory = false);
428+
static lldb::DisassemblerSP
429+
DisassembleRange(const ArchSpec &arch, const char *plugin_name,
430+
const char *flavor, const char *cpu, const char *features,
431+
Target &target, const AddressRange &disasm_range,
432+
bool force_live_memory = false);
432433

433434
static lldb::DisassemblerSP
434435
DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
435-
const char *flavor, const Address &start, const void *bytes,
436-
size_t length, uint32_t max_num_instructions,
437-
bool data_from_file);
436+
const char *flavor, const char *cpu, const char *features,
437+
const Address &start, const void *bytes, size_t length,
438+
uint32_t max_num_instructions, bool data_from_file);
438439

439440
static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
440441
const char *plugin_name, const char *flavor,
442+
const char *cpu, const char *features,
441443
const ExecutionContext &exe_ctx, const Address &start,
442444
Limit limit, bool mixed_source_and_assembly,
443445
uint32_t num_mixed_context_lines, uint32_t options,

lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = {
312312
{ lldb::eArgTypeRemotePath, "remote-path", lldb::CompletionType::eRemoteDiskFileCompletion, {}, { nullptr, false }, "A path on the system managed by the current platform." },
313313
{ lldb::eArgTypeRemoteFilename, "remote-filename", lldb::CompletionType::eRemoteDiskFileCompletion, {}, { nullptr, false }, "A file on the system managed by the current platform." },
314314
{ lldb::eArgTypeModule, "module", lldb::CompletionType::eModuleCompletion, {}, { nullptr, false }, "The name of a module loaded into the current target." },
315+
{ lldb::eArgTypeCPUName, "cpu-name", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The name of a CPU." },
316+
{ lldb::eArgTypeCPUFeatures, "cpu-features", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The CPU feature string." },
315317
// clang-format on
316318
};
317319

lldb/include/lldb/Target/Target.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ class TargetProperties : public Properties {
119119

120120
const char *GetDisassemblyFlavor() const;
121121

122+
const char *GetDisassemblyCPU() const;
123+
124+
const char *GetDisassemblyFeatures() const;
125+
122126
InlineStrategy GetInlineStrategy() const;
123127

124128
RealpathPrefixes GetSourceRealpathPrefixes() const;

lldb/include/lldb/lldb-enumerations.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,8 @@ enum CommandArgumentType {
655655
eArgTypeRemotePath,
656656
eArgTypeRemoteFilename,
657657
eArgTypeModule,
658+
eArgTypeCPUName,
659+
eArgTypeCPUFeatures,
658660
eArgTypeLastArg // Always keep this entry as the last entry in this
659661
// enumeration!!
660662
};

lldb/include/lldb/lldb-private-interfaces.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ typedef lldb::ABISP (*ABICreateInstance)(lldb::ProcessSP process_sp,
2929
const ArchSpec &arch);
3030
typedef std::unique_ptr<Architecture> (*ArchitectureCreateInstance)(
3131
const ArchSpec &arch);
32-
typedef lldb::DisassemblerSP (*DisassemblerCreateInstance)(const ArchSpec &arch,
33-
const char *flavor);
32+
typedef lldb::DisassemblerSP (*DisassemblerCreateInstance)(
33+
const ArchSpec &arch, const char *flavor, const char *cpu,
34+
const char *features);
3435
typedef DynamicLoader *(*DynamicLoaderCreateInstance)(Process *process,
3536
bool force);
3637
typedef lldb::JITLoaderSP (*JITLoaderCreateInstance)(Process *process,

lldb/source/API/SBFunction.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ SBInstructionList SBFunction::GetInstructions(SBTarget target,
125125
lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
126126
const bool force_live_memory = true;
127127
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
128-
module_sp->GetArchitecture(), nullptr, flavor, *target_sp,
129-
m_opaque_ptr->GetAddressRange(), force_live_memory));
128+
module_sp->GetArchitecture(), nullptr, flavor,
129+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
130+
*target_sp, m_opaque_ptr->GetAddressRange(), force_live_memory));
130131
}
131132
}
132133
return sb_instructions;

lldb/source/API/SBSymbol.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,9 @@ SBInstructionList SBSymbol::GetInstructions(SBTarget target,
126126
AddressRange symbol_range(symbol_addr, m_opaque_ptr->GetByteSize());
127127
const bool force_live_memory = true;
128128
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
129-
module_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
130-
symbol_range, force_live_memory));
129+
module_sp->GetArchitecture(), nullptr, flavor_string,
130+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
131+
*target_sp, symbol_range, force_live_memory));
131132
}
132133
}
133134
}

lldb/source/API/SBTarget.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,7 +2013,8 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr,
20132013
error, force_live_memory, &load_addr);
20142014
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
20152015
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
2016-
target_sp->GetArchitecture(), nullptr, flavor_string, *addr_ptr,
2016+
target_sp->GetArchitecture(), nullptr, target_sp->GetDisassemblyCPU(),
2017+
target_sp->GetDisassemblyFeatures(), flavor_string, *addr_ptr,
20172018
data.GetBytes(), bytes_read, count, data_from_file));
20182019
}
20192020
}
@@ -2038,8 +2039,9 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress start_addr,
20382039
AddressRange range(start_load_addr, size);
20392040
const bool force_live_memory = true;
20402041
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
2041-
target_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
2042-
range, force_live_memory));
2042+
target_sp->GetArchitecture(), nullptr, flavor_string,
2043+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
2044+
*target_sp, range, force_live_memory));
20432045
}
20442046
}
20452047
return sb_instructions;
@@ -2071,8 +2073,9 @@ SBTarget::GetInstructionsWithFlavor(lldb::SBAddress base_addr,
20712073
const bool data_from_file = true;
20722074

20732075
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
2074-
target_sp->GetArchitecture(), nullptr, flavor_string, addr, buf, size,
2075-
UINT32_MAX, data_from_file));
2076+
target_sp->GetArchitecture(), nullptr, flavor_string,
2077+
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
2078+
addr, buf, size, UINT32_MAX, data_from_file));
20762079
}
20772080

20782081
return sb_instructions;

lldb/source/Commands/CommandObjectDisassemble.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
120120
break;
121121
}
122122

123+
case 'X':
124+
cpu_string = std::string(option_arg);
125+
break;
126+
127+
case 'Y':
128+
features_string = std::string(option_arg);
129+
break;
130+
123131
case 'r':
124132
raw = true;
125133
break;
@@ -176,20 +184,27 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
176184
Target *target =
177185
execution_context ? execution_context->GetTargetPtr() : nullptr;
178186

179-
// This is a hack till we get the ability to specify features based on
180-
// architecture. For now GetDisassemblyFlavor is really only valid for x86
181-
// (and for the llvm assembler plugin, but I'm papering over that since that
182-
// is the only disassembler plugin we have...
183187
if (target) {
188+
// This is a hack till we get the ability to specify features based on
189+
// architecture. For now GetDisassemblyFlavor is really only valid for x86
190+
// (and for the llvm assembler plugin, but I'm papering over that since that
191+
// is the only disassembler plugin we have...
184192
if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
185193
target->GetArchitecture().GetTriple().getArch() ==
186194
llvm::Triple::x86_64) {
187195
flavor_string.assign(target->GetDisassemblyFlavor());
188-
} else
196+
} else {
189197
flavor_string.assign("default");
190-
191-
} else
198+
}
199+
if (const char *cpu = target->GetDisassemblyCPU())
200+
cpu_string.assign(cpu);
201+
if (const char *features = target->GetDisassemblyFeatures())
202+
features_string.assign(features);
203+
} else {
192204
flavor_string.assign("default");
205+
cpu_string.assign("default");
206+
features_string.assign("default");
207+
}
193208

194209
arch.Clear();
195210
some_location_specified = false;
@@ -453,9 +468,11 @@ void CommandObjectDisassemble::DoExecute(Args &command,
453468

454469
const char *plugin_name = m_options.GetPluginName();
455470
const char *flavor_string = m_options.GetFlavorString();
471+
const char *cpu_string = m_options.GetCPUString();
472+
const char *features_string = m_options.GetFeaturesString();
456473

457-
DisassemblerSP disassembler =
458-
Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
474+
DisassemblerSP disassembler = Disassembler::FindPlugin(
475+
m_options.arch, flavor_string, cpu_string, features_string, plugin_name);
459476

460477
if (!disassembler) {
461478
if (plugin_name) {
@@ -524,7 +541,8 @@ void CommandObjectDisassemble::DoExecute(Args &command,
524541
}
525542
if (Disassembler::Disassemble(
526543
GetDebugger(), m_options.arch, plugin_name, flavor_string,
527-
m_exe_ctx, cur_range.GetBaseAddress(), limit, m_options.show_mixed,
544+
cpu_string, features_string, m_exe_ctx, cur_range.GetBaseAddress(),
545+
limit, m_options.show_mixed,
528546
m_options.show_mixed ? m_options.num_lines_context : 0, options,
529547
result.GetOutputStream())) {
530548
result.SetStatus(eReturnStatusSuccessFinishResult);

lldb/source/Commands/CommandObjectDisassemble.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ class CommandObjectDisassemble : public CommandObjectParsed {
4242
return flavor_string.c_str();
4343
}
4444

45+
const char *GetCPUString() {
46+
if (cpu_string.empty() || cpu_string == "default")
47+
return nullptr;
48+
return cpu_string.c_str();
49+
}
50+
51+
const char *GetFeaturesString() {
52+
if (features_string.empty() || features_string == "default")
53+
return nullptr;
54+
return features_string.c_str();
55+
}
56+
4557
Status OptionParsingFinished(ExecutionContext *execution_context) override;
4658

4759
bool show_mixed; // Show mixed source/assembly
@@ -58,6 +70,8 @@ class CommandObjectDisassemble : public CommandObjectParsed {
5870
bool frame_line = false;
5971
std::string plugin_name;
6072
std::string flavor_string;
73+
std::string cpu_string;
74+
std::string features_string;
6175
ArchSpec arch;
6276
bool some_location_specified = false; // If no location was specified, we'll
6377
// select "at_pc". This should be set

0 commit comments

Comments
 (0)