blob: 7ccb321896e4422b58523799913a4e5bf87a9be0 [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//
Rui Ueyama52654eb2016-07-16 03:45:59 +000031// Multiple groups can be defined in the same file, and they are merged
32// into a single group.
Adhemerval Zanella9df07202016-04-13 18:51:11 +000033
34class DynamicListParser final : public ScriptParserBase {
35public:
36 DynamicListParser(StringRef S) : ScriptParserBase(S) {}
Rui Ueyama4a465392016-04-22 22:59:24 +000037 void run();
Adhemerval Zanella9df07202016-04-13 18:51:11 +000038};
39
Adhemerval Zanella9df07202016-04-13 18:51:11 +000040void DynamicListParser::run() {
Rui Ueyama52654eb2016-07-16 03:45:59 +000041 while (!atEOF()) {
42 expect("{");
43 while (!Error) {
44 Config->DynamicList.push_back(next());
45 expect(";");
46 if (skip("}"))
47 break;
48 }
49 expect(";");
50 }
Adhemerval Zanella9df07202016-04-13 18:51:11 +000051}
52
53void elf::parseDynamicList(MemoryBufferRef MB) {
54 DynamicListParser(MB.getBuffer()).run();
55}
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000056
57// Parse the --version-script argument. We currently only accept the following
58// version script syntax:
59//
60// { [ global: symbol1; symbol2; [...]; symbolN; ] local: *; };
61//
62// No wildcards are supported, other than for the local entry. Symbol versioning
63// is also not supported.
64
65class VersionScriptParser final : public ScriptParserBase {
66public:
67 VersionScriptParser(StringRef S) : ScriptParserBase(S) {}
68
Rui Ueyama4a465392016-04-22 22:59:24 +000069 void run();
George Rimar95eeb772016-06-16 18:47:04 +000070
71private:
George Rimard3566302016-06-20 11:55:12 +000072 void parseVersion(StringRef Version);
Rui Ueyama52654eb2016-07-16 03:45:59 +000073 void parseGlobal(StringRef Version);
Rafael Espindolaf70fb042016-06-17 13:38:09 +000074 void parseLocal();
Peter Collingbourne66ac1d62016-04-22 20:21:26 +000075};
76
George Rimar7899d482016-07-12 07:44:40 +000077size_t elf::defineSymbolVersion(StringRef Version) {
78 // Identifiers start at 2 because 0 and 1 are reserved
79 // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants.
80 size_t VersionId = Config->SymbolVersions.size() + 2;
81 Config->SymbolVersions.push_back(elf::Version(Version, VersionId));
82 return VersionId;
83}
84
George Rimard3566302016-06-20 11:55:12 +000085void VersionScriptParser::parseVersion(StringRef Version) {
George Rimar7899d482016-07-12 07:44:40 +000086 defineSymbolVersion(Version);
Rafael Espindolaf70fb042016-06-17 13:38:09 +000087
Rui Ueyama52654eb2016-07-16 03:45:59 +000088 if (skip("global:") || peek() != "local:")
89 parseGlobal(Version);
90 if (skip("local:"))
91 parseLocal();
Rafael Espindolaf70fb042016-06-17 13:38:09 +000092 expect("}");
George Rimar33b9de42016-07-01 11:45:10 +000093
94 // Each version may have a parent version. For example, "Ver2" defined as
95 // "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" as a parent. This
96 // version hierarchy is, probably against your instinct, purely for human; the
97 // runtime doesn't care about them at all. In LLD, we simply skip the token.
George Rimar0ab48b72016-06-22 14:40:45 +000098 if (!Version.empty() && peek() != ";")
George Rimar33b9de42016-07-01 11:45:10 +000099 next();
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000100 expect(";");
101}
102
103void VersionScriptParser::parseLocal() {
Rui Ueyama52654eb2016-07-16 03:45:59 +0000104 Config->DefaultSymbolVersion = VER_NDX_LOCAL;
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000105 expect("*");
106 expect(";");
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000107}
108
Rui Ueyama52654eb2016-07-16 03:45:59 +0000109void VersionScriptParser::parseGlobal(StringRef Version) {
George Rimardd64bb32016-07-13 08:19:04 +0000110 std::vector<StringRef> *Globals;
Rafael Espindola857d7c52016-06-28 21:48:33 +0000111 if (Version.empty())
George Rimard3566302016-06-20 11:55:12 +0000112 Globals = &Config->VersionScriptGlobals;
Rafael Espindola857d7c52016-06-28 21:48:33 +0000113 else
George Rimard3566302016-06-20 11:55:12 +0000114 Globals = &Config->SymbolVersions.back().Globals;
George Rimard3566302016-06-20 11:55:12 +0000115
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000116 for (;;) {
George Rimarda5fa1e2016-06-23 07:23:07 +0000117 StringRef Cur = peek();
George Rimardd64bb32016-07-13 08:19:04 +0000118 if (Cur == "extern")
119 setError("extern keyword is not supported");
George Rimarda5fa1e2016-06-23 07:23:07 +0000120 if (Cur == "}" || Cur == "local:" || Error)
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000121 return;
George Rimarda5fa1e2016-06-23 07:23:07 +0000122 next();
George Rimardd64bb32016-07-13 08:19:04 +0000123 Globals->push_back(Cur);
Rafael Espindolaf70fb042016-06-17 13:38:09 +0000124 expect(";");
125 }
George Rimar95eeb772016-06-16 18:47:04 +0000126}
127
128void VersionScriptParser::run() {
129 StringRef Msg = "anonymous version definition is used in "
130 "combination with other version definitions";
Rui Ueyama52654eb2016-07-16 03:45:59 +0000131 if (skip("{")) {
George Rimard3566302016-06-20 11:55:12 +0000132 parseVersion("");
George Rimar95eeb772016-06-16 18:47:04 +0000133 if (!atEOF())
134 setError(Msg);
135 return;
136 }
137
138 while (!atEOF() && !Error) {
Rui Ueyama52654eb2016-07-16 03:45:59 +0000139 StringRef Version = next();
140 if (Version == "{") {
George Rimar95eeb772016-06-16 18:47:04 +0000141 setError(Msg);
142 return;
143 }
Rui Ueyama52654eb2016-07-16 03:45:59 +0000144 expect("{");
145 parseVersion(Version);
George Rimar95eeb772016-06-16 18:47:04 +0000146 }
Peter Collingbourne66ac1d62016-04-22 20:21:26 +0000147}
148
149void elf::parseVersionScript(MemoryBufferRef MB) {
150 VersionScriptParser(MB.getBuffer()).run();
151}