diff options
| author | Jim Ingham <jingham@apple.com> | 2013-03-02 00:26:47 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2013-03-02 00:26:47 +0000 |
| commit | 0f063ba6b41276a18f3f60380ce16fcd58b20484 (patch) | |
| tree | 19e25c2ecef13047a0fe0ec382961b0d4d98d027 /lldb | |
| parent | b1caf3c30e6a72b37379600872e253da4d18178e (diff) | |
| download | bcm5719-llvm-0f063ba6b41276a18f3f60380ce16fcd58b20484.tar.gz bcm5719-llvm-0f063ba6b41276a18f3f60380ce16fcd58b20484.zip | |
Convert from the C-based LLVM Disassembler shim to the full MC Disassembler API's.
Calculate "can branch" using the MC API's rather than our hand-rolled regex'es.
As extra credit, allow setting the disassembly flavor for x86 based architectures to intel or att.
<rdar://problem/11319574>
<rdar://problem/9329275>
llvm-svn: 176392
Diffstat (limited to 'lldb')
26 files changed, 528 insertions, 168 deletions
diff --git a/lldb/include/lldb/API/SBFunction.h b/lldb/include/lldb/API/SBFunction.h index e061d1d1bcd..49a3847efbe 100644 --- a/lldb/include/lldb/API/SBFunction.h +++ b/lldb/include/lldb/API/SBFunction.h @@ -41,6 +41,9 @@ public: lldb::SBInstructionList GetInstructions (lldb::SBTarget target); + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target, const char *flavor); + lldb::SBAddress GetStartAddress (); diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h index ddfff277650..0a528a9ac96 100644 --- a/lldb/include/lldb/API/SBSymbol.h +++ b/lldb/include/lldb/API/SBSymbol.h @@ -43,6 +43,9 @@ public: lldb::SBInstructionList GetInstructions (lldb::SBTarget target); + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target, const char *flavor_string); + SBAddress GetStartAddress (); diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 3ea4b3e62d5..7985da218ac 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -744,11 +744,23 @@ public: ReadInstructions (lldb::SBAddress base_addr, uint32_t count); lldb::SBInstructionList + ReadInstructions (lldb::SBAddress base_addr, uint32_t count, const char *flavor_string); + + lldb::SBInstructionList GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size); + // The "WithFlavor" is necessary to keep SWIG from getting confused about overloaded arguments when + // using the buf + size -> Python Object magic. + + lldb::SBInstructionList + GetInstructionsWithFlavor (lldb::SBAddress base_addr, const char *flavor_string, const void *buf, size_t size); + lldb::SBInstructionList GetInstructions (lldb::addr_t base_addr, const void *buf, size_t size); + lldb::SBInstructionList + GetInstructionsWithFlavor (lldb::addr_t base_addr, const char *flavor_string, const void *buf, size_t size); + lldb::SBSymbolContextList FindSymbols (const char *name, lldb::SymbolType type = eSymbolTypeAny); diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 451bff57b56..aa7ceabcc4e 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include <vector> +#include <string> // Other libraries and framework includes // Project includes @@ -51,7 +52,7 @@ public: GetOperands (const ExecutionContext* exe_ctx) { CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); - return m_mnemocics.c_str(); + return m_mnemonics.c_str(); } const char * @@ -137,7 +138,7 @@ private: protected: Opcode m_opcode; // The opcode for this instruction std::string m_opcode_name; - std::string m_mnemocics; + std::string m_mnemonics; std::string m_comment; bool m_calculated_strings; @@ -247,18 +248,28 @@ public: eOptionMarkPCAddress = (1u << 3) // Mark the disassembly line the contains the PC }; + // FindPlugin should be lax about the flavor string (it is too annoying to have various internal uses of the + // disassembler fail because the global 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 *plugin_name); + FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name); + + // This version will use the value in the Target settings if flavor is NULL; + static lldb::DisassemblerSP + FindPluginForTarget(const lldb::TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name); static lldb::DisassemblerSP DisassembleRange (const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &disasm_range); static lldb::DisassemblerSP DisassembleBytes (const ArchSpec &arch, const char *plugin_name, + const char *flavor, const Address &start, const void *bytes, size_t length, @@ -268,6 +279,7 @@ public: Disassemble (Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &range, uint32_t num_instructions, @@ -279,6 +291,7 @@ public: Disassemble (Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const Address &start, uint32_t num_instructions, @@ -290,6 +303,7 @@ public: Disassemble (Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_instructions, @@ -301,6 +315,7 @@ public: Disassemble (Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const ConstString &name, Module *module, @@ -313,16 +328,17 @@ public: Disassemble (Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm); - + //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - Disassembler(const ArchSpec &arch); + Disassembler(const ArchSpec &arch, const char *flavor); virtual ~Disassembler(); typedef const char * (*SummaryCallback)(const Instruction& inst, ExecutionContext *exe_context, void *user_data); @@ -365,6 +381,15 @@ public: { return m_arch; } + + const char * + GetFlavor () const + { + return m_flavor.c_str(); + } + + virtual bool + FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) = 0; protected: //------------------------------------------------------------------ @@ -373,6 +398,7 @@ protected: const ArchSpec m_arch; InstructionList m_instruction_list; lldb::addr_t m_base_addr; + std::string m_flavor; private: //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 79d94a714a8..282a8fa3fde 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -79,6 +79,12 @@ public: void SetDisableSTDIO (bool b); + const char * + GetDisassemblyFlavor() const; + +// void +// SetDisassemblyFlavor(const char *flavor); + InlineStrategy GetInlineStrategy () const; diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index fb246ec29d1..307556a72e0 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -381,6 +381,7 @@ namespace lldb { eArgTypeCommandName, eArgTypeCount, eArgTypeDirectoryName, + eArgTypeDisassemblyFlavor, eArgTypeEndAddress, eArgTypeExpression, eArgTypeExpressionPath, diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h index 6ace910c574..25b71e6efff 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -17,7 +17,7 @@ namespace lldb_private { typedef lldb::ABISP (*ABICreateInstance) (const ArchSpec &arch); - typedef Disassembler* (*DisassemblerCreateInstance) (const ArchSpec &arch); + typedef Disassembler* (*DisassemblerCreateInstance) (const ArchSpec &arch, const char *flavor); typedef DynamicLoader* (*DynamicLoaderCreateInstance) (Process* process, bool force); typedef ObjectContainer* (*ObjectContainerCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t offset, lldb::offset_t length); typedef ObjectFile* (*ObjectFileCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec* file, lldb::offset_t file_offset, lldb::offset_t length); diff --git a/lldb/scripts/Python/interface/SBFunction.i b/lldb/scripts/Python/interface/SBFunction.i index 8eee92f28d5..0b4d1f2cbb4 100644 --- a/lldb/scripts/Python/interface/SBFunction.i +++ b/lldb/scripts/Python/interface/SBFunction.i @@ -65,6 +65,9 @@ public: lldb::SBInstructionList GetInstructions (lldb::SBTarget target); + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target, const char *flavor); + lldb::SBAddress GetStartAddress (); diff --git a/lldb/scripts/Python/interface/SBSymbol.i b/lldb/scripts/Python/interface/SBSymbol.i index a3656972469..a2cec0ec73e 100644 --- a/lldb/scripts/Python/interface/SBSymbol.i +++ b/lldb/scripts/Python/interface/SBSymbol.i @@ -38,6 +38,9 @@ public: lldb::SBInstructionList GetInstructions (lldb::SBTarget target); + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target, const char *flavor_string); + SBAddress GetStartAddress (); diff --git a/lldb/scripts/Python/interface/SBTarget.i b/lldb/scripts/Python/interface/SBTarget.i index c4fe24be4d5..4e3161eedf9 100644 --- a/lldb/scripts/Python/interface/SBTarget.i +++ b/lldb/scripts/Python/interface/SBTarget.i @@ -704,8 +704,14 @@ public: ReadInstructions (lldb::SBAddress base_addr, uint32_t count); lldb::SBInstructionList + ReadInstructions (lldb::SBAddress base_addr, uint32_t count, const char *flavor_string); + + lldb::SBInstructionList GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size); + lldb::SBInstructionList + GetInstructionsWithFlavor (lldb::SBAddress base_addr, const char *flavor_string, const void *buf, size_t size); + lldb::SBSymbolContextList FindSymbols (const char *name, lldb::SymbolType type = eSymbolTypeAny); diff --git a/lldb/source/API/SBFunction.cpp b/lldb/source/API/SBFunction.cpp index 028725cbae2..3617c0e5a4c 100644 --- a/lldb/source/API/SBFunction.cpp +++ b/lldb/source/API/SBFunction.cpp @@ -122,6 +122,12 @@ SBFunction::GetDescription (SBStream &s) SBInstructionList SBFunction::GetInstructions (SBTarget target) { + return GetInstructions (target, NULL); +} + +SBInstructionList +SBFunction::GetInstructions (SBTarget target, const char *flavor) +{ SBInstructionList sb_instructions; if (m_opaque_ptr) { @@ -139,6 +145,7 @@ SBFunction::GetInstructions (SBTarget target) { sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture(), NULL, + flavor, exe_ctx, m_opaque_ptr->GetAddressRange())); } diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp index 3fd06f84eb1..580ef93c4be 100644 --- a/lldb/source/API/SBSymbol.cpp +++ b/lldb/source/API/SBSymbol.cpp @@ -113,11 +113,15 @@ SBSymbol::GetDescription (SBStream &description) return true; } - - SBInstructionList SBSymbol::GetInstructions (SBTarget target) { + return GetInstructions (target, NULL); +} + +SBInstructionList +SBSymbol::GetInstructions (SBTarget target, const char *flavor_string) +{ SBInstructionList sb_instructions; if (m_opaque_ptr) { @@ -137,6 +141,7 @@ SBSymbol::GetInstructions (SBTarget target) AddressRange symbol_range (m_opaque_ptr->GetAddress(), m_opaque_ptr->GetByteSize()); sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture (), NULL, + flavor_string, exe_ctx, symbol_range)); } diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index c41051ff327..739cb4c82ae 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -2250,6 +2250,12 @@ SBTarget::GetSourceManager() lldb::SBInstructionList SBTarget::ReadInstructions (lldb::SBAddress base_addr, uint32_t count) { + return ReadInstructions (base_addr, count, NULL); +} + +lldb::SBInstructionList +SBTarget::ReadInstructions (lldb::SBAddress base_addr, uint32_t count, const char *flavor_string) +{ SBInstructionList sb_instructions; TargetSP target_sp(GetSP()); @@ -2265,6 +2271,7 @@ SBTarget::ReadInstructions (lldb::SBAddress base_addr, uint32_t count) const size_t bytes_read = target_sp->ReadMemory(*addr_ptr, prefer_file_cache, data.GetBytes(), data.GetByteSize(), error); sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(), NULL, + flavor_string, *addr_ptr, data.GetBytes(), bytes_read, @@ -2279,6 +2286,12 @@ SBTarget::ReadInstructions (lldb::SBAddress base_addr, uint32_t count) lldb::SBInstructionList SBTarget::GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size) { + return GetInstructionsWithFlavor (base_addr, NULL, buf, size); +} + +lldb::SBInstructionList +SBTarget::GetInstructionsWithFlavor (lldb::SBAddress base_addr, const char *flavor_string, const void *buf, size_t size) +{ SBInstructionList sb_instructions; TargetSP target_sp(GetSP()); @@ -2291,6 +2304,7 @@ SBTarget::GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t si sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(), NULL, + flavor_string, addr, buf, size)); @@ -2302,7 +2316,13 @@ SBTarget::GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t si lldb::SBInstructionList SBTarget::GetInstructions (lldb::addr_t base_addr, const void *buf, size_t size) { - return GetInstructions (ResolveLoadAddress(base_addr), buf, size); + return GetInstructionsWithFlavor (ResolveLoadAddress(base_addr), NULL, buf, size); +} + +lldb::SBInstructionList +SBTarget::GetInstructionsWithFlavor (lldb::addr_t base_addr, const char *flavor_string, const void *buf, size_t size) +{ + return GetInstructionsWithFlavor (ResolveLoadAddress(base_addr), flavor_string, buf, size); } SBError diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index 8478541828c..7a4d1e727c0 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -46,6 +46,7 @@ CommandObjectDisassemble::CommandOptions::CommandOptions (CommandInterpreter &in at_pc (false), frame_line (false), plugin_name (), + flavor_string(), arch(), some_location_specified (false) { @@ -125,6 +126,18 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (uint32_t option_idx, c plugin_name.assign (option_arg); break; + case 'F': + { + Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); + if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 + || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) + { + flavor_string.assign (option_arg); + } + else + error.SetErrorStringWithFormat("Disassembler flavors are currently only supported for x86 and x86_64 targets."); + break; + } case 'r': raw = true; break; @@ -162,6 +175,26 @@ CommandObjectDisassemble::CommandOptions::OptionParsingStarting () end_addr = LLDB_INVALID_ADDRESS; raw = false; plugin_name.clear(); + + Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); + + // 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) + { + if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 + || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64) + { + flavor_string.assign(target->GetDisassemblyFlavor()); + } + else + flavor_string.assign ("default"); + + } + else + flavor_string.assign("default"); + arch.Clear(); some_location_specified = false; } @@ -189,6 +222,9 @@ CommandObjectDisassemble::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "mixed" , 'm', no_argument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."}, { LLDB_OPT_SET_ALL, false, "raw" , 'r', no_argument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."}, { LLDB_OPT_SET_ALL, false, "plugin" , 'P', required_argument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."}, +{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', required_argument , NULL, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " + "Currently the only valid options are default, and for Intel" + " architectures, att and intel."}, { LLDB_OPT_SET_ALL, false, "arch" , 'a', required_argument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."}, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2 , true , "start-address", 's', required_argument , NULL, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."}, @@ -245,20 +281,26 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) } const char *plugin_name = m_options.GetPluginName (); - DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, plugin_name); + const char *flavor_string = m_options.GetFlavorString(); + + DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name); if (!disassembler) { if (plugin_name) - result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", + { + result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n", plugin_name, m_options.arch.GetArchitectureName()); + } else result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n", m_options.arch.GetArchitectureName()); result.SetStatus (eReturnStatusFailed); return false; } + else if (flavor_string != NULL && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string)) + result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string); result.SetStatus (eReturnStatusSuccessFinishResult); @@ -293,6 +335,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) if (Disassembler::Disassemble (m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, name, NULL, // Module * @@ -413,6 +456,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) if (Disassembler::Disassemble (m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, range.GetBaseAddress(), m_options.num_instructions, @@ -459,6 +503,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) if (Disassembler::Disassemble (m_interpreter.GetDebugger(), m_options.arch, plugin_name, + flavor_string, m_exe_ctx, range, m_options.num_instructions, diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h index 2433c1de1a5..693b5244c72 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.h +++ b/lldb/source/Commands/CommandObjectDisassemble.h @@ -53,6 +53,14 @@ public: return plugin_name.c_str(); } + const char * + GetFlavorString () + { + if (flavor_string.empty() || flavor_string == "default") + return NULL; + return flavor_string.c_str(); + } + virtual Error OptionParsingFinished (); @@ -68,6 +76,7 @@ public: bool at_pc; bool frame_line; std::string plugin_name; + std::string flavor_string; ArchSpec arch; bool some_location_specified; // If no location was specified, we'll select "at_pc". This should be set // in SetOptionValue if anything the selects a location is set. diff --git a/lldb/source/Core/DataExtractor.cpp b/lldb/source/Core/DataExtractor.cpp index bc4b47b795c..22bd612c9b5 100644 --- a/lldb/source/Core/DataExtractor.cpp +++ b/lldb/source/Core/DataExtractor.cpp @@ -1332,7 +1332,7 @@ DataExtractor::Dump (Stream *s, target_sp = exe_scope->CalculateTarget(); if (target_sp) { - DisassemblerSP disassembler_sp (Disassembler::FindPlugin(target_sp->GetArchitecture(), NULL)); + DisassemblerSP disassembler_sp (Disassembler::FindPlugin(target_sp->GetArchitecture(), NULL, NULL)); if (disassembler_sp) { lldb::addr_t addr = base_addr + start_offset; diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index b74238c65e6..8bbd8b51b2a 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -45,7 +45,7 @@ using namespace lldb_private; DisassemblerSP -Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name) +Disassembler::FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name) { Timer scoped_timer (__PRETTY_FUNCTION__, "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", @@ -59,7 +59,7 @@ Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name) create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (plugin_name); if (create_callback) { - DisassemblerSP disassembler_sp(create_callback(arch)); + DisassemblerSP disassembler_sp(create_callback(arch, flavor)); if (disassembler_sp.get()) return disassembler_sp; @@ -69,7 +69,7 @@ Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name) { for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx) { - DisassemblerSP disassembler_sp(create_callback(arch)); + DisassemblerSP disassembler_sp(create_callback(arch, flavor)); if (disassembler_sp.get()) return disassembler_sp; @@ -78,6 +78,20 @@ Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name) return DisassemblerSP(); } +DisassemblerSP +Disassembler::FindPluginForTarget(const TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name) +{ + if (target_sp && flavor == NULL) + { + // 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, + if (arch.GetTriple().getArch() == llvm::Triple::x86 + || arch.GetTriple().getArch() == llvm::Triple::x86_64) + flavor = target_sp->GetDisassemblyFlavor(); + } + return FindPlugin(arch, flavor, plugin_name); +} + static void ResolveAddress (const ExecutionContext &exe_ctx, @@ -114,6 +128,7 @@ Disassembler::Disassemble Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_instructions, @@ -137,6 +152,7 @@ Disassembler::Disassemble if (Disassemble (debugger, arch, plugin_name, + flavor, exe_ctx, range, num_instructions, @@ -158,6 +174,7 @@ Disassembler::Disassemble Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const ConstString &name, Module *module, @@ -204,6 +221,7 @@ Disassembler::Disassemble return Disassemble (debugger, arch, plugin_name, + flavor, exe_ctx, sc_list, num_instructions, @@ -220,6 +238,7 @@ Disassembler::DisassembleRange ( const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &range ) @@ -227,7 +246,7 @@ Disassembler::DisassembleRange lldb::DisassemblerSP disasm_sp; if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) { - disasm_sp = Disassembler::FindPlugin(arch, plugin_name); + disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name); if (disasm_sp) { @@ -244,6 +263,7 @@ Disassembler::DisassembleBytes ( const ArchSpec &arch, const char *plugin_name, + const char *flavor, const Address &start, const void *bytes, size_t length, @@ -254,7 +274,7 @@ Disassembler::DisassembleBytes if (bytes) { - disasm_sp = Disassembler::FindPlugin(arch, plugin_name); + disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); if (disasm_sp) { @@ -278,6 +298,7 @@ Disassembler::Disassemble Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const AddressRange &disasm_range, uint32_t num_instructions, @@ -288,7 +309,7 @@ Disassembler::Disassemble { if (disasm_range.GetByteSize()) { - lldb::DisassemblerSP disasm_sp (Disassembler::FindPlugin(arch, plugin_name)); + lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); if (disasm_sp.get()) { @@ -319,6 +340,7 @@ Disassembler::Disassemble Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, const Address &start_address, uint32_t num_instructions, @@ -329,7 +351,7 @@ Disassembler::Disassemble { if (num_instructions > 0) { - lldb::DisassemblerSP disasm_sp (Disassembler::FindPlugin(arch, plugin_name)); + lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); if (disasm_sp.get()) { Address addr; @@ -473,6 +495,7 @@ Disassembler::Disassemble Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, uint32_t num_instructions, uint32_t num_mixed_context_lines, @@ -506,6 +529,7 @@ Disassembler::Disassemble return Disassemble (debugger, arch, plugin_name, + flavor, exe_ctx, range, num_instructions, @@ -594,7 +618,7 @@ Instruction::Dump (lldb_private::Stream *s, ss.PutCString (m_opcode_name.c_str()); ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' '); - ss.PutCString (m_mnemocics.c_str()); + ss.PutCString (m_mnemonics.c_str()); if (!m_comment.empty()) { @@ -1121,12 +1145,16 @@ Disassembler::ParseInstructions //---------------------------------------------------------------------- // Disassembler copy constructor //---------------------------------------------------------------------- -Disassembler::Disassembler(const ArchSpec& arch) : +Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) : m_arch (arch), m_instruction_list(), - m_base_addr(LLDB_INVALID_ADDRESS) + m_base_addr(LLDB_INVALID_ADDRESS), + m_flavor () { - + if (flavor == NULL) + m_flavor.assign("default"); + else + m_flavor.assign(flavor); } //---------------------------------------------------------------------- diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 1d86c9161b6..af2e1d0ea38 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -798,7 +798,9 @@ ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &ex ArchSpec arch(target->GetArchitecture()); - lldb::DisassemblerSP disassembler = Disassembler::FindPlugin(arch, NULL); + const char *plugin_name = NULL; + const char *flavor_string = NULL; + lldb::DisassemblerSP disassembler = Disassembler::FindPlugin(arch, flavor_string, plugin_name); if (!disassembler) { diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 36b2d7a075f..96e0ef92316 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -1029,6 +1029,7 @@ CommandObject::g_arguments_data[] = { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." }, { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { NULL, false }, "A directory name." }, + { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { NULL, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" }, { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL }, diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index ec715293bd1..440d52618dd 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -10,7 +10,20 @@ #include "DisassemblerLLVMC.h" #include "llvm-c/Disassembler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/ADT/SmallString.h" + #include "lldb/Core/Address.h" #include "lldb/Core/DataExtractor.h" @@ -113,19 +126,20 @@ public: } if (!got_op) { - ::LLVMDisasmContextRef disasm_context = m_disasm.m_disasm_context; + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = m_disasm.m_disasm_ap.get(); bool is_altnernate_isa = false; - if (m_disasm.m_alternate_disasm_context) + if (m_disasm.m_alternate_disasm_ap.get() != NULL) { const AddressClass address_class = GetAddressClass (); if (address_class == eAddressClassCodeAlternateISA) { - disasm_context = m_disasm.m_alternate_disasm_context; + mc_disasm_ptr = m_disasm.m_alternate_disasm_ap.get(); is_altnernate_isa = true; } } + const llvm::Triple::ArchType machine = arch.GetMachine(); if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { @@ -155,19 +169,16 @@ public: { // The opcode isn't evenly sized, so we need to actually use the llvm // disassembler to parse it and get the size. - char out_string[512]; m_disasm.Lock(this, NULL); uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1)); const size_t opcode_data_len = data.GetByteSize() - data_offset; const addr_t pc = m_address.GetFileAddress(); - const size_t inst_size = ::LLVMDisasmInstruction (disasm_context, - opcode_data, - opcode_data_len, - pc, // PC value - out_string, - sizeof(out_string)); - // The address lookup function could have caused us to fill in our comment - m_comment.clear(); + llvm::MCInst inst; + + const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, + opcode_data_len, + pc, + inst); m_disasm.Unlock(); if (inst_size == 0) m_opcode.Clear(); @@ -203,12 +214,12 @@ public: { char out_string[512]; - ::LLVMDisasmContextRef disasm_context; + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; if (address_class == eAddressClassCodeAlternateISA) - disasm_context = m_disasm.m_alternate_disasm_context; + mc_disasm_ptr = m_disasm.m_alternate_disasm_ap.get(); else - disasm_context = m_disasm.m_disasm_context; + mc_disasm_ptr = m_disasm.m_disasm_ap.get(); lldb::addr_t pc = LLDB_INVALID_ADDRESS; @@ -223,14 +234,17 @@ public: pc = m_address.GetFileAddress(); m_disasm.Lock(this, exe_ctx); + uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1)); const size_t opcode_data_len = data.GetByteSize(); - size_t inst_size = ::LLVMDisasmInstruction (disasm_context, - opcode_data, + llvm::MCInst inst; + size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, - out_string, - sizeof(out_string)); + inst); + + if (inst_size > 0) + mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); m_disasm.Unlock(); @@ -290,17 +304,19 @@ public: } break; } - m_mnemocics.swap(mnemonic_strm.GetString()); + m_mnemonics.swap(mnemonic_strm.GetString()); return; } else { if (m_does_branch == eLazyBoolCalculate) { - if (StringRepresentsBranch (out_string, strlen(out_string))) + bool can_branch = mc_disasm_ptr->CanBranch(inst); + if (can_branch) m_does_branch = eLazyBoolYes; else m_does_branch = eLazyBoolNo; + } } @@ -317,7 +333,7 @@ public: if (matches[1].rm_so != -1) m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); if (matches[2].rm_so != -1) - m_mnemocics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); + m_mnemonics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); } } } @@ -335,88 +351,6 @@ public: } protected: - bool StringRepresentsBranch (const char *data, size_t size) - { - const char *cursor = data; - - bool inWhitespace = true; - - while (inWhitespace && cursor < data + size) - { - switch (*cursor) - { - default: - inWhitespace = false; - break; - case ' ': - break; - case '\t': - break; - } - - if (inWhitespace) - ++cursor; - } - - if (cursor >= data + size) - return false; - - llvm::Triple::ArchType arch = m_disasm.GetArchitecture().GetMachine(); - - switch (arch) - { - default: - return false; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - switch (cursor[0]) - { - default: - return false; - case 'j': - return true; - case 'c': - if (cursor[1] == 'a' && - cursor[2] == 'l' && - cursor[3] == 'l') - return true; - else - return false; - } - case llvm::Triple::arm: - case llvm::Triple::thumb: - switch (cursor[0]) - { - default: - return false; - case 'b': - { - switch (cursor[1]) - { - default: - return true; - case 'f': - case 'i': - case 'k': - return false; - } - } - case 'c': - { - switch (cursor[1]) - { - default: - return false; - case 'b': - return true; - } - } - } - } - - return false; - } - bool m_is_valid; DisassemblerLLVMC &m_disasm; DisassemblerSP m_disasm_sp; // for ownership @@ -429,12 +363,159 @@ protected: bool InstructionLLVMC::s_regex_compiled = false; ::regex_t InstructionLLVMC::s_regex; +DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner): + m_is_valid(true) +{ + std::string Error; + const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error); + if (!curr_target) + { + m_is_valid = false; + return; + } + + m_instr_info_ap.reset(curr_target->createMCInstrInfo()); + m_reg_info_ap.reset (curr_target->createMCRegInfo(triple)); + + std::string features_str; + + m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "", + features_str)); + + m_asm_info_ap.reset(curr_target->createMCAsmInfo(triple)); + + if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL) + { + m_is_valid = NULL; + return; + } + + m_context_ap.reset(new llvm::MCContext(*m_asm_info_ap.get(), *(m_reg_info_ap.get()), 0)); + + m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get())); + if (m_disasm_ap.get()) + { + m_disasm_ap->setupForSymbolicDisassembly(NULL, + DisassemblerLLVMC::SymbolLookupCallback, + (void *) &owner, + m_context_ap.get()); + + unsigned asm_printer_variant; + if (flavor == ~0U) + asm_printer_variant = m_asm_info_ap->getAssemblerDialect(); + else + { + asm_printer_variant = flavor; + } + + m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant, + *m_asm_info_ap.get(), + *m_instr_info_ap.get(), + *m_reg_info_ap.get(), + *m_subtarget_info_ap.get())); + if (m_instr_printer_ap.get() == NULL) + { + m_disasm_ap.reset(); + m_is_valid = false; + } + } + else + m_is_valid = false; +} + +namespace { + // This is the memory object we use in GetInstruction. + class LLDBDisasmMemoryObject : public llvm::MemoryObject { + uint8_t *m_bytes; + uint64_t m_size; + uint64_t m_base_PC; + public: + LLDBDisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) : + m_bytes(bytes), m_size(size), m_base_PC(basePC) {} + + uint64_t getBase() const { return m_base_PC; } + uint64_t getExtent() const { return m_size; } + + int readByte(uint64_t addr, uint8_t *byte) const { + if (addr - m_base_PC >= m_size) + return -1; + *byte = m_bytes[addr - m_base_PC]; + return 0; + } + }; +} // End Anonymous Namespace + +uint64_t +DisassemblerLLVMC::LLVMCDisassembler::GetMCInst ( + uint8_t *opcode_data, + size_t opcode_data_len, + lldb::addr_t pc, + llvm::MCInst &mc_inst) +{ + LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc); + llvm::MCInst inst; + llvm::MCDisassembler::DecodeStatus status; + + uint64_t new_inst_size; + status = m_disasm_ap->getInstruction(mc_inst, + new_inst_size, + memory_object, + pc, + llvm::nulls(), + llvm::nulls()); + if (status == llvm::MCDisassembler::Success) + return new_inst_size; + else + return 0; +} + +uint64_t +DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len) +{ + llvm::StringRef unused_annotations; + llvm::SmallString<64> inst_string; + llvm::raw_svector_ostream inst_stream(inst_string); + m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations); + inst_stream.flush(); + + size_t output_size = std::min(out_buffer_len -1, inst_string.size()); + std::memcpy(output_buffer, inst_string.data(), output_size); + output_buffer[output_size] = '\0'; + + return output_size; +} + +bool +DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst) +{ + return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get()); +} + +bool +DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) +{ + llvm::Triple triple = arch.GetTriple(); + if (flavor == NULL || strcmp (flavor, "default") == 0) + return true; + + if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) + { + if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) + return true; + else + return false; + } + else + return false; +} + + Disassembler * -DisassemblerLLVMC::CreateInstance (const ArchSpec &arch) +DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor) { if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) { - std::auto_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch)); + std::auto_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor)); if (disasm_ap.get() && disasm_ap->IsValid()) return disasm_ap.release(); @@ -442,18 +523,41 @@ DisassemblerLLVMC::CreateInstance (const ArchSpec &arch) return NULL; } -DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch) : - Disassembler(arch), +DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) : + Disassembler(arch, flavor_string), m_exe_ctx (NULL), - m_inst (NULL), - m_disasm_context (NULL), - m_alternate_disasm_context (NULL) + m_inst (NULL) { - m_disasm_context = ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), - (void*)this, - /*TagType=*/1, - NULL, - DisassemblerLLVMC::SymbolLookupCallback); + if (!FlavorValidForArchSpec (arch, m_flavor.c_str())) + { + m_flavor.assign("default"); + } + + const char *triple = arch.GetTriple().getTriple().c_str(); + unsigned flavor = ~0U; + + // So far the only supported flavor is "intel" on x86. The base class will set this + // correctly coming in. + if (arch.GetTriple().getArch() == llvm::Triple::x86 + || arch.GetTriple().getArch() == llvm::Triple::x86_64) + { + if (m_flavor == "intel") + { + flavor = 1; + } + else if (m_flavor == "att") + { + flavor = 0; + } + } + + m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this)); + if (!m_disasm_ap->IsValid()) + { + // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason, + // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used. + m_disasm_ap.reset(); + } if (arch.GetTriple().getArch() == llvm::Triple::arm) { @@ -461,26 +565,17 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch) : thumb_arch.GetTriple().setArchName(llvm::StringRef("thumbv7")); std::string thumb_triple(thumb_arch.GetTriple().getTriple()); - m_alternate_disasm_context = ::LLVMCreateDisasm(thumb_triple.c_str(), - (void*)this, - /*TagType=*/1, - NULL, - DisassemblerLLVMC::SymbolLookupCallback); + m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this)); + if (!m_alternate_disasm_ap->IsValid()) + { + m_disasm_ap.reset(); + m_alternate_disasm_ap.reset(); + } } } DisassemblerLLVMC::~DisassemblerLLVMC() { - if (m_disasm_context) - { - ::LLVMDisasmDispose(m_disasm_context); - m_disasm_context = NULL; - } - if (m_alternate_disasm_context) - { - ::LLVMDisasmDispose(m_alternate_disasm_context); - m_alternate_disasm_context = NULL; - } } size_t @@ -506,7 +601,7 @@ DisassemblerLLVMC::DecodeInstructions (const Address &base_addr, AddressClass address_class = eAddressClassCode; - if (m_alternate_disasm_context) + if (m_alternate_disasm_ap.get() != NULL) address_class = inst_addr.GetAddressClass (); InstructionSP inst_sp(new InstructionLLVMC(*this, diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h index c6c3e6652bb..d551c6869ff 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -10,9 +10,23 @@ #ifndef liblldb_DisassemblerLLVMC_h_ #define liblldb_DisassemblerLLVMC_h_ +#include <string> #include "llvm-c/Disassembler.h" +// Opaque references to C++ Objects in LLVM's MC. +namespace llvm +{ + class MCContext; + class MCInst; + class MCInstrInfo; + class MCRegisterInfo; + class MCDisassembler; + class MCInstPrinter; + class MCAsmInfo; + class MCSubtargetInfo; +} + #include "lldb/Core/Address.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/PluginManager.h" @@ -22,6 +36,34 @@ class InstructionLLVMC; class DisassemblerLLVMC : public lldb_private::Disassembler { + // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB), and there's a bit of goo to set up and own + // in the MC disassembler world, I added this class to manage the actual disassemblers. + class LLVMCDisassembler + { + public: + LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner); + + ~LLVMCDisassembler() {}; + + uint64_t GetMCInst (uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst); + uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len); + bool CanBranch (llvm::MCInst &mc_inst); + bool IsValid() + { + return m_is_valid; + } + + private: + bool m_is_valid; + std::auto_ptr<llvm::MCContext> m_context_ap; + std::auto_ptr<llvm::MCAsmInfo> m_asm_info_ap; + std::auto_ptr<llvm::MCSubtargetInfo> m_subtarget_info_ap; + std::auto_ptr<llvm::MCInstrInfo> m_instr_info_ap; + std::auto_ptr<llvm::MCRegisterInfo> m_reg_info_ap; + std::auto_ptr<llvm::MCInstPrinter> m_instr_printer_ap; + std::auto_ptr<llvm::MCDisassembler> m_disasm_ap; + }; + public: //------------------------------------------------------------------ // Static Functions @@ -39,10 +81,9 @@ public: GetPluginDescriptionStatic(); static lldb_private::Disassembler * - CreateInstance(const lldb_private::ArchSpec &arch); - - - DisassemblerLLVMC(const lldb_private::ArchSpec &arch); + CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor); + + DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); virtual ~DisassemblerLLVMC(); @@ -69,10 +110,13 @@ public: protected: friend class InstructionLLVMC; + virtual bool + FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor); + bool IsValid() { - return (m_disasm_context != NULL); + return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid()); } int OpInfo(uint64_t PC, @@ -117,8 +161,9 @@ protected: const lldb_private::ExecutionContext *m_exe_ctx; InstructionLLVMC *m_inst; lldb_private::Mutex m_mutex; - ::LLVMDisasmContextRef m_disasm_context; - ::LLVMDisasmContextRef m_alternate_disasm_context; + + std::auto_ptr<LLVMCDisassembler> m_disasm_ap; + std::auto_ptr<LLVMCDisassembler> m_alternate_disasm_ap; }; #endif // liblldb_DisassemblerLLVM_h_ diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 004d6b5fe7e..8f9217231f4 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -55,6 +55,7 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& thread.CalculateExecutionContext(exe_ctx); DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch, NULL, + NULL, exe_ctx, range)); diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index ad98c5fff99..b5992840ed8 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -266,9 +266,12 @@ StackFrame::Disassemble () Target *target = exe_ctx.GetTargetPtr(); if (target) { + const char *plugin_name = NULL; + const char *flavor = NULL; Disassembler::Disassemble (target->GetDebugger(), target->GetArchitecture(), - NULL, + plugin_name, + flavor, exe_ctx, 0, 0, @@ -1426,9 +1429,12 @@ StackFrame::GetStatus (Stream& strm, AddressRange pc_range; pc_range.GetBaseAddress() = GetFrameCodeAddress(); pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize()); + const char *plugin_name = NULL; + const char *flavor = NULL; Disassembler::Disassemble (target->GetDebugger(), target_arch, - NULL, + plugin_name, + flavor, exe_ctx, pc_range, disasm_lines, diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index ef9f469f730..1cc48dcc665 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -2210,6 +2210,22 @@ g_inline_breakpoint_enums[] = { 0, NULL, NULL } }; +typedef enum x86DisassemblyFlavor +{ + eX86DisFlavorDefault, + eX86DisFlavorIntel, + eX86DisFlavorATT +} x86DisassemblyFlavor; + +static OptionEnumValueElement +g_x86_dis_flavor_value_types[] = +{ + { eX86DisFlavorDefault, "default", "Disassembler default (currently att)."}, + { eX86DisFlavorIntel, "intel", "Intel disassembler flavor."}, + { eX86DisFlavorATT, "att", "AT&T disassembler flavor."}, + { 0, NULL, NULL } +}; + static PropertyDefinition g_properties[] = { @@ -2243,6 +2259,8 @@ g_properties[] = "Always checking for inlined breakpoint locations can be expensive (memory and time), so we try to minimize the " "times we look for inlined locations. This setting allows you to control exactly which strategy is used when settings " "file and line breakpoints." }, + // FIXME: This is the wrong way to do per-architecture settings, but we don't have a general per architecture settings system in place yet. + { "x86-disassembly-flavor" , OptionValue::eTypeEnum , false, eX86DisFlavorDefault, NULL, g_x86_dis_flavor_value_types, "The default disassembly flavor to use for x86 or x86-64 targets." }, { NULL , OptionValue::eTypeInvalid , false, 0 , NULL, NULL, NULL } }; enum @@ -2266,7 +2284,8 @@ enum ePropertyErrorPath, ePropertyDisableASLR, ePropertyDisableSTDIO, - ePropertyInlineStrategy + ePropertyInlineStrategy, + ePropertyDisassemblyFlavor }; @@ -2442,6 +2461,17 @@ TargetProperties::SetDisableSTDIO (bool b) m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); } +const char * +TargetProperties::GetDisassemblyFlavor () const +{ + const uint32_t idx = ePropertyDisassemblyFlavor; + const char *return_value; + + x86DisassemblyFlavor flavor_value = (x86DisassemblyFlavor) m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value); + return_value = g_x86_dis_flavor_value_types[flavor_value].string_value; + return return_value; +} + InlineStrategy TargetProperties::GetInlineStrategy () const { diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 0137e8b865d..912e08769c8 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -265,8 +265,11 @@ ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_ { //Disassemble the address range given: ExecutionContext exe_ctx (m_thread.GetProcess()); + const char *plugin_name = NULL; + const char *flavor = NULL; m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), - NULL, + plugin_name, + flavor, exe_ctx, m_address_ranges[i]); diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp index a9c6c80881a..8249bb3a9c6 100644 --- a/lldb/source/Target/ThreadPlanTracer.cpp +++ b/lldb/source/Target/ThreadPlanTracer.cpp @@ -120,7 +120,7 @@ Disassembler * ThreadPlanAssemblyTracer::GetDisassembler () { if (m_disassembler_sp.get() == NULL) - m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), NULL); + m_disassembler_sp = Disassembler::FindPlugin(m_thread.GetProcess()->GetTarget().GetArchitecture(), NULL, NULL); return m_disassembler_sp.get(); } |

