mirror of
https://github.com/golang/go
synced 2024-10-05 01:21:21 -06:00
cmd/link: process data symbols with slices
First (and largest single) step to switching cmd/link from linked lists of symbols to slices. Sort sections independently and concurrently. This reduces jujud link times on linux/amd64 by ~4%. Updates #15374 Change-Id: I452bc8f33081039468636502fe3c1cc8d6ed9efa Reviewed-on: https://go-review.googlesource.com/22205 Reviewed-by: Michael Hudson-Doyle <michael.hudson@canonical.com>
This commit is contained in:
parent
cda0aa1680
commit
ed41054b6d
@ -32,7 +32,6 @@
|
|||||||
package ld
|
package ld
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"cmd/internal/gcprog"
|
"cmd/internal/gcprog"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
@ -42,6 +41,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Symgrow(ctxt *Link, s *LSym, siz int64) {
|
func Symgrow(ctxt *Link, s *LSym, siz int64) {
|
||||||
@ -651,8 +651,8 @@ func reloc() {
|
|||||||
for s := Ctxt.Textp; s != nil; s = s.Next {
|
for s := Ctxt.Textp; s != nil; s = s.Next {
|
||||||
relocsym(s)
|
relocsym(s)
|
||||||
}
|
}
|
||||||
for s := datap; s != nil; s = s.Next {
|
for _, sym := range datap {
|
||||||
relocsym(s)
|
relocsym(sym)
|
||||||
}
|
}
|
||||||
for s := dwarfp; s != nil; s = s.Next {
|
for s := dwarfp; s != nil; s = s.Next {
|
||||||
relocsym(s)
|
relocsym(s)
|
||||||
@ -713,7 +713,7 @@ func dynrelocsym(s *LSym) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dynreloc() {
|
func dynreloc(data *[obj.SXREF][]*LSym) {
|
||||||
// -d suppresses dynamic loader format, so we may as well not
|
// -d suppresses dynamic loader format, so we may as well not
|
||||||
// compute these sections or mark their symbols as reachable.
|
// compute these sections or mark their symbols as reachable.
|
||||||
if Debug['d'] != 0 && HEADTYPE != obj.Hwindows {
|
if Debug['d'] != 0 && HEADTYPE != obj.Hwindows {
|
||||||
@ -727,8 +727,10 @@ func dynreloc() {
|
|||||||
for s := Ctxt.Textp; s != nil; s = s.Next {
|
for s := Ctxt.Textp; s != nil; s = s.Next {
|
||||||
dynrelocsym(s)
|
dynrelocsym(s)
|
||||||
}
|
}
|
||||||
for s := datap; s != nil; s = s.Next {
|
for _, syms := range data {
|
||||||
dynrelocsym(s)
|
for _, sym := range syms {
|
||||||
|
dynrelocsym(sym)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if Iself {
|
if Iself {
|
||||||
elfdynhash()
|
elfdynhash()
|
||||||
@ -849,27 +851,77 @@ func Codeblk(addr int64, size int64) {
|
|||||||
Bso.Flush()
|
Bso.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blkSlice is a variant of blk that processes slices.
|
||||||
|
// After text symbols are converted from a linked list to a slice,
|
||||||
|
// delete blk and give this function its name.
|
||||||
|
func blkSlice(syms []*LSym, addr, size int64) {
|
||||||
|
for i, s := range syms {
|
||||||
|
if s.Type&obj.SSUB == 0 && s.Value >= addr {
|
||||||
|
syms = syms[i:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eaddr := addr + size
|
||||||
|
for _, s := range syms {
|
||||||
|
if s.Type&obj.SSUB != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if s.Value >= eaddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
Ctxt.Cursym = s
|
||||||
|
if s.Value < addr {
|
||||||
|
Diag("phase error: addr=%#x but sym=%#x type=%d", addr, s.Value, s.Type)
|
||||||
|
errorexit()
|
||||||
|
}
|
||||||
|
if addr < s.Value {
|
||||||
|
strnput("", int(s.Value-addr))
|
||||||
|
addr = s.Value
|
||||||
|
}
|
||||||
|
Cwrite(s.P)
|
||||||
|
addr += int64(len(s.P))
|
||||||
|
if addr < s.Value+s.Size {
|
||||||
|
strnput("", int(s.Value+s.Size-addr))
|
||||||
|
addr = s.Value + s.Size
|
||||||
|
}
|
||||||
|
if addr != s.Value+s.Size {
|
||||||
|
Diag("phase error: addr=%#x value+size=%#x", addr, s.Value+s.Size)
|
||||||
|
errorexit()
|
||||||
|
}
|
||||||
|
if s.Value+s.Size >= eaddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if addr < eaddr {
|
||||||
|
strnput("", int(eaddr-addr))
|
||||||
|
}
|
||||||
|
Cflush()
|
||||||
|
}
|
||||||
|
|
||||||
func Datblk(addr int64, size int64) {
|
func Datblk(addr int64, size int64) {
|
||||||
if Debug['a'] != 0 {
|
if Debug['a'] != 0 {
|
||||||
fmt.Fprintf(Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
|
fmt.Fprintf(Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
|
||||||
}
|
}
|
||||||
|
|
||||||
blk(datap, addr, size)
|
blkSlice(datap, addr, size)
|
||||||
|
|
||||||
/* again for printing */
|
/* again for printing */
|
||||||
if Debug['a'] == 0 {
|
if Debug['a'] == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var sym *LSym
|
syms := datap
|
||||||
for sym = datap; sym != nil; sym = sym.Next {
|
for i, sym := range syms {
|
||||||
if sym.Value >= addr {
|
if sym.Value >= addr {
|
||||||
|
syms = syms[i:]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eaddr := addr + size
|
eaddr := addr + size
|
||||||
for ; sym != nil; sym = sym.Next {
|
for _, sym := range syms {
|
||||||
if sym.Value >= eaddr {
|
if sym.Value >= eaddr {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1080,18 +1132,15 @@ func aligndatsize(datsize int64, s *LSym) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// maxalign returns the maximum required alignment for
|
// maxalign returns the maximum required alignment for
|
||||||
// the list of symbols s; the list stops when s->type exceeds type.
|
// the slice of symbols syms
|
||||||
func maxalign(s *LSym, type_ int) int32 {
|
func maxalign(syms []*LSym) int32 {
|
||||||
var align int32
|
var max int32
|
||||||
|
for _, sym := range syms {
|
||||||
max := int32(0)
|
align := symalign(sym)
|
||||||
for ; s != nil && int(s.Type) <= type_; s = s.Next {
|
|
||||||
align = symalign(s)
|
|
||||||
if max < align {
|
if max < align {
|
||||||
max = align
|
max = align
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return max
|
return max
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,41 +1205,24 @@ func (p *GCProg) AddSym(s *LSym) {
|
|||||||
p.w.Append(prog[4:], nptr)
|
p.w.Append(prog[4:], nptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dataSortKey is used to sort a slice of data symbol *LSym pointers.
|
||||||
|
// The sort keys are kept inline to improve cache behaviour while sorting.
|
||||||
type dataSortKey struct {
|
type dataSortKey struct {
|
||||||
// keep sort keys inline to improve cache behaviour while sorting
|
size int64
|
||||||
Type int16
|
name string
|
||||||
Size int64
|
lsym *LSym
|
||||||
Name string
|
|
||||||
|
|
||||||
Lsym *LSym
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type dataSlice []dataSortKey
|
type bySizeAndName []dataSortKey
|
||||||
|
|
||||||
func (d dataSlice) Len() int { return len(d) }
|
func (d bySizeAndName) Len() int { return len(d) }
|
||||||
func (d dataSlice) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
func (d bySizeAndName) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
||||||
func (d dataSlice) Less(i, j int) bool {
|
func (d bySizeAndName) Less(i, j int) bool {
|
||||||
s1, s2 := &d[i], &d[j]
|
s1, s2 := d[i], d[j]
|
||||||
if s1.Type != s2.Type {
|
if s1.size != s2.size {
|
||||||
return s1.Type < s2.Type
|
return s1.size < s2.size
|
||||||
}
|
}
|
||||||
|
return s1.name < s2.name
|
||||||
// For ppc64, we want to interleave the .got and .toc sections
|
|
||||||
// from input files. Both are type SELFGOT, so in that case
|
|
||||||
// fall through to the name comparison (conveniently, .got
|
|
||||||
// sorts before .toc).
|
|
||||||
if s1.Type != obj.SELFGOT && s1.Size != s2.Size {
|
|
||||||
return s1.Size < s2.Size
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort typelinks by the string field.
|
|
||||||
if strings.HasPrefix(s1.Name, "go.typelink.") && strings.HasPrefix(s2.Name, "go.typelink.") {
|
|
||||||
s1n := decodetype_string(s1.Lsym.R[0].Sym)
|
|
||||||
s2n := decodetype_string(s2.Lsym.R[0].Sym)
|
|
||||||
return bytes.Compare(s1n, s2n) < 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return s1.Name < s2.Name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func growdatsize(datsizep *int64, s *LSym) {
|
func growdatsize(datsizep *int64, s *LSym) {
|
||||||
@ -1207,38 +1239,17 @@ func growdatsize(datsizep *int64, s *LSym) {
|
|||||||
*datsizep = datsize + s.Size
|
*datsizep = datsize + s.Size
|
||||||
}
|
}
|
||||||
|
|
||||||
func list2Slice(head *LSym) dataSlice {
|
func list2slice(s *LSym) []*LSym {
|
||||||
n := 0
|
var syms []*LSym
|
||||||
for s := datap; s != nil; s = s.Next {
|
for ; s != nil; s = s.Next {
|
||||||
n++
|
syms = append(syms, s)
|
||||||
}
|
}
|
||||||
slice := make(dataSlice, n)
|
return syms
|
||||||
i := 0
|
|
||||||
for s := datap; s != nil; s = s.Next {
|
|
||||||
k := &slice[i]
|
|
||||||
k.Type = s.Type
|
|
||||||
k.Size = s.Size
|
|
||||||
k.Name = s.Name
|
|
||||||
k.Lsym = s
|
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return slice
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func slice2List(d dataSlice) *LSym {
|
// datap is a collection of reachable data symbols in address order.
|
||||||
for i := 0; i < len(d)-1; i++ {
|
// Generated by dodata.
|
||||||
d[i].Lsym.Next = d[i+1].Lsym
|
var datap []*LSym
|
||||||
}
|
|
||||||
d[len(d)-1].Lsym.Next = nil
|
|
||||||
return d[0].Lsym
|
|
||||||
}
|
|
||||||
|
|
||||||
func dataSort(head *LSym) *LSym {
|
|
||||||
d := list2Slice(head)
|
|
||||||
sort.Sort(d)
|
|
||||||
return slice2List(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
func dodata() {
|
func dodata() {
|
||||||
if Debug['v'] != 0 {
|
if Debug['v'] != 0 {
|
||||||
@ -1246,135 +1257,103 @@ func dodata() {
|
|||||||
}
|
}
|
||||||
Bso.Flush()
|
Bso.Flush()
|
||||||
|
|
||||||
var last *LSym
|
// Collect data symbols by type into data.
|
||||||
datap = nil
|
var data [obj.SXREF][]*LSym
|
||||||
|
|
||||||
for _, s := range Ctxt.Allsym {
|
for _, s := range Ctxt.Allsym {
|
||||||
if !s.Attr.Reachable() || s.Attr.Special() {
|
if !s.Attr.Reachable() || s.Attr.Special() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if obj.STEXT < s.Type && s.Type < obj.SXREF {
|
if s.Type <= obj.STEXT || s.Type >= obj.SXREF {
|
||||||
if s.Attr.OnList() {
|
continue
|
||||||
log.Fatalf("symbol %s listed multiple times", s.Name)
|
|
||||||
}
|
|
||||||
s.Attr |= AttrOnList
|
|
||||||
if last == nil {
|
|
||||||
datap = s
|
|
||||||
} else {
|
|
||||||
last.Next = s
|
|
||||||
}
|
|
||||||
s.Next = nil
|
|
||||||
last = s
|
|
||||||
}
|
}
|
||||||
|
data[s.Type] = append(data[s.Type], s)
|
||||||
}
|
}
|
||||||
|
|
||||||
for s := datap; s != nil; s = s.Next {
|
// Now that we have the data symbols, but before we start
|
||||||
if int64(len(s.P)) > s.Size {
|
// to assign addresses, record all the necessary
|
||||||
Diag("%s: initialize bounds (%d < %d)", s.Name, s.Size, len(s.P))
|
// dynamic relocations. These will grow the relocation
|
||||||
}
|
// symbol, which is itself data.
|
||||||
}
|
//
|
||||||
|
// On darwin, we need the symbol table numbers for dynreloc.
|
||||||
/*
|
|
||||||
* now that we have the datap list, but before we start
|
|
||||||
* to assign addresses, record all the necessary
|
|
||||||
* dynamic relocations. these will grow the relocation
|
|
||||||
* symbol, which is itself data.
|
|
||||||
*
|
|
||||||
* on darwin, we need the symbol table numbers for dynreloc.
|
|
||||||
*/
|
|
||||||
if HEADTYPE == obj.Hdarwin {
|
if HEADTYPE == obj.Hdarwin {
|
||||||
machosymorder()
|
machosymorder()
|
||||||
}
|
}
|
||||||
dynreloc()
|
dynreloc(&data)
|
||||||
|
|
||||||
/* some symbols may no longer belong in datap (Mach-O) */
|
|
||||||
var l **LSym
|
|
||||||
var s *LSym
|
|
||||||
for l = &datap; ; {
|
|
||||||
s = *l
|
|
||||||
if s == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.Type <= obj.STEXT || obj.SXREF <= s.Type {
|
|
||||||
*l = s.Next
|
|
||||||
} else {
|
|
||||||
l = &s.Next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*l = nil
|
|
||||||
|
|
||||||
if UseRelro() {
|
if UseRelro() {
|
||||||
// "read only" data with relocations needs to go in its own section
|
// "read only" data with relocations needs to go in its own section
|
||||||
// when building a shared library. We do this by boosting objects of
|
// when building a shared library. We do this by boosting objects of
|
||||||
// type SXXX with relocations to type SXXXRELRO.
|
// type SXXX with relocations to type SXXXRELRO.
|
||||||
for s := datap; s != nil; s = s.Next {
|
for symnro := int16(obj.STYPE); symnro < obj.STYPERELRO; symnro++ {
|
||||||
if (s.Type >= obj.STYPE && s.Type <= obj.SFUNCTAB && len(s.R) > 0) || s.Type == obj.STYPE || s.Type == obj.SGOSTRINGHDR {
|
symnrelro := symnro + obj.STYPERELRO - obj.STYPE
|
||||||
s.Type += (obj.STYPERELRO - obj.STYPE)
|
|
||||||
|
ro := []*LSym{}
|
||||||
|
relro := data[symnrelro]
|
||||||
|
|
||||||
|
for _, s := range data[symnro] {
|
||||||
|
isRelro := len(s.R) > 0
|
||||||
|
switch s.Type {
|
||||||
|
case obj.STYPE, obj.SGOSTRINGHDR, obj.STYPERELRO, obj.SGOSTRINGHDRRELRO:
|
||||||
|
// Symbols are not sorted yet, so it is possible
|
||||||
|
// that an Outer symbol has been changed to a
|
||||||
|
// relro Type before it reaches here.
|
||||||
|
isRelro = true
|
||||||
|
}
|
||||||
|
if isRelro {
|
||||||
|
s.Type = symnrelro
|
||||||
if s.Outer != nil {
|
if s.Outer != nil {
|
||||||
s.Outer.Type = s.Type
|
s.Outer.Type = s.Type
|
||||||
}
|
}
|
||||||
|
relro = append(relro, s)
|
||||||
|
} else {
|
||||||
|
ro = append(ro, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that we haven't made two symbols with the same .Outer into
|
// Check that we haven't made two symbols with the same .Outer into
|
||||||
// different types (because references two symbols with non-nil Outer
|
// different types (because references two symbols with non-nil Outer
|
||||||
// become references to the outer symbol + offset it's vital that the
|
// become references to the outer symbol + offset it's vital that the
|
||||||
// symbol and the outer end up in the same section).
|
// symbol and the outer end up in the same section).
|
||||||
for s := datap; s != nil; s = s.Next {
|
for _, s := range relro {
|
||||||
if s.Outer != nil && s.Outer.Type != s.Type {
|
if s.Outer != nil && s.Outer.Type != s.Type {
|
||||||
Diag("inconsistent types for %s and its Outer %s (%d != %d)",
|
Diag("inconsistent types for %s and its Outer %s (%d != %d)",
|
||||||
s.Name, s.Outer.Name, s.Type, s.Outer.Type)
|
s.Name, s.Outer.Name, s.Type, s.Outer.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
data[symnro] = ro
|
||||||
|
data[symnrelro] = relro
|
||||||
datap = dataSort(datap)
|
|
||||||
|
|
||||||
if Iself {
|
|
||||||
// Make .rela and .rela.plt contiguous, the ELF ABI requires this
|
|
||||||
// and Solaris actually cares.
|
|
||||||
var relplt *LSym
|
|
||||||
for l = &datap; *l != nil; l = &(*l).Next {
|
|
||||||
if (*l).Name == ".rel.plt" || (*l).Name == ".rela.plt" {
|
|
||||||
relplt = (*l)
|
|
||||||
*l = (*l).Next
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if relplt != nil {
|
|
||||||
for s = datap; s != nil; s = s.Next {
|
|
||||||
if s.Name == ".rel" || s.Name == ".rela" {
|
|
||||||
relplt.Next = s.Next
|
|
||||||
s.Next = relplt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Sort symbols.
|
||||||
* allocate sections. list is sorted by type,
|
var wg sync.WaitGroup
|
||||||
* so we can just walk it for each piece we want to emit.
|
for symn := range data {
|
||||||
* segdata is processed before segtext, because we need
|
symn := symn
|
||||||
* to see all symbols in the .data and .bss sections in order
|
wg.Add(1)
|
||||||
* to generate garbage collection information.
|
go func() {
|
||||||
*/
|
data[symn] = dodataSect(symn, data[symn])
|
||||||
|
wg.Done()
|
||||||
/* begin segdata */
|
}()
|
||||||
|
|
||||||
/* skip symbols belonging to segtext */
|
|
||||||
s = datap
|
|
||||||
|
|
||||||
for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
|
|
||||||
}
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
/* writable ELF sections */
|
// Allocate sections.
|
||||||
|
// Data is processed before segtext, because we need
|
||||||
|
// to see all symbols in the .data and .bss sections in order
|
||||||
|
// to generate garbage collection information.
|
||||||
datsize := int64(0)
|
datsize := int64(0)
|
||||||
|
|
||||||
var sect *Section
|
// Writable sections.
|
||||||
for ; s != nil && s.Type < obj.SELFGOT; s = s.Next {
|
writableSects := []int{
|
||||||
sect = addsection(&Segdata, s.Name, 06)
|
obj.SELFSECT,
|
||||||
|
obj.SMACHO,
|
||||||
|
obj.SMACHOGOT,
|
||||||
|
obj.SWINDOWS,
|
||||||
|
}
|
||||||
|
for _, symn := range writableSects {
|
||||||
|
for _, s := range data[symn] {
|
||||||
|
sect := addsection(&Segdata, s.Name, 06)
|
||||||
sect.Align = symalign(s)
|
sect.Align = symalign(s)
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
@ -1384,15 +1363,16 @@ func dodata() {
|
|||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* .got (and .toc on ppc64) */
|
// .got (and .toc on ppc64)
|
||||||
if s.Type == obj.SELFGOT {
|
if len(data[obj.SELFGOT]) > 0 {
|
||||||
sect := addsection(&Segdata, ".got", 06)
|
sect := addsection(&Segdata, ".got", 06)
|
||||||
sect.Align = maxalign(s, obj.SELFGOT)
|
sect.Align = maxalign(data[obj.SELFGOT])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
var toc *LSym
|
var toc *LSym
|
||||||
for ; s != nil && s.Type == obj.SELFGOT; s = s.Next {
|
for _, s := range data[obj.SELFGOT] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SDATA
|
s.Type = obj.SDATA
|
||||||
@ -1400,7 +1380,6 @@ func dodata() {
|
|||||||
|
|
||||||
// Resolve .TOC. symbol for this object file (ppc64)
|
// Resolve .TOC. symbol for this object file (ppc64)
|
||||||
toc = Linkrlookup(Ctxt, ".TOC.", int(s.Version))
|
toc = Linkrlookup(Ctxt, ".TOC.", int(s.Version))
|
||||||
|
|
||||||
if toc != nil {
|
if toc != nil {
|
||||||
toc.Sect = sect
|
toc.Sect = sect
|
||||||
toc.Outer = s
|
toc.Outer = s
|
||||||
@ -1412,26 +1391,24 @@ func dodata() {
|
|||||||
|
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pointer-free data */
|
/* pointer-free data */
|
||||||
sect = addsection(&Segdata, ".noptrdata", 06)
|
sect := addsection(&Segdata, ".noptrdata", 06)
|
||||||
|
|
||||||
sect.Align = maxalign(s, obj.SINITARR-1)
|
sect.Align = maxalign(data[obj.SNOPTRDATA])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.noptrdata", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.noptrdata", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.enoptrdata", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.enoptrdata", 0).Sect = sect
|
||||||
for ; s != nil && s.Type < obj.SINITARR; s = s.Next {
|
for _, s := range data[obj.SNOPTRDATA] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SDATA
|
s.Type = obj.SDATA
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
|
||||||
hasinitarr := Linkshared
|
hasinitarr := Linkshared
|
||||||
@ -1441,37 +1418,30 @@ func dodata() {
|
|||||||
case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared:
|
case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared:
|
||||||
hasinitarr = true
|
hasinitarr = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasinitarr {
|
if hasinitarr {
|
||||||
sect := addsection(&Segdata, ".init_array", 06)
|
sect := addsection(&Segdata, ".init_array", 06)
|
||||||
sect.Align = maxalign(s, obj.SINITARR)
|
sect.Align = maxalign(data[obj.SINITARR])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
for ; s != nil && s.Type == obj.SINITARR; s = s.Next {
|
for _, s := range data[obj.SINITARR] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
}
|
}
|
||||||
|
|
||||||
/* data */
|
/* data */
|
||||||
sect = addsection(&Segdata, ".data", 06)
|
sect = addsection(&Segdata, ".data", 06)
|
||||||
sect.Align = maxalign(s, obj.SBSS-1)
|
sect.Align = maxalign(data[obj.SDATA])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.data", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.data", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.edata", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.edata", 0).Sect = sect
|
||||||
var gc GCProg
|
var gc GCProg
|
||||||
gc.Init("runtime.gcdata")
|
gc.Init("runtime.gcdata")
|
||||||
for ; s != nil && s.Type < obj.SBSS; s = s.Next {
|
for _, s := range data[obj.SDATA] {
|
||||||
if s.Type == obj.SINITARR {
|
|
||||||
Ctxt.Cursym = s
|
|
||||||
Diag("unexpected symbol type %d", s.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SDATA
|
s.Type = obj.SDATA
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
@ -1484,14 +1454,14 @@ func dodata() {
|
|||||||
|
|
||||||
/* bss */
|
/* bss */
|
||||||
sect = addsection(&Segdata, ".bss", 06)
|
sect = addsection(&Segdata, ".bss", 06)
|
||||||
sect.Align = maxalign(s, obj.SNOPTRBSS-1)
|
sect.Align = maxalign(data[obj.SBSS])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.bss", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.bss", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect
|
||||||
gc = GCProg{}
|
gc = GCProg{}
|
||||||
gc.Init("runtime.gcbss")
|
gc.Init("runtime.gcbss")
|
||||||
for ; s != nil && s.Type < obj.SNOPTRBSS; s = s.Next {
|
for _, s := range data[obj.SBSS] {
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
@ -1504,12 +1474,12 @@ func dodata() {
|
|||||||
/* pointer-free bss */
|
/* pointer-free bss */
|
||||||
sect = addsection(&Segdata, ".noptrbss", 06)
|
sect = addsection(&Segdata, ".noptrbss", 06)
|
||||||
|
|
||||||
sect.Align = maxalign(s, obj.SNOPTRBSS)
|
sect.Align = maxalign(data[obj.SNOPTRBSS])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.noptrbss", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.noptrbss", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.enoptrbss", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.enoptrbss", 0).Sect = sect
|
||||||
for ; s != nil && s.Type == obj.SNOPTRBSS; s = s.Next {
|
for _, s := range data[obj.SNOPTRBSS] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
@ -1519,22 +1489,21 @@ func dodata() {
|
|||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
Linklookup(Ctxt, "runtime.end", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.end", 0).Sect = sect
|
||||||
|
|
||||||
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
|
// The compiler uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
|
||||||
if datsize != int64(uint32(datsize)) {
|
if datsize != int64(uint32(datsize)) {
|
||||||
Diag("data or bss segment too large")
|
Diag("data or bss segment too large")
|
||||||
}
|
}
|
||||||
|
|
||||||
if s != nil && s.Type == obj.STLSBSS {
|
if len(data[obj.STLSBSS]) > 0 {
|
||||||
|
var sect *Section
|
||||||
if Iself && (Linkmode == LinkExternal || Debug['d'] == 0) && HEADTYPE != obj.Hopenbsd {
|
if Iself && (Linkmode == LinkExternal || Debug['d'] == 0) && HEADTYPE != obj.Hopenbsd {
|
||||||
sect = addsection(&Segdata, ".tbss", 06)
|
sect = addsection(&Segdata, ".tbss", 06)
|
||||||
sect.Align = int32(SysArch.PtrSize)
|
sect.Align = int32(SysArch.PtrSize)
|
||||||
sect.Vaddr = 0
|
sect.Vaddr = 0
|
||||||
} else {
|
|
||||||
sect = nil
|
|
||||||
}
|
}
|
||||||
datsize = 0
|
datsize = 0
|
||||||
|
|
||||||
for ; s != nil && s.Type == obj.STLSBSS; s = s.Next {
|
for _, s := range data[obj.STLSBSS] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Value = datsize
|
s.Value = datsize
|
||||||
@ -1546,11 +1515,6 @@ func dodata() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s != nil {
|
|
||||||
Ctxt.Cursym = nil
|
|
||||||
Diag("unexpected symbol type %d for %s", s.Type, s.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We finished data, begin read-only data.
|
* We finished data, begin read-only data.
|
||||||
* Not all systems support a separate read-only non-executable data section.
|
* Not all systems support a separate read-only non-executable data section.
|
||||||
@ -1568,13 +1532,14 @@ func dodata() {
|
|||||||
segro = &Segtext
|
segro = &Segtext
|
||||||
}
|
}
|
||||||
|
|
||||||
s = datap
|
|
||||||
|
|
||||||
datsize = 0
|
datsize = 0
|
||||||
|
|
||||||
/* read-only executable ELF, Mach-O sections */
|
/* read-only executable ELF, Mach-O sections */
|
||||||
for ; s != nil && s.Type < obj.STYPE; s = s.Next {
|
if len(data[obj.STEXT]) != 0 {
|
||||||
sect = addsection(&Segtext, s.Name, 04)
|
Diag("dodata found an STEXT symbol: %s", data[obj.STEXT][0].Name)
|
||||||
|
}
|
||||||
|
for _, s := range data[obj.SELFRXSECT] {
|
||||||
|
sect := addsection(&Segtext, s.Name, 04)
|
||||||
sect.Align = symalign(s)
|
sect.Align = symalign(s)
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
@ -1588,8 +1553,6 @@ func dodata() {
|
|||||||
/* read-only data */
|
/* read-only data */
|
||||||
sect = addsection(segro, ".rodata", 04)
|
sect = addsection(segro, ".rodata", 04)
|
||||||
|
|
||||||
sect.Align = maxalign(s, obj.STYPERELRO-1)
|
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
|
||||||
sect.Vaddr = 0
|
sect.Vaddr = 0
|
||||||
Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect
|
||||||
@ -1597,14 +1560,32 @@ func dodata() {
|
|||||||
Linklookup(Ctxt, "runtime.types", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.types", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect
|
||||||
}
|
}
|
||||||
for ; s != nil && s.Type < obj.STYPERELRO; s = s.Next {
|
roSects := []int{
|
||||||
|
obj.STYPE,
|
||||||
|
obj.SSTRING,
|
||||||
|
obj.SGOSTRING,
|
||||||
|
obj.SGOSTRINGHDR,
|
||||||
|
obj.SGOFUNC,
|
||||||
|
obj.SGCBITS,
|
||||||
|
obj.SRODATA,
|
||||||
|
obj.SFUNCTAB,
|
||||||
|
}
|
||||||
|
for _, symn := range roSects {
|
||||||
|
align := maxalign(data[symn])
|
||||||
|
if sect.Align < align {
|
||||||
|
sect.Align = align
|
||||||
|
}
|
||||||
|
}
|
||||||
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
|
for _, symn := range roSects {
|
||||||
|
for _, s := range data[symn] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SRODATA
|
s.Type = obj.SRODATA
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
|
||||||
// There is some data that are conceptually read-only but are written to by
|
// There is some data that are conceptually read-only but are written to by
|
||||||
@ -1626,12 +1607,28 @@ func dodata() {
|
|||||||
/* data only written by relocations */
|
/* data only written by relocations */
|
||||||
sect = addsection(segro, ".data.rel.ro", 06)
|
sect = addsection(segro, ".data.rel.ro", 06)
|
||||||
|
|
||||||
sect.Align = maxalign(s, obj.STYPELINK-1)
|
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
|
||||||
sect.Vaddr = 0
|
sect.Vaddr = 0
|
||||||
Linklookup(Ctxt, "runtime.types", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.types", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect
|
||||||
for ; s != nil && s.Type < obj.STYPELINK; s = s.Next {
|
relroSects := []int{
|
||||||
|
obj.STYPERELRO,
|
||||||
|
obj.SSTRINGRELRO,
|
||||||
|
obj.SGOSTRINGRELRO,
|
||||||
|
obj.SGOSTRINGHDRRELRO,
|
||||||
|
obj.SGOFUNCRELRO,
|
||||||
|
obj.SGCBITSRELRO,
|
||||||
|
obj.SRODATARELRO,
|
||||||
|
obj.SFUNCTABRELRO,
|
||||||
|
}
|
||||||
|
for _, symn := range relroSects {
|
||||||
|
align := maxalign(data[symn])
|
||||||
|
if sect.Align < align {
|
||||||
|
sect.Align = align
|
||||||
|
}
|
||||||
|
}
|
||||||
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
|
for _, symn := range relroSects {
|
||||||
|
for _, s := range data[symn] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect {
|
if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect {
|
||||||
Diag("s.Outer (%s) in different section from s (%s)", s.Outer.Name, s.Name)
|
Diag("s.Outer (%s) in different section from s (%s)", s.Outer.Name, s.Name)
|
||||||
@ -1641,6 +1638,7 @@ func dodata() {
|
|||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
|
||||||
@ -1648,78 +1646,85 @@ func dodata() {
|
|||||||
|
|
||||||
/* typelink */
|
/* typelink */
|
||||||
sect = addsection(segro, relro_prefix+".typelink", relro_perms)
|
sect = addsection(segro, relro_prefix+".typelink", relro_perms)
|
||||||
|
sect.Align = maxalign(data[obj.STYPELINK])
|
||||||
sect.Align = maxalign(s, obj.STYPELINK)
|
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.typelink", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.typelink", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.etypelink", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.etypelink", 0).Sect = sect
|
||||||
for ; s != nil && s.Type == obj.STYPELINK; s = s.Next {
|
for _, s := range data[obj.STYPELINK] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SRODATA
|
s.Type = obj.SRODATA
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
|
||||||
/* itablink */
|
/* itablink */
|
||||||
sect = addsection(segro, relro_prefix+".itablink", relro_perms)
|
sect = addsection(segro, relro_prefix+".itablink", relro_perms)
|
||||||
|
|
||||||
sect.Align = maxalign(s, obj.SITABLINK)
|
sect.Align = maxalign(data[obj.SITABLINK])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.itablink", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.itablink", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.eitablink", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.eitablink", 0).Sect = sect
|
||||||
for ; s != nil && s.Type == obj.SITABLINK; s = s.Next {
|
for _, s := range data[obj.SITABLINK] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SRODATA
|
s.Type = obj.SRODATA
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
|
||||||
/* gosymtab */
|
/* gosymtab */
|
||||||
sect = addsection(segro, relro_prefix+".gosymtab", relro_perms)
|
sect = addsection(segro, relro_prefix+".gosymtab", relro_perms)
|
||||||
|
|
||||||
sect.Align = maxalign(s, obj.SPCLNTAB-1)
|
sect.Align = maxalign(data[obj.SSYMTAB])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.symtab", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.symtab", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.esymtab", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.esymtab", 0).Sect = sect
|
||||||
for ; s != nil && s.Type < obj.SPCLNTAB; s = s.Next {
|
for _, s := range data[obj.SSYMTAB] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SRODATA
|
s.Type = obj.SRODATA
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
|
||||||
/* gopclntab */
|
/* gopclntab */
|
||||||
sect = addsection(segro, relro_prefix+".gopclntab", relro_perms)
|
sect = addsection(segro, relro_prefix+".gopclntab", relro_perms)
|
||||||
|
|
||||||
sect.Align = maxalign(s, obj.SELFROSECT-1)
|
sect.Align = maxalign(data[obj.SPCLNTAB])
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
sect.Vaddr = uint64(datsize)
|
sect.Vaddr = uint64(datsize)
|
||||||
Linklookup(Ctxt, "runtime.pclntab", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.pclntab", 0).Sect = sect
|
||||||
Linklookup(Ctxt, "runtime.epclntab", 0).Sect = sect
|
Linklookup(Ctxt, "runtime.epclntab", 0).Sect = sect
|
||||||
for ; s != nil && s.Type < obj.SELFROSECT; s = s.Next {
|
for _, s := range data[obj.SPCLNTAB] {
|
||||||
datsize = aligndatsize(datsize, s)
|
datsize = aligndatsize(datsize, s)
|
||||||
s.Sect = sect
|
s.Sect = sect
|
||||||
s.Type = obj.SRODATA
|
s.Type = obj.SRODATA
|
||||||
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
s.Value = int64(uint64(datsize) - sect.Vaddr)
|
||||||
growdatsize(&datsize, s)
|
growdatsize(&datsize, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Length = uint64(datsize) - sect.Vaddr
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
|
||||||
/* read-only ELF, Mach-O sections */
|
/* read-only ELF, Mach-O sections */
|
||||||
for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
|
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)
|
||||||
|
growdatsize(&datsize, s)
|
||||||
|
sect.Length = uint64(datsize) - sect.Vaddr
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range data[obj.SMACHOPLT] {
|
||||||
sect = addsection(segro, s.Name, 04)
|
sect = addsection(segro, s.Name, 04)
|
||||||
sect.Align = symalign(s)
|
sect.Align = symalign(s)
|
||||||
datsize = Rnd(datsize, int64(sect.Align))
|
datsize = Rnd(datsize, int64(sect.Align))
|
||||||
@ -1736,8 +1741,13 @@ func dodata() {
|
|||||||
Diag("read-only data segment too large")
|
Diag("read-only data segment too large")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for symn := obj.SELFRXSECT; symn < obj.SXREF; symn++ {
|
||||||
|
datap = append(datap, data[symn]...)
|
||||||
|
}
|
||||||
|
|
||||||
dwarfgeneratedebugsyms()
|
dwarfgeneratedebugsyms()
|
||||||
|
|
||||||
|
var s *LSym
|
||||||
for s = dwarfp; s != nil && s.Type == obj.SDWARFSECT; s = s.Next {
|
for s = dwarfp; s != nil && s.Type == obj.SDWARFSECT; s = s.Next {
|
||||||
sect = addsection(&Segdwarf, s.Name, 04)
|
sect = addsection(&Segdwarf, s.Name, 04)
|
||||||
sect.Align = 1
|
sect.Align = 1
|
||||||
@ -1791,6 +1801,84 @@ func dodata() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dodataSect(symn int, syms []*LSym) []*LSym {
|
||||||
|
if HEADTYPE == obj.Hdarwin {
|
||||||
|
// Some symbols may no longer belong in syms
|
||||||
|
// due to movement in machosymorder.
|
||||||
|
newSyms := make([]*LSym, 0, len(syms))
|
||||||
|
for _, s := range syms {
|
||||||
|
if int(s.Type) == symn {
|
||||||
|
newSyms = append(newSyms, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
syms = newSyms
|
||||||
|
}
|
||||||
|
|
||||||
|
symsSort := make([]dataSortKey, len(syms))
|
||||||
|
for i, s := range syms {
|
||||||
|
if s.Attr.OnList() {
|
||||||
|
log.Fatalf("symbol %s listed multiple times", s.Name)
|
||||||
|
}
|
||||||
|
s.Attr |= AttrOnList
|
||||||
|
if int64(len(s.P)) > s.Size {
|
||||||
|
Diag("%s: initialize bounds (%d < %d)", s.Name, s.Size, len(s.P))
|
||||||
|
}
|
||||||
|
|
||||||
|
symsSort[i] = dataSortKey{
|
||||||
|
size: s.Size,
|
||||||
|
name: s.Name,
|
||||||
|
lsym: s,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch s.Type {
|
||||||
|
case obj.SELFGOT:
|
||||||
|
// For ppc64, we want to interleave the .got and .toc sections
|
||||||
|
// from input files. Both are type SELFGOT, so in that case
|
||||||
|
// we skip size comparison and fall through to the name
|
||||||
|
// comparison (conveniently, .got sorts before .toc).
|
||||||
|
symsSort[i].size = 0
|
||||||
|
case obj.STYPELINK:
|
||||||
|
// Sort typelinks by the rtype.string field so the reflect
|
||||||
|
// package can binary search type links.
|
||||||
|
symsSort[i].name = string(decodetype_string(s.R[0].Sym))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(bySizeAndName(symsSort))
|
||||||
|
|
||||||
|
for i, symSort := range symsSort {
|
||||||
|
syms[i] = symSort.lsym
|
||||||
|
}
|
||||||
|
|
||||||
|
if Iself && symn == obj.SELFROSECT {
|
||||||
|
// Make .rela and .rela.plt contiguous, the ELF ABI requires this
|
||||||
|
// and Solaris actually cares.
|
||||||
|
reli, plti := -1, -1
|
||||||
|
for i, s := range syms {
|
||||||
|
switch s.Name {
|
||||||
|
case ".rel.plt", ".rela.plt":
|
||||||
|
plti = i
|
||||||
|
case ".rel", ".rela":
|
||||||
|
reli = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if reli >= 0 && plti >= 0 && plti != reli+1 {
|
||||||
|
newSyms := make([]*LSym, 0, len(syms))
|
||||||
|
plt := syms[plti]
|
||||||
|
newSyms = append(newSyms, syms[:reli+1]...)
|
||||||
|
newSyms = append(newSyms, plt)
|
||||||
|
newSyms = append(newSyms, syms[reli+1:plti]...)
|
||||||
|
newSyms = append(newSyms, syms[plti+1:]...)
|
||||||
|
if len(newSyms) != len(syms) {
|
||||||
|
Diag("plt move failed: len %d/%d", len(newSyms), len(syms))
|
||||||
|
}
|
||||||
|
syms = newSyms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return syms
|
||||||
|
}
|
||||||
|
|
||||||
// Add buildid to beginning of text segment, on non-ELF systems.
|
// Add buildid to beginning of text segment, on non-ELF systems.
|
||||||
// Non-ELF binary formats are not always flexible enough to
|
// Non-ELF binary formats are not always flexible enough to
|
||||||
// give us a place to put the Go build ID. On those systems, we put it
|
// give us a place to put the Go build ID. On those systems, we put it
|
||||||
@ -1816,8 +1904,6 @@ func textbuildid() {
|
|||||||
|
|
||||||
// assign addresses to text
|
// assign addresses to text
|
||||||
func textaddress() {
|
func textaddress() {
|
||||||
var sub *LSym
|
|
||||||
|
|
||||||
addsection(&Segtext, ".text", 05)
|
addsection(&Segtext, ".text", 05)
|
||||||
|
|
||||||
// Assign PCs in text segment.
|
// Assign PCs in text segment.
|
||||||
@ -1844,7 +1930,7 @@ func textaddress() {
|
|||||||
va = uint64(Rnd(int64(va), int64(Funcalign)))
|
va = uint64(Rnd(int64(va), int64(Funcalign)))
|
||||||
}
|
}
|
||||||
sym.Value = 0
|
sym.Value = 0
|
||||||
for sub = sym; sub != nil; sub = sub.Sub {
|
for sub := sym; sub != nil; sub = sub.Sub {
|
||||||
sub.Value += int64(va)
|
sub.Value += int64(va)
|
||||||
}
|
}
|
||||||
if sym.Size == 0 && sym.Sub != nil {
|
if sym.Size == 0 && sym.Sub != nil {
|
||||||
@ -1982,22 +2068,22 @@ func address() {
|
|||||||
symtab := itablink.Next
|
symtab := itablink.Next
|
||||||
pclntab := symtab.Next
|
pclntab := symtab.Next
|
||||||
|
|
||||||
var sub *LSym
|
for _, s := range datap {
|
||||||
for sym := datap; sym != nil; sym = sym.Next {
|
Ctxt.Cursym = s
|
||||||
Ctxt.Cursym = sym
|
if s.Sect != nil {
|
||||||
if sym.Sect != nil {
|
s.Value += int64(s.Sect.Vaddr)
|
||||||
sym.Value += int64(sym.Sect.Vaddr)
|
|
||||||
}
|
}
|
||||||
for sub = sym.Sub; sub != nil; sub = sub.Sub {
|
for sub := s.Sub; sub != nil; sub = sub.Sub {
|
||||||
sub.Value += sym.Value
|
sub.Value += s.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for sym := dwarfp; sym != nil; sym = sym.Next {
|
for sym := dwarfp; sym != nil; sym = sym.Next {
|
||||||
Ctxt.Cursym = sym
|
Ctxt.Cursym = sym
|
||||||
if sym.Sect != nil {
|
if sym.Sect != nil {
|
||||||
sym.Value += int64(sym.Sect.Vaddr)
|
sym.Value += int64(sym.Sect.Vaddr)
|
||||||
}
|
}
|
||||||
for sub = sym.Sub; sub != nil; sub = sub.Sub {
|
for sub := sym.Sub; sub != nil; sub = sub.Sub {
|
||||||
sub.Value += sym.Value
|
sub.Value += sym.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1670,7 +1670,7 @@ func elfshreloc(sect *Section) *ElfShdr {
|
|||||||
return sh
|
return sh
|
||||||
}
|
}
|
||||||
|
|
||||||
func elfrelocsect(sect *Section, first *LSym) {
|
func elfrelocsect(sect *Section, syms []*LSym) {
|
||||||
// If main section is SHT_NOBITS, nothing to relocate.
|
// If main section is SHT_NOBITS, nothing to relocate.
|
||||||
// Also nothing to relocate in .shstrtab.
|
// Also nothing to relocate in .shstrtab.
|
||||||
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
|
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
|
||||||
@ -1681,18 +1681,18 @@ func elfrelocsect(sect *Section, first *LSym) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sect.Reloff = uint64(Cpos())
|
sect.Reloff = uint64(Cpos())
|
||||||
var sym *LSym
|
for i, s := range syms {
|
||||||
for sym = first; sym != nil; sym = sym.Next {
|
if !s.Attr.Reachable() {
|
||||||
if !sym.Attr.Reachable() {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if uint64(sym.Value) >= sect.Vaddr {
|
if uint64(s.Value) >= sect.Vaddr {
|
||||||
|
syms = syms[i:]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eaddr := int32(sect.Vaddr + sect.Length)
|
eaddr := int32(sect.Vaddr + sect.Length)
|
||||||
for ; sym != nil; sym = sym.Next {
|
for _, sym := range syms {
|
||||||
if !sym.Attr.Reachable() {
|
if !sym.Attr.Reachable() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -1710,7 +1710,6 @@ func elfrelocsect(sect *Section, first *LSym) {
|
|||||||
Diag("missing xsym in relocation")
|
Diag("missing xsym in relocation")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Xsym.ElfsymForReloc() == 0 {
|
if r.Xsym.ElfsymForReloc() == 0 {
|
||||||
Diag("reloc %d to non-elf symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
|
Diag("reloc %d to non-elf symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
|
||||||
}
|
}
|
||||||
@ -1728,7 +1727,7 @@ func Elfemitreloc() {
|
|||||||
Cput(0)
|
Cput(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
elfrelocsect(Segtext.Sect, Ctxt.Textp)
|
elfrelocsect(Segtext.Sect, list2slice(Ctxt.Textp))
|
||||||
for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
|
for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
|
||||||
elfrelocsect(sect, datap)
|
elfrelocsect(sect, datap)
|
||||||
}
|
}
|
||||||
@ -1739,7 +1738,7 @@ func Elfemitreloc() {
|
|||||||
elfrelocsect(sect, datap)
|
elfrelocsect(sect, datap)
|
||||||
}
|
}
|
||||||
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
|
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
|
||||||
elfrelocsect(sect, dwarfp)
|
elfrelocsect(sect, list2slice(dwarfp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,6 @@ func (r *Rpath) String() string {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
Thearch Arch
|
Thearch Arch
|
||||||
datap *LSym
|
|
||||||
Debug [128]int
|
Debug [128]int
|
||||||
Lcsize int32
|
Lcsize int32
|
||||||
rpath Rpath
|
rpath Rpath
|
||||||
@ -2109,7 +2108,7 @@ func undef() {
|
|||||||
for s := Ctxt.Textp; s != nil; s = s.Next {
|
for s := Ctxt.Textp; s != nil; s = s.Next {
|
||||||
undefsym(s)
|
undefsym(s)
|
||||||
}
|
}
|
||||||
for s := datap; s != nil; s = s.Next {
|
for _, s := range datap {
|
||||||
undefsym(s)
|
undefsym(s)
|
||||||
}
|
}
|
||||||
if nerrors > 0 {
|
if nerrors > 0 {
|
||||||
|
@ -806,25 +806,25 @@ func Domacholink() int64 {
|
|||||||
return Rnd(int64(size), int64(INITRND))
|
return Rnd(int64(size), int64(INITRND))
|
||||||
}
|
}
|
||||||
|
|
||||||
func machorelocsect(sect *Section, first *LSym) {
|
func machorelocsect(sect *Section, syms []*LSym) {
|
||||||
// If main section has no bits, nothing to relocate.
|
// If main section has no bits, nothing to relocate.
|
||||||
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
|
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sect.Reloff = uint64(Cpos())
|
sect.Reloff = uint64(Cpos())
|
||||||
var sym *LSym
|
for i, s := range syms {
|
||||||
for sym = first; sym != nil; sym = sym.Next {
|
if !s.Attr.Reachable() {
|
||||||
if !sym.Attr.Reachable() {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if uint64(sym.Value) >= sect.Vaddr {
|
if uint64(s.Value) >= sect.Vaddr {
|
||||||
|
syms = syms[i:]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eaddr := int32(sect.Vaddr + sect.Length)
|
eaddr := int32(sect.Vaddr + sect.Length)
|
||||||
for ; sym != nil; sym = sym.Next {
|
for _, sym := range syms {
|
||||||
if !sym.Attr.Reachable() {
|
if !sym.Attr.Reachable() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -852,7 +852,7 @@ func Machoemitreloc() {
|
|||||||
Cput(0)
|
Cput(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
machorelocsect(Segtext.Sect, Ctxt.Textp)
|
machorelocsect(Segtext.Sect, list2slice(Ctxt.Textp))
|
||||||
for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
|
for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
|
||||||
machorelocsect(sect, datap)
|
machorelocsect(sect, datap)
|
||||||
}
|
}
|
||||||
@ -860,6 +860,6 @@ func Machoemitreloc() {
|
|||||||
machorelocsect(sect, datap)
|
machorelocsect(sect, datap)
|
||||||
}
|
}
|
||||||
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
|
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
|
||||||
machorelocsect(sect, dwarfp)
|
machorelocsect(sect, list2slice(dwarfp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,7 +764,7 @@ func addexports() {
|
|||||||
|
|
||||||
// perelocsect relocates symbols from first in section sect, and returns
|
// perelocsect relocates symbols from first in section sect, and returns
|
||||||
// the total number of relocations emitted.
|
// the total number of relocations emitted.
|
||||||
func perelocsect(sect *Section, first *LSym) int {
|
func perelocsect(sect *Section, syms []*LSym) int {
|
||||||
// If main section has no bits, nothing to relocate.
|
// If main section has no bits, nothing to relocate.
|
||||||
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
|
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
|
||||||
return 0
|
return 0
|
||||||
@ -773,18 +773,18 @@ func perelocsect(sect *Section, first *LSym) int {
|
|||||||
relocs := 0
|
relocs := 0
|
||||||
|
|
||||||
sect.Reloff = uint64(Cpos())
|
sect.Reloff = uint64(Cpos())
|
||||||
var sym *LSym
|
for i, s := range syms {
|
||||||
for sym = first; sym != nil; sym = sym.Next {
|
if !s.Attr.Reachable() {
|
||||||
if !sym.Attr.Reachable() {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if uint64(sym.Value) >= sect.Vaddr {
|
if uint64(s.Value) >= sect.Vaddr {
|
||||||
|
syms = syms[i:]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eaddr := int32(sect.Vaddr + sect.Length)
|
eaddr := int32(sect.Vaddr + sect.Length)
|
||||||
for ; sym != nil; sym = sym.Next {
|
for _, sym := range syms {
|
||||||
if !sym.Attr.Reachable() {
|
if !sym.Attr.Reachable() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -831,7 +831,7 @@ func peemitreloc(text, data, ctors *IMAGE_SECTION_HEADER) {
|
|||||||
Lputl(0)
|
Lputl(0)
|
||||||
Wputl(0)
|
Wputl(0)
|
||||||
|
|
||||||
n := perelocsect(Segtext.Sect, Ctxt.Textp) + 1
|
n := perelocsect(Segtext.Sect, list2slice(Ctxt.Textp)) + 1
|
||||||
for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
|
for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
|
||||||
n += perelocsect(sect, datap)
|
n += perelocsect(sect, datap)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user