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 0000000000000..be2f5627f4ea7 --- /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  | 
