Lines Matching +full:cmd +full:- +full:max +full:- +full:name
1 //===- ScriptParser.cpp ---------------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains a recursive-descendent parser for linker scripts.
12 //===----------------------------------------------------------------------===//
53 if (config->sysroot == "") in ScriptParser()
57 if (!sys::fs::equivalent(config->sysroot, path)) in ScriptParser()
67 void readDefsym(StringRef name);
92 SymbolAssignment *readSymbolAssignment(StringRef name);
95 bool readSectionDirective(OutputSection *cmd, StringRef tok);
96 void readSectionAddressType(OutputSection *cmd);
138 // True if a script being read is in the --sysroot directory.
145 // then this member is set to the PROVIDE symbol name.
152 return s.substr(1, s.size() - 2); in unquote()
162 script->recordError( in moveAbsRight()
174 return a.getValue() - b.getValue(); in sub()
175 return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc}; in sub()
181 (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc}; in bitAnd()
187 (a.getValue() ^ b.getValue()) - a.getSecAddr(), a.loc}; in bitXor()
193 (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc}; in bitOr()
208 setError("\"local:\" scope not supported in --dynamic-list"); in readDynamicList()
213 config->dynamicList.push_back(v); in readDynamicList()
288 } else if (SymbolAssignment *cmd = readAssignment(tok)) { in readLinkerScript() local
289 script->sectionCommands.push_back(cmd); in readLinkerScript()
296 void ScriptParser::readDefsym(StringRef name) { in readDefsym() argument
302 auto *cmd = make<SymbolAssignment>( in readDefsym() local
303 name, e, 0, getCurrentMB().getBufferIdentifier().str()); in readDefsym()
304 script->sectionCommands.push_back(cmd); in readDefsym()
309 NoCrossRefCommand cmd{{}, to}; in readNoCrossRefs() local
311 cmd.outputSections.push_back(unquote(next())); in readNoCrossRefs()
312 if (cmd.outputSections.size() < 2) in readNoCrossRefs()
315 script->noCrossRefs.push_back(std::move(cmd)); in readNoCrossRefs()
321 StringRef path = (config->sysroot + s).toStringRef(pathData); in addFile()
325 setError("cannot find " + s + " inside " + config->sysroot); in addFile()
334 if (config->sysroot.empty()) in addFile()
337 ctx.driver.addFile(saver().save(config->sysroot + "/" + s.substr(1)), in addFile()
339 } else if (s.starts_with("-l")) { in addFile()
369 bool orig = config->asNeeded; in readAsNeeded()
370 config->asNeeded = true; in readAsNeeded()
373 config->asNeeded = orig; in readAsNeeded()
377 // -e <symbol> takes predecence over ENTRY(<symbol>). in readEntry()
380 if (config->entry.empty()) in readEntry()
381 config->entry = unquote(tok); in readEntry()
388 config->undefined.push_back(unquote(next())); in readExtern()
427 // -o <file> takes predecence over OUTPUT(<file>). in readOutput()
430 if (config->outputFile.empty()) in readOutput()
431 config->outputFile = unquote(tok); in readOutput()
444 .Case("elf32-i386", {ELF32LEKind, EM_386}) in parseBfdName()
445 .Case("elf32-avr", {ELF32LEKind, EM_AVR}) in parseBfdName()
446 .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU}) in parseBfdName()
447 .Case("elf32-littlearm", {ELF32LEKind, EM_ARM}) in parseBfdName()
448 .Case("elf32-bigarm", {ELF32BEKind, EM_ARM}) in parseBfdName()
449 .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) in parseBfdName()
450 .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) in parseBfdName()
451 .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) in parseBfdName()
452 .Case("elf64-bigaarch64", {ELF64BEKind, EM_AARCH64}) in parseBfdName()
453 .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) in parseBfdName()
454 .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC}) in parseBfdName()
455 .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) in parseBfdName()
456 .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) in parseBfdName()
457 .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) in parseBfdName()
458 .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS}) in parseBfdName()
459 .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) in parseBfdName()
460 .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) in parseBfdName()
461 .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) in parseBfdName()
462 .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS}) in parseBfdName()
463 .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS}) in parseBfdName()
464 .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV}) in parseBfdName()
465 .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV}) in parseBfdName()
466 .Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9}) in parseBfdName()
467 .Case("elf32-msp430", {ELF32LEKind, EM_MSP430}) in parseBfdName()
468 .Case("elf32-loongarch", {ELF32LEKind, EM_LOONGARCH}) in parseBfdName()
469 .Case("elf64-loongarch", {ELF64LEKind, EM_LOONGARCH}) in parseBfdName()
470 .Case("elf64-s390", {ELF64BEKind, EM_S390}) in parseBfdName()
471 .Cases("elf32-hexagon", "elf32-littlehexagon", {ELF32LEKind, EM_HEXAGON}) in parseBfdName()
476 // big if -EB is specified, little if -EL is specified, or default if neither is
485 if (config->optEB) in readOutputFormat()
489 if (config->optEL) in readOutputFormat()
494 if (!config->bfdname.empty()) in readOutputFormat()
496 config->bfdname = s; in readOutputFormat()
499 config->oFormatBinary = true; in readOutputFormat()
503 if (s.consume_back("-freebsd")) in readOutputFormat()
504 config->osabi = ELFOSABI_FREEBSD; in readOutputFormat()
506 std::tie(config->ekind, config->emachine) = parseBfdName(s); in readOutputFormat()
507 if (config->emachine == EM_NONE) in readOutputFormat()
508 setError("unknown output format name: " + config->bfdname); in readOutputFormat()
509 if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips") in readOutputFormat()
510 config->mipsN32Abi = true; in readOutputFormat()
511 if (config->emachine == EM_MSP430) in readOutputFormat()
512 config->osabi = ELFOSABI_STANDALONE; in readOutputFormat()
519 PhdrsCommand cmd; in readPhdrs() local
520 cmd.name = next(); in readPhdrs()
521 cmd.type = readPhdrType(); in readPhdrs()
525 cmd.hasFilehdr = true; in readPhdrs()
527 cmd.hasPhdrs = true; in readPhdrs()
529 cmd.lmaExpr = readParenExpr(); in readPhdrs()
531 cmd.flags = readParenExpr()().getValue(); in readPhdrs()
536 script->phdrsCommands.push_back(cmd); in readPhdrs()
544 StringRef name = next(); in readRegionAlias() local
547 if (script->memoryRegions.count(alias)) in readRegionAlias()
549 if (!script->memoryRegions.count(name)) in readRegionAlias()
550 setError("memory region '" + name + "' is not defined"); in readRegionAlias()
551 script->memoryRegions.insert({alias, script->memoryRegions[name]}); in readRegionAlias()
557 if (!config->nostdlib) in readSearchDir()
558 config->searchPaths.push_back(unquote(tok)); in readSearchDir()
565 // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
569 addrExpr = [] { return script->getDot(); }; in readOverlay()
574 // When AT is omitted, LMA should equal VMA. script->getDot() when evaluating in readOverlay()
577 consume("AT") ? readParenExpr() : [] { return script->getDot(); }; in readOverlay()
586 osd->osec.addrExpr = addrExpr; in readOverlay()
588 osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; }; in readOverlay()
590 osd->osec.lmaExpr = lmaExpr; in readOverlay()
593 osd->osec.usedInExpression = true; in readOverlay()
594 addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; }; in readOverlay()
597 prev = &osd->osec; in readOverlay()
605 uint64_t max = 0; in readOverlay() local
606 for (SectionCommand *cmd : v) in readOverlay()
607 max = std::max(max, cast<OutputDesc>(cmd)->osec.size); in readOverlay()
608 return addrExpr().getValue() + max; in readOverlay()
617 script->overwriteSections.push_back(readOutputSectionDescription(next())); in readOverwriteSections()
626 for (SectionCommand *cmd : readOverlay()) in readSections()
627 v.push_back(cmd); in readSections()
634 if (SectionCommand *cmd = readAssignment(tok)) in readSections() local
635 v.push_back(cmd); in readSections()
642 if (!script->seenRelroEnd) in readSections()
643 for (SectionCommand *cmd : v) in readSections()
644 if (auto *osd = dyn_cast<OutputDesc>(cmd)) in readSections()
645 osd->osec.relro = false; in readSections()
647 script->sectionCommands.insert(script->sectionCommands.end(), v.begin(), in readSections()
651 script->hasSectionsCommand = true; in readSections()
662 for (SectionCommand *cmd : v) in readSections()
663 if (auto *os = dyn_cast<OutputDesc>(cmd)) in readSections()
664 names.push_back(os->osec.name); in readSections()
666 script->insertCommands.push_back({std::move(names), isAfter, where}); in readSections()
670 // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers, in readTarget()
672 // for --format. We recognize only /^elf/ and "binary" in the linker in readTarget()
679 config->formatBinary = false; in readTarget()
681 config->formatBinary = true; in readTarget()
689 .Cases("+", "-", 10) in precedence()
699 .Default(-1); in precedence()
713 .Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name) in peekSortKind()
730 // <elem> ::= <exclude>? <glob-pattern>
731 // <exclude> ::= "EXCLUDE_FILE" "(" <glob-pattern>+ ")"
755 // Detect common mistakes when certain non-wildcard meta characters are in readInputSectionsList()
778 // <patterns> ::= <section-list>
779 // | <sort> "(" <section-list> ")"
780 // | <sort> "(" <sort> "(" <section-list> ")" ")"
785 // <section-list> is parsed by readInputSectionsList().
789 auto *cmd = in readInputSectionRules() local
817 std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns)); in readInputSectionRules()
819 return cmd; in readInputSectionRules()
825 // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep in readInputSectionDescription()
832 InputSectionDescription *cmd = in readInputSectionDescription() local
835 script->keptSections.push_back(cmd); in readInputSectionDescription()
836 return cmd; in readInputSectionDescription()
861 return script->getDot(); in readAssert()
876 bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) { in readSectionDirective() argument
882 cmd->type = SHT_NOBITS; in readSectionDirective()
883 cmd->typeIsSet = true; in readSectionDirective()
890 cmd->type = it->second; in readSectionDirective()
896 cmd->type = readExpr()().getValue(); in readSectionDirective()
898 cmd->typeIsSet = true; in readSectionDirective()
901 cmd->nonAlloc = true; in readSectionDirective()
911 // An output section name can be followed by an address expression
916 // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
917 // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
918 void ScriptParser::readSectionAddressType(OutputSection *cmd) { in readSectionAddressType() argument
922 if (readSectionDirective(cmd, peek())) in readSectionAddressType()
924 cmd->addrExpr = readExpr(); in readSectionAddressType()
927 cmd->addrExpr = readExpr(); in readSectionAddressType()
933 if (!readSectionDirective(cmd, tok)) in readSectionAddressType()
940 uint64_t alignment = std::max((uint64_t)1, e().getValue()); in checkAlignment()
950 OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation()); in readOverlaySectionDescription()
951 osd->osec.inOverlay = true; in readOverlaySectionDescription()
958 osd->osec.commands.push_back( in readOverlaySectionDescription()
961 osd->osec.phdrs = readOutputSectionPhdrs(); in readOverlaySectionDescription()
966 OutputDesc *cmd = in readOutputSectionDescription() local
967 script->createOutputSection(unquote(outSec), getCurrentLocation()); in readOutputSectionDescription()
968 OutputSection *osec = &cmd->osec; in readOutputSectionDescription()
970 osec->relro = script->seenDataAlign && !script->seenRelroEnd; in readOutputSectionDescription()
972 size_t symbolsReferenced = script->referencedSymbols.size(); in readOutputSectionDescription()
980 osec->lmaExpr = readParenExpr(); in readOutputSectionDescription()
982 osec->alignExpr = checkAlignment(readParenExpr(), location); in readOutputSectionDescription()
984 osec->subalignExpr = checkAlignment(readParenExpr(), location); in readOutputSectionDescription()
988 osec->constraint = ConstraintKind::ReadOnly; in readOutputSectionDescription()
990 osec->constraint = ConstraintKind::ReadWrite; in readOutputSectionDescription()
998 osec->commands.push_back(assign); in readOutputSectionDescription()
1000 osec->commands.push_back(data); in readOutputSectionDescription()
1003 // by name. This is for very old file formats such as ECOFF/XCOFF. in readOutputSectionDescription()
1008 // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html in readOutputSectionDescription()
1011 osec->filler = readFill(); in readOutputSectionDescription()
1019 osec->commands.push_back(readInputSectionDescription(tok)); in readOutputSectionDescription()
1021 // We have a file name and no input sections description. It is not a in readOutputSectionDescription()
1028 isd->sectionPatterns.push_back({{}, StringMatcher("*")}); in readOutputSectionDescription()
1029 osec->commands.push_back(isd); in readOutputSectionDescription()
1034 osec->memoryRegionName = std::string(next()); in readOutputSectionDescription()
1038 osec->lmaRegionName = std::string(next()); in readOutputSectionDescription()
1041 if (osec->lmaExpr && !osec->lmaRegionName.empty()) in readOutputSectionDescription()
1044 osec->phdrs = readOutputSectionPhdrs(); in readOutputSectionDescription()
1049 osec->filler = readFill(); in readOutputSectionDescription()
1056 if (script->referencedSymbols.size() > symbolsReferenced) in readOutputSectionDescription()
1057 osec->expressionsUseSymbols = true; in readOutputSectionDescription()
1058 return cmd; in readOutputSectionDescription()
1061 // Reads a `=<fillexp>` expression and returns its value as a big-endian number.
1062 // https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html
1066 // size, while ld.gold always handles it as a 32-bit big-endian number.
1074 setError("filler expression result does not fit 32-bit: 0x" + in readFill()
1084 StringRef name = next(), eq = peek(); in readProvideHidden() local
1093 activeProvideSym = name; in readProvideHidden()
1094 SymbolAssignment *cmd = readSymbolAssignment(name); in readProvideHidden() local
1095 cmd->provide = provide; in readProvideHidden()
1096 cmd->hidden = hidden; in readProvideHidden()
1098 return cmd; in readProvideHidden()
1107 SymbolAssignment *cmd = nullptr; in readAssignment() local
1108 bool savedSeenRelroEnd = script->seenRelroEnd; in readAssignment()
1113 cmd = readSymbolAssignment(tok); in readAssignment()
1114 } else if ((op.size() == 2 && op[1] == '=' && strchr("*/+-&^|", op[0])) || in readAssignment()
1116 cmd = readSymbolAssignment(tok); in readAssignment()
1119 cmd = readProvideHidden(true, false); in readAssignment()
1122 cmd = readProvideHidden(false, true); in readAssignment()
1125 cmd = readProvideHidden(true, true); in readAssignment()
1128 if (cmd) { in readAssignment()
1129 cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && script->seenRelroEnd; in readAssignment()
1130 cmd->commandString = in readAssignment()
1135 return cmd; in readAssignment()
1138 SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) { in readSymbolAssignment() argument
1139 name = unquote(name); in readSymbolAssignment()
1141 assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" || in readSymbolAssignment()
1147 e = [=, c = op[0]]() -> ExprValue { in readSymbolAssignment()
1148 ExprValue lhs = script->getSymbolValue(name, loc); in readSymbolAssignment()
1159 case '-': in readSymbolAssignment()
1176 return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++, in readSymbolAssignment()
1180 // This is an operator-precedence parser to parse a linker
1183 // Our lexer is context-aware. Set the in-expression bit so that in readExpr()
1193 if (op == "-") in combine()
1199 return [=]() -> uint64_t { in combine()
1208 return [=]() -> uint64_t { in combine()
1244 // This is a part of the operator-precedence parser. This function
1275 return [=]() -> uint64_t { in getPageSize()
1277 return config->commonPageSize; in getPageSize()
1288 return [] { return config->maxPageSize; }; in readConstant()
1332 .Default(-1); in readByteCommand()
1333 if (size == -1) in readByteCommand()
1371 // <flag> ::= Recognized Flag Name, or Integer value of flag.
1412 if (osec.location.empty() && script->errorOnMissingSection) in checkIfExists()
1413 script->recordError(location + ": undefined section " + osec.name); in checkIfExists()
1435 if (consume("-")) { in readPrimary()
1437 return [=] { return -e().getValue(); }; in readPrimary()
1443 // Built-in functions are parsed here. in readPrimary()
1444 // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. in readPrimary()
1454 StringRef name = unquote(readParenLiteral()); in readPrimary() local
1455 OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; in readPrimary()
1456 osec->usedInExpression = true; in readPrimary()
1457 return [=]() -> ExprValue { in readPrimary()
1467 return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); }; in readPrimary()
1479 StringRef name = unquote(readParenLiteral()); in readPrimary() local
1480 OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; in readPrimary()
1483 return osec->addralign; in readPrimary()
1496 script->seenDataAlign = true; in readPrimary()
1498 uint64_t align = std::max(uint64_t(1), e().getValue()); in readPrimary()
1499 return (script->getDot() + align - 1) & -align; in readPrimary()
1506 return [] { return script->getDot(); }; in readPrimary()
1517 script->seenRelroEnd = true; in readPrimary()
1518 return [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); }; in readPrimary()
1521 StringRef name = unquote(readParenLiteral()); in readPrimary() local
1526 Symbol *s = symtab.find(name); in readPrimary()
1527 return s && s->isDefined() && ctx.scriptSymOrder.lookup(s) < order ? 1 in readPrimary()
1532 StringRef name = readParenLiteral(); in readPrimary() local
1533 if (script->memoryRegions.count(name) == 0) { in readPrimary()
1534 setError("memory region not defined: " + name); in readPrimary()
1537 return script->memoryRegions[name]->length; in readPrimary()
1540 StringRef name = unquote(readParenLiteral()); in readPrimary() local
1541 OutputSection *osec = &script->getOrCreateOutputSection(name)->osec; in readPrimary()
1542 osec->usedInExpression = true; in readPrimary()
1545 return osec->getLMA(); in readPrimary()
1554 return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1))); in readPrimary()
1557 if (tok == "MAX" || tok == "MIN") { in readPrimary()
1565 return [=] { return std::max(a().getValue(), b().getValue()); }; in readPrimary()
1568 StringRef name = readParenLiteral(); in readPrimary() local
1569 if (script->memoryRegions.count(name) == 0) { in readPrimary()
1570 setError("memory region not defined: " + name); in readPrimary()
1573 return script->memoryRegions[name]->origin; in readPrimary()
1584 StringRef name = unquote(readParenLiteral()); in readPrimary() local
1585 OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec; in readPrimary() local
1589 return [=] { return cmd->size; }; in readPrimary()
1596 return [=] { return script->getSymbolValue(tok, location); }; in readPrimary()
1602 // Tok is a symbol name. in readPrimary()
1608 script->provideMap[*activeProvideSym].push_back(tok); in readPrimary()
1610 script->referencedSymbols.push_back(tok); in readPrimary()
1611 return [=] { return script->getSymbolValue(tok, location); }; in readPrimary()
1637 // Read a program header type name. The next token must be a
1638 // name of a program header type or a constant (e.g. "0x3").
1661 .Default(-1); in readPhdrType()
1663 if (ret == (unsigned)-1) { in readPhdrType()
1676 config->versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat); in readAnonymousDeclaration()
1678 config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(pat); in readAnonymousDeclaration()
1683 // Reads a non-anonymous version definition,
1693 ver.name = verStr; in readVersionDeclaration()
1696 ver.id = config->versionDefinitions.size(); in readVersionDeclaration()
1697 config->versionDefinitions.push_back(ver); in readVersionDeclaration()
1733 v->insert(v->end(), ext.begin(), ext.end()); in readSymbols()
1736 v->push_back({unquote(tok), false, hasWildcard(tok)}); in readSymbols()
1782 // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
1809 if (!script->memoryRegions.insert({tok, mr}).second) in readMemory()
1816 // are only used when an explicit memory region name is not used.
1864 void elf::readDefsym(StringRef name, MemoryBufferRef mb) { in readDefsym() argument
1865 llvm::TimeTraceScope timeScope("Read defsym input", name); in readDefsym()
1866 ScriptParser(mb).readDefsym(name); in readDefsym()