1f7c5fbb1SRui Ueyama //===- LinkerScript.cpp ---------------------------------------------------===// 2f7c5fbb1SRui Ueyama // 3f7c5fbb1SRui Ueyama // The LLVM Linker 4f7c5fbb1SRui Ueyama // 5f7c5fbb1SRui Ueyama // This file is distributed under the University of Illinois Open Source 6f7c5fbb1SRui Ueyama // License. See LICENSE.TXT for details. 7f7c5fbb1SRui Ueyama // 8f7c5fbb1SRui Ueyama //===----------------------------------------------------------------------===// 9f7c5fbb1SRui Ueyama // 10f7c5fbb1SRui Ueyama // This file contains the parser/evaluator of the linker script. 11f7c5fbb1SRui Ueyama // It does not construct an AST but consume linker script directives directly. 1234f29246SRui Ueyama // Results are written to Driver or Config object. 13f7c5fbb1SRui Ueyama // 14f7c5fbb1SRui Ueyama //===----------------------------------------------------------------------===// 15f7c5fbb1SRui Ueyama 16717677afSRui Ueyama #include "LinkerScript.h" 17f7c5fbb1SRui Ueyama #include "Config.h" 18f7c5fbb1SRui Ueyama #include "Driver.h" 191ebc8ed7SRui Ueyama #include "InputSection.h" 20f7c5fbb1SRui Ueyama #include "SymbolTable.h" 21f7c5fbb1SRui Ueyama #include "llvm/Support/FileSystem.h" 22f7c5fbb1SRui Ueyama #include "llvm/Support/MemoryBuffer.h" 23f03f3cc1SRui Ueyama #include "llvm/Support/Path.h" 24a47ee68dSRui Ueyama #include "llvm/Support/StringSaver.h" 25f7c5fbb1SRui Ueyama 26f7c5fbb1SRui Ueyama using namespace llvm; 271ebc8ed7SRui Ueyama using namespace llvm::object; 28f7c5fbb1SRui Ueyama using namespace lld; 29f7c5fbb1SRui Ueyama using namespace lld::elf2; 30f7c5fbb1SRui Ueyama 31717677afSRui Ueyama LinkerScript *elf2::Script; 32717677afSRui Ueyama 331ebc8ed7SRui Ueyama template <class ELFT> 34481c2ce6SGeorge Rimar SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) { 351ebc8ed7SRui Ueyama for (SectionRule &R : Sections) 361ebc8ed7SRui Ueyama if (R.match(S)) 37481c2ce6SGeorge Rimar return &R; 38481c2ce6SGeorge Rimar return nullptr; 39481c2ce6SGeorge Rimar } 40481c2ce6SGeorge Rimar 41481c2ce6SGeorge Rimar template <class ELFT> 42481c2ce6SGeorge Rimar StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) { 43481c2ce6SGeorge Rimar SectionRule *R = find(S); 44481c2ce6SGeorge Rimar return R ? R->Dest : ""; 45717677afSRui Ueyama } 46717677afSRui Ueyama 471ebc8ed7SRui Ueyama template <class ELFT> 481ebc8ed7SRui Ueyama bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) { 491ebc8ed7SRui Ueyama return getOutputSection(S) == "/DISCARD/"; 50717677afSRui Ueyama } 51717677afSRui Ueyama 52481c2ce6SGeorge Rimar template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) { 53481c2ce6SGeorge Rimar SectionRule *R = find(S); 54481c2ce6SGeorge Rimar return R && R->Keep; 55481c2ce6SGeorge Rimar } 56481c2ce6SGeorge Rimar 57*e2ee72b5SGeorge Rimar ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) { 58*e2ee72b5SGeorge Rimar for (OutSection &C : OutSections) 59*e2ee72b5SGeorge Rimar if (C.Name == Name) 60*e2ee72b5SGeorge Rimar return C.Filler; 61*e2ee72b5SGeorge Rimar return {}; 62*e2ee72b5SGeorge Rimar } 63*e2ee72b5SGeorge Rimar 64e9c58065SRui Ueyama // A compartor to sort output sections. Returns -1 or 1 if both 65e9c58065SRui Ueyama // A and B are mentioned in linker scripts. Otherwise, returns 0 66e9c58065SRui Ueyama // to use the default rule which is implemented in Writer.cpp. 67717677afSRui Ueyama int LinkerScript::compareSections(StringRef A, StringRef B) { 68*e2ee72b5SGeorge Rimar auto E = OutSections.end(); 69*e2ee72b5SGeorge Rimar auto I = std::find_if(OutSections.begin(), E, 70*e2ee72b5SGeorge Rimar [&](OutSection &C) { return C.Name == A; }); 71*e2ee72b5SGeorge Rimar auto J = std::find_if(OutSections.begin(), E, 72*e2ee72b5SGeorge Rimar [&](OutSection &C) { return C.Name == B; }); 73e9c58065SRui Ueyama if (I == E || J == E) 74717677afSRui Ueyama return 0; 75717677afSRui Ueyama return I < J ? -1 : 1; 76717677afSRui Ueyama } 77717677afSRui Ueyama 78cb2aeb66SGeorge Rimar // Returns true if S matches T. S can contain glob meta-characters. 79cb2aeb66SGeorge Rimar // The asterisk ('*') matches zero or more characacters, and the question 80cb2aeb66SGeorge Rimar // mark ('?') matches one character. 811ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) { 821ebc8ed7SRui Ueyama for (;;) { 831ebc8ed7SRui Ueyama if (S.empty()) 841ebc8ed7SRui Ueyama return T.empty(); 851ebc8ed7SRui Ueyama if (S[0] == '*') { 861ebc8ed7SRui Ueyama S = S.substr(1); 871ebc8ed7SRui Ueyama if (S.empty()) 881ebc8ed7SRui Ueyama // Fast path. If a pattern is '*', it matches anything. 891ebc8ed7SRui Ueyama return true; 901ebc8ed7SRui Ueyama for (size_t I = 0, E = T.size(); I < E; ++I) 911ebc8ed7SRui Ueyama if (matchStr(S, T.substr(I))) 921ebc8ed7SRui Ueyama return true; 931ebc8ed7SRui Ueyama return false; 941ebc8ed7SRui Ueyama } 95cb2aeb66SGeorge Rimar if (T.empty() || (S[0] != T[0] && S[0] != '?')) 961ebc8ed7SRui Ueyama return false; 971ebc8ed7SRui Ueyama S = S.substr(1); 981ebc8ed7SRui Ueyama T = T.substr(1); 991ebc8ed7SRui Ueyama } 1001ebc8ed7SRui Ueyama } 1011ebc8ed7SRui Ueyama 1021ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) { 1031ebc8ed7SRui Ueyama return matchStr(SectionPattern, S->getSectionName()); 1041ebc8ed7SRui Ueyama } 1051ebc8ed7SRui Ueyama 106717677afSRui Ueyama class elf2::ScriptParser { 107c3794e58SGeorge Rimar typedef void (ScriptParser::*Handler)(); 108c3794e58SGeorge Rimar 109f7c5fbb1SRui Ueyama public: 110717677afSRui Ueyama ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) 111c3794e58SGeorge Rimar : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {} 112f23b2320SGeorge Rimar 113f7c5fbb1SRui Ueyama void run(); 114f7c5fbb1SRui Ueyama 115f7c5fbb1SRui Ueyama private: 116025d59b1SRui Ueyama void setError(const Twine &Msg); 117f7c5fbb1SRui Ueyama static std::vector<StringRef> tokenize(StringRef S); 118f7c5fbb1SRui Ueyama static StringRef skipSpace(StringRef S); 119025d59b1SRui Ueyama bool atEOF(); 120f7c5fbb1SRui Ueyama StringRef next(); 121*e2ee72b5SGeorge Rimar StringRef peek(); 1228e3b38abSDenis Protivensky bool skip(StringRef Tok); 123f7c5fbb1SRui Ueyama void expect(StringRef Expect); 124f7c5fbb1SRui Ueyama 12552a1509eSRui Ueyama void addFile(StringRef Path); 12652a1509eSRui Ueyama 127f7c5fbb1SRui Ueyama void readAsNeeded(); 12890c5099eSDenis Protivensky void readEntry(); 12983f406cfSGeorge Rimar void readExtern(); 130f7c5fbb1SRui Ueyama void readGroup(); 13131aa1f83SRui Ueyama void readInclude(); 132c3794e58SGeorge Rimar void readNothing() {} 133ee59282bSRui Ueyama void readOutput(); 1349159ce93SDavide Italiano void readOutputArch(); 135f7c5fbb1SRui Ueyama void readOutputFormat(); 13668a39a65SDavide Italiano void readSearchDir(); 1378e3b38abSDenis Protivensky void readSections(); 1388e3b38abSDenis Protivensky 1398e3b38abSDenis Protivensky void readOutputSectionDescription(); 140481c2ce6SGeorge Rimar void readSectionPatterns(StringRef OutSec, bool Keep); 141f7c5fbb1SRui Ueyama 142*e2ee72b5SGeorge Rimar std::vector<uint8_t> parseHex(StringRef S); 143*e2ee72b5SGeorge Rimar 144a47ee68dSRui Ueyama StringSaver Saver; 145f7c5fbb1SRui Ueyama std::vector<StringRef> Tokens; 146c3794e58SGeorge Rimar const static StringMap<Handler> Cmd; 147f7c5fbb1SRui Ueyama size_t Pos = 0; 14816b0cc9eSSimon Atanasyan bool IsUnderSysroot; 149f23b2320SGeorge Rimar bool Error = false; 150f7c5fbb1SRui Ueyama }; 151f7c5fbb1SRui Ueyama 152c3794e58SGeorge Rimar const StringMap<elf2::ScriptParser::Handler> elf2::ScriptParser::Cmd = { 153c3794e58SGeorge Rimar {"ENTRY", &ScriptParser::readEntry}, 154c3794e58SGeorge Rimar {"EXTERN", &ScriptParser::readExtern}, 155c3794e58SGeorge Rimar {"GROUP", &ScriptParser::readGroup}, 156c3794e58SGeorge Rimar {"INCLUDE", &ScriptParser::readInclude}, 157c3794e58SGeorge Rimar {"INPUT", &ScriptParser::readGroup}, 158c3794e58SGeorge Rimar {"OUTPUT", &ScriptParser::readOutput}, 159c3794e58SGeorge Rimar {"OUTPUT_ARCH", &ScriptParser::readOutputArch}, 160c3794e58SGeorge Rimar {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat}, 161c3794e58SGeorge Rimar {"SEARCH_DIR", &ScriptParser::readSearchDir}, 162c3794e58SGeorge Rimar {"SECTIONS", &ScriptParser::readSections}, 163c3794e58SGeorge Rimar {";", &ScriptParser::readNothing}}; 164c3794e58SGeorge Rimar 165717677afSRui Ueyama void ScriptParser::run() { 166f7c5fbb1SRui Ueyama while (!atEOF()) { 167f7c5fbb1SRui Ueyama StringRef Tok = next(); 168c3794e58SGeorge Rimar if (Handler Fn = Cmd.lookup(Tok)) 169c3794e58SGeorge Rimar (this->*Fn)(); 170c3794e58SGeorge Rimar else 171025d59b1SRui Ueyama setError("unknown directive: " + Tok); 172f7c5fbb1SRui Ueyama } 173f7c5fbb1SRui Ueyama } 174f7c5fbb1SRui Ueyama 175025d59b1SRui Ueyama // We don't want to record cascading errors. Keep only the first one. 176717677afSRui Ueyama void ScriptParser::setError(const Twine &Msg) { 177025d59b1SRui Ueyama if (Error) 178025d59b1SRui Ueyama return; 179025d59b1SRui Ueyama error(Msg); 180025d59b1SRui Ueyama Error = true; 181025d59b1SRui Ueyama } 182025d59b1SRui Ueyama 183f7c5fbb1SRui Ueyama // Split S into linker script tokens. 184717677afSRui Ueyama std::vector<StringRef> ScriptParser::tokenize(StringRef S) { 185f7c5fbb1SRui Ueyama std::vector<StringRef> Ret; 186f7c5fbb1SRui Ueyama for (;;) { 187f7c5fbb1SRui Ueyama S = skipSpace(S); 188f7c5fbb1SRui Ueyama if (S.empty()) 189f7c5fbb1SRui Ueyama return Ret; 190f7c5fbb1SRui Ueyama 191f7c5fbb1SRui Ueyama // Quoted token 192f7c5fbb1SRui Ueyama if (S.startswith("\"")) { 193f7c5fbb1SRui Ueyama size_t E = S.find("\"", 1); 194025d59b1SRui Ueyama if (E == StringRef::npos) { 195025d59b1SRui Ueyama error("unclosed quote"); 196025d59b1SRui Ueyama return {}; 197025d59b1SRui Ueyama } 19860259337SPete Cooper Ret.push_back(S.substr(1, E - 1)); 199f7c5fbb1SRui Ueyama S = S.substr(E + 1); 200f7c5fbb1SRui Ueyama continue; 201f7c5fbb1SRui Ueyama } 202f7c5fbb1SRui Ueyama 203f7c5fbb1SRui Ueyama // Unquoted token 204f7c5fbb1SRui Ueyama size_t Pos = S.find_first_not_of( 205f7c5fbb1SRui Ueyama "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 206f7c5fbb1SRui Ueyama "0123456789_.$/\\~=+[]*?-:"); 207f7c5fbb1SRui Ueyama // A character that cannot start a word (which is usually a 208f7c5fbb1SRui Ueyama // punctuation) forms a single character token. 209f7c5fbb1SRui Ueyama if (Pos == 0) 210f7c5fbb1SRui Ueyama Pos = 1; 211f7c5fbb1SRui Ueyama Ret.push_back(S.substr(0, Pos)); 212f7c5fbb1SRui Ueyama S = S.substr(Pos); 213f7c5fbb1SRui Ueyama } 214f7c5fbb1SRui Ueyama } 215f7c5fbb1SRui Ueyama 216f7c5fbb1SRui Ueyama // Skip leading whitespace characters or /**/-style comments. 217717677afSRui Ueyama StringRef ScriptParser::skipSpace(StringRef S) { 218f7c5fbb1SRui Ueyama for (;;) { 219f7c5fbb1SRui Ueyama if (S.startswith("/*")) { 220f7c5fbb1SRui Ueyama size_t E = S.find("*/", 2); 221025d59b1SRui Ueyama if (E == StringRef::npos) { 222025d59b1SRui Ueyama error("unclosed comment in a linker script"); 223025d59b1SRui Ueyama return ""; 224025d59b1SRui Ueyama } 225f7c5fbb1SRui Ueyama S = S.substr(E + 2); 226f7c5fbb1SRui Ueyama continue; 227f7c5fbb1SRui Ueyama } 228f7c5fbb1SRui Ueyama size_t Size = S.size(); 229f7c5fbb1SRui Ueyama S = S.ltrim(); 230f7c5fbb1SRui Ueyama if (S.size() == Size) 231f7c5fbb1SRui Ueyama return S; 232f7c5fbb1SRui Ueyama } 233f7c5fbb1SRui Ueyama } 234f7c5fbb1SRui Ueyama 235025d59b1SRui Ueyama // An errneous token is handled as if it were the last token before EOF. 236717677afSRui Ueyama bool ScriptParser::atEOF() { return Error || Tokens.size() == Pos; } 237025d59b1SRui Ueyama 238717677afSRui Ueyama StringRef ScriptParser::next() { 239025d59b1SRui Ueyama if (Error) 240025d59b1SRui Ueyama return ""; 241025d59b1SRui Ueyama if (atEOF()) { 242025d59b1SRui Ueyama setError("unexpected EOF"); 243025d59b1SRui Ueyama return ""; 244025d59b1SRui Ueyama } 245f7c5fbb1SRui Ueyama return Tokens[Pos++]; 246f7c5fbb1SRui Ueyama } 247f7c5fbb1SRui Ueyama 248*e2ee72b5SGeorge Rimar StringRef ScriptParser::peek() { 249*e2ee72b5SGeorge Rimar StringRef Tok = next(); 250*e2ee72b5SGeorge Rimar if (Error) 251*e2ee72b5SGeorge Rimar return ""; 252*e2ee72b5SGeorge Rimar --Pos; 253*e2ee72b5SGeorge Rimar return Tok; 254*e2ee72b5SGeorge Rimar } 255*e2ee72b5SGeorge Rimar 256717677afSRui Ueyama bool ScriptParser::skip(StringRef Tok) { 257025d59b1SRui Ueyama if (Error) 258025d59b1SRui Ueyama return false; 259025d59b1SRui Ueyama if (atEOF()) { 260025d59b1SRui Ueyama setError("unexpected EOF"); 261025d59b1SRui Ueyama return false; 262025d59b1SRui Ueyama } 2638e3b38abSDenis Protivensky if (Tok != Tokens[Pos]) 2648e3b38abSDenis Protivensky return false; 2658e3b38abSDenis Protivensky ++Pos; 2668e3b38abSDenis Protivensky return true; 2678e3b38abSDenis Protivensky } 2688e3b38abSDenis Protivensky 269717677afSRui Ueyama void ScriptParser::expect(StringRef Expect) { 270025d59b1SRui Ueyama if (Error) 271025d59b1SRui Ueyama return; 272f7c5fbb1SRui Ueyama StringRef Tok = next(); 273f7c5fbb1SRui Ueyama if (Tok != Expect) 274025d59b1SRui Ueyama setError(Expect + " expected, but got " + Tok); 275f7c5fbb1SRui Ueyama } 276f7c5fbb1SRui Ueyama 277717677afSRui Ueyama void ScriptParser::addFile(StringRef S) { 27816b0cc9eSSimon Atanasyan if (IsUnderSysroot && S.startswith("/")) { 27916b0cc9eSSimon Atanasyan SmallString<128> Path; 28016b0cc9eSSimon Atanasyan (Config->Sysroot + S).toStringRef(Path); 28116b0cc9eSSimon Atanasyan if (sys::fs::exists(Path)) { 28216b0cc9eSSimon Atanasyan Driver->addFile(Saver.save(Path.str())); 28316b0cc9eSSimon Atanasyan return; 28416b0cc9eSSimon Atanasyan } 28516b0cc9eSSimon Atanasyan } 28616b0cc9eSSimon Atanasyan 287f03f3cc1SRui Ueyama if (sys::path::is_absolute(S)) { 28852a1509eSRui Ueyama Driver->addFile(S); 28952a1509eSRui Ueyama } else if (S.startswith("=")) { 29052a1509eSRui Ueyama if (Config->Sysroot.empty()) 29152a1509eSRui Ueyama Driver->addFile(S.substr(1)); 29252a1509eSRui Ueyama else 29352a1509eSRui Ueyama Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); 29452a1509eSRui Ueyama } else if (S.startswith("-l")) { 29521eecb4fSRui Ueyama Driver->addLibrary(S.substr(2)); 296a1b8fc3bSSimon Atanasyan } else if (sys::fs::exists(S)) { 297a1b8fc3bSSimon Atanasyan Driver->addFile(S); 29852a1509eSRui Ueyama } else { 29952a1509eSRui Ueyama std::string Path = findFromSearchPaths(S); 30052a1509eSRui Ueyama if (Path.empty()) 301025d59b1SRui Ueyama setError("Unable to find " + S); 302025d59b1SRui Ueyama else 30352a1509eSRui Ueyama Driver->addFile(Saver.save(Path)); 30452a1509eSRui Ueyama } 30552a1509eSRui Ueyama } 30652a1509eSRui Ueyama 307717677afSRui Ueyama void ScriptParser::readAsNeeded() { 308f7c5fbb1SRui Ueyama expect("("); 30935da9b6eSRui Ueyama bool Orig = Config->AsNeeded; 31035da9b6eSRui Ueyama Config->AsNeeded = true; 311025d59b1SRui Ueyama while (!Error) { 312f7c5fbb1SRui Ueyama StringRef Tok = next(); 313f7c5fbb1SRui Ueyama if (Tok == ")") 31435da9b6eSRui Ueyama break; 31552a1509eSRui Ueyama addFile(Tok); 316f7c5fbb1SRui Ueyama } 31735da9b6eSRui Ueyama Config->AsNeeded = Orig; 318f7c5fbb1SRui Ueyama } 319f7c5fbb1SRui Ueyama 320717677afSRui Ueyama void ScriptParser::readEntry() { 32190c5099eSDenis Protivensky // -e <symbol> takes predecence over ENTRY(<symbol>). 32290c5099eSDenis Protivensky expect("("); 32390c5099eSDenis Protivensky StringRef Tok = next(); 32490c5099eSDenis Protivensky if (Config->Entry.empty()) 32590c5099eSDenis Protivensky Config->Entry = Tok; 32690c5099eSDenis Protivensky expect(")"); 32790c5099eSDenis Protivensky } 32890c5099eSDenis Protivensky 329717677afSRui Ueyama void ScriptParser::readExtern() { 33083f406cfSGeorge Rimar expect("("); 331025d59b1SRui Ueyama while (!Error) { 33283f406cfSGeorge Rimar StringRef Tok = next(); 33383f406cfSGeorge Rimar if (Tok == ")") 33483f406cfSGeorge Rimar return; 33583f406cfSGeorge Rimar Config->Undefined.push_back(Tok); 33683f406cfSGeorge Rimar } 33783f406cfSGeorge Rimar } 33883f406cfSGeorge Rimar 339717677afSRui Ueyama void ScriptParser::readGroup() { 340f7c5fbb1SRui Ueyama expect("("); 341025d59b1SRui Ueyama while (!Error) { 342f7c5fbb1SRui Ueyama StringRef Tok = next(); 343f7c5fbb1SRui Ueyama if (Tok == ")") 344f7c5fbb1SRui Ueyama return; 345f7c5fbb1SRui Ueyama if (Tok == "AS_NEEDED") { 346f7c5fbb1SRui Ueyama readAsNeeded(); 347f7c5fbb1SRui Ueyama continue; 348f7c5fbb1SRui Ueyama } 34952a1509eSRui Ueyama addFile(Tok); 350f7c5fbb1SRui Ueyama } 351f7c5fbb1SRui Ueyama } 352f7c5fbb1SRui Ueyama 353717677afSRui Ueyama void ScriptParser::readInclude() { 35431aa1f83SRui Ueyama StringRef Tok = next(); 35531aa1f83SRui Ueyama auto MBOrErr = MemoryBuffer::getFile(Tok); 356025d59b1SRui Ueyama if (!MBOrErr) { 357025d59b1SRui Ueyama setError("cannot open " + Tok); 358025d59b1SRui Ueyama return; 359025d59b1SRui Ueyama } 36031aa1f83SRui Ueyama std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; 361a47ee68dSRui Ueyama StringRef S = Saver.save(MB->getMemBufferRef().getBuffer()); 362a47ee68dSRui Ueyama std::vector<StringRef> V = tokenize(S); 36331aa1f83SRui Ueyama Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end()); 36431aa1f83SRui Ueyama } 36531aa1f83SRui Ueyama 366717677afSRui Ueyama void ScriptParser::readOutput() { 367ee59282bSRui Ueyama // -o <file> takes predecence over OUTPUT(<file>). 368ee59282bSRui Ueyama expect("("); 369ee59282bSRui Ueyama StringRef Tok = next(); 370ee59282bSRui Ueyama if (Config->OutputFile.empty()) 371ee59282bSRui Ueyama Config->OutputFile = Tok; 372ee59282bSRui Ueyama expect(")"); 373ee59282bSRui Ueyama } 374ee59282bSRui Ueyama 375717677afSRui Ueyama void ScriptParser::readOutputArch() { 3769159ce93SDavide Italiano // Error checking only for now. 3779159ce93SDavide Italiano expect("("); 3789159ce93SDavide Italiano next(); 3799159ce93SDavide Italiano expect(")"); 3809159ce93SDavide Italiano } 3819159ce93SDavide Italiano 382717677afSRui Ueyama void ScriptParser::readOutputFormat() { 383f7c5fbb1SRui Ueyama // Error checking only for now. 384f7c5fbb1SRui Ueyama expect("("); 385f7c5fbb1SRui Ueyama next(); 3866836c618SDavide Italiano StringRef Tok = next(); 3876836c618SDavide Italiano if (Tok == ")") 3886836c618SDavide Italiano return; 389025d59b1SRui Ueyama if (Tok != ",") { 390025d59b1SRui Ueyama setError("unexpected token: " + Tok); 391025d59b1SRui Ueyama return; 392025d59b1SRui Ueyama } 3936836c618SDavide Italiano next(); 3946836c618SDavide Italiano expect(","); 3956836c618SDavide Italiano next(); 396f7c5fbb1SRui Ueyama expect(")"); 397f7c5fbb1SRui Ueyama } 398f7c5fbb1SRui Ueyama 399717677afSRui Ueyama void ScriptParser::readSearchDir() { 40068a39a65SDavide Italiano expect("("); 40152a1509eSRui Ueyama Config->SearchPaths.push_back(next()); 40268a39a65SDavide Italiano expect(")"); 40368a39a65SDavide Italiano } 40468a39a65SDavide Italiano 405717677afSRui Ueyama void ScriptParser::readSections() { 4068e3b38abSDenis Protivensky expect("{"); 407025d59b1SRui Ueyama while (!Error && !skip("}")) 4088e3b38abSDenis Protivensky readOutputSectionDescription(); 4098e3b38abSDenis Protivensky } 4108e3b38abSDenis Protivensky 411481c2ce6SGeorge Rimar void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { 412481c2ce6SGeorge Rimar expect("("); 413481c2ce6SGeorge Rimar while (!Error && !skip(")")) 414481c2ce6SGeorge Rimar Script->Sections.emplace_back(OutSec, next(), Keep); 415481c2ce6SGeorge Rimar } 416481c2ce6SGeorge Rimar 417*e2ee72b5SGeorge Rimar std::vector<uint8_t> ScriptParser::parseHex(StringRef S) { 418*e2ee72b5SGeorge Rimar std::vector<uint8_t> Hex; 419*e2ee72b5SGeorge Rimar while (!S.empty()) { 420*e2ee72b5SGeorge Rimar StringRef B = S.substr(0, 2); 421*e2ee72b5SGeorge Rimar S = S.substr(2); 422*e2ee72b5SGeorge Rimar uint8_t H; 423*e2ee72b5SGeorge Rimar if (B.getAsInteger(16, H)) { 424*e2ee72b5SGeorge Rimar setError("Not a HEX value: " + B); 425*e2ee72b5SGeorge Rimar return {}; 426*e2ee72b5SGeorge Rimar } 427*e2ee72b5SGeorge Rimar Hex.push_back(H); 428*e2ee72b5SGeorge Rimar } 429*e2ee72b5SGeorge Rimar return Hex; 430*e2ee72b5SGeorge Rimar } 431*e2ee72b5SGeorge Rimar 432717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() { 433*e2ee72b5SGeorge Rimar OutSection OutSec; 434*e2ee72b5SGeorge Rimar OutSec.Name = next(); 4358e3b38abSDenis Protivensky expect(":"); 4368e3b38abSDenis Protivensky expect("{"); 437025d59b1SRui Ueyama while (!Error && !skip("}")) { 438481c2ce6SGeorge Rimar StringRef Tok = next(); 439481c2ce6SGeorge Rimar if (Tok == "*") { 440*e2ee72b5SGeorge Rimar readSectionPatterns(OutSec.Name, false); 441481c2ce6SGeorge Rimar } else if (Tok == "KEEP") { 4428e3b38abSDenis Protivensky expect("("); 443481c2ce6SGeorge Rimar next(); // Skip * 444*e2ee72b5SGeorge Rimar readSectionPatterns(OutSec.Name, true); 445481c2ce6SGeorge Rimar expect(")"); 446481c2ce6SGeorge Rimar } else { 447481c2ce6SGeorge Rimar setError("Unknown command " + Tok); 448481c2ce6SGeorge Rimar } 4498e3b38abSDenis Protivensky } 450*e2ee72b5SGeorge Rimar StringRef Tok = peek(); 451*e2ee72b5SGeorge Rimar if (Tok.startswith("=")) { 452*e2ee72b5SGeorge Rimar if (!Tok.startswith("=0x")) { 453*e2ee72b5SGeorge Rimar setError("Filler should be a HEX value"); 454*e2ee72b5SGeorge Rimar return; 455*e2ee72b5SGeorge Rimar } 456*e2ee72b5SGeorge Rimar Tok = Tok.substr(3); // Skip '=0x' 457*e2ee72b5SGeorge Rimar OutSec.Filler = parseHex(Tok); 458*e2ee72b5SGeorge Rimar next(); 459*e2ee72b5SGeorge Rimar } 460*e2ee72b5SGeorge Rimar Script->OutSections.push_back(OutSec); 4618e3b38abSDenis Protivensky } 4628e3b38abSDenis Protivensky 46316b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) { 46416b0cc9eSSimon Atanasyan if (Config->Sysroot == "") 46516b0cc9eSSimon Atanasyan return false; 46616b0cc9eSSimon Atanasyan for (; !Path.empty(); Path = sys::path::parent_path(Path)) 46716b0cc9eSSimon Atanasyan if (sys::fs::equivalent(Config->Sysroot, Path)) 46816b0cc9eSSimon Atanasyan return true; 46916b0cc9eSSimon Atanasyan return false; 47016b0cc9eSSimon Atanasyan } 47116b0cc9eSSimon Atanasyan 472f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file. 473f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) { 47416b0cc9eSSimon Atanasyan StringRef Path = MB.getBufferIdentifier(); 475f9de0d69SRui Ueyama ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); 476f7c5fbb1SRui Ueyama } 4771ebc8ed7SRui Ueyama 4781ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *); 4791ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *); 4801ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *); 4811ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *); 4821ebc8ed7SRui Ueyama 4831ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *); 4841ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *); 4851ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *); 4861ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *); 4871ebc8ed7SRui Ueyama 488481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *); 489481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *); 490481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *); 491481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *); 492