[lldb] Support overriding the disassembly CPU & features by JDevlieghere · Pull Request #115382 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-lldb

Author: Jonas Devlieghere (JDevlieghere)

Changes

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:

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, // 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 (*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_lockstd::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");

@@ -453,9 +468,11 @@ void CommandObjectDisassemble::DoExecute(Args &command,

const char *plugin_name = m_options.GetPluginName(); const char *flavor_string = m_options.GetFlavorString();

@@ -524,7 +541,8 @@ void CommandObjectDisassemble::DoExecute(Args &command, } if (Disassembler::Disassemble( GetDebugger(), m_options.arch, plugin_name, flavor_string,

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(); }

@@ -58,6 +70,8 @@ class CommandObjectDisassemble : public CommandObjectParsed { bool frame_line = false; std::string plugin_name; std::string flavor_string;

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_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,

@@ -67,7 +68,7 @@ DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch, create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName(plugin_name); if (create_callback) {

-DisassemblerSP Disassembler::FindPluginForTarget(const Target &target,

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,

if (range.GetByteSize() <= 0) return {};

if (!range.GetBaseAddress().IsValid()) return {};

@@ -141,14 +147,15 @@ lldb::DisassemblerSP Disassembler::DisassembleRange(

lldb::DisassemblerSP Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name,

@@ -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,

@@ -172,7 +180,7 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, return false;

lldb::Disassemb... [truncated]