//
//===----------------------------------------------------------------------===//
+#include "InputFiles.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
struct X86_64 : TargetInfo {
X86_64();
- uint64_t getImplicitAddend(const uint8_t *loc, uint8_t type) const override;
+ uint64_t getImplicitAddend(MemoryBufferRef, const section_64 &,
+ const relocation_info &) const override;
void relocateOne(uint8_t *loc, uint8_t type, uint64_t val) const override;
void writeStub(uint8_t *buf, const DylibSymbol &) const override;
} // namespace
-uint64_t X86_64::getImplicitAddend(const uint8_t *loc, uint8_t type) const {
- switch (type) {
+static std::string getErrorLocation(MemoryBufferRef mb, const section_64 &sec,
+ const relocation_info &rel) {
+ return ("invalid relocation at offset " + std::to_string(rel.r_address) +
+ " of " + sec.segname + "," + sec.sectname + " in " +
+ mb.getBufferIdentifier())
+ .str();
+}
+
+uint64_t X86_64::getImplicitAddend(MemoryBufferRef mb, const section_64 &sec,
+ const relocation_info &rel) const {
+ auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart());
+ const uint8_t *loc = buf + sec.offset + rel.r_address;
+ switch (rel.r_type) {
case X86_64_RELOC_BRANCH:
case X86_64_RELOC_SIGNED:
case X86_64_RELOC_SIGNED_1:
case X86_64_RELOC_SIGNED_2:
case X86_64_RELOC_SIGNED_4:
case X86_64_RELOC_GOT_LOAD:
+ if (!rel.r_pcrel)
+ fatal(getErrorLocation(mb, sec, rel) + ": relocations of type " +
+ std::to_string(rel.r_type) + " must be pcrel");
return read32le(loc);
case X86_64_RELOC_UNSIGNED:
+ if (rel.r_pcrel)
+ fatal(getErrorLocation(mb, sec, rel) + ": relocations of type " +
+ std::to_string(rel.r_type) + " must not be pcrel");
return read64le(loc);
default:
- error("TODO: Unhandled relocation type " + std::to_string(type));
+ error("TODO: Unhandled relocation type " + std::to_string(rel.r_type));
return 0;
}
}
Reloc r;
r.type = rel.r_type;
r.pcrel = rel.r_pcrel;
- uint32_t secRelOffset = rel.r_address;
- uint64_t rawAddend =
- target->getImplicitAddend(buf + sec.offset + secRelOffset, r.type);
+ uint64_t rawAddend = target->getImplicitAddend(mb, sec, rel);
if (rel.r_extern) {
r.target = symbols[rel.r_symbolnum];
// TODO: The offset of 4 is probably not right for ARM64, nor for
// relocations with r_length != 2.
uint32_t targetOffset =
- sec.addr + secRelOffset + 4 + rawAddend - targetSec.addr;
+ sec.addr + rel.r_address + 4 + rawAddend - targetSec.addr;
r.target = findContainingSubsection(targetSubsecMap, &targetOffset);
r.addend = targetOffset;
}
- InputSection *subsec = findContainingSubsection(subsecMap, &secRelOffset);
- r.offset = secRelOffset;
+ r.offset = rel.r_address;
+ InputSection *subsec = findContainingSubsection(subsecMap, &r.offset);
subsec->relocs.push_back(r);
}
}
#ifndef LLD_MACHO_TARGET_H
#define LLD_MACHO_TARGET_H
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Support/MemoryBuffer.h"
+
#include <cstddef>
#include <cstdint>
namespace macho {
class DylibSymbol;
+class InputSection;
+struct Reloc;
enum {
// We are currently only supporting 64-bit targets since macOS and iOS are
public:
virtual ~TargetInfo() = default;
- virtual uint64_t getImplicitAddend(const uint8_t *loc,
- uint8_t type) const = 0;
+ // Validate the relocation structure and get its addend.
+ virtual uint64_t
+ getImplicitAddend(llvm::MemoryBufferRef, const llvm::MachO::section_64 &,
+ const llvm::MachO::relocation_info &) const = 0;
virtual void relocateOne(uint8_t *loc, uint8_t type, uint64_t val) const = 0;
// Write code for lazy binding. See the comments on StubsSection for more
--- /dev/null
+# REQUIRES: x86
+# RUN: yaml2obj %s -o %t.o
+# RUN: not lld -flavor darwinnew -o %t %t.o 2>&1 | FileCheck %s -DFILE=%t.o
+#
+# CHECK: error: invalid relocation at offset 1 of __TEXT,__text in [[FILE]]: relocations of type 0 must not be pcrel
+
+!mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 4
+ sizeofcmds: 280
+ flags: 0x00000000
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 152
+ segname: ''
+ vmaddr: 0
+ vmsize: 9
+ fileoff: 312
+ filesize: 9
+ maxprot: 7
+ initprot: 7
+ nsects: 1
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000000000000
+ size: 9
+ offset: 0x00000138
+ align: 0
+ reloff: 0x00000144
+ nreloc: 1
+ flags: 0x80000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ content: '000000000000000000'
+ relocations:
+ - address: 0x00000001
+ symbolnum: 1
+ pcrel: true
+ length: 3
+ extern: true
+ type: 0
+ scattered: false
+ value: 0
+ - cmd: LC_BUILD_VERSION
+ cmdsize: 24
+ platform: 1
+ minos: 659200
+ sdk: 0
+ ntools: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 332
+ nsyms: 2
+ stroff: 364
+ strsize: 12
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 2
+ iundefsym: 2
+ nundefsym: 0
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ NameList:
+ - n_strx: 1
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 1
+ - n_strx: 6
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 9
+ StringTable:
+ - ''
+ - _foo
+ - _main