Add support for adding section relocations in -r mode. Enhance the test cases which validate the parsing of .o files to also round trip. They now write out the .o file and then parse that, verifying all relocations survived the round trip. llvm-svn: 213333
148 lines
3.6 KiB
C++
148 lines
3.6 KiB
C++
//===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#include "ArchHandler.h"
|
|
#include "Atoms.h"
|
|
#include "MachONormalizedFileBinaryUtils.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
#include "llvm/ADT/Triple.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
using namespace llvm::MachO;
|
|
using namespace lld::mach_o::normalized;
|
|
|
|
namespace lld {
|
|
namespace mach_o {
|
|
|
|
|
|
ArchHandler::ArchHandler() {
|
|
}
|
|
|
|
ArchHandler::~ArchHandler() {
|
|
}
|
|
|
|
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create(
|
|
MachOLinkingContext::Arch arch) {
|
|
switch (arch) {
|
|
case MachOLinkingContext::arch_x86_64:
|
|
return create_x86_64();
|
|
case MachOLinkingContext::arch_x86:
|
|
return create_x86();
|
|
case MachOLinkingContext::arch_armv6:
|
|
case MachOLinkingContext::arch_armv7:
|
|
case MachOLinkingContext::arch_armv7s:
|
|
return create_arm();
|
|
default:
|
|
llvm_unreachable("Unknown arch");
|
|
}
|
|
}
|
|
|
|
|
|
bool ArchHandler::isLazyPointer(const Reference &ref) {
|
|
// A lazy bind entry is needed for a lazy pointer.
|
|
const StubInfo &info = stubInfo();
|
|
if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
|
|
return false;
|
|
if (ref.kindArch() != info.lazyPointerReferenceToFinal.arch)
|
|
return false;
|
|
return (ref.kindValue() == info.lazyPointerReferenceToFinal.kind);
|
|
}
|
|
|
|
|
|
ArchHandler::RelocPattern ArchHandler::relocPattern(const Relocation &reloc) {
|
|
assert((reloc.type & 0xFFF0) == 0);
|
|
uint16_t result = reloc.type;
|
|
if (reloc.scattered)
|
|
result |= rScattered;
|
|
if (reloc.pcRel)
|
|
result |= rPcRel;
|
|
if (reloc.isExtern)
|
|
result |= rExtern;
|
|
switch(reloc.length) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
result |= rLength2;
|
|
break;
|
|
case 2:
|
|
result |= rLength4;
|
|
break;
|
|
case 3:
|
|
result |= rLength8;
|
|
break;
|
|
default:
|
|
llvm_unreachable("bad r_length");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
normalized::Relocation
|
|
ArchHandler::relocFromPattern(ArchHandler::RelocPattern pattern) {
|
|
normalized::Relocation result;
|
|
result.offset = 0;
|
|
result.scattered = (pattern & rScattered);
|
|
result.type = (RelocationInfoType)(pattern & 0xF);
|
|
result.pcRel = (pattern & rPcRel);
|
|
result.isExtern = (pattern & rExtern);
|
|
result.value = 0;
|
|
result.symbol = 0;
|
|
switch (pattern & 0x300) {
|
|
case rLength1:
|
|
result.length = 0;
|
|
break;
|
|
case rLength2:
|
|
result.length = 1;
|
|
break;
|
|
case rLength4:
|
|
result.length = 2;
|
|
break;
|
|
case rLength8:
|
|
result.length = 3;
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void ArchHandler::appendReloc(normalized::Relocations &relocs, uint32_t offset,
|
|
uint32_t symbol, uint32_t value,
|
|
RelocPattern pattern) {
|
|
normalized::Relocation reloc = relocFromPattern(pattern);
|
|
reloc.offset = offset;
|
|
reloc.symbol = symbol;
|
|
reloc.value = value;
|
|
relocs.push_back(reloc);
|
|
}
|
|
|
|
|
|
int16_t ArchHandler::readS16(bool swap, const uint8_t *addr) {
|
|
return read16(swap, *reinterpret_cast<const uint16_t*>(addr));
|
|
}
|
|
|
|
int32_t ArchHandler::readS32(bool swap, const uint8_t *addr) {
|
|
return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
|
|
}
|
|
|
|
uint32_t ArchHandler::readU32(bool swap, const uint8_t *addr) {
|
|
return read32(swap, *reinterpret_cast<const uint32_t*>(addr));
|
|
}
|
|
|
|
int64_t ArchHandler::readS64(bool swap, const uint8_t *addr) {
|
|
return read64(swap, *reinterpret_cast<const uint64_t*>(addr));
|
|
}
|
|
|
|
} // namespace mach_o
|
|
} // namespace lld
|
|
|
|
|
|
|