2222#include " Writer.h"
2323#include " lld/Common/CommonLinkerContext.h"
2424#include " lld/Common/Strings.h"
25+ #include " llvm/ADT/ArrayRef.h"
26+ #include " llvm/ADT/DenseMap.h"
2527#include " llvm/ADT/STLExtras.h"
28+ #include " llvm/ADT/SmallVector.h"
2629#include " llvm/ADT/StringRef.h"
2730#include " llvm/BinaryFormat/ELF.h"
2831#include " llvm/Support/Casting.h"
@@ -390,6 +393,10 @@ static inline StringRef getFilename(const InputFile *file) {
390393 return file ? file->getNameForScript () : StringRef ();
391394}
392395
396+ static inline StringRef getFilenameAlreadyCached (const InputFile *file) {
397+ return file ? file->getNameForScriptAlreadyCached () : StringRef ();
398+ }
399+
393400bool InputSectionDescription::matchesFile (const InputFile *file) const {
394401 if (filePat.isTrivialMatchAll ())
395402 return true ;
@@ -400,6 +407,14 @@ bool InputSectionDescription::matchesFile(const InputFile *file) const {
400407 return matchesFileCache->second ;
401408}
402409
410+ bool InputSectionDescription::matchesFileCacheless (
411+ const InputFile *file) const {
412+ if (filePat.isTrivialMatchAll ())
413+ return true ;
414+
415+ return filePat.match (getFilenameAlreadyCached (file));
416+ }
417+
403418bool SectionPattern::excludesFile (const InputFile *file) const {
404419 if (excludedFilePat.empty ())
405420 return false ;
@@ -410,6 +425,13 @@ bool SectionPattern::excludesFile(const InputFile *file) const {
410425 return excludesFileCache->second ;
411426}
412427
428+ bool SectionPattern::excludesFileCacheless (const InputFile *file) const {
429+ if (excludedFilePat.empty ())
430+ return false ;
431+
432+ return excludedFilePat.match (getFilenameAlreadyCached (file));
433+ }
434+
413435bool LinkerScript::shouldKeep (InputSectionBase *s) {
414436 for (InputSectionDescription *id : keptSections)
415437 if (id->matchesFile (s->file ))
@@ -600,11 +622,223 @@ LinkerScript::createInputSectionList(OutputSection &outCmd) {
600622 return ret;
601623}
602624
625+ // Helper struct to relate input sections with descriptions and patterns
626+ struct IsecBaseIsecDescPattern {
627+ size_t isecIndex = 0 ;
628+ // Because of constraints that can be enforced on sections
629+ // (ONLY_IF_R[OW]) we need to try to match to more than one
630+ // output section, in case the constraints are not fully satisfied.
631+ SmallVector<InputSectionDescription *, 1 > isecDescs;
632+ SmallVector<size_t , 1 > patternIndexes;
633+
634+ IsecBaseIsecDescPattern (size_t index) : isecIndex(index) {}
635+ };
636+
637+ // Helper function
638+ static inline void assignPatternsToInputSections (
639+ IsecBaseIsecDescPattern &isecBaseIsecDescPattern,
640+ ArrayRef<OutputSection *> osecs,
641+ DenseMap<OutputSection *, SmallVector<InputSectionDescription *, 0 >>
642+ &outSecToISecDescs) {
643+ InputSectionBase *isec = ctx.inputSections [isecBaseIsecDescPattern.isecIndex ];
644+
645+ if (!isec->isLive () || isec->parent )
646+ return ;
647+
648+ // For --emit-relocs we have to ignore entries like
649+ // .rela.dyn : { *(.rela.data) }
650+ // which are common because they are in the default bfd script.
651+ // We do not ignore SHT_REL[A] linker-synthesized sections here because
652+ // want to support scripts that do custom layout for them.
653+ if (isa<InputSection>(isec) &&
654+ cast<InputSection>(isec)->getRelocatedSection ())
655+ return ;
656+
657+ for (OutputSection *osec : osecs) {
658+ bool assignedToConstrainedSec = false ;
659+ if (osec->constraintUnsatisfied &&
660+ osec->constraint == ConstraintKind::ReadOnly)
661+ continue ;
662+ for (InputSectionDescription *isd : outSecToISecDescs[osec]) {
663+ if (!isd->matchesFileCacheless (isec->file ) ||
664+ (isec->flags & isd->withFlags ) != isd->withFlags ||
665+ (isec->flags & isd->withoutFlags ) != 0 )
666+ continue ;
667+ for (auto [i, pat] : llvm::enumerate (isd->sectionPatterns )) {
668+ if (!pat.sectionPat .match (isec->name ) ||
669+ pat.excludesFileCacheless (isec->file ))
670+ continue ;
671+
672+ isecBaseIsecDescPattern.isecDescs .push_back (isd);
673+ isecBaseIsecDescPattern.patternIndexes .push_back (i);
674+ if (osec->constraint != ConstraintKind::NoConstraint) {
675+ // This is for ONLY_IF_RO and ONLY_IF_RW. An output section directive
676+ // ".foo : ONLY_IF_R[OW] { ... }" is handled only if all member input
677+ // sections satisfy a given constraint. If not, a directive is handled
678+ // as if it wasn't present from the beginning.
679+ bool isRW = isec->flags & SHF_WRITE;
680+ if (isRW && osec->constraint == ConstraintKind::ReadOnly)
681+ osec->constraintUnsatisfied = true ;
682+ else if (isRW && osec->constraint == ConstraintKind::ReadWrite)
683+ osec->constraintUnsatisfied = false ;
684+
685+ assignedToConstrainedSec = true ;
686+ break ;
687+ }
688+ return ;
689+ }
690+
691+ if (assignedToConstrainedSec)
692+ break ;
693+ }
694+ }
695+ }
696+
697+ // Helper function
698+ static inline DenseMap<OutputSection *, SmallVector<InputSectionBase *, 0 >>
699+ assignAndSortInputToOutputSections (
700+ ArrayRef<OutputSection *> osecs,
701+ DenseMap<OutputSection *, SmallVector<InputSectionDescription *, 0 >>
702+ &outSecToISecDescs) {
703+
704+ DenseMap<OutputSection *, SmallVector<InputSectionBase *, 0 >> outSecToISecs;
705+ SmallVector<size_t , 0 > sectionIndexes;
706+
707+ auto sortByPositionThenCommandLine =
708+ [&](size_t begin, size_t end, MutableArrayRef<InputSectionBase *> secs) {
709+ llvm::sort (
710+ MutableArrayRef<size_t >(sectionIndexes).slice (begin, end - begin));
711+ for (size_t i = begin; i != end; ++i)
712+ secs[i] = ctx.inputSections [sectionIndexes[i]];
713+ sortInputSections (secs.slice (begin, end - begin), config->sortSection ,
714+ SortSectionPolicy::None);
715+ };
716+
717+ for (OutputSection *osec : osecs) {
718+ outSecToISecs[osec] = SmallVector<InputSectionBase *, 0 >();
719+ // If constraints are unsatisfied ignore this output section
720+ if (osec->constraintUnsatisfied )
721+ continue ;
722+ for (InputSectionDescription *isd : outSecToISecDescs[osec]) {
723+ size_t sizeAfterPrevSort = 0 ;
724+ sectionIndexes.clear ();
725+ for (SectionPattern &pat : isd->sectionPatterns ) {
726+ if (pat.matchedSections .size () == 0 )
727+ continue ;
728+
729+ size_t sizeBeforeCurrPat = isd->sectionBases .size ();
730+
731+ for (size_t index : pat.matchedSections ) {
732+ // There might be input sections repeated more than one time in
733+ // several output sections, because of constraints, here we check
734+ // if they are already mapped.
735+ if (!ctx.inputSections [index]->parent ) {
736+ isd->sectionBases .push_back (ctx.inputSections [index]);
737+ ctx.inputSections [index]->parent = osec;
738+ sectionIndexes.push_back (index);
739+ }
740+ }
741+ if (pat.sortOuter != SortSectionPolicy::Default) {
742+ // Matched sections are ordered by radix sort with the keys being
743+ // (SORT*,
744+ // --sort-section, input order), where SORT* (if present) is most
745+ // significant.
746+ //
747+ // Matched sections between the previous SORT* and this SORT* are
748+ // sorted by
749+ // (--sort-alignment, input order).
750+
751+ sortByPositionThenCommandLine (
752+ sizeAfterPrevSort, sizeBeforeCurrPat,
753+ MutableArrayRef<InputSectionBase *>(isd->sectionBases ));
754+
755+ // Matched sections by this SORT* pattern are sorted using all 3 keys.
756+ // ret[sizeBeforeCurrPat,ret.size()) are already in the input order,
757+ // so we just sort by sortOuter and sortInner.
758+ sortInputSections (
759+ MutableArrayRef<InputSectionBase *>(isd->sectionBases )
760+ .slice (sizeBeforeCurrPat),
761+ pat.sortOuter , pat.sortInner );
762+
763+ sizeAfterPrevSort = isd->sectionBases .size ();
764+ }
765+ }
766+ // Matched sections after the last SORT* are sorted by (--sort-alignment,
767+ // input order).
768+ sortByPositionThenCommandLine (
769+ sizeAfterPrevSort, isd->sectionBases .size (),
770+ MutableArrayRef<InputSectionBase *>(isd->sectionBases ));
771+ outSecToISecs[osec].append (isd->sectionBases );
772+ }
773+ }
774+
775+ return outSecToISecs;
776+ }
777+ DenseMap<OutputSection *, SmallVector<InputSectionBase *, 0 >>
778+ LinkerScript::mapInputToOutputSections (ArrayRef<OutputSection *> osecs) {
779+ // Input section descriptions per output sections in the linker script
780+ DenseMap<OutputSection *, SmallVector<InputSectionDescription *, 0 >>
781+ outSecToISecDescs;
782+ DenseMap<OutputSection *, SmallVector<InputSectionDescription *, 0 >>
783+ outSecToUsedISecDescs;
784+ // Input sections matched to section patterns and their descriptions
785+ SmallVector<IsecBaseIsecDescPattern, 0 > isecsToPatterns;
786+
787+ isecsToPatterns.reserve (ctx.inputSections .size ());
788+ for (size_t i = 0 ; i < ctx.inputSections .size (); ++i) {
789+ isecsToPatterns.push_back ({i});
790+ // Initialize name for script for archives to avoid problems because of
791+ // multithreading later
792+ InputFile *file = ctx.inputSections [i]->file ;
793+ if (file && !file->archiveName .empty ())
794+ file->initializeCachedArchiveName ();
795+ }
796+
797+ // Initialize the osec if ReadWrite constrained and
798+ // map out secs to input sec description
799+ for (OutputSection *osec : osecs) {
800+ if (osec->constraint == ConstraintKind::ReadWrite)
801+ osec->constraintUnsatisfied = true ;
802+
803+ SmallVector<InputSectionDescription *, 0 > osecInputSecCmds;
804+ for (SectionCommand *cmd : osec->commands ) {
805+ if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
806+ osecInputSecCmds.push_back (isd);
807+ }
808+
809+ outSecToISecDescs.insert ({osec, osecInputSecCmds});
810+ }
811+
812+ parallelForEach (isecsToPatterns,
813+ [&](IsecBaseIsecDescPattern &isecBaseIsecDescPattern) {
814+ assignPatternsToInputSections (isecBaseIsecDescPattern,
815+ osecs, outSecToISecDescs);
816+ });
817+
818+ // Add input sections to their matching patterns
819+ for (IsecBaseIsecDescPattern &isecBaseIsecDescPattern : isecsToPatterns) {
820+ for (auto [i, isecDesc] :
821+ llvm::enumerate (isecBaseIsecDescPattern.isecDescs )) {
822+ isecDesc->sectionPatterns [isecBaseIsecDescPattern.patternIndexes [i]]
823+ .matchedSections .push_back (isecBaseIsecDescPattern.isecIndex );
824+ }
825+ }
826+
827+ return assignAndSortInputToOutputSections (osecs, outSecToISecDescs);
828+ }
829+
603830// Create output sections described by SECTIONS commands.
604831void LinkerScript::processSectionCommands () {
605- auto process = [this ](OutputSection *osec) {
606- SmallVector<InputSectionBase *, 0 > v = createInputSectionList (*osec);
607832
833+ auto process = [this ](OutputSection *osec,
834+ SmallVector<InputSectionBase *, 0 > &v) {
835+ // If constraints are unsatisfied, skip this section and make it as if it
836+ // never existed, we do this by clearing all of its commands (this is the
837+ // easiest way)
838+ if (osec->constraintUnsatisfied ) {
839+ osec->commands .clear ();
840+ return false ;
841+ }
608842 // The output section name `/DISCARD/' is special.
609843 // Any input section assigned to it is discarded.
610844 if (osec->name == " /DISCARD/" ) {
@@ -615,20 +849,6 @@ void LinkerScript::processSectionCommands() {
615849 return false ;
616850 }
617851
618- // This is for ONLY_IF_RO and ONLY_IF_RW. An output section directive
619- // ".foo : ONLY_IF_R[OW] { ... }" is handled only if all member input
620- // sections satisfy a given constraint. If not, a directive is handled
621- // as if it wasn't present from the beginning.
622- //
623- // Because we'll iterate over SectionCommands many more times, the easy
624- // way to "make it as if it wasn't present" is to make it empty.
625- if (!matchConstraints (v, osec->constraint )) {
626- for (InputSectionBase *s : v)
627- s->parent = nullptr ;
628- osec->commands .clear ();
629- return false ;
630- }
631-
632852 // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
633853 // is given, input sections are aligned to that value, whether the
634854 // given value is larger or smaller than the original section alignment.
@@ -649,23 +869,41 @@ void LinkerScript::processSectionCommands() {
649869 // or orphans.
650870 DenseMap<CachedHashStringRef, OutputDesc *> map;
651871 size_t i = 0 ;
872+
873+ SmallVector<OutputSection *, 0 > overwriteSectionsVec;
874+ overwriteSectionsVec.reserve (overwriteSections.size ());
875+ for (OutputDesc *osd : overwriteSections)
876+ overwriteSectionsVec.push_back (&osd->osec );
877+
878+ DenseMap<OutputSection *, SmallVector<InputSectionBase *, 0 >>
879+ outSecToISecsOverwrite = mapInputToOutputSections (overwriteSectionsVec);
652880 for (OutputDesc *osd : overwriteSections) {
653881 OutputSection *osec = &osd->osec ;
654- if (process (osec) &&
882+ if (process (osec, outSecToISecsOverwrite[osec] ) &&
655883 !map.try_emplace (CachedHashStringRef (osec->name ), osd).second )
656884 warn (" OVERWRITE_SECTIONS specifies duplicate " + osec->name );
657885 }
658- for (SectionCommand *&base : sectionCommands)
886+
887+ SmallVector<OutputSection *, 0 > outputSecVec;
888+ for (SectionCommand *base : sectionCommands) {
889+ if (auto *osd = dyn_cast<OutputDesc>(base))
890+ outputSecVec.push_back (&osd->osec );
891+ }
892+
893+ DenseMap<OutputSection *, SmallVector<InputSectionBase *, 0 >> outSecToISecs =
894+ mapInputToOutputSections (outputSecVec);
895+ for (SectionCommand *&base : sectionCommands) {
659896 if (auto *osd = dyn_cast<OutputDesc>(base)) {
660897 OutputSection *osec = &osd->osec ;
661898 if (OutputDesc *overwrite = map.lookup (CachedHashStringRef (osec->name ))) {
662899 log (overwrite->osec .location + " overwrites " + osec->name );
663900 overwrite->osec .sectionIndex = i++;
664901 base = overwrite;
665- } else if (process (osec)) {
902+ } else if (process (osec, outSecToISecs[osec] )) {
666903 osec->sectionIndex = i++;
667904 }
668905 }
906+ }
669907
670908 // If an OVERWRITE_SECTIONS specified output section is not in
671909 // sectionCommands, append it to the end. The section will be inserted by
0 commit comments