diff options
author | Mohit K. Bhakkad <mohit.bhakkad@gmail.com> | 2016-06-01 13:18:51 +0000 |
---|---|---|
committer | Mohit K. Bhakkad <mohit.bhakkad@gmail.com> | 2016-06-01 13:18:51 +0000 |
commit | 316537de6fb64eee08449408aca65c2f66a5787a (patch) | |
tree | a53d392b92129e110f8721d3a78bf321bd10a95e | |
parent | 9a9fc8fb9d0e74ef88f362de433f1958b54d3c48 (diff) |
Merging r270564:release_38
------------------------------------------------------------------------
r270564 | slthakur | 2016-05-24 20:22:50 +0530 (Tue, 24 May 2016) | 9 lines
[LLDB][MIPS] Fix floating point handling in case of thread step-out
Patch by Nitesh Jain.
Summary: These patch fix thread step-out for hard and soft float.
Reviewers: jaydeep, bhushan, clayborg
Differential Revision: http://reviews.llvm.org/D20416
------------------------------------------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/lldb/branches/release_38@271390 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/lldb/Core/ArchSpec.h | 14 | ||||
-rw-r--r-- | source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp | 121 | ||||
-rw-r--r-- | source/Plugins/ABI/SysV-mips/ABISysV_mips.h | 3 | ||||
-rw-r--r-- | source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp | 90 | ||||
-rw-r--r-- | source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h | 3 | ||||
-rw-r--r-- | source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 36 |
6 files changed, 229 insertions, 38 deletions
diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 60e413c14..5343828c0 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -75,6 +75,20 @@ public: eMIPSABI_mask = 0x000ff000 }; + // MIPS Floating point ABI Values + enum MIPS_ABI_FP + { + eMIPS_ABI_FP_ANY = 0x00000000, + eMIPS_ABI_FP_DOUBLE = 0x00100000, // hard float / -mdouble-float + eMIPS_ABI_FP_SINGLE = 0x00200000, // hard float / -msingle-float + eMIPS_ABI_FP_SOFT = 0x00300000, // soft float + eMIPS_ABI_FP_OLD_64 = 0x00400000, // -mips32r2 -mfp64 + eMIPS_ABI_FP_XX = 0x00500000, // -mfpxx + eMIPS_ABI_FP_64 = 0x00600000, // -mips32r2 -mfp64 + eMIPS_ABI_FP_64A = 0x00700000, // -mips32r2 -mfp64 -mno-odd-spreg + eMIPS_ABI_FP_mask = 0x00700000 + }; + enum Core { eCore_arm_generic, diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index 1b77946c1..7e1cf76df 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -393,7 +393,11 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_com if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) return return_valobj_sp; + Target *target = exe_ctx.GetTargetPtr(); + const ArchSpec target_arch = target->GetArchitecture(); + ByteOrder target_byte_order = target_arch.GetByteOrder(); value.SetCompilerType(return_compiler_type); + uint32_t fp_flag = target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask; RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -405,8 +409,7 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_com // In MIPS register "r2" (v0) holds the integer function return values const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); - size_t bit_width = return_compiler_type.GetBitSize(&thread); - + size_t bit_width = return_compiler_type.GetBitSize(&thread); if (return_compiler_type.IsIntegerType (is_signed)) { switch (bit_width) @@ -463,37 +466,107 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_com } else if (return_compiler_type.IsFloatingPointType (count, is_complex)) { - const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); - const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); - - if (count == 1 && !is_complex) + if (IsSoftFloat (fp_flag)) { + uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0); + if (count != 1 && is_complex) + return return_valobj_sp; switch (bit_width) { default: return return_valobj_sp; - case 64: - { - static_assert(sizeof(double) == sizeof(uint64_t), ""); - uint64_t raw_value; - raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; - raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32; - value.GetScalar() = *reinterpret_cast<double*>(&raw_value); - break; - } case 32: - { static_assert(sizeof(float) == sizeof(uint32_t), ""); - uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; - value.GetScalar() = *reinterpret_cast<float*>(&raw_value); + value.GetScalar() = *((float *)(&raw_value)); + break; + case 64: + static_assert(sizeof(double) == sizeof(uint64_t), ""); + const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); + if (target_byte_order == eByteOrderLittle) + raw_value = ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) | raw_value; + else + raw_value = (raw_value << 32) | reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0); + value.GetScalar() = *((double *)(&raw_value)); break; - } } } + else { - // not handled yet - return return_valobj_sp; + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + RegisterValue f0_value; + DataExtractor f0_data; + reg_ctx->ReadRegister (f0_info, f0_value); + f0_value.GetData(f0_data); + lldb::offset_t offset = 0; + + if (count == 1 && !is_complex) + { + switch (bit_width) + { + default: + return return_valobj_sp; + case 64: + { + static_assert(sizeof(double) == sizeof(uint64_t), ""); + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + RegisterValue f1_value; + DataExtractor f1_data; + reg_ctx->ReadRegister (f1_info, f1_value); + DataExtractor *copy_from_extractor = nullptr; + DataBufferSP data_sp (new DataBufferHeap(8, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + if (target_byte_order == eByteOrderLittle) + { + copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes(), + 4, + target_byte_order); + f1_value.GetData(f1_data); + copy_from_extractor = &f1_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes() + 4, + 4, + target_byte_order); + } + else + { + copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes() + 4, + 4, + target_byte_order); + f1_value.GetData(f1_data); + copy_from_extractor = &f1_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes(), + 4, + target_byte_order); + } + value.GetScalar() = (double) return_ext.GetDouble(&offset); + break; + } + case 32: + { + static_assert(sizeof(float) == sizeof(uint32_t), ""); + value.GetScalar() = (float) f0_data.GetFloat(&offset); + break; + } + } + } + else + { + // not handled yet + return return_valobj_sp; + } } } else @@ -559,6 +632,12 @@ ABISysV_mips::RegisterIsVolatile (const RegisterInfo *reg_info) } bool +ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const +{ + return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT); +} + +bool ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info) { if (reg_info) diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h index 709c3bfe3..388009d0f 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h @@ -54,6 +54,9 @@ public: RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; bool + IsSoftFloat(uint32_t fp_flag) const; + + bool CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index 8226ef15f..5db1079b4 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -368,9 +368,11 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c return return_valobj_sp; Target *target = exe_ctx.GetTargetPtr(); - ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); + const ArchSpec target_arch = target->GetArchitecture(); + ByteOrder target_byte_order = target_arch.GetByteOrder(); const size_t byte_size = return_compiler_type.GetByteSize(nullptr); const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL); + uint32_t fp_flag = target_arch.GetFlags () & lldb_private::ArchSpec::eMIPS_ABI_FP_mask; const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -434,20 +436,52 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c { // Don't handle complex yet. } + else if (IsSoftFloat(fp_flag)) + { + uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0); + switch (byte_size) + { + case 4: + value.GetScalar() = *((float *)(&raw_value)); + success = true; + break; + case 8: + value.GetScalar() = *((double *)(&raw_value)); + success = true; + break; + case 16: + uint64_t result[2]; + if (target_byte_order == eByteOrderLittle) + { + result[0] = raw_value; + result[1] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0); + value.GetScalar() = *((long double *)(result)); + } + else + { + result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0); + result[1] = raw_value; + value.GetScalar() = *((long double *)(result)); + } + success = true; + break; + } + + } else { if (byte_size <= sizeof(long double)) { const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); - const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); - RegisterValue f0_value, f2_value; - DataExtractor f0_data, f2_data; + + RegisterValue f0_value; + DataExtractor f0_data; reg_ctx->ReadRegister (f0_info, f0_value); - reg_ctx->ReadRegister (f2_info, f2_value); + f0_value.GetData(f0_data); - f2_value.GetData(f2_data); + lldb::offset_t offset = 0; if (byte_size == sizeof(float)) @@ -462,6 +496,10 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c } else if (byte_size == sizeof(long double)) { + const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); + RegisterValue f2_value; + DataExtractor f2_data; + reg_ctx->ReadRegister (f2_info, f2_value); DataExtractor *copy_from_extractor = NULL; DataBufferSP data_sp (new DataBufferHeap(16, 0)); DataExtractor return_ext (data_sp, @@ -470,21 +508,37 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c if (target_byte_order == eByteOrderLittle) { - f0_data.Append(f2_data); copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes(), + byte_size - 8, + target_byte_order); + f2_value.GetData(f2_data); + copy_from_extractor = &f2_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes() + 8, + byte_size - 8, + target_byte_order); } else { - f2_data.Append(f0_data); - copy_from_extractor = &f2_data; + copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes() + 8, + byte_size - 8, + target_byte_order); + f2_value.GetData(f2_data); + copy_from_extractor = &f2_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes(), + byte_size - 8, + target_byte_order); } - copy_from_extractor->CopyByteOrderedData (0, - byte_size, - data_sp->GetBytes(), - byte_size, - target_byte_order); - return_valobj_sp = ValueObjectConstResult::Create (&thread, return_compiler_type, ConstString(""), @@ -777,6 +831,12 @@ ABISysV_mips64::RegisterIsVolatile (const RegisterInfo *reg_info) } bool +ABISysV_mips64::IsSoftFloat (uint32_t fp_flag) const +{ + return (fp_flag == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT); +} + +bool ABISysV_mips64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) { if (reg_info) diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h index 3290331e0..9f1ea0922 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h @@ -53,6 +53,9 @@ public: bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + bool + IsSoftFloat(uint32_t fp_flag) const; + // The SysV mips ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland // code, we've seen that the stack pointer is often not aligned properly diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 70817d9e1..479c07b2e 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -32,6 +32,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/MipsABIFlags.h" #define CASE_AND_STREAM(s, def, width) \ case def: s->Printf("%-*s", width, #def); break; @@ -1611,8 +1612,39 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size)) { - lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0 - arch_flags |= data.GetU32 (&ase_offset); + // MIPS ASE Mask is at offset 12 in MIPS.abiflags section + lldb::offset_t offset = 12; // MIPS ABI Flags Version: 0 + arch_flags |= data.GetU32 (&offset); + + // The floating point ABI is at offset 7 + offset = 7; + switch (data.GetU8 (&offset)) + { + case llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_ANY; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_DOUBLE : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_DOUBLE; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_SINGLE : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SINGLE; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_SOFT : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_OLD_64 : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_OLD_64; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_XX : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_XX; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_64 : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_64A : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64A; + break; + } } } // Settings appropriate ArchSpec ABI Flags |