diff options
author | Hans Wennborg <hans@hanshq.net> | 2015-07-16 15:58:25 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2015-07-16 15:58:25 +0000 |
commit | 1abd7241f9116c249c4c11867a1580be94058fdf (patch) | |
tree | f9386411753cebf9708b3d760571d9988efaffe8 | |
parent | 13393862c4b0ea054df648e3feb7867ccdb05661 (diff) |
Merging r242381:
------------------------------------------------------------------------
r242381 | jaydeep | 2015-07-15 20:51:55 -0700 (Wed, 15 Jul 2015) | 10 lines
[LLDB][MIPS] Detect MIPS application specific extensions like micromips
SUMMARY:
The patch detects MIPS application specific extensions (ASE) like micromips by reading
ELF header.e_flags and SHT_MIPS_ABIFLAGS section. MIPS triple does not contain ASE
information like micromips, mips16, DSP, MSA etc. These can be read from header.e_flags
or SHT_MIPS_ABIFLAGS section.
Reviewers: clayborg
Subscribers: mohit.bhakkad, sagar, lldb-commits
Differential Revision: http://reviews.llvm.org/D11133
------------------------------------------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/lldb/branches/release_37@242411 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/lldb/Core/ArchSpec.h | 38 | ||||
-rw-r--r-- | source/Core/ArchSpec.cpp | 57 | ||||
-rw-r--r-- | source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp | 25 | ||||
-rw-r--r-- | source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h | 2 | ||||
-rw-r--r-- | source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp | 15 | ||||
-rw-r--r-- | source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp | 15 | ||||
-rw-r--r-- | source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 35 |
7 files changed, 153 insertions, 34 deletions
diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 0cadd8d8d..0b818a0c7 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -48,7 +48,26 @@ public: eMIPSSubType_mips64r2el, eMIPSSubType_mips64r6el, }; - + + // Masks for the ases word of an ABI flags structure. + enum MIPSASE + { + eMIPSAse_dsp = 0x00000001, // DSP ASE + eMIPSAse_dspr2 = 0x00000002, // DSP R2 ASE + eMIPSAse_eva = 0x00000004, // Enhanced VA Scheme + eMIPSAse_mcu = 0x00000008, // MCU (MicroController) ASE + eMIPSAse_mdmx = 0x00000010, // MDMX ASE + eMIPSAse_mips3d = 0x00000020, // MIPS-3D ASE + eMIPSAse_mt = 0x00000040, // MT ASE + eMIPSAse_smartmips = 0x00000080, // SmartMIPS ASE + eMIPSAse_virt = 0x00000100, // VZ ASE + eMIPSAse_msa = 0x00000200, // MSA ASE + eMIPSAse_mips16 = 0x00000400, // MIPS16 ASE + eMIPSAse_micromips = 0x00000800, // MICROMIPS ASE + eMIPSAse_xpa = 0x00001000, // XPA ASE + eMIPSAse_mask = 0x00001fff + }; + enum Core { eCore_arm_generic, @@ -546,6 +565,18 @@ public: StopInfoOverrideCallbackType GetStopInfoOverrideCallback () const; + uint32_t + GetFlags () const + { + return m_flags; + } + + void + SetFlags (uint32_t flags) + { + m_flags = flags; + } + protected: bool IsEqualTo (const ArchSpec& rhs, bool exact_match) const; @@ -554,6 +585,11 @@ protected: Core m_core; lldb::ByteOrder m_byte_order; + // Additional arch flags which we cannot get from triple and core + // For MIPS these are application specific extensions like + // micromips, mips16 etc. + uint32_t m_flags; + ConstString m_distribution_id; // Called when m_def or m_entry are changed. Fills in all remaining diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index 363443077..2dc001a90 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -90,28 +90,28 @@ static const CoreDefinition g_core_definitions[] = { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_aarch64 , "aarch64" }, // mips32, mips32r2, mips32r3, mips32r5, mips32r6 - { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32 , "mips" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r2 , "mipsr2" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r3 , "mipsr3" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r5 , "mipsr5" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r6 , "mipsr6" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32el , "mipsel" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r2el , "mipsr2el" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r3el , "mipsr3el" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r5el , "mipsr5el" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r6el , "mipsr6el" }, + { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32 , "mips" }, + { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r2 , "mipsr2" }, + { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r3 , "mipsr3" }, + { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r5 , "mipsr5" }, + { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r6 , "mipsr6" }, + { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32el , "mipsel" }, + { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r2el , "mipsr2el" }, + { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r3el , "mipsr3el" }, + { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r5el , "mipsr5el" }, + { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r6el , "mipsr6el" }, // mips64, mips64r2, mips64r3, mips64r5, mips64r6 - { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" }, - { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r2 , "mips64r2" }, - { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r3 , "mips64r3" }, - { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r5 , "mips64r5" }, - { eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r6 , "mips64r6" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64el , "mips64el" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r2el , "mips64r2el" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r3el , "mips64r3el" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r5el , "mips64r5el" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r6el , "mips64r6el" }, + { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" }, + { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r2 , "mips64r2" }, + { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r3 , "mips64r3" }, + { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r5 , "mips64r5" }, + { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r6 , "mips64r6" }, + { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64el , "mips64el" }, + { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r2el , "mips64r2el" }, + { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r3el , "mips64r3el" }, + { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r5el , "mips64r5el" }, + { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r6el , "mips64r6el" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "powerpc" }, { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc601 , "ppc601" }, @@ -419,7 +419,8 @@ ArchSpec::ArchSpec() : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id () + m_distribution_id (), + m_flags (0) { } @@ -427,7 +428,8 @@ ArchSpec::ArchSpec (const char *triple_cstr, Platform *platform) : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id () + m_distribution_id (), + m_flags (0) { if (triple_cstr) SetTriple(triple_cstr, platform); @@ -438,7 +440,8 @@ ArchSpec::ArchSpec (const char *triple_cstr) : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id () + m_distribution_id (), + m_flags (0) { if (triple_cstr) SetTriple(triple_cstr); @@ -448,7 +451,8 @@ ArchSpec::ArchSpec(const llvm::Triple &triple) : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id () + m_distribution_id (), + m_flags (0) { SetTriple(triple); } @@ -457,7 +461,8 @@ ArchSpec::ArchSpec (ArchitectureType arch_type, uint32_t cpu, uint32_t subtype) m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id () + m_distribution_id (), + m_flags (0) { SetArchitecture (arch_type, cpu, subtype); } @@ -478,6 +483,7 @@ ArchSpec::operator= (const ArchSpec& rhs) m_core = rhs.m_core; m_byte_order = rhs.m_byte_order; m_distribution_id = rhs.m_distribution_id; + m_flags = rhs.m_flags; } return *this; } @@ -489,6 +495,7 @@ ArchSpec::Clear() m_core = kCore_invalid; m_byte_order = eByteOrderInvalid; m_distribution_id.Clear (); + m_flags = 0; } //===----------------------------------------------------------------------===// diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 75ee8aa4c..d20219f6d 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -415,7 +415,7 @@ protected: -DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, unsigned flavor, DisassemblerLLVMC &owner): +DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner): m_is_valid(true) { std::string Error; @@ -429,8 +429,6 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, con 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, cpu, features_str)); @@ -674,8 +672,25 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s default: cpu = ""; break; } + + std::string features_str = ""; + if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel + || arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el) + { + uint32_t arch_flags = arch.GetFlags (); + if (arch_flags & ArchSpec::eMIPSAse_msa) + features_str += "+msa,"; + if (arch_flags & ArchSpec::eMIPSAse_dsp) + features_str += "+dsp,"; + if (arch_flags & ArchSpec::eMIPSAse_dspr2) + features_str += "+dspr2,"; + if (arch_flags & ArchSpec::eMIPSAse_mips16) + features_str += "+mips16,"; + if (arch_flags & ArchSpec::eMIPSAse_micromips) + features_str += "+micromips,"; + } - m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, flavor, *this)); + m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, features_str.c_str(), 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, @@ -687,7 +702,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s if (arch.GetTriple().getArch() == llvm::Triple::arm) { std::string thumb_triple(thumb_arch.GetTriple().getTriple()); - m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", flavor, *this)); + m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this)); if (!m_alternate_disasm_ap->IsValid()) { m_disasm_ap.reset(); diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h index 4c32e2578..56cec0399 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -41,7 +41,7 @@ class DisassemblerLLVMC : public lldb_private::Disassembler class LLVMCDisassembler { public: - LLVMCDisassembler (const char *triple, const char *cpu, unsigned flavor, DisassemblerLLVMC &owner); + LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner); ~LLVMCDisassembler(); diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index 1af25dc81..9b8ea344e 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -124,6 +124,19 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar cpu = "generic"; break; } + std::string features = ""; + uint32_t arch_flags = arch.GetFlags (); + if (arch_flags & ArchSpec::eMIPSAse_msa) + features += "+msa,"; + if (arch_flags & ArchSpec::eMIPSAse_dsp) + features += "+dsp,"; + if (arch_flags & ArchSpec::eMIPSAse_dspr2) + features += "+dspr2,"; + if (arch_flags & ArchSpec::eMIPSAse_mips16) + features += "+mips16,"; + if (arch_flags & ArchSpec::eMIPSAse_micromips) + features += "+micromips,"; + m_reg_info.reset (target->createMCRegInfo (triple.getTriple())); assert (m_reg_info.get()); @@ -131,7 +144,7 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar assert (m_insn_info.get()); m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple())); - m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, "")); + m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features)); assert (m_asm_info.get() && m_subtype_info.get()); m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr)); diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 7abf68734..09bbcbd9c 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -124,6 +124,19 @@ EmulateInstructionMIPS64::EmulateInstructionMIPS64 (const lldb_private::ArchSpec cpu = "generic"; break; } + std::string features = ""; + uint32_t arch_flags = arch.GetFlags (); + if (arch_flags & ArchSpec::eMIPSAse_msa) + features += "+msa,"; + if (arch_flags & ArchSpec::eMIPSAse_dsp) + features += "+dsp,"; + if (arch_flags & ArchSpec::eMIPSAse_dspr2) + features += "+dspr2,"; + if (arch_flags & ArchSpec::eMIPSAse_mips16) + features += "+mips16,"; + if (arch_flags & ArchSpec::eMIPSAse_micromips) + features += "+micromips,"; + m_reg_info.reset (target->createMCRegInfo (triple.getTriple())); assert (m_reg_info.get()); @@ -131,7 +144,7 @@ EmulateInstructionMIPS64::EmulateInstructionMIPS64 (const lldb_private::ArchSpec assert (m_insn_info.get()); m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple())); - m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, "")); + m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features)); assert (m_asm_info.get() && m_subtype_info.get()); m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr)); diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 5fc83f061..789fd4913 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1437,6 +1437,25 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, assert(spec_ostype == ostype); } + if (arch_spec.GetMachine() == llvm::Triple::mips || arch_spec.GetMachine() == llvm::Triple::mipsel + || arch_spec.GetMachine() == llvm::Triple::mips64 || arch_spec.GetMachine() == llvm::Triple::mips64el) + { + switch (header.e_flags & llvm::ELF::EF_MIPS_ARCH_ASE) + { + case llvm::ELF::EF_MIPS_MICROMIPS: + arch_spec.SetFlags (ArchSpec::eMIPSAse_micromips); + break; + case llvm::ELF::EF_MIPS_ARCH_ASE_M16: + arch_spec.SetFlags (ArchSpec::eMIPSAse_mips16); + break; + case llvm::ELF::EF_MIPS_ARCH_ASE_MDMX: + arch_spec.SetFlags (ArchSpec::eMIPSAse_mdmx); + break; + default: + break; + } + } + // If there are no section headers we are done. if (header.e_shnum == 0) return 0; @@ -1483,6 +1502,22 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, I->section_name = name; + if (arch_spec.GetMachine() == llvm::Triple::mips || arch_spec.GetMachine() == llvm::Triple::mipsel + || arch_spec.GetMachine() == llvm::Triple::mips64 || arch_spec.GetMachine() == llvm::Triple::mips64el) + { + if (header.sh_type == SHT_MIPS_ABIFLAGS) + { + DataExtractor data; + if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + { + lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0 + uint32_t arch_flags = arch_spec.GetFlags (); + arch_flags |= data.GetU32 (&ase_offset); + arch_spec.SetFlags (arch_flags); + } + } + } + if (name == g_sect_name_gnu_debuglink) { DataExtractor data; |