blob: f07b8ee88503652d9bcf1f20a8330ee660f71a4e [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;
Rui Ueyama25068662016-07-16 03:08:26 +000022using namespace llvm::ELF;
23
Adhemerval Zanella9df07202016-04-13 18:51:11 +000024using namespace lld;
25using namespace lld::elf;
26
27// Parse the --dynamic-list argument. A dynamic list is in the form
28//
29// { symbol1; symbol2; [...]; symbolN };
30//
31// Multiple groups can be defined in the same file and they are merged
32// in only one definition.
33
34class DynamicListParser final : public ScriptParserBase {
35public:
36 DynamicListParser(StringRef S) : ScriptParserBase(S) {}
37
Rui Ueyama4a465392016-04-22 22:59:24 +000038 void run();
Adhemerval Zanella9df07202016-04-13 18:51:11 +000039
40private:
41 void readGroup();
42};
43
44// Parse the default group definition using C language symbol name.
45void DynamicListParser::readGroup() {
46 expect("{");
47 while (!Error) {
48 Config->DynamicList.push_back(next());
49 expect(";");
50 if (peek() == "}") {
51 next();
52 break;
53 }
54 }
55 expect(";");
56}
57
58void DynamicListParser::run() {
59 while (!atEOF())
60 readGroup();
61}
62
63void elf::parseDynamicList(MemoryBufferRef MB) {
64 DynamicListParser(MB.getBuffer()).run();
65}
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000066
67// Parse the --version-script argument. We currently only accept the following
68// version script syntax:
69//
70// { [ global: symbol1; symbol2; [...]; symbolN; ] local: *; };
71//
72// No wildcards are supported, other than for the local entry. Symbol versioning
73// is also not supported.
74
75class VersionScriptParser final : public ScriptParserBase {
76public:
77 VersionScriptParser(StringRef S) : ScriptParserBase(S) {}
78
Rui Ueyama4a465392016-04-22 22:59:24 +000079 void run();
George Rimar95eeb772016-06-16 18:47:04 +000080
81private:
George Rimard3566302016-06-20 11:55:12 +000082 void parseVersion(StringRef Version);
Rafael Espindolaf70fb042016-06-17 13:38:09 +000083 void parseLocal();
George Rimard3566302016-06-20 11:55:12 +000084 void parseVersionSymbols(StringRef Version);
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000085};
86
George Rimar7899d482016-07-12 07:44:40 +000087size_t elf::defineSymbolVersion(StringRef Version) {
88 // Identifiers start at 2 because 0 and 1 are reserved
89 // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants.
90 size_t VersionId = Config->SymbolVersions.size() + 2;
91 Config->SymbolVersions.push_back(elf::Version(Version, VersionId));
92 return VersionId;
93}
94
George Rimard3566302016-06-20 11:55:12 +000095void VersionScriptParser::parseVersion(StringRef Version) {
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000096 expect("{");
George Rimar7899d482016-07-12 07:44:40 +000097 defineSymbolVersion(Version);
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000098 if (peek() == "global:") {
99 next();
George Rimard3566302016-06-20 11:55:12 +0000100 parseVersionSymbols(Version);
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000101 }
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000102 if (peek() == "local:")
103 parseLocal();
George Rimar6a7cfd02016-06-24 11:23:55 +0000104 else if (peek() != "}")
George Rimard3566302016-06-20 11:55:12 +0000105 parseVersionSymbols(Version);
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000106
107 expect("}");
George Rimar33b9de42016-07-01 11:45:10 +0000108
109 // Each version may have a parent version. For example, "Ver2" defined as
110 // "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" as a parent. This
111 // version hierarchy is, probably against your instinct, purely for human; the
112 // runtime doesn't care about them at all. In LLD, we simply skip the token.
George Rimar0ab48b72016-06-22 14:40:45 +0000113 if (!Version.empty() && peek() != ";")
George Rimar33b9de42016-07-01 11:45:10 +0000114 next();
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000115 expect(";");
116}
117
118void VersionScriptParser::parseLocal() {
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000119 expect("local:");
120 expect("*");
121 expect(";");
Rui Ueyama25068662016-07-16 03:08:26 +0000122 Config->DefaultSymbolVersion = VER_NDX_LOCAL;
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000123}
124
George Rimard3566302016-06-20 11:55:12 +0000125void VersionScriptParser::parseVersionSymbols(StringRef Version) {
George Rimardd64bb32016-07-13 08:19:04 +0000126 std::vector<StringRef> *Globals;
Rafael Espindola857d7c52016-06-28 21:48:33 +0000127 if (Version.empty())
George Rimard3566302016-06-20 11:55:12 +0000128 Globals = &Config->VersionScriptGlobals;
Rafael Espindola857d7c52016-06-28 21:48:33 +0000129 else
George Rimard3566302016-06-20 11:55:12 +0000130 Globals = &Config->SymbolVersions.back().Globals;
George Rimard3566302016-06-20 11:55:12 +0000131
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000132 for (;;) {
George Rimarda5fa1e2016-06-23 07:23:07 +0000133 StringRef Cur = peek();
George Rimardd64bb32016-07-13 08:19:04 +0000134 if (Cur == "extern")
135 setError("extern keyword is not supported");
George Rimarda5fa1e2016-06-23 07:23:07 +0000136 if (Cur == "}" || Cur == "local:" || Error)
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000137 return;
George Rimarda5fa1e2016-06-23 07:23:07 +0000138 next();
George Rimardd64bb32016-07-13 08:19:04 +0000139 Globals->push_back(Cur);
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000140 expect(";");
141 }
George Rimar95eeb772016-06-16 18:47:04 +0000142}
143
144void VersionScriptParser::run() {
145 StringRef Msg = "anonymous version definition is used in "
146 "combination with other version definitions";
147 if (peek() == "{") {
George Rimard3566302016-06-20 11:55:12 +0000148 parseVersion("");
George Rimar95eeb772016-06-16 18:47:04 +0000149 if (!atEOF())
150 setError(Msg);
151 return;
152 }
153
154 while (!atEOF() && !Error) {
George Rimard3566302016-06-20 11:55:12 +0000155 if (peek() == "{") {
George Rimar95eeb772016-06-16 18:47:04 +0000156 setError(Msg);
157 return;
158 }
George Rimard3566302016-06-20 11:55:12 +0000159 parseVersion(next());
George Rimar95eeb772016-06-16 18:47:04 +0000160 }
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000161}
162
163void elf::parseVersionScript(MemoryBufferRef MB) {
164 VersionScriptParser(MB.getBuffer()).run();
165}