1 /** 2 * Compiler implementation of the 3 * $(LINK2 https://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (C) 1994-1998 by Symantec 6 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/obj.d, backend/obj.d) 10 */ 11 12 module dmd.backend.obj; 13 14 // Online documentation: https://dlang.org/phobos/dmd_backend_obj.html 15 16 /* Interface to object file format 17 */ 18 19 import dmd.backend.cdef; 20 import dmd.backend.cc; 21 import dmd.backend.code; 22 import dmd.backend.el; 23 24 import dmd.common.outbuffer; 25 26 nothrow: 27 28 version (Windows) 29 { 30 } 31 else version (Posix) 32 { 33 } 34 else 35 static assert(0, "unsupported version"); 36 37 /******************************************************************/ 38 39 import dmd.backend.cgobj; 40 import dmd.backend.mscoffobj; 41 import dmd.backend.elfobj; 42 import dmd.backend.machobj; 43 44 /******************************************************************/ 45 46 version (STUB) 47 { 48 public import stubobj; 49 } 50 else 51 { 52 /******************************************* 53 * Generic interface to the four object module file formats supported. 54 * Instead of using virtual functions (i.e. virtual dispatch) it uses 55 * static dispatch. Since config.objfmt never changes after initialization 56 * of the compiler, static branch prediction should make it faster than 57 * virtual dispatch. 58 * 59 * Making static dispatch work requires tediously repetitive boilerplate, 60 * which we accomplish via string mixins. 61 */ 62 class Obj 63 { 64 static 65 { 66 nothrow: 67 68 Obj initialize(OutBuffer* objbuf, const(char)* filename, const(char)* csegname) 69 { 70 mixin(genRetVal("init(objbuf, filename, csegname)")); 71 } 72 73 void initfile(const(char)* filename, const(char)* csegname, const(char)* modname) 74 { 75 mixin(genRetVal("initfile(filename, csegname, modname)")); 76 } 77 78 void termfile() 79 { 80 mixin(genRetVal("termfile()")); 81 } 82 83 void term(const(char)* objfilename) 84 { 85 mixin(genRetVal("term(objfilename)")); 86 } 87 88 size_t mangle(Symbol *s,char *dest) 89 { 90 assert(config.objfmt == OBJ_OMF); 91 return OmfObj_mangle(s, dest); 92 } 93 94 void _import(elem *e) 95 { 96 assert(config.objfmt == OBJ_OMF); 97 return OmfObj_import(e); 98 } 99 100 void linnum(Srcpos srcpos, int seg, targ_size_t offset) 101 { 102 mixin(genRetVal("linnum(srcpos, seg, offset)")); 103 } 104 105 int codeseg(const char *name,int suffix) 106 { 107 mixin(genRetVal("codeseg(name, suffix)")); 108 } 109 110 void dosseg() 111 { 112 assert(config.objfmt == OBJ_OMF); 113 return OmfObj_dosseg(); 114 } 115 116 void startaddress(Symbol *s) 117 { 118 mixin(genRetVal("startaddress(s)")); 119 } 120 121 bool includelib(scope const(char)[] name) 122 { 123 mixin(genRetVal("includelib(name)")); 124 } 125 126 bool linkerdirective(const(char)* p) 127 { 128 mixin(genRetVal("linkerdirective(p)")); 129 } 130 131 bool allowZeroSize() 132 { 133 mixin(genRetVal("allowZeroSize()")); 134 } 135 136 void exestr(const(char)* p) 137 { 138 mixin(genRetVal("exestr(p)")); 139 } 140 141 void user(const(char)* p) 142 { 143 mixin(genRetVal("user(p)")); 144 } 145 146 void compiler(const(char)* p) 147 { 148 mixin(genRetVal("compiler(p)")); 149 } 150 151 void wkext(Symbol* s1, Symbol* s2) 152 { 153 mixin(genRetVal("wkext(s1, s2)")); 154 } 155 156 void lzext(Symbol* s1, Symbol* s2) 157 { 158 assert(config.objfmt == OBJ_OMF); 159 OmfObj_lzext(s1, s2); 160 } 161 162 void _alias(const(char)* n1,const(char)* n2) 163 { 164 mixin(genRetVal("alias(n1, n2)")); 165 } 166 167 void theadr(const(char)* modname) 168 { 169 assert(config.objfmt == OBJ_OMF); 170 OmfObj_theadr(modname); 171 } 172 173 void segment_group(targ_size_t codesize, targ_size_t datasize, targ_size_t cdatasize, targ_size_t udatasize) 174 { 175 assert(config.objfmt == OBJ_OMF); 176 OmfObj_segment_group(codesize, datasize, cdatasize, udatasize); 177 } 178 179 void staticctor(Symbol *s,int dtor,int seg) 180 { 181 mixin(genRetVal("staticctor(s, dtor, seg)")); 182 } 183 184 void staticdtor(Symbol *s) 185 { 186 mixin(genRetVal("staticdtor(s)")); 187 } 188 189 void setModuleCtorDtor(Symbol *s, bool isCtor) 190 { 191 mixin(genRetVal("setModuleCtorDtor(s, isCtor)")); 192 } 193 194 void ehtables(Symbol *sfunc,uint size,Symbol *ehsym) 195 { 196 mixin(genRetVal("ehtables(sfunc, size, ehsym)")); 197 } 198 199 void ehsections() 200 { 201 mixin(genRetVal("ehsections()")); 202 } 203 204 void moduleinfo(Symbol *scc) 205 { 206 mixin(genRetVal("moduleinfo(scc)")); 207 } 208 209 int comdat(Symbol *s) 210 { 211 mixin(genRetVal("comdat(s)")); 212 } 213 214 int comdatsize(Symbol *s, targ_size_t symsize) 215 { 216 mixin(genRetVal("comdatsize(s, symsize)")); 217 } 218 219 int readonly_comdat(Symbol *s) 220 { 221 mixin(genRetVal("comdat(s)")); 222 } 223 224 void setcodeseg(int seg) 225 { 226 mixin(genRetVal("setcodeseg(seg)")); 227 } 228 229 seg_data *tlsseg() 230 { 231 mixin(genRetVal("tlsseg()")); 232 } 233 234 seg_data *tlsseg_bss() 235 { 236 mixin(genRetVal("tlsseg_bss()")); 237 } 238 239 seg_data *tlsseg_data() 240 { 241 mixin(genRetVal("tlsseg_data()")); 242 } 243 244 int fardata(char *name, targ_size_t size, targ_size_t *poffset) 245 { 246 assert(config.objfmt == OBJ_OMF); 247 return OmfObj_fardata(name, size, poffset); 248 } 249 250 void export_symbol(Symbol *s, uint argsize) 251 { 252 mixin(genRetVal("export_symbol(s, argsize)")); 253 } 254 255 void pubdef(int seg, Symbol *s, targ_size_t offset) 256 { 257 mixin(genRetVal("pubdef(seg, s, offset)")); 258 } 259 260 void pubdefsize(int seg, Symbol *s, targ_size_t offset, targ_size_t symsize) 261 { 262 mixin(genRetVal("pubdefsize(seg, s, offset, symsize)")); 263 } 264 265 int external_def(const(char)* name) 266 { 267 mixin(genRetVal("external_def(name)")); 268 } 269 270 int data_start(Symbol *sdata, targ_size_t datasize, int seg) 271 { 272 mixin(genRetVal("data_start(sdata, datasize, seg)")); 273 } 274 275 int external(Symbol *s) 276 { 277 mixin(genRetVal("external(s)")); 278 } 279 280 int common_block(Symbol *s, targ_size_t size, targ_size_t count) 281 { 282 mixin(genRetVal("common_block(s, size, count)")); 283 } 284 285 int common_block(Symbol *s, int flag, targ_size_t size, targ_size_t count) 286 { 287 mixin(genRetVal("common_block(s, flag, size, count)")); 288 } 289 290 void lidata(int seg, targ_size_t offset, targ_size_t count) 291 { 292 mixin(genRetVal("lidata(seg, offset, count)")); 293 } 294 295 void write_zeros(seg_data *pseg, targ_size_t count) 296 { 297 mixin(genRetVal("write_zeros(pseg, count)")); 298 } 299 300 void write_byte(seg_data *pseg, uint _byte) 301 { 302 mixin(genRetVal("write_byte(pseg, _byte)")); 303 } 304 305 void write_bytes(seg_data *pseg, const(void[]) a) 306 { 307 mixin(genRetVal("write_bytes(pseg, a)")); 308 } 309 310 void _byte(int seg, targ_size_t offset, uint _byte) 311 { 312 mixin(genRetVal("byte(seg, offset, _byte)")); 313 } 314 315 size_t bytes(int seg, targ_size_t offset, size_t nbytes, const(void)* p) 316 { 317 mixin(genRetVal("bytes(seg, offset, nbytes, p)")); 318 } 319 320 void ledata(int seg, targ_size_t offset, targ_size_t data, uint lcfd, uint idx1, uint idx2) 321 { 322 assert(config.objfmt == OBJ_OMF); 323 OmfObj_ledata(seg, offset, data, lcfd, idx1, idx2); 324 } 325 326 void reftodatseg(int seg, targ_size_t offset, targ_size_t val, uint targetdatum, int flags) 327 { 328 mixin(genRetVal("reftodatseg(seg, offset, val, targetdatum, flags)")); 329 } 330 331 void reftofarseg(int seg, targ_size_t offset, targ_size_t val, int farseg, int flags) 332 { 333 assert(config.objfmt == OBJ_OMF); 334 OmfObj_reftofarseg(seg, offset, val, farseg, flags); 335 } 336 337 void reftocodeseg(int seg, targ_size_t offset, targ_size_t val) 338 { 339 mixin(genRetVal("reftocodeseg(seg, offset, val)")); 340 } 341 342 int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, int flags) 343 { 344 mixin(genRetVal("reftoident(seg, offset, s, val, flags)")); 345 } 346 347 void far16thunk(Symbol *s) 348 { 349 mixin(genRetVal("far16thunk(s)")); 350 } 351 352 void fltused() 353 { 354 mixin(genRetVal("fltused()")); 355 } 356 357 int data_readonly(char *p, int len, int *pseg) 358 { 359 mixin(genRetVal("data_readonly(p, len, pseg)")); 360 } 361 362 int data_readonly(char *p, int len) 363 { 364 mixin(genRetVal("data_readonly(p, len)")); 365 } 366 367 int string_literal_segment(uint sz) 368 { 369 mixin(genRetVal("string_literal_segment(sz)")); 370 } 371 372 Symbol *sym_cdata(tym_t ty, char *p, int len) 373 { 374 mixin(genRetVal("sym_cdata(ty, p, len)")); 375 } 376 377 void func_start(Symbol *sfunc) 378 { 379 mixin(genRetVal("func_start(sfunc)")); 380 } 381 382 void func_term(Symbol *sfunc) 383 { 384 mixin(genRetVal("func_term(sfunc)")); 385 } 386 387 void write_pointerRef(Symbol* s, uint off) 388 { 389 mixin(genRetVal("write_pointerRef(s, off)")); 390 } 391 392 int jmpTableSegment(Symbol* s) 393 { 394 mixin(genRetVal("jmpTableSegment(s)")); 395 } 396 397 Symbol *tlv_bootstrap() 398 { 399 mixin(genRetVal("tlv_bootstrap()")); 400 } 401 402 void gotref(Symbol *s) 403 { 404 switch (config.objfmt) 405 { 406 case OBJ_ELF: ElfObj_gotref(s); break; 407 case OBJ_MACH: MachObj_gotref(s); break; 408 default: assert(0); 409 } 410 } 411 412 Symbol *getGOTsym() 413 { 414 switch (config.objfmt) 415 { 416 case OBJ_ELF: return ElfObj_getGOTsym(); 417 case OBJ_MACH: return MachObj_getGOTsym(); 418 default: assert(0); 419 } 420 } 421 422 void refGOTsym() 423 { 424 switch (config.objfmt) 425 { 426 case OBJ_ELF: ElfObj_refGOTsym(); break; 427 case OBJ_MACH: MachObj_refGOTsym(); break; 428 default: assert(0); 429 } 430 } 431 432 int seg_debugT() // where the symbolic debug type data goes 433 { 434 switch (config.objfmt) 435 { 436 case OBJ_MSCOFF: return MsCoffObj_seg_debugT(); 437 case OBJ_OMF: return OmfObj_seg_debugT(); 438 default: assert(0); 439 } 440 } 441 442 void write_long(int seg, targ_size_t offset, uint data, uint lcfd, uint idx1, uint idx2) 443 { 444 assert(config.objfmt == OBJ_OMF); 445 return OmfObj_write_long(seg, offset, data, lcfd, idx1, idx2); 446 } 447 448 uint addstr(OutBuffer *strtab, const(char)* p) 449 { 450 switch (config.objfmt) 451 { 452 case OBJ_ELF: return ElfObj_addstr(strtab, p); 453 case OBJ_MACH: return MachObj_addstr(strtab, p); 454 default: assert(0); 455 } 456 } 457 458 int getsegment(const(char)* sectname, const(char)* segname, int align_, int flags) 459 { 460 assert(config.objfmt == OBJ_MACH); 461 return MachObj_getsegment(sectname, segname, align_, flags); 462 } 463 464 int getsegment(const(char)* name, const(char)* suffix, int type, int flags, int align_) 465 { 466 assert(config.objfmt == OBJ_ELF); 467 return ElfObj_getsegment(name, suffix, type, flags, align_); 468 } 469 470 int getsegment(const(char)* sectname, uint flags) 471 { 472 assert(config.objfmt == OBJ_MSCOFF); 473 return MsCoffObj_getsegment(sectname, flags); 474 } 475 476 void addrel(int seg, targ_size_t offset, Symbol *targsym, uint targseg, int rtype, int val = 0) 477 { 478 switch (config.objfmt) 479 { 480 case OBJ_MSCOFF: return MsCoffObj_addrel(seg, offset, targsym, targseg, rtype, val); 481 case OBJ_MACH: return MachObj_addrel(seg, offset, targsym, targseg, rtype, val); 482 default: assert(0); 483 } 484 } 485 486 void addrel(int seg, targ_size_t offset, uint type, uint symidx, targ_size_t val) 487 { 488 assert(config.objfmt == OBJ_ELF); 489 return ElfObj_addrel(seg, offset, type, symidx, val); 490 } 491 492 size_t writerel(int targseg, size_t offset, uint type, uint symidx, targ_size_t val) 493 { 494 assert(config.objfmt == OBJ_ELF); 495 return ElfObj_writerel(targseg, offset, type, symidx, val); 496 } 497 498 int getsegment2(uint shtidx) 499 { 500 assert(config.objfmt == OBJ_MSCOFF); 501 return MsCoffObj_getsegment2(shtidx); 502 } 503 504 uint addScnhdr(const(char)* scnhdr_name, uint flags) 505 { 506 assert(config.objfmt == OBJ_MSCOFF); 507 return MsCoffObj_addScnhdr(scnhdr_name, flags); 508 } 509 510 int seg_drectve() 511 { 512 assert(config.objfmt == OBJ_MSCOFF); 513 return MsCoffObj_seg_drectve(); 514 } 515 516 int seg_pdata() 517 { 518 assert(config.objfmt == OBJ_MSCOFF); 519 return MsCoffObj_seg_pdata(); 520 } 521 522 int seg_xdata() 523 { 524 assert(config.objfmt == OBJ_MSCOFF); 525 return MsCoffObj_seg_xdata(); 526 } 527 528 int seg_pdata_comdat(Symbol *sfunc) 529 { 530 assert(config.objfmt == OBJ_MSCOFF); 531 return MsCoffObj_seg_pdata_comdat(sfunc); 532 } 533 534 int seg_xdata_comdat(Symbol *sfunc) 535 { 536 assert(config.objfmt == OBJ_MSCOFF); 537 return MsCoffObj_seg_xdata_comdat(sfunc); 538 } 539 540 int seg_debugS() 541 { 542 assert(config.objfmt == OBJ_MSCOFF); 543 return MsCoffObj_seg_debugS(); 544 } 545 546 int seg_debugS_comdat(Symbol *sfunc) 547 { 548 assert(config.objfmt == OBJ_MSCOFF); 549 return MsCoffObj_seg_debugS_comdat(sfunc); 550 } 551 } 552 } 553 } 554 555 public import dmd.backend.var : objmod; 556 557 /***************************************** 558 * Use to generate 4 function declarations, one for 559 * each object file format supported. 560 * Params: 561 * pattern = function declaration 562 * Returns: 563 * declarations as a string suitable for mixin 564 */ 565 private extern (D) 566 string ObjMemDecl(string pattern) 567 { 568 string r = 569 gen(pattern, "Omf") ~ ";\n" ~ 570 gen(pattern, "MsCoff") ~ ";\n" ~ 571 gen(pattern, "Elf") ~ ";\n" ~ 572 gen(pattern, "Mach") ~ ";\n"; 573 return r; 574 } 575 576 /**************************************** 577 * Generate boilerplate for static dispatch that 578 * returns a value. Don't care about type of the value. 579 * Params: 580 * arg = function name to be dispatched based on `objfmt` 581 * Returns: 582 * mixin string with static dispatch 583 */ 584 private extern (D) 585 string genRetVal(string arg) 586 { 587 return 588 " 589 switch (config.objfmt) 590 { 591 case OBJ_ELF: return ElfObj_"~arg~"; 592 case OBJ_MSCOFF: return MsCoffObj_"~arg~"; 593 case OBJ_OMF: return OmfObj_"~arg~"; 594 case OBJ_MACH: return MachObj_"~arg~"; 595 default: assert(0); 596 } 597 "; 598 } 599 600 /**************************************** 601 * Generate boilerplate that replaces the single '$' in `pattern` with `arg` 602 * Params: 603 * pattern = pattern to scan for '$' 604 * arg = string to insert where '$' is found 605 * Returns: 606 * boilerplate string 607 */ 608 private extern (D) 609 string gen(string pattern, string arg) 610 { 611 foreach (i; 0 .. pattern.length) 612 if (pattern[i] == '$') 613 return pattern[0 .. i] ~ arg ~ pattern[i + 1 .. $]; 614 assert(0); 615 }