summaryrefslogtreecommitdiff
path: root/src/cmd/ld/decodesym.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ld/decodesym.c')
-rw-r--r--src/cmd/ld/decodesym.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/cmd/ld/decodesym.c b/src/cmd/ld/decodesym.c
new file mode 100644
index 000000000..ab3f4fbd5
--- /dev/null
+++ b/src/cmd/ld/decodesym.c
@@ -0,0 +1,215 @@
+// 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(Sym *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 Sym*
+decode_reloc_sym(Sym *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;
+}
+
+// Type.commonType.kind
+uint8
+decodetype_kind(Sym *s)
+{
+ return s->p[1*PtrSize + 7] & ~KindNoPointers; // 0x13 / 0x1f
+}
+
+// Type.commonType.size
+vlong
+decodetype_size(Sym *s)
+{
+ return decode_inuxi(s->p, PtrSize); // 0x8 / 0x10
+}
+
+// Type.commonType.gc
+Sym*
+decodetype_gc(Sym *s)
+{
+ return decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
+}
+
+// Type.ArrayType.elem and Type.SliceType.Elem
+Sym*
+decodetype_arrayelem(Sym *s)
+{
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+
+vlong
+decodetype_arraylen(Sym *s)
+{
+ return decode_inuxi(s->p + CommonSize+PtrSize, PtrSize);
+}
+
+// Type.PtrType.elem
+Sym*
+decodetype_ptrelem(Sym *s)
+{
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+
+// Type.MapType.key, elem
+Sym*
+decodetype_mapkey(Sym *s)
+{
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+Sym*
+decodetype_mapvalue(Sym *s)
+{
+ return decode_reloc_sym(s, CommonSize+PtrSize); // 0x20 / 0x38
+}
+
+// Type.ChanType.elem
+Sym*
+decodetype_chanelem(Sym *s)
+{
+ return decode_reloc_sym(s, CommonSize); // 0x1c / 0x30
+}
+
+// Type.FuncType.dotdotdot
+int
+decodetype_funcdotdotdot(Sym *s)
+{
+ return s->p[CommonSize];
+}
+
+// Type.FuncType.in.len
+int
+decodetype_funcincount(Sym *s)
+{
+ return decode_inuxi(s->p + CommonSize+2*PtrSize, IntSize);
+}
+
+int
+decodetype_funcoutcount(Sym *s)
+{
+ return decode_inuxi(s->p + CommonSize+3*PtrSize + 2*IntSize, IntSize);
+}
+
+Sym*
+decodetype_funcintype(Sym *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);
+}
+
+Sym*
+decodetype_funcouttype(Sym *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(Sym *s)
+{
+ return decode_inuxi(s->p + CommonSize + PtrSize, IntSize);
+}
+
+enum {
+ StructFieldSize = 5*PtrSize
+};
+// Type.StructType.fields[]-> name, typ and offset.
+char*
+decodetype_structfieldname(Sym *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
+}
+
+Sym*
+decodetype_structfieldtype(Sym *s, int i)
+{
+ return decode_reloc_sym(s, CommonSize + PtrSize + 2*IntSize + i*StructFieldSize + 2*PtrSize);
+}
+
+vlong
+decodetype_structfieldoffs(Sym *s, int i)
+{
+ return decode_inuxi(s->p + CommonSize + PtrSize + 2*IntSize + i*StructFieldSize + 4*PtrSize, IntSize);
+}
+
+// InterfaceTYpe.methods.len
+vlong
+decodetype_ifacemethodcount(Sym *s)
+{
+ return decode_inuxi(s->p + CommonSize + PtrSize, IntSize);
+}