Commit bd837745 authored by Austin Clements's avatar Austin Clements

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. Currently, each instance of this is slightly different, but
there's no reason for it to be. For example, we don't perform
PEFILEALIGN alignment on Segrodata or Selreltodata even when HeadType
== Hwindows, but it turns out it doesn't matter whether you do or
don't because these segments simply don't exist on Windows. Hence, in
the unified code path, we do this alignment for all segments.
Likewise, there are two ways of computing Fileoff:
  seg.Vaddr - prev.Vaddr + prev.Fileoff
and
  prev.Fileoff + uint64(Rnd(int64(prev.Filelen), int64(*FlagRound)))
At the moment, these always have the same value, but the latter will
continue to work after we start compressing sections on disk.

Tested by comparing test binaries for all packages in std before and
after this change for GOOS={linux,windows,darwin,plan9}. All binaries
are identical.

For #11799.

Change-Id: If09f28771bb4d78dd392fd58b8d7c9d5f22b0b9f
Reviewed-on: https://go-review.googlesource.com/111682
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarHeschi Kreinick <heschi@google.com>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent f7142206
......@@ -1903,12 +1903,15 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s *sym.Symbol, va uint6
return sect, n, va
}
// assign addresses
func (ctxt *Link) address() {
// address assigns virtual addresses to all segments and sections and
// returns all segments in file order.
func (ctxt *Link) address() []*sym.Segment {
var order []*sym.Segment // Layout order
va := uint64(*FlagTextAddr)
order = append(order, &Segtext)
Segtext.Rwx = 05
Segtext.Vaddr = va
Segtext.Fileoff = uint64(HEADR)
for _, s := range Segtext.Sections {
va = uint64(Rnd(int64(va), int64(s.Align)))
s.Vaddr = va
......@@ -1916,7 +1919,6 @@ func (ctxt *Link) address() {
}
Segtext.Length = va - uint64(*FlagTextAddr)
Segtext.Filelen = Segtext.Length
if ctxt.HeadType == objabi.Hnacl {
va += 32 // room for the "halt sled"
}
......@@ -1937,13 +1939,9 @@ func (ctxt *Link) address() {
// writable even for this short period.
va = uint64(Rnd(int64(va), int64(*FlagRound)))
order = append(order, &Segrodata)
Segrodata.Rwx = 04
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 {
va = uint64(Rnd(int64(va), int64(s.Align)))
s.Vaddr = va
......@@ -1951,17 +1949,15 @@ func (ctxt *Link) address() {
}
Segrodata.Length = va - Segrodata.Vaddr
Segrodata.Filelen = Segrodata.Length
}
if len(Segrelrodata.Sections) > 0 {
// align to page boundary so as not to mix
// rodata, rel-ro data, and executable text.
va = uint64(Rnd(int64(va), int64(*FlagRound)))
order = append(order, &Segrelrodata)
Segrelrodata.Rwx = 06
Segrelrodata.Vaddr = va
Segrelrodata.Fileoff = va - Segrodata.Vaddr + Segrodata.Fileoff
Segrelrodata.Filelen = 0
for _, s := range Segrelrodata.Sections {
va = uint64(Rnd(int64(va), int64(s.Align)))
s.Vaddr = va
......@@ -1969,20 +1965,12 @@ func (ctxt *Link) address() {
}
Segrelrodata.Length = va - Segrelrodata.Vaddr
Segrelrodata.Filelen = Segrelrodata.Length
}
va = uint64(Rnd(int64(va), int64(*FlagRound)))
order = append(order, &Segdata)
Segdata.Rwx = 06
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 noptr *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
va = uint64(Rnd(int64(va), int64(*FlagRound)))
order = append(order, &Segdwarf)
Segdwarf.Rwx = 06
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 {
vlen := int64(s.Length)
if i+1 < len(Segdwarf.Sections) {
......@@ -2035,8 +2021,6 @@ func (ctxt *Link) address() {
Segdwarf.Length = va - Segdwarf.Vaddr
}
Segdwarf.Filelen = va - Segdwarf.Vaddr
var (
text = Segtext.Sections[0]
rodata = ctxt.Syms.Lookup("runtime.rodata", 0).Sect
......@@ -2123,6 +2107,34 @@ func (ctxt *Link) address() {
ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.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:
seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), int64(*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)
......
......@@ -224,8 +224,9 @@ func Main(arch *sys.Arch, theArch Arch) {
ctxt.typelink()
ctxt.symtab()
ctxt.dodata()
ctxt.address()
order := ctxt.address()
ctxt.reloc()
ctxt.layout(order)
thearch.Asmb(ctxt)
ctxt.undef()
ctxt.hostlink()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment