From: Sid Manning Date: Tue, 9 Oct 2012 02:20:47 +0000 (+0000) Subject: * Add relocation reference support for Hexagon and PowerPC. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=42064e5b603e46abadc9adea24c49d5c1a4b259b;p=platform%2Fupstream%2Fllvm.git * Add relocation reference support for Hexagon and PowerPC. - Hexagon has many relocation types, this patch covers just a subset, more will be added. - PowerPC support was added so that we can verify mixed endian environments. * Add some basic test cases * Update ldd-core to accept -endian flag llvm-svn: 165477 --- diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt index 549ecb8..f19a07e 100644 --- a/lld/lib/ReaderWriter/ELF/CMakeLists.txt +++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt @@ -2,5 +2,7 @@ add_lld_library(lldELF ReaderELF.cpp WriterELF.cpp ReferenceKinds.cpp + HexagonReference.cpp + PPCReference.cpp WriterOptionsELF.cpp ) diff --git a/lld/lib/ReaderWriter/ELF/HexagonReference.cpp b/lld/lib/ReaderWriter/ELF/HexagonReference.cpp new file mode 100644 index 0000000..42758c5 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/HexagonReference.cpp @@ -0,0 +1,171 @@ +//===- lib/ReaderWriter/ELF/HexagonReference.cpp ----------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "ReferenceKinds.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" + +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ELF.h" + +namespace lld { +namespace elf { + +//===----------------------------------------------------------------------===// +// KindHandler_hexagon +// TODO: more to do here +//===----------------------------------------------------------------------===// + +KindHandler_hexagon::~KindHandler_hexagon() { +} + +/// \brief The following relocation routines are derived from the +/// Hexagon ABI specification, Section 11.6: Relocation +/// Symbols used: +/// A: Added used to compute the value, r_addend +/// P: Place address of the field being relocated, r_offset +/// S: Value of the symbol whose index resides in the relocation entry. + +namespace hexagon { +int reloc_NONE(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + return KindHandler_hexagon::NoError; +} + +/// \brief Word32_B22: 0x01ff3ffe : (S + A - P) >> 2 : Verify +int reloc_B22_PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int32_t result = (uint32_t)(((S + A) - P)>>2); + if ((result < 0x200000) && (result > -0x200000)) { + result = ((result<<1) & 0x3ffe) | ((result<<3) & 0x01ff0000); + *reinterpret_cast(location) = result | + *reinterpret_cast(location); + return KindHandler_hexagon::NoError; + } + return KindHandler_hexagon::Overflow; +} + +/// \brief Word32_B15: 0x00df20fe : (S + A - P) >> 2 : Verify +int reloc_B15_PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int32_t result = (uint32_t)(((S + A) - P)>>2); + if ((result < 0x8000) && (result > -0x8000)) { + result = ((result<<1) & 0x20fe) | ((result<<7) & 0x00df0000); + *reinterpret_cast(location) = result | + *reinterpret_cast(location); + return KindHandler_hexagon::NoError; + } + return KindHandler_hexagon::Overflow; +} + +/// \brief Word32_LO: 0x00c03fff : (S + A) : Truncate +int reloc_LO16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + uint32_t result = (uint32_t)(S + A); + result = ((result & 0x3fff) | ((result << 2) & 0x00c00000)); + *reinterpret_cast(location) = result | + *reinterpret_cast(location); + return KindHandler_hexagon::NoError; +} + +/// \brief Word32_LO: 0x00c03fff : (S + A) >> 16 : Truncate +int reloc_HI16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + uint32_t result = (uint32_t)((S + A)>>16); + result = ((result & 0x3fff) | ((result << 2) & 0x00c00000)); + *reinterpret_cast(location) = result | + *reinterpret_cast(location); + return KindHandler_hexagon::NoError; +} + +/// \brief Word32: 0xffffffff : (S + A) : Truncate +int reloc_32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + uint32_t result = (uint32_t)(S + A); + *reinterpret_cast(location) = result | + *reinterpret_cast(location); + return KindHandler_hexagon::NoError; +} +} // namespace hexagon + +KindHandler_hexagon::KindHandler_hexagon(){ + _fixupHandler[llvm::ELF::R_HEX_B22_PCREL] = hexagon::reloc_B22_PCREL; + _fixupHandler[llvm::ELF::R_HEX_B15_PCREL] = hexagon::reloc_B15_PCREL; + _fixupHandler[llvm::ELF::R_HEX_LO16] = hexagon::reloc_LO16; + _fixupHandler[llvm::ELF::R_HEX_HI16] = hexagon::reloc_HI16; + _fixupHandler[llvm::ELF::R_HEX_32] = hexagon::reloc_32; +} + +Reference::Kind KindHandler_hexagon::stringToKind(StringRef str) { + return llvm::StringSwitch(str) + .Case("none", none) + .Case("R_HEX_B22_PCREL", llvm::ELF::R_HEX_B22_PCREL) + .Case("R_HEX_B15_PCREL", llvm::ELF::R_HEX_B15_PCREL) + .Case("R_HEX_LO16", llvm::ELF::R_HEX_LO16) + .Case("R_HEX_HI16", llvm::ELF::R_HEX_HI16) + .Case("R_HEX_32", llvm::ELF::R_HEX_32) + .Default(invalid); +} + +StringRef KindHandler_hexagon::kindToString(Reference::Kind kind) { + switch (static_cast(kind)) { + case llvm::ELF::R_HEX_B22_PCREL: + return "R_HEX_B22_PCREL"; + case llvm::ELF::R_HEX_B15_PCREL: + return "R_HEX_B15_PCREL"; + case llvm::ELF::R_HEX_LO16: + return "R_HEX_LO16"; + case llvm::ELF::R_HEX_HI16: + return "R_HEX_HI16"; + case llvm::ELF::R_HEX_32: + return "R_HEX_32"; + default: + return "none"; + } +} + +bool KindHandler_hexagon::isCallSite(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_hexagon::isCallSite"); + return false; +} + +bool KindHandler_hexagon::isPointer(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_hexagon::isPointer"); + return false; +} + +bool KindHandler_hexagon::isLazyImmediate(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_hexagon::isLazyImmediate"); + return false; +} + +bool KindHandler_hexagon::isLazyTarget(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_hexagon::isLazyTarget"); + return false; +} + +void KindHandler_hexagon::applyFixup(int32_t reloc, uint64_t addend, + uint8_t *location, uint64_t fixupAddress, + uint64_t targetAddress) { + int error; + if (_fixupHandler[reloc]) + { + error = (*_fixupHandler[reloc])(location, + fixupAddress, targetAddress, addend); + + switch ((RelocationError)error) { + case NoError: + return; + case Overflow: + llvm::report_fatal_error("applyFixup relocation overflow"); + return; + } + } +} + + +} // namespace elf +} // namespace lld diff --git a/lld/lib/ReaderWriter/ELF/PPCReference.cpp b/lld/lib/ReaderWriter/ELF/PPCReference.cpp new file mode 100644 index 0000000..31b0df73 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/PPCReference.cpp @@ -0,0 +1,116 @@ +//===- lib/ReaderWriter/ELF/PPCReference.cpp ----------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "ReferenceKinds.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" + +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ELF.h" + +namespace lld { +namespace elf { + +//===----------------------------------------------------------------------===// +// KindHandler_ppc +// TODO: more to do here +//===----------------------------------------------------------------------===// + +KindHandler_ppc::~KindHandler_ppc() { +} + +/// \brief The following relocation routines are derived from the +/// SYSTEM V APPLICATION BINARY INTERFACE: PowerPC Processor Supplement +/// Symbols used: +/// A: Added used to compute the value, r_addend +/// P: Place address of the field being relocated, r_offset +/// S: Value of the symbol whose index resides in the relocation entry. + +namespace ppc { +int reloc_NONE(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + return KindHandler_ppc::NoError; +} + +/// \brief low24 (S + A - P) >> 2 : Verify +int reloc_B24_PCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int32_t result = (uint32_t)(((S + A) - P)); + if ((result < 0x1000000) && (result > -0x1000000)) { + result &= ~-(0x1000000); + *reinterpret_cast(location) = result | + *reinterpret_cast(location); + return KindHandler_ppc::NoError; + } + return KindHandler_ppc::Overflow; +} +} // namespace ppc + +KindHandler_ppc::KindHandler_ppc(llvm::support::endianness endian){ + _fixupHandler[llvm::ELF::R_PPC_REL24] = ppc::reloc_B24_PCREL; +} + +Reference::Kind KindHandler_ppc::stringToKind(StringRef str) { + return llvm::StringSwitch(str) + .Case("none", none) + .Case("R_PPC_REL24", llvm::ELF::R_PPC_REL24) + .Default(invalid); +} + +StringRef KindHandler_ppc::kindToString(Reference::Kind kind) { + switch ((int32_t)kind) { + case llvm::ELF::R_PPC_REL24: + return "R_PPC_REL24"; + default: + return "none"; + } +} + +bool KindHandler_ppc::isCallSite(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_ppc::isCallSite"); + return false; +} + +bool KindHandler_ppc::isPointer(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_ppc::isPointer"); + return false; +} + +bool KindHandler_ppc::isLazyImmediate(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_ppc::isLazyImmediate"); + return false; +} + +bool KindHandler_ppc::isLazyTarget(Kind kind) { + llvm_unreachable("Unimplemented: KindHandler_ppc::isLazyTarget"); + return false; +} + +void KindHandler_ppc::applyFixup(int32_t reloc, uint64_t addend, + uint8_t *location, uint64_t fixupAddress, + uint64_t targetAddress) { + int error; + if (_fixupHandler[reloc]) + { + error = (*_fixupHandler[reloc])(location, + fixupAddress, targetAddress, addend); + + switch ((RelocationError)error) { + case NoError: + return; + case Overflow: + llvm::report_fatal_error("applyFixup relocation overflow"); + return; + } + } +} + +} // namespace elf +} // namespace lld diff --git a/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp b/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp index 3ff983a..06d9732 100644 --- a/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp +++ b/lld/lib/ReaderWriter/ELF/ReferenceKinds.cpp @@ -28,12 +28,15 @@ KindHandler::KindHandler() { KindHandler::~KindHandler() { } -std::unique_ptr KindHandler::makeHandler(uint16_t arch) { +std::unique_ptr KindHandler::makeHandler(uint16_t arch, + llvm::support::endianness endian) { switch(arch) { case llvm::ELF::EM_HEXAGON: return std::unique_ptr(new KindHandler_hexagon()); case llvm::ELF::EM_386: return std::unique_ptr(new KindHandler_x86()); + case llvm::ELF::EM_PPC: + return std::unique_ptr(new KindHandler_ppc(endian)); default: llvm_unreachable("arch not supported"); } @@ -55,9 +58,9 @@ Reference::Kind KindHandler_x86::stringToKind(StringRef str) { StringRef KindHandler_x86::kindToString(Reference::Kind kind) { switch ( (Kinds)kind ) { case invalid: - return StringRef("invalid"); + return "invalid"; case none: - return StringRef("none"); + return "none"; } llvm_unreachable("invalid x86 Reference kind"); } @@ -82,82 +85,13 @@ bool KindHandler_x86::isLazyTarget(Kind kind) { return false; } - -void KindHandler_x86::applyFixup(Kind kind, uint64_t addend, - uint8_t *location, uint64_t fixupAddress, - uint64_t targetAddress) { - switch ((Kinds)kind) { - case none: - // do nothing - break; - case invalid: - assert(0 && "invalid Reference Kind"); - break; - } -} - -//===----------------------------------------------------------------------===// -// KindHandler_hexagon -// TODO: more to do here -//===----------------------------------------------------------------------===// - -KindHandler_hexagon::~KindHandler_hexagon() { -} - -Reference::Kind KindHandler_hexagon::stringToKind(StringRef str) { - return llvm::StringSwitch(str) - .Case("none", none) - .Default(invalid); - - llvm_unreachable("invalid hexagon Reference kind"); -} - -StringRef KindHandler_hexagon::kindToString(Reference::Kind kind) { - switch ( (Kinds)kind ) { - case invalid: - return StringRef("invalid"); - case none: - return StringRef("none"); - } - llvm_unreachable("invalid hexagon Reference kind"); -} - -bool KindHandler_hexagon::isCallSite(Kind kind) { - llvm_unreachable("Unimplemented: KindHandler_hexagon::isCallSite"); - return false; -} - -bool KindHandler_hexagon::isPointer(Kind kind) { - llvm_unreachable("Unimplemented: KindHandler_hexagon::isPointer"); - return false; -} - -bool KindHandler_hexagon::isLazyImmediate(Kind kind) { - llvm_unreachable("Unimplemented: KindHandler_hexagon::isLazyImmediate"); - return false; -} - -bool KindHandler_hexagon::isLazyTarget(Kind kind) { - llvm_unreachable("Unimplemented: KindHandler_hexagon::isLazyTarget"); - return false; -} - - -void KindHandler_hexagon::applyFixup(Kind kind, uint64_t addend, - uint8_t *location, uint64_t fixupAddress, +void KindHandler_x86::applyFixup(int32_t reloc, uint64_t addend, + uint8_t *location, uint64_t fixupAddress, uint64_t targetAddress) { - switch ((Kinds)kind) { - case none: - // do nothing - break; - case invalid: - llvm_unreachable("invalid Reference Kind"); - break; - } +// TODO: Add reloc funcs for X86 + return; } - - } // namespace elf } // namespace lld diff --git a/lld/lib/ReaderWriter/ELF/ReferenceKinds.h b/lld/lib/ReaderWriter/ELF/ReferenceKinds.h index 6a4b6d2..ff26a81 100644 --- a/lld/lib/ReaderWriter/ELF/ReferenceKinds.h +++ b/lld/lib/ReaderWriter/ELF/ReferenceKinds.h @@ -7,11 +7,13 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/DenseMap.h" #include "lld/Core/LLVM.h" #include "lld/Core/Reference.h" #include "lld/ReaderWriter/WriterELF.h" +#include #include #ifndef LLD_READER_WRITER_ELF_REFERENCE_KINDS_H_ @@ -31,7 +33,8 @@ class KindHandler { public: typedef Reference::Kind Kind; - static std::unique_ptr makeHandler(uint16_t arch); + static std::unique_ptr makeHandler(uint16_t arch, + llvm::support::endianness endian); virtual ~KindHandler(); virtual Kind stringToKind(StringRef str) = 0; virtual StringRef kindToString(Kind) = 0; @@ -39,8 +42,10 @@ public: virtual bool isPointer(Kind) = 0; virtual bool isLazyImmediate(Kind) = 0; virtual bool isLazyTarget(Kind) = 0; - virtual void applyFixup(Kind kind, uint64_t addend, uint8_t *location, - uint64_t fixupAddress, uint64_t targetAddress) = 0; + virtual void applyFixup(int32_t reloc, uint64_t addend, + uint8_t *location, + uint64_t fixupAddress, + uint64_t targetAddress) = 0; protected: KindHandler(); @@ -49,20 +54,38 @@ protected: class KindHandler_hexagon : public KindHandler { public: + +// Note: Reference::Kinds are a another representation of +// relocation types, using negative values to represent architecture +// independent reference type. +// The positive values are the same ones defined in ELF.h and that +// is what we are using. enum Kinds { - invalid, // used to denote an error creating a Reference - none, + none = llvm::ELF::R_HEX_NONE, + invalid=255, // used to denote an error creating a Reference + }; + + enum RelocationError { + NoError, + Overflow }; virtual ~KindHandler_hexagon(); + KindHandler_hexagon(); virtual Kind stringToKind(StringRef str); virtual StringRef kindToString(Kind); virtual bool isCallSite(Kind); virtual bool isPointer(Kind); virtual bool isLazyImmediate(Kind); virtual bool isLazyTarget(Kind); - virtual void applyFixup(Kind kind, uint64_t addend, uint8_t *location, - uint64_t fixupAddress, uint64_t targetAddress); + virtual void applyFixup(int32_t reloc, uint64_t addend, + uint8_t *location, + uint64_t fixupAddress, uint64_t targetAddress); + +private: + std::map _fixupHandler; }; @@ -81,8 +104,45 @@ public: virtual bool isPointer(Kind); virtual bool isLazyImmediate(Kind); virtual bool isLazyTarget(Kind); - virtual void applyFixup(Kind kind, uint64_t addend, uint8_t *location, - uint64_t fixupAddress, uint64_t targetAddress); + virtual void applyFixup(int32_t reloc, uint64_t addend, uint8_t *location, + uint64_t fixupAddress, uint64_t targetAddress); + +}; + +class KindHandler_ppc : public KindHandler { +public: + +// Note: Reference::Kinds are a another representation of +// relocation types, using negative values to represent architecture +// independent reference type. +// The positive values are the same ones defined in ELF.h and that +// is what we are using. + enum Kinds { + none = llvm::ELF::R_PPC_NONE, + invalid=255, // used to denote an error creating a Reference + }; + + enum RelocationError { + NoError, + Overflow + }; + + virtual ~KindHandler_ppc(); + KindHandler_ppc(llvm::support::endianness endian); + virtual Kind stringToKind(StringRef str); + virtual StringRef kindToString(Kind); + virtual bool isCallSite(Kind); + virtual bool isPointer(Kind); + virtual bool isLazyImmediate(Kind); + virtual bool isLazyTarget(Kind); + virtual void applyFixup(int32_t reloc, uint64_t addend, + uint8_t *location, + uint64_t fixupAddress, uint64_t targetAddress); + +private: + std::map _fixupHandler; }; diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp index 1d8b7b9..974e829 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -855,7 +855,8 @@ template ELFWriter ::ELFWriter(const WriterOptionsELF &options) : _options(options) - , _referenceKindHandler(KindHandler::makeHandler(_options.machine())) + , _referenceKindHandler(KindHandler::makeHandler(_options.machine(), + target_endianness)) {} template diff --git a/lld/test/elf/Inputs/branch-test.hexagon b/lld/test/elf/Inputs/branch-test.hexagon new file mode 100644 index 0000000..1ffb472 Binary files /dev/null and b/lld/test/elf/Inputs/branch-test.hexagon differ diff --git a/lld/test/elf/Inputs/branch-test.ppc b/lld/test/elf/Inputs/branch-test.ppc new file mode 100644 index 0000000..4698941 Binary files /dev/null and b/lld/test/elf/Inputs/branch-test.ppc differ diff --git a/lld/test/elf/Inputs/target-test.hexagon b/lld/test/elf/Inputs/target-test.hexagon new file mode 100644 index 0000000..7da1145 Binary files /dev/null and b/lld/test/elf/Inputs/target-test.hexagon differ diff --git a/lld/test/elf/Inputs/target-test.ppc b/lld/test/elf/Inputs/target-test.ppc new file mode 100644 index 0000000..001be33 Binary files /dev/null and b/lld/test/elf/Inputs/target-test.ppc differ diff --git a/lld/test/elf/branch.objtxt b/lld/test/elf/branch.objtxt new file mode 100644 index 0000000..91c25b6 --- /dev/null +++ b/lld/test/elf/branch.objtxt @@ -0,0 +1,34 @@ +RUN: lld-core -reader ELF %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon | FileCheck %s -check-prefix hexagon-yaml +RUN: lld-core -arch hexagon -reader ELF -writer ELF -o %t1 %p/Inputs/branch-test.hexagon %p/Inputs/target-test.hexagon +RUN: elf-dump %t1 | FileCheck -check-prefix=hexagon-elfdump %s + +hexagon-yaml: - name: back +hexagon-yaml: scope: global +hexagon-yaml: type: code +hexagon-yaml: section-choice: custom-required +hexagon-yaml: section-name: .text +hexagon-yaml: content: [ 00, C0, 00, 7F, 00, C0, 00, 5A, 00, 00, 00, 00, +hexagon-yaml: 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 ] + +hexagon-yaml: fixups: +hexagon-yaml: - offset: 4 +hexagon-yaml: target: target + +hexagon-yaml: - name: target +hexagon-yaml: scope: global +hexagon-yaml: type: code +hexagon-yaml: section-choice: custom-required +hexagon-yaml: section-name: .text +hexagon-yaml: content: [ 00, C0, 00, 5A ] +hexagon-yaml: fixups: +hexagon-yaml: - offset: 0 +hexagon-yaml: target: back + + +hexagon-elfdump: ('e_indent[EI_CLASS]', 0x01) +hexagon-elfdump: ('e_indent[EI_DATA]', 0x01) +hexagon-elfdump: ('e_indent[EI_VERSION]', 0x01) +hexagon-elfdump: ('e_indent[EI_OSABI]', 0x00) +hexagon-elfdump: ('e_indent[EI_ABIVERSION]', 0x00) +hexagon-elfdump: ('e_type', 0x0002) +hexagon-elfdump: ('e_machine', 0x00a4) diff --git a/lld/test/elf/ppc.objtxt b/lld/test/elf/ppc.objtxt new file mode 100644 index 0000000..d3b9344 --- /dev/null +++ b/lld/test/elf/ppc.objtxt @@ -0,0 +1,11 @@ +RUN: lld-core -reader ELF -writer ELF -arch ppc -endian big %p/Inputs/branch-test.ppc %p/Inputs/target-test.ppc -o %t1 +RUN: elf-dump %t1 | FileCheck -check-prefix=ppc-elfdump %s + +ppc-elfdump: ('e_indent[EI_CLASS]', 0x01) +ppc-elfdump: ('e_indent[EI_DATA]', 0x02) +ppc-elfdump: ('e_indent[EI_VERSION]', 0x01) +ppc-elfdump: ('e_indent[EI_OSABI]', 0x00) +ppc-elfdump: ('e_indent[EI_ABIVERSION]', 0x00) +ppc-elfdump: ('e_type', 0x0002) +ppc-elfdump: ('e_machine', 0x0014) + diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp index 9a004cb..5512961 100644 --- a/lld/tools/lld-core/lld-core.cpp +++ b/lld/tools/lld-core/lld-core.cpp @@ -25,6 +25,7 @@ #include "lld/ReaderWriter/WriterYAML.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" @@ -117,7 +118,8 @@ readerSelected("reader", enum ArchChoice { i386 = llvm::ELF::EM_386, x86_64 = llvm::ELF::EM_X86_64, - hexagon = llvm::ELF::EM_HEXAGON + hexagon = llvm::ELF::EM_HEXAGON, + ppc = llvm::ELF::EM_PPC }; llvm::cl::opt archSelected("arch", @@ -129,6 +131,22 @@ archSelected("arch", "x86_64", "output x86_64, EM_X86_64 file"), clEnumValN(hexagon, "hexagon", "output Hexagon, EM_HEXAGON file"), + clEnumValN(ppc, + "ppc", "output PowerPC, EM_PPC file"), + clEnumValEnd)); + + +enum endianChoice { + little, big +}; +llvm::cl::opt +endianSelected("endian", + llvm::cl::desc("Select endianness of ELF output"), + llvm::cl::values( + clEnumValN(big, "big", + "output big endian format"), + clEnumValN(little, "little", + "output little endian format"), clEnumValEnd)); @@ -163,7 +181,10 @@ int main(int argc, char *argv[]) { cmdLineOutputFilePath.assign("-"); // create writer for final output, default to i386 if none selected - WriterOptionsELF writerOptionsELF(false, llvm::support::little, + WriterOptionsELF writerOptionsELF(false, + endianSelected == big + ? llvm::support::big + : llvm::support::little, llvm::ELF::ET_EXEC, archSelected.getValue() == 0 ? i386