aboutsummaryrefslogtreecommitdiffstats
path: root/ELF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-06 20:14:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-06 20:14:02 +0000
commitc09ce7fd2d62d85dcdf370f4bef732380fca4f1b (patch)
treedd5cf05b9ae703e6fb816b9663d4a0c903e0c2c6 /ELF
parent5d4d137132d719d0d20d119375b205d6a2c721ee (diff)
downloadsrc-c09ce7fd2d62d85dcdf370f4bef732380fca4f1b.tar.gz
src-c09ce7fd2d62d85dcdf370f4bef732380fca4f1b.zip
Vendor import of lld trunk r291274:vendor/lld/lld-trunk-r291274
Notes
Notes: svn path=/vendor/lld/dist/; revision=311540 svn path=/vendor/lld/lld-trunk-r291274/; revision=311541; tag=vendor/lld/lld-trunk-r291274
Diffstat (limited to 'ELF')
-rw-r--r--ELF/Driver.cpp25
-rw-r--r--ELF/Driver.h3
-rw-r--r--ELF/DriverUtils.cpp2
-rw-r--r--ELF/InputFiles.cpp11
-rw-r--r--ELF/InputFiles.h11
-rw-r--r--ELF/InputSection.cpp10
-rw-r--r--ELF/InputSection.h5
-rw-r--r--ELF/LinkerScript.cpp32
-rw-r--r--ELF/OutputSections.cpp126
-rw-r--r--ELF/OutputSections.h27
-rw-r--r--ELF/Symbols.cpp2
-rw-r--r--ELF/Symbols.h5
-rw-r--r--ELF/Target.cpp8
-rw-r--r--ELF/Target.h3
14 files changed, 145 insertions, 125 deletions
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index a11dbc7cc47f..6afbe62e5ec7 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -25,6 +25,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
@@ -182,8 +183,8 @@ Optional<MemoryBufferRef> LinkerDriver::readFile(StringRef Path) {
MemoryBufferRef MBRef = MB->getMemBufferRef();
make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
- if (Cpio)
- Cpio->append(relativeToRoot(Path), MBRef.getBuffer());
+ if (Tar)
+ Tar->append(relativeToRoot(Path), MBRef.getBuffer());
return MBRef;
}
@@ -309,14 +310,16 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
if (const char *Path = getReproduceOption(Args)) {
// Note that --reproduce is a debug option so you can ignore it
// if you are trying to understand the whole picture of the code.
- ErrorOr<CpioFile *> F = CpioFile::create(Path);
- if (F) {
- Cpio.reset(*F);
- Cpio->append("response.txt", createResponseFile(Args));
- Cpio->append("version.txt", getLLDVersion() + "\n");
- } else
- error(F.getError(),
- Twine("--reproduce: failed to open ") + Path + ".cpio");
+ Expected<std::unique_ptr<TarWriter>> ErrOrWriter =
+ TarWriter::create(Path, path::stem(Path));
+ if (ErrOrWriter) {
+ Tar = std::move(*ErrOrWriter);
+ Tar->append("response.txt", createResponseFile(Args));
+ Tar->append("version.txt", getLLDVersion() + "\n");
+ } else {
+ error(Twine("--reproduce: failed to open ") + Path + ": " +
+ toString(ErrOrWriter.takeError()));
+ }
}
readConfigs(Args);
@@ -423,7 +426,7 @@ static uint64_t parseSectionAddress(StringRef S, opt::Arg *Arg) {
if (S.startswith("0x"))
S = S.drop_front(2);
if (S.getAsInteger(16, VA))
- error("invalid argument: " + stringize(Arg));
+ error("invalid argument: " + toString(Arg));
return VA;
}
diff --git a/ELF/Driver.h b/ELF/Driver.h
index cba1eb164fdd..dadee5eef355 100644
--- a/ELF/Driver.h
+++ b/ELF/Driver.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/TarWriter.h"
#include "llvm/Support/raw_ostream.h"
namespace lld {
@@ -29,7 +30,7 @@ public:
void main(ArrayRef<const char *> Args, bool CanExitEarly);
void addFile(StringRef Path);
void addLibrary(StringRef Name);
- std::unique_ptr<CpioFile> Cpio; // for reproduce
+ std::unique_ptr<llvm::TarWriter> Tar; // for reproduce
private:
std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
diff --git a/ELF/DriverUtils.cpp b/ELF/DriverUtils.cpp
index a81b133f674b..3a20cd76efe2 100644
--- a/ELF/DriverUtils.cpp
+++ b/ELF/DriverUtils.cpp
@@ -146,7 +146,7 @@ std::string elf::createResponseFile(const opt::InputArgList &Args) {
<< "\n";
break;
default:
- OS << stringize(Arg) << "\n";
+ OS << toString(Arg) << "\n";
}
}
return Data.str();
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index f4128c5096cb..bd9f25873c87 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -92,12 +92,11 @@ std::string elf::ObjectFile<ELFT>::getLineInfo(InputSectionBase<ELFT> *S,
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info);
if (Info.Line == 0)
return "";
- return convertToUnixPathSeparator(Info.FileName) + ":" +
- std::to_string(Info.Line);
+ return Info.FileName + ":" + std::to_string(Info.Line);
}
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
-std::string elf::toString(const InputFile *F) {
+std::string lld::toString(const InputFile *F) {
if (!F)
return "(internal)";
if (!F->ArchiveName.empty())
@@ -525,9 +524,9 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) {
"could not get the buffer for the member defining symbol " +
Sym->getName());
- if (C.getParent()->isThin() && Driver->Cpio)
- Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
- Ret.getBuffer());
+ if (C.getParent()->isThin() && Driver->Tar)
+ Driver->Tar->append(relativeToRoot(check(C.getFullName())),
+ Ret.getBuffer());
if (C.getParent()->isThin())
return {Ret, 0};
return {Ret, C.getChildOffset()};
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index aba1d71379b0..8b188348199f 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -36,10 +36,16 @@ class InputFile;
namespace lld {
namespace elf {
+class InputFile;
+}
+
+// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
+std::string toString(const elf::InputFile *F);
+
+namespace elf {
using llvm::object::Archive;
-class InputFile;
class Lazy;
class SymbolBody;
@@ -84,9 +90,6 @@ private:
const Kind FileKind;
};
-// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
-std::string toString(const InputFile *F);
-
template <typename ELFT> class ELFFileBase : public InputFile {
public:
typedef typename ELFT::Shdr Elf_Shdr;
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index 805e51dab507..e87d92aa207c 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -34,7 +34,7 @@ using namespace lld::elf;
// Returns a string to construct an error message.
template <class ELFT>
-std::string elf::toString(const InputSectionBase<ELFT> *Sec) {
+std::string lld::toString(const InputSectionBase<ELFT> *Sec) {
return (Sec->getFile()->getName() + ":(" + Sec->Name + ")").str();
}
@@ -844,7 +844,7 @@ template class elf::MergeInputSection<ELF32BE>;
template class elf::MergeInputSection<ELF64LE>;
template class elf::MergeInputSection<ELF64BE>;
-template std::string elf::toString(const InputSectionBase<ELF32LE> *);
-template std::string elf::toString(const InputSectionBase<ELF32BE> *);
-template std::string elf::toString(const InputSectionBase<ELF64LE> *);
-template std::string elf::toString(const InputSectionBase<ELF64BE> *);
+template std::string lld::toString(const InputSectionBase<ELF32LE> *);
+template std::string lld::toString(const InputSectionBase<ELF32BE> *);
+template std::string lld::toString(const InputSectionBase<ELF64LE> *);
+template std::string lld::toString(const InputSectionBase<ELF64BE> *);
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
index adbc1e1e3829..fc7a7fb60973 100644
--- a/ELF/InputSection.h
+++ b/ELF/InputSection.h
@@ -318,10 +318,9 @@ private:
};
template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded;
-
-template <class ELFT> std::string toString(const InputSectionBase<ELFT> *);
-
} // namespace elf
+
+template <class ELFT> std::string toString(const elf::InputSectionBase<ELFT> *);
} // namespace lld
#endif
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index 5057b57a4a54..ccc1059949db 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -264,42 +264,12 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) {
}
template <class ELFT>
-static SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
- StringRef OutsecName) {
- // When using linker script the merge rules are different.
- // Unfortunately, linker scripts are name based. This means that expressions
- // like *(.foo*) can refer to multiple input sections that would normally be
- // placed in different output sections. We cannot put them in different
- // output sections or we would produce wrong results for
- // start = .; *(.foo.*) end = .; *(.bar)
- // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to
- // another. The problem is that there is no way to layout those output
- // sections such that the .foo sections are the only thing between the
- // start and end symbols.
-
- // An extra annoyance is that we cannot simply disable merging of the contents
- // of SHF_MERGE sections, but our implementation requires one output section
- // per "kind" (string or not, which size/aligment).
- // Fortunately, creating symbols in the middle of a merge section is not
- // supported by bfd or gold, so we can just create multiple section in that
- // case.
- typedef typename ELFT::uint uintX_t;
- uintX_t Flags = C->Flags & (SHF_MERGE | SHF_STRINGS);
-
- uintX_t Alignment = 0;
- if (isa<MergeInputSection<ELFT>>(C))
- Alignment = std::max<uintX_t>(C->Alignment, C->Entsize);
-
- return SectionKey<ELFT::Is64Bits>{OutsecName, /*Type*/ 0, Flags, Alignment};
-}
-
-template <class ELFT>
void LinkerScript<ELFT>::addSection(OutputSectionFactory<ELFT> &Factory,
InputSectionBase<ELFT> *Sec,
StringRef Name) {
OutputSectionBase *OutSec;
bool IsNew;
- std::tie(OutSec, IsNew) = Factory.create(createKey(Sec, Name), Sec);
+ std::tie(OutSec, IsNew) = Factory.create(Sec, Name);
if (IsNew)
OutputSections->push_back(OutSec);
OutSec->addSection(Sec);
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index bf7f9c29a29a..a9d951dcc745 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -534,41 +534,111 @@ static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) {
return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
}
+namespace llvm {
+template <> struct DenseMapInfo<lld::elf::SectionKey> {
+ static lld::elf::SectionKey getEmptyKey();
+ static lld::elf::SectionKey getTombstoneKey();
+ static unsigned getHashValue(const lld::elf::SectionKey &Val);
+ static bool isEqual(const lld::elf::SectionKey &LHS,
+ const lld::elf::SectionKey &RHS);
+};
+}
+
template <class ELFT>
-static SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
- StringRef OutsecName) {
+static SectionKey createKey(InputSectionBase<ELFT> *C, StringRef OutsecName) {
+ // The ELF spec just says
+ // ----------------------------------------------------------------
+ // In the first phase, input sections that match in name, type and
+ // attribute flags should be concatenated into single sections.
+ // ----------------------------------------------------------------
+ //
+ // However, it is clear that at least some flags have to be ignored for
+ // section merging. At the very least SHF_GROUP and SHF_COMPRESSED have to be
+ // ignored. We should not have two output .text sections just because one was
+ // in a group and another was not for example.
+ //
+ // It also seems that that wording was a late addition and didn't get the
+ // necessary scrutiny.
+ //
+ // Merging sections with different flags is expected by some users. One
+ // reason is that if one file has
+ //
+ // int *const bar __attribute__((section(".foo"))) = (int *)0;
+ //
+ // gcc with -fPIC will produce a read only .foo section. But if another
+ // file has
+ //
+ // int zed;
+ // int *const bar __attribute__((section(".foo"))) = (int *)&zed;
+ //
+ // gcc with -fPIC will produce a read write section.
+ //
+ // Last but not least, when using linker script the merge rules are forced by
+ // the script. Unfortunately, linker scripts are name based. This means that
+ // expressions like *(.foo*) can refer to multiple input sections with
+ // different flags. We cannot put them in different output sections or we
+ // would produce wrong results for
+ //
+ // start = .; *(.foo.*) end = .; *(.bar)
+ //
+ // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to
+ // another. The problem is that there is no way to layout those output
+ // sections such that the .foo sections are the only thing between the start
+ // and end symbols.
+ //
+ // Given the above issues, we instead merge sections by name and error on
+ // incompatible types and flags.
+ //
+ // The exception being SHF_MERGE, where we create different output sections
+ // for each alignment. This makes each output section simple. In case of
+ // relocatable object generation we do not try to perform merging and treat
+ // SHF_MERGE sections as regular ones, but also create different output
+ // sections for them to allow merging at final linking stage.
+ //
+ // Fortunately, creating symbols in the middle of a merge section is not
+ // supported by bfd or gold, so the SHF_MERGE exception should not cause
+ // problems with most linker scripts.
+
typedef typename ELFT::uint uintX_t;
- uintX_t Flags = getOutFlags(C);
+ uintX_t Flags = C->Flags & (SHF_MERGE | SHF_STRINGS);
- // For SHF_MERGE we create different output sections for each alignment.
- // This makes each output section simple and keeps a single level mapping from
- // input to output.
- // In case of relocatable object generation we do not try to perform merging
- // and treat SHF_MERGE sections as regular ones, but also create different
- // output sections for them to allow merging at final linking stage.
uintX_t Alignment = 0;
if (isa<MergeInputSection<ELFT>>(C) ||
(Config->Relocatable && (C->Flags & SHF_MERGE)))
Alignment = std::max<uintX_t>(C->Alignment, C->Entsize);
- return SectionKey<ELFT::Is64Bits>{OutsecName, C->Type, Flags, Alignment};
+ return SectionKey{OutsecName, Flags, Alignment};
}
+template <class ELFT> OutputSectionFactory<ELFT>::OutputSectionFactory() {}
+
+template <class ELFT> OutputSectionFactory<ELFT>::~OutputSectionFactory() {}
+
template <class ELFT>
std::pair<OutputSectionBase *, bool>
OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
StringRef OutsecName) {
- SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName);
+ SectionKey Key = createKey(C, OutsecName);
return create(Key, C);
}
+static uint64_t getIncompatibleFlags(uint64_t Flags) {
+ return Flags & (SHF_ALLOC | SHF_TLS);
+}
+
template <class ELFT>
std::pair<OutputSectionBase *, bool>
-OutputSectionFactory<ELFT>::create(const SectionKey<ELFT::Is64Bits> &Key,
+OutputSectionFactory<ELFT>::create(const SectionKey &Key,
InputSectionBase<ELFT> *C) {
uintX_t Flags = getOutFlags(C);
OutputSectionBase *&Sec = Map[Key];
if (Sec) {
+ if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(C->Flags))
+ error("Section has flags incompatible with others with the same name " +
+ toString(C));
+ if (Sec->Type != C->Type)
+ error("Section has different type from others with the same name " +
+ toString(C));
Sec->Flags |= Flags;
return {Sec, false};
}
@@ -588,36 +658,22 @@ OutputSectionFactory<ELFT>::create(const SectionKey<ELFT::Is64Bits> &Key,
return {Sec, true};
}
-template <bool Is64Bits>
-typename lld::elf::SectionKey<Is64Bits>
-DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getEmptyKey() {
- return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0, 0};
+SectionKey DenseMapInfo<SectionKey>::getEmptyKey() {
+ return SectionKey{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0};
}
-template <bool Is64Bits>
-typename lld::elf::SectionKey<Is64Bits>
-DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getTombstoneKey() {
- return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0,
- 0};
+SectionKey DenseMapInfo<SectionKey>::getTombstoneKey() {
+ return SectionKey{DenseMapInfo<StringRef>::getTombstoneKey(), 0, 0};
}
-template <bool Is64Bits>
-unsigned
-DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::getHashValue(const Key &Val) {
- return hash_combine(Val.Name, Val.Type, Val.Flags, Val.Alignment);
+unsigned DenseMapInfo<SectionKey>::getHashValue(const SectionKey &Val) {
+ return hash_combine(Val.Name, Val.Flags, Val.Alignment);
}
-template <bool Is64Bits>
-bool DenseMapInfo<lld::elf::SectionKey<Is64Bits>>::isEqual(const Key &LHS,
- const Key &RHS) {
+bool DenseMapInfo<SectionKey>::isEqual(const SectionKey &LHS,
+ const SectionKey &RHS) {
return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
- LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
- LHS.Alignment == RHS.Alignment;
-}
-
-namespace llvm {
-template struct DenseMapInfo<SectionKey<true>>;
-template struct DenseMapInfo<SectionKey<false>>;
+ LHS.Flags == RHS.Flags && LHS.Alignment == RHS.Alignment;
}
namespace lld {
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index 978b1f8191ef..45e1a232e2a9 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -217,12 +217,10 @@ template <class ELFT> struct Out {
static OutputSectionBase *FiniArray;
};
-template <bool Is64Bits> struct SectionKey {
- typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
+struct SectionKey {
StringRef Name;
- uint32_t Type;
- uintX_t Flags;
- uintX_t Alignment;
+ uint64_t Flags;
+ uint64_t Alignment;
};
// This class knows how to create an output section for a given
@@ -232,16 +230,17 @@ template <bool Is64Bits> struct SectionKey {
template <class ELFT> class OutputSectionFactory {
typedef typename ELFT::Shdr Elf_Shdr;
typedef typename ELFT::uint uintX_t;
- typedef typename elf::SectionKey<ELFT::Is64Bits> Key;
public:
+ OutputSectionFactory();
+ ~OutputSectionFactory();
std::pair<OutputSectionBase *, bool> create(InputSectionBase<ELFT> *C,
StringRef OutsecName);
- std::pair<OutputSectionBase *, bool>
- create(const SectionKey<ELFT::Is64Bits> &Key, InputSectionBase<ELFT> *C);
+ std::pair<OutputSectionBase *, bool> create(const SectionKey &Key,
+ InputSectionBase<ELFT> *C);
private:
- llvm::SmallDenseMap<Key, OutputSectionBase *> Map;
+ llvm::SmallDenseMap<SectionKey, OutputSectionBase *> Map;
};
template <class ELFT> uint64_t getHeaderSize() {
@@ -265,15 +264,5 @@ template <class ELFT> OutputSectionBase *Out<ELFT>::FiniArray;
} // namespace elf
} // namespace lld
-namespace llvm {
-template <bool Is64Bits> struct DenseMapInfo<lld::elf::SectionKey<Is64Bits>> {
- typedef typename lld::elf::SectionKey<Is64Bits> Key;
-
- static Key getEmptyKey();
- static Key getTombstoneKey();
- static unsigned getHashValue(const Key &Val);
- static bool isEqual(const Key &LHS, const Key &RHS);
-};
-}
#endif
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index f168d37bdf0a..72bcff4e0f4d 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -305,7 +305,7 @@ void elf::printTraceSymbol(Symbol *Sym) {
}
// Returns a symbol for an error message.
-std::string elf::toString(const SymbolBody &B) {
+std::string lld::toString(const SymbolBody &B) {
if (Config->Demangle)
if (Optional<std::string> S = demangle(B.getName()))
return *S;
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index cbf8fa81a138..38889571679c 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -453,10 +453,9 @@ inline Symbol *SymbolBody::symbol() {
return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
offsetof(Symbol, Body));
}
-
-std::string toString(const SymbolBody &B);
-
} // namespace elf
+
+std::string toString(const elf::SymbolBody &B);
} // namespace lld
#endif
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index d82e654b9c4c..cb2b178fa849 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -44,6 +44,10 @@ using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;
+std::string lld::toString(uint32_t Type) {
+ return getELFRelocationTypeName(elf::Config->EMachine, Type);
+}
+
namespace lld {
namespace elf {
@@ -52,10 +56,6 @@ TargetInfo *Target;
static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
static void or32be(uint8_t *P, int32_t V) { write32be(P, read32be(P) | V); }
-std::string toString(uint32_t Type) {
- return getELFRelocationTypeName(Config->EMachine, Type);
-}
-
template <class ELFT> static std::string getErrorLoc(uint8_t *Loc) {
for (InputSectionData *D : Symtab<ELFT>::X->Sections) {
auto *IS = dyn_cast_or_null<InputSection<ELFT>>(D);
diff --git a/ELF/Target.h b/ELF/Target.h
index 156a2c023230..752f9cd5ee4e 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -104,13 +104,14 @@ public:
virtual void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
};
-std::string toString(uint32_t RelType);
uint64_t getPPC64TocBase();
uint64_t getAArch64Page(uint64_t Expr);
extern TargetInfo *Target;
TargetInfo *createTarget();
}
+
+std::string toString(uint32_t RelType);
}
#endif