The implementation of AMD64 relocations was imcomplete and wrong. On AMD64, we of course have to use AMD64 relocations instead of i386 ones. This patch fixes the issue. LLD is now able to link hello64.obj (created from hello64.asm) against user32.lib and kernel32.lib to create a Win64 binary. llvm-svn: 216253
78 lines
2.3 KiB
C++
78 lines
2.3 KiB
C++
//===- lib/ReaderWriter/PECOFF/LoadConfigPass.cpp -------------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// A Load Configuration is a data structure for x86 containing an address of the
|
|
// SEH handler table. The Data Directory in the file header points to a load
|
|
// configuration. Technically that indirection is not needed but exists for
|
|
// historical reasons.
|
|
//
|
|
// If the file being handled has .sxdata section containing SEH handler table,
|
|
// this pass will create a Load Configuration atom.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Pass.h"
|
|
#include "LoadConfigPass.h"
|
|
|
|
#include "lld/Core/File.h"
|
|
#include "lld/Core/Pass.h"
|
|
#include "lld/Core/Simple.h"
|
|
#include "llvm/Object/COFF.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
#include <climits>
|
|
#include <ctime>
|
|
#include <utility>
|
|
|
|
using llvm::object::coff_load_configuration32;
|
|
|
|
namespace lld {
|
|
namespace pecoff {
|
|
namespace loadcfg {
|
|
|
|
LoadConfigAtom::LoadConfigAtom(VirtualFile &file, const DefinedAtom *sxdata,
|
|
int count)
|
|
: COFFLinkerInternalAtom(
|
|
file, file.getNextOrdinal(),
|
|
std::vector<uint8_t>(sizeof(coff_load_configuration32))) {
|
|
addDir32Reloc(
|
|
this, sxdata, false,
|
|
offsetof(llvm::object::coff_load_configuration32, SEHandlerTable));
|
|
auto *data = getContents<llvm::object::coff_load_configuration32>();
|
|
data->SEHandlerCount = count;
|
|
}
|
|
|
|
} // namespace loadcfg
|
|
|
|
void LoadConfigPass::perform(std::unique_ptr<MutableFile> &file) {
|
|
if (_ctx.noSEH())
|
|
return;
|
|
|
|
// Find the first atom in .sxdata section.
|
|
const DefinedAtom *sxdata = nullptr;
|
|
int sectionSize = 0;
|
|
for (const DefinedAtom *atom : file->defined()) {
|
|
if (atom->customSectionName() == ".sxdata") {
|
|
if (!sxdata)
|
|
sxdata = atom;
|
|
sectionSize += sxdata->size();
|
|
}
|
|
}
|
|
if (!sxdata)
|
|
return;
|
|
|
|
auto *loadcfg = new (_alloc)
|
|
loadcfg::LoadConfigAtom(_file, sxdata, sectionSize / sizeof(uint32_t));
|
|
file->addAtom(*loadcfg);
|
|
}
|
|
|
|
} // namespace pecoff
|
|
} // namespace lld
|