Ejemplo n.º 1
0
// dname dumps a reflect.name for a struct field or method.
func dname(s *Sym, ot int, name, tag string, pkg *Pkg, exported bool) int {
	if len(name) > 1<<16-1 {
		Fatalf("name too long: %s", name)
	}
	if len(tag) > 1<<16-1 {
		Fatalf("tag too long: %s", tag)
	}

	// Encode name and tag. See reflect/type.go for details.
	var bits byte
	l := 1 + 2 + len(name)
	if exported {
		bits |= 1 << 0
	}
	if len(tag) > 0 {
		l += 2 + len(tag)
		bits |= 1 << 1
	}
	if pkg != nil {
		bits |= 1 << 2
	}
	b := make([]byte, l)
	b[0] = bits
	b[1] = uint8(len(name) >> 8)
	b[2] = uint8(len(name))
	copy(b[3:], name)
	if len(tag) > 0 {
		tb := b[3+len(name):]
		tb[0] = uint8(len(tag) >> 8)
		tb[1] = uint8(len(tag))
		copy(tb[2:], tag)
	}

	// Very few names require a pkgPath *string (only those
	// defined in a different package than their type). So if
	// there is no pkgPath, we treat the name contents as string
	// data that duplicates across packages.
	var bsym *obj.LSym
	if pkg == nil {
		_, bsym = stringsym(string(b))
	} else {
		// Write out data as "type.." to signal two things to the
		// linker, first that when dynamically linking, the symbol
		// should be moved to a relro section, and second that the
		// contents should not be decoded as a type.
		bsymname := fmt.Sprintf(`type..methodname."".%d`, dnameCount)
		dnameCount++
		bsym = obj.Linklookup(Ctxt, bsymname, 0)
		bsym.P = b
		boff := len(b)
		boff = int(Rnd(int64(boff), int64(Widthptr)))
		boff = dgopkgpathLSym(bsym, boff, pkg)
		ggloblLSym(bsym, int32(boff), obj.RODATA|obj.LOCAL)
	}

	ot = dsymptrLSym(Linksym(s), ot, bsym, 0)

	return ot
}