summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index bb388d45e36..76416843fd5 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -31,6 +31,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/MathExtras.h"
#define CASE_AND_STREAM(s, def, width) \
@@ -1516,6 +1517,93 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
return error;
}
+void
+ObjectFileELF::ParseARMAttributes(DataExtractor &data, uint64_t length, ArchSpec &arch_spec)
+{
+ lldb::offset_t Offset = 0;
+
+ uint8_t FormatVersion = data.GetU8(&Offset);
+ if (FormatVersion != llvm::ARMBuildAttrs::Format_Version)
+ return;
+
+ Offset = Offset + sizeof(uint32_t); // Section Length
+ llvm::StringRef VendorName = data.GetCStr(&Offset);
+
+ if (VendorName != "aeabi")
+ return;
+
+ if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment)
+ arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);
+
+ while (Offset < length)
+ {
+ uint8_t Tag = data.GetU8(&Offset);
+ uint32_t Size = data.GetU32(&Offset);
+
+ if (Tag != llvm::ARMBuildAttrs::File || Size == 0)
+ continue;
+
+ while (Offset < length)
+ {
+ uint64_t Tag = data.GetULEB128(&Offset);
+ switch (Tag)
+ {
+ default:
+ if (Tag < 32)
+ data.GetULEB128(&Offset);
+ else if (Tag % 2 == 0)
+ data.GetULEB128(&Offset);
+ else
+ data.GetCStr(&Offset);
+
+ break;
+
+ case llvm::ARMBuildAttrs::CPU_raw_name:
+ case llvm::ARMBuildAttrs::CPU_name:
+ data.GetCStr(&Offset);
+
+ break;
+
+ case llvm::ARMBuildAttrs::THUMB_ISA_use:
+ {
+ uint64_t ThumbISA = data.GetULEB128(&Offset);
+
+ // NOTE: ignore ThumbISA == llvm::ARMBuildAttrs::AllowThumbDerived
+ // since that derives it based on the architecutre/profile
+ if (ThumbISA == llvm::ARMBuildAttrs::AllowThumb32)
+ if (arch_spec.GetTriple().getArch() == llvm::Triple::UnknownArch ||
+ arch_spec.GetTriple().getArch() == llvm::Triple::arm)
+ arch_spec.GetTriple().setArch(llvm::Triple::thumb);
+
+ break;
+ }
+ case llvm::ARMBuildAttrs::ABI_VFP_args:
+ {
+ uint64_t VFPArgs = data.GetULEB128(&Offset);
+
+ if (VFPArgs == llvm::ARMBuildAttrs::BaseAAPCS)
+ {
+ if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment ||
+ arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABIHF)
+ arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);
+
+ arch_spec.SetFlags(ArchSpec::eARM_abi_soft_float);
+ }
+ else if (VFPArgs == llvm::ARMBuildAttrs::HardFPAAPCS)
+ {
+ if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment ||
+ arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABI)
+ arch_spec.GetTriple().setEnvironment(llvm::Triple::EABIHF);
+
+ arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float);
+ }
+
+ break;
+ }
+ }
+ }
+ }
+}
//----------------------------------------------------------------------
// GetSectionHeaderInfo
@@ -1648,6 +1736,18 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
arch_spec.SetFlags (arch_flags);
}
+ if (arch_spec.GetMachine() == llvm::Triple::arm || arch_spec.GetMachine() == llvm::Triple::thumb)
+ {
+ DataExtractor data;
+
+ if (sheader.sh_type != SHT_ARM_ATTRIBUTES)
+ continue;
+ if (section_size == 0 || set_data(data, sheader.sh_offset, section_size) != section_size)
+ continue;
+
+ ParseARMAttributes(data, section_size, arch_spec);
+ }
+
if (name == g_sect_name_gnu_debuglink)
{
DataExtractor data;
OpenPOWER on IntegriCloud