Beispiel #1
0
        public override void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent)
        {
            d.Add((byte)12);
            w(d, ns, ds.smap);

            base.WriteToOutput(ds, d, parent);
        }
Beispiel #2
0
        public override void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent)
        {
            w(d, 21);
            w(d, name, ds.smap);
            dcu.fmap[d.Count] = dcu.GetTypeDie(ts);
            for (int i = 0; i < 4; i++)
            {
                d.Add(0);
            }

            // location as exprloc
            var b = new List <byte>();

            if (t.AddDwarfLocation(loc, b))
            {
                DwarfDIE.w(d, (uint)b.Count);
                foreach (var c in b)
                {
                    d.Add(c);
                }
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Beispiel #3
0
        public override void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent)
        {
            w(d, 22);
            dcu.fmap[d.Count] = decl;
            for (int i = 0; i < 4; i++)
            {
                d.Add(0);
            }

            var low_r = ds.bf.CreateRelocation();

            low_r.Type       = t.GetDataToDataReloc();
            low_r.Offset     = (ulong)d.Count;
            low_r.References = ds.bf.FindSymbol(decl.ms.MangleMethod());
            low_r.DefinedIn  = ds.info;
            ds.bf.AddRelocation(low_r);
            wp(d);                        // low_pc
            wp(d, low_r.References.Size); // high_pc

            foreach (var child in decl.Children)
            {
                child.WriteToOutput(ds, d, this);
            }

            d.Add(0);
        }
Beispiel #4
0
        public override void WriteToOutput(DwarfSections ds, IList <byte> dinfo, DwarfDIE parent)
        {
            foreach (var c in Children)
            {
                c.Offset = dinfo.Count;
                c.WriteToOutput(ds, dinfo, this);
            }

            dinfo.Add(0);    // null-terminate
        }
Beispiel #5
0
 public override void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent)
 {
     d.Add(18);
     w(d, Name, ds.smap);
     dcu.fmap[d.Count] = FieldType;
     for (int i = 0; i < 4; i++)
     {
         d.Add(0);
     }
     w(d, (uint)FieldOffset);
 }
Beispiel #6
0
        public void WriteToOutput(DwarfSections odbgsect)
        {
            WriteAbbrev(odbgsect.abbrev);

            WriteInfo(odbgsect);
            odbgsect.smap.Write(odbgsect.str);

            WriteLines(odbgsect);

            WritePubTypes(odbgsect);
            WritePubNames(odbgsect);
        }
Beispiel #7
0
        private void WriteInfo(DwarfSections ds)
        {
            var info       = ds.info;
            var string_map = ds.smap;

            List <byte> d = new List <byte>();

            // Output header

            // Reserve space for unit_length
            if (t.psize == 4)
            {
                for (int i = 0; i < 4; i++)
                {
                    d.Add(0);
                }
            }
            else
            {
                for (int i = 0; i < 12; i++)
                {
                    d.Add(0);
                }
            }

            // version
            d.Add(4);
            d.Add(0);

            // debug_abbrev_offset
            for (int i = 0; i < t.psize; i++)
            {
                d.Add(0);
            }

            // address_size
            d.Add((byte)t.psize);

            // Store offset of root entry
            this.Offset = d.Count;


            // Write the root DIE
            w(d, 1);
            w(d, "tysila", string_map);
            w(d, 0x4);  // pretend to be C++

            var fname = m.file.Name;

            if (fname == null || fname.Equals(string.Empty))
            {
                w(d, m.AssemblyName, string_map);
                w(d, "", string_map);
            }
            else
            {
                var finfo = new System.IO.FileInfo(fname);
                w(d, finfo.Name, string_map);
                w(d, finfo.DirectoryName, string_map);
            }

            // store low/high pc offsets for patching later
            var low_pc_offset = d.Count;

            for (int i = 0; i < t.psize; i++)
            {
                d.Add(0);
            }
            var high_pc_offset = d.Count;

            for (int i = 0; i < t.psize; i++)
            {
                d.Add(0);
            }
            var stmt_list_offset = d.Count;

            for (int i = 0; i < t.psize; i++)
            {
                d.Add(0);
            }

            /* Children:
             *  Items in the empty namespace are placed as direct children
             *  Others are placed as children of the namespace
             */
            foreach (var kvp in ns_dies)
            {
                if (kvp.Key == "")
                {
                    foreach (var dc in kvp.Value.Children)
                    {
                        Children.Add(dc);
                    }
                }
                else
                {
                    Children.Add(kvp.Value);
                }
            }

            /* Add defintions for all the methods in the main namespace */
            foreach (var methkvp in method_dies)
            {
                var methdef = new DwarfMethodDefDIE();
                methdef.dcu  = this;
                methdef.t    = t;
                methdef.decl = methkvp.Value;
                Children.Add(methdef);
            }

            // Write children
            base.WriteToOutput(ds, d, null);

            // Patch relocs
            byte[] bytes;
            foreach (var kvp in fmap)
            {
                uint dest = (uint)kvp.Value.Offset;
                int  addr = kvp.Key;
                bytes = BitConverter.GetBytes(dest);
                for (int i = 0; i < 4; i++)
                {
                    d[addr + i] = bytes[i];
                }
            }

            // Patch low/high_pc
            var low_r = ds.bf.CreateRelocation();

            low_r.Type       = t.GetDataToDataReloc();
            low_r.Offset     = (ulong)low_pc_offset;
            low_r.References = first_sym;
            low_r.DefinedIn  = ds.info;
            ds.bf.AddRelocation(low_r);

            var pc_size = last_sym.Offset - first_sym.Offset + (ulong)last_sym.Size;

            bytes = (t.psize == 4) ? BitConverter.GetBytes((int)pc_size) :
                    BitConverter.GetBytes((long)pc_size);
            for (int i = 0; i < t.psize; i++)
            {
                d[high_pc_offset + i] = bytes[i];
            }

            // Finally, patch the length back in
            if (t.psize == 4)
            {
                uint len = (uint)d.Count - 4;
                bytes = BitConverter.GetBytes(len);
                for (int i = 0; i < 4; i++)
                {
                    d[i] = bytes[i];
                }
            }
            else
            {
                ulong len = (ulong)d.Count - 12;
                bytes = BitConverter.GetBytes(len);
                for (int i = 0; i < 4; i++)
                {
                    d[i] = 0xff;
                }
                for (int i = 0; i < 8; i++)
                {
                    d[i + 4] = bytes[i];
                }
            }

            // Store to section
            for (int i = 0; i < d.Count; i++)
            {
                info.Data.Add(d[i]);
            }
        }
Beispiel #8
0
        private void WriteLines(DwarfSections odbgsect)
        {
            /* Write lines header */
            List <byte> d = new List <byte>();

            // Reserve space for unit_length
            if (t.psize == 4)
            {
                for (int i = 0; i < 4; i++)
                {
                    d.Add(0);
                }
            }
            else
            {
                for (int i = 0; i < 12; i++)
                {
                    d.Add(0);
                }
            }

            // version
            d.Add(4);
            d.Add(0);

            // header_length
            var header_length_offset = d.Count;

            for (int i = 0; i < t.psize; i++)
            {
                d.Add(0);
            }

            // minimum_instruction_length
            d.Add(1);

            // maximum_operations_per_instruction
            d.Add(1);

            // default_is_stmt
            d.Add(1);

            // line_base
            if (line_base < 0)
            {
                d.Add((byte)(0x100 + line_base));
            }
            else
            {
                d.Add((byte)line_base);
            }

            // line_range
            d.Add((byte)line_range);

            // opcode_base
            d.Add((byte)opcode_base);

            // standard_opcode_lengths
            d.AddRange(new byte[] { 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 });

            // include_directories
            d.Add(0);

            // file_names
            foreach (var fname in lnp_fnames)
            {
                foreach (var c in fname)
                {
                    d.Add((byte)c);
                }
                d.Add(0);

                // dir index
                d.Add(0);

                // last_mod
                d.Add(0);

                // length
                d.Add(0);
            }
            d.Add(0);

            // point header_length here
            var doffset       = d.Count;
            var header_length = doffset - header_length_offset - t.psize;

            byte[] bytes = (t.psize == 4) ? BitConverter.GetBytes((int)header_length) :
                           BitConverter.GetBytes((long)header_length);
            for (int i = 0; i < t.psize; i++)
            {
                d[header_length_offset + i] = bytes[i];
            }

            // add the actual data
            d.AddRange(lnp);

            // add relocs
            foreach (var reloc in lnp_relocs)
            {
                var r = odbgsect.bf.CreateRelocation();
                r.Type       = t.GetDataToDataReloc();
                r.Offset     = (ulong)(doffset + reloc.Key);
                r.References = reloc.Value;
                r.DefinedIn  = odbgsect.line;
                odbgsect.bf.AddRelocation(r);
            }

            // Finally, patch the length back in
            if (t.psize == 4)
            {
                uint len = (uint)d.Count - 4;
                bytes = BitConverter.GetBytes(len);
                for (int i = 0; i < 4; i++)
                {
                    d[i] = bytes[i];
                }
            }
            else
            {
                ulong len = (ulong)d.Count - 12;
                bytes = BitConverter.GetBytes(len);
                for (int i = 0; i < 4; i++)
                {
                    d[i] = 0xff;
                }
                for (int i = 0; i < 8; i++)
                {
                    d[i + 4] = bytes[i];
                }
            }

            // Store to section
            for (int i = 0; i < d.Count; i++)
            {
                odbgsect.line.Data.Add(d[i]);
            }
        }
Beispiel #9
0
        private void WritePubNames(DwarfSections odbgsect)
        {
            /* Write lines header */
            List <byte> d = new List <byte>();

            // Reserve space for unit_length
            if (t.psize == 4)
            {
                for (int i = 0; i < 4; i++)
                {
                    d.Add(0);
                }
            }
            else
            {
                for (int i = 0; i < 12; i++)
                {
                    d.Add(0);
                }
            }

            // version
            d.Add(2);
            d.Add(0);

            // debug_info_offset
            for (int i = 0; i < t.psize; i++)
            {
                d.Add(0);
            }

            // debug_info_length
            var length = odbgsect.info.Data.Count;
            var bytes  = (t.psize == 4) ? BitConverter.GetBytes((int)length) :
                         BitConverter.GetBytes((long)length);

            foreach (var b in bytes)
            {
                d.Add(b);
            }

            foreach (var kvp in method_dies)
            {
                // offset
                bytes = (t.psize == 4) ? BitConverter.GetBytes((int)kvp.Value.Offset) :
                        BitConverter.GetBytes((long)kvp.Value.Offset);
                foreach (var b in bytes)
                {
                    d.Add(b);
                }

                // name
                foreach (var c in kvp.Key.MangleMethod())
                {
                    d.Add((byte)c);
                }
                d.Add(0);
            }

            // Finally, patch the length back in
            if (t.psize == 4)
            {
                uint len = (uint)d.Count - 4;
                bytes = BitConverter.GetBytes(len);
                for (int i = 0; i < 4; i++)
                {
                    d[i] = bytes[i];
                }
            }
            else
            {
                ulong len = (ulong)d.Count - 12;
                bytes = BitConverter.GetBytes(len);
                for (int i = 0; i < 4; i++)
                {
                    d[i] = 0xff;
                }
                for (int i = 0; i < 8; i++)
                {
                    d[i + 4] = bytes[i];
                }
            }

            // Store to section
            for (int i = 0; i < d.Count; i++)
            {
                odbgsect.pubnames.Data.Add(d[i]);
            }
        }
Beispiel #10
0
 public abstract void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent);
Beispiel #11
0
        public override void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent)
        {
            var ms = cil.ms;

            int abbrev = 5;

            if (ms.ReturnType != null)
            {
                abbrev += 1;
            }
            if (!ms.IsStatic)
            {
                abbrev += 2;
                if (ms.IsVirtual)
                {
                    abbrev += 2;
                }
            }

            d.Add((byte)abbrev);
            w(d, ms.Name, ds.smap);
            var low_r = ds.bf.CreateRelocation();

            low_r.Type       = t.GetDataToDataReloc();
            low_r.Offset     = (ulong)d.Count;
            low_r.References = ds.bf.FindSymbol(ms.MangleMethod());
            low_r.DefinedIn  = ds.info;
            ds.bf.AddRelocation(low_r);
            wp(d);                        // low_pc
            wp(d, low_r.References.Size); // high_pc

            // Update first/last sym if necessary
            if (dcu.first_sym == null || low_r.References.Offset < dcu.first_sym.Offset)
            {
                dcu.first_sym = low_r.References;
            }
            if (dcu.last_sym == null || low_r.References.Offset > dcu.last_sym.Offset)
            {
                dcu.last_sym = low_r.References;
            }

            var mflags = ms.m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                          ms.mdrow, 2);
            var access = mflags & 0x07;

            if (access == 0x6)
            {
                d.Add(0x1); // public
            }
            else if (access >= 0x4)
            {
                d.Add(0x2); // protected
            }
            else
            {
                d.Add(0x3); // private
            }
            w(d, ms.MangleMethod(), ds.smap);

            if (ms.ReturnType != null)
            {
                dcu.fmap[d.Count] = (ms.ReturnType.stype == metadata.TypeSpec.SpecialType.None && !ms.ReturnType.IsValueType) ?
                                    dcu.GetTypeDie(ms.ReturnType.Pointer) :
                                    dcu.GetTypeDie(ms.ReturnType);

                // add return type
                for (int i = 0; i < 4; i++)
                {
                    d.Add(0);
                }
            }

            int fparam_ref_loc = 0;

            if (!ms.IsStatic)
            {
                // reference for first parameter
                fparam_ref_loc = d.Count;

                for (int i = 0; i < 4; i++)
                {
                    d.Add(0);
                }
            }

            if (ms.IsVirtual)
            {
                d.Add(0x1); // virtual
            }

            // Add parameters
            int sig_idx = ms.mdrow == 0 ? ms.msig :
                          (int)ms.m.GetIntEntry(metadata.MetadataStream.tid_MethodDef, ms.mdrow, 4);

            var pc_nonthis = ms.m.GetMethodDefSigParamCount(sig_idx);
            var rt_idx     = ms.m.GetMethodDefSigRetTypeIndex(sig_idx);

            ms.m.GetTypeSpec(ref rt_idx, ms.gtparams, ms.gmparams);

            if (ms.m.GetMethodDefSigHasNonExplicitThis(ms.msig))
            {
                var fparam = new DwarfParamDIE();
                fparam.dcu    = dcu;
                fparam.t      = t;
                fparam.IsThis = true;
                fparam.ts     = ms.type.Pointer;

                Children.Add(fparam);
            }

            for (int i = 0; i < pc_nonthis; i++)
            {
                var fparam = new DwarfParamDIE();
                fparam.dcu    = dcu;
                fparam.t      = t;
                fparam.IsThis = false;
                fparam.ts     = ms.m.GetTypeSpec(ref rt_idx, ms.gtparams, ms.gmparams);

                if (fparam.ts.stype == metadata.TypeSpec.SpecialType.None &&
                    !fparam.ts.IsValueType)
                {
                    fparam.ts = fparam.ts.Pointer;
                }

                Children.Add(fparam);
            }

            // Get param names
            if (ms.mdrow != 0)
            {
                int param_start = (int)ms.m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                                        ms.mdrow, 5);

                int param_last_row = ms.m.GetRowCount(metadata.MetadataStream.tid_Param);
                int next_param     = int.MaxValue;
                if (ms.mdrow < ms.m.GetRowCount(metadata.MetadataStream.tid_MethodDef))
                {
                    next_param = (int)ms.m.GetIntEntry(metadata.MetadataStream.tid_MethodDef,
                                                       ms.mdrow + 1, 5) - 1;
                }
                int param_end = param_last_row > next_param ? next_param : param_last_row;

                for (int i = param_start; i <= param_end; i++)
                {
                    var seq = ms.m.GetIntEntry(metadata.MetadataStream.tid_Param,
                                               i, 1);
                    var name = ms.m.GetStringEntry(metadata.MetadataStream.tid_Param,
                                                   i, 2);

                    seq--;
                    if (ms.m.GetMethodDefSigHasNonExplicitThis(ms.msig))
                    {
                        seq++;
                    }

                    ((DwarfParamDIE)Children[(int)seq]).name = name;
                }
            }

            if (!ms.IsStatic)
            {
                // Patch the .this pointer to the first child
                dcu.fmap[fparam_ref_loc] = Children[0];
            }

            // Param locations
            if (cil != null && cil.la_locs != null && cil.la_locs.Length == Children.Count)
            {
                for (int i = 0; i < cil.la_locs.Length; i++)
                {
                    ((DwarfParamDIE)Children[i]).loc = cil.la_locs[i];
                }
            }

            // Get param names
            if (ms.mdrow != 0)
            {
                string[] pnames = new string[cil.lv_types.Length];

                if (ms.m.pdb != null)
                {
                    for (int i = 1; i < ms.m.pdb.table_rows[(int)metadata.MetadataStream.TableId.LocalScope]; i++)
                    {
                        var lv_mdrow = (int)ms.m.pdb.GetIntEntry((int)metadata.MetadataStream.TableId.LocalScope,
                                                                 i, 0);
                        if (lv_mdrow == ms.mdrow)
                        {
                            var lv_start = (int)ms.m.pdb.GetIntEntry((int)metadata.MetadataStream.TableId.LocalScope,
                                                                     i, 2);

                            int lv_last_row = ms.m.pdb.GetRowCount((int)metadata.MetadataStream.TableId.LocalVariable);
                            int next_lv     = int.MaxValue;
                            if (i < ms.m.pdb.GetRowCount((int)metadata.MetadataStream.TableId.LocalScope))
                            {
                                next_lv = (int)ms.m.pdb.GetIntEntry((int)metadata.MetadataStream.TableId.LocalScope,
                                                                    i + 1, 2) - 1;
                            }
                            int lv_end = lv_last_row > next_lv ? next_lv : lv_last_row;

                            for (int j = lv_start; j <= lv_end; j++)
                            {
                                var pindex = (int)ms.m.pdb.GetIntEntry((int)metadata.MetadataStream.TableId.LocalVariable,
                                                                       j, 1);
                                var pname = ms.m.pdb.GetStringEntry((int)metadata.MetadataStream.TableId.LocalVariable,
                                                                    j, 2);

                                pnames[pindex] = pname;
                            }
                        }
                    }
                }

                for (int i = 0; i < pnames.Length; i++)
                {
                    var pname = pnames[i];
                    if (pname != null)
                    {
                        var ptype = cil.lv_types[i];
                        var ploc  = cil.lv_locs[i];

                        var vparam = new DwarfVarDIE();
                        vparam.dcu  = dcu;
                        vparam.t    = t;
                        vparam.ts   = ptype;
                        vparam.name = pname;
                        vparam.loc  = ploc;

                        if (vparam.ts.stype == metadata.TypeSpec.SpecialType.None &&
                            !vparam.ts.IsValueType)
                        {
                            vparam.ts = vparam.ts.Pointer;
                        }

                        Children.Add(vparam);
                    }
                }
            }

            base.WriteToOutput(ds, d, parent);
        }
Beispiel #12
0
        public override void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent)
        {
            switch (stype)
            {
            case 0x02:
                // bool
                d.Add(15);
                w(d, "bool", ds.smap);
                d.Add((byte)t.GetSize(dcu.m.SystemBool));
                d.Add(0x07);        // unsigned
                break;

            case 0x03:
                // Char
                d.Add(15);
                w(d, "char", ds.smap);
                d.Add(2);
                d.Add(0x06);        // signed char
                break;

            case 0x04:
                // I1
                d.Add(15);
                w(d, "sbyte", ds.smap);
                d.Add(1);
                d.Add(0x05);        // signed
                break;

            case 0x05:
                // U1
                d.Add(15);
                w(d, "byte", ds.smap);
                d.Add(1);
                d.Add(0x07);        // unsigned
                break;

            case 0x06:
                // I2
                d.Add(15);
                w(d, "short", ds.smap);
                d.Add(2);
                d.Add(0x05);        // signed
                break;

            case 0x07:
                // U2
                d.Add(15);
                w(d, "ushort", ds.smap);
                d.Add(2);
                d.Add(0x07);        // unsigned
                break;

            case 0x08:
                // I4
                d.Add(15);
                w(d, "int", ds.smap);
                d.Add(4);
                d.Add(0x05);        // signed
                break;

            case 0x09:
                // U4
                d.Add(15);
                w(d, "uint", ds.smap);
                d.Add(4);
                d.Add(0x07);        // unsigned
                break;

            case 0x0a:
                // I8
                d.Add(15);
                w(d, "long", ds.smap);
                d.Add(8);
                d.Add(0x05);        // signed
                break;

            case 0x0b:
                // U8
                d.Add(15);
                w(d, "ulong", ds.smap);
                d.Add(8);
                d.Add(0x07);        // unsigned
                break;

            case 0x0c:
                // R4
                d.Add(15);
                w(d, "float", ds.smap);
                d.Add(4);
                d.Add(0x04);        // float
                break;

            case 0x0d:
                // R8
                d.Add(15);
                w(d, "double", ds.smap);
                d.Add(8);
                d.Add(0x04);        // float
                break;


            default:
                throw new NotImplementedException();
            }
        }
Beispiel #13
0
        private void WriteBaseType(int st, DwarfSections ds, IList <byte> d, DwarfDIE parent)
        {
            if (parent is DwarfNSDIE && ((DwarfNSDIE)parent).ns == "System" && dcu.basetype_dies.ContainsKey(st))
            {
                // These are typedefs to types in the global scope
                d.Add(20);
                w(d, ts.Name, ds.smap);
                dcu.fmap[d.Count] = dcu.basetype_dies[st];
                for (int i = 0; i < 4; i++)
                {
                    d.Add(0);
                }

                if (st == 0x1c)
                {
                    System.Diagnostics.Debugger.Break();
                }
            }
            else
            {
                /* There are a few CLI basetypes that do not have C# equivalents
                 * or this is a string/object in the main namespace */
                switch (st)
                {
                case 0x11:
                    // ValueType
                    // class_type
                    d.Add(13);
                    w(d, "ValueType", ds.smap);
                    w(d, (uint)t.GetSize(ts));
                    base.WriteToOutput(ds, d, parent);
                    break;

                case 0x18:
                    // IntPtr
                    d.Add(20);
                    w(d, "IntPtr", ds.smap);
                    dcu.fmap[d.Count] = dcu.basetype_dies[t.psize == 4 ? 0x08 : 0x0a];
                    for (int i = 0; i < 4; i++)
                    {
                        d.Add(0);
                    }
                    break;

                case 0x19:
                    // IntPtr
                    d.Add(20);
                    w(d, "UIntPtr", ds.smap);
                    dcu.fmap[d.Count] = dcu.basetype_dies[t.psize == 4 ? 0x09 : 0x0b];
                    for (int i = 0; i < 4; i++)
                    {
                        d.Add(0);
                    }
                    break;

                case 0x0e:
                    // String
                    // class_type
                    d.Add(13);
                    w(d, NameOverride ?? "String", ds.smap);
                    w(d, 0);            // size - TODO
                    base.WriteToOutput(ds, d, parent);
                    break;

                case 0x1c:
                    // Object
                    // class_type
                    d.Add(13);
                    w(d, NameOverride ?? "Object", ds.smap);
                    w(d, (uint)t.GetSize(ts));
                    base.WriteToOutput(ds, d, parent);
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
Beispiel #14
0
        public override void WriteToOutput(DwarfSections ds, IList <byte> d, DwarfDIE parent)
        {
            int abbrev;

            // decide upon type
            switch (ts.stype)
            {
            case metadata.TypeSpec.SpecialType.Ptr:
            case metadata.TypeSpec.SpecialType.MPtr:
                d.Add(16);
                d.Add((byte)t.psize);
                dcu.fmap[d.Count] = dcu.GetTypeDie(ts.other);
                for (int i = 0; i < 4; i++)
                {
                    d.Add(0);
                }
                break;

            case metadata.TypeSpec.SpecialType.Array:
                throw new NotImplementedException();

            case metadata.TypeSpec.SpecialType.SzArray:
                throw new NotImplementedException();

            case metadata.TypeSpec.SpecialType.None:
                if (ts.SimpleType != 0)
                {
                    // base_type
                    WriteBaseType(ts.SimpleType, ds, d, parent);
                }
                else if (ts.IsValueType && (ts.m == dcu.m))
                {
                    if (ts.m == dcu.m)
                    {
                        // structure_type
                        var source_loc = GetSourceLoc();
                        if (source_loc == null)
                        {
                            d.Add(14);
                        }
                        else
                        {
                            d.Add(24);
                        }
                        w(d, ts.Name, ds.smap);
                        w(d, (uint)t.GetSize(ts));

                        if (source_loc != null)
                        {
                            d.Add((byte)source_loc.file);
                            d.Add((byte)source_loc.line);
                            d.Add((byte)source_loc.col);
                        }

                        base.WriteToOutput(ds, d, parent);
                    }
                    else
                    {
                        // structure_type external
                        throw new NotImplementedException();
                    }
                }
                else
                {
                    if (ts.m == dcu.m)
                    {
                        // class_type
                        var source_loc = GetSourceLoc();
                        if (source_loc == null)
                        {
                            d.Add(13);
                        }
                        else
                        {
                            d.Add(23);
                        }
                        w(d, ts.Name, ds.smap);
                        w(d, (uint)t.GetSize(ts));

                        if (source_loc != null)
                        {
                            d.Add((byte)source_loc.file);
                            d.Add((byte)source_loc.line);
                            d.Add((byte)source_loc.col);
                        }

                        base.WriteToOutput(ds, d, parent);
                    }
                    else
                    {
                        // class_type external
                        throw new NotImplementedException();
                    }
                }
                break;

            default:
                throw new NotImplementedException();
            }
        }