@@ -54,6 +54,7 @@ template <class ELFT> class Writer {
54
54
void sortSections ();
55
55
void finalizeSections ();
56
56
void addPredefinedSections ();
57
+ void addPredefinedSymbols ();
57
58
58
59
std::vector<PhdrEntry *> createPhdrs ();
59
60
void removeEmptyPTLoad ();
@@ -200,6 +201,12 @@ template <class ELFT> void Writer<ELFT>::run() {
200
201
parallelForEach (OutputSections,
201
202
[](OutputSection *Sec) { Sec->maybeCompress <ELFT>(); });
202
203
204
+ // Generate assignments for predefined symbols (e.g. _end or _etext)
205
+ // before assigning addresses. These symbols may be referred to from
206
+ // the linker script and we need to ensure they have the correct value
207
+ // prior evaluating any expressions using these symbols.
208
+ addPredefinedSymbols ();
209
+
203
210
Script->assignAddresses ();
204
211
Script->allocateHeaders (Phdrs);
205
212
@@ -920,6 +927,80 @@ template <class ELFT> void Writer<ELFT>::createSections() {
920
927
sortCtorsDtors (findSection (" .dtors" ));
921
928
}
922
929
930
+ // This function generates assignments for predefined symbols (e.g. _end or
931
+ // _etext) and inserts them into the commands sequence to be processed at the
932
+ // appropriate time. This ensures that the value is going to be correct by the
933
+ // time any references to these symbols are processed and is equivalent to
934
+ // defining these symbols explicitly in the linker script.
935
+ template <class ELFT > void Writer<ELFT>::addPredefinedSymbols() {
936
+ PhdrEntry *Last = nullptr ;
937
+ PhdrEntry *LastRO = nullptr ;
938
+ PhdrEntry *LastRW = nullptr ;
939
+ for (PhdrEntry *P : Phdrs) {
940
+ if (P->p_type != PT_LOAD)
941
+ continue ;
942
+ Last = P;
943
+ if (P->p_flags & PF_W)
944
+ LastRW = P;
945
+ else
946
+ LastRO = P;
947
+ }
948
+
949
+ auto Make = [](DefinedRegular *S) {
950
+ auto *Cmd = make<SymbolAssignment>(
951
+ S->getName (), [=] { return Script->getSymbolValue (" " , " ." ); }, " " );
952
+ Cmd->Sym = S;
953
+ return Cmd;
954
+ };
955
+
956
+ auto IsSection = [](OutputSection *Sec) {
957
+ return [=](BaseCommand *Base) { return Base == Sec; };
958
+ };
959
+
960
+ auto IsNoBits = [](BaseCommand *Base) {
961
+ if (auto *Sec = dyn_cast<OutputSection>(Base))
962
+ return Sec->Type == SHT_NOBITS;
963
+ return false ;
964
+ };
965
+
966
+ if (Last) {
967
+ // _end is the first location after the uninitialized data region.
968
+ auto E = Script->Opt .Commands .end ();
969
+ auto I = Script->Opt .Commands .begin ();
970
+ I = std::find_if (I, E, IsSection (Last->Last ));
971
+ if (I != E) {
972
+ if (ElfSym::End1)
973
+ Script->Opt .Commands .insert (++I, Make (ElfSym::End1));
974
+ if (ElfSym::End2)
975
+ Script->Opt .Commands .insert (++I, Make (ElfSym::End2));
976
+ }
977
+ }
978
+ if (LastRO) {
979
+ // _etext is the first location after the last read-only loadable segment.
980
+ auto E = Script->Opt .Commands .end ();
981
+ auto I = Script->Opt .Commands .begin ();
982
+ I = std::find_if (I, E, IsSection (LastRO->Last ));
983
+ if (I != E) {
984
+ if (ElfSym::Etext1)
985
+ Script->Opt .Commands .insert (++I, Make (ElfSym::Etext1));
986
+ if (ElfSym::Etext2)
987
+ Script->Opt .Commands .insert (++I, Make (ElfSym::Etext2));
988
+ }
989
+ }
990
+ if (LastRW) {
991
+ // _edata points to the end of the last non SHT_NOBITS section.
992
+ auto E = Script->Opt .Commands .end ();
993
+ auto I = Script->Opt .Commands .begin ();
994
+ I = std::find_if (std::find_if (I, E, IsSection (LastRW->First )), E, IsNoBits);
995
+ if (I != E) {
996
+ if (ElfSym::Edata2)
997
+ I = Script->Opt .Commands .insert (I, Make (ElfSym::Edata2));
998
+ if (ElfSym::Edata1)
999
+ I = Script->Opt .Commands .insert (I, Make (ElfSym::Edata1));
1000
+ }
1001
+ }
1002
+ }
1003
+
923
1004
// We want to find how similar two ranks are.
924
1005
// The more branches in getSectionRank that match, the more similar they are.
925
1006
// Since each branch corresponds to a bit flag, we can just use
@@ -1718,42 +1799,6 @@ static uint16_t getELFType() {
1718
1799
// to each section. This function fixes some predefined
1719
1800
// symbol values that depend on section address and size.
1720
1801
template <class ELFT > void Writer<ELFT>::fixPredefinedSymbols() {
1721
- // _etext is the first location after the last read-only loadable segment.
1722
- // _edata is the first location after the last read-write loadable segment.
1723
- // _end is the first location after the uninitialized data region.
1724
- PhdrEntry *Last = nullptr ;
1725
- PhdrEntry *LastRO = nullptr ;
1726
- PhdrEntry *LastRW = nullptr ;
1727
- for (PhdrEntry *P : Phdrs) {
1728
- if (P->p_type != PT_LOAD)
1729
- continue ;
1730
- Last = P;
1731
- if (P->p_flags & PF_W)
1732
- LastRW = P;
1733
- else
1734
- LastRO = P;
1735
- }
1736
-
1737
- auto Set = [](DefinedRegular *S, OutputSection *Cmd, uint64_t Value) {
1738
- if (S) {
1739
- S->Section = Cmd;
1740
- S->Value = Value;
1741
- }
1742
- };
1743
-
1744
- if (Last) {
1745
- Set (ElfSym::End1, Last->First , Last->p_memsz );
1746
- Set (ElfSym::End2, Last->First , Last->p_memsz );
1747
- }
1748
- if (LastRO) {
1749
- Set (ElfSym::Etext1, LastRO->First , LastRO->p_filesz );
1750
- Set (ElfSym::Etext2, LastRO->First , LastRO->p_filesz );
1751
- }
1752
- if (LastRW) {
1753
- Set (ElfSym::Edata1, LastRW->First , LastRW->p_filesz );
1754
- Set (ElfSym::Edata2, LastRW->First , LastRW->p_filesz );
1755
- }
1756
-
1757
1802
if (ElfSym::Bss)
1758
1803
ElfSym::Bss->Section = findSection (" .bss" );
1759
1804
0 commit comments