ELF: Remove ELFT and LinkingContext template parameters from ELFReader.
Previously, ELFReader takes three template arguments: EFLT, LinkingContextT and FileT. FileT is itself templated. So it was a bit complicated. Maybe too much. Most architectures don't actually need to be parameterized for ELFT. For example, x86 is always ELF32LE and x86-64 is ELF64LE. However, because ELFReader requires a ELFT argument, we needed to parameterize a class even if not needed. This patch removes the parameter from the class. So now we can de-templatize such classes (I didn't do that in this patch, though). This patch also removes ContextT parameter since it didn't have to be passed as a template argument. llvm-svn: 234853
This commit is contained in:
parent
acdee690c8
commit
7bda84d25e
|
|
@ -106,6 +106,7 @@ public:
|
|||
uint16_t getOutputELFType() const { return _outputELFType; }
|
||||
uint16_t getOutputMachine() const;
|
||||
bool mergeCommonStrings() const { return _mergeCommonStrings; }
|
||||
virtual int getMachineType() const = 0;
|
||||
virtual uint64_t getBaseAddress() const { return _baseAddress; }
|
||||
virtual void setBaseAddress(uint64_t address) { _baseAddress = address; }
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ enum {
|
|||
|
||||
class AArch64LinkingContext final : public ELFLinkingContext {
|
||||
public:
|
||||
static const int machine = llvm::ELF::EM_AARCH64;
|
||||
int getMachineType() const override { return llvm::ELF::EM_AARCH64; }
|
||||
AArch64LinkingContext(llvm::Triple);
|
||||
|
||||
void addPasses(PassManager &) override;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace elf {
|
|||
class AArch64LinkingContext;
|
||||
|
||||
class AArch64TargetHandler final : public TargetHandler {
|
||||
typedef ELFReader<ELF64LE, AArch64LinkingContext, ELFFile> ObjReader;
|
||||
typedef ELFReader<ELF64LE, AArch64LinkingContext, DynamicFile> DSOReader;
|
||||
typedef ELFReader<ELFFile<ELF64LE>> ObjReader;
|
||||
typedef ELFReader<DynamicFile<ELF64LE>> DSOReader;
|
||||
|
||||
public:
|
||||
AArch64TargetHandler(AArch64LinkingContext &ctx);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ template <class ELFT> class ARMELFFile : public ELFFile<ELFT> {
|
|||
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
|
||||
|
||||
public:
|
||||
ARMELFFile(std::unique_ptr<MemoryBuffer> mb, ARMLinkingContext &ctx)
|
||||
ARMELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
|
||||
: ELFFile<ELFT>(std::move(mb), ctx) {}
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace elf {
|
|||
|
||||
class ARMLinkingContext final : public ELFLinkingContext {
|
||||
public:
|
||||
static const int machine = llvm::ELF::EM_ARM;
|
||||
int getMachineType() const override { return llvm::ELF::EM_ARM; }
|
||||
ARMLinkingContext(llvm::Triple);
|
||||
|
||||
void addPasses(PassManager &) override;
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ private:
|
|||
};
|
||||
|
||||
class ARMTargetHandler final : public TargetHandler {
|
||||
typedef ELFReader<ELF32LE, ARMLinkingContext, ARMELFFile> ObjReader;
|
||||
typedef ELFReader<ELF32LE, ARMLinkingContext, DynamicFile> DSOReader;
|
||||
typedef ELFReader<ARMELFFile<ELF32LE>> ObjReader;
|
||||
typedef ELFReader<DynamicFile<ELF32LE>> DSOReader;
|
||||
|
||||
public:
|
||||
ARMTargetHandler(ARMLinkingContext &ctx);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ add_llvm_library(lldELF
|
|||
DynamicFile.cpp
|
||||
ELFFile.cpp
|
||||
ELFLinkingContext.cpp
|
||||
FileCommon.cpp
|
||||
Reader.cpp
|
||||
Writer.cpp
|
||||
LINK_LIBS
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DynamicFile.h"
|
||||
#include "FileCommon.h"
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
|
|
@ -29,6 +30,12 @@ DynamicFile<ELFT>::DynamicFile(std::unique_ptr<MemoryBuffer> mb,
|
|||
: SharedLibraryFile(mb->getBufferIdentifier()), _mb(std::move(mb)),
|
||||
_ctx(ctx), _useShlibUndefines(ctx.useShlibUndefines()) {}
|
||||
|
||||
template <typename ELFT>
|
||||
std::error_code DynamicFile<ELFT>::isCompatible(const MemoryBuffer &mb,
|
||||
ELFLinkingContext &ctx) {
|
||||
return lld::elf::isCompatible<ELFT>(mb, ctx);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
const SharedLibraryAtom *DynamicFile<ELFT>::exports(StringRef name,
|
||||
bool dataSymbolOnly) const {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ public:
|
|||
|
||||
DynamicFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
|
||||
|
||||
static std::error_code isCompatible(const MemoryBuffer &mb,
|
||||
ELFLinkingContext &ctx);
|
||||
|
||||
const SharedLibraryAtom *exports(StringRef name,
|
||||
bool dataSymbolOnly) const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ELFFile.h"
|
||||
#include "FileCommon.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
namespace lld {
|
||||
|
|
@ -26,6 +27,12 @@ ELFFile<ELFT>::ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
|
|||
_doStringsMerge(ctx.mergeCommonStrings()),
|
||||
_useWrap(ctx.wrapCalls().size()), _ctx(ctx) {}
|
||||
|
||||
template <typename ELFT>
|
||||
std::error_code ELFFile<ELFT>::isCompatible(const MemoryBuffer &mb,
|
||||
ELFLinkingContext &ctx) {
|
||||
return lld::elf::isCompatible<ELFT>(mb, ctx);
|
||||
}
|
||||
|
||||
template <typename ELFT>
|
||||
Atom *ELFFile<ELFT>::findAtom(const Elf_Sym *sourceSym,
|
||||
const Elf_Sym *targetSym) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#define LLD_READER_WRITER_ELF_FILE_H
|
||||
|
||||
#include "Atoms.h"
|
||||
#include "FileCommon.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
|
@ -89,6 +90,9 @@ public:
|
|||
ELFFile(StringRef name, ELFLinkingContext &ctx);
|
||||
ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
|
||||
|
||||
static std::error_code isCompatible(const MemoryBuffer &mb,
|
||||
ELFLinkingContext &ctx);
|
||||
|
||||
static bool canParse(file_magic magic) {
|
||||
return magic == file_magic::elf_relocatable;
|
||||
}
|
||||
|
|
@ -334,6 +338,8 @@ protected:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static bool isCompatible(unsigned char size, unsigned char endian);
|
||||
|
||||
llvm::BumpPtrAllocator _readerStorage;
|
||||
std::unique_ptr<llvm::object::ELFFile<ELFT> > _objFile;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,60 +20,25 @@
|
|||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
template <typename ELFT, typename ContextT, template <typename> class FileT>
|
||||
class ELFReader : public Reader {
|
||||
template <typename FileT> class ELFReader : public Reader {
|
||||
public:
|
||||
typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
|
||||
|
||||
ELFReader(ContextT &ctx) : _ctx(ctx) {}
|
||||
ELFReader(ELFLinkingContext &ctx) : _ctx(ctx) {}
|
||||
|
||||
bool canParse(file_magic magic, const MemoryBuffer &mb) const override {
|
||||
return (FileT<ELFT>::canParse(magic) &&
|
||||
elfHeader(mb)->e_machine == ContextT::machine);
|
||||
return FileT::canParse(magic);
|
||||
}
|
||||
|
||||
std::error_code
|
||||
loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
|
||||
std::vector<std::unique_ptr<File>> &result) const override {
|
||||
const Elf_Ehdr *hdr = elfHeader(*mb);
|
||||
if (auto ec = _ctx.mergeHeaderFlags(hdr->getFileClass(), hdr->e_flags))
|
||||
if (std::error_code ec = FileT::isCompatible(*mb, _ctx))
|
||||
return ec;
|
||||
result.push_back(createELF(std::move(mb)));
|
||||
result.push_back(llvm::make_unique<FileT>(std::move(mb), _ctx));
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
private:
|
||||
/// Create an object depending on the runtime attributes and alignment
|
||||
/// of an ELF file.
|
||||
std::unique_ptr<File> createELF(std::unique_ptr<MemoryBuffer> mb) const {
|
||||
using namespace llvm::ELF;
|
||||
using namespace llvm::support;
|
||||
|
||||
if (uintptr_t(mb->getBufferStart()) & 1)
|
||||
llvm_unreachable("Invalid alignment for ELF file!");
|
||||
unsigned char size;
|
||||
unsigned char endian;
|
||||
std::tie(size, endian) = llvm::object::getElfArchType(mb->getBuffer());
|
||||
File *file = nullptr;
|
||||
if (size == ELFCLASS32 && endian == ELFDATA2LSB) {
|
||||
file = new FileT<ELF32LE>(std::move(mb), _ctx);
|
||||
} else if (size == ELFCLASS32 && endian == ELFDATA2MSB) {
|
||||
file = new FileT<ELF32BE>(std::move(mb), _ctx);
|
||||
} else if (size == ELFCLASS64 && endian == ELFDATA2LSB) {
|
||||
file = new FileT<ELF64LE>(std::move(mb), _ctx);
|
||||
} else if (size == ELFCLASS64 && endian == ELFDATA2MSB) {
|
||||
file = new FileT<ELF64BE>(std::move(mb), _ctx);
|
||||
}
|
||||
if (!file)
|
||||
llvm_unreachable("Invalid ELF type!");
|
||||
return std::unique_ptr<File>(file);
|
||||
}
|
||||
|
||||
static const Elf_Ehdr *elfHeader(const MemoryBuffer &buf) {
|
||||
return reinterpret_cast<const Elf_Ehdr *>(buf.getBuffer().data());
|
||||
}
|
||||
|
||||
ContextT &_ctx;
|
||||
ELFLinkingContext &_ctx;
|
||||
};
|
||||
|
||||
} // namespace elf
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
//===- lib/ReaderWriter/ELF/FileCommon.cpp --------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ELFFile.h"
|
||||
#include "FileCommon.h"
|
||||
|
||||
using namespace llvm::ELF;
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
template <>
|
||||
std::error_code checkCompatibility<ELF32LE>(unsigned char size,
|
||||
unsigned char endian) {
|
||||
if (size == ELFCLASS64)
|
||||
return make_dynamic_error_code("ELF32 expected, but got ELF64");
|
||||
if (endian == ELFDATA2MSB)
|
||||
return make_dynamic_error_code(
|
||||
"Little endian files are expected, but got a big endian file.");
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <>
|
||||
std::error_code checkCompatibility<ELF32BE>(unsigned char size,
|
||||
unsigned char endian) {
|
||||
if (size == ELFCLASS64)
|
||||
return make_dynamic_error_code("ELF32 expected, but got ELF64");
|
||||
if (endian == ELFDATA2LSB)
|
||||
return make_dynamic_error_code(
|
||||
"Big endian files are expected, but got a little endian file.");
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <>
|
||||
std::error_code checkCompatibility<ELF64LE>(unsigned char size,
|
||||
unsigned char endian) {
|
||||
if (size == ELFCLASS32)
|
||||
return make_dynamic_error_code("ELF64 expected, but got ELF32");
|
||||
if (endian == ELFDATA2MSB)
|
||||
return make_dynamic_error_code(
|
||||
"Little endian files are expected, but got a big endian file.");
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <>
|
||||
std::error_code checkCompatibility<ELF64BE>(unsigned char size,
|
||||
unsigned char endian) {
|
||||
if (size == ELFCLASS32)
|
||||
return make_dynamic_error_code("ELF64 expected, but got ELF32");
|
||||
if (endian == ELFDATA2LSB)
|
||||
return make_dynamic_error_code(
|
||||
"Big endian files are expected, but got a little endian file.");
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
//===- lib/ReaderWriter/ELF/FileCommon.h ----------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_ELF_FILE_COMMON_H
|
||||
#define LLD_READER_WRITER_ELF_FILE_COMMON_H
|
||||
|
||||
#include "lld/ReaderWriter/ELFLinkingContext.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
template <class ELFT>
|
||||
std::error_code checkCompatibility(unsigned char size, unsigned char endian);
|
||||
|
||||
template <typename ELFT>
|
||||
std::error_code isCompatible(const MemoryBuffer &mb, ELFLinkingContext &ctx) {
|
||||
typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
|
||||
|
||||
if (uintptr_t(mb.getBufferStart()) & 1)
|
||||
return make_dynamic_error_code("invalid alignment");
|
||||
|
||||
auto *hdr = reinterpret_cast<const Elf_Ehdr *>(mb.getBuffer().data());
|
||||
if (hdr->e_machine != ctx.getMachineType())
|
||||
return make_dynamic_error_code("incompatible machine type");
|
||||
|
||||
unsigned char size;
|
||||
unsigned char endian;
|
||||
std::tie(size, endian) = llvm::object::getElfArchType(mb.getBuffer());
|
||||
if (std::error_code ec = checkCompatibility<ELFT>(size, endian))
|
||||
return ec;
|
||||
|
||||
if (auto ec = ctx.mergeHeaderFlags(hdr->getFileClass(), hdr->e_flags))
|
||||
return ec;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
} // end namespace elf
|
||||
} // end namespace lld
|
||||
|
||||
#endif
|
||||
|
|
@ -108,7 +108,7 @@ template <class ELFT> class HexagonELFFile : public ELFFile<ELFT> {
|
|||
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
|
||||
|
||||
public:
|
||||
HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, HexagonLinkingContext &ctx)
|
||||
HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
|
||||
: ELFFile<ELFT>(std::move(mb), ctx) {}
|
||||
|
||||
bool isCommonSymbol(const Elf_Sym *symbol) const override {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace elf {
|
|||
|
||||
class HexagonLinkingContext final : public ELFLinkingContext {
|
||||
public:
|
||||
static const int machine = llvm::ELF::EM_HEXAGON;
|
||||
int getMachineType() const override { return llvm::ELF::EM_HEXAGON; }
|
||||
HexagonLinkingContext(llvm::Triple triple);
|
||||
|
||||
void addPasses(PassManager &) override;
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ private:
|
|||
|
||||
/// \brief TargetHandler for Hexagon
|
||||
class HexagonTargetHandler final : public TargetHandler {
|
||||
typedef ELFReader<ELF32LE, HexagonLinkingContext, HexagonELFFile> ObjReader;
|
||||
typedef ELFReader<ELF32LE, HexagonLinkingContext, DynamicFile> ELFDSOReader;
|
||||
typedef ELFReader<HexagonELFFile<ELF32LE>> ObjReader;
|
||||
typedef ELFReader<DynamicFile<ELF32LE>> ELFDSOReader;
|
||||
|
||||
public:
|
||||
HexagonTargetHandler(HexagonLinkingContext &targetInfo);
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ private:
|
|||
|
||||
template <class ELFT> class MipsELFFile : public ELFFile<ELFT> {
|
||||
public:
|
||||
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, MipsLinkingContext &ctx)
|
||||
MipsELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
|
||||
: ELFFile<ELFT>(std::move(mb), ctx) {}
|
||||
|
||||
bool isPIC() const {
|
||||
|
|
|
|||
|
|
@ -66,11 +66,6 @@ uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
|
|||
|
||||
std::error_code MipsELFFlagsMerger::mergeHeaderFlags(uint8_t newClass,
|
||||
uint32_t newFlags) {
|
||||
// Check bitness.
|
||||
if (_is64Bit != (newClass == ELFCLASS64))
|
||||
return make_dynamic_error_code(
|
||||
"Bitness is incompatible with that of the selected target");
|
||||
|
||||
// We support two ABI: O32 and N64. The last one does not have
|
||||
// the corresponding ELF flag.
|
||||
uint32_t inAbi = newFlags & EF_MIPS_ABI;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ enum {
|
|||
|
||||
class MipsLinkingContext final : public ELFLinkingContext {
|
||||
public:
|
||||
static const int machine = llvm::ELF::EM_MIPS;
|
||||
int getMachineType() const override { return llvm::ELF::EM_MIPS; }
|
||||
MipsLinkingContext(llvm::Triple triple);
|
||||
|
||||
std::error_code mergeHeaderFlags(uint8_t fileClass, uint64_t flags) override;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ namespace elf {
|
|||
|
||||
/// \brief TargetHandler for Mips
|
||||
template <class ELFT> class MipsTargetHandler final : public TargetHandler {
|
||||
typedef ELFReader<ELFT, MipsLinkingContext, MipsELFFile> ObjReader;
|
||||
typedef ELFReader<ELFT, MipsLinkingContext, DynamicFile> DSOReader;
|
||||
typedef ELFReader<MipsELFFile<ELFT>> ObjReader;
|
||||
typedef ELFReader<DynamicFile<ELFT>> DSOReader;
|
||||
|
||||
public:
|
||||
MipsTargetHandler(MipsLinkingContext &ctx)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace elf {
|
|||
class X86LinkingContext final : public ELFLinkingContext {
|
||||
public:
|
||||
static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
|
||||
static const int machine = llvm::ELF::EM_386;
|
||||
int getMachineType() const override { return llvm::ELF::EM_386; }
|
||||
X86LinkingContext(llvm::Triple);
|
||||
void registerRelocationNames(Registry &r) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace elf {
|
|||
class X86LinkingContext;
|
||||
|
||||
class X86TargetHandler final : public TargetHandler {
|
||||
typedef ELFReader<ELF32LE, X86LinkingContext, ELFFile> ObjReader;
|
||||
typedef ELFReader<ELF32LE, X86LinkingContext, DynamicFile> DSOReader;
|
||||
typedef ELFReader<ELFFile<ELF32LE>> ObjReader;
|
||||
typedef ELFReader<DynamicFile<ELF32LE>> DSOReader;
|
||||
|
||||
public:
|
||||
X86TargetHandler(X86LinkingContext &ctx);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ protected:
|
|||
|
||||
public:
|
||||
static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
|
||||
static const int machine = llvm::ELF::EM_X86_64;
|
||||
int getMachineType() const override { return llvm::ELF::EM_X86_64; }
|
||||
X86_64LinkingContext(llvm::Triple);
|
||||
|
||||
void addPasses(PassManager &) override;
|
||||
|
|
|
|||
|
|
@ -58,9 +58,8 @@ private:
|
|||
};
|
||||
|
||||
class X86_64TargetHandler : public TargetHandler {
|
||||
typedef llvm::object::ELFType<llvm::support::little, 2, true> ELFT;
|
||||
typedef ELFReader<ELFT, X86_64LinkingContext, ELFFile> ObjReader;
|
||||
typedef ELFReader<ELFT, X86_64LinkingContext, DynamicFile> DSOReader;
|
||||
typedef ELFReader<ELFFile<ELF64LE>> ObjReader;
|
||||
typedef ELFReader<DynamicFile<ELF64LE>> DSOReader;
|
||||
|
||||
public:
|
||||
X86_64TargetHandler(X86_64LinkingContext &ctx);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# RUN: not lld -flavor gnu -target mips64el -shared -o %t.so \
|
||||
# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: Bitness is incompatible with that of the selected target
|
||||
# CHECK: ELF64 expected, but got ELF32
|
||||
|
||||
# 32.o
|
||||
---
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so \
|
||||
# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: Bitness is incompatible with that of the selected target
|
||||
# CHECK: ELF32 expected, but got ELF64
|
||||
|
||||
# 32.o
|
||||
---
|
||||
|
|
|
|||
Loading…
Reference in New Issue