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