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