blob: 68867cf8ae613a5548af0ffbb41250201c423faf [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:
George Rimard3566302016-06-20 11:55:12 +000080 void parseVersion(StringRef Version);
Rafael Espindolaf70fb042016-06-17 13:38:09 +000081 void parseLocal();
George Rimard3566302016-06-20 11:55:12 +000082 void parseVersionSymbols(StringRef Version);
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000083};
84
George Rimar7899d482016-07-12 07:44:40 +000085size_t elf::defineSymbolVersion(StringRef Version) {
86 // Identifiers start at 2 because 0 and 1 are reserved
87 // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants.
88 size_t VersionId = Config->SymbolVersions.size() + 2;
89 Config->SymbolVersions.push_back(elf::Version(Version, VersionId));
90 return VersionId;
91}
92
George Rimard3566302016-06-20 11:55:12 +000093void VersionScriptParser::parseVersion(StringRef Version) {
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000094 expect("{");
George Rimar7899d482016-07-12 07:44:40 +000095 defineSymbolVersion(Version);
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000096 if (peek() == "global:") {
97 next();
George Rimard3566302016-06-20 11:55:12 +000098 parseVersionSymbols(Version);
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000099 }
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000100 if (peek() == "local:")
101 parseLocal();
George Rimar6a7cfd02016-06-24 11:23:55 +0000102 else if (peek() != "}")
George Rimard3566302016-06-20 11:55:12 +0000103 parseVersionSymbols(Version);
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000104
105 expect("}");
George Rimar33b9de42016-07-01 11:45:10 +0000106
107 // Each version may have a parent version. For example, "Ver2" defined as
108 // "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" as a parent. This
109 // version hierarchy is, probably against your instinct, purely for human; the
110 // runtime doesn't care about them at all. In LLD, we simply skip the token.
George Rimar0ab48b72016-06-22 14:40:45 +0000111 if (!Version.empty() && peek() != ";")
George Rimar33b9de42016-07-01 11:45:10 +0000112 next();
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000113 expect(";");
114}
115
116void VersionScriptParser::parseLocal() {
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000117 expect("local:");
118 expect("*");
119 expect(";");
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000120 Config->VersionScriptGlobalByDefault = false;
121}
122
George Rimard3566302016-06-20 11:55:12 +0000123void VersionScriptParser::parseVersionSymbols(StringRef Version) {
George Rimardd64bb32016-07-13 08:19:04 +0000124 std::vector<StringRef> *Globals;
Rafael Espindola857d7c52016-06-28 21:48:33 +0000125 if (Version.empty())
George Rimard3566302016-06-20 11:55:12 +0000126 Globals = &Config->VersionScriptGlobals;
Rafael Espindola857d7c52016-06-28 21:48:33 +0000127 else
George Rimard3566302016-06-20 11:55:12 +0000128 Globals = &Config->SymbolVersions.back().Globals;
George Rimard3566302016-06-20 11:55:12 +0000129
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000130 for (;;) {
George Rimarda5fa1e2016-06-23 07:23:07 +0000131 StringRef Cur = peek();
George Rimardd64bb32016-07-13 08:19:04 +0000132 if (Cur == "extern")
133 setError("extern keyword is not supported");
George Rimarda5fa1e2016-06-23 07:23:07 +0000134 if (Cur == "}" || Cur == "local:" || Error)
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000135 return;
George Rimarda5fa1e2016-06-23 07:23:07 +0000136 next();
George Rimardd64bb32016-07-13 08:19:04 +0000137 Globals->push_back(Cur);
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000138 expect(";");
139 }
George Rimar95eeb772016-06-16 18:47:04 +0000140}
141
142void VersionScriptParser::run() {
143 StringRef Msg = "anonymous version definition is used in "
144 "combination with other version definitions";
145 if (peek() == "{") {
George Rimard3566302016-06-20 11:55:12 +0000146 parseVersion("");
George Rimar95eeb772016-06-16 18:47:04 +0000147 if (!atEOF())
148 setError(Msg);
149 return;
150 }
151
152 while (!atEOF() && !Error) {
George Rimard3566302016-06-20 11:55:12 +0000153 if (peek() == "{") {
George Rimar95eeb772016-06-16 18:47:04 +0000154 setError(Msg);
155 return;
156 }
George Rimard3566302016-06-20 11:55:12 +0000157 parseVersion(next());
George Rimar95eeb772016-06-16 18:47:04 +0000158 }
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000159}
160
161void elf::parseVersionScript(MemoryBufferRef MB) {
162 VersionScriptParser(MB.getBuffer()).run();
163}