root/src/cmd/ld/decodesym.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. decode_reloc
  2. decode_reloc_sym
  3. decode_inuxi
  4. commonsize
  5. decodetype_kind
  6. decodetype_size
  7. decodetype_gc
  8. decodetype_arrayelem
  9. decodetype_arraylen
  10. decodetype_ptrelem
  11. decodetype_mapkey
  12. decodetype_mapvalue
  13. decodetype_chanelem
  14. decodetype_funcdotdotdot
  15. decodetype_funcincount
  16. decodetype_funcoutcount
  17. decodetype_funcintype
  18. decodetype_funcouttype
  19. decodetype_structfieldcount
  20. structfieldsize
  21. decodetype_structfieldname
  22. decodetype_structfieldtype
  23. decodetype_structfieldoffs
  24. decodetype_ifacemethodcount

// 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.

#include        "l.h"
#include        "lib.h"
#include        "../../pkg/runtime/typekind.h"

// Decoding the type.* symbols.  This has to be in sync with
// ../../pkg/runtime/type.go, or more specificaly, with what
// ../gc/reflect.c stuffs in these.

static Reloc*
decode_reloc(LSym *s, int32 off)
{
        int i;

        for (i = 0; i < s->nr; i++)
                if (s->r[i].off == off)
                        return s->r + i;
        return nil;
}

static LSym*
decode_reloc_sym(LSym *s, int32 off)
{
        Reloc *r;

        r = decode_reloc(s,off);
        if (r == nil)
                return nil;
        return r->sym;
}

static uvlong
decode_inuxi(uchar* p, int sz)
{
        uint64 v;
        uint32 l;
        uchar *cast, *inuxi;
        int i;

        v = l = 0;
        cast = nil;
        inuxi = nil;
        switch (sz) {
        case 2:
                cast = (uchar*)&l;
                inuxi = inuxi2;
                break;
        case 4:
                cast = (uchar*)&l;
                inuxi = inuxi4;
                break;
        case 8:
                cast = (uchar*)&v;
                inuxi = inuxi8;
                break;
        default:
                diag("dwarf: decode inuxi %d", sz);
                errorexit();
        }
        for (i = 0; i < sz; i++)
                cast[inuxi[i]] = p[i];
        if (sz == 8)
                return v;
        return l;
}

static int
commonsize(void)
{
        return 7*PtrSize + 8;
}

// Type.commonType.kind
uint8
decodetype_kind(LSym *s)
{
        return s->p[1*PtrSize + 7] & ~KindNoPointers;   //  0x13 / 0x1f
}

// Type.commonType.size
vlong
decodetype_size(LSym *s)
{
        return decode_inuxi(s->p, PtrSize);      // 0x8 / 0x10
}

// Type.commonType.gc
LSym*
decodetype_gc(LSym *s)
{
        return decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
}

// Type.ArrayType.elem and Type.SliceType.Elem
LSym*
decodetype_arrayelem(LSym *s)
{
        return decode_reloc_sym(s, commonsize());       // 0x1c / 0x30
}

vlong
decodetype_arraylen(LSym *s)
{
        return decode_inuxi(s->p + commonsize()+PtrSize, PtrSize);
}

// Type.PtrType.elem
LSym*
decodetype_ptrelem(LSym *s)
{
        return decode_reloc_sym(s, commonsize());       // 0x1c / 0x30
}

// Type.MapType.key, elem
LSym*
decodetype_mapkey(LSym *s)
{
        return decode_reloc_sym(s, commonsize());       // 0x1c / 0x30
}
LSym*
decodetype_mapvalue(LSym *s)
{
        return decode_reloc_sym(s, commonsize()+PtrSize);       // 0x20 / 0x38
}

// Type.ChanType.elem
LSym*
decodetype_chanelem(LSym *s)
{
        return decode_reloc_sym(s, commonsize());       // 0x1c / 0x30
}

// Type.FuncType.dotdotdot
int
decodetype_funcdotdotdot(LSym *s)
{
        return s->p[commonsize()];
}

// Type.FuncType.in.len
int
decodetype_funcincount(LSym *s)
{
        return decode_inuxi(s->p + commonsize()+2*PtrSize, IntSize);
}

int
decodetype_funcoutcount(LSym *s)
{
        return decode_inuxi(s->p + commonsize()+3*PtrSize + 2*IntSize, IntSize);
}

LSym*
decodetype_funcintype(LSym *s, int i)
{
        Reloc *r;

        r = decode_reloc(s, commonsize() + PtrSize);
        if (r == nil)
                return nil;
        return decode_reloc_sym(r->sym, r->add + i * PtrSize);
}

LSym*
decodetype_funcouttype(LSym *s, int i)
{
        Reloc *r;

        r = decode_reloc(s, commonsize() + 2*PtrSize + 2*IntSize);
        if (r == nil)
                return nil;
        return decode_reloc_sym(r->sym, r->add + i * PtrSize);
}

// Type.StructType.fields.Slice::len
int
decodetype_structfieldcount(LSym *s)
{
        return decode_inuxi(s->p + commonsize() + PtrSize, IntSize);
}

static int
structfieldsize(void)
{
        return 5*PtrSize;
}

// Type.StructType.fields[]-> name, typ and offset.
char*
decodetype_structfieldname(LSym *s, int i)
{
        Reloc *r;

        // go.string."foo"  0x28 / 0x40
        s = decode_reloc_sym(s, commonsize() + PtrSize + 2*IntSize + i*structfieldsize());
        if (s == nil)                   // embedded structs have a nil name.
                return nil;
        r = decode_reloc(s, 0);         // s has a pointer to the string data at offset 0
        if (r == nil)                   // shouldn't happen.
                return nil;
        return (char*) r->sym->p + r->add;      // the c-string
}

LSym*
decodetype_structfieldtype(LSym *s, int i)
{
        return decode_reloc_sym(s, commonsize() + PtrSize + 2*IntSize + i*structfieldsize() + 2*PtrSize);
}

vlong
decodetype_structfieldoffs(LSym *s, int i)
{
        return decode_inuxi(s->p + commonsize() + PtrSize + 2*IntSize + i*structfieldsize() + 4*PtrSize, IntSize);
}

// InterfaceTYpe.methods.len
vlong
decodetype_ifacemethodcount(LSym *s)
{
        return decode_inuxi(s->p + commonsize() + PtrSize, IntSize);
}

/* [<][>][^][v][top][bottom][index][help] */