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 extern (C++): 27 28 nothrow: 29 30 version (HTOD) 31 version = STUB; 32 else version (Windows) 33 { 34 } 35 else version (Posix) 36 { 37 } 38 else 39 static assert(0, "unsupported version"); 40 41 /******************************************************************/ 42 43 /* Functions common to all object formats 44 */ 45 mixin(ObjMemDecl("Obj $Obj_init(OutBuffer *, const(char)* filename, const(char)* csegname)")); 46 mixin(ObjMemDecl("void $Obj_initfile(const(char)* filename, const(char)* csegname, const(char)* modname)")); 47 mixin(ObjMemDecl("void $Obj_termfile()")); 48 mixin(ObjMemDecl("void $Obj_term(const(char)* objfilename)")); 49 mixin(ObjMemDecl("void $Obj_linnum(Srcpos srcpos, int seg, targ_size_t offset)")); 50 mixin(ObjMemDecl("int $Obj_codeseg(const char *name,int suffix)")); 51 mixin(ObjMemDecl("void $Obj_startaddress(Symbol *)")); 52 mixin(ObjMemDecl("bool $Obj_includelib(const(char)* )")); 53 mixin(ObjMemDecl("bool $Obj_linkerdirective(const(char)* )")); 54 mixin(ObjMemDecl("bool $Obj_allowZeroSize()")); 55 mixin(ObjMemDecl("void $Obj_exestr(const(char)* p)")); 56 mixin(ObjMemDecl("void $Obj_user(const(char)* p)")); 57 mixin(ObjMemDecl("void $Obj_compiler()")); 58 mixin(ObjMemDecl("void $Obj_wkext(Symbol *,Symbol *)")); 59 mixin(ObjMemDecl("void $Obj_alias(const(char)* n1,const(char)* n2)")); 60 mixin(ObjMemDecl("void $Obj_staticctor(Symbol *s,int dtor,int seg)")); 61 mixin(ObjMemDecl("void $Obj_staticdtor(Symbol *s)")); 62 mixin(ObjMemDecl("void $Obj_setModuleCtorDtor(Symbol *s, bool isCtor)")); 63 mixin(ObjMemDecl("void $Obj_ehtables(Symbol *sfunc,uint size,Symbol *ehsym)")); 64 mixin(ObjMemDecl("void $Obj_ehsections()")); 65 mixin(ObjMemDecl("void $Obj_moduleinfo(Symbol *scc)")); 66 mixin(ObjMemDecl("int $Obj_comdat(Symbol *)")); 67 mixin(ObjMemDecl("int $Obj_comdatsize(Symbol *, targ_size_t symsize)")); 68 mixin(ObjMemDecl("int $Obj_readonly_comdat(Symbol *s)")); 69 mixin(ObjMemDecl("void $Obj_setcodeseg(int seg)")); 70 mixin(ObjMemDecl("seg_data* $Obj_tlsseg()")); 71 mixin(ObjMemDecl("seg_data* $Obj_tlsseg_bss()")); 72 mixin(ObjMemDecl("seg_data* $Obj_tlsseg_data()")); 73 mixin(ObjMemDecl("void $Obj_export_symbol(Symbol *s, uint argsize)")); 74 mixin(ObjMemDecl("void $Obj_pubdef(int seg, Symbol *s, targ_size_t offset)")); 75 mixin(ObjMemDecl("void $Obj_pubdefsize(int seg, Symbol *s, targ_size_t offset, targ_size_t symsize)")); 76 mixin(ObjMemDecl("int $Obj_external_def(const(char)*)")); 77 mixin(ObjMemDecl("int $Obj_data_start(Symbol *sdata, targ_size_t datasize, int seg)")); 78 mixin(ObjMemDecl("int $Obj_external(Symbol *)")); 79 mixin(ObjMemDecl("int $Obj_common_block(Symbol *s, targ_size_t size, targ_size_t count)")); 80 mixin(ObjMemDecl("int $Obj_common_block(Symbol *s, int flag, targ_size_t size, targ_size_t count)")); 81 mixin(ObjMemDecl("void $Obj_lidata(int seg, targ_size_t offset, targ_size_t count)")); 82 mixin(ObjMemDecl("void $Obj_write_zeros(seg_data *pseg, targ_size_t count)")); 83 mixin(ObjMemDecl("void $Obj_write_byte(seg_data *pseg, uint _byte)")); 84 mixin(ObjMemDecl("void $Obj_write_bytes(seg_data *pseg, uint nbytes, void *p)")); 85 mixin(ObjMemDecl("void $Obj_byte(int seg, targ_size_t offset, uint _byte)")); 86 mixin(ObjMemDecl("uint $Obj_bytes(int seg, targ_size_t offset, uint nbytes, void *p)")); 87 mixin(ObjMemDecl("void $Obj_reftodatseg(int seg, targ_size_t offset, targ_size_t val, uint targetdatum, int flags)")); 88 mixin(ObjMemDecl("void $Obj_reftocodeseg(int seg, targ_size_t offset, targ_size_t val)")); 89 mixin(ObjMemDecl("int $Obj_reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, int flags)")); 90 mixin(ObjMemDecl("void $Obj_far16thunk(Symbol *s)")); 91 mixin(ObjMemDecl("void $Obj_fltused()")); 92 mixin(ObjMemDecl("int $Obj_data_readonly(char *p, int len, int *pseg)")); 93 mixin(ObjMemDecl("int $Obj_data_readonly(char *p, int len)")); 94 mixin(ObjMemDecl("int $Obj_string_literal_segment(uint sz)")); 95 mixin(ObjMemDecl("Symbol* $Obj_sym_cdata(tym_t, char *, int)")); 96 mixin(ObjMemDecl("void $Obj_func_start(Symbol *sfunc)")); 97 mixin(ObjMemDecl("void $Obj_func_term(Symbol *sfunc)")); 98 mixin(ObjMemDecl("void $Obj_write_pointerRef(Symbol* s, uint off)")); 99 mixin(ObjMemDecl("int $Obj_jmpTableSegment(Symbol* s)")); 100 mixin(ObjMemDecl("Symbol* $Obj_tlv_bootstrap()")); 101 102 /******************************************************************/ 103 104 size_t OmfObj_mangle(Symbol *s,char *dest); 105 void OmfObj_import(elem *e); 106 void OmfObj_dosseg(); 107 void OmfObj_lzext(Symbol *,Symbol *); 108 void OmfObj_theadr(const(char)* modname); 109 void OmfObj_segment_group(targ_size_t codesize, targ_size_t datasize, targ_size_t cdatasize, targ_size_t udatasize); 110 int OmfObj_fardata(char *name, targ_size_t size, targ_size_t *poffset); 111 void OmfObj_ledata(int seg, targ_size_t offset, targ_size_t data, uint lcfd, uint idx1, uint idx2); 112 void OmfObj_write_long(int seg, targ_size_t offset, uint data, uint lcfd, uint idx1, uint idx2); 113 void OmfObj_reftofarseg(int seg, targ_size_t offset, targ_size_t val, int farseg, int flags); 114 int OmfObj_seg_debugT(); // where the symbolic debug type data goes 115 116 /******************************************************************/ 117 118 int MsCoffObj_getsegment(const(char)* sectname, uint flags); 119 int MsCoffObj_getsegment2(uint shtidx); 120 uint MsCoffObj_addScnhdr(const(char)* scnhdr_name, uint flags); 121 void MsCoffObj_addrel(int seg, targ_size_t offset, Symbol *targsym, uint targseg, int rtype, int val); 122 int MsCoffObj_seg_drectve(); 123 int MsCoffObj_seg_pdata(); 124 int MsCoffObj_seg_xdata(); 125 int MsCoffObj_seg_pdata_comdat(Symbol *sfunc); 126 int MsCoffObj_seg_xdata_comdat(Symbol *sfunc); 127 int MsCoffObj_seg_debugS(); 128 int MsCoffObj_seg_debugS_comdat(Symbol *sfunc); 129 int MsCoffObj_seg_debugT(); // where the symbolic debug type data goes 130 131 /******************************************************************/ 132 133 void ElfObj_dosseg(); 134 size_t ElfObj_mangle(Symbol* s, char* dest); 135 void ElfObj_import(elem* e); 136 void ElfObj_lzext(Symbol*, Symbol*); 137 void ElfObj_theadr(const(char)* modname); 138 void ElfObj_segment_group(targ_size_t codesize, targ_size_t datasize, targ_size_t cdatasize, targ_size_t udatasize); 139 int ElfObj_fardata(char *name, targ_size_t size, targ_size_t* poffset); 140 void ElfObj_ledata(int seg, targ_size_t offset, targ_size_t data, uint lcfd, uint idx1, uint idx2); 141 void ElfObj_reftofarseg(int seg, targ_size_t offset, targ_size_t val, int farseg, int flags); 142 void ElfObj_gotref(Symbol* s); 143 uint ElfObj_addstr(OutBuffer* strtab, const(char)*); 144 Symbol* ElfObj_getGOTsym(); 145 void ElfObj_refGOTsym(); 146 int ElfObj_getsegment(const(char)* sectname, const(char)* suffix, int type, int flags, int align_); 147 void ElfObj_addrel(int seg, targ_size_t offset, uint type, uint symidx, targ_size_t val); 148 size_t ElfObj_writerel(int targseg, size_t offset, uint type, uint symidx, targ_size_t val); 149 150 /******************************************************************/ 151 152 void MachObj_dosseg(); 153 size_t MachObj_mangle(Symbol *s,char *dest); 154 void MachObj_import(elem *e); 155 void MachObj_lzext(Symbol *,Symbol *); 156 void MachObj_theadr(const(char)* modname); 157 void MachObj_segment_group(targ_size_t codesize, targ_size_t datasize, targ_size_t cdatasize, targ_size_t udatasize); 158 int MachObj_fardata(char *name, targ_size_t size, targ_size_t *poffset); 159 void MachObj_ledata(int seg, targ_size_t offset, targ_size_t data, uint lcfd, uint idx1, uint idx2); 160 void MachObj_reftofarseg(int seg, targ_size_t offset, targ_size_t val, int farseg, int flags); 161 void MachObj_gotref(Symbol *s); 162 uint MachObj_addstr(OutBuffer *strtab, const(char)* ); 163 Symbol* MachObj_getGOTsym(); 164 void MachObj_refGOTsym(); 165 int MachObj_getsegment(const(char)* sectname, const(char)* segname, int align_, int flags); 166 void MachObj_addrel(int seg, targ_size_t offset, Symbol* targsym, uint targseg, int rtype, int val); 167 168 /******************************************************************/ 169 170 version (STUB) 171 { 172 public import stubobj; 173 } 174 else 175 { 176 /******************************************* 177 * Generic interface to the four object module file formats supported. 178 * Instead of using virtual functions (i.e. virtual dispatch) it uses 179 * static dispatch. Since config.objfmt never changes after initialization 180 * of the compiler, static branch prediction should make it faster than 181 * virtual dispatch. 182 * 183 * Making static dispatch work requires tediously repetitive boilerplate, 184 * which we accomplish via string mixins. 185 */ 186 class Obj 187 { 188 static 189 { 190 nothrow: 191 192 Obj initialize(OutBuffer* objbuf, const(char)* filename, const(char)* csegname) 193 { 194 mixin(genRetVal("init(objbuf, filename, csegname)")); 195 } 196 197 void initfile(const(char)* filename, const(char)* csegname, const(char)* modname) 198 { 199 mixin(genRetVal("initfile(filename, csegname, modname)")); 200 } 201 202 void termfile() 203 { 204 mixin(genRetVal("termfile()")); 205 } 206 207 void term(const(char)* objfilename) 208 { 209 mixin(genRetVal("term(objfilename)")); 210 } 211 212 size_t mangle(Symbol *s,char *dest) 213 { 214 assert(config.objfmt == OBJ_OMF); 215 return OmfObj_mangle(s, dest); 216 } 217 218 void _import(elem *e) 219 { 220 assert(config.objfmt == OBJ_OMF); 221 return OmfObj_import(e); 222 } 223 224 void linnum(Srcpos srcpos, int seg, targ_size_t offset) 225 { 226 mixin(genRetVal("linnum(srcpos, seg, offset)")); 227 } 228 229 int codeseg(const char *name,int suffix) 230 { 231 mixin(genRetVal("codeseg(name, suffix)")); 232 } 233 234 void dosseg() 235 { 236 assert(config.objfmt == OBJ_OMF); 237 return OmfObj_dosseg(); 238 } 239 240 void startaddress(Symbol *s) 241 { 242 mixin(genRetVal("startaddress(s)")); 243 } 244 245 bool includelib(const(char)* name) 246 { 247 mixin(genRetVal("includelib(name)")); 248 } 249 250 bool linkerdirective(const(char)* p) 251 { 252 mixin(genRetVal("linkerdirective(p)")); 253 } 254 255 bool allowZeroSize() 256 { 257 mixin(genRetVal("allowZeroSize()")); 258 } 259 260 void exestr(const(char)* p) 261 { 262 mixin(genRetVal("exestr(p)")); 263 } 264 265 void user(const(char)* p) 266 { 267 mixin(genRetVal("user(p)")); 268 } 269 270 void compiler() 271 { 272 mixin(genRetVal("compiler()")); 273 } 274 275 void wkext(Symbol* s1, Symbol* s2) 276 { 277 mixin(genRetVal("wkext(s1, s2)")); 278 } 279 280 void lzext(Symbol* s1, Symbol* s2) 281 { 282 assert(config.objfmt == OBJ_OMF); 283 OmfObj_lzext(s1, s2); 284 } 285 286 void _alias(const(char)* n1,const(char)* n2) 287 { 288 mixin(genRetVal("alias(n1, n2)")); 289 } 290 291 void theadr(const(char)* modname) 292 { 293 assert(config.objfmt == OBJ_OMF); 294 OmfObj_theadr(modname); 295 } 296 297 void segment_group(targ_size_t codesize, targ_size_t datasize, targ_size_t cdatasize, targ_size_t udatasize) 298 { 299 assert(config.objfmt == OBJ_OMF); 300 OmfObj_segment_group(codesize, datasize, cdatasize, udatasize); 301 } 302 303 void staticctor(Symbol *s,int dtor,int seg) 304 { 305 mixin(genRetVal("staticctor(s, dtor, seg)")); 306 } 307 308 void staticdtor(Symbol *s) 309 { 310 mixin(genRetVal("staticdtor(s)")); 311 } 312 313 void setModuleCtorDtor(Symbol *s, bool isCtor) 314 { 315 mixin(genRetVal("setModuleCtorDtor(s, isCtor)")); 316 } 317 318 void ehtables(Symbol *sfunc,uint size,Symbol *ehsym) 319 { 320 mixin(genRetVal("ehtables(sfunc, size, ehsym)")); 321 } 322 323 void ehsections() 324 { 325 mixin(genRetVal("ehsections()")); 326 } 327 328 void moduleinfo(Symbol *scc) 329 { 330 mixin(genRetVal("moduleinfo(scc)")); 331 } 332 333 int comdat(Symbol *s) 334 { 335 mixin(genRetVal("comdat(s)")); 336 } 337 338 int comdatsize(Symbol *s, targ_size_t symsize) 339 { 340 mixin(genRetVal("comdatsize(s, symsize)")); 341 } 342 343 int readonly_comdat(Symbol *s) 344 { 345 mixin(genRetVal("comdat(s)")); 346 } 347 348 void setcodeseg(int seg) 349 { 350 mixin(genRetVal("setcodeseg(seg)")); 351 } 352 353 seg_data *tlsseg() 354 { 355 mixin(genRetVal("tlsseg()")); 356 } 357 358 seg_data *tlsseg_bss() 359 { 360 mixin(genRetVal("tlsseg_bss()")); 361 } 362 363 seg_data *tlsseg_data() 364 { 365 mixin(genRetVal("tlsseg_data()")); 366 } 367 368 int fardata(char *name, targ_size_t size, targ_size_t *poffset) 369 { 370 assert(config.objfmt == OBJ_OMF); 371 return OmfObj_fardata(name, size, poffset); 372 } 373 374 void export_symbol(Symbol *s, uint argsize) 375 { 376 mixin(genRetVal("export_symbol(s, argsize)")); 377 } 378 379 void pubdef(int seg, Symbol *s, targ_size_t offset) 380 { 381 mixin(genRetVal("pubdef(seg, s, offset)")); 382 } 383 384 void pubdefsize(int seg, Symbol *s, targ_size_t offset, targ_size_t symsize) 385 { 386 mixin(genRetVal("pubdefsize(seg, s, offset, symsize)")); 387 } 388 389 int external_def(const(char)* name) 390 { 391 mixin(genRetVal("external_def(name)")); 392 } 393 394 int data_start(Symbol *sdata, targ_size_t datasize, int seg) 395 { 396 mixin(genRetVal("data_start(sdata, datasize, seg)")); 397 } 398 399 int external(Symbol *s) 400 { 401 mixin(genRetVal("external(s)")); 402 } 403 404 int common_block(Symbol *s, targ_size_t size, targ_size_t count) 405 { 406 mixin(genRetVal("common_block(s, size, count)")); 407 } 408 409 int common_block(Symbol *s, int flag, targ_size_t size, targ_size_t count) 410 { 411 mixin(genRetVal("common_block(s, flag, size, count)")); 412 } 413 414 void lidata(int seg, targ_size_t offset, targ_size_t count) 415 { 416 mixin(genRetVal("lidata(seg, offset, count)")); 417 } 418 419 void write_zeros(seg_data *pseg, targ_size_t count) 420 { 421 mixin(genRetVal("write_zeros(pseg, count)")); 422 } 423 424 void write_byte(seg_data *pseg, uint _byte) 425 { 426 mixin(genRetVal("write_byte(pseg, _byte)")); 427 } 428 429 void write_bytes(seg_data *pseg, uint nbytes, void *p) 430 { 431 mixin(genRetVal("write_bytes(pseg, nbytes, p)")); 432 } 433 434 void _byte(int seg, targ_size_t offset, uint _byte) 435 { 436 mixin(genRetVal("byte(seg, offset, _byte)")); 437 } 438 439 uint bytes(int seg, targ_size_t offset, uint nbytes, void *p) 440 { 441 mixin(genRetVal("bytes(seg, offset, nbytes, p)")); 442 } 443 444 void ledata(int seg, targ_size_t offset, targ_size_t data, uint lcfd, uint idx1, uint idx2) 445 { 446 assert(config.objfmt == OBJ_OMF); 447 OmfObj_ledata(seg, offset, data, lcfd, idx1, idx2); 448 } 449 450 void reftodatseg(int seg, targ_size_t offset, targ_size_t val, uint targetdatum, int flags) 451 { 452 mixin(genRetVal("reftodatseg(seg, offset, val, targetdatum, flags)")); 453 } 454 455 void reftofarseg(int seg, targ_size_t offset, targ_size_t val, int farseg, int flags) 456 { 457 assert(config.objfmt == OBJ_OMF); 458 OmfObj_reftofarseg(seg, offset, val, farseg, flags); 459 } 460 461 void reftocodeseg(int seg, targ_size_t offset, targ_size_t val) 462 { 463 mixin(genRetVal("reftocodeseg(seg, offset, val)")); 464 } 465 466 int reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val, int flags) 467 { 468 mixin(genRetVal("reftoident(seg, offset, s, val, flags)")); 469 } 470 471 void far16thunk(Symbol *s) 472 { 473 mixin(genRetVal("far16thunk(s)")); 474 } 475 476 void fltused() 477 { 478 mixin(genRetVal("fltused()")); 479 } 480 481 int data_readonly(char *p, int len, int *pseg) 482 { 483 mixin(genRetVal("data_readonly(p, len, pseg)")); 484 } 485 486 int data_readonly(char *p, int len) 487 { 488 mixin(genRetVal("data_readonly(p, len)")); 489 } 490 491 int string_literal_segment(uint sz) 492 { 493 mixin(genRetVal("string_literal_segment(sz)")); 494 } 495 496 Symbol *sym_cdata(tym_t ty, char *p, int len) 497 { 498 mixin(genRetVal("sym_cdata(ty, p, len)")); 499 } 500 501 void func_start(Symbol *sfunc) 502 { 503 mixin(genRetVal("func_start(sfunc)")); 504 } 505 506 void func_term(Symbol *sfunc) 507 { 508 mixin(genRetVal("func_term(sfunc)")); 509 } 510 511 void write_pointerRef(Symbol* s, uint off) 512 { 513 mixin(genRetVal("write_pointerRef(s, off)")); 514 } 515 516 int jmpTableSegment(Symbol* s) 517 { 518 mixin(genRetVal("jmpTableSegment(s)")); 519 } 520 521 Symbol *tlv_bootstrap() 522 { 523 mixin(genRetVal("tlv_bootstrap()")); 524 } 525 526 void gotref(Symbol *s) 527 { 528 switch (config.objfmt) 529 { 530 case OBJ_ELF: ElfObj_gotref(s); break; 531 case OBJ_MACH: MachObj_gotref(s); break; 532 default: assert(0); 533 } 534 } 535 536 Symbol *getGOTsym() 537 { 538 switch (config.objfmt) 539 { 540 case OBJ_ELF: return ElfObj_getGOTsym(); 541 case OBJ_MACH: return MachObj_getGOTsym(); 542 default: assert(0); 543 } 544 } 545 546 void refGOTsym() 547 { 548 switch (config.objfmt) 549 { 550 case OBJ_ELF: ElfObj_refGOTsym(); break; 551 case OBJ_MACH: MachObj_refGOTsym(); break; 552 default: assert(0); 553 } 554 } 555 556 int seg_debugT() // where the symbolic debug type data goes 557 { 558 switch (config.objfmt) 559 { 560 case OBJ_MSCOFF: return MsCoffObj_seg_debugT(); 561 case OBJ_OMF: return OmfObj_seg_debugT(); 562 default: assert(0); 563 } 564 } 565 566 void write_long(int seg, targ_size_t offset, uint data, uint lcfd, uint idx1, uint idx2) 567 { 568 assert(config.objfmt == OBJ_OMF); 569 return OmfObj_write_long(seg, offset, data, lcfd, idx1, idx2); 570 } 571 572 uint addstr(OutBuffer *strtab, const(char)* p) 573 { 574 switch (config.objfmt) 575 { 576 case OBJ_ELF: return ElfObj_addstr(strtab, p); 577 case OBJ_MACH: return MachObj_addstr(strtab, p); 578 default: assert(0); 579 } 580 } 581 582 int getsegment(const(char)* sectname, const(char)* segname, int align_, int flags) 583 { 584 assert(config.objfmt == OBJ_MACH); 585 return MachObj_getsegment(sectname, segname, align_, flags); 586 } 587 588 int getsegment(const(char)* name, const(char)* suffix, int type, int flags, int align_) 589 { 590 assert(config.objfmt == OBJ_ELF); 591 return ElfObj_getsegment(name, suffix, type, flags, align_); 592 } 593 594 int getsegment(const(char)* sectname, uint flags) 595 { 596 assert(config.objfmt == OBJ_MSCOFF); 597 return MsCoffObj_getsegment(sectname, flags); 598 } 599 600 void addrel(int seg, targ_size_t offset, Symbol *targsym, uint targseg, int rtype, int val = 0) 601 { 602 switch (config.objfmt) 603 { 604 case OBJ_MSCOFF: return MsCoffObj_addrel(seg, offset, targsym, targseg, rtype, val); 605 case OBJ_MACH: return MachObj_addrel(seg, offset, targsym, targseg, rtype, val); 606 default: assert(0); 607 } 608 } 609 610 void addrel(int seg, targ_size_t offset, uint type, uint symidx, targ_size_t val) 611 { 612 assert(config.objfmt == OBJ_ELF); 613 return ElfObj_addrel(seg, offset, type, symidx, val); 614 } 615 616 size_t writerel(int targseg, size_t offset, uint type, uint symidx, targ_size_t val) 617 { 618 assert(config.objfmt == OBJ_ELF); 619 return ElfObj_writerel(targseg, offset, type, symidx, val); 620 } 621 622 int getsegment2(uint shtidx) 623 { 624 assert(config.objfmt == OBJ_MSCOFF); 625 return MsCoffObj_getsegment2(shtidx); 626 } 627 628 uint addScnhdr(const(char)* scnhdr_name, uint flags) 629 { 630 assert(config.objfmt == OBJ_MSCOFF); 631 return MsCoffObj_addScnhdr(scnhdr_name, flags); 632 } 633 634 int seg_drectve() 635 { 636 assert(config.objfmt == OBJ_MSCOFF); 637 return MsCoffObj_seg_drectve(); 638 } 639 640 int seg_pdata() 641 { 642 assert(config.objfmt == OBJ_MSCOFF); 643 return MsCoffObj_seg_pdata(); 644 } 645 646 int seg_xdata() 647 { 648 assert(config.objfmt == OBJ_MSCOFF); 649 return MsCoffObj_seg_xdata(); 650 } 651 652 int seg_pdata_comdat(Symbol *sfunc) 653 { 654 assert(config.objfmt == OBJ_MSCOFF); 655 return MsCoffObj_seg_pdata_comdat(sfunc); 656 } 657 658 int seg_xdata_comdat(Symbol *sfunc) 659 { 660 assert(config.objfmt == OBJ_MSCOFF); 661 return MsCoffObj_seg_xdata_comdat(sfunc); 662 } 663 664 int seg_debugS() 665 { 666 assert(config.objfmt == OBJ_MSCOFF); 667 return MsCoffObj_seg_debugS(); 668 } 669 670 int seg_debugS_comdat(Symbol *sfunc) 671 { 672 assert(config.objfmt == OBJ_MSCOFF); 673 return MsCoffObj_seg_debugS_comdat(sfunc); 674 } 675 } 676 } 677 } 678 679 680 extern __gshared Obj objmod; 681 682 /***************************************** 683 * Use to generate 4 function declarations, one for 684 * each object file format supported. 685 * Params: 686 * pattern = function declaration 687 * Returns: 688 * declarations as a string suitable for mixin 689 */ 690 private extern (D) 691 string ObjMemDecl(string pattern) 692 { 693 string r = 694 gen(pattern, "Omf") ~ ";\n" ~ 695 gen(pattern, "MsCoff") ~ ";\n" ~ 696 gen(pattern, "Elf") ~ ";\n" ~ 697 gen(pattern, "Mach") ~ ";\n"; 698 return r; 699 } 700 701 /**************************************** 702 * Generate boilerplate for static dispatch that 703 * returns a value. Don't care about type of the value. 704 * Params: 705 * arg = function name to be dispatched based on `objfmt` 706 * Returns: 707 * mixin string with static dispatch 708 */ 709 private extern (D) 710 string genRetVal(string arg) 711 { 712 return 713 " 714 switch (config.objfmt) 715 { 716 case OBJ_ELF: return ElfObj_"~arg~"; 717 case OBJ_MSCOFF: return MsCoffObj_"~arg~"; 718 case OBJ_OMF: return OmfObj_"~arg~"; 719 case OBJ_MACH: return MachObj_"~arg~"; 720 default: assert(0); 721 } 722 "; 723 } 724 725 /**************************************** 726 * Generate boilerplate that replaces the single '$' in `pattern` with `arg` 727 * Params: 728 * pattern = pattern to scan for '$' 729 * arg = string to insert where '$' is found 730 * Returns: 731 * boilerplate string 732 */ 733 private extern (D) 734 string gen(string pattern, string arg) 735 { 736 foreach (i; 0 .. pattern.length) 737 if (pattern[i] == '$') 738 return pattern[0 .. i] ~ arg ~ pattern[i + 1 .. $]; 739 assert(0); 740 }