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