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" 20652852c5SGeorge Rimar #include "OutputSections.h" 21e77b5bf6SAdhemerval Zanella #include "ScriptParser.h" 22f7c5fbb1SRui Ueyama #include "SymbolTable.h" 23652852c5SGeorge Rimar #include "llvm/Support/ELF.h" 24f7c5fbb1SRui Ueyama #include "llvm/Support/FileSystem.h" 25f7c5fbb1SRui Ueyama #include "llvm/Support/MemoryBuffer.h" 26f03f3cc1SRui Ueyama #include "llvm/Support/Path.h" 27a47ee68dSRui Ueyama #include "llvm/Support/StringSaver.h" 28f7c5fbb1SRui Ueyama 29f7c5fbb1SRui Ueyama using namespace llvm; 30652852c5SGeorge Rimar using namespace llvm::ELF; 311ebc8ed7SRui Ueyama using namespace llvm::object; 32f7c5fbb1SRui Ueyama using namespace lld; 33e0df00b9SRafael Espindola using namespace lld::elf; 34f7c5fbb1SRui Ueyama 35e0df00b9SRafael Espindola LinkerScript *elf::Script; 36717677afSRui Ueyama 37652852c5SGeorge Rimar static uint64_t getInteger(StringRef S) { 38652852c5SGeorge Rimar uint64_t V; 39652852c5SGeorge Rimar if (S.getAsInteger(0, V)) { 40652852c5SGeorge Rimar error("malformed number: " + S); 41652852c5SGeorge Rimar return 0; 42652852c5SGeorge Rimar } 43652852c5SGeorge Rimar return V; 44652852c5SGeorge Rimar } 45652852c5SGeorge Rimar 46652852c5SGeorge Rimar // Evaluates the expression given by list of tokens. 47652852c5SGeorge Rimar uint64_t LinkerScript::evaluate(std::vector<StringRef> &Tokens, 48652852c5SGeorge Rimar uint64_t LocCounter) { 49652852c5SGeorge Rimar uint64_t Result = 0; 50652852c5SGeorge Rimar for (size_t I = 0, E = Tokens.size(); I < E; ++I) { 51652852c5SGeorge Rimar // Each second token should be '+' as this is the 52652852c5SGeorge Rimar // only operator we support now. 53652852c5SGeorge Rimar if (I % 2 == 1) { 54652852c5SGeorge Rimar if (Tokens[I] == "+") 55652852c5SGeorge Rimar continue; 56652852c5SGeorge Rimar error("error in location counter expression"); 57652852c5SGeorge Rimar return 0; 58652852c5SGeorge Rimar } 59652852c5SGeorge Rimar 60652852c5SGeorge Rimar StringRef Tok = Tokens[I]; 61652852c5SGeorge Rimar if (Tok == ".") 62652852c5SGeorge Rimar Result += LocCounter; 63652852c5SGeorge Rimar else 64652852c5SGeorge Rimar Result += getInteger(Tok); 65652852c5SGeorge Rimar } 66652852c5SGeorge Rimar return Result; 67652852c5SGeorge Rimar } 68652852c5SGeorge Rimar 691ebc8ed7SRui Ueyama template <class ELFT> 70481c2ce6SGeorge Rimar SectionRule *LinkerScript::find(InputSectionBase<ELFT> *S) { 711ebc8ed7SRui Ueyama for (SectionRule &R : Sections) 721ebc8ed7SRui Ueyama if (R.match(S)) 73481c2ce6SGeorge Rimar return &R; 74481c2ce6SGeorge Rimar return nullptr; 75481c2ce6SGeorge Rimar } 76481c2ce6SGeorge Rimar 77481c2ce6SGeorge Rimar template <class ELFT> 78481c2ce6SGeorge Rimar StringRef LinkerScript::getOutputSection(InputSectionBase<ELFT> *S) { 79481c2ce6SGeorge Rimar SectionRule *R = find(S); 80481c2ce6SGeorge Rimar return R ? R->Dest : ""; 81717677afSRui Ueyama } 82717677afSRui Ueyama 831ebc8ed7SRui Ueyama template <class ELFT> 841ebc8ed7SRui Ueyama bool LinkerScript::isDiscarded(InputSectionBase<ELFT> *S) { 851ebc8ed7SRui Ueyama return getOutputSection(S) == "/DISCARD/"; 86717677afSRui Ueyama } 87717677afSRui Ueyama 88481c2ce6SGeorge Rimar template <class ELFT> bool LinkerScript::shouldKeep(InputSectionBase<ELFT> *S) { 89481c2ce6SGeorge Rimar SectionRule *R = find(S); 90481c2ce6SGeorge Rimar return R && R->Keep; 91481c2ce6SGeorge Rimar } 92481c2ce6SGeorge Rimar 93652852c5SGeorge Rimar template <class ELFT> 947c18c28cSRui Ueyama static OutputSectionBase<ELFT> * 957c18c28cSRui Ueyama findSection(std::vector<OutputSectionBase<ELFT> *> &V, StringRef Name) { 967c18c28cSRui Ueyama for (OutputSectionBase<ELFT> *Sec : V) 977c18c28cSRui Ueyama if (Sec->getName() == Name) 987c18c28cSRui Ueyama return Sec; 997c18c28cSRui Ueyama return nullptr; 1007c18c28cSRui Ueyama } 1017c18c28cSRui Ueyama 1027c18c28cSRui Ueyama template <class ELFT> 1037c18c28cSRui Ueyama void LinkerScript::assignAddresses( 1047c18c28cSRui Ueyama std::vector<OutputSectionBase<ELFT> *> &Sections) { 1057c18c28cSRui Ueyama typedef typename ELFT::uint uintX_t; 1067c18c28cSRui Ueyama 107652852c5SGeorge Rimar // Orphan sections are sections present in the input files which 1087c18c28cSRui Ueyama // are not explicitly placed into the output file by the linker script. 1097c18c28cSRui Ueyama // We place orphan sections at end of file. 1107c18c28cSRui Ueyama // Other linkers places them using some heuristics as described in 111652852c5SGeorge Rimar // https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections. 1127c18c28cSRui Ueyama for (OutputSectionBase<ELFT> *Sec : Sections) { 113652852c5SGeorge Rimar StringRef Name = Sec->getName(); 114652852c5SGeorge Rimar auto I = std::find(SectionOrder.begin(), SectionOrder.end(), Name); 115652852c5SGeorge Rimar if (I == SectionOrder.end()) 116*9e957a0aSRui Ueyama Commands.push_back({SectionKind, {}, Name}); 117652852c5SGeorge Rimar } 118652852c5SGeorge Rimar 1197c18c28cSRui Ueyama // Assign addresses as instructed by linker script SECTIONS sub-commands. 120652852c5SGeorge Rimar uintX_t ThreadBssOffset = 0; 121652852c5SGeorge Rimar uintX_t VA = 122652852c5SGeorge Rimar Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize(); 123652852c5SGeorge Rimar 124*9e957a0aSRui Ueyama for (SectionsCommand &Cmd : Commands) { 125*9e957a0aSRui Ueyama if (Cmd.Kind == ExprKind) { 126*9e957a0aSRui Ueyama VA = evaluate(Cmd.Expr, VA); 127652852c5SGeorge Rimar continue; 128652852c5SGeorge Rimar } 129652852c5SGeorge Rimar 130*9e957a0aSRui Ueyama OutputSectionBase<ELFT> *Sec = findSection(Sections, Cmd.SectionName); 1317c18c28cSRui Ueyama if (!Sec) 132652852c5SGeorge Rimar continue; 133652852c5SGeorge Rimar 134652852c5SGeorge Rimar if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { 135652852c5SGeorge Rimar uintX_t TVA = VA + ThreadBssOffset; 1367c18c28cSRui Ueyama TVA = alignTo(TVA, Sec->getAlign()); 137652852c5SGeorge Rimar Sec->setVA(TVA); 138652852c5SGeorge Rimar ThreadBssOffset = TVA - VA + Sec->getSize(); 139652852c5SGeorge Rimar continue; 140652852c5SGeorge Rimar } 141652852c5SGeorge Rimar 142652852c5SGeorge Rimar if (Sec->getFlags() & SHF_ALLOC) { 1437c18c28cSRui Ueyama VA = alignTo(VA, Sec->getAlign()); 144652852c5SGeorge Rimar Sec->setVA(VA); 145652852c5SGeorge Rimar VA += Sec->getSize(); 146652852c5SGeorge Rimar continue; 147652852c5SGeorge Rimar } 148652852c5SGeorge Rimar } 149652852c5SGeorge Rimar } 150652852c5SGeorge Rimar 151e2ee72b5SGeorge Rimar ArrayRef<uint8_t> LinkerScript::getFiller(StringRef Name) { 1523e808976SRui Ueyama auto I = Filler.find(Name); 1533e808976SRui Ueyama if (I == Filler.end()) 154e2ee72b5SGeorge Rimar return {}; 1553e808976SRui Ueyama return I->second; 156e2ee72b5SGeorge Rimar } 157e2ee72b5SGeorge Rimar 158e9c58065SRui Ueyama // A compartor to sort output sections. Returns -1 or 1 if both 159e9c58065SRui Ueyama // A and B are mentioned in linker scripts. Otherwise, returns 0 160e9c58065SRui Ueyama // to use the default rule which is implemented in Writer.cpp. 161717677afSRui Ueyama int LinkerScript::compareSections(StringRef A, StringRef B) { 1623e808976SRui Ueyama auto E = SectionOrder.end(); 1633e808976SRui Ueyama auto I = std::find(SectionOrder.begin(), E, A); 1643e808976SRui Ueyama auto J = std::find(SectionOrder.begin(), E, B); 1653e808976SRui Ueyama if (I == E || J == E) 166717677afSRui Ueyama return 0; 167717677afSRui Ueyama return I < J ? -1 : 1; 168717677afSRui Ueyama } 169717677afSRui Ueyama 170cb2aeb66SGeorge Rimar // Returns true if S matches T. S can contain glob meta-characters. 171cb2aeb66SGeorge Rimar // The asterisk ('*') matches zero or more characacters, and the question 172cb2aeb66SGeorge Rimar // mark ('?') matches one character. 1731ebc8ed7SRui Ueyama static bool matchStr(StringRef S, StringRef T) { 1741ebc8ed7SRui Ueyama for (;;) { 1751ebc8ed7SRui Ueyama if (S.empty()) 1761ebc8ed7SRui Ueyama return T.empty(); 1771ebc8ed7SRui Ueyama if (S[0] == '*') { 1781ebc8ed7SRui Ueyama S = S.substr(1); 1791ebc8ed7SRui Ueyama if (S.empty()) 1801ebc8ed7SRui Ueyama // Fast path. If a pattern is '*', it matches anything. 1811ebc8ed7SRui Ueyama return true; 1821ebc8ed7SRui Ueyama for (size_t I = 0, E = T.size(); I < E; ++I) 1831ebc8ed7SRui Ueyama if (matchStr(S, T.substr(I))) 1841ebc8ed7SRui Ueyama return true; 1851ebc8ed7SRui Ueyama return false; 1861ebc8ed7SRui Ueyama } 187cb2aeb66SGeorge Rimar if (T.empty() || (S[0] != T[0] && S[0] != '?')) 1881ebc8ed7SRui Ueyama return false; 1891ebc8ed7SRui Ueyama S = S.substr(1); 1901ebc8ed7SRui Ueyama T = T.substr(1); 1911ebc8ed7SRui Ueyama } 1921ebc8ed7SRui Ueyama } 1931ebc8ed7SRui Ueyama 1941ebc8ed7SRui Ueyama template <class ELFT> bool SectionRule::match(InputSectionBase<ELFT> *S) { 1951ebc8ed7SRui Ueyama return matchStr(SectionPattern, S->getSectionName()); 1961ebc8ed7SRui Ueyama } 1971ebc8ed7SRui Ueyama 198e77b5bf6SAdhemerval Zanella class elf::ScriptParser final : public elf::ScriptParserBase { 199c3794e58SGeorge Rimar typedef void (ScriptParser::*Handler)(); 200c3794e58SGeorge Rimar 201f7c5fbb1SRui Ueyama public: 202717677afSRui Ueyama ScriptParser(BumpPtrAllocator *A, StringRef S, bool B) 203e77b5bf6SAdhemerval Zanella : ScriptParserBase(S), Saver(*A), IsUnderSysroot(B) {} 204f23b2320SGeorge Rimar 205e77b5bf6SAdhemerval Zanella void run() override; 206f7c5fbb1SRui Ueyama 207f7c5fbb1SRui Ueyama private: 20852a1509eSRui Ueyama void addFile(StringRef Path); 20952a1509eSRui Ueyama 210f7c5fbb1SRui Ueyama void readAsNeeded(); 21190c5099eSDenis Protivensky void readEntry(); 21283f406cfSGeorge Rimar void readExtern(); 213f7c5fbb1SRui Ueyama void readGroup(); 21431aa1f83SRui Ueyama void readInclude(); 215c3794e58SGeorge Rimar void readNothing() {} 216ee59282bSRui Ueyama void readOutput(); 2179159ce93SDavide Italiano void readOutputArch(); 218f7c5fbb1SRui Ueyama void readOutputFormat(); 21968a39a65SDavide Italiano void readSearchDir(); 2208e3b38abSDenis Protivensky void readSections(); 2218e3b38abSDenis Protivensky 222652852c5SGeorge Rimar void readLocationCounterValue(); 2238e3b38abSDenis Protivensky void readOutputSectionDescription(); 224481c2ce6SGeorge Rimar void readSectionPatterns(StringRef OutSec, bool Keep); 225f7c5fbb1SRui Ueyama 226a47ee68dSRui Ueyama StringSaver Saver; 227c3794e58SGeorge Rimar const static StringMap<Handler> Cmd; 22816b0cc9eSSimon Atanasyan bool IsUnderSysroot; 229f7c5fbb1SRui Ueyama }; 230f7c5fbb1SRui Ueyama 231e0df00b9SRafael Espindola const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = { 232c3794e58SGeorge Rimar {"ENTRY", &ScriptParser::readEntry}, 233c3794e58SGeorge Rimar {"EXTERN", &ScriptParser::readExtern}, 234c3794e58SGeorge Rimar {"GROUP", &ScriptParser::readGroup}, 235c3794e58SGeorge Rimar {"INCLUDE", &ScriptParser::readInclude}, 236c3794e58SGeorge Rimar {"INPUT", &ScriptParser::readGroup}, 237c3794e58SGeorge Rimar {"OUTPUT", &ScriptParser::readOutput}, 238c3794e58SGeorge Rimar {"OUTPUT_ARCH", &ScriptParser::readOutputArch}, 239c3794e58SGeorge Rimar {"OUTPUT_FORMAT", &ScriptParser::readOutputFormat}, 240c3794e58SGeorge Rimar {"SEARCH_DIR", &ScriptParser::readSearchDir}, 241c3794e58SGeorge Rimar {"SECTIONS", &ScriptParser::readSections}, 242c3794e58SGeorge Rimar {";", &ScriptParser::readNothing}}; 243c3794e58SGeorge Rimar 244717677afSRui Ueyama void ScriptParser::run() { 245f7c5fbb1SRui Ueyama while (!atEOF()) { 246f7c5fbb1SRui Ueyama StringRef Tok = next(); 247c3794e58SGeorge Rimar if (Handler Fn = Cmd.lookup(Tok)) 248c3794e58SGeorge Rimar (this->*Fn)(); 249c3794e58SGeorge Rimar else 2505761042dSGeorge Rimar setError("unknown directive: " + Tok); 251f7c5fbb1SRui Ueyama } 252f7c5fbb1SRui Ueyama } 253f7c5fbb1SRui Ueyama 254717677afSRui Ueyama void ScriptParser::addFile(StringRef S) { 25516b0cc9eSSimon Atanasyan if (IsUnderSysroot && S.startswith("/")) { 25616b0cc9eSSimon Atanasyan SmallString<128> Path; 25716b0cc9eSSimon Atanasyan (Config->Sysroot + S).toStringRef(Path); 25816b0cc9eSSimon Atanasyan if (sys::fs::exists(Path)) { 25916b0cc9eSSimon Atanasyan Driver->addFile(Saver.save(Path.str())); 26016b0cc9eSSimon Atanasyan return; 26116b0cc9eSSimon Atanasyan } 26216b0cc9eSSimon Atanasyan } 26316b0cc9eSSimon Atanasyan 264f03f3cc1SRui Ueyama if (sys::path::is_absolute(S)) { 26552a1509eSRui Ueyama Driver->addFile(S); 26652a1509eSRui Ueyama } else if (S.startswith("=")) { 26752a1509eSRui Ueyama if (Config->Sysroot.empty()) 26852a1509eSRui Ueyama Driver->addFile(S.substr(1)); 26952a1509eSRui Ueyama else 27052a1509eSRui Ueyama Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1))); 27152a1509eSRui Ueyama } else if (S.startswith("-l")) { 27221eecb4fSRui Ueyama Driver->addLibrary(S.substr(2)); 273a1b8fc3bSSimon Atanasyan } else if (sys::fs::exists(S)) { 274a1b8fc3bSSimon Atanasyan Driver->addFile(S); 27552a1509eSRui Ueyama } else { 27652a1509eSRui Ueyama std::string Path = findFromSearchPaths(S); 27752a1509eSRui Ueyama if (Path.empty()) 278777f9630SGeorge Rimar setError("unable to find " + S); 279025d59b1SRui Ueyama else 28052a1509eSRui Ueyama Driver->addFile(Saver.save(Path)); 28152a1509eSRui Ueyama } 28252a1509eSRui Ueyama } 28352a1509eSRui Ueyama 284717677afSRui Ueyama void ScriptParser::readAsNeeded() { 285f7c5fbb1SRui Ueyama expect("("); 28635da9b6eSRui Ueyama bool Orig = Config->AsNeeded; 28735da9b6eSRui Ueyama Config->AsNeeded = true; 288025d59b1SRui Ueyama while (!Error) { 289f7c5fbb1SRui Ueyama StringRef Tok = next(); 290f7c5fbb1SRui Ueyama if (Tok == ")") 29135da9b6eSRui Ueyama break; 29252a1509eSRui Ueyama addFile(Tok); 293f7c5fbb1SRui Ueyama } 29435da9b6eSRui Ueyama Config->AsNeeded = Orig; 295f7c5fbb1SRui Ueyama } 296f7c5fbb1SRui Ueyama 297717677afSRui Ueyama void ScriptParser::readEntry() { 29890c5099eSDenis Protivensky // -e <symbol> takes predecence over ENTRY(<symbol>). 29990c5099eSDenis Protivensky expect("("); 30090c5099eSDenis Protivensky StringRef Tok = next(); 30190c5099eSDenis Protivensky if (Config->Entry.empty()) 30290c5099eSDenis Protivensky Config->Entry = Tok; 30390c5099eSDenis Protivensky expect(")"); 30490c5099eSDenis Protivensky } 30590c5099eSDenis Protivensky 306717677afSRui Ueyama void ScriptParser::readExtern() { 30783f406cfSGeorge Rimar expect("("); 308025d59b1SRui Ueyama while (!Error) { 30983f406cfSGeorge Rimar StringRef Tok = next(); 31083f406cfSGeorge Rimar if (Tok == ")") 31183f406cfSGeorge Rimar return; 31283f406cfSGeorge Rimar Config->Undefined.push_back(Tok); 31383f406cfSGeorge Rimar } 31483f406cfSGeorge Rimar } 31583f406cfSGeorge Rimar 316717677afSRui Ueyama void ScriptParser::readGroup() { 317f7c5fbb1SRui Ueyama expect("("); 318025d59b1SRui Ueyama while (!Error) { 319f7c5fbb1SRui Ueyama StringRef Tok = next(); 320f7c5fbb1SRui Ueyama if (Tok == ")") 321f7c5fbb1SRui Ueyama return; 322f7c5fbb1SRui Ueyama if (Tok == "AS_NEEDED") { 323f7c5fbb1SRui Ueyama readAsNeeded(); 324f7c5fbb1SRui Ueyama continue; 325f7c5fbb1SRui Ueyama } 32652a1509eSRui Ueyama addFile(Tok); 327f7c5fbb1SRui Ueyama } 328f7c5fbb1SRui Ueyama } 329f7c5fbb1SRui Ueyama 330717677afSRui Ueyama void ScriptParser::readInclude() { 33131aa1f83SRui Ueyama StringRef Tok = next(); 33231aa1f83SRui Ueyama auto MBOrErr = MemoryBuffer::getFile(Tok); 333025d59b1SRui Ueyama if (!MBOrErr) { 3345761042dSGeorge Rimar setError("cannot open " + Tok); 335025d59b1SRui Ueyama return; 336025d59b1SRui Ueyama } 33731aa1f83SRui Ueyama std::unique_ptr<MemoryBuffer> &MB = *MBOrErr; 338a47ee68dSRui Ueyama StringRef S = Saver.save(MB->getMemBufferRef().getBuffer()); 339a47ee68dSRui Ueyama std::vector<StringRef> V = tokenize(S); 34031aa1f83SRui Ueyama Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end()); 34131aa1f83SRui Ueyama } 34231aa1f83SRui Ueyama 343717677afSRui Ueyama void ScriptParser::readOutput() { 344ee59282bSRui Ueyama // -o <file> takes predecence over OUTPUT(<file>). 345ee59282bSRui Ueyama expect("("); 346ee59282bSRui Ueyama StringRef Tok = next(); 347ee59282bSRui Ueyama if (Config->OutputFile.empty()) 348ee59282bSRui Ueyama Config->OutputFile = Tok; 349ee59282bSRui Ueyama expect(")"); 350ee59282bSRui Ueyama } 351ee59282bSRui Ueyama 352717677afSRui Ueyama void ScriptParser::readOutputArch() { 3539159ce93SDavide Italiano // Error checking only for now. 3549159ce93SDavide Italiano expect("("); 3559159ce93SDavide Italiano next(); 3569159ce93SDavide Italiano expect(")"); 3579159ce93SDavide Italiano } 3589159ce93SDavide Italiano 359717677afSRui Ueyama void ScriptParser::readOutputFormat() { 360f7c5fbb1SRui Ueyama // Error checking only for now. 361f7c5fbb1SRui Ueyama expect("("); 362f7c5fbb1SRui Ueyama next(); 3636836c618SDavide Italiano StringRef Tok = next(); 3646836c618SDavide Italiano if (Tok == ")") 3656836c618SDavide Italiano return; 366025d59b1SRui Ueyama if (Tok != ",") { 3675761042dSGeorge Rimar setError("unexpected token: " + Tok); 368025d59b1SRui Ueyama return; 369025d59b1SRui Ueyama } 3706836c618SDavide Italiano next(); 3716836c618SDavide Italiano expect(","); 3726836c618SDavide Italiano next(); 373f7c5fbb1SRui Ueyama expect(")"); 374f7c5fbb1SRui Ueyama } 375f7c5fbb1SRui Ueyama 376717677afSRui Ueyama void ScriptParser::readSearchDir() { 37768a39a65SDavide Italiano expect("("); 37806501920SRafael Espindola Config->SearchPaths.push_back(next()); 37968a39a65SDavide Italiano expect(")"); 38068a39a65SDavide Italiano } 38168a39a65SDavide Italiano 382717677afSRui Ueyama void ScriptParser::readSections() { 383652852c5SGeorge Rimar Script->DoLayout = true; 3848e3b38abSDenis Protivensky expect("{"); 385652852c5SGeorge Rimar while (!Error && !skip("}")) { 386652852c5SGeorge Rimar StringRef Tok = peek(); 387652852c5SGeorge Rimar if (Tok == ".") 388652852c5SGeorge Rimar readLocationCounterValue(); 389652852c5SGeorge Rimar else 3908e3b38abSDenis Protivensky readOutputSectionDescription(); 3918e3b38abSDenis Protivensky } 392652852c5SGeorge Rimar } 3938e3b38abSDenis Protivensky 394481c2ce6SGeorge Rimar void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) { 395481c2ce6SGeorge Rimar expect("("); 396481c2ce6SGeorge Rimar while (!Error && !skip(")")) 397481c2ce6SGeorge Rimar Script->Sections.emplace_back(OutSec, next(), Keep); 398481c2ce6SGeorge Rimar } 399481c2ce6SGeorge Rimar 400652852c5SGeorge Rimar void ScriptParser::readLocationCounterValue() { 401652852c5SGeorge Rimar expect("."); 402652852c5SGeorge Rimar expect("="); 403*9e957a0aSRui Ueyama Script->Commands.push_back({ExprKind, {}, ""}); 404*9e957a0aSRui Ueyama SectionsCommand &Cmd = Script->Commands.back(); 405652852c5SGeorge Rimar while (!Error) { 406652852c5SGeorge Rimar StringRef Tok = next(); 407652852c5SGeorge Rimar if (Tok == ";") 408652852c5SGeorge Rimar break; 409*9e957a0aSRui Ueyama Cmd.Expr.push_back(Tok); 410652852c5SGeorge Rimar } 411*9e957a0aSRui Ueyama if (Cmd.Expr.empty()) 412652852c5SGeorge Rimar error("error in location counter expression"); 413652852c5SGeorge Rimar } 414652852c5SGeorge Rimar 415717677afSRui Ueyama void ScriptParser::readOutputSectionDescription() { 4163e808976SRui Ueyama StringRef OutSec = next(); 4173e808976SRui Ueyama Script->SectionOrder.push_back(OutSec); 418*9e957a0aSRui Ueyama Script->Commands.push_back({SectionKind, {}, OutSec}); 4198e3b38abSDenis Protivensky expect(":"); 4208e3b38abSDenis Protivensky expect("{"); 421025d59b1SRui Ueyama while (!Error && !skip("}")) { 422481c2ce6SGeorge Rimar StringRef Tok = next(); 423481c2ce6SGeorge Rimar if (Tok == "*") { 4243e808976SRui Ueyama readSectionPatterns(OutSec, false); 425481c2ce6SGeorge Rimar } else if (Tok == "KEEP") { 4268e3b38abSDenis Protivensky expect("("); 427481c2ce6SGeorge Rimar next(); // Skip * 4283e808976SRui Ueyama readSectionPatterns(OutSec, true); 429481c2ce6SGeorge Rimar expect(")"); 430481c2ce6SGeorge Rimar } else { 431777f9630SGeorge Rimar setError("unknown command " + Tok); 432481c2ce6SGeorge Rimar } 4338e3b38abSDenis Protivensky } 434e2ee72b5SGeorge Rimar StringRef Tok = peek(); 435e2ee72b5SGeorge Rimar if (Tok.startswith("=")) { 436e2ee72b5SGeorge Rimar if (!Tok.startswith("=0x")) { 4373ed2f069SRui Ueyama setError("filler should be a hexadecimal value"); 438e2ee72b5SGeorge Rimar return; 439e2ee72b5SGeorge Rimar } 4403e808976SRui Ueyama Tok = Tok.substr(3); 4413e808976SRui Ueyama Script->Filler[OutSec] = parseHex(Tok); 442e2ee72b5SGeorge Rimar next(); 443e2ee72b5SGeorge Rimar } 4448e3b38abSDenis Protivensky } 4458e3b38abSDenis Protivensky 44616b0cc9eSSimon Atanasyan static bool isUnderSysroot(StringRef Path) { 44716b0cc9eSSimon Atanasyan if (Config->Sysroot == "") 44816b0cc9eSSimon Atanasyan return false; 44916b0cc9eSSimon Atanasyan for (; !Path.empty(); Path = sys::path::parent_path(Path)) 45016b0cc9eSSimon Atanasyan if (sys::fs::equivalent(Config->Sysroot, Path)) 45116b0cc9eSSimon Atanasyan return true; 45216b0cc9eSSimon Atanasyan return false; 45316b0cc9eSSimon Atanasyan } 45416b0cc9eSSimon Atanasyan 455f7c5fbb1SRui Ueyama // Entry point. The other functions or classes are private to this file. 456f9de0d69SRui Ueyama void LinkerScript::read(MemoryBufferRef MB) { 45716b0cc9eSSimon Atanasyan StringRef Path = MB.getBufferIdentifier(); 458f9de0d69SRui Ueyama ScriptParser(&Alloc, MB.getBuffer(), isUnderSysroot(Path)).run(); 459f7c5fbb1SRui Ueyama } 4601ebc8ed7SRui Ueyama 4611ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32LE> *); 4621ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF32BE> *); 4631ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64LE> *); 4641ebc8ed7SRui Ueyama template StringRef LinkerScript::getOutputSection(InputSectionBase<ELF64BE> *); 4651ebc8ed7SRui Ueyama 4661ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32LE> *); 4671ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF32BE> *); 4681ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64LE> *); 4691ebc8ed7SRui Ueyama template bool LinkerScript::isDiscarded(InputSectionBase<ELF64BE> *); 4701ebc8ed7SRui Ueyama 471481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32LE> *); 472481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF32BE> *); 473481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64LE> *); 474481c2ce6SGeorge Rimar template bool LinkerScript::shouldKeep(InputSectionBase<ELF64BE> *); 475652852c5SGeorge Rimar 476652852c5SGeorge Rimar template void 477652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32LE> *> &); 478652852c5SGeorge Rimar template void 479652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF32BE> *> &); 480652852c5SGeorge Rimar template void 481652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64LE> *> &); 482652852c5SGeorge Rimar template void 483652852c5SGeorge Rimar LinkerScript::assignAddresses(std::vector<OutputSectionBase<ELF64BE> *> &); 484