blob: b8cfdc88f332cb7249047d6c5de4fa492688a83b [file] [log] [blame]
Peter Collingbourne66ac1d62016-04-22 20:21:26 +00001//===- SymbolListFile.cpp -------------------------------------------------===//
Adhemerval Zanella9df07202016-04-13 18:51:11 +00002//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the parser/evaluator of the linker script.
11// It does not construct an AST but consume linker script directives directly.
12// Results are written to Driver or Config object.
13//
14//===----------------------------------------------------------------------===//
15
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000016#include "SymbolListFile.h"
Adhemerval Zanella9df07202016-04-13 18:51:11 +000017#include "Config.h"
18#include "ScriptParser.h"
19#include "llvm/Support/MemoryBuffer.h"
Adhemerval Zanella9df07202016-04-13 18:51:11 +000020
21using namespace llvm;
22using namespace lld;
23using namespace lld::elf;
24
25// Parse the --dynamic-list argument. A dynamic list is in the form
26//
27// { symbol1; symbol2; [...]; symbolN };
28//
29// Multiple groups can be defined in the same file and they are merged
30// in only one definition.
31
32class DynamicListParser final : public ScriptParserBase {
33public:
34 DynamicListParser(StringRef S) : ScriptParserBase(S) {}
35
Rui Ueyama4a465392016-04-22 22:59:24 +000036 void run();
Adhemerval Zanella9df07202016-04-13 18:51:11 +000037
38private:
39 void readGroup();
40};
41
42// Parse the default group definition using C language symbol name.
43void DynamicListParser::readGroup() {
44 expect("{");
45 while (!Error) {
46 Config->DynamicList.push_back(next());
47 expect(";");
48 if (peek() == "}") {
49 next();
50 break;
51 }
52 }
53 expect(";");
54}
55
56void DynamicListParser::run() {
57 while (!atEOF())
58 readGroup();
59}
60
61void elf::parseDynamicList(MemoryBufferRef MB) {
62 DynamicListParser(MB.getBuffer()).run();
63}
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000064
65// Parse the --version-script argument. We currently only accept the following
66// version script syntax:
67//
68// { [ global: symbol1; symbol2; [...]; symbolN; ] local: *; };
69//
70// No wildcards are supported, other than for the local entry. Symbol versioning
71// is also not supported.
72
73class VersionScriptParser final : public ScriptParserBase {
74public:
75 VersionScriptParser(StringRef S) : ScriptParserBase(S) {}
76
Rui Ueyama4a465392016-04-22 22:59:24 +000077 void run();
George Rimar95eeb772016-06-16 18:47:04 +000078
79private:
80 void parseVersion();
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000081};
82
George Rimar95eeb772016-06-16 18:47:04 +000083void VersionScriptParser::parseVersion() {
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000084 expect("{");
85 if (peek() == "global:") {
86 next();
87 while (!Error) {
88 Config->VersionScriptGlobals.push_back(next());
89 expect(";");
90 if (peek() == "local:")
91 break;
92 }
93 }
94 expect("local:");
95 expect("*");
96 expect(";");
97 expect("}");
98 expect(";");
George Rimar95eeb772016-06-16 18:47:04 +000099}
100
101void VersionScriptParser::run() {
102 StringRef Msg = "anonymous version definition is used in "
103 "combination with other version definitions";
104 if (peek() == "{") {
105 parseVersion();
106 if (!atEOF())
107 setError(Msg);
108 return;
109 }
110
111 while (!atEOF() && !Error) {
112 if (next() == "{") {
113 setError(Msg);
114 return;
115 }
116 parseVersion();
117 }
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000118}
119
120void elf::parseVersionScript(MemoryBufferRef MB) {
121 VersionScriptParser(MB.getBuffer()).run();
122}