summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/PECOFF/EdataPass.h
blob: 442be3ca24aa01a5eb7e7baa8691270c9ab4de31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//===- lib/ReaderWriter/PECOFF/EdataPass.h --------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file \brief This linker pass creates atoms for the DLL export
/// information. The defined atoms constructed in this pass will go into .edata
/// section.
///
/// For the details of the .edata section format, see Microsoft PE/COFF
/// Specification section 5.3, The .edata Section.
///
//===----------------------------------------------------------------------===//

#ifndef LLD_READER_WRITER_PE_COFF_EDATA_PASS_H
#define LLD_READER_WRITER_PE_COFF_EDATA_PASS_H

#include "Atoms.h"
#include "lld/Core/File.h"
#include "lld/Core/Pass.h"
#include "lld/Core/Simple.h"
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
#include "llvm/Support/COFF.h"
#include <map>

using llvm::COFF::ImportDirectoryTableEntry;

namespace lld {
namespace pecoff {
namespace edata {

struct TableEntry {
  TableEntry(StringRef exp, int ord, const DefinedAtom *a, bool n)
      : exportName(exp), ordinal(ord), atom(a), noname(n) {}
  std::string exportName;
  int ordinal;
  const DefinedAtom *atom;
  bool noname;
};

/// The root class of all edata atoms.
class EdataAtom : public COFFLinkerInternalAtom {
public:
  EdataAtom(VirtualFile &file, size_t size)
      : COFFLinkerInternalAtom(file, file.getNextOrdinal(),
                               std::vector<uint8_t>(size)) {}

  SectionChoice sectionChoice() const override { return sectionCustomRequired; }
  StringRef customSectionName() const override { return ".edata"; }
  ContentType contentType() const override { return typeData; }
  ContentPermissions permissions() const override { return permR__; }

  template <typename T> T *getContents() const {
    return (T *)const_cast<uint8_t *>(rawContent().data());
  }
};

} // namespace edata

class EdataPass : public lld::Pass {
public:
  EdataPass(PECOFFLinkingContext &ctx)
      : _ctx(ctx), _file(ctx), _is64(ctx.is64Bit()), _stringOrdinal(1024) {}

  void perform(std::unique_ptr<MutableFile> &file) override;

private:
  edata::EdataAtom *
  createExportDirectoryTable(const std::vector<edata::TableEntry> &namedEntries,
                             int ordinalBase, int maxOrdinal);

  edata::EdataAtom *
  createAddressTable(const std::vector<edata::TableEntry> &entries,
                     int ordinalBase, int maxOrdinal);

  edata::EdataAtom *
  createNamePointerTable(const PECOFFLinkingContext &ctx,
                         const std::vector<edata::TableEntry> &entries,
                         MutableFile *file);

  edata::EdataAtom *
  createOrdinalTable(const std::vector<edata::TableEntry> &entries,
                     int ordinalBase);

  PECOFFLinkingContext &_ctx;
  VirtualFile _file;
  bool _is64;
  int _stringOrdinal;
  mutable llvm::BumpPtrAllocator _alloc;
};

} // namespace pecoff
} // namespace lld

#endif
OpenPOWER on IntegriCloud