// 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 ( "debug/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, }) }