mirror of
https://github.com/golang/go
synced 2024-11-19 05:54:44 -07: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. 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: Heschi Kreinick <heschi@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
f7142206e9
commit
bd83774593
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user