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