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