[Lldb-commits] [lldb] [lldb] Support overriding the disassembly CPU & features (PR #115382)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Nov 7 14:30:07 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Jonas Devlieghere (JDevlieghere)
<details>
<summary>Changes</summary>
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.
---
Patch is 49.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/115382.diff
30 Files Affected:
- (modified) lldb/include/lldb/Core/Disassembler.h (+17-15)
- (modified) lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h (+2)
- (modified) lldb/include/lldb/Target/Target.h (+4)
- (modified) lldb/include/lldb/lldb-enumerations.h (+2)
- (modified) lldb/include/lldb/lldb-private-interfaces.h (+3-2)
- (modified) lldb/source/API/SBFunction.cpp (+2-2)
- (modified) lldb/source/API/SBSymbol.cpp (+2-2)
- (modified) lldb/source/API/SBTarget.cpp (+7-6)
- (modified) lldb/source/Commands/CommandObjectDisassemble.cpp (+28-10)
- (modified) lldb/source/Commands/CommandObjectDisassemble.h (+14)
- (modified) lldb/source/Commands/Options.td (+4)
- (modified) lldb/source/Core/Disassembler.cpp (+25-17)
- (modified) lldb/source/Core/DumpDataExtractor.cpp (+4-3)
- (modified) lldb/source/Expression/IRExecutionUnit.cpp (+4-2)
- (modified) lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp (+1-1)
- (modified) lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp (+65-55)
- (modified) lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h (+5-3)
- (modified) lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp (+1-1)
- (modified) lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp (+5-2)
- (modified) lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp (+2-2)
- (modified) lldb/source/Symbol/Function.cpp (+3-3)
- (modified) lldb/source/Symbol/Symbol.cpp (+3-3)
- (modified) lldb/source/Target/Process.cpp (+4-1)
- (modified) lldb/source/Target/StackFrame.cpp (+11-6)
- (modified) lldb/source/Target/Target.cpp (+14)
- (modified) lldb/source/Target/TargetProperties.td (+6)
- (modified) lldb/source/Target/ThreadPlanStepRange.cpp (+4-2)
- (modified) lldb/source/Target/ThreadPlanTracer.cpp (+3-2)
- (modified) lldb/source/Target/TraceDumper.cpp (+3-3)
- (added) lldb/test/Shell/Commands/command-disassemble-cpu-features.yaml (+230)
``````````diff
diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h
index 21969aed03c209..e0ad4316e02497 100644
--- a/lldb/include/lldb/Core/Disassembler.h
+++ b/lldb/include/lldb/Core/Disassembler.h
@@ -409,35 +409,37 @@ class Disassembler : public std::enable_shared_from_this<Disassembler>,
// flavor string gets set wrong. Instead, if you get a flavor string you
// don't understand, use the default. Folks who care to check can use the
// FlavorValidForArchSpec method on the disassembler they got back.
- static lldb::DisassemblerSP
- FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name);
+ static lldb::DisassemblerSP FindPlugin(const ArchSpec &arch,
+ const char *flavor, const char *cpu,
+ const char *features,
+ const char *plugin_name);
// This version will use the value in the Target settings if flavor is NULL;
- static lldb::DisassemblerSP FindPluginForTarget(const Target &target,
- const ArchSpec &arch,
- const char *flavor,
- const char *plugin_name);
+ static lldb::DisassemblerSP
+ FindPluginForTarget(const Target &target, const ArchSpec &arch,
+ const char *flavor, const char *cpu, const char *features,
+ const char *plugin_name);
struct Limit {
enum { Bytes, Instructions } kind;
lldb::addr_t value;
};
- static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch,
- const char *plugin_name,
- const char *flavor,
- Target &target,
- const AddressRange &disasm_range,
- bool force_live_memory = false);
+ static lldb::DisassemblerSP
+ DisassembleRange(const ArchSpec &arch, const char *plugin_name,
+ const char *flavor, const char *cpu, const char *features,
+ Target &target, const AddressRange &disasm_range,
+ bool force_live_memory = false);
static lldb::DisassemblerSP
DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
- const char *flavor, const Address &start, const void *bytes,
- size_t length, uint32_t max_num_instructions,
- bool data_from_file);
+ const char *flavor, const char *cpu, const char *features,
+ const Address &start, const void *bytes, size_t length,
+ uint32_t max_num_instructions, bool data_from_file);
static bool Disassemble(Debugger &debugger, const ArchSpec &arch,
const char *plugin_name, const char *flavor,
+ const char *cpu, const char *features,
const ExecutionContext &exe_ctx, const Address &start,
Limit limit, bool mixed_source_and_assembly,
uint32_t num_mixed_context_lines, uint32_t options,
diff --git a/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h b/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h
index b5e989633ea3fc..1875ff6a048d4c 100644
--- a/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h
+++ b/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h
@@ -312,6 +312,8 @@ static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = {
{ lldb::eArgTypeRemotePath, "remote-path", lldb::CompletionType::eRemoteDiskFileCompletion, {}, { nullptr, false }, "A path on the system managed by the current platform." },
{ lldb::eArgTypeRemoteFilename, "remote-filename", lldb::CompletionType::eRemoteDiskFileCompletion, {}, { nullptr, false }, "A file on the system managed by the current platform." },
{ lldb::eArgTypeModule, "module", lldb::CompletionType::eModuleCompletion, {}, { nullptr, false }, "The name of a module loaded into the current target." },
+ { lldb::eArgTypeCPUName, "cpu-name", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The name of a CPU." },
+ { lldb::eArgTypeCPUFeatures, "cpu-features", lldb::CompletionType::eNoCompletion, {}, { nullptr, false }, "The CPU feature string." },
// clang-format on
};
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index cab21c29a7486f..f4ca5df44b7878 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -119,6 +119,10 @@ class TargetProperties : public Properties {
const char *GetDisassemblyFlavor() const;
+ const char *GetDisassemblyCPU() const;
+
+ const char *GetDisassemblyFeatures() const;
+
InlineStrategy GetInlineStrategy() const;
RealpathPrefixes GetSourceRealpathPrefixes() const;
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 938f6e3abe8f2a..a9a66ea2662f39 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -655,6 +655,8 @@ enum CommandArgumentType {
eArgTypeRemotePath,
eArgTypeRemoteFilename,
eArgTypeModule,
+ eArgTypeCPUName,
+ eArgTypeCPUFeatures,
eArgTypeLastArg // Always keep this entry as the last entry in this
// enumeration!!
};
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index 5bac5cd3e86b59..d366dbd1d78329 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -29,8 +29,9 @@ typedef lldb::ABISP (*ABICreateInstance)(lldb::ProcessSP process_sp,
const ArchSpec &arch);
typedef std::unique_ptr<Architecture> (*ArchitectureCreateInstance)(
const ArchSpec &arch);
-typedef lldb::DisassemblerSP (*DisassemblerCreateInstance)(const ArchSpec &arch,
- const char *flavor);
+typedef lldb::DisassemblerSP (*DisassemblerCreateInstance)(
+ const ArchSpec &arch, const char *flavor, const char *cpu,
+ const char *features);
typedef DynamicLoader *(*DynamicLoaderCreateInstance)(Process *process,
bool force);
typedef lldb::JITLoaderSP (*JITLoaderCreateInstance)(Process *process,
diff --git a/lldb/source/API/SBFunction.cpp b/lldb/source/API/SBFunction.cpp
index 6a97352fc2c2fd..c07d48fe5b499d 100644
--- a/lldb/source/API/SBFunction.cpp
+++ b/lldb/source/API/SBFunction.cpp
@@ -125,8 +125,8 @@ SBInstructionList SBFunction::GetInstructions(SBTarget target,
lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
const bool force_live_memory = true;
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
- module_sp->GetArchitecture(), nullptr, flavor, *target_sp,
- m_opaque_ptr->GetAddressRange(), force_live_memory));
+ module_sp->GetArchitecture(), nullptr, flavor, nullptr, nullptr,
+ *target_sp, m_opaque_ptr->GetAddressRange(), force_live_memory));
}
}
return sb_instructions;
diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp
index 3f940538d1240a..90920060594143 100644
--- a/lldb/source/API/SBSymbol.cpp
+++ b/lldb/source/API/SBSymbol.cpp
@@ -126,8 +126,8 @@ SBInstructionList SBSymbol::GetInstructions(SBTarget target,
AddressRange symbol_range(symbol_addr, m_opaque_ptr->GetByteSize());
const bool force_live_memory = true;
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
- module_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
- symbol_range, force_live_memory));
+ module_sp->GetArchitecture(), nullptr, flavor_string, nullptr,
+ nullptr, *target_sp, symbol_range, force_live_memory));
}
}
}
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 28bdf47a34137a..ff752a519d951e 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -2013,8 +2013,9 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr,
error, force_live_memory, &load_addr);
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
- target_sp->GetArchitecture(), nullptr, flavor_string, *addr_ptr,
- data.GetBytes(), bytes_read, count, data_from_file));
+ target_sp->GetArchitecture(), nullptr, nullptr, nullptr,
+ flavor_string, *addr_ptr, data.GetBytes(), bytes_read, count,
+ data_from_file));
}
}
@@ -2038,8 +2039,8 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress start_addr,
AddressRange range(start_load_addr, size);
const bool force_live_memory = true;
sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
- target_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
- range, force_live_memory));
+ target_sp->GetArchitecture(), nullptr, flavor_string, nullptr,
+ nullptr, *target_sp, range, force_live_memory));
}
}
return sb_instructions;
@@ -2071,8 +2072,8 @@ SBTarget::GetInstructionsWithFlavor(lldb::SBAddress base_addr,
const bool data_from_file = true;
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
- target_sp->GetArchitecture(), nullptr, flavor_string, addr, buf, size,
- UINT32_MAX, data_from_file));
+ target_sp->GetArchitecture(), nullptr, flavor_string, nullptr, nullptr,
+ addr, buf, size, UINT32_MAX, data_from_file));
}
return sb_instructions;
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
index 250f849ac04c55..6db4b2665bd84a 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -120,6 +120,14 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
break;
}
+ case 'X':
+ cpu_string = std::string(option_arg);
+ break;
+
+ case 'Y':
+ features_string = std::string(option_arg);
+ break;
+
case 'r':
raw = true;
break;
@@ -176,20 +184,27 @@ void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
Target *target =
execution_context ? execution_context->GetTargetPtr() : nullptr;
- // This is a hack till we get the ability to specify features based on
- // architecture. For now GetDisassemblyFlavor is really only valid for x86
- // (and for the llvm assembler plugin, but I'm papering over that since that
- // is the only disassembler plugin we have...
if (target) {
+ // This is a hack till we get the ability to specify features based on
+ // architecture. For now GetDisassemblyFlavor is really only valid for x86
+ // (and for the llvm assembler plugin, but I'm papering over that since that
+ // is the only disassembler plugin we have...
if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
target->GetArchitecture().GetTriple().getArch() ==
llvm::Triple::x86_64) {
flavor_string.assign(target->GetDisassemblyFlavor());
- } else
+ } else {
flavor_string.assign("default");
-
- } else
+ }
+ if (const char *cpu = target->GetDisassemblyCPU())
+ cpu_string.assign(cpu);
+ if (const char *features = target->GetDisassemblyFeatures())
+ features_string.assign(features);
+ } else {
flavor_string.assign("default");
+ cpu_string.assign("default");
+ features_string.assign("default");
+ }
arch.Clear();
some_location_specified = false;
@@ -453,9 +468,11 @@ void CommandObjectDisassemble::DoExecute(Args &command,
const char *plugin_name = m_options.GetPluginName();
const char *flavor_string = m_options.GetFlavorString();
+ const char *cpu_string = m_options.GetCPUString();
+ const char *features_string = m_options.GetFeaturesString();
- DisassemblerSP disassembler =
- Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
+ DisassemblerSP disassembler = Disassembler::FindPlugin(
+ m_options.arch, flavor_string, cpu_string, features_string, plugin_name);
if (!disassembler) {
if (plugin_name) {
@@ -524,7 +541,8 @@ void CommandObjectDisassemble::DoExecute(Args &command,
}
if (Disassembler::Disassemble(
GetDebugger(), m_options.arch, plugin_name, flavor_string,
- m_exe_ctx, cur_range.GetBaseAddress(), limit, m_options.show_mixed,
+ cpu_string, features_string, m_exe_ctx, cur_range.GetBaseAddress(),
+ limit, m_options.show_mixed,
m_options.show_mixed ? m_options.num_lines_context : 0, options,
result.GetOutputStream())) {
result.SetStatus(eReturnStatusSuccessFinishResult);
diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h
index 2e4d46dd0ec586..f9cba1e5ae9cb6 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.h
+++ b/lldb/source/Commands/CommandObjectDisassemble.h
@@ -42,6 +42,18 @@ class CommandObjectDisassemble : public CommandObjectParsed {
return flavor_string.c_str();
}
+ const char *GetCPUString() {
+ if (cpu_string.empty() || cpu_string == "default")
+ return nullptr;
+ return cpu_string.c_str();
+ }
+
+ const char *GetFeaturesString() {
+ if (features_string.empty() || features_string == "default")
+ return nullptr;
+ return features_string.c_str();
+ }
+
Status OptionParsingFinished(ExecutionContext *execution_context) override;
bool show_mixed; // Show mixed source/assembly
@@ -58,6 +70,8 @@ class CommandObjectDisassemble : public CommandObjectParsed {
bool frame_line = false;
std::string plugin_name;
std::string flavor_string;
+ std::string cpu_string;
+ std::string features_string;
ArchSpec arch;
bool some_location_specified = false; // If no location was specified, we'll
// select "at_pc". This should be set
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index 9d8d45d083eca4..777f8c36c4916c 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -324,6 +324,10 @@ let Command = "disassemble" in {
Arg<"DisassemblyFlavor">, Desc<"Name of the disassembly flavor you want to "
"use. Currently the only valid options are default, and for Intel "
"architectures, att and intel.">;
+ def disassemble_options_cpu : Option<"cpu", "X">, Arg<"CPUName">,
+ Desc<"Override the CPU for disassembling.">;
+ def disassemble_options_features : Option<"features", "Y">, Arg<"CPUFeatures">,
+ Desc<"Specify additional CPU features for disassembling.">;
def disassemble_options_arch : Option<"arch", "A">, Arg<"Architecture">,
Desc<"Specify the architecture to use from cross disassembly.">;
def disassemble_options_start_address : Option<"start-address", "s">,
diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp
index d071e3bfe4f77d..522a3ef2efc334 100644
--- a/lldb/source/Core/Disassembler.cpp
+++ b/lldb/source/Core/Disassembler.cpp
@@ -56,7 +56,8 @@ using namespace lldb;
using namespace lldb_private;
DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
- const char *flavor,
+ const char *flavor, const char *cpu,
+ const char *features,
const char *plugin_name) {
LLDB_SCOPED_TIMERF("Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
arch.GetArchitectureName(), plugin_name);
@@ -67,7 +68,7 @@ DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
create_callback =
PluginManager::GetDisassemblerCreateCallbackForPluginName(plugin_name);
if (create_callback) {
- if (auto disasm_sp = create_callback(arch, flavor))
+ if (auto disasm_sp = create_callback(arch, flavor, cpu, features))
return disasm_sp;
}
} else {
@@ -75,18 +76,17 @@ DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
(create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(
idx)) != nullptr;
++idx) {
- if (auto disasm_sp = create_callback(arch, flavor))
+ if (auto disasm_sp = create_callback(arch, flavor, cpu, features))
return disasm_sp;
}
}
return DisassemblerSP();
}
-DisassemblerSP Disassembler::FindPluginForTarget(const Target &target,
- const ArchSpec &arch,
- const char *flavor,
- const char *plugin_name) {
- if (flavor == nullptr) {
+DisassemblerSP Disassembler::FindPluginForTarget(
+ const Target &target, const ArchSpec &arch, const char *flavor,
+ const char *cpu, const char *features, const char *plugin_name) {
+ if (!flavor) {
// FIXME - we don't have the mechanism in place to do per-architecture
// settings. But since we know that for now we only support flavors on x86
// & x86_64,
@@ -94,7 +94,12 @@ DisassemblerSP Disassembler::FindPluginForTarget(const Target &target,
arch.GetTriple().getArch() == llvm::Triple::x86_64)
flavor = target.GetDisassemblyFlavor();
}
- return FindPlugin(arch, flavor, plugin_name);
+ if (!cpu)
+ cpu = target.GetDisassemblyCPU();
+ if (!features)
+ features = target.GetDisassemblyFeatures();
+
+ return FindPlugin(arch, flavor, cpu, features, plugin_name);
}
static Address ResolveAddress(Target &target, const Address &addr) {
@@ -117,15 +122,16 @@ static Address ResolveAddress(Target &target, const Address &addr) {
lldb::DisassemblerSP Disassembler::DisassembleRange(
const ArchSpec &arch, const char *plugin_name, const char *flavor,
- Target &target, const AddressRange &range, bool force_live_memory) {
+ const char *cpu, const char *features, Target &target,
+ const AddressRange &range, bool force_live_memory) {
if (range.GetByteSize() <= 0)
return {};
if (!range.GetBaseAddress().IsValid())
return {};
- lldb::DisassemblerSP disasm_sp =
- Disassembler::FindPluginForTarget(target, arch, flavor, plugin_name);
+ lldb::DisassemblerSP disasm_sp = Disassembler::FindPluginForTarget(
+ target, arch, flavor, cpu, features, plugin_name);
if (!disasm_sp)
return {};
@@ -141,14 +147,15 @@ lldb::DisassemblerSP Disassembler::DisassembleRange(
lldb::DisassemblerSP
Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
- const char *flavor, const Address &start,
+ const char *flavor, const char *cpu,
+ const char *features, const Address &start,
const void *src, size_t src_len,
uint32_t num_instructions, bool data_from_file) {
if (!src)
return {};
lldb::DisassemblerSP disasm_sp =
- Disassembler::FindPlugin(arch, flavor, plugin_name);
+ Disassembler::FindPlugin(arch, flavor, cpu, features, plugin_name);
if (!disasm_sp)
return {};
@@ -163,6 +170,7 @@ Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,
bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
const char *plugin_name, const char *flavor,
+ const char *cpu, const char *features,
const ExecutionContext &exe_ctx,
const Address &address, Limit limit,
bool mixed_source_and_assembly,
@@ -172,7 +180,7 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
return false;
lldb::Disassemb...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/115382
More information about the lldb-commits
mailing list