2 // System.Diagnostics.SymbolStore/MonoDwarfWriter.cs
5 // Martin Baulig (martin@gnome.org)
7 // This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter
10 // (C) 2002 Ximian, Inc. http://www.ximian.com
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Diagnostics.SymbolStore;
17 using System.Collections;
20 namespace Mono.CSharp.Debugger
23 public class DwarfFileWriter
25 protected const string producer_id = "Mono C# Compiler 0.01 03-18-2002";
27 protected ArrayList compile_units = new ArrayList ();
28 protected ArrayList line_number_engines = new ArrayList ();
29 protected StreamWriter writer = null;
30 protected string symbol_file = null;
32 // Write a generic file which contains no machine dependant stuff but
33 // only function and type declarations.
34 protected readonly bool DoGeneric = false;
37 // DwarfFileWriter public interface
39 public DwarfFileWriter (string symbol_file)
41 this.symbol_file = symbol_file;
42 this.writer = new StreamWriter (symbol_file);
45 // Writes the final dwarf file.
48 foreach (CompileUnit compile_unit in compile_units)
51 foreach (LineNumberEngine line_number_engine in line_number_engines)
52 line_number_engine.Emit ();
54 WriteAbbrevDeclarations ();
60 // Adds a new compile unit to this dwarf file
61 public void AddCompileUnit (CompileUnit compile_unit)
63 compile_units.Add (compile_unit);
66 // Adds a new line number engine to this dwarf file
67 public void AddLineNumberEngine (LineNumberEngine line_number_engine)
69 line_number_engines.Add (line_number_engine);
72 // This string is written into the generated dwarf file to identify the
73 // producer and version number.
74 public string ProducerID {
81 // Create a debugging information entry for the given type.
83 public Die CreateType (DieCompileUnit die_compile_unit, Type type)
86 return new DieBaseType (die_compile_unit, type);
87 else if (type.IsPointer)
88 return new DiePointerType (die_compile_unit, type.GetElementType ());
90 throw new NotSupportedException ("Type " + type + " is not yet supported.");
94 // A compile unit refers to a single C# source file.
96 public class CompileUnit
98 protected DwarfFileWriter dw;
99 protected string source_file;
100 protected ArrayList dies = new ArrayList ();
102 private static int next_ref_index = 0;
104 public readonly int ReferenceIndex;
105 public readonly string ReferenceLabel;
107 public CompileUnit (DwarfFileWriter dw, string source_file, Die[] dies)
110 this.source_file = source_file;
112 this.dies.AddRange (dies);
114 this.ReferenceIndex = ++next_ref_index;
115 this.ReferenceLabel = ".L_COMPILE_UNIT_" + this.ReferenceIndex;
117 dw.AddCompileUnit (this);
121 // Construct a new compile unit for source file @source_file.
123 // This constructor automatically adds the newly created compile
124 // unit to the DwarfFileWriter's list of compile units.
126 public CompileUnit (DwarfFileWriter dw, string source_file)
127 : this (dw, source_file, null)
130 public string SourceFile {
136 public string ProducerID {
138 return dw.ProducerID;
142 public DwarfFileWriter DwarfFileWriter
149 // Add a new debugging information entry to this compile unit.
150 public void AddDie (Die die)
155 // Write the whole compile unit to the dwarf file.
158 int start_index, end_index;
160 dw.WriteSectionStart (Section.DEBUG_INFO);
162 dw.WriteLabel (ReferenceLabel);
164 start_index = dw.WriteAnonLabel ();
166 end_index = dw.WriteSectionSize ();
168 dw.WriteOffset ("debug_abbrev_b");
172 dw.AddRelocEntry (RelocEntryType.TARGET_ADDRESS_SIZE);
177 foreach (Die die in dies)
180 dw.WriteAnonLabel (end_index);
182 dw.WriteSectionEnd ();
186 public class LineNumberEngine
188 public readonly int ReferenceIndex;
189 public readonly string ReferenceLabel;
191 public readonly int LineBase = 1;
192 public readonly int LineRange = 8;
194 protected DwarfFileWriter dw;
196 public readonly int[] StandardOpcodeSizes = {
197 0, 0, 1, 1, 1, 1, 0, 0, 0, 0
200 public readonly int OpcodeBase;
202 private Hashtable _sources = new Hashtable ();
203 private Hashtable _directories = new Hashtable ();
204 private Hashtable _methods = new Hashtable ();
206 private int next_source_id;
207 private int next_directory_id;
209 private static int next_ref_index;
210 private static int next_method_id;
212 private enum DW_LNS {
216 LNS_advance_line = 3,
220 LNS_set_basic_block = 7,
221 LNS_const_add_pc = 8,
222 LNS_fixed_advance_pc = 9
225 private enum DW_LNE {
226 LNE_end_sequence = 1,
232 public ISourceFile[] Sources {
234 ISourceFile[] retval = new ISourceFile [_sources.Count];
236 foreach (ISourceFile source in _sources.Keys)
237 retval [(int) _sources [source] - 1] = source;
243 public string[] Directories {
245 string[] retval = new string [_directories.Count];
247 foreach (string directory in _directories.Keys)
248 retval [(int) _directories [directory] - 1] = directory;
254 public ISourceMethod[] Methods {
256 ISourceMethod[] retval = new ISourceMethod [_methods.Count];
258 foreach (ISourceMethod method in _methods.Keys)
259 retval [(int) _methods [method] - 1] = method;
265 public LineNumberEngine (DwarfFileWriter writer)
268 this.ReferenceIndex = ++next_ref_index;
269 this.ReferenceLabel = ".L_DEBUG_LINE_" + this.ReferenceIndex;
271 dw.AddLineNumberEngine (this);
274 public int LookupSource (ISourceFile source)
276 if (_sources.ContainsKey (source))
277 return (int) _sources [source];
279 int index = ++next_source_id;
280 _sources.Add (source, index);
284 public int LookupDirectory (string directory)
286 if (_directories.ContainsKey (directory))
287 return (int) _directories [directory];
289 int index = ++next_directory_id;
290 _directories.Add (directory, index);
294 public void AddMethod (ISourceMethod method)
296 LookupSource (method.SourceFile);
298 int index = ++next_method_id;
299 _methods.Add (method, index);
302 private void SetFile (ISourceFile source)
304 dw.WriteInt8 ((int) DW_LNS.LNS_set_file);
305 dw.WriteULeb128 (LookupSource (source));
308 private int st_line = 1;
309 private int st_address = 0;
311 private void SetLine (int line)
313 dw.WriteInt8 ((int) DW_LNS.LNS_advance_line);
314 dw.WriteSLeb128 (line - st_line);
318 private void SetAddress (int token, int address)
321 int end_index = dw.WriteShortSectionSize ();
322 dw.WriteUInt8 ((int) DW_LNE.LNE_set_address);
323 dw.AddRelocEntry (RelocEntryType.IL_OFFSET, token);
324 dw.WriteAddress (address);
325 dw.WriteAnonLabel (end_index);
326 st_address = address;
329 private void EndSequence ()
333 dw.WriteUInt8 ((int) DW_LNE.LNE_end_sequence);
336 private void Commit ()
338 dw.WriteUInt8 ((int) DW_LNS.LNS_copy);
343 dw.WriteSectionStart (Section.DEBUG_LINE);
344 dw.WriteLabel (ReferenceLabel);
345 int end_index = dw.WriteSectionSize ();
348 int start_index = dw.WriteSectionSize ();
351 dw.WriteInt8 (LineBase);
352 dw.WriteUInt8 (LineRange);
353 dw.WriteUInt8 (StandardOpcodeSizes.Length);
354 for (int i = 1; i < StandardOpcodeSizes.Length; i++)
355 dw.WriteUInt8 (StandardOpcodeSizes [i]);
357 foreach (string directory in Directories)
358 dw.WriteString (directory);
361 foreach (ISourceFile source in Sources) {
362 dw.WriteString (source.FileName);
370 dw.WriteAnonLabel (start_index);
372 foreach (ISourceMethod method in Methods) {
373 SetFile (method.SourceFile);
374 SetLine (method.FirstLine);
375 SetAddress (method.Token, 0);
378 foreach (ISourceLine line in method.Lines) {
380 SetAddress (method.Token, line.Offset);
384 SetLine (method.LastLine);
385 if (method.CodeSize >= 0)
386 SetAddress (method.Token, method.CodeSize);
392 dw.WriteAnonLabel (end_index);
393 dw.WriteSectionEnd ();
397 // DWARF tag from the DWARF 2 specification.
399 TAG_pointer_type = 0x0f,
400 TAG_compile_unit = 0x11,
401 TAG_base_type = 0x24,
402 TAG_subprogram = 0x2e
405 // DWARF attribute from the DWARF 2 specification.
414 AT_declaration = 0x3c,
420 // DWARF form from the DWARF 2 specification.
421 public enum DW_FORM {
430 public enum DW_LANG {
431 LANG_C_plus_plus = 0x04,
432 LANG_C_sharp = LANG_C_plus_plus
435 // Abstract base class for a "debugging information entry" (die).
436 public abstract class Die
438 protected DwarfFileWriter dw;
439 protected ArrayList child_dies = new ArrayList ();
440 public readonly Die Parent;
442 private static int next_ref_index = 0;
444 protected readonly int abbrev_id;
445 protected readonly AbbrevDeclaration abbrev_decl;
447 public readonly int ReferenceIndex;
448 public readonly string ReferenceLabel;
451 // Create a new die If @parent is not null, add the newly
452 // created die to the parent's list of child dies.
454 // @abbrev_id is the abbreviation id for this die class.
455 // Derived classes should call the DwarfFileWriter's static
456 // RegisterAbbrevDeclaration function in their static constructor
457 // to get an abbrev id. Once you registered an abbrev entry, it'll
458 // be automatically written to the debug_abbrev section.
460 public Die (DwarfFileWriter dw, Die parent, int abbrev_id)
463 this.Parent = parent;
464 this.abbrev_id = abbrev_id;
465 this.abbrev_decl = GetAbbrevDeclaration (abbrev_id);
466 this.ReferenceIndex = ++next_ref_index;
467 this.ReferenceLabel = ".L_DIE_" + this.ReferenceIndex;
470 parent.AddChildDie (this);
473 public Die (DwarfFileWriter dw, int abbrev_id)
474 : this (dw, null, abbrev_id)
477 public Die (Die parent, int abbrev_id)
478 : this (parent.dw, parent, abbrev_id)
481 protected void AddChildDie (Die die)
483 child_dies.Add (die);
486 public override bool Equals (object o)
491 return ((Die) o).ReferenceIndex == ReferenceIndex;
494 public override int GetHashCode ()
496 return ReferenceIndex;
500 // Write this die and all its children to the dwarf file.
502 public virtual void Emit ()
504 dw.WriteLabel (ReferenceLabel);
506 dw.WriteULeb128 (abbrev_id);
509 if (abbrev_decl.HasChildren) {
510 foreach (Die child in child_dies)
518 // Derived classes must implement this function to actually
519 // write themselves to the dwarf file.
521 // Note that the abbrev id has already been written in Emit() -
522 // if you don't like this, you must override Emit() as well.
524 public abstract void DoEmit ();
527 // Gets the compile unit of this die.
529 public virtual DieCompileUnit GetCompileUnit ()
533 while (die.Parent != null)
536 if (die is DieCompileUnit)
537 return (DieCompileUnit) die;
542 public DieCompileUnit DieCompileUnit {
544 return GetCompileUnit ();
549 // DW_TAG_compile_unit
550 public class DieCompileUnit : Die
552 private static int my_abbrev_id;
554 protected Hashtable types = new Hashtable ();
556 static DieCompileUnit ()
558 AbbrevEntry[] entries = {
559 new AbbrevEntry (DW_AT.AT_name, DW_FORM.FORM_string),
560 new AbbrevEntry (DW_AT.AT_producer, DW_FORM.FORM_string),
561 new AbbrevEntry (DW_AT.AT_language, DW_FORM.FORM_data1),
562 new AbbrevEntry (DW_AT.AT_stmt_list, DW_FORM.FORM_ref4)
564 AbbrevDeclaration decl = new AbbrevDeclaration (
565 DW_TAG.TAG_compile_unit, true, entries);
567 my_abbrev_id = RegisterAbbrevDeclaration (decl);
570 public readonly CompileUnit CompileUnit;
571 public readonly bool DoGeneric;
572 public readonly LineNumberEngine LineNumberEngine;
575 // Create a new DW_TAG_compile_unit debugging information entry
576 // and add it to the @compile_unit.
578 public DieCompileUnit (CompileUnit compile_unit)
579 : base (compile_unit.DwarfFileWriter, my_abbrev_id)
581 this.CompileUnit = compile_unit;
582 this.DoGeneric = dw.DoGeneric;
583 compile_unit.AddDie (this);
585 // GDB doesn't support DW_TAG_base_types yet, so we need to
586 // include the types in each compile unit.
587 RegisterType (typeof (bool));
588 RegisterType (typeof (char));
589 RegisterType (typeof (SByte));
590 RegisterType (typeof (Byte));
591 RegisterType (typeof (Int16));
592 RegisterType (typeof (UInt16));
593 RegisterType (typeof (Int32));
594 RegisterType (typeof (UInt32));
595 RegisterType (typeof (Int64));
596 RegisterType (typeof (UInt64));
597 RegisterType (typeof (Single));
598 RegisterType (typeof (Double));
600 LineNumberEngine = new LineNumberEngine (dw);
603 // Registers a new type
604 public Die RegisterType (Type type)
606 if (types.Contains (type))
607 return (Die) types [type];
609 Die die = dw.CreateType (this, type);
611 types.Add (type, die);
615 public void WriteRelativeDieReference (Die target_die)
617 if (!this.Equals (target_die.GetCompileUnit ()))
618 throw new ArgumentException ("Target die must be in the same "
621 dw.WriteRelativeReference (CompileUnit.ReferenceLabel,
622 target_die.ReferenceLabel);
625 public override void DoEmit ()
627 dw.WriteString (CompileUnit.SourceFile);
628 dw.WriteString (CompileUnit.ProducerID);
629 dw.WriteUInt8 ((int) DW_LANG.LANG_C_sharp);
630 dw.WriteAbsoluteReference (LineNumberEngine.ReferenceLabel);
635 public class DieSubProgram : Die
637 private static int my_abbrev_id_1;
638 private static int my_abbrev_id_2;
639 private static int my_abbrev_id_3;
640 private static int my_abbrev_id_4;
642 static DieSubProgram ()
644 // Method without return value
645 AbbrevEntry[] entries_1 = {
646 new AbbrevEntry (DW_AT.AT_name, DW_FORM.FORM_string),
647 new AbbrevEntry (DW_AT.AT_external, DW_FORM.FORM_flag),
648 new AbbrevEntry (DW_AT.AT_low_pc, DW_FORM.FORM_addr),
649 new AbbrevEntry (DW_AT.AT_high_pc, DW_FORM.FORM_addr)
651 // Method with return value
652 AbbrevEntry[] entries_2 = {
653 new AbbrevEntry (DW_AT.AT_name, DW_FORM.FORM_string),
654 new AbbrevEntry (DW_AT.AT_external, DW_FORM.FORM_flag),
655 new AbbrevEntry (DW_AT.AT_low_pc, DW_FORM.FORM_addr),
656 new AbbrevEntry (DW_AT.AT_high_pc, DW_FORM.FORM_addr),
657 new AbbrevEntry (DW_AT.AT_type, DW_FORM.FORM_ref4)
659 // Method declaration without return value
660 AbbrevEntry[] entries_3 = {
661 new AbbrevEntry (DW_AT.AT_name, DW_FORM.FORM_string),
662 new AbbrevEntry (DW_AT.AT_external, DW_FORM.FORM_flag),
663 new AbbrevEntry (DW_AT.AT_declaration, DW_FORM.FORM_flag)
665 // Method declaration with return value
666 AbbrevEntry[] entries_4 = {
667 new AbbrevEntry (DW_AT.AT_name, DW_FORM.FORM_string),
668 new AbbrevEntry (DW_AT.AT_external, DW_FORM.FORM_flag),
669 new AbbrevEntry (DW_AT.AT_declaration, DW_FORM.FORM_flag),
670 new AbbrevEntry (DW_AT.AT_type, DW_FORM.FORM_ref4)
674 AbbrevDeclaration decl_1 = new AbbrevDeclaration (
675 DW_TAG.TAG_subprogram, true, entries_1);
676 AbbrevDeclaration decl_2 = new AbbrevDeclaration (
677 DW_TAG.TAG_subprogram, true, entries_2);
678 AbbrevDeclaration decl_3 = new AbbrevDeclaration (
679 DW_TAG.TAG_subprogram, true, entries_3);
680 AbbrevDeclaration decl_4 = new AbbrevDeclaration (
681 DW_TAG.TAG_subprogram, true, entries_4);
683 my_abbrev_id_1 = RegisterAbbrevDeclaration (decl_1);
684 my_abbrev_id_2 = RegisterAbbrevDeclaration (decl_2);
685 my_abbrev_id_3 = RegisterAbbrevDeclaration (decl_3);
686 my_abbrev_id_4 = RegisterAbbrevDeclaration (decl_4);
689 private static int get_abbrev_id (DieCompileUnit parent_die, ISourceMethod method)
691 if (parent_die.DoGeneric)
692 if (method.MethodInfo.ReturnType == typeof (void))
693 return my_abbrev_id_3;
695 return my_abbrev_id_4;
697 if (method.MethodInfo.ReturnType == typeof (void))
698 return my_abbrev_id_1;
700 return my_abbrev_id_2;
703 protected ISourceMethod method;
704 protected Die retval_die;
707 // Create a new DW_TAG_subprogram debugging information entry
708 // for method @name (which has a void return value) and add it
709 // to the @parent_die
711 public DieSubProgram (DieCompileUnit parent_die, ISourceMethod method)
712 : base (parent_die, get_abbrev_id (parent_die, method))
714 this.method = method;
716 if (method.MethodInfo.ReturnType != typeof (void))
717 retval_die = DieCompileUnit.RegisterType (
718 method.MethodInfo.ReturnType);
720 DieCompileUnit.LineNumberEngine.AddMethod (method);
723 public override void DoEmit ()
725 dw.WriteString (method.MethodInfo.Name);
730 dw.AddRelocEntry (RelocEntryType.IL_OFFSET, method.Token);
732 dw.AddRelocEntry (RelocEntryType.IL_OFFSET, method.Token);
735 if (method.MethodInfo.ReturnType != typeof (void))
736 DieCompileUnit.WriteRelativeDieReference (retval_die);
741 public class DieBaseType : Die
743 private static int my_abbrev_id;
745 static DieBaseType ()
747 AbbrevEntry[] entries = {
748 new AbbrevEntry (DW_AT.AT_name, DW_FORM.FORM_string),
749 new AbbrevEntry (DW_AT.AT_encoding, DW_FORM.FORM_data1),
750 new AbbrevEntry (DW_AT.AT_byte_size, DW_FORM.FORM_data1)
753 AbbrevDeclaration decl = new AbbrevDeclaration (
754 DW_TAG.TAG_base_type, false, entries);
756 my_abbrev_id = RegisterAbbrevDeclaration (decl);
762 // Create a new DW_TAG_base_type debugging information entry
764 public DieBaseType (DieCompileUnit parent_die, Type type)
765 : base (parent_die, my_abbrev_id)
770 protected enum DW_ATE {
774 ATE_complex_float = 0x03,
777 ATE_signed_char = 0x06,
779 ATE_unsigned_char = 0x08
782 public override void DoEmit ()
784 string name = type.Name;
786 dw.WriteString (name);
789 dw.WriteUInt8 ((int) DW_ATE.ATE_address);
793 dw.WriteUInt8 ((int) DW_ATE.ATE_boolean);
797 dw.WriteUInt8 ((int) DW_ATE.ATE_unsigned_char);
801 dw.WriteUInt8 ((int) DW_ATE.ATE_signed);
805 dw.WriteUInt8 ((int) DW_ATE.ATE_unsigned);
809 dw.WriteUInt8 ((int) DW_ATE.ATE_signed);
813 dw.WriteUInt8 ((int) DW_ATE.ATE_unsigned);
817 dw.WriteUInt8 ((int) DW_ATE.ATE_signed);
821 dw.WriteUInt8 ((int) DW_ATE.ATE_unsigned);
825 dw.WriteUInt8 ((int) DW_ATE.ATE_signed);
829 dw.WriteUInt8 ((int) DW_ATE.ATE_unsigned);
833 dw.WriteUInt8 ((int) DW_ATE.ATE_float);
837 dw.WriteUInt8 ((int) DW_ATE.ATE_float);
841 throw new ArgumentException ("Not a base type: " + type);
846 // DW_TAG_pointer_type
847 public class DiePointerType : Die
849 private static int my_abbrev_id;
851 static DiePointerType ()
853 AbbrevEntry[] entries = {
854 new AbbrevEntry (DW_AT.AT_type, DW_FORM.FORM_ref4)
857 AbbrevDeclaration decl = new AbbrevDeclaration (
858 DW_TAG.TAG_pointer_type, false, entries);
860 my_abbrev_id = RegisterAbbrevDeclaration (decl);
864 protected Die type_die;
867 // Create a new type DIE describing a pointer to @type.
869 public DiePointerType (DieCompileUnit parent_die, Type type)
870 : base (parent_die, my_abbrev_id)
873 type_die = DieCompileUnit.RegisterType (type);
876 public override void DoEmit ()
878 DieCompileUnit.WriteRelativeDieReference (type_die);
882 protected const int reloc_table_version = 2;
884 protected enum Section {
891 public struct AbbrevEntry {
892 public AbbrevEntry (DW_AT attribute, DW_FORM form)
894 this._attribute = attribute;
898 private DW_AT _attribute;
899 private DW_FORM _form;
901 public DW_AT Attribute {
907 public DW_FORM Form {
914 public struct AbbrevDeclaration {
915 public AbbrevDeclaration (DW_TAG tag, bool has_children, AbbrevEntry[] entries)
918 this._has_children = has_children;
919 this._entries = entries;
923 private bool _has_children;
924 private AbbrevEntry[] _entries;
932 public bool HasChildren {
934 return _has_children;
938 public AbbrevEntry[] Entries {
945 protected enum RelocEntryType {
947 // Size of an address on the target machine
948 TARGET_ADDRESS_SIZE = 0x01,
949 // Map an IL offset to a machine address
953 protected class RelocEntry {
954 public RelocEntry (RelocEntryType type, int token, Section section, int index)
962 public RelocEntryType RelocType {
968 public Section Section {
986 private RelocEntryType _type;
987 private Section _section;
992 private int next_anon_label_idx = 0;
993 private Section current_section;
994 private ArrayList reloc_entries = new ArrayList ();
996 private static ArrayList abbrev_declarations = new ArrayList ();
998 protected string GetSectionName (Section section)
1001 case Section.DEBUG_INFO:
1002 return "debug_info";
1003 case Section.DEBUG_ABBREV:
1004 return "debug_abbrev";
1005 case Section.DEBUG_LINE:
1006 return "debug_line";
1007 case Section.MONO_RELOC_TABLE:
1008 return "mono_reloc_table";
1010 throw new ArgumentException ();
1014 protected int WriteAnonLabel ()
1016 int index = ++next_anon_label_idx;
1018 WriteAnonLabel (index);
1023 protected void AddRelocEntry (RelocEntry entry)
1025 reloc_entries.Add (entry);
1028 protected void AddRelocEntry (RelocEntryType type, int token, Section section, int index)
1030 AddRelocEntry (new RelocEntry (type, token, section, index));
1033 protected void AddRelocEntry (RelocEntryType type, int token)
1035 AddRelocEntry (type, token, current_section, WriteAnonLabel ());
1038 protected void AddRelocEntry (RelocEntryType type)
1040 AddRelocEntry (type, 0);
1044 // Mono relocation table. See the README.relocation-table file in this
1045 // directory for a detailed description of the file format.
1047 protected void WriteRelocEntries ()
1049 WriteSectionStart (Section.MONO_RELOC_TABLE);
1050 WriteUInt16 (reloc_table_version);
1052 int end_index = WriteSectionSize ();
1054 foreach (RelocEntry entry in reloc_entries) {
1055 WriteUInt8 ((int) entry.RelocType);
1056 int tmp_index = WriteSectionSize ();
1058 WriteUInt8 ((int) entry.Section);
1059 WriteUInt16 (entry.Index);
1061 switch (entry.RelocType) {
1062 case RelocEntryType.IL_OFFSET:
1063 WriteUInt32 (entry.Token);
1067 WriteAnonLabel (tmp_index);
1070 WriteAnonLabel (end_index);
1075 // Registers a new abbreviation declaration.
1077 // This function should be called by a static constructor in one of
1078 // Die's subclasses.
1080 protected static int RegisterAbbrevDeclaration (AbbrevDeclaration decl)
1082 return abbrev_declarations.Add (decl) + 1;
1085 protected static AbbrevDeclaration GetAbbrevDeclaration (int index)
1087 return (AbbrevDeclaration) abbrev_declarations [index - 1];
1090 protected void WriteAbbrevDeclarations ()
1092 WriteSectionStart (Section.DEBUG_ABBREV);
1093 WriteLabel ("debug_abbrev_b");
1095 for (int index = 0; index < abbrev_declarations.Count; index++) {
1096 AbbrevDeclaration decl = (AbbrevDeclaration) abbrev_declarations [index];
1098 WriteULeb128 (index + 1);
1099 WriteULeb128 ((int) decl.Tag);
1100 WriteFlag (decl.HasChildren);
1102 foreach (AbbrevEntry entry in decl.Entries)
1103 WritePair ((int) entry.Attribute, (int) entry.Form);
1111 protected void WriteAnonLabel (int index)
1113 writer.WriteLine (".L_" + index + ":");
1116 protected void WriteLabel (string label)
1118 writer.WriteLine (label + ":");
1121 protected int WriteSectionSize ()
1123 int start_index = ++next_anon_label_idx;
1124 int end_index = ++next_anon_label_idx;
1126 writer.WriteLine ("\t.long\t\t.L_" + end_index + " - .L_" + start_index);
1127 WriteAnonLabel (start_index);
1132 protected int WriteShortSectionSize ()
1134 int start_index = ++next_anon_label_idx;
1135 int end_index = ++next_anon_label_idx;
1137 writer.WriteLine ("\t.byte\t\t.L_" + end_index + " - .L_" + start_index);
1138 WriteAnonLabel (start_index);
1143 protected void WriteRelativeReference (string start_label, string end_label)
1145 writer.WriteLine ("\t.long\t\t" + end_label + " - " + start_label);
1148 protected void WriteAbsoluteReference (string label)
1150 writer.WriteLine ("\t.long\t\t" + label);
1153 protected void WriteSectionStart (Section section)
1155 writer.WriteLine ("\t.section\t." + GetSectionName (section));
1156 current_section = section;
1159 protected void WriteSectionEnd ()
1161 writer.WriteLine ("\t.previous\n");
1164 protected void WriteFlag (bool value)
1166 writer.WriteLine ("\t.byte\t\t" + (value ? 1 : 0));
1169 protected void WritePair (int key, int value)
1171 writer.WriteLine ("\t.byte\t\t" + key + ", " + value);
1174 protected void WriteUInt8 (int value)
1176 writer.WriteLine ("\t.byte\t\t" + value);
1179 protected void WriteInt8 (int value)
1181 writer.WriteLine ("\t.byte\t\t" + value);
1184 protected void WriteUInt16 (int value)
1186 writer.WriteLine ("\t.2byte\t\t" + value);
1189 protected void WriteUInt32 (int value)
1191 writer.WriteLine ("\t.long\t\t" + value);
1194 protected void WriteSLeb128 (int value)
1196 writer.WriteLine ("\t.sleb128\t" + value);
1199 protected void WriteULeb128 (int value)
1201 writer.WriteLine ("\t.uleb128\t" + value);
1204 protected void WriteOffset (string section)
1206 writer.WriteLine ("\t.long\t\t" + section);
1209 protected void WriteAddress (int value)
1211 writer.WriteLine ("\t.long\t\t" + value);
1214 protected void WriteString (string value)
1216 writer.WriteLine ("\t.string\t\t\"" + value + "\"");