1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
6  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
7  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/dwarfdbginf.d, backend/dwarfdbginf.d)
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/dwarfdbginf.d
10  */
11 
12 // Emit Dwarf symbolic debug info
13 
14 /*
15 Some generic information for debug info on macOS:
16 
17 The linker on macOS will remove any debug info, i.e. every section with the
18 `S_ATTR_DEBUG` flag, this includes everything in the `__DWARF` section. By using
19 the `S_REGULAR` flag the linker will not remove this section. This allows to get
20 the filenames and line numbers for backtraces from the executable.
21 
22 Normally the linker removes all the debug info but adds a reference to the
23 object files. The debugger can then read the object files to get filename and
24 line number information. It's also possible to use an additional tool that
25 generates a separate `.dSYM` file. This file can then later be deployed with the
26 application if debug info is needed when the application is deployed.
27 */
28 
29 module dmd.backend.dwarfdbginf;
30 
31 version (SCPP)
32     version = COMPILE;
33 version (MARS)
34     version = COMPILE;
35 
36 version (COMPILE):
37 
38 import core.stdc.stdio;
39 import core.stdc.stdlib;
40 import core.stdc.string;
41 import core.stdc.errno;
42 
43 import dmd.backend.cc;
44 import dmd.backend.cdef;
45 
46 version(Windows)
47 {
48     nothrow
49     extern (C) char* getcwd(char* buffer, size_t maxlen);
50     nothrow
51     extern (C) int* _errno();   // not the multi-threaded version
52 }
53 else
54 {
55     import core.sys.posix.unistd : getcwd;
56 }
57 
58 static if (1)
59 {
60     import dmd.backend.aarray;
61     import dmd.backend.barray;
62     import dmd.backend.code;
63     import dmd.backend.code_x86;
64     import dmd.backend.dwarf;
65     import dmd.backend.dwarf2;
66     import dmd.backend.mem;
67     import dmd.backend.dlist;
68     import dmd.backend.el;
69     import dmd.backend.global;
70     import dmd.backend.obj;
71     import dmd.backend.oper;
72     import dmd.backend.outbuf;
73     import dmd.backend.symtab;
74     import dmd.backend.ty;
75     import dmd.backend.type;
76 
77     import dmd.backend.melf;
78     import dmd.backend.mach;
79 
80     extern (C++):
81 
82     nothrow:
83 
84     int REGSIZE();
85 
86     __gshared
87     {
88         //static if (MACHOBJ)
89             int except_table_seg = UNKNOWN; // __gcc_except_tab segment
90             int except_table_num = 0;       // sequence number for GCC_except_table%d symbols
91             int eh_frame_seg = UNKNOWN;     // __eh_frame segment
92             Symbol *eh_frame_sym = null;    // past end of __eh_frame
93 
94         uint CIE_offset_unwind;     // CIE offset for unwind data
95         uint CIE_offset_no_unwind;  // CIE offset for no unwind data
96 
97         static if (ELFOBJ)
98         {
99             IDXSYM elf_addsym(IDXSTR nam, targ_size_t val, uint sz,
100                     uint typ, uint bind, IDXSEC sec,
101                     ubyte visibility = STV_DEFAULT);
102             void addSegmentToComdat(segidx_t seg, segidx_t comdatseg);
103         }
104 
105         static if (MACHOBJ)
106         {
107             int getsegment2(ref int seg, const(char)* sectname, const(char)* segname,
108                 int align_, int flags);
109         }
110 
111         Symbol* getRtlsymPersonality();
112 
113         private Barray!(Symbol*) resetSyms;        // Keep pointers to reset symbols
114     }
115 
116     /***********************************
117      * Determine if generating a eh_frame with full
118      * unwinding information.
119      * This decision is done on a per-function basis.
120      * Returns:
121      *      true if unwinding needs to be done
122      */
123     bool doUnwindEhFrame()
124     {
125         if (funcsym_p.Sfunc.Fflags3 & Feh_none)
126         {
127             return (config.exe & (EX_FREEBSD | EX_FREEBSD64 | EX_DRAGONFLYBSD64)) != 0;
128         }
129 
130         /* FreeBSD fails when having some frames as having unwinding info and some not.
131          * (It hangs in unittests for std.datetime.)
132          * g++ on FreeBSD does not generate mixed frames, while g++ on OSX and Linux does.
133          */
134         assert(!(usednteh & ~(EHtry | EHcleanup)));
135         return (usednteh & (EHtry | EHcleanup)) ||
136                (config.exe & (EX_FREEBSD | EX_FREEBSD64 | EX_DRAGONFLYBSD64)) && config.useExceptions;
137     }
138 
139     static if (ELFOBJ)
140         SYMIDX MAP_SEG2SYMIDX(int seg) { return SegData[seg].SDsymidx; }
141     else
142         SYMIDX MAP_SEG2SYMIDX(int seg) { assert(0); }
143 
144 
145     int OFFSET_FAC() { return REGSIZE(); }
146 
147     int dwarf_getsegment(const(char)* name, int align_, int flags)
148     {
149         static if (ELFOBJ)
150             return Obj.getsegment(name, null, flags, 0, align_ * 4);
151         else static if (MACHOBJ)
152             return Obj.getsegment(name, "__DWARF", align_ * 2, flags);
153         else
154             assert(0);
155     }
156 
157     static if (ELFOBJ)
158     {
159         int dwarf_getsegment_alloc(const(char)* name, const(char)* suffix, int align_)
160         {
161             return Obj.getsegment(name, suffix, SHT_PROGBITS, SHF_ALLOC, align_ * 4);
162         }
163     }
164 
165     int dwarf_except_table_alloc(Symbol *s)
166     {
167         //printf("dwarf_except_table_alloc('%s')\n", s.Sident.ptr);
168         static if (ELFOBJ)
169         {
170             /* If `s` is in a COMDAT, then this table needs to go into
171              * a unique section, which then gets added to the COMDAT group
172              * associated with `s`.
173              */
174             seg_data *pseg = SegData[s.Sseg];
175             if (pseg.SDassocseg)
176             {
177                 const(char)* suffix = s.Sident.ptr; // cpp_mangle(s);
178                 segidx_t tableseg = Obj.getsegment(".gcc_except_table.", suffix, SHT_PROGBITS, SHF_ALLOC|SHF_GROUP, 1);
179                 addSegmentToComdat(tableseg, s.Sseg);
180                 return tableseg;
181             }
182             else
183                 return dwarf_getsegment_alloc(".gcc_except_table", null, 1);
184         }
185         else static if (MACHOBJ)
186         {
187             return getsegment2(except_table_seg, "__gcc_except_tab", "__TEXT", 2, S_REGULAR);
188         }
189         else
190             assert(0);
191     }
192 
193     int dwarf_eh_frame_alloc()
194     {
195         static if (ELFOBJ)
196             return dwarf_getsegment_alloc(".eh_frame", null, I64 ? 2 : 1);
197         else static if (MACHOBJ)
198         {
199             int seg = getsegment2(eh_frame_seg, "__eh_frame", "__TEXT", I64 ? 3 : 2,
200                 S_COALESCED | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS | S_ATTR_LIVE_SUPPORT);
201             /* Generate symbol for it to use for fixups
202              */
203             if (!eh_frame_sym)
204             {
205                 type *t = tspvoid;
206                 t.Tcount++;
207                 type_setmangle(&t, mTYman_sys);         // no leading '_' for mangled name
208                 eh_frame_sym = symbol_name("EH_frame0", SCstatic, t);
209                 Obj.pubdef(seg, eh_frame_sym, 0);
210                 symbol_keep(eh_frame_sym);
211             }
212             return seg;
213         }
214         else
215             assert(0);
216     }
217 
218     // machobj.c
219     enum RELaddr = 0;       // straight address
220     enum RELrel  = 1;       // relative to location to be fixed up
221 
222     void dwarf_addrel(int seg, targ_size_t offset, int targseg, targ_size_t val = 0)
223     {
224         static if (ELFOBJ)
225             Obj.addrel(seg, offset, I64 ? R_X86_64_32 : R_386_32, cast(int)MAP_SEG2SYMIDX(targseg), val);
226         else static if (MACHOBJ)
227             Obj.addrel(seg, offset, cast(Symbol*) null, targseg, RELaddr, cast(int)val);
228         else
229             assert(0);
230     }
231 
232     void dwarf_addrel64(int seg, targ_size_t offset, int targseg, targ_size_t val)
233     {
234         static if (ELFOBJ)
235             Obj.addrel(seg, offset, R_X86_64_64, cast(int)MAP_SEG2SYMIDX(targseg), val);
236         else static if (MACHOBJ)
237             Obj.addrel(seg, offset, null, targseg, RELaddr, cast(uint)val);
238         else
239             assert(0);
240     }
241 
242     void dwarf_appreladdr(int seg, Outbuffer *buf, int targseg, targ_size_t val)
243     {
244         if (I64)
245         {
246             dwarf_addrel64(seg, buf.length(), targseg, val);
247             buf.write64(0);
248         }
249         else
250         {
251             dwarf_addrel(seg, buf.length(), targseg, 0);
252             buf.write32(cast(uint)val);
253         }
254     }
255 
256     void dwarf_apprel32(int seg, Outbuffer *buf, int targseg, targ_size_t val)
257     {
258         dwarf_addrel(seg, buf.length(), targseg, I64 ? val : 0);
259         buf.write32(I64 ? 0 : cast(uint)val);
260     }
261 
262     void append_addr(Outbuffer *buf, targ_size_t addr)
263     {
264         if (I64)
265             buf.write64(addr);
266         else
267             buf.write32(cast(uint)addr);
268     }
269 
270 
271     /************************  DWARF DEBUG OUTPUT ********************************/
272 
273     // Dwarf Symbolic Debugging Information
274 
275     // CFA = value of the stack pointer at the call site in the previous frame
276 
277     struct CFA_reg
278     {
279         int offset;                 // offset from CFA
280     }
281 
282     // Current CFA state for .debug_frame
283     struct CFA_state
284     {
285         size_t location;
286         int reg;                    // CFA register number
287         int offset;                 // CFA register offset
288         CFA_reg[17] regstates;      // register states
289     }
290 
291     /***********************
292      * Convert CPU register number to Dwarf register number.
293      * Params:
294      *      reg = CPU register
295      * Returns:
296      *      dwarf register
297      */
298     int dwarf_regno(int reg)
299     {
300         assert(reg < NUMGENREGS);
301         if (I32)
302         {
303             static if (MACHOBJ)
304             {
305                     if (reg == BP || reg == SP)
306                         reg ^= BP ^ SP;     // swap EBP and ESP register values for OSX (!)
307             }
308             return reg;
309         }
310         else
311         {
312             assert(I64);
313             /* See https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
314              * Figure 3.3.8 pg. 62
315              * R8..15    :  8..15
316              * XMM0..15  : 17..32
317              * ST0..7    : 33..40
318              * MM0..7    : 41..48
319              * XMM16..31 : 67..82
320              */
321             static immutable int[8] to_amd64_reg_map =
322             // AX CX DX BX SP BP SI DI
323             [   0, 2, 1, 3, 7, 6, 4, 5 ];
324             return reg < 8 ? to_amd64_reg_map[reg] : reg;
325         }
326     }
327 
328     private __gshared
329     {
330         CFA_state CFA_state_init_32 =       // initial CFA state as defined by CIE
331         {   0,                // location
332             -1,               // register
333             4,                // offset
334             [   { 0 },        // 0: EAX
335                 { 0 },        // 1: ECX
336                 { 0 },        // 2: EDX
337                 { 0 },        // 3: EBX
338                 { 0 },        // 4: ESP
339                 { 0 },        // 5: EBP
340                 { 0 },        // 6: ESI
341                 { 0 },        // 7: EDI
342                 { -4 },       // 8: EIP
343             ]
344         };
345 
346         CFA_state CFA_state_init_64 =       // initial CFA state as defined by CIE
347         {   0,                // location
348             -1,               // register
349             8,                // offset
350             [   { 0 },        // 0: RAX
351                 { 0 },        // 1: RBX
352                 { 0 },        // 2: RCX
353                 { 0 },        // 3: RDX
354                 { 0 },        // 4: RSI
355                 { 0 },        // 5: RDI
356                 { 0 },        // 6: RBP
357                 { 0 },        // 7: RSP
358                 { 0 },        // 8: R8
359                 { 0 },        // 9: R9
360                 { 0 },        // 10: R10
361                 { 0 },        // 11: R11
362                 { 0 },        // 12: R12
363                 { 0 },        // 13: R13
364                 { 0 },        // 14: R14
365                 { 0 },        // 15: R15
366                 { -8 },       // 16: RIP
367             ]
368         };
369 
370         CFA_state CFA_state_current;     // current CFA state
371         Outbuffer cfa_buf;               // CFA instructions
372     }
373 
374     /***********************************
375      * Set the location, i.e. the offset from the start
376      * of the function. It must always be greater than
377      * the current location.
378      * Params:
379      *      location = offset from the start of the function
380      */
381     void dwarf_CFA_set_loc(uint location)
382     {
383         assert(location >= CFA_state_current.location);
384         uint inc = cast(uint)(location - CFA_state_current.location);
385         if (inc <= 63)
386             cfa_buf.writeByte(DW_CFA_advance_loc + inc);
387         else if (inc <= 255)
388         {   cfa_buf.writeByte(DW_CFA_advance_loc1);
389             cfa_buf.writeByte(inc);
390         }
391         else if (inc <= 0xFFFF)
392         {   cfa_buf.writeByte(DW_CFA_advance_loc2);
393             cfa_buf.write16(inc);
394         }
395         else
396         {   cfa_buf.writeByte(DW_CFA_advance_loc4);
397             cfa_buf.write32(inc);
398         }
399         CFA_state_current.location = location;
400     }
401 
402     /*******************************************
403      * Set the frame register, and its offset.
404      * Params:
405      *      reg = machine register
406      *      offset = offset from frame register
407      */
408     void dwarf_CFA_set_reg_offset(int reg, int offset)
409     {
410         int dw_reg = dwarf_regno(reg);
411         if (dw_reg != CFA_state_current.reg)
412         {
413             if (offset == CFA_state_current.offset)
414             {
415                 cfa_buf.writeByte(DW_CFA_def_cfa_register);
416                 cfa_buf.writeuLEB128(dw_reg);
417             }
418             else if (offset < 0)
419             {
420                 cfa_buf.writeByte(DW_CFA_def_cfa_sf);
421                 cfa_buf.writeuLEB128(dw_reg);
422                 cfa_buf.writesLEB128(offset / -OFFSET_FAC);
423             }
424             else
425             {
426                 cfa_buf.writeByte(DW_CFA_def_cfa);
427                 cfa_buf.writeuLEB128(dw_reg);
428                 cfa_buf.writeuLEB128(offset);
429             }
430         }
431         else if (offset < 0)
432         {
433             cfa_buf.writeByte(DW_CFA_def_cfa_offset_sf);
434             cfa_buf.writesLEB128(offset / -OFFSET_FAC);
435         }
436         else
437         {
438             cfa_buf.writeByte(DW_CFA_def_cfa_offset);
439             cfa_buf.writeuLEB128(offset);
440         }
441         CFA_state_current.reg = dw_reg;
442         CFA_state_current.offset = offset;
443     }
444 
445     /***********************************************
446      * Set reg to be at offset from frame register.
447      * Params:
448      *      reg = machine register
449      *      offset = offset from frame register
450      */
451     void dwarf_CFA_offset(int reg, int offset)
452     {
453         int dw_reg = dwarf_regno(reg);
454         if (CFA_state_current.regstates[dw_reg].offset != offset)
455         {
456             if (offset <= 0)
457             {
458                 cfa_buf.writeByte(DW_CFA_offset + dw_reg);
459                 cfa_buf.writeuLEB128(offset / -OFFSET_FAC);
460             }
461             else
462             {
463                 cfa_buf.writeByte(DW_CFA_offset_extended_sf);
464                 cfa_buf.writeuLEB128(dw_reg);
465                 cfa_buf.writesLEB128(offset / -OFFSET_FAC);
466             }
467         }
468         CFA_state_current.regstates[dw_reg].offset = offset;
469     }
470 
471     /**************************************
472      * Set total size of arguments pushed on the stack.
473      * Params:
474      *      sz = total size
475      */
476     void dwarf_CFA_args_size(size_t sz)
477     {
478         cfa_buf.writeByte(DW_CFA_GNU_args_size);
479         cfa_buf.writeuLEB128(cast(uint)sz);
480     }
481 
482     struct Section
483     {
484         segidx_t seg = 0;
485         IDXSEC secidx = 0;
486         Outbuffer *buf = null;
487         const(char)* name;
488 
489         static if (MACHOBJ)
490             immutable flags = S_ATTR_DEBUG;
491         else
492             immutable flags = SHT_PROGBITS;
493 
494         /* Allocate and initialize Section
495          */
496         nothrow void initialize()
497         {
498             const segidx_t segi = dwarf_getsegment(name, 0, flags);
499             seg = segi;
500             secidx = SegData[segi].SDshtidx;
501             buf = SegData[segi].SDbuf;
502             buf.reserve(1000);
503         }
504     }
505 
506 
507     private __gshared
508     {
509 
510         static if (MACHOBJ)
511         {
512             Section debug_pubnames = { name: "__debug_pubnames" };
513             Section debug_aranges  = { name: "__debug_aranges" };
514             Section debug_ranges   = { name: "__debug_ranges" };
515             Section debug_loc      = { name: "__debug_loc" };
516             Section debug_abbrev   = { name: "__debug_abbrev" };
517             Section debug_info     = { name: "__debug_info" };
518             Section debug_str      = { name: "__debug_str" };
519         // We use S_REGULAR to make sure the linker doesn't remove this section. Needed
520         // for filenames and line numbers in backtraces.
521             Section debug_line     = { name: "__debug_line", flags: S_REGULAR };
522         }
523         else static if (ELFOBJ)
524         {
525             Section debug_pubnames = { name: ".debug_pubnames" };
526             Section debug_aranges  = { name: ".debug_aranges" };
527             Section debug_ranges   = { name: ".debug_ranges" };
528             Section debug_loc      = { name: ".debug_loc" };
529             Section debug_abbrev   = { name: ".debug_abbrev" };
530             Section debug_info     = { name: ".debug_info" };
531             Section debug_str      = { name: ".debug_str" };
532             Section debug_line     = { name: ".debug_line" };
533         }
534         else
535         {
536             Section debug_pubnames;
537             Section debug_aranges;
538             Section debug_ranges;
539             Section debug_loc;
540             Section debug_abbrev;
541             Section debug_info;
542             Section debug_str;
543             Section debug_line;
544         }
545 
546         static if (MACHOBJ)
547             const char* debug_frame_name = "__debug_frame";
548         else static if (ELFOBJ)
549             const char* debug_frame_name = ".debug_frame";
550         else
551             const char* debug_frame_name = null;
552 
553         /* DWARF 7.5.3: "Each declaration begins with an unsigned LEB128 number
554          * representing the abbreviation code itself."
555          */
556         uint abbrevcode = 1;
557         AApair *abbrev_table;
558         int hasModname;    // 1 if has DW_TAG_module
559 
560         // .debug_info
561         AAchars *infoFileName_table;
562 
563         AApair *type_table;
564         AApair *functype_table;  // not sure why this cannot be combined with type_table
565         Outbuffer *functypebuf;
566 
567         // .debug_line
568         size_t linebuf_filetab_end;
569 
570         struct DebugLineHeader
571         {
572           align (1):
573             uint total_length                = 0;
574             ushort version_                  = 2;
575             uint prologue_length             = 0;
576             ubyte minimum_instruction_length = 1;
577             ubyte default_is_stmt            = true;
578             byte line_base                   = -5;
579             ubyte line_range                 = 14;
580             ubyte opcode_base                = 10;
581             ubyte[9] standard_opcode_lengths = [ 0,1,1,1,1,0,0,0,1 ];
582         }
583         static assert(DebugLineHeader.sizeof == 24);
584 
585         DebugLineHeader debugline;
586 
587         public uint[TYMAX] typidx_tab;
588     }
589 
590     /*****************************************
591      * Replace the bytes in `buf` from the `offset` by `data`.
592      *
593      * Params:
594      *      buf = buffer where `data` will be written
595      *      offset = offset of the bytes in `buf` to replace
596      *      data = bytes to write
597      */
598     extern(D) void rewrite(T)(Outbuffer* buf, size_t offset, T data)
599     {
600         *(cast(T*)&buf.buf[offset]) = data;
601     }
602 
603     alias rewrite32 = rewrite!uint;
604     alias rewrite64 = rewrite!ulong;
605 
606     /*****************************************
607      * Append .debug_frame header to buf.
608      * Params:
609      *      buf = write raw data here
610      */
611     void writeDebugFrameHeader(Outbuffer *buf)
612     {
613         static struct DebugFrameHeader
614         {
615           align (1):
616             uint length;
617             uint CIE_id;
618             ubyte version_;
619             ubyte augmentation;
620             ubyte code_alignment_factor;
621             ubyte data_alignment_factor;
622             ubyte return_address_register;
623             ubyte[11] opcodes;
624         }
625         static assert(DebugFrameHeader.sizeof == 24);
626 
627         __gshared DebugFrameHeader debugFrameHeader =
628         {   16,             // length
629             0xFFFFFFFF,     // CIE_id
630             1,              // version_
631             0,              // augmentation
632             1,              // code alignment factor
633             0x7C,           // data alignment factor (-4)
634             8,              // return address register
635             [
636                 DW_CFA_def_cfa, 4,4,    // r4,4 [r7,8]
637                 DW_CFA_offset   +8,1,   // r8,1 [r16,1]
638                 DW_CFA_nop, DW_CFA_nop,
639                 DW_CFA_nop, DW_CFA_nop, // 64 padding
640                 DW_CFA_nop, DW_CFA_nop, // 64 padding
641             ]
642         };
643         if (I64)
644         {   debugFrameHeader.length = 20;
645             debugFrameHeader.data_alignment_factor = 0x78;          // (-8)
646             debugFrameHeader.return_address_register = 16;
647             debugFrameHeader.opcodes[1] = 7;                        // RSP
648             debugFrameHeader.opcodes[2] = 8;
649             debugFrameHeader.opcodes[3] = DW_CFA_offset + 16;       // RIP
650         }
651         assert(debugFrameHeader.data_alignment_factor == 0x80 - OFFSET_FAC);
652 
653         buf.writen(&debugFrameHeader,debugFrameHeader.length + 4);
654     }
655 
656     /*****************************************
657      * Append .eh_frame header to buf.
658      * Almost identical to .debug_frame
659      * Params:
660      *      dfseg = SegData[] index for .eh_frame
661      *      buf = write raw data here
662      *      personality = "__dmd_personality_v0"
663      *      ehunwind = will have EH unwind table
664      * Returns:
665      *      offset of start of this header
666      * See_Also:
667      *      https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html
668      */
669     private uint writeEhFrameHeader(IDXSEC dfseg, Outbuffer *buf, Symbol *personality, bool ehunwind)
670     {
671         /* Augmentation string:
672          *  z = first character, means Augmentation Data field is present
673          *  eh = EH Data field is present
674          *  P = Augmentation Data contains 2 args:
675          *          1. encoding of 2nd arg
676          *          2. address of personality routine
677          *  L = Augmentation Data contains 1 arg:
678          *          1. the encoding used for Augmentation Data in FDE
679          *      Augmentation Data in FDE:
680          *          1. address of LSDA (gcc_except_table)
681          *  R = Augmentation Data contains 1 arg:
682          *          1. encoding of addresses in FDE
683          * Non-EH code: "zR"
684          * EH code: "zPLR"
685          */
686 
687         const uint startsize = cast(uint)buf.length();
688 
689         // Length of CIE, not including padding
690         const uint cielen = 4 + 4 + 1 +
691             (ehunwind ? 5 : 3) +
692             1 + 1 + 1 +
693             (ehunwind ? 8 : 2) +
694             5;
695 
696         const uint pad = -cielen & (I64 ? 7 : 3);      // pad to addressing unit size boundary
697         const uint length = cielen + pad - 4;
698 
699         buf.reserve(length + 4);
700         buf.write32(length);       // length of CIE, not including length and extended length fields
701         buf.write32(0);            // CIE ID
702         buf.writeByten(1);         // version_
703         if (ehunwind)
704             buf.write("zPLR".ptr, 5);  // Augmentation String
705         else
706             buf.writen("zR".ptr, 3);
707         // not present: EH Data: 4 bytes for I32, 8 bytes for I64
708         buf.writeByten(1);                 // code alignment factor
709         buf.writeByten(cast(ubyte)(0x80 - OFFSET_FAC)); // data alignment factor (I64 ? -8 : -4)
710         buf.writeByten(I64 ? 16 : 8);      // return address register
711         if (ehunwind)
712         {
713             static if (ELFOBJ)
714             {
715                     const ubyte personality_pointer_encoding = config.flags3 & CFG3pic
716                             ? DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4
717                             : DW_EH_PE_absptr | DW_EH_PE_udata4;
718                     const ubyte LSDA_pointer_encoding = config.flags3 & CFG3pic
719                             ? DW_EH_PE_pcrel | DW_EH_PE_sdata4
720                             : DW_EH_PE_absptr | DW_EH_PE_udata4;
721                     const ubyte address_pointer_encoding =
722                             DW_EH_PE_pcrel | DW_EH_PE_sdata4;
723             }
724             else static if (MACHOBJ)
725             {
726                     const ubyte personality_pointer_encoding =
727                             DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4;
728                     const ubyte LSDA_pointer_encoding =
729                             DW_EH_PE_pcrel | DW_EH_PE_ptr;
730                     const ubyte address_pointer_encoding =
731                             DW_EH_PE_pcrel | DW_EH_PE_ptr;
732             }
733             else
734             {
735                     const ubyte personality_pointer_encoding = 0;
736                     const ubyte LSDA_pointer_encoding = 0;
737                     const ubyte address_pointer_encoding = 0;
738             }
739             buf.writeByten(7);                                  // Augmentation Length
740             buf.writeByten(personality_pointer_encoding);       // P: personality routine address encoding
741             /* MACHOBJ 64: pcrel 1 length 2 extern 1 RELOC_GOT
742              *         32: [4] address x0013 pcrel 0 length 2 value xfc type 4 RELOC_LOCAL_SECTDIFF
743              *             [5] address x0000 pcrel 0 length 2 value xc7 type 1 RELOC_PAIR
744              */
745             if (config.objfmt == OBJ_ELF)
746                 elf_dwarf_reftoident(dfseg, buf.length(), personality, 0);
747             else
748                 mach_dwarf_reftoident(dfseg, buf.length(), personality, 0);
749             buf.writeByten(LSDA_pointer_encoding);              // L: address encoding for LSDA in FDE
750             buf.writeByten(address_pointer_encoding);           // R: encoding of addresses in FDE
751         }
752         else
753         {
754             buf.writeByten(1);                                  // Augmentation Length
755 
756             static if (ELFOBJ)
757                     buf.writeByten(DW_EH_PE_pcrel | DW_EH_PE_sdata4);   // R: encoding of addresses in FDE
758             static if (MACHOBJ)
759                     buf.writeByten(DW_EH_PE_pcrel | DW_EH_PE_ptr);      // R: encoding of addresses in FDE
760         }
761 
762         // Set CFA beginning state at function entry point
763         if (I64)
764         {
765             buf.writeByten(DW_CFA_def_cfa);        // DEF_CFA r7,8   RSP is at offset 8
766             buf.writeByten(7);                     // r7 is RSP
767             buf.writeByten(8);
768 
769             buf.writeByten(DW_CFA_offset + 16);    // OFFSET r16,1   RIP is at -8*1[RSP]
770             buf.writeByten(1);
771         }
772         else
773         {
774             buf.writeByten(DW_CFA_def_cfa);        // DEF_CFA ESP,4
775             buf.writeByten(cast(ubyte)dwarf_regno(SP));
776             buf.writeByten(4);
777 
778             buf.writeByten(DW_CFA_offset + 8);     // OFFSET r8,1
779             buf.writeByten(1);
780         }
781 
782         for (uint i = 0; i < pad; ++i)
783             buf.writeByten(DW_CFA_nop);
784 
785         assert(startsize + length + 4 == buf.length());
786         return startsize;
787     }
788 
789     /*********************************************
790      * Generate function's Frame Description Entry into .debug_frame
791      * Params:
792      *      dfseg = SegData[] index for .debug_frame
793      *      sfunc = the function
794      */
795     void writeDebugFrameFDE(IDXSEC dfseg, Symbol *sfunc)
796     {
797         if (I64)
798         {
799             static struct DebugFrameFDE64
800             {
801               align (1):
802                 uint length;
803                 uint CIE_pointer;
804                 ulong initial_location;
805                 ulong address_range;
806             }
807             static assert(DebugFrameFDE64.sizeof == 24);
808 
809             __gshared DebugFrameFDE64 debugFrameFDE64 =
810             {
811                 20,             // length
812                 0,              // CIE_pointer
813                 0,              // initial_location
814                 0,              // address_range
815             };
816 
817             // Pad to 8 byte boundary
818             for (uint n = (-cfa_buf.length() & 7); n; n--)
819                 cfa_buf.writeByte(DW_CFA_nop);
820 
821             debugFrameFDE64.length = 20 + cast(uint)cfa_buf.length();
822             debugFrameFDE64.address_range = sfunc.Ssize;
823             // Do we need this?
824             //debugFrameFDE64.initial_location = sfunc.Soffset;
825 
826             Outbuffer *debug_frame_buf = SegData[dfseg].SDbuf;
827             uint debug_frame_buf_offset = cast(uint)debug_frame_buf.length();
828             debug_frame_buf.reserve(1000);
829             debug_frame_buf.writen(&debugFrameFDE64,debugFrameFDE64.sizeof);
830             debug_frame_buf.write(cfa_buf[]);
831 
832             static if (ELFOBJ)
833                 // Absolute address for debug_frame, relative offset for eh_frame
834                 dwarf_addrel(dfseg,debug_frame_buf_offset + 4,dfseg,0);
835 
836             dwarf_addrel64(dfseg,debug_frame_buf_offset + 8,sfunc.Sseg,0);
837         }
838         else
839         {
840             static struct DebugFrameFDE32
841             {
842               align (1):
843                 uint length;
844                 uint CIE_pointer;
845                 uint initial_location;
846                 uint address_range;
847             }
848             static assert(DebugFrameFDE32.sizeof == 16);
849 
850             __gshared DebugFrameFDE32 debugFrameFDE32 =
851             {
852                 12,             // length
853                 0,              // CIE_pointer
854                 0,              // initial_location
855                 0,              // address_range
856             };
857 
858             // Pad to 4 byte boundary
859             for (uint n = (-cfa_buf.length() & 3); n; n--)
860                 cfa_buf.writeByte(DW_CFA_nop);
861 
862             debugFrameFDE32.length = 12 + cast(uint)cfa_buf.length();
863             debugFrameFDE32.address_range = cast(uint)sfunc.Ssize;
864             // Do we need this?
865             //debugFrameFDE32.initial_location = sfunc.Soffset;
866 
867             Outbuffer *debug_frame_buf = SegData[dfseg].SDbuf;
868             uint debug_frame_buf_offset = cast(uint)debug_frame_buf.length();
869             debug_frame_buf.reserve(1000);
870             debug_frame_buf.writen(&debugFrameFDE32,debugFrameFDE32.sizeof);
871             debug_frame_buf.write(cfa_buf[]);
872 
873             static if (ELFOBJ)
874                 // Absolute address for debug_frame, relative offset for eh_frame
875                 dwarf_addrel(dfseg,debug_frame_buf_offset + 4,dfseg,0);
876 
877             dwarf_addrel(dfseg,debug_frame_buf_offset + 8,sfunc.Sseg,0);
878         }
879     }
880 
881     /*********************************************
882      * Append function's FDE (Frame Description Entry) to .eh_frame
883      * Params:
884      *      dfseg = SegData[] index for .eh_frame
885      *      sfunc = the function
886      *      ehunwind = will have EH unwind table
887      *      CIE_offset = offset of enclosing CIE
888      */
889     void writeEhFrameFDE(IDXSEC dfseg, Symbol *sfunc, bool ehunwind, uint CIE_offset)
890     {
891         Outbuffer *buf = SegData[dfseg].SDbuf;
892         const uint startsize = cast(uint)buf.length();
893 
894         static if (MACHOBJ)
895         {
896             /* Create symbol named "funcname.eh" for the start of the FDE
897              */
898             Symbol *fdesym;
899             {
900                 const size_t len = strlen(getSymName(sfunc));
901                 char *name = cast(char *)malloc(len + 3 + 1);
902                 if (!name)
903                     err_nomem();
904                 memcpy(name, getSymName(sfunc), len);
905                 memcpy(name + len, ".eh".ptr, 3 + 1);
906                 fdesym = symbol_name(name, SCglobal, tspvoid);
907                 Obj.pubdef(dfseg, fdesym, startsize);
908                 symbol_keep(fdesym);
909                 free(name);
910             }
911         }
912 
913         if (sfunc.ty() & mTYnaked)
914         {
915             /* Do not have info on naked functions. Assume they are set up as:
916              *   push RBP
917              *   mov  RSP,RSP
918              */
919             int off = 2 * REGSIZE;
920             dwarf_CFA_set_loc(1);
921             dwarf_CFA_set_reg_offset(SP, off);
922             dwarf_CFA_offset(BP, -off);
923             dwarf_CFA_set_loc(I64 ? 4 : 3);
924             dwarf_CFA_set_reg_offset(BP, off);
925         }
926 
927         // Length of FDE, not including padding
928         static if (ELFOBJ)
929             const uint fdelen = 4 + 4
930                 + 4 + 4
931                 + (ehunwind ? 5 : 1) + cast(uint)cfa_buf.length();
932         else static if (MACHOBJ)
933             const uint fdelen = 4 + 4
934                 + (I64 ? 8 + 8 : 4 + 4)                         // PC_Begin + PC_Range
935                 + (ehunwind ? (I64 ? 9 : 5) : 1) + cast(uint)cfa_buf.length();
936         else
937             const uint fdelen = 0;
938 
939             const uint pad = -fdelen & (I64 ? 7 : 3);      // pad to addressing unit size boundary
940             const uint length = fdelen + pad - 4;
941 
942             buf.reserve(length + 4);
943             buf.write32(length);                               // Length (no Extended Length)
944             buf.write32((startsize + 4) - CIE_offset);         // CIE Pointer
945         static if (ELFOBJ)
946         {
947             int fixup = I64 ? R_X86_64_PC32 : R_386_PC32;
948             buf.write32(cast(uint)(I64 ? 0 : sfunc.Soffset));             // address of function
949             Obj.addrel(dfseg, startsize + 8, fixup, cast(int)MAP_SEG2SYMIDX(sfunc.Sseg), sfunc.Soffset);
950             //Obj.reftoident(dfseg, startsize + 8, sfunc, 0, CFpc32 | CFoff); // PC_begin
951             buf.write32(cast(uint)sfunc.Ssize);                         // PC Range
952         }
953         else static if (MACHOBJ)
954         {
955             dwarf_eh_frame_fixup(dfseg, buf.length(), sfunc, 0, fdesym);
956 
957             if (I64)
958                 buf.write64(sfunc.Ssize);                     // PC Range
959             else
960                 buf.write32(cast(uint)sfunc.Ssize);           // PC Range
961         }
962 
963         if (ehunwind)
964         {
965             int etseg = dwarf_except_table_alloc(sfunc);
966             static if (ELFOBJ)
967             {
968                 buf.writeByten(4);                             // Augmentation Data Length
969                 buf.write32(I64 ? 0 : sfunc.Sfunc.LSDAoffset); // address of LSDA (".gcc_except_table")
970                 if (config.flags3 & CFG3pic)
971                 {
972                     Obj.addrel(dfseg, buf.length() - 4, fixup, cast(int)MAP_SEG2SYMIDX(etseg), sfunc.Sfunc.LSDAoffset);
973                 }
974                 else
975                     dwarf_addrel(dfseg, buf.length() - 4, etseg, sfunc.Sfunc.LSDAoffset);      // and the fixup
976             }
977             else static if (MACHOBJ)
978             {
979                 buf.writeByten(I64 ? 8 : 4);                   // Augmentation Data Length
980                 dwarf_eh_frame_fixup(dfseg, buf.length(), sfunc.Sfunc.LSDAsym, 0, fdesym);
981             }
982         }
983         else
984             buf.writeByten(0);                             // Augmentation Data Length
985 
986         buf.write(cfa_buf[]);
987 
988         for (uint i = 0; i < pad; ++i)
989             buf.writeByten(DW_CFA_nop);
990 
991         assert(startsize + length + 4 == buf.length());
992     }
993 
994     void dwarf_initfile(const(char)* filename)
995     {
996         dwarf_initfile(filename ? filename[0 .. strlen(filename)] : null);
997     }
998 
999     extern(D) void dwarf_initfile(const(char)[] filename)
1000     {
1001         if (config.ehmethod == EHmethod.EH_DWARF)
1002         {
1003             static if (MACHOBJ)
1004             {
1005                 except_table_seg = UNKNOWN;
1006                 except_table_num = 0;
1007                 eh_frame_seg = UNKNOWN;
1008                 eh_frame_sym = null;
1009             }
1010             CIE_offset_unwind = ~0;
1011             CIE_offset_no_unwind = ~0;
1012             //dwarf_except_table_alloc();
1013             dwarf_eh_frame_alloc();
1014         }
1015         if (!config.fulltypes)
1016             return;
1017         if (config.ehmethod == EHmethod.EH_DM)
1018         {
1019             static if (MACHOBJ)
1020                 int flags = S_ATTR_DEBUG;
1021             else static if (ELFOBJ)
1022                 int flags = SHT_PROGBITS;
1023             else
1024                 int flags = 0;
1025 
1026             int seg = dwarf_getsegment(debug_frame_name, 1, flags);
1027             Outbuffer *buf = SegData[seg].SDbuf;
1028             buf.reserve(1000);
1029             writeDebugFrameHeader(buf);
1030         }
1031 
1032         /* ======================================== */
1033 
1034         foreach (s; resetSyms)
1035             symbol_reset(s);
1036         resetSyms.reset();
1037 
1038         /* *********************************************************************
1039          *                          String Table
1040          ******************************************************************** */
1041         {
1042             debug_str.initialize();
1043             //Outbuffer *debug_str_buf = debug_str.buf;
1044         }
1045 
1046         /* *********************************************************************
1047          *                2.17.3 Non-Contiguous Address Ranges
1048          ******************************************************************** */
1049         {
1050             debug_ranges.initialize();
1051         }
1052 
1053         /* *********************************************************************
1054          *                         2.6.6 Location Lists
1055          ******************************************************************** */
1056         {
1057             debug_loc.initialize();
1058         }
1059 
1060         /* *********************************************************************
1061          *                  6.2.4 The Line Number Program Header
1062          ******************************************************************** */
1063         {
1064             if (infoFileName_table)
1065             {
1066                 AAchars.destroy(infoFileName_table);
1067                 infoFileName_table = null;
1068             }
1069 
1070             debug_line.initialize();
1071 
1072             debugline = DebugLineHeader.init;
1073 
1074             debug_line.buf.write(&debugline, debugline.sizeof);
1075 
1076             // include_directories
1077             version (SCPP)
1078                 for (size_t i = 0; i < pathlist.length(); ++i)
1079                 {
1080                     debug_line.buf.writeString(pathlist[i]);
1081                     debug_line.buf.writeByte(0);
1082                 }
1083 
1084             version (MARS)
1085             version (none)
1086                 for (int i = 0; i < global.params.imppath.dim; i++)
1087                 {
1088                     debug_line.buf.writeString((*global.params.imppath)[i]);
1089                     debug_line.buf.writeByte(0);
1090                 }
1091 
1092             debug_line.buf.writeByte(0);              // terminated with 0 byte
1093         }
1094 
1095         /* *********************************************************************
1096          *                     7.5.3 Abbreviations Tables
1097          ******************************************************************** */
1098         {
1099             debug_abbrev.initialize();
1100             abbrevcode = 1;
1101 
1102             // Free only if starting another file. Waste of time otherwise.
1103             if (abbrev_table)
1104             {
1105                 AApair.destroy(abbrev_table);
1106                 abbrev_table = null;
1107             }
1108 
1109             static immutable ubyte[21] abbrevHeader =
1110             [
1111                 1,                      // abbreviation code
1112                 DW_TAG_compile_unit,
1113                 1,
1114                 DW_AT_producer,  DW_FORM_string,
1115                 DW_AT_language,  DW_FORM_data1,
1116                 DW_AT_name,      DW_FORM_string,
1117                 DW_AT_comp_dir,  DW_FORM_string,
1118                 DW_AT_low_pc,    DW_FORM_addr,
1119                 DW_AT_entry_pc,  DW_FORM_addr,
1120                 DW_AT_ranges,    DW_FORM_data4,
1121                 DW_AT_stmt_list, DW_FORM_data4,
1122                 0,               0,
1123             ];
1124 
1125             debug_abbrev.buf.write(abbrevHeader.ptr,abbrevHeader.sizeof);
1126         }
1127 
1128         /* *********************************************************************
1129          *             7.5.1.1 Full and Partial Compilation Unit Headers
1130          ******************************************************************** */
1131         {
1132             debug_info.initialize();
1133 
1134 
1135             // Compilation Unit Header
1136             {
1137                 debug_info.buf.write32(0);                      // unit length
1138                 debug_info.buf.write16(config.dwarf);           // version
1139                 if (config.dwarf >= 5)
1140                 {
1141                     debug_info.buf.writeByte(DW_UT_compile);    // Unit Type
1142                     debug_info.buf.writeByte(I64 ? 8 : 4);      // Address size
1143                     debug_info.buf.write32(0);                  // debug abbrev offset
1144                 }
1145                 else
1146                 {
1147                     debug_info.buf.write32(0);                  // debug abbrev offset
1148                     debug_info.buf.writeByte(I64 ? 8 : 4);      // Address size
1149                 }
1150             }
1151 
1152             static if (ELFOBJ)
1153                 dwarf_addrel(debug_info.seg,6,debug_abbrev.seg);
1154 
1155             debug_info.buf.writeuLEB128(1);                   // abbreviation code
1156 
1157             version (MARS)
1158             {
1159                 debug_info.buf.write("Digital Mars D ");
1160                 debug_info.buf.writeString(config._version);     // DW_AT_producer
1161                 // DW_AT_language
1162                 debug_info.buf.writeByte((config.fulltypes == CVDWARF_D) ? DW_LANG_D : DW_LANG_C89);
1163             }
1164             else version (SCPP)
1165             {
1166                 debug_info.buf.write("Digital Mars C ");
1167                 debug_info.buf.writeString(global._version);      // DW_AT_producer
1168                 debug_info.buf.writeByte(DW_LANG_C89);            // DW_AT_language
1169             }
1170             else
1171                 static assert(0);
1172 
1173             debug_info.buf.writeString(filename);             // DW_AT_name
1174 
1175             char* cwd = getcwd(null, 0);
1176             debug_info.buf.writeString(cwd);                  // DW_AT_comp_dir as DW_FORM_string
1177             free(cwd);
1178 
1179             append_addr(debug_info.buf, 0);               // DW_AT_low_pc
1180             append_addr(debug_info.buf, 0);               // DW_AT_entry_pc
1181 
1182             static if (ELFOBJ)
1183                 dwarf_addrel(debug_info.seg,debug_info.buf.length(),debug_ranges.seg);
1184 
1185             debug_info.buf.write32(0);                        // DW_AT_ranges
1186 
1187             static if (ELFOBJ)
1188                 dwarf_addrel(debug_info.seg,debug_info.buf.length(),debug_line.seg);
1189 
1190             debug_info.buf.write32(0);                        // DW_AT_stmt_list
1191 
1192             memset(typidx_tab.ptr, 0, typidx_tab.sizeof);
1193         }
1194 
1195         /* *********************************************************************
1196          *                        6.1.1 Lookup by Name
1197          ******************************************************************** */
1198         {
1199             debug_pubnames.initialize();
1200             int seg = debug_pubnames.seg;
1201 
1202             debug_pubnames.buf.write32(0);             // unit_length
1203             debug_pubnames.buf.write16(2);           // version_
1204 
1205             static if (ELFOBJ)
1206                 dwarf_addrel(seg,debug_pubnames.buf.length(),debug_info.seg);
1207 
1208             debug_pubnames.buf.write32(0);             // debug_info_offset
1209             debug_pubnames.buf.write32(0);             // debug_info_length
1210         }
1211 
1212         /* *********************************************************************
1213          *                      6.1.2 Lookup by Address
1214          ******************************************************************** */
1215         {
1216             debug_aranges.initialize();
1217 
1218             debug_aranges.buf.write32(0);              // unit_length
1219             debug_aranges.buf.write16(2);            // version_
1220 
1221             static if (ELFOBJ)
1222                 dwarf_addrel(debug_aranges.seg,debug_aranges.buf.length(),debug_info.seg);
1223 
1224             debug_aranges.buf.write32(0);              // debug_info_offset
1225             debug_aranges.buf.writeByte(I64 ? 8 : 4);  // address_size
1226             debug_aranges.buf.writeByte(0);            // segment_size
1227             debug_aranges.buf.write32(0);              // pad to 16
1228         }
1229     }
1230 
1231 
1232     /*************************************
1233      * Add a file to the .debug_line header
1234      */
1235     int dwarf_line_addfile(const(char)* filename)
1236     {
1237         return dwarf_line_addfile(filename ? filename[0 .. strlen(filename)] : null);
1238     }
1239 
1240     /// Ditto
1241     extern(D) int dwarf_line_addfile(const(char)[] filename)
1242     {
1243         if (!infoFileName_table)
1244         {
1245             infoFileName_table = AAchars.create();
1246             linebuf_filetab_end = debug_line.buf.length();
1247         }
1248 
1249         uint *pidx = infoFileName_table.get(filename);
1250         if (!*pidx)                 // if no idx assigned yet
1251         {
1252             *pidx = infoFileName_table.length(); // assign newly computed idx
1253 
1254             size_t before = debug_line.buf.length();
1255             debug_line.buf.writeString(filename);
1256             debug_line.buf.writeByte(0);      // directory table index
1257             debug_line.buf.writeByte(0);      // mtime
1258             debug_line.buf.writeByte(0);      // length
1259             linebuf_filetab_end += debug_line.buf.length() - before;
1260         }
1261 
1262         return *pidx;
1263     }
1264 
1265     void dwarf_initmodule(const(char)* filename, const(char)* modname)
1266     {
1267         dwarf_initmodule(filename ? filename[0 .. strlen(filename)] : null,
1268                          modname ? modname[0 .. strlen(modname)] : null);
1269     }
1270 
1271     extern(D) void dwarf_initmodule(const(char)[] filename, const(char)[] modname)
1272     {
1273         if (modname)
1274         {
1275             static immutable ubyte[6] abbrevModule =
1276             [
1277                 DW_TAG_module, DW_CHILDREN_no,
1278                 DW_AT_name,    DW_FORM_string, // module name
1279                 0,             0,
1280             ];
1281             abbrevcode++;
1282             debug_abbrev.buf.writeuLEB128(abbrevcode);
1283             debug_abbrev.buf.write(abbrevModule.ptr, abbrevModule.sizeof);
1284             debug_info.buf.writeuLEB128(abbrevcode);      // abbreviation code
1285             debug_info.buf.writeString(modname);          // DW_AT_name
1286             //hasModname = 1;
1287         }
1288         else
1289             hasModname = 0;
1290 
1291         dwarf_line_addfile(filename);
1292     }
1293 
1294     void dwarf_termmodule()
1295     {
1296         if (hasModname)
1297             debug_info.buf.writeByte(0);  // end of DW_TAG_module's children
1298     }
1299 
1300     /*************************************
1301      * Finish writing Dwarf debug info to object file.
1302      */
1303     void dwarf_termfile()
1304     {
1305         //printf("dwarf_termfile()\n");
1306 
1307         /* ======================================== */
1308 
1309         // Put out line number info
1310 
1311         // file_names
1312         uint last_filenumber = 0;
1313         const(char)* last_filename = null;
1314         for (uint seg = 1; seg < SegData.length; seg++)
1315         {
1316             for (uint i = 0; i < SegData[seg].SDlinnum_data.length; i++)
1317             {
1318                 linnum_data *ld = &SegData[seg].SDlinnum_data[i];
1319                 const(char)* filename;
1320 
1321                 version (MARS)
1322                     filename = ld.filename;
1323                 else
1324                 {
1325                     Sfile *sf = ld.filptr;
1326                     if (sf)
1327                         filename = sf.SFname;
1328                     else
1329                         filename = .filename;
1330                 }
1331 
1332                 if (last_filename == filename)
1333                 {
1334                     ld.filenumber = last_filenumber;
1335                 }
1336                 else
1337                 {
1338                     ld.filenumber = dwarf_line_addfile(filename);
1339 
1340                     last_filenumber = ld.filenumber;
1341                     last_filename = filename;
1342                 }
1343             }
1344         }
1345         // assert we haven't emitted anything but file table entries
1346         assert(debug_line.buf.length() == linebuf_filetab_end);
1347         debug_line.buf.writeByte(0);              // end of file_names
1348 
1349         debugline.prologue_length = cast(uint)debug_line.buf.length() - 10;
1350 
1351         for (uint seg = 1; seg < SegData.length; seg++)
1352         {
1353             seg_data *sd = SegData[seg];
1354             uint addressmax = 0;
1355             uint linestart = ~0;
1356 
1357             if (!sd.SDlinnum_data.length)
1358                 continue;
1359 
1360             static if (ELFOBJ)
1361                 if (!sd.SDsym) // gdb ignores line number data without a DW_AT_name
1362                     continue;
1363 
1364             //printf("sd = %x, SDlinnum_count = %d\n", sd, sd.SDlinnum_count);
1365             for (int i = 0; i < sd.SDlinnum_data.length; i++)
1366             {   linnum_data *ld = &sd.SDlinnum_data[i];
1367 
1368                 // Set address to start of segment with DW_LNE_set_address
1369                 debug_line.buf.writeByte(0);
1370                 debug_line.buf.writeByte(_tysize[TYnptr] + 1);
1371                 debug_line.buf.writeByte(DW_LNE_set_address);
1372 
1373                 dwarf_appreladdr(debug_line.seg,debug_line.buf,seg,0);
1374 
1375                 // Dwarf2 6.2.2 State machine registers
1376                 uint address = 0;       // instruction address
1377                 uint file = ld.filenumber;
1378                 uint line = 1;          // line numbers beginning with 1
1379 
1380                 debug_line.buf.writeByte(DW_LNS_set_file);
1381                 debug_line.buf.writeuLEB128(file);
1382 
1383                 for (int j = 0; j < ld.linoff.length; j++)
1384                 {   int lininc = ld.linoff[j].lineNumber - line;
1385                     int addinc = ld.linoff[j].offset - address;
1386 
1387                     //printf("\tld[%d] line = %d offset = x%x lininc = %d addinc = %d\n", j, ld.linoff[j].lineNumber, ld.linoff[j].offset, lininc, addinc);
1388 
1389                     //assert(addinc >= 0);
1390                     if (addinc < 0)
1391                         continue;
1392                     if (j && lininc == 0 && !(addinc && j + 1 == ld.linoff.length))
1393                         continue;
1394                     line += lininc;
1395                     if (line < linestart)
1396                         linestart = line;
1397                     address += addinc;
1398                     if (address >= addressmax)
1399                         addressmax = address + 1;
1400                     if (lininc >= debugline.line_base && lininc < debugline.line_base + debugline.line_range)
1401                     {
1402                         uint opcode = lininc - debugline.line_base +
1403                             debugline.line_range * addinc +
1404                             debugline.opcode_base;
1405 
1406                         if (opcode <= 255)
1407                         {
1408                             debug_line.buf.writeByte(opcode);
1409                             continue;
1410                         }
1411                     }
1412                     if (lininc)
1413                     {
1414                         debug_line.buf.writeByte(DW_LNS_advance_line);
1415                         debug_line.buf.writesLEB128(cast(int)lininc);
1416                     }
1417                     if (addinc)
1418                     {
1419                         debug_line.buf.writeByte(DW_LNS_advance_pc);
1420                         debug_line.buf.writeuLEB128(cast(uint)addinc);
1421                     }
1422                     if (lininc || addinc)
1423                         debug_line.buf.writeByte(DW_LNS_copy);
1424                 }
1425 
1426                 // Write DW_LNS_advance_pc to cover the function prologue
1427                 debug_line.buf.writeByte(DW_LNS_advance_pc);
1428                 debug_line.buf.writeuLEB128(cast(uint)(sd.SDbuf.length() - address));
1429 
1430                 // Write DW_LNE_end_sequence
1431                 debug_line.buf.writeByte(0);
1432                 debug_line.buf.writeByte(1);
1433                 debug_line.buf.writeByte(1);
1434 
1435                 // reset linnum_data
1436                 ld.linoff.reset();
1437             }
1438         }
1439 
1440         debugline.total_length = cast(uint)debug_line.buf.length() - 4;
1441         memcpy(debug_line.buf.buf, &debugline, debugline.sizeof);
1442 
1443         // Bugzilla 3502, workaround OSX's ld64-77 bug.
1444         // Don't emit the the debug_line section if nothing has been written to the line table.
1445         if (debugline.prologue_length + 10 == debugline.total_length + 4)
1446             debug_line.buf.reset();
1447 
1448         /* ================================================= */
1449 
1450         debug_abbrev.buf.writeByte(0);
1451 
1452         /* ================================================= */
1453 
1454         // debug_info
1455         {
1456             debug_info.buf.writeByte(0);    // ending abbreviation code
1457             rewrite32(debug_info.buf, 0, cast(uint) debug_info.buf.length() - 4); // rewrites the unit length
1458         }
1459 
1460 
1461         /* ================================================= */
1462 
1463         // Terminate by offset field containing 0
1464         debug_pubnames.buf.write32(0);
1465 
1466         // Plug final sizes into header
1467         *cast(uint *)debug_pubnames.buf.buf = cast(uint)debug_pubnames.buf.length() - 4;
1468         *cast(uint *)(debug_pubnames.buf.buf + 10) = cast(uint)debug_info.buf.length();
1469 
1470         /* ================================================= */
1471 
1472         // Terminate by address/length fields containing 0
1473         append_addr(debug_aranges.buf, 0);
1474         append_addr(debug_aranges.buf, 0);
1475 
1476         // Plug final sizes into header
1477         *cast(uint *)debug_aranges.buf.buf = cast(uint)debug_aranges.buf.length() - 4;
1478 
1479         /* ================================================= */
1480 
1481         // Terminate by beg address/end address fields containing 0
1482         append_addr(debug_ranges.buf, 0);
1483         append_addr(debug_ranges.buf, 0);
1484 
1485         /* ================================================= */
1486 
1487         // Free only if starting another file. Waste of time otherwise.
1488         if (type_table)
1489         {
1490             AApair.destroy(type_table);
1491             type_table = null;
1492         }
1493         if (functype_table)
1494         {
1495             AApair.destroy(functype_table);
1496             functype_table = null;
1497         }
1498         if (functypebuf)
1499             functypebuf.reset();
1500     }
1501 
1502     /*****************************************
1503      * Start of code gen for function.
1504      */
1505     void dwarf_func_start(Symbol *sfunc)
1506     {
1507         //printf("dwarf_func_start(%s)\n", sfunc.Sident.ptr);
1508         if (I16 || I32)
1509             CFA_state_current = CFA_state_init_32;
1510         else if (I64)
1511             CFA_state_current = CFA_state_init_64;
1512         else
1513             assert(0);
1514         CFA_state_current.reg = dwarf_regno(SP);
1515         assert(CFA_state_current.offset == OFFSET_FAC);
1516         cfa_buf.reset();
1517     }
1518 
1519     /*****************************************
1520      * End of code gen for function.
1521      */
1522     void dwarf_func_term(Symbol *sfunc)
1523     {
1524         //printf("dwarf_func_term(sfunc = '%s')\n", sfunc.Sident.ptr);
1525 
1526         if (config.ehmethod == EHmethod.EH_DWARF)
1527         {
1528             bool ehunwind = doUnwindEhFrame();
1529 
1530             IDXSEC dfseg = dwarf_eh_frame_alloc();
1531 
1532             Outbuffer *buf = SegData[dfseg].SDbuf;
1533             buf.reserve(1000);
1534 
1535             uint *poffset = ehunwind ? &CIE_offset_unwind : &CIE_offset_no_unwind;
1536             if (*poffset == ~0)
1537                 *poffset = writeEhFrameHeader(dfseg, buf, getRtlsymPersonality(), ehunwind);
1538 
1539             writeEhFrameFDE(dfseg, sfunc, ehunwind, *poffset);
1540         }
1541         if (!config.fulltypes)
1542             return;
1543 
1544         version (MARS)
1545         {
1546             if (sfunc.Sflags & SFLnodebug)
1547                 return;
1548             const(char)* filename = sfunc.Sfunc.Fstartline.Sfilename;
1549             if (!filename)
1550                 return;
1551         }
1552 
1553         uint funcabbrevcode;
1554 
1555         if (ehmethod(sfunc) == EHmethod.EH_DM)
1556         {
1557             static if (MACHOBJ)
1558                 int flags = S_ATTR_DEBUG;
1559             else static if (ELFOBJ)
1560                 int flags = SHT_PROGBITS;
1561             else
1562                 int flags = 0;
1563 
1564             IDXSEC dfseg = dwarf_getsegment(debug_frame_name, 1, flags);
1565             writeDebugFrameFDE(dfseg, sfunc);
1566         }
1567 
1568         IDXSEC seg = sfunc.Sseg;
1569         seg_data *sd = SegData[seg];
1570 
1571         version (MARS)
1572             int filenum = dwarf_line_addfile(filename);
1573         else
1574             int filenum = 1;
1575 
1576         uint ret_type = dwarf_typidx(sfunc.Stype.Tnext);
1577         if (tybasic(sfunc.Stype.Tnext.Tty) == TYvoid)
1578             ret_type = 0;
1579 
1580         // See if there are any parameters
1581         int haveparameters = 0;
1582         uint formalcode = 0;
1583         uint autocode = 0;
1584 
1585         for (SYMIDX si = 0; si < globsym.length; si++)
1586         {
1587             Symbol *sa = globsym[si];
1588 
1589             version (MARS)
1590                 if (sa.Sflags & SFLnodebug) continue;
1591 
1592             __gshared ubyte[12] formal =
1593             [
1594                 DW_TAG_formal_parameter,
1595                 0,
1596                 DW_AT_name,       DW_FORM_string,
1597                 DW_AT_type,       DW_FORM_ref4,
1598                 DW_AT_artificial, DW_FORM_flag,
1599                 DW_AT_location,   DW_FORM_block1,
1600                 0,                0,
1601             ];
1602 
1603             switch (sa.Sclass)
1604             {
1605                 case SCparameter:
1606                 case SCregpar:
1607                 case SCfastpar:
1608                     dwarf_typidx(sa.Stype);
1609                     formal[0] = DW_TAG_formal_parameter;
1610                     if (!formalcode)
1611                         formalcode = dwarf_abbrev_code(formal.ptr, formal.sizeof);
1612                     haveparameters = 1;
1613                     break;
1614 
1615                 case SCauto:
1616                 case SCbprel:
1617                 case SCregister:
1618                 case SCpseudo:
1619                     dwarf_typidx(sa.Stype);
1620                     formal[0] = DW_TAG_variable;
1621                     if (!autocode)
1622                         autocode = dwarf_abbrev_code(formal.ptr, formal.sizeof);
1623                     haveparameters = 1;
1624                     break;
1625 
1626                 default:
1627                     break;
1628             }
1629         }
1630 
1631         Outbuffer abuf;
1632         abuf.writeByte(DW_TAG_subprogram);
1633         abuf.writeByte(haveparameters);          // have children?
1634         if (haveparameters)
1635         {
1636             abuf.writeByte(DW_AT_sibling);  abuf.writeByte(DW_FORM_ref4);
1637         }
1638         abuf.writeByte(DW_AT_name);      abuf.writeByte(DW_FORM_string);
1639 
1640         if (config.dwarf >= 4)
1641             abuf.writeuLEB128(DW_AT_linkage_name);
1642         else
1643             abuf.writeuLEB128(DW_AT_MIPS_linkage_name);
1644         abuf.writeByte(DW_FORM_string);
1645 
1646         abuf.writeByte(DW_AT_decl_file); abuf.writeByte(DW_FORM_data1);
1647         abuf.writeByte(DW_AT_decl_line); abuf.writeByte(DW_FORM_data2);
1648         if (ret_type)
1649         {
1650             abuf.writeByte(DW_AT_type);  abuf.writeByte(DW_FORM_ref4);
1651         }
1652         if (sfunc.Sclass == SCglobal)
1653         {
1654             abuf.writeByte(DW_AT_external);       abuf.writeByte(DW_FORM_flag);
1655         }
1656         if (sfunc.Sfunc.Fflags3 & Fpure)
1657         {
1658             abuf.writeByte(DW_AT_pure);
1659             if (config.dwarf >= 4)
1660                 abuf.writeByte(DW_FORM_flag_present);
1661             else
1662                 abuf.writeByte(DW_FORM_flag);
1663         }
1664 
1665         abuf.writeByte(DW_AT_low_pc);     abuf.writeByte(DW_FORM_addr);
1666         abuf.writeByte(DW_AT_high_pc);    abuf.writeByte(DW_FORM_addr);
1667         abuf.writeByte(DW_AT_frame_base); abuf.writeByte(DW_FORM_data4);
1668         abuf.writeByte(0);                abuf.writeByte(0);
1669 
1670         funcabbrevcode = dwarf_abbrev_code(abuf.buf, abuf.length());
1671 
1672         uint idxsibling = 0;
1673         uint siblingoffset;
1674 
1675         uint infobuf_offset = cast(uint)debug_info.buf.length();
1676         debug_info.buf.writeuLEB128(funcabbrevcode);  // abbreviation code
1677         if (haveparameters)
1678         {
1679             siblingoffset = cast(uint)debug_info.buf.length();
1680             debug_info.buf.write32(idxsibling);       // DW_AT_sibling
1681         }
1682 
1683         const(char)* name = getSymName(sfunc);
1684 
1685         debug_info.buf.writeString(name);             // DW_AT_name
1686         debug_info.buf.writeString(sfunc.Sident.ptr);    // DW_AT_MIPS_linkage_name
1687         debug_info.buf.writeByte(filenum);            // DW_AT_decl_file
1688         debug_info.buf.write16(sfunc.Sfunc.Fstartline.Slinnum);   // DW_AT_decl_line
1689         if (ret_type)
1690             debug_info.buf.write32(ret_type);         // DW_AT_type
1691 
1692         if (sfunc.Sclass == SCglobal)
1693             debug_info.buf.writeByte(1);              // DW_AT_external
1694 
1695         if (config.dwarf < 4 && sfunc.Sfunc.Fflags3 & Fpure)
1696             debug_info.buf.writeByte(true);           // DW_AT_pure
1697 
1698         // DW_AT_low_pc and DW_AT_high_pc
1699         dwarf_appreladdr(debug_info.seg, debug_info.buf, seg, funcoffset);
1700         dwarf_appreladdr(debug_info.seg, debug_info.buf, seg, funcoffset + sfunc.Ssize);
1701 
1702         // DW_AT_frame_base
1703         static if (ELFOBJ)
1704             dwarf_apprel32(debug_info.seg, debug_info.buf, debug_loc.seg, debug_loc.buf.length());
1705         else
1706             // 64-bit DWARF relocations don't work for OSX64 codegen
1707             debug_info.buf.write32(cast(uint)debug_loc.buf.length());
1708 
1709         if (haveparameters)
1710         {
1711             for (SYMIDX si = 0; si < globsym.length; si++)
1712             {
1713                 Symbol *sa = globsym[si];
1714 
1715                 version (MARS)
1716                     if (sa.Sflags & SFLnodebug)
1717                         continue;
1718 
1719                 uint vcode;
1720 
1721                 switch (sa.Sclass)
1722                 {
1723                     case SCparameter:
1724                     case SCregpar:
1725                     case SCfastpar:
1726                         vcode = formalcode;
1727                         goto L1;
1728                     case SCauto:
1729                     case SCregister:
1730                     case SCpseudo:
1731                     case SCbprel:
1732                         vcode = autocode;
1733                     L1:
1734                     {
1735                         uint soffset;
1736                         uint tidx = dwarf_typidx(sa.Stype);
1737 
1738                         debug_info.buf.writeuLEB128(vcode);           // abbreviation code
1739                         debug_info.buf.writeString(getSymName(sa));   // DW_AT_name
1740                         debug_info.buf.write32(tidx);                 // DW_AT_type
1741                         debug_info.buf.writeByte(sa.Sflags & SFLartifical ? 1 : 0); // DW_FORM_tag
1742                         soffset = cast(uint)debug_info.buf.length();
1743                         debug_info.buf.writeByte(2);                  // DW_FORM_block1
1744                         if (sa.Sfl == FLreg || sa.Sclass == SCpseudo)
1745                         {
1746                             // BUG: register pairs not supported in Dwarf?
1747                             debug_info.buf.writeByte(DW_OP_reg0 + sa.Sreglsw);
1748                         }
1749                         else if (sa.Sscope && vcode == autocode)
1750                         {
1751                             assert(sa.Sscope.Stype.Tnext && sa.Sscope.Stype.Tnext.Tty == TYstruct);
1752 
1753                             /* find member offset in closure */
1754                             targ_size_t memb_off = 0;
1755                             struct_t *st = sa.Sscope.Stype.Tnext.Ttag.Sstruct; // Sscope is __closptr
1756                             foreach (sl; ListRange(st.Sfldlst))
1757                             {
1758                                 Symbol *sf = list_symbol(sl);
1759                                 if (sf.Sclass == SCmember)
1760                                 {
1761                                     if(strcmp(sa.Sident.ptr, sf.Sident.ptr) == 0)
1762                                     {
1763                                         memb_off = sf.Smemoff;
1764                                         goto L2;
1765                                     }
1766                                 }
1767                             }
1768                         L2:
1769                             targ_size_t closptr_off = sa.Sscope.Soffset; // __closptr offset
1770                             //printf("dwarf closure: sym: %s, closptr: %s, ptr_off: %lli, memb_off: %lli\n",
1771                             //    sa.Sident.ptr, sa.Sscope.Sident.ptr, closptr_off, memb_off);
1772 
1773                             debug_info.buf.writeByte(DW_OP_fbreg);
1774                             debug_info.buf.writesLEB128(cast(uint)(Auto.size + BPoff - Para.size + closptr_off)); // closure pointer offset from frame base
1775                             debug_info.buf.writeByte(DW_OP_deref);
1776                             debug_info.buf.writeByte(DW_OP_plus_uconst);
1777                             debug_info.buf.writeuLEB128(cast(uint)memb_off); // closure variable offset
1778                         }
1779                         else
1780                         {
1781                             debug_info.buf.writeByte(DW_OP_fbreg);
1782                             if (sa.Sclass == SCregpar ||
1783                                 sa.Sclass == SCparameter)
1784                                 debug_info.buf.writesLEB128(cast(int)sa.Soffset);
1785                             else if (sa.Sclass == SCfastpar)
1786                                 debug_info.buf.writesLEB128(cast(int)(Fast.size + BPoff - Para.size + sa.Soffset));
1787                             else if (sa.Sclass == SCbprel)
1788                                 debug_info.buf.writesLEB128(cast(int)(-Para.size + sa.Soffset));
1789                             else
1790                                 debug_info.buf.writesLEB128(cast(int)(Auto.size + BPoff - Para.size + sa.Soffset));
1791                         }
1792                         debug_info.buf.buf[soffset] = cast(ubyte)(debug_info.buf.length() - soffset - 1);
1793                         break;
1794                     }
1795                     default:
1796                         break;
1797                 }
1798             }
1799             debug_info.buf.writeByte(0);              // end of parameter children
1800 
1801             idxsibling = cast(uint)debug_info.buf.length();
1802             *cast(uint *)(debug_info.buf.buf + siblingoffset) = idxsibling;
1803         }
1804 
1805         /* ============= debug_pubnames =========================== */
1806 
1807         debug_pubnames.buf.write32(infobuf_offset);
1808         debug_pubnames.buf.writeString(name);
1809 
1810         /* ============= debug_aranges =========================== */
1811 
1812         if (sd.SDaranges_offset)
1813             // Extend existing entry size
1814             *cast(ulong *)(debug_aranges.buf.buf + sd.SDaranges_offset + _tysize[TYnptr]) = funcoffset + sfunc.Ssize;
1815         else
1816         {   // Add entry
1817             sd.SDaranges_offset = cast(uint)debug_aranges.buf.length();
1818             // address of start of .text segment
1819             dwarf_appreladdr(debug_aranges.seg, debug_aranges.buf, seg, 0);
1820             // size of .text segment
1821             append_addr(debug_aranges.buf, funcoffset + sfunc.Ssize);
1822         }
1823 
1824         /* ============= debug_ranges =========================== */
1825 
1826         /* Each function gets written into its own segment,
1827          * indicate this by adding to the debug_ranges
1828          */
1829         // start of function and end of function
1830         dwarf_appreladdr(debug_ranges.seg, debug_ranges.buf, seg, funcoffset);
1831         dwarf_appreladdr(debug_ranges.seg, debug_ranges.buf, seg, funcoffset + sfunc.Ssize);
1832 
1833         /* ============= debug_loc =========================== */
1834 
1835         assert(Para.size >= 2 * REGSIZE);
1836         assert(Para.size < 63); // avoid sLEB128 encoding
1837         ushort op_size = 0x0002;
1838         ushort loc_op;
1839 
1840         // set the entry for this function in .debug_loc segment
1841         // after call
1842         dwarf_appreladdr(debug_loc.seg, debug_loc.buf, seg, funcoffset + 0);
1843         dwarf_appreladdr(debug_loc.seg, debug_loc.buf, seg, funcoffset + 1);
1844 
1845         loc_op = cast(ushort)(((Para.size - REGSIZE) << 8) | (DW_OP_breg0 + dwarf_regno(SP)));
1846         debug_loc.buf.write32(loc_op << 16 | op_size);
1847 
1848         // after push EBP
1849         dwarf_appreladdr(debug_loc.seg, debug_loc.buf, seg, funcoffset + 1);
1850         dwarf_appreladdr(debug_loc.seg, debug_loc.buf, seg, funcoffset + 3);
1851 
1852         loc_op = cast(ushort)(((Para.size) << 8) | (DW_OP_breg0 + dwarf_regno(SP)));
1853         debug_loc.buf.write32(loc_op << 16 | op_size);
1854 
1855         // after mov EBP, ESP
1856         dwarf_appreladdr(debug_loc.seg, debug_loc.buf, seg, funcoffset + 3);
1857         dwarf_appreladdr(debug_loc.seg, debug_loc.buf, seg, funcoffset + sfunc.Ssize);
1858 
1859         loc_op = cast(ushort)(((Para.size) << 8) | (DW_OP_breg0 + dwarf_regno(BP)));
1860         debug_loc.buf.write32(loc_op << 16 | op_size);
1861 
1862         // 2 zero addresses to end loc_list
1863         append_addr(debug_loc.buf, 0);
1864         append_addr(debug_loc.buf, 0);
1865     }
1866 
1867 
1868     /******************************************
1869      * Write out symbol table for current function.
1870      */
1871 
1872     void dwarf_outsym(Symbol *s)
1873     {
1874         //printf("dwarf_outsym('%s')\n",s.Sident.ptr);
1875         //symbol_print(s);
1876 
1877         symbol_debug(s);
1878 
1879         version (MARS)
1880         {
1881             if (s.Sflags & SFLnodebug)
1882                 return;
1883         }
1884 
1885         type *t = s.Stype;
1886         type_debug(t);
1887         tym_t tym = tybasic(t.Tty);
1888         if (tyfunc(tym) && s.Sclass != SCtypedef)
1889             return;
1890 
1891         Outbuffer abuf;
1892         uint code;
1893         uint typidx;
1894         uint soffset;
1895         switch (s.Sclass)
1896         {
1897             case SCglobal:
1898                 typidx = dwarf_typidx(t);
1899 
1900                 abuf.writeByte(DW_TAG_variable);
1901                 abuf.writeByte(DW_CHILDREN_no);
1902                 abuf.writeByte(DW_AT_name);         abuf.writeByte(DW_FORM_string);
1903                 abuf.writeByte(DW_AT_type);         abuf.writeByte(DW_FORM_ref4);
1904                 abuf.writeByte(DW_AT_external);     abuf.writeByte(DW_FORM_flag);
1905                 abuf.writeByte(DW_AT_location);     abuf.writeByte(DW_FORM_block1);
1906                 abuf.writeByte(0);                  abuf.writeByte(0);
1907                 code = dwarf_abbrev_code(abuf.buf, abuf.length());
1908 
1909                 debug_info.buf.writeuLEB128(code);        // abbreviation code
1910                 debug_info.buf.writeString(getSymName(s));// DW_AT_name
1911                 debug_info.buf.write32(typidx);           // DW_AT_type
1912                 debug_info.buf.writeByte(1);              // DW_AT_external
1913 
1914                 soffset = cast(uint)debug_info.buf.length();
1915                 debug_info.buf.writeByte(2);                      // DW_FORM_block1
1916 
1917                 static if (ELFOBJ)
1918                 {
1919                     // debug info for TLS variables
1920                     assert(s.Sxtrnnum);
1921                     if (s.Sfl == FLtlsdata)
1922                     {
1923                         if (I64)
1924                         {
1925                             debug_info.buf.writeByte(DW_OP_const8u);
1926                             Obj.addrel(debug_info.seg, debug_info.buf.length(), R_X86_64_DTPOFF32, s.Sxtrnnum, 0);
1927                             debug_info.buf.write64(0);
1928                         }
1929                         else
1930                         {
1931                             debug_info.buf.writeByte(DW_OP_const4u);
1932                             Obj.addrel(debug_info.seg, debug_info.buf.length(), R_386_TLS_LDO_32, s.Sxtrnnum, 0);
1933                             debug_info.buf.write32(0);
1934                         }
1935                         debug_info.buf.writeByte(DW_OP_GNU_push_tls_address);
1936                     }
1937                     else
1938                     {
1939                         debug_info.buf.writeByte(DW_OP_addr);
1940                         dwarf_appreladdr(debug_info.seg, debug_info.buf, s.Sseg, s.Soffset); // address of global
1941                     }
1942                 }
1943                 else
1944                 {
1945                     debug_info.buf.writeByte(DW_OP_addr);
1946                     dwarf_appreladdr(debug_info.seg, debug_info.buf, s.Sseg, s.Soffset); // address of global
1947                 }
1948 
1949                 debug_info.buf.buf[soffset] = cast(ubyte)(debug_info.buf.length() - soffset - 1);
1950                 break;
1951 
1952             default:
1953                 break;
1954         }
1955     }
1956 
1957 
1958     /******************************************
1959      * Write out any deferred symbols.
1960      */
1961     static if (0)
1962     void cv_outlist()
1963     {
1964     }
1965 
1966 
1967     /* =================== Cached Types in debug_info ================= */
1968 
1969     ubyte dwarf_classify_struct(uint sflags)
1970     {
1971         if (sflags & STRclass)
1972             return DW_TAG_class_type;
1973 
1974         if (sflags & STRunion)
1975             return DW_TAG_union_type;
1976 
1977         return DW_TAG_structure_type;
1978     }
1979 
1980     /* ======================= Type Index ============================== */
1981 
1982     uint dwarf_typidx(type *t)
1983     {
1984         uint idx = 0;
1985         uint nextidx;
1986         uint keyidx;
1987         uint pvoididx;
1988         uint code;
1989         type *tnext;
1990         type *tbase;
1991         const(char)* p;
1992 
1993         static immutable ubyte[10] abbrevTypeBasic =
1994         [
1995             DW_TAG_base_type,       DW_CHILDREN_no,
1996             DW_AT_name,             DW_FORM_string,
1997             DW_AT_byte_size,        DW_FORM_data1,
1998             DW_AT_encoding,         DW_FORM_data1,
1999             0,                      0,
2000         ];
2001         static immutable ubyte[12] abbrevWchar =
2002         [
2003             DW_TAG_typedef,         DW_CHILDREN_no,
2004             DW_AT_name,             DW_FORM_string,
2005             DW_AT_type,             DW_FORM_ref4,
2006             DW_AT_decl_file,        DW_FORM_data1,
2007             DW_AT_decl_line,        DW_FORM_data2,
2008             0,                      0,
2009         ];
2010         static immutable ubyte[6] abbrevTypePointer =
2011         [
2012             DW_TAG_pointer_type,    DW_CHILDREN_no,
2013             DW_AT_type,             DW_FORM_ref4,
2014             0,                      0,
2015         ];
2016         static immutable ubyte[4] abbrevTypePointerVoid =
2017         [
2018             DW_TAG_pointer_type,    DW_CHILDREN_no,
2019             0,                      0,
2020         ];
2021         static immutable ubyte[6] abbrevTypeRef =
2022         [
2023             DW_TAG_reference_type,  DW_CHILDREN_no,
2024             DW_AT_type,             DW_FORM_ref4,
2025             0,                      0,
2026         ];
2027         static immutable ubyte[6] abbrevTypeConst =
2028         [
2029             DW_TAG_const_type,      DW_CHILDREN_no,
2030             DW_AT_type,             DW_FORM_ref4,
2031             0,                      0,
2032         ];
2033         static immutable ubyte[4] abbrevTypeConstVoid =
2034         [
2035             DW_TAG_const_type,      DW_CHILDREN_no,
2036             0,                      0,
2037         ];
2038         static immutable ubyte[6] abbrevTypeVolatile =
2039         [
2040             DW_TAG_volatile_type,   DW_CHILDREN_no,
2041             DW_AT_type,             DW_FORM_ref4,
2042             0,                      0,
2043         ];
2044         static immutable ubyte[4] abbrevTypeVolatileVoid =
2045         [
2046             DW_TAG_volatile_type,   DW_CHILDREN_no,
2047             0,                      0,
2048         ];
2049         static immutable ubyte[6] abbrevTypeShared =
2050         [
2051             DW_TAG_shared_type,     DW_CHILDREN_no,
2052             DW_AT_type,             DW_FORM_ref4,
2053             0,                      0,
2054         ];
2055         static immutable ubyte[4] abbrevTypeSharedVoid =
2056         [
2057             DW_TAG_shared_type,     DW_CHILDREN_no,
2058             0,                      0,
2059         ];
2060 
2061         if (!t)
2062             return 0;
2063 
2064         foreach(mty; [mTYconst, mTYshared, mTYvolatile])
2065         {
2066             if (t.Tty & mty)
2067             {
2068                 // We make a copy of the type to strip off the const qualifier and
2069                 // recurse, and then add the const abbrev code. To avoid ending in a
2070                 // loop if the type references the const version of itself somehow,
2071                 // we need to set TFforward here, because setting TFforward during
2072                 // member generation of dwarf_typidx(tnext) has no effect on t itself.
2073                 const ushort old_flags = t.Tflags;
2074                 t.Tflags |= TFforward;
2075 
2076                 tnext = type_copy(t);
2077                 tnext.Tcount++;
2078                 tnext.Tty &= ~mty;
2079                 nextidx = dwarf_typidx(tnext);
2080 
2081                 t.Tflags = old_flags;
2082 
2083                 if (mty == mTYconst)
2084                 {
2085                     code = nextidx
2086                         ? dwarf_abbrev_code(abbrevTypeConst)
2087                         : dwarf_abbrev_code(abbrevTypeConstVoid);
2088                 }
2089                 else if (mty == mTYvolatile)
2090                 {
2091                     code = nextidx
2092                         ? dwarf_abbrev_code(abbrevTypeVolatile)
2093                         : dwarf_abbrev_code(abbrevTypeVolatileVoid);
2094                 }
2095                 else if (mty == mTYshared)
2096                 {
2097                     code = nextidx
2098                         ? dwarf_abbrev_code(abbrevTypeShared)
2099                         : dwarf_abbrev_code(abbrevTypeSharedVoid);
2100                 }
2101                 else
2102                     assert(0);
2103 
2104                 idx = cast(uint)debug_info.buf.length();
2105                 debug_info.buf.writeuLEB128(code);    // abbreviation code
2106                 if (nextidx)
2107                     debug_info.buf.write32(nextidx);  // DW_AT_type
2108                 goto Lret;
2109             }
2110         }
2111 
2112         tym_t ty;
2113         ty = tybasic(t.Tty);
2114         // use cached basic type if it's not TYdarray or TYdelegate
2115         if (!(t.Tnext && (ty == TYdarray || ty == TYdelegate)))
2116         {
2117             idx = typidx_tab[ty];
2118             if (idx)
2119                 return idx;
2120         }
2121 
2122         ubyte ate;
2123         ate = tyuns(t.Tty) ? DW_ATE_unsigned : DW_ATE_signed;
2124 
2125         static immutable ubyte[8] abbrevTypeStruct =
2126         [
2127             DW_TAG_structure_type,  DW_CHILDREN_yes,
2128             DW_AT_name,             DW_FORM_string,
2129             DW_AT_byte_size,        DW_FORM_data1,
2130             0,                      0,
2131         ];
2132 
2133         static immutable ubyte[10] abbrevTypeMember =
2134         [
2135             DW_TAG_member,          DW_CHILDREN_no,
2136             DW_AT_name,             DW_FORM_string,
2137             DW_AT_type,             DW_FORM_ref4,
2138             DW_AT_data_member_location, DW_FORM_block1,
2139             0,                      0,
2140         ];
2141 
2142         switch (tybasic(t.Tty))
2143         {
2144             Lnptr:
2145                 nextidx = dwarf_typidx(t.Tnext);
2146                 code = nextidx
2147                     ? dwarf_abbrev_code(abbrevTypePointer.ptr, (abbrevTypePointer).sizeof)
2148                     : dwarf_abbrev_code(abbrevTypePointerVoid.ptr, (abbrevTypePointerVoid).sizeof);
2149                 idx = cast(uint)debug_info.buf.length();
2150                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2151                 if (nextidx)
2152                     debug_info.buf.write32(nextidx);      // DW_AT_type
2153                 break;
2154 
2155             case TYullong:
2156             case TYucent:
2157                 if (!t.Tnext)
2158                 {   p = (tybasic(t.Tty) == TYullong) ? "uint long long" : "ucent";
2159                     goto Lsigned;
2160                 }
2161 
2162                 /* It's really TYdarray, and Tnext is the
2163                  * element type
2164                  */
2165                 {
2166                     uint lenidx = I64 ? dwarf_typidx(tstypes[TYulong]) : dwarf_typidx(tstypes[TYuint]);
2167 
2168                     {
2169                         type *tdata = type_alloc(TYnptr);
2170                         tdata.Tnext = t.Tnext;
2171                         t.Tnext.Tcount++;
2172                         tdata.Tcount++;
2173                         nextidx = dwarf_typidx(tdata);
2174                         type_free(tdata);
2175                     }
2176 
2177                     code = dwarf_abbrev_code(abbrevTypeStruct.ptr, (abbrevTypeStruct).sizeof);
2178                     idx = cast(uint)debug_info.buf.length();
2179                     debug_info.buf.writeuLEB128(code);        // abbreviation code
2180                     debug_info.buf.write("_Array_".ptr, 7);       // DW_AT_name
2181                     // Handles multi-dimensional array
2182                     auto lastdim = t.Tnext;
2183                     while (lastdim.Tty == TYucent && lastdim.Tnext)
2184                     {
2185                         debug_info.buf.write("Array_".ptr, 6);
2186                         lastdim = lastdim.Tnext;
2187                     }
2188 
2189                     if (tybasic(lastdim.Tty))
2190                         debug_info.buf.writeString(tystring[tybasic(lastdim.Tty)]);
2191                     else
2192                         debug_info.buf.writeByte(0);
2193                     debug_info.buf.writeByte(tysize(t.Tty)); // DW_AT_byte_size
2194 
2195                     // length
2196                     code = dwarf_abbrev_code(abbrevTypeMember.ptr, (abbrevTypeMember).sizeof);
2197                     debug_info.buf.writeuLEB128(code);        // abbreviation code
2198                     debug_info.buf.writeString("length");     // DW_AT_name
2199                     debug_info.buf.write32(lenidx);           // DW_AT_type
2200 
2201                     debug_info.buf.writeByte(2);              // DW_AT_data_member_location
2202                     debug_info.buf.writeByte(DW_OP_plus_uconst);
2203                     debug_info.buf.writeByte(0);
2204 
2205                     // ptr
2206                     debug_info.buf.writeuLEB128(code);        // abbreviation code
2207                     debug_info.buf.writeString("ptr");        // DW_AT_name
2208                     debug_info.buf.write32(nextidx);          // DW_AT_type
2209 
2210                     debug_info.buf.writeByte(2);              // DW_AT_data_member_location
2211                     debug_info.buf.writeByte(DW_OP_plus_uconst);
2212                     debug_info.buf.writeByte(I64 ? 8 : 4);
2213 
2214                     debug_info.buf.writeByte(0);              // no more children
2215                 }
2216                 break;
2217 
2218             case TYllong:
2219             case TYcent:
2220                 if (!t.Tnext)
2221                 {   p = (tybasic(t.Tty) == TYllong) ? "long long" : "cent";
2222                     goto Lsigned;
2223                 }
2224                 /* It's really TYdelegate, and Tnext is the
2225                  * function type
2226                  */
2227                 {
2228                     type *tp = type_fake(TYnptr);
2229                     tp.Tcount++;
2230                     pvoididx = dwarf_typidx(tp);    // void*
2231 
2232                     tp.Tnext = t.Tnext;           // fptr*
2233                     tp.Tnext.Tcount++;
2234                     nextidx = dwarf_typidx(tp);
2235                     type_free(tp);
2236                 }
2237 
2238                 code = dwarf_abbrev_code(abbrevTypeStruct.ptr, (abbrevTypeStruct).sizeof);
2239                 idx = cast(uint)debug_info.buf.length();
2240                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2241                 debug_info.buf.writeString("_Delegate");  // DW_AT_name
2242                 debug_info.buf.writeByte(tysize(t.Tty)); // DW_AT_byte_size
2243 
2244                 // ctxptr
2245                 code = dwarf_abbrev_code(abbrevTypeMember.ptr, (abbrevTypeMember).sizeof);
2246                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2247                 debug_info.buf.writeString("ctxptr");     // DW_AT_name
2248                 debug_info.buf.write32(pvoididx);         // DW_AT_type
2249 
2250                 debug_info.buf.writeByte(2);              // DW_AT_data_member_location
2251                 debug_info.buf.writeByte(DW_OP_plus_uconst);
2252                 debug_info.buf.writeByte(0);
2253 
2254                 // funcptr
2255                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2256                 debug_info.buf.writeString("funcptr");    // DW_AT_name
2257                 debug_info.buf.write32(nextidx);          // DW_AT_type
2258 
2259                 debug_info.buf.writeByte(2);              // DW_AT_data_member_location
2260                 debug_info.buf.writeByte(DW_OP_plus_uconst);
2261                 debug_info.buf.writeByte(I64 ? 8 : 4);
2262 
2263                 debug_info.buf.writeByte(0);              // no more children
2264                 break;
2265 
2266             case TYnref:
2267             case TYref:
2268                 nextidx = dwarf_typidx(t.Tnext);
2269                 assert(nextidx);
2270                 code = dwarf_abbrev_code(abbrevTypeRef.ptr, (abbrevTypeRef).sizeof);
2271                 idx = cast(uint)cast(uint)debug_info.buf.length();
2272                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2273                 debug_info.buf.write32(nextidx);          // DW_AT_type
2274                 break;
2275 
2276             case TYnptr:
2277                 if (!t.Tkey)
2278                     goto Lnptr;
2279 
2280                 /* It's really TYaarray, and Tnext is the
2281                  * element type, Tkey is the key type
2282                  */
2283                 {
2284                     type *tp = type_fake(TYnptr);
2285                     tp.Tcount++;
2286                     pvoididx = dwarf_typidx(tp);    // void*
2287                 }
2288 
2289                 code = dwarf_abbrev_code(abbrevTypeStruct.ptr, (abbrevTypeStruct).sizeof);
2290                 idx = cast(uint)debug_info.buf.length();
2291                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2292                 debug_info.buf.write("_AArray_".ptr, 8);      // DW_AT_name
2293                 if (tybasic(t.Tkey.Tty))
2294                     p = tystring[tybasic(t.Tkey.Tty)];
2295                 else
2296                     p = "key";
2297                 debug_info.buf.write(p, cast(uint)strlen(p));
2298 
2299                 debug_info.buf.writeByte('_');
2300                 if (tybasic(t.Tnext.Tty))
2301                     p = tystring[tybasic(t.Tnext.Tty)];
2302                 else
2303                     p = "value";
2304                 debug_info.buf.writeString(p);
2305 
2306                 debug_info.buf.writeByte(tysize(t.Tty)); // DW_AT_byte_size
2307 
2308                 // ptr
2309                 code = dwarf_abbrev_code(abbrevTypeMember.ptr, (abbrevTypeMember).sizeof);
2310                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2311                 debug_info.buf.writeString("ptr");        // DW_AT_name
2312                 debug_info.buf.write32(pvoididx);         // DW_AT_type
2313 
2314                 debug_info.buf.writeByte(2);              // DW_AT_data_member_location
2315                 debug_info.buf.writeByte(DW_OP_plus_uconst);
2316                 debug_info.buf.writeByte(0);
2317 
2318                 debug_info.buf.writeByte(0);              // no more children
2319                 break;
2320 
2321             case TYvoid:        return 0;
2322             case TYbool:        p = "_Bool";         ate = DW_ATE_boolean;       goto Lsigned;
2323             case TYchar:
2324                 p = "char";
2325                 ate = (config.flags & CFGuchar) ? DW_ATE_unsigned_char : DW_ATE_signed_char;
2326                 goto Lsigned;
2327             case TYschar:       p = "signed char";   ate = DW_ATE_signed_char;   goto Lsigned;
2328             case TYuchar:       p = "ubyte";         ate = DW_ATE_unsigned_char; goto Lsigned;
2329             case TYshort:       p = "short";         goto Lsigned;
2330             case TYushort:      p = "ushort";        goto Lsigned;
2331             case TYint:         p = "int";           goto Lsigned;
2332             case TYuint:        p = "uint";          goto Lsigned;
2333             case TYlong:        p = "long";          goto Lsigned;
2334             case TYulong:       p = "ulong";         goto Lsigned;
2335             case TYdchar:       p = "dchar";                goto Lsigned;
2336             case TYfloat:       p = "float";        ate = DW_ATE_float;     goto Lsigned;
2337             case TYdouble_alias:
2338             case TYdouble:      p = "double";       ate = DW_ATE_float;     goto Lsigned;
2339             case TYldouble:     p = "long double";  ate = DW_ATE_float;     goto Lsigned;
2340             case TYifloat:      p = "imaginary float";       ate = DW_ATE_imaginary_float;  goto Lsigned;
2341             case TYidouble:     p = "imaginary double";      ate = DW_ATE_imaginary_float;  goto Lsigned;
2342             case TYildouble:    p = "imaginary long double"; ate = DW_ATE_imaginary_float;  goto Lsigned;
2343             case TYcfloat:      p = "complex float";         ate = DW_ATE_complex_float;    goto Lsigned;
2344             case TYcdouble:     p = "complex double";        ate = DW_ATE_complex_float;    goto Lsigned;
2345             case TYcldouble:    p = "complex long double";   ate = DW_ATE_complex_float;    goto Lsigned;
2346             Lsigned:
2347                 code = dwarf_abbrev_code(abbrevTypeBasic.ptr, (abbrevTypeBasic).sizeof);
2348                 idx = cast(uint)debug_info.buf.length();
2349                 debug_info.buf.writeuLEB128(code);        // abbreviation code
2350                 debug_info.buf.writeString(p);            // DW_AT_name
2351                 debug_info.buf.writeByte(tysize(t.Tty)); // DW_AT_byte_size
2352                 debug_info.buf.writeByte(ate);            // DW_AT_encoding
2353                 typidx_tab[ty] = idx;
2354                 return idx;
2355 
2356             case TYnsfunc:
2357             case TYnpfunc:
2358             case TYjfunc:
2359 
2360             case TYnfunc:
2361             {
2362                 /* The dwarf typidx for the function type is completely determined by
2363                  * the return type typidx and the parameter typidx's. Thus, by
2364                  * caching these, we can cache the function typidx.
2365                  * Cache them in functypebuf[]
2366                  */
2367                 Outbuffer tmpbuf;
2368                 nextidx = dwarf_typidx(t.Tnext);                   // function return type
2369                 tmpbuf.write32(nextidx);
2370                 uint params = 0;
2371                 for (param_t *p2 = t.Tparamtypes; p2; p2 = p2.Pnext)
2372                 {
2373                     params = 1;
2374                     uint paramidx = dwarf_typidx(p2.Ptype);
2375                     //printf("1: paramidx = %d\n", paramidx);
2376 
2377                     debug
2378                         if (!paramidx)
2379                             type_print(p2.Ptype);
2380 
2381                     assert(paramidx);
2382                     tmpbuf.write32(paramidx);
2383                 }
2384 
2385                 if (!functypebuf)
2386                 {
2387                     functypebuf = cast(Outbuffer*) calloc(1, Outbuffer.sizeof);
2388                     assert(functypebuf);
2389                 }
2390                 uint functypebufidx = cast(uint)functypebuf.length();
2391                 functypebuf.write(tmpbuf.buf, cast(uint)tmpbuf.length());
2392                 /* If it's in the cache already, return the existing typidx
2393                  */
2394                 if (!functype_table)
2395                     functype_table = AApair.create(&functypebuf.buf);
2396                 uint *pidx = cast(uint *)functype_table.get(functypebufidx, cast(uint)functypebuf.length());
2397                 if (*pidx)
2398                 {
2399                     // Reuse existing typidx
2400                     functypebuf.setsize(functypebufidx);
2401                     return *pidx;
2402                 }
2403 
2404                 /* Not in the cache, create a new typidx
2405                  */
2406                 Outbuffer abuf;             // for abbrev
2407                 abuf.writeByte(DW_TAG_subroutine_type);
2408                 abuf.writeByte(params ? DW_CHILDREN_yes : DW_CHILDREN_no);
2409                 abuf.writeByte(DW_AT_prototyped);
2410                 abuf.writeByte(DW_FORM_flag);
2411                 if (nextidx != 0)           // Don't write DW_AT_type for void
2412                 {
2413                     abuf.writeByte(DW_AT_type);
2414                     abuf.writeByte(DW_FORM_ref4);
2415                 }
2416 
2417                 abuf.writeByte(0);
2418                 abuf.writeByte(0);
2419                 code = dwarf_abbrev_code(abuf.buf, abuf.length());
2420 
2421                 uint paramcode;
2422                 if (params)
2423                 {
2424                     abuf.reset();
2425                     abuf.writeByte(DW_TAG_formal_parameter);
2426                     abuf.writeByte(0);
2427                     abuf.writeByte(DW_AT_type);     abuf.writeByte(DW_FORM_ref4);
2428                     abuf.writeByte(0);              abuf.writeByte(0);
2429                     paramcode = dwarf_abbrev_code(abuf.buf, abuf.length());
2430                 }
2431 
2432                 idx = cast(uint)debug_info.buf.length();
2433                 debug_info.buf.writeuLEB128(code);
2434                 debug_info.buf.writeByte(1);            // DW_AT_prototyped
2435                 if (nextidx)                            // if return type is not void
2436                     debug_info.buf.write32(nextidx);    // DW_AT_type
2437 
2438                 if (params)
2439                 {
2440                     uint *pparamidx = cast(uint *)(functypebuf.buf + functypebufidx);
2441                     //printf("2: functypebufidx = %x, pparamidx = %p, size = %x\n", functypebufidx, pparamidx, functypebuf.length());
2442                     for (param_t *p2 = t.Tparamtypes; p2; p2 = p2.Pnext)
2443                     {
2444                         debug_info.buf.writeuLEB128(paramcode);
2445                         //uint x = dwarf_typidx(p2.Ptype);
2446                         uint paramidx = *++pparamidx;
2447                         //printf("paramidx = %d\n", paramidx);
2448                         assert(paramidx);
2449                         debug_info.buf.write32(paramidx);        // DW_AT_type
2450                     }
2451                     debug_info.buf.writeByte(0);          // end parameter list
2452                 }
2453 
2454                 *pidx = idx;                        // remember it in the functype_table[] cache
2455                 break;
2456             }
2457 
2458             case TYarray:
2459             {
2460                 static immutable ubyte[6] abbrevTypeArray =
2461                 [
2462                     DW_TAG_array_type,      DW_CHILDREN_yes,    // child (the subrange type)
2463                     DW_AT_type,             DW_FORM_ref4,
2464                     0,                      0,
2465                 ];
2466                 static immutable ubyte[4] abbrevTypeArrayVoid =
2467                 [
2468                     DW_TAG_array_type,      DW_CHILDREN_yes,    // child (the subrange type)
2469                     0,                      0,
2470                 ];
2471                 static immutable ubyte[8] abbrevTypeSubrange =
2472                 [
2473                     DW_TAG_subrange_type,   DW_CHILDREN_no,
2474                     DW_AT_type,             DW_FORM_ref4,
2475                     DW_AT_upper_bound,      DW_FORM_data4,
2476                     0,                      0,
2477                 ];
2478                 static immutable ubyte[6] abbrevTypeSubrange2 =
2479                 [
2480                     DW_TAG_subrange_type,   DW_CHILDREN_no,
2481                     DW_AT_type,             DW_FORM_ref4,
2482                     0,                      0,
2483                 ];
2484                 uint code2 = (t.Tflags & TFsizeunknown)
2485                     ? dwarf_abbrev_code(abbrevTypeSubrange2.ptr, (abbrevTypeSubrange2).sizeof)
2486                     : dwarf_abbrev_code(abbrevTypeSubrange.ptr, (abbrevTypeSubrange).sizeof);
2487                 uint idxbase = dwarf_typidx(tssize);
2488                 nextidx = dwarf_typidx(t.Tnext);
2489                 uint code1 = nextidx ? dwarf_abbrev_code(abbrevTypeArray.ptr, (abbrevTypeArray).sizeof)
2490                                      : dwarf_abbrev_code(abbrevTypeArrayVoid.ptr, (abbrevTypeArrayVoid).sizeof);
2491                 idx = cast(uint)debug_info.buf.length();
2492 
2493                 debug_info.buf.writeuLEB128(code1);       // DW_TAG_array_type
2494                 if (nextidx)
2495                     debug_info.buf.write32(nextidx);      // DW_AT_type
2496 
2497                 debug_info.buf.writeuLEB128(code2);       // DW_TAG_subrange_type
2498                 debug_info.buf.write32(idxbase);          // DW_AT_type
2499                 if (!(t.Tflags & TFsizeunknown))
2500                     debug_info.buf.write32(t.Tdim ? cast(uint)t.Tdim - 1 : 0);    // DW_AT_upper_bound
2501 
2502                 debug_info.buf.writeByte(0);              // no more children
2503                 break;
2504             }
2505 
2506             // SIMD vector types
2507             case TYfloat16:
2508             case TYfloat8:
2509             case TYfloat4:   tbase = tstypes[TYfloat];  goto Lvector;
2510             case TYdouble8:
2511             case TYdouble4:
2512             case TYdouble2:  tbase = tstypes[TYdouble]; goto Lvector;
2513             case TYschar64:
2514             case TYschar32:
2515             case TYschar16:  tbase = tstypes[TYschar];  goto Lvector;
2516             case TYuchar64:
2517             case TYuchar32:
2518             case TYuchar16:  tbase = tstypes[TYuchar];  goto Lvector;
2519             case TYshort32:
2520             case TYshort16:
2521             case TYshort8:   tbase = tstypes[TYshort];  goto Lvector;
2522             case TYushort32:
2523             case TYushort16:
2524             case TYushort8:  tbase = tstypes[TYushort]; goto Lvector;
2525             case TYlong16:
2526             case TYlong8:
2527             case TYlong4:    tbase = tstypes[TYlong];   goto Lvector;
2528             case TYulong16:
2529             case TYulong8:
2530             case TYulong4:   tbase = tstypes[TYulong];  goto Lvector;
2531             case TYllong8:
2532             case TYllong4:
2533             case TYllong2:   tbase = tstypes[TYllong];  goto Lvector;
2534             case TYullong8:
2535             case TYullong4:
2536             case TYullong2:  tbase = tstypes[TYullong]; goto Lvector;
2537             Lvector:
2538             {
2539                 static immutable ubyte[9] abbrevTypeArray2 =
2540                 [
2541                     DW_TAG_array_type,      DW_CHILDREN_yes,    // child (the subrange type)
2542                     (DW_AT_GNU_vector & 0x7F) | 0x80, DW_AT_GNU_vector >> 7,
2543                     DW_FORM_flag,
2544                     DW_AT_type,             DW_FORM_ref4,
2545                     0,                      0,
2546                 ];
2547                 static immutable ubyte[6] abbrevSubRange =
2548                 [
2549                     DW_TAG_subrange_type,   DW_CHILDREN_no,
2550                     DW_AT_upper_bound,      DW_FORM_data1,  // length of vector
2551                     0,                      0,
2552                 ];
2553 
2554                 uint code2 = dwarf_abbrev_code(abbrevTypeArray2.ptr, (abbrevTypeArray2).sizeof);
2555                 uint idxbase = dwarf_typidx(tbase);
2556 
2557                 idx = cast(uint)debug_info.buf.length();
2558 
2559                 debug_info.buf.writeuLEB128(code2);       // DW_TAG_array_type
2560                 debug_info.buf.writeByte(1);              // DW_AT_GNU_vector
2561                 debug_info.buf.write32(idxbase);          // DW_AT_type
2562 
2563                 // vector length stored as subrange type
2564                 code2 = dwarf_abbrev_code(abbrevSubRange.ptr, (abbrevSubRange).sizeof);
2565                 debug_info.buf.writeuLEB128(code2);       // DW_TAG_subrange_type
2566                 ubyte dim = cast(ubyte)(tysize(t.Tty) / tysize(tbase.Tty));
2567                 debug_info.buf.writeByte(dim - 1);        // DW_AT_upper_bound
2568 
2569                 debug_info.buf.writeByte(0);              // no more children
2570                 break;
2571             }
2572 
2573             case TYwchar_t:
2574             {
2575                 uint code3 = dwarf_abbrev_code(abbrevWchar.ptr, (abbrevWchar).sizeof);
2576                 uint typebase = dwarf_typidx(tstypes[TYint]);
2577                 idx = cast(uint)debug_info.buf.length();
2578                 debug_info.buf.writeuLEB128(code3);       // abbreviation code
2579                 debug_info.buf.writeString("wchar_t");    // DW_AT_name
2580                 debug_info.buf.write32(typebase);         // DW_AT_type
2581                 debug_info.buf.writeByte(1);              // DW_AT_decl_file
2582                 debug_info.buf.write16(1);                // DW_AT_decl_line
2583                 typidx_tab[ty] = idx;
2584                 break;
2585             }
2586 
2587 
2588             case TYstruct:
2589             {
2590                 Classsym *s = t.Ttag;
2591                 struct_t *st = s.Sstruct;
2592 
2593                 if (s.Stypidx)
2594                     return s.Stypidx;
2595 
2596                 __gshared ubyte[8] abbrevTypeStruct0 =
2597                 [
2598                     DW_TAG_structure_type,  DW_CHILDREN_no,
2599                     DW_AT_name,             DW_FORM_string,
2600                     DW_AT_byte_size,        DW_FORM_data1,
2601                     0,                      0,
2602                 ];
2603                 __gshared ubyte[8] abbrevTypeStruct1 =
2604                 [
2605                     DW_TAG_structure_type,  DW_CHILDREN_no,
2606                     DW_AT_name,             DW_FORM_string,
2607                     DW_AT_declaration,      DW_FORM_flag,
2608                     0,                      0,
2609                 ];
2610 
2611                 if (t.Tflags & (TFsizeunknown | TFforward))
2612                 {
2613                     abbrevTypeStruct1[0] = dwarf_classify_struct(st.Sflags);
2614                     code = dwarf_abbrev_code(abbrevTypeStruct1.ptr, (abbrevTypeStruct1).sizeof);
2615                     idx = cast(uint)debug_info.buf.length();
2616                     debug_info.buf.writeuLEB128(code);
2617                     debug_info.buf.writeString(getSymName(s));    // DW_AT_name
2618                     debug_info.buf.writeByte(1);                  // DW_AT_declaration
2619                     break;                  // don't set Stypidx
2620                 }
2621 
2622                 Outbuffer fieldidx;
2623 
2624                 // Count number of fields
2625                 uint nfields = 0;
2626                 t.Tflags |= TFforward;
2627                 foreach (sl; ListRange(st.Sfldlst))
2628                 {
2629                     Symbol *sf = list_symbol(sl);
2630                     switch (sf.Sclass)
2631                     {
2632                         case SCmember:
2633                             fieldidx.write32(dwarf_typidx(sf.Stype));
2634                             nfields++;
2635                             break;
2636 
2637                         default:
2638                             break;
2639                     }
2640                 }
2641                 t.Tflags &= ~TFforward;
2642                 if (nfields == 0)
2643                 {
2644                     abbrevTypeStruct0[0] = dwarf_classify_struct(st.Sflags);
2645                     abbrevTypeStruct0[1] = DW_CHILDREN_no;
2646                     abbrevTypeStruct0[5] = DW_FORM_data1;   // DW_AT_byte_size
2647                     code = dwarf_abbrev_code(abbrevTypeStruct0.ptr, (abbrevTypeStruct0).sizeof);
2648                     idx = cast(uint)debug_info.buf.length();
2649                     debug_info.buf.writeuLEB128(code);
2650                     debug_info.buf.writeString(getSymName(s));    // DW_AT_name
2651                     debug_info.buf.writeByte(0);                  // DW_AT_byte_size
2652                 }
2653                 else
2654                 {
2655                     Outbuffer abuf;         // for abbrev
2656                     abuf.writeByte(dwarf_classify_struct(st.Sflags));
2657                     abuf.writeByte(DW_CHILDREN_yes);
2658                     abuf.writeByte(DW_AT_name);     abuf.writeByte(DW_FORM_string);
2659                     abuf.writeByte(DW_AT_byte_size);
2660 
2661                     size_t sz = cast(uint)st.Sstructsize;
2662                     if (sz <= 0xFF)
2663                         abuf.writeByte(DW_FORM_data1);      // DW_AT_byte_size
2664                     else if (sz <= 0xFFFF)
2665                         abuf.writeByte(DW_FORM_data2);      // DW_AT_byte_size
2666                     else
2667                         abuf.writeByte(DW_FORM_data4);      // DW_AT_byte_size
2668                     abuf.writeByte(0);              abuf.writeByte(0);
2669 
2670                     code = dwarf_abbrev_code(abuf.buf, abuf.length());
2671 
2672                     uint membercode;
2673                     abuf.reset();
2674                     abuf.writeByte(DW_TAG_member);
2675                     abuf.writeByte(DW_CHILDREN_no);
2676                     abuf.writeByte(DW_AT_name);
2677                     abuf.writeByte(DW_FORM_string);
2678                     abuf.writeByte(DW_AT_type);
2679                     abuf.writeByte(DW_FORM_ref4);
2680                     abuf.writeByte(DW_AT_data_member_location);
2681                     abuf.writeByte(DW_FORM_block1);
2682                     abuf.writeByte(0);
2683                     abuf.writeByte(0);
2684                     membercode = dwarf_abbrev_code(abuf.buf, abuf.length());
2685 
2686                     idx = cast(uint)debug_info.buf.length();
2687                     debug_info.buf.writeuLEB128(code);
2688                     debug_info.buf.writeString(getSymName(s));      // DW_AT_name
2689                     if (sz <= 0xFF)
2690                         debug_info.buf.writeByte(cast(uint)sz);     // DW_AT_byte_size
2691                     else if (sz <= 0xFFFF)
2692                         debug_info.buf.write16(cast(uint)sz);     // DW_AT_byte_size
2693                     else
2694                         debug_info.buf.write32(cast(uint)sz);       // DW_AT_byte_size
2695 
2696                     s.Stypidx = idx;
2697                     uint n = 0;
2698                     foreach (sl; ListRange(st.Sfldlst))
2699                     {
2700                         Symbol *sf = list_symbol(sl);
2701                         size_t soffset;
2702 
2703                         switch (sf.Sclass)
2704                         {
2705                             case SCmember:
2706                                 debug_info.buf.writeuLEB128(membercode);
2707                                 debug_info.buf.writeString(getSymName(sf));      // DW_AT_name
2708                                 //debug_info.buf.write32(dwarf_typidx(sf.Stype));
2709                                 uint fi = (cast(uint *)fieldidx.buf)[n];
2710                                 debug_info.buf.write32(fi);
2711                                 n++;
2712                                 soffset = debug_info.buf.length();
2713                                 debug_info.buf.writeByte(2);
2714                                 debug_info.buf.writeByte(DW_OP_plus_uconst);
2715                                 debug_info.buf.writeuLEB128(cast(uint)sf.Smemoff);
2716                                 debug_info.buf.buf[soffset] = cast(ubyte)(debug_info.buf.length() - soffset - 1);
2717                                 break;
2718 
2719                             default:
2720                                 break;
2721                         }
2722                     }
2723 
2724                     debug_info.buf.writeByte(0);          // no more children
2725                 }
2726                 s.Stypidx = idx;
2727                 resetSyms.push(s);
2728                 return idx;                 // no need to cache it
2729             }
2730 
2731             case TYenum:
2732             {
2733                 static immutable ubyte[8] abbrevTypeEnum =
2734                 [
2735                     DW_TAG_enumeration_type,DW_CHILDREN_yes,    // child (the subrange type)
2736                     DW_AT_name,             DW_FORM_string,
2737                     DW_AT_byte_size,        DW_FORM_data1,
2738                     0,                      0,
2739                 ];
2740                 static immutable ubyte[8] abbrevTypeEnumMember =
2741                 [
2742                     DW_TAG_enumerator,      DW_CHILDREN_no,
2743                     DW_AT_name,             DW_FORM_string,
2744                     DW_AT_const_value,      DW_FORM_data1,
2745                     0,                      0,
2746                 ];
2747 
2748                 Symbol *s = t.Ttag;
2749                 enum_t *se = s.Senum;
2750                 type *tbase2 = s.Stype.Tnext;
2751                 uint sz = cast(uint)type_size(tbase2);
2752                 symlist_t sl;
2753 
2754                 if (s.Stypidx)
2755                     return s.Stypidx;
2756 
2757                 if (se.SEflags & SENforward)
2758                 {
2759                     static immutable ubyte[8] abbrevTypeEnumForward =
2760                     [
2761                         DW_TAG_enumeration_type,    DW_CHILDREN_no,
2762                         DW_AT_name,                 DW_FORM_string,
2763                         DW_AT_declaration,          DW_FORM_flag,
2764                         0,                          0,
2765                     ];
2766                     code = dwarf_abbrev_code(abbrevTypeEnumForward.ptr, abbrevTypeEnumForward.sizeof);
2767                     idx = cast(uint)debug_info.buf.length();
2768                     debug_info.buf.writeuLEB128(code);
2769                     debug_info.buf.writeString(getSymName(s));    // DW_AT_name
2770                     debug_info.buf.writeByte(1);                  // DW_AT_declaration
2771                     break;                  // don't set Stypidx
2772                 }
2773 
2774                 Outbuffer abuf;             // for abbrev
2775                 abuf.write(abbrevTypeEnum.ptr, abbrevTypeEnum.sizeof);
2776                 code = dwarf_abbrev_code(abuf.buf, abuf.length());
2777 
2778                 uint membercode;
2779                 abuf.reset();
2780                 abuf.writeByte(DW_TAG_enumerator);
2781                 abuf.writeByte(DW_CHILDREN_no);
2782                 abuf.writeByte(DW_AT_name);
2783                 abuf.writeByte(DW_FORM_string);
2784                 abuf.writeByte(DW_AT_const_value);
2785                 if (tyuns(tbase2.Tty))
2786                     abuf.writeByte(DW_FORM_udata);
2787                 else
2788                     abuf.writeByte(DW_FORM_sdata);
2789                 abuf.writeByte(0);
2790                 abuf.writeByte(0);
2791                 membercode = dwarf_abbrev_code(abuf.buf, abuf.length());
2792 
2793                 idx = cast(uint)debug_info.buf.length();
2794                 debug_info.buf.writeuLEB128(code);
2795                 debug_info.buf.writeString(getSymName(s));// DW_AT_name
2796                 debug_info.buf.writeByte(sz);             // DW_AT_byte_size
2797 
2798                 foreach (sl2; ListRange(s.Senum.SEenumlist))
2799                 {
2800                     Symbol *sf = cast(Symbol *)list_ptr(sl2);
2801                     const value = cast(uint)el_tolongt(sf.Svalue);
2802 
2803                     debug_info.buf.writeuLEB128(membercode);
2804                     debug_info.buf.writeString(getSymName(sf)); // DW_AT_name
2805                     if (tyuns(tbase2.Tty))
2806                         debug_info.buf.writeuLEB128(value);
2807                     else
2808                         debug_info.buf.writesLEB128(value);
2809                 }
2810 
2811                 debug_info.buf.writeByte(0);              // no more children
2812 
2813                 s.Stypidx = idx;
2814                 resetSyms.push(s);
2815                 return idx;                 // no need to cache it
2816             }
2817 
2818             default:
2819                 return 0;
2820         }
2821     Lret:
2822         /* If debug_info.buf.buf[idx .. length()] is already in debug_info.buf,
2823          * discard this one and use the previous one.
2824          */
2825         if (!type_table)
2826             /* uint[Adata] type_table;
2827              * where the table values are the type indices
2828              */
2829             type_table = AApair.create(&debug_info.buf.buf);
2830 
2831         uint *pidx = type_table.get(idx, cast(uint)debug_info.buf.length());
2832         if (!*pidx)                 // if no idx assigned yet
2833         {
2834             *pidx = idx;            // assign newly computed idx
2835         }
2836         else
2837         {   // Reuse existing code
2838             debug_info.buf.setsize(idx);  // discard current
2839             idx = *pidx;
2840         }
2841         return idx;
2842     }
2843 
2844     /**
2845      *  Returns a pretty identifier name from `sym`.
2846      *
2847      *  Params:
2848      *      sym = the symbol which the name comes from
2849      *  Returns:
2850      *      The identifier name
2851      */
2852     const(char)* getSymName(Symbol* sym)
2853     {
2854         version (MARS)
2855             return sym.prettyIdent ? sym.prettyIdent : sym.Sident.ptr;
2856         else
2857             return sym.Sident.ptr;
2858     }
2859 
2860     /* ======================= Abbreviation Codes ====================== */
2861 
2862     extern(D) uint dwarf_abbrev_code(const(ubyte)[] data)
2863     {
2864         return dwarf_abbrev_code(data.ptr, data.length);
2865     }
2866 
2867     uint dwarf_abbrev_code(const(ubyte)* data, size_t nbytes)
2868     {
2869         if (!abbrev_table)
2870             /* uint[Adata] abbrev_table;
2871              * where the table values are the abbreviation codes.
2872              */
2873             abbrev_table = AApair.create(&debug_abbrev.buf.buf);
2874 
2875         /* Write new entry into debug_abbrev.buf
2876          */
2877 
2878         uint idx = cast(uint)debug_abbrev.buf.length();
2879         abbrevcode++;
2880         debug_abbrev.buf.writeuLEB128(abbrevcode);
2881         size_t start = debug_abbrev.buf.length();
2882         debug_abbrev.buf.write(data, cast(uint)nbytes);
2883         size_t end = debug_abbrev.buf.length();
2884 
2885         /* If debug_abbrev.buf.buf[idx .. length()] is already in debug_abbrev.buf,
2886          * discard this one and use the previous one.
2887          */
2888 
2889         uint *pcode = abbrev_table.get(cast(uint)start, cast(uint)end);
2890         if (!*pcode)                // if no code assigned yet
2891         {
2892             *pcode = abbrevcode;    // assign newly computed code
2893         }
2894         else
2895         {   // Reuse existing code
2896             debug_abbrev.buf.setsize(idx);        // discard current
2897             abbrevcode--;
2898         }
2899         return *pcode;
2900     }
2901 
2902     /*****************************************************
2903      * Write Dwarf-style exception tables.
2904      * Params:
2905      *      sfunc = function to generate tables for
2906      *      startoffset = size of function prolog
2907      *      retoffset = offset from start of function to epilog
2908      */
2909     void dwarf_except_gentables(Funcsym *sfunc, uint startoffset, uint retoffset)
2910     {
2911         if (!doUnwindEhFrame())
2912             return;
2913 
2914         int seg = dwarf_except_table_alloc(sfunc);
2915         Outbuffer *buf = SegData[seg].SDbuf;
2916         buf.reserve(100);
2917 
2918         static if (ELFOBJ)
2919             sfunc.Sfunc.LSDAoffset = cast(uint)buf.length();
2920 
2921         static if (MACHOBJ)
2922         {
2923             char[16 + (except_table_num).sizeof * 3 + 1] name = void;
2924             sprintf(name.ptr, "GCC_except_table%d", ++except_table_num);
2925             type *t = tspvoid;
2926             t.Tcount++;
2927             type_setmangle(&t, mTYman_sys);         // no leading '_' for mangled name
2928             Symbol *s = symbol_name(name.ptr, SCstatic, t);
2929             Obj.pubdef(seg, s, cast(uint)buf.length());
2930             symbol_keep(s);
2931 
2932             sfunc.Sfunc.LSDAsym = s;
2933         }
2934         genDwarfEh(sfunc, seg, buf, (usednteh & EHcleanup) != 0, startoffset, retoffset);
2935     }
2936 
2937 }
2938 else
2939 {
2940     extern (C++):
2941 
2942     void dwarf_CFA_set_loc(uint location) { }
2943     void dwarf_CFA_set_reg_offset(int reg, int offset) { }
2944     void dwarf_CFA_offset(int reg, int offset) { }
2945     void dwarf_except_gentables(Funcsym *sfunc, uint startoffset, uint retoffset) { }
2946 }