summaryrefslogtreecommitdiffstats
path: root/lld/ELF/LinkerScript.h
blob: bdc217e836a15c9cfbb4cce78b3d926bc6be0543 (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
100
101
102
103
104
//===- LinkerScript.h -------------------------------------------*- C++ -*-===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLD_ELF_LINKER_SCRIPT_H
#define LLD_ELF_LINKER_SCRIPT_H

#include "lld/Core/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/MemoryBuffer.h"

namespace lld {
namespace elf {

// Parses a linker script. Calling this function updates
// Config and ScriptConfig.
void readLinkerScript(MemoryBufferRef MB);

class ScriptParser;
template <class ELFT> class InputSectionBase;
template <class ELFT> class OutputSectionBase;

// This class represents each rule in SECTIONS command.
class SectionRule {
public:
  SectionRule(StringRef D, StringRef S, bool Keep)
      : Dest(D), Keep(Keep), SectionPattern(S) {}

  // Returns true if S should be in Dest section.
  template <class ELFT> bool match(InputSectionBase<ELFT> *S);

  StringRef Dest;

  // KEEP command saves unused sections even if --gc-sections is specified.
  bool Keep = false;

private:
  StringRef SectionPattern;
};

// This enum represents what we can observe in SECTIONS tag of script:
// ExprKind is a location counter change, like ". = . + 0x1000"
// SectionKind is a description of output section, like ".data :..."
enum SectionsCommandKind { ExprKind, SectionKind };

struct SectionsCommand {
  SectionsCommandKind Kind;
  std::vector<StringRef> Expr;
  StringRef SectionName;
};

// ScriptConfiguration holds linker script parse results.
struct ScriptConfiguration {
  // SECTIONS commands.
  std::vector<SectionRule> Sections;

  // Output sections are sorted by this order.
  std::vector<StringRef> SectionOrder;

  // Section fill attribute for each section.
  llvm::StringMap<std::vector<uint8_t>> Filler;

  // Used to assign addresses to sections.
  std::vector<SectionsCommand> Commands;

  bool DoLayout = false;

  llvm::BumpPtrAllocator Alloc;
};

extern ScriptConfiguration *ScriptConfig;

// This is a runner of the linker script.
template <class ELFT> class LinkerScript {
public:
  StringRef getOutputSection(InputSectionBase<ELFT> *S);
  ArrayRef<uint8_t> getFiller(StringRef Name);
  bool isDiscarded(InputSectionBase<ELFT> *S);
  bool shouldKeep(InputSectionBase<ELFT> *S);
  void assignAddresses(std::vector<OutputSectionBase<ELFT> *> &S);
  int compareSections(StringRef A, StringRef B);

private:
  SectionRule *find(InputSectionBase<ELFT> *S);

  ScriptConfiguration &Opt = *ScriptConfig;
};

// Variable template is a C++14 feature, so we can't template
// a global variable. Use a struct to workaround.
template <class ELFT> struct Script { static LinkerScript<ELFT> *X; };
template <class ELFT> LinkerScript<ELFT> *Script<ELFT>::X;

} // namespace elf
} // namespace lld

#endif
OpenPOWER on IntegriCloud