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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits