mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/link: separate virtual address layout from file layout
Currently these two forms of layout are done in a single pass. This makes it difficult to compress DWARF sections because that must be done after relocations are applied, which must happen after virtual address layout, but we can't layout the file until we've compressed the DWARF sections. Fix this by separating the two layout steps. In the process, we can also unify the copy-pasted code in Link.address to compute file offsets, which currently has some unnecessary variation. Unlike the current file offset computation, which depends on virtual addresses, the new computation only uses file offsets and sizes. This will let us compress the file representation of a segment and create the file layout based on its on-disk size rather than its original in-memory size. Tested by comparing the test binary for the "strings" package on all supported GOOS/GOARCH combinations. All binaries are identical (except, of course, their build IDs). This is a second attempt at CL 111682. For #11799. Fixes #25863. Change-Id: If09f28771bb4d78dd392fd58b8d7c9d5f22b0b9e Reviewed-on: https://go-review.googlesource.com/118716 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
c12399fffb
commit
8998c55ec0
2 changed files with 49 additions and 29 deletions
|
|
@ -1903,12 +1903,15 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s *sym.Symbol, va uint6
|
||||||
return sect, n, va
|
return sect, n, va
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign addresses
|
// address assigns virtual addresses to all segments and sections and
|
||||||
func (ctxt *Link) address() {
|
// returns all segments in file order.
|
||||||
|
func (ctxt *Link) address() []*sym.Segment {
|
||||||
|
var order []*sym.Segment // Layout order
|
||||||
|
|
||||||
va := uint64(*FlagTextAddr)
|
va := uint64(*FlagTextAddr)
|
||||||
|
order = append(order, &Segtext)
|
||||||
Segtext.Rwx = 05
|
Segtext.Rwx = 05
|
||||||
Segtext.Vaddr = va
|
Segtext.Vaddr = va
|
||||||
Segtext.Fileoff = uint64(HEADR)
|
|
||||||
for _, s := range Segtext.Sections {
|
for _, s := range Segtext.Sections {
|
||||||
va = uint64(Rnd(int64(va), int64(s.Align)))
|
va = uint64(Rnd(int64(va), int64(s.Align)))
|
||||||
s.Vaddr = va
|
s.Vaddr = va
|
||||||
|
|
@ -1916,7 +1919,6 @@ func (ctxt *Link) address() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Segtext.Length = va - uint64(*FlagTextAddr)
|
Segtext.Length = va - uint64(*FlagTextAddr)
|
||||||
Segtext.Filelen = Segtext.Length
|
|
||||||
if ctxt.HeadType == objabi.Hnacl {
|
if ctxt.HeadType == objabi.Hnacl {
|
||||||
va += 32 // room for the "halt sled"
|
va += 32 // room for the "halt sled"
|
||||||
}
|
}
|
||||||
|
|
@ -1937,13 +1939,9 @@ func (ctxt *Link) address() {
|
||||||
// writable even for this short period.
|
// writable even for this short period.
|
||||||
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
||||||
|
|
||||||
|
order = append(order, &Segrodata)
|
||||||
Segrodata.Rwx = 04
|
Segrodata.Rwx = 04
|
||||||
Segrodata.Vaddr = va
|
Segrodata.Vaddr = va
|
||||||
Segrodata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
|
|
||||||
Segrodata.Filelen = 0
|
|
||||||
if ctxt.HeadType == objabi.Hwindows {
|
|
||||||
Segrodata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN))
|
|
||||||
}
|
|
||||||
for _, s := range Segrodata.Sections {
|
for _, s := range Segrodata.Sections {
|
||||||
va = uint64(Rnd(int64(va), int64(s.Align)))
|
va = uint64(Rnd(int64(va), int64(s.Align)))
|
||||||
s.Vaddr = va
|
s.Vaddr = va
|
||||||
|
|
@ -1951,17 +1949,15 @@ func (ctxt *Link) address() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Segrodata.Length = va - Segrodata.Vaddr
|
Segrodata.Length = va - Segrodata.Vaddr
|
||||||
Segrodata.Filelen = Segrodata.Length
|
|
||||||
}
|
}
|
||||||
if len(Segrelrodata.Sections) > 0 {
|
if len(Segrelrodata.Sections) > 0 {
|
||||||
// align to page boundary so as not to mix
|
// align to page boundary so as not to mix
|
||||||
// rodata, rel-ro data, and executable text.
|
// rodata, rel-ro data, and executable text.
|
||||||
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
||||||
|
|
||||||
|
order = append(order, &Segrelrodata)
|
||||||
Segrelrodata.Rwx = 06
|
Segrelrodata.Rwx = 06
|
||||||
Segrelrodata.Vaddr = va
|
Segrelrodata.Vaddr = va
|
||||||
Segrelrodata.Fileoff = va - Segrodata.Vaddr + Segrodata.Fileoff
|
|
||||||
Segrelrodata.Filelen = 0
|
|
||||||
for _, s := range Segrelrodata.Sections {
|
for _, s := range Segrelrodata.Sections {
|
||||||
va = uint64(Rnd(int64(va), int64(s.Align)))
|
va = uint64(Rnd(int64(va), int64(s.Align)))
|
||||||
s.Vaddr = va
|
s.Vaddr = va
|
||||||
|
|
@ -1969,20 +1965,12 @@ func (ctxt *Link) address() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Segrelrodata.Length = va - Segrelrodata.Vaddr
|
Segrelrodata.Length = va - Segrelrodata.Vaddr
|
||||||
Segrelrodata.Filelen = Segrelrodata.Length
|
|
||||||
}
|
}
|
||||||
|
|
||||||
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
||||||
|
order = append(order, &Segdata)
|
||||||
Segdata.Rwx = 06
|
Segdata.Rwx = 06
|
||||||
Segdata.Vaddr = va
|
Segdata.Vaddr = va
|
||||||
Segdata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
|
|
||||||
Segdata.Filelen = 0
|
|
||||||
if ctxt.HeadType == objabi.Hwindows {
|
|
||||||
Segdata.Fileoff = Segrodata.Fileoff + uint64(Rnd(int64(Segrodata.Length), PEFILEALIGN))
|
|
||||||
}
|
|
||||||
if ctxt.HeadType == objabi.Hplan9 {
|
|
||||||
Segdata.Fileoff = Segtext.Fileoff + Segtext.Filelen
|
|
||||||
}
|
|
||||||
var data *sym.Section
|
var data *sym.Section
|
||||||
var noptr *sym.Section
|
var noptr *sym.Section
|
||||||
var bss *sym.Section
|
var bss *sym.Section
|
||||||
|
|
@ -2012,16 +2000,14 @@ func (ctxt *Link) address() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign Segdata's Filelen omitting the BSS. We do this here
|
||||||
|
// simply because right now we know where the BSS starts.
|
||||||
Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
|
Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
|
||||||
|
|
||||||
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
va = uint64(Rnd(int64(va), int64(*FlagRound)))
|
||||||
|
order = append(order, &Segdwarf)
|
||||||
Segdwarf.Rwx = 06
|
Segdwarf.Rwx = 06
|
||||||
Segdwarf.Vaddr = va
|
Segdwarf.Vaddr = va
|
||||||
Segdwarf.Fileoff = Segdata.Fileoff + uint64(Rnd(int64(Segdata.Filelen), int64(*FlagRound)))
|
|
||||||
Segdwarf.Filelen = 0
|
|
||||||
if ctxt.HeadType == objabi.Hwindows {
|
|
||||||
Segdwarf.Fileoff = Segdata.Fileoff + uint64(Rnd(int64(Segdata.Filelen), PEFILEALIGN))
|
|
||||||
}
|
|
||||||
for i, s := range Segdwarf.Sections {
|
for i, s := range Segdwarf.Sections {
|
||||||
vlen := int64(s.Length)
|
vlen := int64(s.Length)
|
||||||
if i+1 < len(Segdwarf.Sections) {
|
if i+1 < len(Segdwarf.Sections) {
|
||||||
|
|
@ -2035,8 +2021,6 @@ func (ctxt *Link) address() {
|
||||||
Segdwarf.Length = va - Segdwarf.Vaddr
|
Segdwarf.Length = va - Segdwarf.Vaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
Segdwarf.Filelen = va - Segdwarf.Vaddr
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
text = Segtext.Sections[0]
|
text = Segtext.Sections[0]
|
||||||
rodata = ctxt.Syms.Lookup("runtime.rodata", 0).Sect
|
rodata = ctxt.Syms.Lookup("runtime.rodata", 0).Sect
|
||||||
|
|
@ -2123,6 +2107,41 @@ func (ctxt *Link) address() {
|
||||||
ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
|
ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
|
||||||
ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
|
ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
|
||||||
ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
|
ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
|
||||||
|
|
||||||
|
return order
|
||||||
|
}
|
||||||
|
|
||||||
|
// layout assigns file offsets and lengths to the segments in order.
|
||||||
|
func (ctxt *Link) layout(order []*sym.Segment) {
|
||||||
|
var prev *sym.Segment
|
||||||
|
for _, seg := range order {
|
||||||
|
if prev == nil {
|
||||||
|
seg.Fileoff = uint64(HEADR)
|
||||||
|
} else {
|
||||||
|
switch ctxt.HeadType {
|
||||||
|
default:
|
||||||
|
// Assuming the previous segment was
|
||||||
|
// aligned, the following rounding
|
||||||
|
// should ensure that this segment's
|
||||||
|
// VA ≡ Fileoff mod FlagRound.
|
||||||
|
seg.Fileoff = uint64(Rnd(int64(prev.Fileoff+prev.Filelen), int64(*FlagRound)))
|
||||||
|
if seg.Vaddr%uint64(*FlagRound) != seg.Fileoff%uint64(*FlagRound) {
|
||||||
|
Exitf("bad segment rounding (Vaddr=%#x Fileoff=%#x FlagRound=%#x)", seg.Vaddr, seg.Fileoff, *FlagRound)
|
||||||
|
}
|
||||||
|
case objabi.Hwindows:
|
||||||
|
seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), PEFILEALIGN))
|
||||||
|
case objabi.Hplan9:
|
||||||
|
seg.Fileoff = prev.Fileoff + prev.Filelen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if seg != &Segdata {
|
||||||
|
// Link.address already set Segdata.Filelen to
|
||||||
|
// account for BSS.
|
||||||
|
seg.Filelen = seg.Length
|
||||||
|
}
|
||||||
|
prev = seg
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a trampoline with symbol s (to be laid down after the current function)
|
// add a trampoline with symbol s (to be laid down after the current function)
|
||||||
|
|
|
||||||
|
|
@ -224,8 +224,9 @@ func Main(arch *sys.Arch, theArch Arch) {
|
||||||
ctxt.typelink()
|
ctxt.typelink()
|
||||||
ctxt.symtab()
|
ctxt.symtab()
|
||||||
ctxt.dodata()
|
ctxt.dodata()
|
||||||
ctxt.address()
|
order := ctxt.address()
|
||||||
ctxt.reloc()
|
ctxt.reloc()
|
||||||
|
ctxt.layout(order)
|
||||||
thearch.Asmb(ctxt)
|
thearch.Asmb(ctxt)
|
||||||
ctxt.undef()
|
ctxt.undef()
|
||||||
ctxt.hostlink()
|
ctxt.hostlink()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue