@@ -1508,6 +1508,33 @@ func (ctxt *Link) dodata() {
1508
1508
}
1509
1509
sect .Length = uint64 (datsize ) - sect .Vaddr
1510
1510
1511
+ /* read-only ELF, Mach-O sections */
1512
+ for _ , s := range data [obj .SELFROSECT ] {
1513
+ sect = addsection (segro , s .Name , 04 )
1514
+ sect .Align = symalign (s )
1515
+ datsize = Rnd (datsize , int64 (sect .Align ))
1516
+ sect .Vaddr = uint64 (datsize )
1517
+ s .Sect = sect
1518
+ s .Type = obj .SRODATA
1519
+ s .Value = int64 (uint64 (datsize ) - sect .Vaddr )
1520
+ datsize += s .Size
1521
+ sect .Length = uint64 (datsize ) - sect .Vaddr
1522
+ }
1523
+ checkdatsize (ctxt , datsize , obj .SELFROSECT )
1524
+
1525
+ for _ , s := range data [obj .SMACHOPLT ] {
1526
+ sect = addsection (segro , s .Name , 04 )
1527
+ sect .Align = symalign (s )
1528
+ datsize = Rnd (datsize , int64 (sect .Align ))
1529
+ sect .Vaddr = uint64 (datsize )
1530
+ s .Sect = sect
1531
+ s .Type = obj .SRODATA
1532
+ s .Value = int64 (uint64 (datsize ) - sect .Vaddr )
1533
+ datsize += s .Size
1534
+ sect .Length = uint64 (datsize ) - sect .Vaddr
1535
+ }
1536
+ checkdatsize (ctxt , datsize , obj .SMACHOPLT )
1537
+
1511
1538
// There is some data that are conceptually read-only but are written to by
1512
1539
// relocations. On GNU systems, we can arrange for the dynamic linker to
1513
1540
// mprotect sections after relocations are applied by giving them write
@@ -1518,14 +1545,26 @@ func (ctxt *Link) dodata() {
1518
1545
// situation.
1519
1546
// TODO(mwhudson): It would make sense to do this more widely, but it makes
1520
1547
// the system linker segfault on darwin.
1521
- relroPerms := 04
1522
- relroPrefix := ""
1548
+ addrelrosection := func (suffix string ) * Section {
1549
+ return addsection (segro , suffix , 04 )
1550
+ }
1523
1551
1524
1552
if UseRelro () {
1525
- relroPerms = 06
1526
- relroPrefix = ".data.rel.ro"
1553
+ addrelrosection = func (suffix string ) * Section {
1554
+ seg := & Segrelrodata
1555
+ if Linkmode == LinkExternal {
1556
+ // Using a separate segment with an external
1557
+ // linker results in some programs moving
1558
+ // their data sections unexpectedly, which
1559
+ // corrupts the moduledata. So we use the
1560
+ // rodata segment and let the external linker
1561
+ // sort out a rel.ro segment.
1562
+ seg = & Segrodata
1563
+ }
1564
+ return addsection (seg , ".data.rel.ro" + suffix , 06 )
1565
+ }
1527
1566
/* data only written by relocations */
1528
- sect = addsection ( segro , ".data.rel.ro" , 06 )
1567
+ sect = addrelrosection ( "" )
1529
1568
1530
1569
sect .Vaddr = 0
1531
1570
Linklookup (ctxt , "runtime.types" , 0 ).Sect = sect
@@ -1554,11 +1593,10 @@ func (ctxt *Link) dodata() {
1554
1593
}
1555
1594
1556
1595
sect .Length = uint64 (datsize ) - sect .Vaddr
1557
-
1558
1596
}
1559
1597
1560
1598
/* typelink */
1561
- sect = addsection ( segro , relroPrefix + ".typelink" , relroPerms )
1599
+ sect = addrelrosection ( ".typelink" )
1562
1600
sect .Align = dataMaxAlign [obj .STYPELINK ]
1563
1601
datsize = Rnd (datsize , int64 (sect .Align ))
1564
1602
sect .Vaddr = uint64 (datsize )
@@ -1575,7 +1613,7 @@ func (ctxt *Link) dodata() {
1575
1613
sect .Length = uint64 (datsize ) - sect .Vaddr
1576
1614
1577
1615
/* itablink */
1578
- sect = addsection ( segro , relroPrefix + ".itablink" , relroPerms )
1616
+ sect = addrelrosection ( ".itablink" )
1579
1617
sect .Align = dataMaxAlign [obj .SITABLINK ]
1580
1618
datsize = Rnd (datsize , int64 (sect .Align ))
1581
1619
sect .Vaddr = uint64 (datsize )
@@ -1592,7 +1630,7 @@ func (ctxt *Link) dodata() {
1592
1630
sect .Length = uint64 (datsize ) - sect .Vaddr
1593
1631
1594
1632
/* gosymtab */
1595
- sect = addsection ( segro , relroPrefix + ".gosymtab" , relroPerms )
1633
+ sect = addrelrosection ( ".gosymtab" )
1596
1634
sect .Align = dataMaxAlign [obj .SSYMTAB ]
1597
1635
datsize = Rnd (datsize , int64 (sect .Align ))
1598
1636
sect .Vaddr = uint64 (datsize )
@@ -1609,7 +1647,7 @@ func (ctxt *Link) dodata() {
1609
1647
sect .Length = uint64 (datsize ) - sect .Vaddr
1610
1648
1611
1649
/* gopclntab */
1612
- sect = addsection ( segro , relroPrefix + ".gopclntab" , relroPerms )
1650
+ sect = addrelrosection ( ".gopclntab" )
1613
1651
sect .Align = dataMaxAlign [obj .SPCLNTAB ]
1614
1652
datsize = Rnd (datsize , int64 (sect .Align ))
1615
1653
sect .Vaddr = uint64 (datsize )
@@ -1625,33 +1663,6 @@ func (ctxt *Link) dodata() {
1625
1663
checkdatsize (ctxt , datsize , obj .SRODATA )
1626
1664
sect .Length = uint64 (datsize ) - sect .Vaddr
1627
1665
1628
- /* read-only ELF, Mach-O sections */
1629
- for _ , s := range data [obj .SELFROSECT ] {
1630
- sect = addsection (segro , s .Name , 04 )
1631
- sect .Align = symalign (s )
1632
- datsize = Rnd (datsize , int64 (sect .Align ))
1633
- sect .Vaddr = uint64 (datsize )
1634
- s .Sect = sect
1635
- s .Type = obj .SRODATA
1636
- s .Value = int64 (uint64 (datsize ) - sect .Vaddr )
1637
- datsize += s .Size
1638
- sect .Length = uint64 (datsize ) - sect .Vaddr
1639
- }
1640
- checkdatsize (ctxt , datsize , obj .SELFROSECT )
1641
-
1642
- for _ , s := range data [obj .SMACHOPLT ] {
1643
- sect = addsection (segro , s .Name , 04 )
1644
- sect .Align = symalign (s )
1645
- datsize = Rnd (datsize , int64 (sect .Align ))
1646
- sect .Vaddr = uint64 (datsize )
1647
- s .Sect = sect
1648
- s .Type = obj .SRODATA
1649
- s .Value = int64 (uint64 (datsize ) - sect .Vaddr )
1650
- datsize += s .Size
1651
- sect .Length = uint64 (datsize ) - sect .Vaddr
1652
- }
1653
- checkdatsize (ctxt , datsize , obj .SMACHOPLT )
1654
-
1655
1666
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
1656
1667
if datsize != int64 (uint32 (datsize )) {
1657
1668
ctxt .Diag ("read-only data segment too large" )
@@ -1711,6 +1722,10 @@ func (ctxt *Link) dodata() {
1711
1722
sect .Extnum = int16 (n )
1712
1723
n ++
1713
1724
}
1725
+ for sect := Segrelrodata .Sect ; sect != nil ; sect = sect .Next {
1726
+ sect .Extnum = int16 (n )
1727
+ n ++
1728
+ }
1714
1729
for sect := Segdata .Sect ; sect != nil ; sect = sect .Next {
1715
1730
sect .Extnum = int16 (n )
1716
1731
n ++
@@ -1897,6 +1912,17 @@ func (ctxt *Link) address() {
1897
1912
if Segrodata .Sect != nil {
1898
1913
// align to page boundary so as not to mix
1899
1914
// rodata and executable text.
1915
+ //
1916
+ // Note: gold or GNU ld will reduce the size of the executable
1917
+ // file by arranging for the relro segment to end at a page
1918
+ // boundary, and overlap the end of the text segment with the
1919
+ // start of the relro segment in the file. The PT_LOAD segments
1920
+ // will be such that the last page of the text segment will be
1921
+ // mapped twice, once r-x and once starting out rw- and, after
1922
+ // relocation processing, changed to r--.
1923
+ //
1924
+ // Ideally the last page of the text segment would not be
1925
+ // writable even for this short period.
1900
1926
va = uint64 (Rnd (int64 (va ), int64 (* FlagRound )))
1901
1927
1902
1928
Segrodata .Rwx = 04
@@ -1912,6 +1938,24 @@ func (ctxt *Link) address() {
1912
1938
Segrodata .Length = va - Segrodata .Vaddr
1913
1939
Segrodata .Filelen = Segrodata .Length
1914
1940
}
1941
+ if Segrelrodata .Sect != nil {
1942
+ // align to page boundary so as not to mix
1943
+ // rodata, rel-ro data, and executable text.
1944
+ va = uint64 (Rnd (int64 (va ), int64 (* FlagRound )))
1945
+
1946
+ Segrelrodata .Rwx = 06
1947
+ Segrelrodata .Vaddr = va
1948
+ Segrelrodata .Fileoff = va - Segrodata .Vaddr + Segrodata .Fileoff
1949
+ Segrelrodata .Filelen = 0
1950
+ for s := Segrelrodata .Sect ; s != nil ; s = s .Next {
1951
+ va = uint64 (Rnd (int64 (va ), int64 (s .Align )))
1952
+ s .Vaddr = va
1953
+ va += s .Length
1954
+ }
1955
+
1956
+ Segrelrodata .Length = va - Segrelrodata .Vaddr
1957
+ Segrelrodata .Filelen = Segrelrodata .Length
1958
+ }
1915
1959
1916
1960
va = uint64 (Rnd (int64 (va ), int64 (* FlagRound )))
1917
1961
Segdata .Rwx = 06
@@ -1979,24 +2023,15 @@ func (ctxt *Link) address() {
1979
2023
1980
2024
Segdwarf .Filelen = va - Segdwarf .Vaddr
1981
2025
1982
- text := Segtext .Sect
1983
- var rodata * Section
1984
- if Segrodata .Sect != nil {
1985
- rodata = Segrodata .Sect
1986
- } else {
1987
- rodata = text .Next
1988
- }
1989
- var relrodata * Section
1990
- typelink := rodata .Next
1991
- if UseRelro () {
1992
- // There is another section (.data.rel.ro) when building a shared
1993
- // object on elf systems.
1994
- relrodata = typelink
1995
- typelink = typelink .Next
1996
- }
1997
- itablink := typelink .Next
1998
- symtab := itablink .Next
1999
- pclntab := symtab .Next
2026
+ var (
2027
+ text = Segtext .Sect
2028
+ rodata = Linklookup (ctxt , "runtime.rodata" , 0 ).Sect
2029
+ typelink = Linklookup (ctxt , "runtime.typelink" , 0 ).Sect
2030
+ itablink = Linklookup (ctxt , "runtime.itablink" , 0 ).Sect
2031
+ symtab = Linklookup (ctxt , "runtime.symtab" , 0 ).Sect
2032
+ pclntab = Linklookup (ctxt , "runtime.pclntab" , 0 ).Sect
2033
+ types = Linklookup (ctxt , "runtime.types" , 0 ).Sect
2034
+ )
2000
2035
2001
2036
for _ , s := range datap {
2002
2037
ctxt .Cursym = s
@@ -2025,11 +2060,6 @@ func (ctxt *Link) address() {
2025
2060
s .Value = int64 (sectSym .Sect .Vaddr + 16 )
2026
2061
}
2027
2062
2028
- types := relrodata
2029
- if types == nil {
2030
- types = rodata
2031
- }
2032
-
2033
2063
ctxt .xdefine ("runtime.text" , obj .STEXT , int64 (text .Vaddr ))
2034
2064
ctxt .xdefine ("runtime.etext" , obj .STEXT , int64 (text .Vaddr + text .Length ))
2035
2065
if Headtype == obj .Hwindows || Headtype == obj .Hwindowsgui {
0 commit comments