diff options
Diffstat (limited to 'lib/ReaderWriter/PECOFF/Pass.cpp')
-rw-r--r-- | lib/ReaderWriter/PECOFF/Pass.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/ReaderWriter/PECOFF/Pass.cpp b/lib/ReaderWriter/PECOFF/Pass.cpp new file mode 100644 index 000000000000..ed731984e378 --- /dev/null +++ b/lib/ReaderWriter/PECOFF/Pass.cpp @@ -0,0 +1,95 @@ +//===- lib/ReaderWriter/PECOFF/Pass.cpp -----------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Atoms.h" +#include "Pass.h" +#include "lld/Core/File.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/COFF.h" + +namespace lld { +namespace pecoff { + +static void addReloc(COFFBaseDefinedAtom *atom, const Atom *target, + size_t offsetInAtom, Reference::KindArch arch, + Reference::KindValue relType) { + atom->addReference(llvm::make_unique<SimpleReference>( + Reference::KindNamespace::COFF, arch, relType, offsetInAtom, target, 0)); +} + +void addDir64Reloc(COFFBaseDefinedAtom *atom, const Atom *target, + llvm::COFF::MachineTypes machine, size_t offsetInAtom) { + switch (machine) { + case llvm::COFF::IMAGE_FILE_MACHINE_I386: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86, + llvm::COFF::IMAGE_REL_I386_DIR32); + return; + case llvm::COFF::IMAGE_FILE_MACHINE_AMD64: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64, + llvm::COFF::IMAGE_REL_AMD64_ADDR64); + return; + default: + llvm_unreachable("unsupported machine type"); + } +} + +void addDir32Reloc(COFFBaseDefinedAtom *atom, const Atom *target, + llvm::COFF::MachineTypes machine, size_t offsetInAtom) { + switch (machine) { + case llvm::COFF::IMAGE_FILE_MACHINE_I386: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86, + llvm::COFF::IMAGE_REL_I386_DIR32); + return; + case llvm::COFF::IMAGE_FILE_MACHINE_AMD64: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64, + llvm::COFF::IMAGE_REL_AMD64_ADDR32); + return; + default: + llvm_unreachable("unsupported machine type"); + } +} + +void addDir32NBReloc(COFFBaseDefinedAtom *atom, const Atom *target, + llvm::COFF::MachineTypes machine, size_t offsetInAtom) { + switch (machine) { + case llvm::COFF::IMAGE_FILE_MACHINE_I386: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86, + llvm::COFF::IMAGE_REL_I386_DIR32NB); + return; + case llvm::COFF::IMAGE_FILE_MACHINE_AMD64: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64, + llvm::COFF::IMAGE_REL_AMD64_ADDR32NB); + return; + case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT: + addReloc(atom, target, offsetInAtom, Reference::KindArch::ARM, + llvm::COFF::IMAGE_REL_ARM_ADDR32NB); + return; + default: + llvm_unreachable("unsupported machine type"); + } +} + +void addRel32Reloc(COFFBaseDefinedAtom *atom, const Atom *target, + llvm::COFF::MachineTypes machine, size_t offsetInAtom) { + switch (machine) { + case llvm::COFF::IMAGE_FILE_MACHINE_I386: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86, + llvm::COFF::IMAGE_REL_I386_REL32); + return; + case llvm::COFF::IMAGE_FILE_MACHINE_AMD64: + addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64, + llvm::COFF::IMAGE_REL_AMD64_REL32); + return; + default: + llvm_unreachable("unsupported machine type"); + } +} + +} // end namespace pecoff +} // end namespace lld |