Skip to content

Commit

Permalink
[ARM] Create objdump subtarget from build attrs
Browse files Browse the repository at this point in the history
Enable an ELFObjectFile to read the its arm build attributes to
produce a target triple with a specific ARM architecture.
llvm-objdump now uses this functionality to automatically produce
a more accurate target.

Differential Revision: https://reviews.llvm.org/D28769


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292366 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
sparker-arm committed Jan 18, 2017
1 parent caaf153 commit aa96763
Show file tree
Hide file tree
Showing 19 changed files with 686 additions and 58 deletions.
25 changes: 25 additions & 0 deletions include/llvm/Object/ELFObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
Expand Down Expand Up @@ -72,6 +73,8 @@ class ELFObjectFileBase : public ObjectFile {
static inline bool classof(const Binary *v) { return v->isELF(); }

SubtargetFeatures getFeatures() const override;

void setARMSubArch(Triple &TheTriple) const override;
};

class ELFSectionRef : public SectionRef {
Expand Down Expand Up @@ -356,6 +359,28 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
return std::error_code();
}

std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override {
auto SectionsOrErr = EF.sections();
if (!SectionsOrErr)
return errorToErrorCode(SectionsOrErr.takeError());

for (const Elf_Shdr &Sec : *SectionsOrErr) {
if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES) {
auto ErrorOrContents = EF.getSectionContents(&Sec);
if (!ErrorOrContents)
return errorToErrorCode(ErrorOrContents.takeError());

auto Contents = ErrorOrContents.get();
if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1)
return std::error_code();

Attributes.Parse(Contents, ELFT::TargetEndianness == support::little);
break;
}
}
return std::error_code();
}

const ELFFile<ELFT> *getELFFile() const { return &EF; }

bool isDyldType() const { return isDyldELFObject; }
Expand Down
8 changes: 8 additions & 0 deletions include/llvm/Object/ObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <cstring>

namespace llvm {
class ARMAttributeParser;

namespace object {

class ObjectFile;
Expand Down Expand Up @@ -265,13 +267,19 @@ class ObjectFile : public SymbolicFile {
virtual StringRef getFileFormatName() const = 0;
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
virtual SubtargetFeatures getFeatures() const = 0;
virtual void setARMSubArch(Triple &TheTriple) const { }

/// Returns platform-specific object flags, if any.
virtual std::error_code getPlatformFlags(unsigned &Result) const {
Result = 0;
return object_error::invalid_file_type;
}

virtual std::error_code
getBuildAttributes(ARMAttributeParser &Attributes) const {
return std::error_code();
}

/// True if this is a relocatable object (.o/.obj).
virtual bool isRelocatableObject() const = 0;

Expand Down
20 changes: 17 additions & 3 deletions include/llvm/Support/ARMAttributeParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@
#include "ARMBuildAttributes.h"
#include "ScopedPrinter.h"

#include <map>

namespace llvm {
class StringRef;

class ARMAttributeParser {
ScopedPrinter &SW;
ScopedPrinter *SW;

std::map<unsigned, unsigned> Attributes;

struct DisplayHandler {
ARMBuildAttrs::AttrType Attribute;
Expand Down Expand Up @@ -115,9 +119,19 @@ class ARMAttributeParser {
SmallVectorImpl<uint8_t> &IndexList);
void ParseSubsection(const uint8_t *Data, uint32_t Length);
public:
ARMAttributeParser(ScopedPrinter &SW) : SW(SW) {}
ARMAttributeParser(ScopedPrinter *SW) : SW(SW) {}

ARMAttributeParser() : SW(nullptr) { }

void Parse(ArrayRef<uint8_t> Section, bool isLittle);

bool hasAttribute(unsigned Tag) const {
return Attributes.count(Tag);
}

void Parse(ArrayRef<uint8_t> Section);
unsigned getAttributeValue(unsigned Tag) const {
return Attributes.find(Tag)->second;
}
};

}
Expand Down
14 changes: 13 additions & 1 deletion include/llvm/Support/ARMBuildAttributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,25 @@ enum {
WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2
WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4

// Tag_ABI_align_needed, (=24), uleb128
Align8Byte = 1,
Align4Byte = 2,
AlignReserved = 3,

// Tag_ABI_align_needed, (=25), uleb128
AlignNotPreserved = 0,
AlignPreserve8Byte = 1,
AlignPreserveAll = 2,

// Tag_ABI_FP_denormal, (=20), uleb128
PositiveZero = 0,
IEEEDenormals = 1,
PreserveFPSign = 2, // sign when flushed-to-zero is preserved

// Tag_ABI_FP_number_model, (=23), uleb128
AllowIEEENormal = 1,
AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI])
AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings
AllowIEEE754 = 3, // this code to use all the IEEE 754-defined FP encodings

// Tag_ABI_enum_size, (=26), uleb128
EnumProhibited = 0, // The user prohibited the use of enums when building
Expand All @@ -208,6 +219,7 @@ enum {

// Tag_FP_16bit_format, (=38), uleb128
FP16FormatIEEE = 1,
FP16VFP3 = 2,

// Tag_MPextension_use, (=42), uleb128
AllowMP = 1, // Allow use of MP extensions
Expand Down
67 changes: 67 additions & 0 deletions lib/Object/ELFObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,71 @@ SubtargetFeatures ELFObjectFileBase::getFeatures() const {
}
}

// FIXME Encode from a tablegen description or target parser.
void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
if (TheTriple.getSubArch() != Triple::NoSubArch)
return;

ARMAttributeParser Attributes;
std::error_code EC = getBuildAttributes(Attributes);
if (EC)
return;

std::string Triple;
// Default to ARM, but use the triple if it's been set.
if (TheTriple.getArch() == Triple::thumb ||
TheTriple.getArch() == Triple::thumbeb)
Triple = "thumb";
else
Triple = "arm";

if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
case ARMBuildAttrs::v4:
Triple += "v4";
break;
case ARMBuildAttrs::v4T:
Triple += "v4t";
break;
case ARMBuildAttrs::v5T:
Triple += "v5t";
break;
case ARMBuildAttrs::v5TE:
Triple += "v5te";
break;
case ARMBuildAttrs::v5TEJ:
Triple += "v5tej";
break;
case ARMBuildAttrs::v6:
Triple += "v6";
break;
case ARMBuildAttrs::v6KZ:
Triple += "v6kz";
break;
case ARMBuildAttrs::v6T2:
Triple += "v6t2";
break;
case ARMBuildAttrs::v6K:
Triple += "v6k";
break;
case ARMBuildAttrs::v7:
Triple += "v7";
break;
case ARMBuildAttrs::v6_M:
Triple += "v6m";
break;
case ARMBuildAttrs::v6S_M:
Triple += "v6sm";
break;
case ARMBuildAttrs::v7E_M:
Triple += "v7em";
break;
}
}
if (!isLittleEndian())
Triple += "eb";

TheTriple.setArchName(Triple);
}

} // end namespace llvm
Loading

0 comments on commit aa96763

Please sign in to comment.