diff options
Diffstat (limited to 'lib/ReaderWriter/PECOFF/LoadConfigPass.cpp')
-rw-r--r-- | lib/ReaderWriter/PECOFF/LoadConfigPass.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/ReaderWriter/PECOFF/LoadConfigPass.cpp b/lib/ReaderWriter/PECOFF/LoadConfigPass.cpp new file mode 100644 index 000000000000..be2f5627f4ea --- /dev/null +++ b/lib/ReaderWriter/PECOFF/LoadConfigPass.cpp @@ -0,0 +1,75 @@ +//===- 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, llvm::COFF::IMAGE_FILE_MACHINE_I386, + 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 |