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