@@ -1183,6 +1183,29 @@ func dodata() {
1183
1183
1184
1184
* l = nil
1185
1185
1186
+ if Buildmode == BuildmodeShared {
1187
+ // "read only" data with relocations needs to go in its own section
1188
+ // when building a shared library.
1189
+ for s := datap ; s != nil ; s = s .Next {
1190
+ if s .Type >= obj .STYPE && s .Type <= obj .SFUNCTAB && len (s .R ) > 0 {
1191
+ s .Type += (obj .STYPERELRO - obj .STYPE )
1192
+ if s .Outer != nil && s .Outer .Type != s .Type {
1193
+ s .Outer .Type = s .Type
1194
+ }
1195
+ }
1196
+ }
1197
+ // Check that we haven't made two symbols with the same .Outer into
1198
+ // different types.
1199
+ for s := datap ; s != nil ; s = s .Next {
1200
+ if s .Outer != nil && s .Outer .Type != s .Type {
1201
+ Diag (
1202
+ "inconsisent types for %s and its Outer %s (%d != %d)" ,
1203
+ s .Name , s .Outer .Name , s .Type , s .Outer .Type )
1204
+ }
1205
+ }
1206
+
1207
+ }
1208
+
1186
1209
datap = listsort (datap , datcmp , listnextp )
1187
1210
1188
1211
if Iself {
@@ -1442,12 +1465,12 @@ func dodata() {
1442
1465
/* read-only data */
1443
1466
sect = addsection (segro , ".rodata" , 04 )
1444
1467
1445
- sect .Align = maxalign (s , obj .STYPELINK - 1 )
1468
+ sect .Align = maxalign (s , obj .STYPERELRO - 1 )
1446
1469
datsize = Rnd (datsize , int64 (sect .Align ))
1447
1470
sect .Vaddr = 0
1448
1471
Linklookup (Ctxt , "runtime.rodata" , 0 ).Sect = sect
1449
1472
Linklookup (Ctxt , "runtime.erodata" , 0 ).Sect = sect
1450
- for ; s != nil && s .Type < obj .STYPELINK ; s = s .Next {
1473
+ for ; s != nil && s .Type < obj .STYPERELRO ; s = s .Next {
1451
1474
datsize = aligndatsize (datsize , s )
1452
1475
s .Sect = sect
1453
1476
s .Type = obj .SRODATA
@@ -1457,8 +1480,43 @@ func dodata() {
1457
1480
1458
1481
sect .Length = uint64 (datsize ) - sect .Vaddr
1459
1482
1483
+ // There are a few sections that are conceptually read-only but are written
1484
+ // to by relocations. We can arrange for the dynamic linker to mprotect
1485
+ // exactly one section after relocations are applied by calling it
1486
+ // ".data.rel.ro". We use that section for things that would ordinarily be go
1487
+ // into .rodata and leave the other sections (.typelink, .gosymtab,
1488
+ // .gopclntab) writable.
1489
+ // TODO(mwhudson): Why can't we just put the typelink table and so on into
1490
+ // .data.rel.ro? What exactly depends on them being their own sections?
1491
+ relro_perms := 04
1492
+
1493
+ if Buildmode == BuildmodeShared {
1494
+ relro_perms = 06
1495
+ /* data only written by relocations */
1496
+ sect = addsection (segro , ".data.rel.ro" , 06 )
1497
+
1498
+ sect .Align = maxalign (s , obj .STYPELINK - 1 )
1499
+ datsize = Rnd (datsize , int64 (sect .Align ))
1500
+ sect .Vaddr = 0
1501
+ Linklookup (Ctxt , "runtime.rodata" , 0 ).Sect = sect
1502
+ Linklookup (Ctxt , "runtime.erodata" , 0 ).Sect = sect
1503
+ for ; s != nil && s .Type < obj .STYPELINK ; s = s .Next {
1504
+ datsize = aligndatsize (datsize , s )
1505
+ if s .Outer != nil && s .Outer .Sect != nil && s .Outer .Sect != sect {
1506
+ Diag ("vomit %s" , s .Name )
1507
+ }
1508
+ s .Sect = sect
1509
+ s .Type = obj .SRODATA
1510
+ s .Value = int64 (uint64 (datsize ) - sect .Vaddr )
1511
+ growdatsize (& datsize , s )
1512
+ }
1513
+
1514
+ sect .Length = uint64 (datsize ) - sect .Vaddr
1515
+
1516
+ }
1517
+
1460
1518
/* typelink */
1461
- sect = addsection (segro , ".typelink" , 04 )
1519
+ sect = addsection (segro , ".typelink" , relro_perms )
1462
1520
1463
1521
sect .Align = maxalign (s , obj .STYPELINK )
1464
1522
datsize = Rnd (datsize , int64 (sect .Align ))
@@ -1476,7 +1534,7 @@ func dodata() {
1476
1534
sect .Length = uint64 (datsize ) - sect .Vaddr
1477
1535
1478
1536
/* gosymtab */
1479
- sect = addsection (segro , ".gosymtab" , 04 )
1537
+ sect = addsection (segro , ".gosymtab" , relro_perms )
1480
1538
1481
1539
sect .Align = maxalign (s , obj .SPCLNTAB - 1 )
1482
1540
datsize = Rnd (datsize , int64 (sect .Align ))
@@ -1494,7 +1552,7 @@ func dodata() {
1494
1552
sect .Length = uint64 (datsize ) - sect .Vaddr
1495
1553
1496
1554
/* gopclntab */
1497
- sect = addsection (segro , ".gopclntab" , 04 )
1555
+ sect = addsection (segro , ".gopclntab" , relro_perms )
1498
1556
1499
1557
sect .Align = maxalign (s , obj .SELFROSECT - 1 )
1500
1558
datsize = Rnd (datsize , int64 (sect .Align ))
@@ -1674,6 +1732,10 @@ func address() {
1674
1732
rodata = text .Next
1675
1733
}
1676
1734
typelink := rodata .Next
1735
+ if Buildmode == BuildmodeShared {
1736
+ // There is another section (.data.rel.ro) when building a shared object...
1737
+ typelink = typelink .Next
1738
+ }
1677
1739
symtab := typelink .Next
1678
1740
pclntab := symtab .Next
1679
1741
0 commit comments