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 }