1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 1996-2016 The NASM Authors - All Rights Reserved
4  *   See the file AUTHORS included with the NASM distribution for
5  *   the specific copyright holders.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following
9  *   conditions are met:
10  *
11  *   * Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17  *
18  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * ----------------------------------------------------------------------- */
33 
34 /*
35  * outrdf2.c	output routines for the Netwide Assembler to produce
36  *		RDOFF version 2 format object files, which Julian originally
37  *		planned to use it in his MOSCOW operating system.
38  */
39 
40 #include "compiler.h"
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <assert.h>
47 
48 #include "nasm.h"
49 #include "nasmlib.h"
50 #include "error.h"
51 #include "saa.h"
52 #include "outform.h"
53 #include "outlib.h"
54 
55 /* VERBOSE_WARNINGS: define this to add some extra warnings... */
56 #define VERBOSE_WARNINGS
57 
58 #ifdef OF_RDF2
59 
60 #include "rdoff.h"
61 
62 /* This signature is written to start of RDOFF files */
63 static const char *RDOFF2Id = RDOFF2_SIGNATURE;
64 
65 /* Note that whenever a segment is referred to in the RDOFF file, its number
66  * is always half of the segment number that NASM uses to refer to it; this
67  * is because NASM only allocates even numbered segments, so as to not
68  * waste any of the 16 bits of segment number written to the file - this
69  * allows up to 65533 external labels to be defined; otherwise it would be
70  * 32764. */
71 
72 #define COUNT_SEGTYPES 9
73 
74 static char *segmenttypes[COUNT_SEGTYPES] = {
75     "null", "text", "code", "data",
76     "comment", "lcomment", "pcomment",
77     "symdebug", "linedebug"
78 };
79 
80 static int segmenttypenumbers[COUNT_SEGTYPES] = {
81     0, 1, 1, 2, 3, 4, 5, 6, 7
82 };
83 
84 /* code for managing buffers needed to separate code and data into individual
85  * sections until they are ready to be written to the file.
86  * We'd better hope that it all fits in memory else we're buggered... */
87 
88 #define BUF_BLOCK_LEN 4088      /* selected to match page size (4096)
89                                  * on 80x86 machines for efficiency */
90 
91 /***********************************************************************
92  * Actual code to deal with RDOFF2 ouput format begins here...
93  */
94 
95 /* global variables set during the initialisation phase */
96 
97 static struct SAA *seg[RDF_MAXSEGS];    /* seg 0 = code, seg 1 = data */
98 static struct SAA *header;      /* relocation/import/export records */
99 
100 static struct seginfo {
101     char *segname;
102     int segnumber;
103     uint16_t segtype;
104     uint16_t segreserved;
105     int32_t seglength;
106 } segments[RDF_MAXSEGS];
107 
108 static int nsegments;
109 
110 static int32_t bsslength;
111 static int32_t headerlength;
112 
rdf2_init(void)113 static void rdf2_init(void)
114 {
115     int segtext, segdata, segbss;
116 
117     /* set up the initial segments */
118     segments[0].segname = ".text";
119     segments[0].segnumber = 0;
120     segments[0].segtype = 1;
121     segments[0].segreserved = 0;
122     segments[0].seglength = 0;
123 
124     segments[1].segname = ".data";
125     segments[1].segnumber = 1;
126     segments[1].segtype = 2;
127     segments[1].segreserved = 0;
128     segments[1].seglength = 0;
129 
130     segments[2].segname = ".bss";
131     segments[2].segnumber = 2;
132     segments[2].segtype = 0xFFFF;       /* reserved - should never be produced */
133     segments[2].segreserved = 0;
134     segments[2].seglength = 0;
135 
136     nsegments = 3;
137 
138     seg[0] = saa_init(1L);
139     seg[1] = saa_init(1L);
140     seg[2] = NULL;              /* special case! */
141 
142     header = saa_init(1L);
143 
144     segtext = seg_alloc();
145     segdata = seg_alloc();
146     segbss = seg_alloc();
147     if (segtext != 0 || segdata != 2 || segbss != 4)
148         nasm_panic("rdf segment numbers not allocated as expected (%d,%d,%d)",
149                    segtext, segdata, segbss);
150     bsslength = 0;
151     headerlength = 0;
152 }
153 
rdf2_section_names(char * name,int pass,int * bits)154 static int32_t rdf2_section_names(char *name, int pass, int *bits)
155 {
156     int i;
157     bool err;
158     char *p, *q;
159     int code = -1;
160     int reserved = 0;
161 
162     (void)pass;
163 
164     /*
165      * Default is 32 bits, in the text segment.
166      */
167     if (!name) {
168         *bits = 32;
169         return 0;
170     }
171 
172     /* look for segment type code following segment name */
173     p = name;
174     while (*p && !nasm_isspace(*p))
175         p++;
176     if (*p) {                   /* we're now in whitespace */
177         *p++ = '\0';
178         while (*p && nasm_isspace(80))
179             *p++ = '\0';
180     }
181     if (*p) {                   /* we're now in an attribute value */
182         /*
183          * see if we have an optional ',number' following the type code
184          */
185         if ((q = strchr(p, ','))) {
186             *q++ = '\0';
187 
188             reserved = readnum(q, &err);
189             if (err) {
190                 nasm_error(ERR_NONFATAL,
191                       "value following comma must be numeric");
192                 reserved = 0;
193             }
194         }
195         /*
196          * check it against the text strings in segmenttypes
197          */
198 
199         for (i = 0; i < COUNT_SEGTYPES; i++)
200             if (!nasm_stricmp(p, segmenttypes[i])) {
201                 code = segmenttypenumbers[i];
202                 break;
203             }
204         if (code == -1) {       /* didn't find anything */
205             code = readnum(p, &err);
206             if (err) {
207                 nasm_error(ERR_NONFATAL, "unrecognised RDF segment type (%s)",
208                       p);
209                 code = 3;
210             }
211         }
212     }
213     for (i = 0; i < nsegments; i++) {
214         if (!strcmp(name, segments[i].segname)) {
215             if (code != -1 || reserved != 0)
216                 nasm_error(ERR_NONFATAL, "segment attributes specified on"
217                       " redeclaration of segment");
218             return segments[i].segnumber * 2;
219         }
220     }
221 
222     /* declaring a new segment! */
223 
224     if (code == -1) {
225         nasm_error(ERR_NONFATAL, "new segment declared without type code");
226         code = 3;
227     }
228     if (nsegments == RDF_MAXSEGS) {
229         nasm_fatal("reached compiled-in maximum segment limit (%d)",
230               RDF_MAXSEGS);
231         return NO_SEG;
232     }
233 
234     segments[nsegments].segname = nasm_strdup(name);
235     i = seg_alloc();
236     if (i % 2 != 0)
237         nasm_panic("seg_alloc() returned odd number");
238     segments[nsegments].segnumber = i >> 1;
239     segments[nsegments].segtype = code;
240     segments[nsegments].segreserved = reserved;
241     segments[nsegments].seglength = 0;
242 
243     seg[nsegments] = saa_init(1L);
244 
245     return i;
246 }
247 
248 /*
249  * Write relocation record
250  */
write_reloc_rec(struct RelocRec * r)251 static void write_reloc_rec(struct RelocRec *r)
252 {
253     char buf[4], *b;
254 
255     if (r->refseg != (uint16_t) NO_SEG && (r->refseg & 1))        /* segment base ref */
256         r->type = RDFREC_SEGRELOC;
257 
258     r->refseg >>= 1;            /* adjust segment nos to RDF rather than NASM */
259 
260     saa_wbytes(header, &r->type, 1);
261     saa_wbytes(header, &r->reclen, 1);
262     saa_wbytes(header, &r->segment, 1);
263     b = buf;
264     WRITELONG(b, r->offset);
265     saa_wbytes(header, buf, 4);
266     saa_wbytes(header, &r->length, 1);
267     b = buf;
268     WRITESHORT(b, r->refseg);
269     saa_wbytes(header, buf, 2);
270     headerlength += r->reclen + 2;
271 }
272 
273 /*
274  * Write export record
275  */
write_export_rec(struct ExportRec * r)276 static void write_export_rec(struct ExportRec *r)
277 {
278     char buf[4], *b;
279 
280     r->segment >>= 1;
281 
282     saa_wbytes(header, &r->type, 1);
283     saa_wbytes(header, &r->reclen, 1);
284     saa_wbytes(header, &r->flags, 1);
285     saa_wbytes(header, &r->segment, 1);
286     b = buf;
287     WRITELONG(b, r->offset);
288     saa_wbytes(header, buf, 4);
289     saa_wbytes(header, r->label, strlen(r->label) + 1);
290     headerlength += r->reclen + 2;
291 }
292 
write_import_rec(struct ImportRec * r)293 static void write_import_rec(struct ImportRec *r)
294 {
295     char buf[4], *b;
296 
297     r->segment >>= 1;
298 
299     saa_wbytes(header, &r->type, 1);
300     saa_wbytes(header, &r->reclen, 1);
301     saa_wbytes(header, &r->flags, 1);
302     b = buf;
303     WRITESHORT(b, r->segment);
304     saa_wbytes(header, buf, 2);
305     saa_wbytes(header, r->label, strlen(r->label) + 1);
306     headerlength += r->reclen + 2;
307 }
308 
309 /*
310  * Write BSS record
311  */
write_bss_rec(struct BSSRec * r)312 static void write_bss_rec(struct BSSRec *r)
313 {
314     char buf[4], *b;
315 
316     saa_wbytes(header, &r->type, 1);
317     saa_wbytes(header, &r->reclen, 1);
318     b = buf;
319     WRITELONG(b, r->amount);
320     saa_wbytes(header, buf, 4);
321     headerlength += r->reclen + 2;
322 }
323 
324 /*
325  * Write common variable record
326  */
write_common_rec(struct CommonRec * r)327 static void write_common_rec(struct CommonRec *r)
328 {
329     char buf[4], *b;
330 
331     r->segment >>= 1;
332 
333     saa_wbytes(header, &r->type, 1);
334     saa_wbytes(header, &r->reclen, 1);
335     b = buf;
336     WRITESHORT(b, r->segment);
337     saa_wbytes(header, buf, 2);
338     b = buf;
339     WRITELONG(b, r->size);
340     saa_wbytes(header, buf, 4);
341     b = buf;
342     WRITESHORT(b, r->align);
343     saa_wbytes(header, buf, 2);
344     saa_wbytes(header, r->label, strlen(r->label) + 1);
345     headerlength += r->reclen + 2;
346 }
347 
348 /*
349  * Write library record
350  */
write_dll_rec(struct DLLRec * r)351 static void write_dll_rec(struct DLLRec *r)
352 {
353     saa_wbytes(header, &r->type, 1);
354     saa_wbytes(header, &r->reclen, 1);
355     saa_wbytes(header, r->libname, strlen(r->libname) + 1);
356     headerlength += r->reclen + 2;
357 }
358 
359 /*
360  * Write module name record
361  */
write_modname_rec(struct ModRec * r)362 static void write_modname_rec(struct ModRec *r)
363 {
364     saa_wbytes(header, &r->type, 1);
365     saa_wbytes(header, &r->reclen, 1);
366     saa_wbytes(header, r->modname, strlen(r->modname) + 1);
367     headerlength += r->reclen + 2;
368 }
369 
370 /*
371  * Handle export, import and common records.
372  */
rdf2_deflabel(char * name,int32_t segment,int64_t offset,int is_global,char * special)373 static void rdf2_deflabel(char *name, int32_t segment, int64_t offset,
374                           int is_global, char *special)
375 {
376     struct ExportRec r;
377     struct ImportRec ri;
378     struct CommonRec ci;
379     static int farsym = 0;
380     static int i;
381     char symflags = 0;
382     int len;
383 
384     /* Check if the label length is OK */
385     if ((len = strlen(name)) >= EXIM_LABEL_MAX) {
386         nasm_error(ERR_NONFATAL, "label size exceeds %d bytes", EXIM_LABEL_MAX);
387         return;
388     }
389     if (!len) {
390         nasm_error(ERR_NONFATAL, "zero-length label");
391         return;
392     }
393 
394     if (is_global == 2) {
395         /* Common variable */
396         ci.type = RDFREC_COMMON;
397         ci.size = offset;
398         ci.segment = segment;
399         strcpy(ci.label, name);
400         ci.reclen = 9 + len;
401         ci.align = 0;
402 
403         /*
404          * Check the special text to see if it's a valid number and power
405          * of two; if so, store it as the alignment for the common variable.
406          */
407         if (special) {
408             bool err;
409             ci.align = readnum(special, &err);
410             if (err)
411                 nasm_error(ERR_NONFATAL, "alignment constraint `%s' is not a"
412                       " valid number", special);
413             else if ((ci.align | (ci.align - 1)) != 2 * ci.align - 1)
414                 nasm_error(ERR_NONFATAL, "alignment constraint `%s' is not a"
415                       " power of two", special);
416         }
417         write_common_rec(&ci);
418     }
419 
420     /* We don't care about local labels or fix-up hints */
421     if (is_global != 1)
422         return;
423 
424     if (special) {
425         while (*special == ' ' || *special == '\t')
426             special++;
427 
428         if (!nasm_strnicmp(special, "export", 6)) {
429             special += 6;
430             symflags |= SYM_GLOBAL;
431         } else if (!nasm_strnicmp(special, "import", 6)) {
432             special += 6;
433             symflags |= SYM_IMPORT;
434         }
435 
436         if (*special) {
437             while (nasm_isspace(*special))
438                 special++;
439             if (!nasm_stricmp(special, "far")) {
440                 farsym = 1;
441             } else if (!nasm_stricmp(special, "near")) {
442                 farsym = 0;
443             } else if (!nasm_stricmp(special, "proc") ||
444                        !nasm_stricmp(special, "function")) {
445                 symflags |= SYM_FUNCTION;
446             } else if (!nasm_stricmp(special, "data") ||
447                        !nasm_stricmp(special, "object")) {
448                 symflags |= SYM_DATA;
449             } else
450                 nasm_error(ERR_NONFATAL, "unrecognised symbol type `%s'",
451                       special);
452         }
453     }
454 
455     if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
456         nasm_error(ERR_NONFATAL, "unrecognised special symbol `%s'", name);
457         return;
458     }
459 
460     for (i = 0; i < nsegments; i++) {
461         if (segments[i].segnumber == segment >> 1)
462             break;
463     }
464 
465     if (i >= nsegments) {       /* EXTERN declaration */
466         ri.type = farsym ? RDFREC_FARIMPORT : RDFREC_IMPORT;
467         if (symflags & SYM_GLOBAL)
468             nasm_error(ERR_NONFATAL,
469                   "symbol type conflict - EXTERN cannot be EXPORT");
470         ri.flags = symflags;
471         ri.segment = segment;
472         strcpy(ri.label, name);
473         ri.reclen = 4 + len;
474         write_import_rec(&ri);
475     } else if (is_global) {
476         r.type = RDFREC_GLOBAL; /* GLOBAL declaration */
477         if (symflags & SYM_IMPORT)
478             nasm_error(ERR_NONFATAL,
479                   "symbol type conflict - GLOBAL cannot be IMPORT");
480         r.flags = symflags;
481         r.segment = segment;
482         r.offset = offset;
483         strcpy(r.label, name);
484         r.reclen = 7 + len;
485         write_export_rec(&r);
486     }
487 }
488 
membufwrite(int segment,const void * data,int bytes)489 static void membufwrite(int segment, const void *data, int bytes)
490 {
491     int i;
492     char buf[4], *b;
493 
494     for (i = 0; i < nsegments; i++) {
495         if (segments[i].segnumber == segment)
496             break;
497     }
498     if (i == nsegments)
499         nasm_panic("can't find segment %d", segment);
500 
501     if (bytes < 0) {
502         b = buf;
503         if (bytes == -2)
504             WRITESHORT(b, *(int16_t *)data);
505         else
506             WRITELONG(b, *(int32_t *)data);
507         data = buf;
508         bytes = -bytes;
509     }
510     segments[i].seglength += bytes;
511     saa_wbytes(seg[i], data, bytes);
512 }
513 
getsegmentlength(int segment)514 static int getsegmentlength(int segment)
515 {
516     int i;
517     for (i = 0; i < nsegments; i++) {
518         if (segments[i].segnumber == segment)
519             break;
520     }
521     if (i == nsegments)
522         nasm_panic("can't find segment %d", segment);
523 
524     return segments[i].seglength;
525 }
526 
rdf2_out(int32_t segto,const void * data,enum out_type type,uint64_t size,int32_t segment,int32_t wrt)527 static void rdf2_out(int32_t segto, const void *data,
528 		     enum out_type type, uint64_t size,
529                      int32_t segment, int32_t wrt)
530 {
531     struct RelocRec rr;
532     uint8_t databuf[8], *pd;
533     int seg;
534 
535     segto >>= 1;                /* convert NASM segment no to RDF number */
536 
537     for (seg = 0; seg < nsegments; seg++) {
538         if (segments[seg].segnumber == segto)
539             break;
540     }
541     if (seg >= nsegments) {
542         nasm_error(ERR_NONFATAL,
543               "specified segment not supported by rdf output format");
544         return;
545     }
546 
547     if (wrt != NO_SEG) {
548         wrt = NO_SEG;           /* continue to do _something_ */
549         nasm_error(ERR_NONFATAL, "WRT not supported by rdf output format");
550     }
551 
552     if (segto == 2 && type != OUT_RESERVE) {
553         nasm_error(ERR_NONFATAL, "BSS segments may not be initialized");
554 
555         /* just reserve the space for now... */
556 
557         if (type == OUT_REL2ADR)
558             size = 2;
559         else
560             size = 4;
561         type = OUT_RESERVE;
562     }
563 
564     if (type == OUT_RESERVE) {
565         if (segto == 2)         /* BSS segment space reserverd */
566             bsslength += size;
567         else
568             while (size--)
569                 membufwrite(segto, databuf, 1);
570     } else if (type == OUT_RAWDATA) {
571         membufwrite(segto, data, size);
572     } else if (type == OUT_ADDRESS) {
573         int asize = abs((int)size);
574 
575         /* if segment == NO_SEG then we are writing an address of an
576            object within the same segment - do not produce reloc rec. */
577 
578         /* FIXME - is this behaviour sane? at first glance it doesn't
579            appear to be. Must test this thoroughly...! */
580 
581         if (segment != NO_SEG) {
582             /* it's an address, so we must write a relocation record */
583 
584             rr.type = RDFREC_RELOC;     /* type signature */
585             rr.reclen = 8;
586             rr.segment = segto; /* segment we're currently in */
587             rr.offset = getsegmentlength(segto);        /* current offset */
588             rr.length = asize; /* length of reference */
589             rr.refseg = segment;        /* segment referred to */
590             write_reloc_rec(&rr);
591         }
592 
593         pd = databuf;           /* convert address to little-endian */
594 	WRITEADDR(pd, *(int64_t *)data, asize);
595         membufwrite(segto, databuf, asize);
596     } else if (type == OUT_REL2ADR) {
597         if (segment == segto)
598             nasm_panic("intra-segment OUT_REL2ADR");
599 
600         rr.reclen = 8;
601         rr.offset = getsegmentlength(segto);    /* current offset */
602         rr.length = 2;          /* length of reference */
603         rr.refseg = segment;    /* segment referred to (will be >>1'd) */
604 
605         if (segment != NO_SEG && segment % 2) {
606             rr.type = RDFREC_SEGRELOC;
607             rr.segment = segto; /* memory base refs *aren't ever* relative! */
608             write_reloc_rec(&rr);
609 
610             /* what do we put in the code? Simply the data. This should almost
611              * always be zero, unless someone's doing segment arithmetic...
612              */
613             rr.offset = *(int64_t *)data;
614         } else {
615             rr.type = RDFREC_RELOC;     /* type signature */
616             rr.segment = segto + 64;    /* segment we're currently in + rel flag */
617             write_reloc_rec(&rr);
618 
619             /* work out what to put in the code: offset of the end of this operand,
620              * subtracted from any data specified, so that loader can just add
621              * address of imported symbol onto it to get address relative to end of
622              * instruction: import_address + data(offset) - end_of_instrn */
623 
624             rr.offset = *(int32_t *)data - (rr.offset + size);
625         }
626 
627         membufwrite(segto, &rr.offset, -2);
628     } else if (type == OUT_REL4ADR) {
629         if ((segment == segto) && (globalbits != 64))
630             nasm_panic("intra-segment OUT_REL4ADR");
631         if (segment != NO_SEG && segment % 2) {
632             nasm_panic("erm... 4 byte segment base ref?");
633         }
634 
635         rr.type = RDFREC_RELOC; /* type signature */
636         rr.segment = segto + 64;        /* segment we're currently in + rel tag */
637         rr.offset = getsegmentlength(segto);    /* current offset */
638         rr.length = 4;          /* length of reference */
639         rr.refseg = segment;    /* segment referred to */
640         rr.reclen = 8;
641         write_reloc_rec(&rr);
642 
643         rr.offset = *(int64_t *)data - (rr.offset + size);
644 
645         membufwrite(segto, &rr.offset, -4);
646     }
647 }
648 
rdf2_cleanup(void)649 static void rdf2_cleanup(void)
650 {
651     int32_t l;
652     struct BSSRec bs;
653     int i;
654 
655     /* should write imported & exported symbol declarations to header here */
656 
657     /* generate the output file... */
658     nasm_write(RDOFF2Id, 6, ofile); /* file type magic number */
659 
660     if (bsslength != 0) {       /* reserve BSS */
661         bs.type = RDFREC_BSS;
662         bs.amount = bsslength;
663         bs.reclen = 4;
664         write_bss_rec(&bs);
665     }
666 
667     /*
668      * calculate overall length of the output object
669      */
670     l = headerlength + 4;
671 
672     for (i = 0; i < nsegments; i++) {
673         if (i == 2)
674             continue;           /* skip BSS segment */
675         l += 10 + segments[i].seglength;
676     }
677     l += 10;                    /* null segment */
678 
679     fwriteint32_t(l, ofile);
680 
681     fwriteint32_t(headerlength, ofile);
682     saa_fpwrite(header, ofile); /* dump header */
683     saa_free(header);
684 
685     for (i = 0; i < nsegments; i++) {
686         if (i == 2)
687             continue;
688 
689         fwriteint16_t(segments[i].segtype, ofile);
690         fwriteint16_t(segments[i].segnumber, ofile);
691         fwriteint16_t(segments[i].segreserved, ofile);
692         fwriteint32_t(segments[i].seglength, ofile);
693 
694         saa_fpwrite(seg[i], ofile);
695         saa_free(seg[i]);
696     }
697 
698     /* null segment - write 10 bytes of zero */
699     fwriteint32_t(0, ofile);
700     fwriteint32_t(0, ofile);
701     fwriteint16_t(0, ofile);
702 }
703 
704 /*
705  * Handle RDOFF2 specific directives
706  */
707 static enum directive_result
rdf2_directive(enum directive directive,char * value,int pass)708 rdf2_directive(enum directive directive, char *value, int pass)
709 {
710     size_t n;
711 
712     switch (directive) {
713     case D_LIBRARY:
714 	n = strlen(value);
715 	if (n >= MODLIB_NAME_MAX) {
716 	    nasm_error(ERR_NONFATAL, "name size exceeds %d bytes", MODLIB_NAME_MAX);
717 	    return DIRR_ERROR;
718 	}
719         if (pass == 1) {
720             struct DLLRec r;
721             r.type = RDFREC_DLL;
722             r.reclen = n + 1;
723             strcpy(r.libname, value);
724             write_dll_rec(&r);
725         }
726         return DIRR_OK;
727 
728     case D_MODULE:
729 	if ((n = strlen(value)) >= MODLIB_NAME_MAX) {
730 	    nasm_error(ERR_NONFATAL, "name size exceeds %d bytes", MODLIB_NAME_MAX);
731 	    return DIRR_ERROR;
732 	}
733         if (pass == 1) {
734             struct ModRec r;
735             r.type = RDFREC_MODNAME;
736             r.reclen = n + 1;
737             strcpy(r.modname, value);
738             write_modname_rec(&r);
739         }
740         return DIRR_OK;
741 
742     default:
743 	return DIRR_UNKNOWN;
744     }
745 }
746 
747 extern macros_t rdf2_stdmac[];
748 
749 const struct ofmt of_rdf2 = {
750     "Relocatable Dynamic Object File Format v2.0",
751     "rdf",
752     ".rdf",
753     0,
754     64,
755     null_debug_arr,
756     &null_debug_form,
757     rdf2_stdmac,
758     rdf2_init,
759     null_reset,
760     nasm_do_legacy_output,
761     rdf2_out,
762     rdf2_deflabel,
763     rdf2_section_names,
764     NULL,
765     null_sectalign,
766     null_segbase,
767     rdf2_directive,
768     rdf2_cleanup,
769     NULL                        /* pragma list */
770 };
771 
772 #endif                          /* OF_RDF2 */
773