[Lldb-commits] [lldb] [lldb] Support overriding the disassembly CPU & features (PR #115382)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Fri Nov 8 09:33:02 PST 2024
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/115382
>From b5947cfe8fd7702f801c91f48ca050a5c839a707 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 7 Nov 2024 14:08:50 -0800
Subject: [PATCH 1/4] [lldb] Support overriding the disassembly CPU & features
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.
---
lldb/include/lldb/Core/Disassembler.h | 32 +--
.../Interpreter/CommandOptionArgumentTable.h | 2 +
lldb/include/lldb/Target/Target.h | 4 +
lldb/include/lldb/lldb-enumerations.h | 2 +
lldb/include/lldb/lldb-private-interfaces.h | 5 +-
lldb/source/API/SBFunction.cpp | 4 +-
lldb/source/API/SBSymbol.cpp | 4 +-
lldb/source/API/SBTarget.cpp | 13 +-
.../Commands/CommandObjectDisassemble.cpp | 38 ++-
.../Commands/CommandObjectDisassemble.h | 14 ++
lldb/source/Commands/Options.td | 4 +
lldb/source/Core/Disassembler.cpp | 42 ++--
lldb/source/Core/DumpDataExtractor.cpp | 7 +-
lldb/source/Expression/IRExecutionUnit.cpp | 6 +-
.../Architecture/Mips/ArchitectureMips.cpp | 2 +-
.../Disassembler/LLVMC/DisassemblerLLVMC.cpp | 120 ++++-----
.../Disassembler/LLVMC/DisassemblerLLVMC.h | 8 +-
.../Windows-DYLD/DynamicLoaderWindowsDYLD.cpp | 2 +-
.../Process/Utility/StopInfoMachException.cpp | 7 +-
.../UnwindAssemblyInstEmulation.cpp | 4 +-
lldb/source/Symbol/Function.cpp | 6 +-
lldb/source/Symbol/Symbol.cpp | 6 +-
lldb/source/Target/Process.cpp | 5 +-
lldb/source/Target/StackFrame.cpp | 17 +-
lldb/source/Target/Target.cpp | 14 ++
lldb/source/Target/TargetProperties.td | 6 +
lldb/source/Target/ThreadPlanStepRange.cpp | 6 +-
lldb/source/Target/ThreadPlanTracer.cpp | 5 +-
lldb/source/Target/TraceDumper.cpp | 6 +-
.../command-disassemble-cpu-features.yaml | 230 ++++++++++++++++++
30 files changed, 478 insertions(+), 143 deletions(-)
create mode 100644 lldb/test/Shell/Commands/command-disassemble-cpu-features.yaml
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::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget(
- exe_ctx.GetTargetRef(), arch, flavor, plugin_name));
+ exe_ctx.GetTargetRef(), arch, flavor, cpu, features, plugin_name));
if (!disasm_sp)
return false;
@@ -559,8 +567,8 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch,
if (limit.value == 0)
limit.value = DEFAULT_DISASM_BYTE_SIZE;
- return Disassemble(debugger, arch, nullptr, nullptr, frame,
- range.GetBaseAddress(), limit, false, 0, 0, strm);
+ return Disassemble(debugger, arch, nullptr, nullptr, nullptr, nullptr,
+ frame, range.GetBaseAddress(), limit, false, 0, 0, strm);
}
Instruction::Instruction(const Address &address, AddressClass addr_class)
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index 826edd7bab046e..565ee3a0ae40a4 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -128,9 +128,10 @@ static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s,
if (exe_scope)
target_sp = exe_scope->CalculateTarget();
if (target_sp) {
- DisassemblerSP disassembler_sp(
- Disassembler::FindPlugin(target_sp->GetArchitecture(),
- target_sp->GetDisassemblyFlavor(), nullptr));
+ DisassemblerSP disassembler_sp(Disassembler::FindPlugin(
+ target_sp->GetArchitecture(), target_sp->GetDisassemblyFlavor(),
+ target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
+ nullptr));
if (disassembler_sp) {
lldb::addr_t addr = base_addr + start_offset;
lldb_private::Address so_addr;
diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 7bee183d2ff227..9158b43b1c5c0d 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -167,8 +167,10 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream,
const char *plugin_name = nullptr;
const char *flavor_string = nullptr;
- lldb::DisassemblerSP disassembler_sp =
- Disassembler::FindPlugin(arch, flavor_string, plugin_name);
+ const char *cpu_string = nullptr;
+ const char *features_string = nullptr;
+ lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(
+ arch, flavor_string, cpu_string, features_string, plugin_name);
if (!disassembler_sp) {
ret = Status::FromErrorStringWithFormat(
diff --git a/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp b/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
index a9f2e7af601db9..27ba10524141ed 100644
--- a/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
+++ b/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
@@ -150,7 +150,7 @@ Instruction *ArchitectureMips::GetInstructionAtAddress(
// Create Disassembler Instance
lldb::DisassemblerSP disasm_sp(
- Disassembler::FindPlugin(m_arch, nullptr, nullptr));
+ Disassembler::FindPlugin(m_arch, nullptr, nullptr, nullptr, nullptr));
InstructionList instruction_list;
InstructionSP prev_insn;
diff --git a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
index 31edd8d46c444e..e108e92fcca4ce 100644
--- a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
+++ b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
@@ -1439,7 +1439,9 @@ bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated(
}
DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
- const char *flavor_string)
+ const char *flavor_string,
+ const char *cpu_string,
+ const char *features_string)
: Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr),
m_data_from_file(false), m_adrp_address(LLDB_INVALID_ADDRESS),
m_adrp_insn() {
@@ -1447,6 +1449,7 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
m_flavor.assign("default");
}
+ const bool cpu_or_features_overriden = cpu_string || features_string;
unsigned flavor = ~0U;
llvm::Triple triple = arch.GetTriple();
@@ -1483,64 +1486,68 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
triple.getSubArch() == llvm::Triple::NoSubArch)
triple.setArchName("armv9.3a");
- std::string features_str;
+ std::string features_str =
+ features_string ? std::string(features_string) : "";
const char *triple_str = triple.getTriple().c_str();
// ARM Cortex M0-M7 devices only execute thumb instructions
if (arch.IsAlwaysThumbInstructions()) {
triple_str = thumb_arch.GetTriple().getTriple().c_str();
- features_str += "+fp-armv8,";
+ if (!features_string)
+ features_str += "+fp-armv8,";
}
- const char *cpu = "";
+ const char *cpu = cpu_string;
- switch (arch.GetCore()) {
- case ArchSpec::eCore_mips32:
- case ArchSpec::eCore_mips32el:
- cpu = "mips32";
- break;
- case ArchSpec::eCore_mips32r2:
- case ArchSpec::eCore_mips32r2el:
- cpu = "mips32r2";
- break;
- case ArchSpec::eCore_mips32r3:
- case ArchSpec::eCore_mips32r3el:
- cpu = "mips32r3";
- break;
- case ArchSpec::eCore_mips32r5:
- case ArchSpec::eCore_mips32r5el:
- cpu = "mips32r5";
- break;
- case ArchSpec::eCore_mips32r6:
- case ArchSpec::eCore_mips32r6el:
- cpu = "mips32r6";
- break;
- case ArchSpec::eCore_mips64:
- case ArchSpec::eCore_mips64el:
- cpu = "mips64";
- break;
- case ArchSpec::eCore_mips64r2:
- case ArchSpec::eCore_mips64r2el:
- cpu = "mips64r2";
- break;
- case ArchSpec::eCore_mips64r3:
- case ArchSpec::eCore_mips64r3el:
- cpu = "mips64r3";
- break;
- case ArchSpec::eCore_mips64r5:
- case ArchSpec::eCore_mips64r5el:
- cpu = "mips64r5";
- break;
- case ArchSpec::eCore_mips64r6:
- case ArchSpec::eCore_mips64r6el:
- cpu = "mips64r6";
- break;
- default:
- cpu = "";
- break;
+ if (!cpu_or_features_overriden) {
+ switch (arch.GetCore()) {
+ case ArchSpec::eCore_mips32:
+ case ArchSpec::eCore_mips32el:
+ cpu = "mips32";
+ break;
+ case ArchSpec::eCore_mips32r2:
+ case ArchSpec::eCore_mips32r2el:
+ cpu = "mips32r2";
+ break;
+ case ArchSpec::eCore_mips32r3:
+ case ArchSpec::eCore_mips32r3el:
+ cpu = "mips32r3";
+ break;
+ case ArchSpec::eCore_mips32r5:
+ case ArchSpec::eCore_mips32r5el:
+ cpu = "mips32r5";
+ break;
+ case ArchSpec::eCore_mips32r6:
+ case ArchSpec::eCore_mips32r6el:
+ cpu = "mips32r6";
+ break;
+ case ArchSpec::eCore_mips64:
+ case ArchSpec::eCore_mips64el:
+ cpu = "mips64";
+ break;
+ case ArchSpec::eCore_mips64r2:
+ case ArchSpec::eCore_mips64r2el:
+ cpu = "mips64r2";
+ break;
+ case ArchSpec::eCore_mips64r3:
+ case ArchSpec::eCore_mips64r3el:
+ cpu = "mips64r3";
+ break;
+ case ArchSpec::eCore_mips64r5:
+ case ArchSpec::eCore_mips64r5el:
+ cpu = "mips64r5";
+ break;
+ case ArchSpec::eCore_mips64r6:
+ case ArchSpec::eCore_mips64r6el:
+ cpu = "mips64r6";
+ break;
+ default:
+ cpu = "";
+ break;
+ }
}
- if (arch.IsMIPS()) {
+ if (arch.IsMIPS() && !cpu_or_features_overriden) {
uint32_t arch_flags = arch.GetFlags();
if (arch_flags & ArchSpec::eMIPSAse_msa)
features_str += "+msa,";
@@ -1550,15 +1557,15 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
features_str += "+dspr2,";
}
- // If any AArch64 variant, enable latest ISA with all extensions.
- if (triple.isAArch64()) {
+ // If any AArch64 variant, enable latest ISA with all extensions unless the
+ // CPU or features were overridden.
+ if (triple.isAArch64() && !cpu_or_features_overriden) {
features_str += "+all,";
-
if (triple.getVendor() == llvm::Triple::Apple)
cpu = "apple-latest";
}
- if (triple.isRISCV()) {
+ if (triple.isRISCV() && !cpu_or_features_overriden) {
uint32_t arch_flags = arch.GetFlags();
if (arch_flags & ArchSpec::eRISCV_rvc)
features_str += "+c,";
@@ -1614,9 +1621,12 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
DisassemblerLLVMC::~DisassemblerLLVMC() = default;
lldb::DisassemblerSP DisassemblerLLVMC::CreateInstance(const ArchSpec &arch,
- const char *flavor) {
+ const char *flavor,
+ const char *cpu,
+ const char *features) {
if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) {
- auto disasm_sp = std::make_shared<DisassemblerLLVMC>(arch, flavor);
+ auto disasm_sp =
+ std::make_shared<DisassemblerLLVMC>(arch, flavor, cpu, features);
if (disasm_sp && disasm_sp->IsValid())
return disasm_sp;
}
diff --git a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h
index 30c69de81dfc83..d6b3d70934989b 100644
--- a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h
+++ b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h
@@ -22,8 +22,8 @@ class InstructionLLVMC;
class DisassemblerLLVMC : public lldb_private::Disassembler {
public:
- DisassemblerLLVMC(const lldb_private::ArchSpec &arch,
- const char *flavor /* = NULL */);
+ DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor,
+ const char *cpu, const char *features);
~DisassemblerLLVMC() override;
@@ -35,7 +35,9 @@ class DisassemblerLLVMC : public lldb_private::Disassembler {
static llvm::StringRef GetPluginNameStatic() { return "llvm-mc"; }
static lldb::DisassemblerSP CreateInstance(const lldb_private::ArchSpec &arch,
- const char *flavor);
+ const char *flavor,
+ const char *cpu,
+ const char *features);
size_t DecodeInstructions(const lldb_private::Address &base_addr,
const lldb_private::DataExtractor &data,
diff --git a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index f044aa786806fc..348cf58d69243d 100644
--- a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -183,7 +183,7 @@ DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread,
AddressRange range(pc, 2 * 15);
DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
- arch, nullptr, nullptr, m_process->GetTarget(), range);
+ arch, nullptr, nullptr, nullptr, nullptr, m_process->GetTarget(), range);
if (!disassembler_sp) {
return ThreadPlanSP();
}
diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 25cee369d7ee3d..d08e99f4844de3 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -48,10 +48,13 @@ GetPtrauthInstructionInfo(Target &target, const ArchSpec &arch,
const Address &at_addr) {
const char *plugin_name = nullptr;
const char *flavor = nullptr;
+ const char *cpu = nullptr;
+ const char *features = nullptr;
AddressRange range_bounds(at_addr, 4);
const bool prefer_file_cache = true;
- DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
- arch, plugin_name, flavor, target, range_bounds, prefer_file_cache);
+ DisassemblerSP disassembler_sp =
+ Disassembler::DisassembleRange(arch, plugin_name, flavor, cpu, features,
+ target, range_bounds, prefer_file_cache);
if (!disassembler_sp)
return std::nullopt;
diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 1a680d80a9d3d7..8a26d76b65d1b4 100644
--- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -70,8 +70,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
const bool prefer_file_cache = true;
DisassemblerSP disasm_sp(Disassembler::DisassembleBytes(
- m_arch, nullptr, nullptr, range.GetBaseAddress(), opcode_data,
- opcode_size, 99999, prefer_file_cache));
+ m_arch, nullptr, nullptr, nullptr, nullptr, range.GetBaseAddress(),
+ opcode_data, opcode_size, 99999, prefer_file_cache));
Log *log = GetLog(LLDBLog::Unwind);
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index 96d8322b43d843..04766e26674c8c 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -459,9 +459,9 @@ lldb::DisassemblerSP Function::GetInstructions(const ExecutionContext &exe_ctx,
bool prefer_file_cache) {
ModuleSP module_sp(GetAddressRange().GetBaseAddress().GetModule());
if (module_sp && exe_ctx.HasTargetScope()) {
- return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
- flavor, exe_ctx.GetTargetRef(),
- GetAddressRange(), !prefer_file_cache);
+ return Disassembler::DisassembleRange(
+ module_sp->GetArchitecture(), nullptr, nullptr, nullptr, flavor,
+ exe_ctx.GetTargetRef(), GetAddressRange(), !prefer_file_cache);
}
return lldb::DisassemblerSP();
}
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index 9b0042ffdb4bfe..4828de4fdfa377 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -591,9 +591,9 @@ lldb::DisassemblerSP Symbol::GetInstructions(const ExecutionContext &exe_ctx,
bool prefer_file_cache) {
ModuleSP module_sp(m_addr_range.GetBaseAddress().GetModule());
if (module_sp && exe_ctx.HasTargetScope()) {
- return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr,
- flavor, exe_ctx.GetTargetRef(),
- m_addr_range, !prefer_file_cache);
+ return Disassembler::DisassembleRange(
+ module_sp->GetArchitecture(), nullptr, flavor, nullptr, nullptr,
+ exe_ctx.GetTargetRef(), m_addr_range, !prefer_file_cache);
}
return lldb::DisassemblerSP();
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index c009d17d3ba507..b99692b8a0bfd9 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -6144,8 +6144,11 @@ Process::AdvanceAddressToNextBranchInstruction(Address default_stop_addr,
const char *plugin_name = nullptr;
const char *flavor = nullptr;
+ const char *cpu = nullptr;
+ const char *features = nullptr;
disassembler_sp = Disassembler::DisassembleRange(
- target.GetArchitecture(), plugin_name, flavor, GetTarget(), range_bounds);
+ target.GetArchitecture(), plugin_name, flavor, cpu, features, GetTarget(),
+ range_bounds);
if (disassembler_sp)
insn_list = &disassembler_sp->GetInstructionList();
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 3761b867452c99..ef71fc6acb1703 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -1316,11 +1316,13 @@ lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {
const char *plugin_name = nullptr;
const char *flavor = nullptr;
+ const char *cpu = nullptr;
+ const char *features = nullptr;
const bool force_live_memory = true;
- DisassemblerSP disassembler_sp =
- Disassembler::DisassembleRange(target_arch, plugin_name, flavor,
- *target_sp, pc_range, force_live_memory);
+ DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
+ target_arch, plugin_name, flavor, cpu, features, *target_sp, pc_range,
+ force_live_memory);
if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
return ValueObjectSP();
@@ -1697,10 +1699,12 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
const char *plugin_name = nullptr;
const char *flavor = nullptr;
+ const char *cpu = nullptr;
+ const char *features = nullptr;
const bool force_live_memory = true;
- DisassemblerSP disassembler_sp =
- Disassembler::DisassembleRange(target_arch, plugin_name, flavor,
- *target_sp, pc_range, force_live_memory);
+ DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
+ target_arch, plugin_name, flavor, cpu, features, *target_sp, pc_range,
+ force_live_memory);
if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
return ValueObjectSP();
@@ -1966,6 +1970,7 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
const bool mixed_source_and_assembly = false;
Disassembler::Disassemble(
target->GetDebugger(), target_arch, plugin_name, flavor,
+ target->GetDisassemblyCPU(), target->GetDisassemblyFeatures(),
exe_ctx, GetFrameCodeAddress(),
{Disassembler::Limit::Instructions, disasm_lines},
mixed_source_and_assembly, 0,
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 242d2eaec2a15a..a788bad88b2977 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -4490,6 +4490,20 @@ const char *TargetProperties::GetDisassemblyFlavor() const {
return return_value;
}
+const char *TargetProperties::GetDisassemblyCPU() const {
+ const uint32_t idx = ePropertyDisassemblyCPU;
+ llvm::StringRef str = GetPropertyAtIndexAs<llvm::StringRef>(
+ idx, g_target_properties[idx].default_cstr_value);
+ return str.empty() ? nullptr : str.data();
+}
+
+const char *TargetProperties::GetDisassemblyFeatures() const {
+ const uint32_t idx = ePropertyDisassemblyFeatures;
+ llvm::StringRef str = GetPropertyAtIndexAs<llvm::StringRef>(
+ idx, g_target_properties[idx].default_cstr_value);
+ return str.empty() ? nullptr : str.data();
+}
+
InlineStrategy TargetProperties::GetInlineStrategy() const {
const uint32_t idx = ePropertyInlineStrategy;
return GetPropertyAtIndexAs<InlineStrategy>(
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 00ad8dd2a9f7f9..d8d7e6353aad43 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -157,6 +157,12 @@ let Definition = "target" in {
DefaultEnumValue<"eX86DisFlavorDefault">,
EnumValues<"OptionEnumValues(g_x86_dis_flavor_value_types)">,
Desc<"The default disassembly flavor to use for x86 or x86-64 targets.">;
+ def DisassemblyCPU: Property<"disassembly-cpu", "String">,
+ DefaultStringValue<"">,
+ Desc<"Override the CPU for disassembling. Takes the same values as the -mcpu compiler flag.">;
+ def DisassemblyFeatures: Property<"disassembly-features", "String">,
+ DefaultStringValue<"">,
+ Desc<"Specify additional CPU features for disassembling.">;
def UseHexImmediates: Property<"use-hex-immediates", "Boolean">,
DefaultTrue,
Desc<"Show immediates in disassembly as hexadecimal.">;
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index b64ce6f0dc9c28..de4cd5995f6953 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -266,9 +266,11 @@ InstructionList *ThreadPlanStepRange::GetInstructionsForAddress(
// Disassemble the address range given:
const char *plugin_name = nullptr;
const char *flavor = nullptr;
+ const char *cpu = nullptr;
+ const char *features = nullptr;
m_instruction_ranges[i] = Disassembler::DisassembleRange(
- GetTarget().GetArchitecture(), plugin_name, flavor, GetTarget(),
- m_address_ranges[i]);
+ GetTarget().GetArchitecture(), plugin_name, flavor, cpu, features,
+ GetTarget(), m_address_ranges[i]);
}
if (!m_instruction_ranges[i])
return nullptr;
diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp
index acadda8f582f9d..ff9f49c6d4bb68 100644
--- a/lldb/source/Target/ThreadPlanTracer.cpp
+++ b/lldb/source/Target/ThreadPlanTracer.cpp
@@ -95,8 +95,9 @@ ThreadPlanAssemblyTracer::ThreadPlanAssemblyTracer(Thread &thread)
Disassembler *ThreadPlanAssemblyTracer::GetDisassembler() {
if (!m_disassembler_sp)
- m_disassembler_sp = Disassembler::FindPlugin(
- m_process.GetTarget().GetArchitecture(), nullptr, nullptr);
+ m_disassembler_sp =
+ Disassembler::FindPlugin(m_process.GetTarget().GetArchitecture(),
+ nullptr, nullptr, nullptr, nullptr);
return m_disassembler_sp.get();
}
diff --git a/lldb/source/Target/TraceDumper.cpp b/lldb/source/Target/TraceDumper.cpp
index 4ef8efc1a67689..fa732fa87c5290 100644
--- a/lldb/source/Target/TraceDumper.cpp
+++ b/lldb/source/Target/TraceDumper.cpp
@@ -510,9 +510,9 @@ CalculateDisass(const TraceDumper::SymbolInfo &symbol_info,
const ArchSpec arch = target.GetArchitecture();
lldb_private::AddressRange range(symbol_info.address,
arch.GetMaximumOpcodeByteSize());
- DisassemblerSP disassembler =
- Disassembler::DisassembleRange(arch, /*plugin_name*/ nullptr,
- /*flavor*/ nullptr, target, range);
+ DisassemblerSP disassembler = Disassembler::DisassembleRange(
+ arch, /*plugin_name=*/nullptr,
+ /*flavor=*/nullptr, /*cpu=*/nullptr, /*features=*/nullptr, target, range);
return std::make_tuple(
disassembler,
disassembler ? disassembler->GetInstructionList().GetInstructionAtAddress(
diff --git a/lldb/test/Shell/Commands/command-disassemble-cpu-features.yaml b/lldb/test/Shell/Commands/command-disassemble-cpu-features.yaml
new file mode 100644
index 00000000000000..199e78f4474ca6
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-disassemble-cpu-features.yaml
@@ -0,0 +1,230 @@
+# REQUIRES: aarch64
+
+# RUN: yaml2obj %s -o %t.out
+
+# RUN: %lldb %t.out -b -o "disassemble -c 1 --cpu 'apple-a16' -n main" | FileCheck %s --check-prefix SUPPORTED
+# RUN: %lldb %t.out -b -o "disassemble -c 1 --cpu 'apple-a11' -n main" | FileCheck %s --check-prefix UNSUPPORTED
+# RUN: %lldb %t.out -b -o "disassemble -c 1 --cpu 'apple-a11' --features '+all' -n main" | FileCheck %s --check-prefix SUPPORTED
+
+# RUN: %lldb %t.out -b -o "settings set target.disassembly-cpu 'apple-a16'" -o "disassemble -c 1 -n main" | FileCheck %s --check-prefix SUPPORTED
+# RUN: %lldb %t.out -b -o "settings set target.disassembly-cpu 'apple-a11'" -o "disassemble -c 1 -n main" | FileCheck %s --check-prefix UNSUPPORTED
+# RUN: %lldb %t.out -b -o "settings set target.disassembly-cpu 'apple-a11'" -o "settings set target.disassembly-features '+all'" -o "disassemble -c 1 -n main" | FileCheck %s --check-prefix SUPPORTED
+
+# SUPPORTED: <+0>: pacibsp
+# UNSUPPORTED-NOT: <+0>: pacibsp
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x100000C
+ cpusubtype: 0x80000002
+ filetype: 0x2
+ ncmds: 17
+ sizeofcmds: 1056
+ flags: 0x200085
+ reserved: 0x0
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __PAGEZERO
+ vmaddr: 0
+ vmsize: 4294967296
+ fileoff: 0
+ filesize: 0
+ maxprot: 0
+ initprot: 0
+ nsects: 0
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 392
+ segname: __TEXT
+ vmaddr: 4294967296
+ vmsize: 16384
+ fileoff: 0
+ filesize: 16384
+ maxprot: 5
+ initprot: 5
+ nsects: 4
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x100000460
+ size: 36
+ offset: 0x460
+ align: 2
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: 7F2303D5FD7BBFA9FD03009100000090005012910400009400008052FD7BC1A8FF0F5FD6
+ - sectname: __cstring
+ segname: __TEXT
+ addr: 0x100000494
+ size: 3
+ offset: 0x494
+ align: 0
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x2
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: '484900'
+ - cmd: LC_SEGMENT_64
+ cmdsize: 152
+ segname: __DATA_CONST
+ vmaddr: 4294983680
+ vmsize: 16384
+ fileoff: 16384
+ filesize: 16384
+ maxprot: 3
+ initprot: 3
+ nsects: 1
+ flags: 16
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 4295000064
+ vmsize: 16384
+ fileoff: 32768
+ filesize: 664
+ maxprot: 1
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 32920
+ nsyms: 3
+ stroff: 32976
+ strsize: 40
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 2
+ iundefsym: 2
+ nundefsym: 1
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 32968
+ nindirectsyms: 2
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+ - cmd: LC_LOAD_DYLINKER
+ cmdsize: 32
+ name: 12
+ Content: '/usr/lib/dyld'
+ ZeroPadBytes: 7
+ - cmd: LC_UUID
+ cmdsize: 24
+ uuid: CF3EBEFA-8D83-3C25-931A-5AF74AFE0B3A
+ - cmd: LC_BUILD_VERSION
+ cmdsize: 32
+ platform: 1
+ minos: 983040
+ sdk: 983808
+ ntools: 1
+ Tools:
+ - tool: 3
+ version: 76153600
+ - cmd: LC_SOURCE_VERSION
+ cmdsize: 16
+ version: 0
+ - cmd: LC_MAIN
+ cmdsize: 24
+ entryoff: 1120
+ stacksize: 0
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 56
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 88539136
+ compatibility_version: 65536
+ Content: '/usr/lib/libSystem.B.dylib'
+ ZeroPadBytes: 6
+ - cmd: LC_FUNCTION_STARTS
+ cmdsize: 16
+ dataoff: 32912
+ datasize: 8
+ - cmd: LC_DATA_IN_CODE
+ cmdsize: 16
+ dataoff: 32920
+ datasize: 0
+ - cmd: LC_CODE_SIGNATURE
+ cmdsize: 16
+ dataoff: 33024
+ datasize: 408
+LinkEditData:
+ ExportTrie:
+ TerminalSize: 0
+ NodeOffset: 0
+ Name: ''
+ Flags: 0x0
+ Address: 0x0
+ Other: 0x0
+ ImportName: ''
+ Children:
+ - TerminalSize: 0
+ NodeOffset: 18
+ Name: _
+ Flags: 0x0
+ Address: 0x0
+ Other: 0x0
+ ImportName: ''
+ Children:
+ - TerminalSize: 2
+ NodeOffset: 9
+ Name: _mh_execute_header
+ Flags: 0x0
+ Address: 0x0
+ Other: 0x0
+ ImportName: ''
+ - TerminalSize: 3
+ NodeOffset: 13
+ Name: main
+ Flags: 0x0
+ Address: 0x460
+ Other: 0x0
+ ImportName: ''
+ NameList:
+ - n_strx: 2
+ n_type: 0xF
+ n_sect: 1
+ n_desc: 16
+ n_value: 4294967296
+ - n_strx: 22
+ n_type: 0xF
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294968416
+ - n_strx: 28
+ n_type: 0x1
+ n_sect: 0
+ n_desc: 256
+ n_value: 0
+ StringTable:
+ - ' '
+ - __mh_execute_header
+ - _main
+ - _puts
+ - ''
+ - ''
+ - ''
+ - ''
+ - ''
+ - ''
+ IndirectSymbols: [ 0x2, 0x2 ]
+ FunctionStarts: [ 0x460 ]
+...
>From 584eba125a8263d3739a28739a8ca27a39a3107c Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 7 Nov 2024 16:29:10 -0800
Subject: [PATCH 2/4] Address Jason's feedback
---
lldb/source/Target/TargetProperties.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index d8d7e6353aad43..4faf4c26b57011 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -159,7 +159,7 @@ let Definition = "target" in {
Desc<"The default disassembly flavor to use for x86 or x86-64 targets.">;
def DisassemblyCPU: Property<"disassembly-cpu", "String">,
DefaultStringValue<"">,
- Desc<"Override the CPU for disassembling. Takes the same values as the -mcpu compiler flag.">;
+ Desc<"Override the CPU for disassembling. Takes the same values as the -mcpu clang flag.">;
def DisassemblyFeatures: Property<"disassembly-features", "String">,
DefaultStringValue<"">,
Desc<"Specify additional CPU features for disassembling.">;
>From 390624d7f63ac85f616e568dd7f8c38424b1cb6f Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 7 Nov 2024 16:29:56 -0800
Subject: [PATCH 3/4] Update unit test
---
lldb/unittests/Disassembler/ARM/TestArm64Disassembly.cpp | 5 +++--
lldb/unittests/Disassembler/ARM/TestArmv7Disassembly.cpp | 5 +++--
.../Disassembler/RISCV/TestMCDisasmInstanceRISCV.cpp | 6 +++---
.../Disassembler/x86/TestGetControlFlowKindx86.cpp | 6 +++---
4 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/lldb/unittests/Disassembler/ARM/TestArm64Disassembly.cpp b/lldb/unittests/Disassembler/ARM/TestArm64Disassembly.cpp
index f89a918e3e54fa..dcca1a7ae959b3 100644
--- a/lldb/unittests/Disassembler/ARM/TestArm64Disassembly.cpp
+++ b/lldb/unittests/Disassembler/ARM/TestArm64Disassembly.cpp
@@ -56,8 +56,9 @@ TEST_F(TestArm64Disassembly, TestArmv81Instruction) {
DisassemblerSP disass_sp;
Address start_addr(0x100);
- disass_sp = Disassembler::DisassembleBytes(arch, nullptr, nullptr, start_addr,
- &data, sizeof (data), num_of_instructions, false);
+ disass_sp = Disassembler::DisassembleBytes(
+ arch, nullptr, nullptr, nullptr, nullptr, start_addr, &data, sizeof(data),
+ num_of_instructions, false);
// If we failed to get a disassembler, we can assume it is because
// the llvm we linked against was not built with the ARM target,
diff --git a/lldb/unittests/Disassembler/ARM/TestArmv7Disassembly.cpp b/lldb/unittests/Disassembler/ARM/TestArmv7Disassembly.cpp
index 047cba1db40821..00632cc57f005b 100644
--- a/lldb/unittests/Disassembler/ARM/TestArmv7Disassembly.cpp
+++ b/lldb/unittests/Disassembler/ARM/TestArmv7Disassembly.cpp
@@ -64,8 +64,9 @@ TEST_F(TestArmv7Disassembly, TestCortexFPDisass) {
DisassemblerSP disass_sp;
Address start_addr(0x100);
- disass_sp = Disassembler::DisassembleBytes(arch, nullptr, nullptr, start_addr,
- &data, sizeof (data), num_of_instructions, false);
+ disass_sp = Disassembler::DisassembleBytes(
+ arch, nullptr, nullptr, nullptr, nullptr, start_addr, &data, sizeof(data),
+ num_of_instructions, false);
// If we failed to get a disassembler, we can assume it is because
// the llvm we linked against was not built with the ARM target,
diff --git a/lldb/unittests/Disassembler/RISCV/TestMCDisasmInstanceRISCV.cpp b/lldb/unittests/Disassembler/RISCV/TestMCDisasmInstanceRISCV.cpp
index 2f2585a23d7624..8ec5d62a99ac57 100644
--- a/lldb/unittests/Disassembler/RISCV/TestMCDisasmInstanceRISCV.cpp
+++ b/lldb/unittests/Disassembler/RISCV/TestMCDisasmInstanceRISCV.cpp
@@ -56,9 +56,9 @@ TEST_F(TestMCDisasmInstanceRISCV, TestRISCV32Instruction) {
DisassemblerSP disass_sp;
Address start_addr(0x100);
- disass_sp =
- Disassembler::DisassembleBytes(arch, nullptr, nullptr, start_addr, &data,
- sizeof (data), num_of_instructions, false);
+ disass_sp = Disassembler::DisassembleBytes(
+ arch, nullptr, nullptr, nullptr, nullptr, start_addr, &data, sizeof(data),
+ num_of_instructions, false);
// If we failed to get a disassembler, we can assume it is because
// the llvm we linked against was not built with the riscv target,
diff --git a/lldb/unittests/Disassembler/x86/TestGetControlFlowKindx86.cpp b/lldb/unittests/Disassembler/x86/TestGetControlFlowKindx86.cpp
index e9d5ae3f7b3cdb..4b62e5f747529c 100644
--- a/lldb/unittests/Disassembler/x86/TestGetControlFlowKindx86.cpp
+++ b/lldb/unittests/Disassembler/x86/TestGetControlFlowKindx86.cpp
@@ -124,9 +124,9 @@ TEST_F(TestGetControlFlowKindx86, TestX86_64Instruction) {
DisassemblerSP disass_sp;
Address start_addr(0x100);
- disass_sp =
- Disassembler::DisassembleBytes(arch, nullptr, nullptr, start_addr, &data,
- sizeof (data), num_of_instructions, false);
+ disass_sp = Disassembler::DisassembleBytes(
+ arch, nullptr, nullptr, nullptr, nullptr, start_addr, &data, sizeof(data),
+ num_of_instructions, false);
// If we failed to get a disassembler, we can assume it is because
// the llvm we linked against was not built with the i386 target,
>From 3e3b00b96489ee0975c1b88fe3775642570ee123 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Fri, 8 Nov 2024 09:32:46 -0800
Subject: [PATCH 4/4] Honor the setting in the SBAPI
---
lldb/source/API/SBFunction.cpp | 3 ++-
lldb/source/API/SBSymbol.cpp | 5 +++--
lldb/source/API/SBTarget.cpp | 14 ++++++++------
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/lldb/source/API/SBFunction.cpp b/lldb/source/API/SBFunction.cpp
index c07d48fe5b499d..ac61220ec8736a 100644
--- a/lldb/source/API/SBFunction.cpp
+++ b/lldb/source/API/SBFunction.cpp
@@ -125,7 +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, nullptr, nullptr,
+ module_sp->GetArchitecture(), nullptr, flavor,
+ target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
*target_sp, m_opaque_ptr->GetAddressRange(), force_live_memory));
}
}
diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp
index 90920060594143..79477dd3a70fc6 100644
--- a/lldb/source/API/SBSymbol.cpp
+++ b/lldb/source/API/SBSymbol.cpp
@@ -126,8 +126,9 @@ 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, nullptr,
- nullptr, *target_sp, symbol_range, force_live_memory));
+ module_sp->GetArchitecture(), nullptr, flavor_string,
+ target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
+ *target_sp, symbol_range, force_live_memory));
}
}
}
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index ff752a519d951e..3c4c3d8d85292e 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -2013,9 +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, nullptr, nullptr,
- flavor_string, *addr_ptr, data.GetBytes(), bytes_read, count,
- data_from_file));
+ target_sp->GetArchitecture(), nullptr, target_sp->GetDisassemblyCPU(),
+ target_sp->GetDisassemblyFeatures(), flavor_string, *addr_ptr,
+ data.GetBytes(), bytes_read, count, data_from_file));
}
}
@@ -2039,8 +2039,9 @@ 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, nullptr,
- nullptr, *target_sp, range, force_live_memory));
+ target_sp->GetArchitecture(), nullptr, flavor_string,
+ target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
+ *target_sp, range, force_live_memory));
}
}
return sb_instructions;
@@ -2072,7 +2073,8 @@ SBTarget::GetInstructionsWithFlavor(lldb::SBAddress base_addr,
const bool data_from_file = true;
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
- target_sp->GetArchitecture(), nullptr, flavor_string, nullptr, nullptr,
+ target_sp->GetArchitecture(), nullptr, flavor_string,
+ target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
addr, buf, size, UINT32_MAX, data_from_file));
}
More information about the lldb-commits
mailing list