blob: 21f6d6082722d923beb93b47a797e246ebcb8908 [file] [log] [blame]
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Automatic symbol generation.
// TODO(rsc): Handle go.typelink, go.track symbols.
// TODO(rsc): Do not handle $f64. and $f32. symbols. Instead, generate those
// from the compiler and assemblers as dupok data, and then remove autoData below.
package main
import (
"cmd/internal/goobj"
"strconv"
"strings"
)
// linkerDefined lists the symbols supplied by other parts of the linker
// (runtime.go and layout.go).
var linkerDefined = map[string]bool{
"runtime.bss": true,
"runtime.data": true,
"runtime.ebss": true,
"runtime.edata": true,
"runtime.efunctab": true,
"runtime.end": true,
"runtime.enoptrbss": true,
"runtime.enoptrdata": true,
"runtime.erodata": true,
"runtime.etext": true,
"runtime.etypelink": true,
"runtime.functab": true,
"runtime.gcbss": true,
"runtime.gcdata": true,
"runtime.noptrbss": true,
"runtime.noptrdata": true,
"runtime.pclntab": true,
"runtime.rodata": true,
"runtime.text": true,
"runtime.typelink": true,
}
// isAuto reports whether sym is an automatically-generated data or constant symbol.
func (p *Prog) isAuto(sym goobj.SymID) bool {
return strings.HasPrefix(sym.Name, "go.weak.") ||
strings.HasPrefix(sym.Name, "$f64.") ||
strings.HasPrefix(sym.Name, "$f32.") ||
linkerDefined[sym.Name]
}
// autoData defines the automatically generated data symbols needed by p.
func (p *Prog) autoData() {
for sym := range p.Missing {
switch {
// Floating-point constants that need to be loaded from memory are
// written as $f64.{16 hex digits} or $f32.{8 hex digits}; the hex digits
// give the IEEE bit pattern of the constant. As far as the layout into
// memory is concerned, we interpret these as uint64 or uint32 constants.
case strings.HasPrefix(sym.Name, "$f64."), strings.HasPrefix(sym.Name, "$f32."):
size := 64
if sym.Name[2:4] == "32" {
size = 32
}
delete(p.Missing, sym)
fbits, err := strconv.ParseUint(sym.Name[len("$f64."):], 16, size)
if err != nil {
p.errorf("unexpected floating point symbol %s", sym)
continue
}
data := make([]byte, size/8)
if size == 64 {
p.byteorder.PutUint64(data, fbits)
} else {
p.byteorder.PutUint32(data, uint32(fbits))
}
p.addSym(&Sym{
Sym: &goobj.Sym{
SymID: sym,
Kind: goobj.SRODATA,
Size: size / 8,
},
Bytes: data,
})
}
}
}
// autoConst defines the automatically generated constant symbols needed by p.
func (p *Prog) autoConst() {
for sym := range p.Missing {
switch {
case strings.HasPrefix(sym.Name, "go.weak."):
// weak symbol resolves to actual symbol if present, or else nil.
delete(p.Missing, sym)
targ := sym
targ.Name = sym.Name[len("go.weak."):]
var addr Addr
if s := p.Syms[targ]; s != nil {
addr = s.Addr
}
p.defineConst(sym.Name, addr)
}
}
}
// defineConst defines a new symbol with the given name and constant address.
func (p *Prog) defineConst(name string, addr Addr) {
sym := goobj.SymID{Name: name}
p.addSym(&Sym{
Sym: &goobj.Sym{
SymID: sym,
Kind: goobj.SCONST,
},
Package: nil,
Addr: addr,
})
}