llvm-6502/lib/Target/ARM/MCTargetDesc/ARMWinCOFFObjectWriter.cpp
Saleem Abdulrasool cba7ac7bda MC: correct IMAGE_REL_ARM_MOV32T relocation emission
This corrects the emission of IMAGE_REL_ARM_MOV32T relocations.  Previously, we
were avoiding the high portion of the relocation too early.  If there was a
section-relative relocation with an offset greater than 16-bits (65535), you
would end up truncating the high order bits of the offset.  Allow the current
relocation representation to flow through out the MC layer to the object writer.
Use the new ability to restrict recorded relocations to avoid emitting the
relocation into the final object.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209337 91177308-0d34-0410-b5e6-96231b3b80d8
2014-05-21 23:17:56 +00:00

83 lines
2.7 KiB
C++

//===-- ARMWinCOFFObjectWriter.cpp - ARM Windows COFF Object Writer -- C++ -==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/ARMFixupKinds.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCWinCOFFObjectWriter.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
namespace {
class ARMWinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
public:
ARMWinCOFFObjectWriter(bool Is64Bit)
: MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_ARMNT) {
assert(!Is64Bit && "AArch64 support not yet implemented");
}
virtual ~ARMWinCOFFObjectWriter() { }
unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,
bool IsCrossSection) const override;
bool recordRelocation(const MCFixup &) const override;
};
unsigned ARMWinCOFFObjectWriter::getRelocType(const MCValue &Target,
const MCFixup &Fixup,
bool IsCrossSection) const {
assert(getMachine() == COFF::IMAGE_FILE_MACHINE_ARMNT &&
"AArch64 support not yet implemented");
MCSymbolRefExpr::VariantKind Modifier =
Target.isAbsolute() ? MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
switch (static_cast<unsigned>(Fixup.getKind())) {
default: llvm_unreachable("unsupported relocation type");
case FK_Data_4:
switch (Modifier) {
case MCSymbolRefExpr::VK_COFF_IMGREL32:
return COFF::IMAGE_REL_ARM_ADDR32NB;
case MCSymbolRefExpr::VK_SECREL:
return COFF::IMAGE_REL_ARM_SECREL;
default:
return COFF::IMAGE_REL_ARM_ADDR32;
}
case FK_SecRel_2:
return COFF::IMAGE_REL_ARM_SECTION;
case FK_SecRel_4:
return COFF::IMAGE_REL_ARM_SECREL;
case ARM::fixup_t2_condbranch:
return COFF::IMAGE_REL_ARM_BRANCH20T;
case ARM::fixup_t2_uncondbranch:
return COFF::IMAGE_REL_ARM_BRANCH24T;
case ARM::fixup_arm_thumb_bl:
case ARM::fixup_arm_thumb_blx:
return COFF::IMAGE_REL_ARM_BLX23T;
case ARM::fixup_t2_movw_lo16:
case ARM::fixup_t2_movt_hi16:
return COFF::IMAGE_REL_ARM_MOV32T;
}
}
bool ARMWinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const {
return static_cast<unsigned>(Fixup.getKind()) != ARM::fixup_t2_movt_hi16;
}
}
namespace llvm {
MCObjectWriter *createARMWinCOFFObjectWriter(raw_ostream &OS, bool Is64Bit) {
MCWinCOFFObjectTargetWriter *MOTW = new ARMWinCOFFObjectWriter(Is64Bit);
return createWinCOFFObjectWriter(MOTW, OS);
}
}