Skip to content

Commit bd83774

Browse files
committed
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>
1 parent f714220 commit bd83774

File tree

2 files changed

+42
-29
lines changed

2 files changed

+42
-29
lines changed

src/cmd/link/internal/ld/data.go

+40-28
Original file line numberDiff line numberDiff line change
@@ -1903,20 +1903,22 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s *sym.Symbol, va uint6
19031903
return sect, n, va
19041904
}
19051905

1906-
// assign addresses
1907-
func (ctxt *Link) address() {
1906+
// address assigns virtual addresses to all segments and sections and
1907+
// returns all segments in file order.
1908+
func (ctxt *Link) address() []*sym.Segment {
1909+
var order []*sym.Segment // Layout order
1910+
19081911
va := uint64(*FlagTextAddr)
1912+
order = append(order, &Segtext)
19091913
Segtext.Rwx = 05
19101914
Segtext.Vaddr = va
1911-
Segtext.Fileoff = uint64(HEADR)
19121915
for _, s := range Segtext.Sections {
19131916
va = uint64(Rnd(int64(va), int64(s.Align)))
19141917
s.Vaddr = va
19151918
va += s.Length
19161919
}
19171920

19181921
Segtext.Length = va - uint64(*FlagTextAddr)
1919-
Segtext.Filelen = Segtext.Length
19201922
if ctxt.HeadType == objabi.Hnacl {
19211923
va += 32 // room for the "halt sled"
19221924
}
@@ -1937,52 +1939,38 @@ func (ctxt *Link) address() {
19371939
// writable even for this short period.
19381940
va = uint64(Rnd(int64(va), int64(*FlagRound)))
19391941

1942+
order = append(order, &Segrodata)
19401943
Segrodata.Rwx = 04
19411944
Segrodata.Vaddr = va
1942-
Segrodata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
1943-
Segrodata.Filelen = 0
1944-
if ctxt.HeadType == objabi.Hwindows {
1945-
Segrodata.Fileoff = Segtext.Fileoff + uint64(Rnd(int64(Segtext.Length), PEFILEALIGN))
1946-
}
19471945
for _, s := range Segrodata.Sections {
19481946
va = uint64(Rnd(int64(va), int64(s.Align)))
19491947
s.Vaddr = va
19501948
va += s.Length
19511949
}
19521950

19531951
Segrodata.Length = va - Segrodata.Vaddr
1954-
Segrodata.Filelen = Segrodata.Length
19551952
}
19561953
if len(Segrelrodata.Sections) > 0 {
19571954
// align to page boundary so as not to mix
19581955
// rodata, rel-ro data, and executable text.
19591956
va = uint64(Rnd(int64(va), int64(*FlagRound)))
19601957

1958+
order = append(order, &Segrelrodata)
19611959
Segrelrodata.Rwx = 06
19621960
Segrelrodata.Vaddr = va
1963-
Segrelrodata.Fileoff = va - Segrodata.Vaddr + Segrodata.Fileoff
1964-
Segrelrodata.Filelen = 0
19651961
for _, s := range Segrelrodata.Sections {
19661962
va = uint64(Rnd(int64(va), int64(s.Align)))
19671963
s.Vaddr = va
19681964
va += s.Length
19691965
}
19701966

19711967
Segrelrodata.Length = va - Segrelrodata.Vaddr
1972-
Segrelrodata.Filelen = Segrelrodata.Length
19731968
}
19741969

19751970
va = uint64(Rnd(int64(va), int64(*FlagRound)))
1971+
order = append(order, &Segdata)
19761972
Segdata.Rwx = 06
19771973
Segdata.Vaddr = va
1978-
Segdata.Fileoff = va - Segtext.Vaddr + Segtext.Fileoff
1979-
Segdata.Filelen = 0
1980-
if ctxt.HeadType == objabi.Hwindows {
1981-
Segdata.Fileoff = Segrodata.Fileoff + uint64(Rnd(int64(Segrodata.Length), PEFILEALIGN))
1982-
}
1983-
if ctxt.HeadType == objabi.Hplan9 {
1984-
Segdata.Fileoff = Segtext.Fileoff + Segtext.Filelen
1985-
}
19861974
var data *sym.Section
19871975
var noptr *sym.Section
19881976
var bss *sym.Section
@@ -2012,16 +2000,14 @@ func (ctxt *Link) address() {
20122000
}
20132001
}
20142002

2003+
// Assign Segdata's Filelen omitting the BSS. We do this here
2004+
// simply because right now we know where the BSS starts.
20152005
Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
20162006

20172007
va = uint64(Rnd(int64(va), int64(*FlagRound)))
2008+
order = append(order, &Segdwarf)
20182009
Segdwarf.Rwx = 06
20192010
Segdwarf.Vaddr = va
2020-
Segdwarf.Fileoff = Segdata.Fileoff + uint64(Rnd(int64(Segdata.Filelen), int64(*FlagRound)))
2021-
Segdwarf.Filelen = 0
2022-
if ctxt.HeadType == objabi.Hwindows {
2023-
Segdwarf.Fileoff = Segdata.Fileoff + uint64(Rnd(int64(Segdata.Filelen), PEFILEALIGN))
2024-
}
20252011
for i, s := range Segdwarf.Sections {
20262012
vlen := int64(s.Length)
20272013
if i+1 < len(Segdwarf.Sections) {
@@ -2035,8 +2021,6 @@ func (ctxt *Link) address() {
20352021
Segdwarf.Length = va - Segdwarf.Vaddr
20362022
}
20372023

2038-
Segdwarf.Filelen = va - Segdwarf.Vaddr
2039-
20402024
var (
20412025
text = Segtext.Sections[0]
20422026
rodata = ctxt.Syms.Lookup("runtime.rodata", 0).Sect
@@ -2123,6 +2107,34 @@ func (ctxt *Link) address() {
21232107
ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
21242108
ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
21252109
ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
2110+
2111+
return order
2112+
}
2113+
2114+
// layout assigns file offsets and lengths to the segments in order.
2115+
func (ctxt *Link) layout(order []*sym.Segment) {
2116+
var prev *sym.Segment
2117+
for _, seg := range order {
2118+
if prev == nil {
2119+
seg.Fileoff = uint64(HEADR)
2120+
} else {
2121+
switch ctxt.HeadType {
2122+
default:
2123+
seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), int64(*FlagRound)))
2124+
case objabi.Hwindows:
2125+
seg.Fileoff = prev.Fileoff + uint64(Rnd(int64(prev.Filelen), PEFILEALIGN))
2126+
case objabi.Hplan9:
2127+
seg.Fileoff = prev.Fileoff + prev.Filelen
2128+
}
2129+
}
2130+
if seg != &Segdata {
2131+
// Link.address already set Segdata.Filelen to
2132+
// account for BSS.
2133+
seg.Filelen = seg.Length
2134+
}
2135+
prev = seg
2136+
}
2137+
21262138
}
21272139

21282140
// add a trampoline with symbol s (to be laid down after the current function)

src/cmd/link/internal/ld/main.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,9 @@ func Main(arch *sys.Arch, theArch Arch) {
224224
ctxt.typelink()
225225
ctxt.symtab()
226226
ctxt.dodata()
227-
ctxt.address()
227+
order := ctxt.address()
228228
ctxt.reloc()
229+
ctxt.layout(order)
229230
thearch.Asmb(ctxt)
230231
ctxt.undef()
231232
ctxt.hostlink()

0 commit comments

Comments
 (0)