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 }