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