mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/link: introduce a rel.ro segment
When internally linking with using rel.ro sections, this segment covers the sections. To do this, move to other read-only sections, SELFROSECT and SMACHOPLT, out of the way. Part of adding PIE internal linking on linux/amd64. Change-Id: I4fb3d180e92f7e801789ab89864010faf5a2cb6d Reviewed-on: https://go-review.googlesource.com/28538 Run-TryBot: David Crawshaw <crawshaw@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
13dc4d378b
commit
276803d611
11 changed files with 168 additions and 72 deletions
|
|
@ -384,6 +384,7 @@ const (
|
|||
STEXT
|
||||
SELFRXSECT
|
||||
|
||||
// Read-only sections.
|
||||
STYPE
|
||||
SSTRING
|
||||
SGOSTRING
|
||||
|
|
@ -393,6 +394,11 @@ const (
|
|||
SRODATA
|
||||
SFUNCTAB
|
||||
|
||||
SELFROSECT
|
||||
SMACHOPLT
|
||||
|
||||
// Read-only sections with relocations.
|
||||
//
|
||||
// Types STYPE-SFUNCTAB above are written to the .rodata section by default.
|
||||
// When linking a shared object, some conceptually "read only" types need to
|
||||
// be written to by relocations and putting them in a section called
|
||||
|
|
@ -412,12 +418,13 @@ const (
|
|||
SRODATARELRO
|
||||
SFUNCTABRELRO
|
||||
|
||||
// Part of .data.rel.ro if it exists, otherwise part of .rodata.
|
||||
STYPELINK
|
||||
SITABLINK
|
||||
SSYMTAB
|
||||
SPCLNTAB
|
||||
SELFROSECT
|
||||
SMACHOPLT
|
||||
|
||||
// Writable sections.
|
||||
SELFSECT
|
||||
SMACHO
|
||||
SMACHOGOT
|
||||
|
|
|
|||
|
|
@ -623,10 +623,16 @@ func asmb(ctxt *ld.Link) {
|
|||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
|
||||
ld.Cseek(int64(ld.Segrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
||||
}
|
||||
if ld.Segrelrodata.Filelen > 0 {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime())
|
||||
}
|
||||
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
||||
}
|
||||
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
|
||||
|
|
|
|||
|
|
@ -602,10 +602,16 @@ func asmb(ctxt *ld.Link) {
|
|||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
|
||||
ld.Cseek(int64(ld.Segrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
||||
}
|
||||
if ld.Segrelrodata.Filelen > 0 {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime())
|
||||
}
|
||||
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
||||
}
|
||||
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
|
||||
|
|
|
|||
|
|
@ -411,10 +411,16 @@ func asmb(ctxt *ld.Link) {
|
|||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
|
||||
ld.Cseek(int64(ld.Segrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
||||
}
|
||||
if ld.Segrelrodata.Filelen > 0 {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime())
|
||||
}
|
||||
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
||||
}
|
||||
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
|
||||
|
|
|
|||
|
|
@ -1508,6 +1508,33 @@ func (ctxt *Link) dodata() {
|
|||
}
|
||||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
|
||||
/* read-only ELF, Mach-O sections */
|
||||
for _, s := range data[obj.SELFROSECT] {
|
||||
sect = addsection(segro, s.Name, 04)
|
||||
sect.Align = symalign(s)
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
s.Sect = sect
|
||||
s.Type = obj.SRODATA
|
||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||
datsize += s.Size
|
||||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
}
|
||||
checkdatsize(ctxt, datsize, obj.SELFROSECT)
|
||||
|
||||
for _, s := range data[obj.SMACHOPLT] {
|
||||
sect = addsection(segro, s.Name, 04)
|
||||
sect.Align = symalign(s)
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
s.Sect = sect
|
||||
s.Type = obj.SRODATA
|
||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||
datsize += s.Size
|
||||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
}
|
||||
checkdatsize(ctxt, datsize, obj.SMACHOPLT)
|
||||
|
||||
// There is some data that are conceptually read-only but are written to by
|
||||
// relocations. On GNU systems, we can arrange for the dynamic linker to
|
||||
// mprotect sections after relocations are applied by giving them write
|
||||
|
|
@ -1518,14 +1545,26 @@ func (ctxt *Link) dodata() {
|
|||
// situation.
|
||||
// TODO(mwhudson): It would make sense to do this more widely, but it makes
|
||||
// the system linker segfault on darwin.
|
||||
relroPerms := 04
|
||||
relroPrefix := ""
|
||||
addrelrosection := func(suffix string) *Section {
|
||||
return addsection(segro, suffix, 04)
|
||||
}
|
||||
|
||||
if UseRelro() {
|
||||
relroPerms = 06
|
||||
relroPrefix = ".data.rel.ro"
|
||||
addrelrosection = func(suffix string) *Section {
|
||||
seg := &Segrelrodata
|
||||
if Linkmode == LinkExternal {
|
||||
// Using a separate segment with an external
|
||||
// linker results in some programs moving
|
||||
// their data sections unexpectedly, which
|
||||
// corrupts the moduledata. So we use the
|
||||
// rodata segment and let the external linker
|
||||
// sort out a rel.ro segment.
|
||||
seg = &Segrodata
|
||||
}
|
||||
return addsection(seg, ".data.rel.ro"+suffix, 06)
|
||||
}
|
||||
/* data only written by relocations */
|
||||
sect = addsection(segro, ".data.rel.ro", 06)
|
||||
sect = addrelrosection("")
|
||||
|
||||
sect.Vaddr = 0
|
||||
Linklookup(ctxt, "runtime.types", 0).Sect = sect
|
||||
|
|
@ -1554,11 +1593,10 @@ func (ctxt *Link) dodata() {
|
|||
}
|
||||
|
||||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
|
||||
}
|
||||
|
||||
/* typelink */
|
||||
sect = addsection(segro, relroPrefix+".typelink", relroPerms)
|
||||
sect = addrelrosection(".typelink")
|
||||
sect.Align = dataMaxAlign[obj.STYPELINK]
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
|
|
@ -1575,7 +1613,7 @@ func (ctxt *Link) dodata() {
|
|||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
|
||||
/* itablink */
|
||||
sect = addsection(segro, relroPrefix+".itablink", relroPerms)
|
||||
sect = addrelrosection(".itablink")
|
||||
sect.Align = dataMaxAlign[obj.SITABLINK]
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
|
|
@ -1592,7 +1630,7 @@ func (ctxt *Link) dodata() {
|
|||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
|
||||
/* gosymtab */
|
||||
sect = addsection(segro, relroPrefix+".gosymtab", relroPerms)
|
||||
sect = addrelrosection(".gosymtab")
|
||||
sect.Align = dataMaxAlign[obj.SSYMTAB]
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
|
|
@ -1609,7 +1647,7 @@ func (ctxt *Link) dodata() {
|
|||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
|
||||
/* gopclntab */
|
||||
sect = addsection(segro, relroPrefix+".gopclntab", relroPerms)
|
||||
sect = addrelrosection(".gopclntab")
|
||||
sect.Align = dataMaxAlign[obj.SPCLNTAB]
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
|
|
@ -1625,33 +1663,6 @@ func (ctxt *Link) dodata() {
|
|||
checkdatsize(ctxt, datsize, obj.SRODATA)
|
||||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
|
||||
/* read-only ELF, Mach-O sections */
|
||||
for _, s := range data[obj.SELFROSECT] {
|
||||
sect = addsection(segro, s.Name, 04)
|
||||
sect.Align = symalign(s)
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
s.Sect = sect
|
||||
s.Type = obj.SRODATA
|
||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||
datsize += s.Size
|
||||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
}
|
||||
checkdatsize(ctxt, datsize, obj.SELFROSECT)
|
||||
|
||||
for _, s := range data[obj.SMACHOPLT] {
|
||||
sect = addsection(segro, s.Name, 04)
|
||||
sect.Align = symalign(s)
|
||||
datsize = Rnd(datsize, int64(sect.Align))
|
||||
sect.Vaddr = uint64(datsize)
|
||||
s.Sect = sect
|
||||
s.Type = obj.SRODATA
|
||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||
datsize += s.Size
|
||||
sect.Length = uint64(datsize) - sect.Vaddr
|
||||
}
|
||||
checkdatsize(ctxt, datsize, obj.SMACHOPLT)
|
||||
|
||||
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
|
||||
if datsize != int64(uint32(datsize)) {
|
||||
ctxt.Diag("read-only data segment too large")
|
||||
|
|
@ -1711,6 +1722,10 @@ func (ctxt *Link) dodata() {
|
|||
sect.Extnum = int16(n)
|
||||
n++
|
||||
}
|
||||
for sect := Segrelrodata.Sect; sect != nil; sect = sect.Next {
|
||||
sect.Extnum = int16(n)
|
||||
n++
|
||||
}
|
||||
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
|
||||
sect.Extnum = int16(n)
|
||||
n++
|
||||
|
|
@ -1897,6 +1912,17 @@ func (ctxt *Link) address() {
|
|||
if Segrodata.Sect != nil {
|
||||
// align to page boundary so as not to mix
|
||||
// rodata and executable text.
|
||||
//
|
||||
// Note: gold or GNU ld will reduce the size of the executable
|
||||
// file by arranging for the relro segment to end at a page
|
||||
// boundary, and overlap the end of the text segment with the
|
||||
// start of the relro segment in the file. The PT_LOAD segments
|
||||
// will be such that the last page of the text segment will be
|
||||
// mapped twice, once r-x and once starting out rw- and, after
|
||||
// relocation processing, changed to r--.
|
||||
//
|
||||
// Ideally the last page of the text segment would not be
|
||||
// writable even for this short period.
|
||||
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
||||
|
||||
Segrodata.Rwx = 04
|
||||
|
|
@ -1912,6 +1938,24 @@ func (ctxt *Link) address() {
|
|||
Segrodata.Length = va - Segrodata.Vaddr
|
||||
Segrodata.Filelen = Segrodata.Length
|
||||
}
|
||||
if Segrelrodata.Sect != nil {
|
||||
// align to page boundary so as not to mix
|
||||
// rodata, rel-ro data, and executable text.
|
||||
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
||||
|
||||
Segrelrodata.Rwx = 06
|
||||
Segrelrodata.Vaddr = va
|
||||
Segrelrodata.Fileoff = va - Segrodata.Vaddr + Segrodata.Fileoff
|
||||
Segrelrodata.Filelen = 0
|
||||
for s := Segrelrodata.Sect; s != nil; s = s.Next {
|
||||
va = uint64(Rnd(int64(va), int64(s.Align)))
|
||||
s.Vaddr = va
|
||||
va += s.Length
|
||||
}
|
||||
|
||||
Segrelrodata.Length = va - Segrelrodata.Vaddr
|
||||
Segrelrodata.Filelen = Segrelrodata.Length
|
||||
}
|
||||
|
||||
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
||||
Segdata.Rwx = 06
|
||||
|
|
@ -1979,24 +2023,15 @@ func (ctxt *Link) address() {
|
|||
|
||||
Segdwarf.Filelen = va - Segdwarf.Vaddr
|
||||
|
||||
text := Segtext.Sect
|
||||
var rodata *Section
|
||||
if Segrodata.Sect != nil {
|
||||
rodata = Segrodata.Sect
|
||||
} else {
|
||||
rodata = text.Next
|
||||
}
|
||||
var relrodata *Section
|
||||
typelink := rodata.Next
|
||||
if UseRelro() {
|
||||
// There is another section (.data.rel.ro) when building a shared
|
||||
// object on elf systems.
|
||||
relrodata = typelink
|
||||
typelink = typelink.Next
|
||||
}
|
||||
itablink := typelink.Next
|
||||
symtab := itablink.Next
|
||||
pclntab := symtab.Next
|
||||
var (
|
||||
text = Segtext.Sect
|
||||
rodata = Linklookup(ctxt, "runtime.rodata", 0).Sect
|
||||
typelink = Linklookup(ctxt, "runtime.typelink", 0).Sect
|
||||
itablink = Linklookup(ctxt, "runtime.itablink", 0).Sect
|
||||
symtab = Linklookup(ctxt, "runtime.symtab", 0).Sect
|
||||
pclntab = Linklookup(ctxt, "runtime.pclntab", 0).Sect
|
||||
types = Linklookup(ctxt, "runtime.types", 0).Sect
|
||||
)
|
||||
|
||||
for _, s := range datap {
|
||||
ctxt.Cursym = s
|
||||
|
|
@ -2025,11 +2060,6 @@ func (ctxt *Link) address() {
|
|||
s.Value = int64(sectSym.Sect.Vaddr + 16)
|
||||
}
|
||||
|
||||
types := relrodata
|
||||
if types == nil {
|
||||
types = rodata
|
||||
}
|
||||
|
||||
ctxt.xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
|
||||
ctxt.xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length))
|
||||
if Headtype == obj.Hwindows || Headtype == obj.Hwindowsgui {
|
||||
|
|
|
|||
|
|
@ -1783,6 +1783,9 @@ func Elfemitreloc(ctxt *Link) {
|
|||
for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfrelocsect(ctxt, sect, datap)
|
||||
}
|
||||
for sect := Segrelrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfrelocsect(ctxt, sect, datap)
|
||||
}
|
||||
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
|
||||
elfrelocsect(ctxt, sect, datap)
|
||||
}
|
||||
|
|
@ -2114,6 +2117,9 @@ func Asmbelfsetup(ctxt *Link) {
|
|||
for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshalloc(ctxt, sect)
|
||||
}
|
||||
for sect := Segrelrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshalloc(ctxt, sect)
|
||||
}
|
||||
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshalloc(ctxt, sect)
|
||||
}
|
||||
|
|
@ -2283,6 +2289,9 @@ func Asmbelf(ctxt *Link, symo int64) {
|
|||
if Segrodata.Sect != nil {
|
||||
elfphload(ctxt, &Segrodata)
|
||||
}
|
||||
if Segrelrodata.Sect != nil {
|
||||
elfphload(ctxt, &Segrelrodata)
|
||||
}
|
||||
elfphload(ctxt, &Segdata)
|
||||
|
||||
/* Dynamic linking sections */
|
||||
|
|
@ -2482,6 +2491,9 @@ elfobj:
|
|||
for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshbits(ctxt, sect)
|
||||
}
|
||||
for sect := Segrelrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshbits(ctxt, sect)
|
||||
}
|
||||
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshbits(ctxt, sect)
|
||||
}
|
||||
|
|
@ -2496,6 +2508,9 @@ elfobj:
|
|||
for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshreloc(ctxt, sect)
|
||||
}
|
||||
for sect := Segrelrodata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshreloc(ctxt, sect)
|
||||
}
|
||||
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
|
||||
elfshreloc(ctxt, sect)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ var (
|
|||
var (
|
||||
Segtext Segment
|
||||
Segrodata Segment
|
||||
Segrelrodata Segment
|
||||
Segdata Segment
|
||||
Segdwarf Segment
|
||||
)
|
||||
|
|
|
|||
|
|
@ -203,10 +203,16 @@ func asmb(ctxt *ld.Link) {
|
|||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
|
||||
ld.Cseek(int64(ld.Segrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
||||
}
|
||||
if ld.Segrelrodata.Filelen > 0 {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
||||
}
|
||||
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
|
||||
|
|
|
|||
|
|
@ -824,10 +824,16 @@ func asmb(ctxt *ld.Link) {
|
|||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
|
||||
ld.Cseek(int64(ld.Segrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
||||
}
|
||||
if ld.Segrelrodata.Filelen > 0 {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime())
|
||||
}
|
||||
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
||||
}
|
||||
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
|
||||
|
|
|
|||
|
|
@ -519,10 +519,16 @@ func asmb(ctxt *ld.Link) {
|
|||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
|
||||
ld.Cseek(int64(ld.Segrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
||||
}
|
||||
if ld.Segrelrodata.Filelen > 0 {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
|
||||
}
|
||||
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
||||
}
|
||||
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
|
||||
|
|
|
|||
|
|
@ -649,6 +649,13 @@ func asmb(ctxt *ld.Link) {
|
|||
ld.Cseek(int64(ld.Segrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
|
||||
}
|
||||
if ld.Segrelrodata.Filelen > 0 {
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime())
|
||||
}
|
||||
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
|
||||
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
|
||||
}
|
||||
|
||||
if ctxt.Debugvlog != 0 {
|
||||
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue