2015-02-27 22:57:28 -05:00
|
|
|
// Copyright 2012 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.
|
|
|
|
|
|
|
|
|
|
package ld
|
|
|
|
|
|
|
|
|
|
import "cmd/internal/obj"
|
|
|
|
|
|
|
|
|
|
// Decoding the type.* symbols. This has to be in sync with
|
|
|
|
|
// ../../runtime/type.go, or more specifically, with what
|
|
|
|
|
// ../gc/reflect.c stuffs in these.
|
|
|
|
|
|
|
|
|
|
func decode_reloc(s *LSym, off int32) *Reloc {
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; i < len(s.R); i++ {
|
2015-02-27 22:57:28 -05:00
|
|
|
if s.R[i].Off == off {
|
|
|
|
|
return &s.R[i:][0]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decode_reloc_sym(s *LSym, off int32) *LSym {
|
2015-03-02 12:35:15 -05:00
|
|
|
r := decode_reloc(s, off)
|
2015-02-27 22:57:28 -05:00
|
|
|
if r == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return r.Sym
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decode_inuxi(p []byte, sz int) uint64 {
|
|
|
|
|
switch sz {
|
|
|
|
|
case 2:
|
|
|
|
|
return uint64(Ctxt.Arch.ByteOrder.Uint16(p))
|
|
|
|
|
case 4:
|
|
|
|
|
return uint64(Ctxt.Arch.ByteOrder.Uint32(p))
|
|
|
|
|
case 8:
|
|
|
|
|
return Ctxt.Arch.ByteOrder.Uint64(p)
|
2015-04-09 07:37:17 -04:00
|
|
|
default:
|
|
|
|
|
Exitf("dwarf: decode inuxi %d", sz)
|
|
|
|
|
panic("unreachable")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func commonsize() int {
|
|
|
|
|
return 8*Thearch.Ptrsize + 8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.commonType.kind
|
|
|
|
|
func decodetype_kind(s *LSym) uint8 {
|
|
|
|
|
return uint8(s.P[1*Thearch.Ptrsize+7] & obj.KindMask) // 0x13 / 0x1f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.commonType.kind
|
|
|
|
|
func decodetype_noptr(s *LSym) uint8 {
|
|
|
|
|
return uint8(s.P[1*Thearch.Ptrsize+7] & obj.KindNoPointers) // 0x13 / 0x1f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.commonType.kind
|
|
|
|
|
func decodetype_usegcprog(s *LSym) uint8 {
|
|
|
|
|
return uint8(s.P[1*Thearch.Ptrsize+7] & obj.KindGCProg) // 0x13 / 0x1f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.commonType.size
|
|
|
|
|
func decodetype_size(s *LSym) int64 {
|
|
|
|
|
return int64(decode_inuxi(s.P, Thearch.Ptrsize)) // 0x8 / 0x10
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.commonType.gc
|
|
|
|
|
func decodetype_gcprog(s *LSym) *LSym {
|
2015-04-01 16:20:44 +13:00
|
|
|
if s.Type == obj.SDYNIMPORT {
|
|
|
|
|
// The gcprog for "type.$name" is calle "type..gcprog.$name".
|
|
|
|
|
x := "type..gcprog." + s.Name[5:]
|
|
|
|
|
return Linklookup(Ctxt, x, 0)
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
return decode_reloc_sym(s, 1*int32(Thearch.Ptrsize)+8+2*int32(Thearch.Ptrsize))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_gcmask(s *LSym) []byte {
|
2015-04-01 16:20:44 +13:00
|
|
|
if s.Type == obj.SDYNIMPORT {
|
|
|
|
|
// ldshlibsyms makes special efforts to read the value
|
|
|
|
|
// of gcmask for types defined in that shared library.
|
|
|
|
|
return s.gcmask
|
|
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
mask := decode_reloc_sym(s, 1*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
|
2015-02-27 22:57:28 -05:00
|
|
|
return mask.P
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.ArrayType.elem and Type.SliceType.Elem
|
|
|
|
|
func decodetype_arrayelem(s *LSym) *LSym {
|
|
|
|
|
return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_arraylen(s *LSym) int64 {
|
|
|
|
|
return int64(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Ptrsize))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.PtrType.elem
|
|
|
|
|
func decodetype_ptrelem(s *LSym) *LSym {
|
|
|
|
|
return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.MapType.key, elem
|
|
|
|
|
func decodetype_mapkey(s *LSym) *LSym {
|
|
|
|
|
return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_mapvalue(s *LSym) *LSym {
|
|
|
|
|
return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)) // 0x20 / 0x38
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.ChanType.elem
|
|
|
|
|
func decodetype_chanelem(s *LSym) *LSym {
|
|
|
|
|
return decode_reloc_sym(s, int32(commonsize())) // 0x1c / 0x30
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.FuncType.dotdotdot
|
|
|
|
|
func decodetype_funcdotdotdot(s *LSym) int {
|
|
|
|
|
return int(s.P[commonsize()])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.FuncType.in.length
|
|
|
|
|
func decodetype_funcincount(s *LSym) int {
|
|
|
|
|
return int(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_funcoutcount(s *LSym) int {
|
|
|
|
|
return int(decode_inuxi(s.P[commonsize()+3*Thearch.Ptrsize+2*Thearch.Intsize:], Thearch.Intsize))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_funcintype(s *LSym, i int) *LSym {
|
2015-03-02 12:35:15 -05:00
|
|
|
r := decode_reloc(s, int32(commonsize())+int32(Thearch.Ptrsize))
|
2015-02-27 22:57:28 -05:00
|
|
|
if r == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return decode_reloc_sym(r.Sym, int32(r.Add+int64(int32(i)*int32(Thearch.Ptrsize))))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_funcouttype(s *LSym, i int) *LSym {
|
2015-03-02 12:35:15 -05:00
|
|
|
r := decode_reloc(s, int32(commonsize())+2*int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize))
|
2015-02-27 22:57:28 -05:00
|
|
|
if r == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return decode_reloc_sym(r.Sym, int32(r.Add+int64(int32(i)*int32(Thearch.Ptrsize))))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.StructType.fields.Slice::length
|
|
|
|
|
func decodetype_structfieldcount(s *LSym) int {
|
|
|
|
|
return int(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func structfieldsize() int {
|
|
|
|
|
return 5 * Thearch.Ptrsize
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Type.StructType.fields[]-> name, typ and offset.
|
|
|
|
|
func decodetype_structfieldname(s *LSym, i int) string {
|
|
|
|
|
// go.string."foo" 0x28 / 0x40
|
|
|
|
|
s = decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize)+int32(i)*int32(structfieldsize()))
|
|
|
|
|
|
|
|
|
|
if s == nil { // embedded structs have a nil name.
|
|
|
|
|
return ""
|
|
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
r := decode_reloc(s, 0) // s has a pointer to the string data at offset 0
|
|
|
|
|
if r == nil { // shouldn't happen.
|
2015-02-27 22:57:28 -05:00
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
return cstring(r.Sym.P[r.Add:])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_structfieldtype(s *LSym, i int) *LSym {
|
|
|
|
|
return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize)+int32(i)*int32(structfieldsize())+2*int32(Thearch.Ptrsize))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func decodetype_structfieldoffs(s *LSym, i int) int64 {
|
|
|
|
|
return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize+2*Thearch.Intsize+i*structfieldsize()+4*Thearch.Ptrsize:], Thearch.Intsize))
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-05 13:57:36 -05:00
|
|
|
// InterfaceType.methods.length
|
2015-02-27 22:57:28 -05:00
|
|
|
func decodetype_ifacemethodcount(s *LSym) int64 {
|
|
|
|
|
return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize))
|
|
|
|
|
}
|