1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 1996-2014 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  * rdoff.c	library of routines for manipulating rdoff files
36  */
37 
38 /* TODO:	The functions in this module assume they are running
39  *		on a little-endian machine. This should be fixed to
40  *		make it portable.
41  */
42 
43 #include "compiler.h"
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <errno.h>
48 
49 #include "rdfutils.h"
50 
51 /*
52  * Comment this out to allow the module to read & write header record types
53  * that it isn't aware of. With this defined, unrecognised header records
54  * will generate error number 8, reported as 'unknown extended header record'.
55  */
56 
57 #define STRICT_ERRORS
58 
59 /* ========================================================================
60  * Code for memory buffers (for delayed writing of header until we know
61  * how int32_t it is).
62  * ======================================================================== */
63 
newmembuf(void)64 static memorybuffer *newmembuf(void)
65 {
66     memorybuffer *t;
67 
68     t = nasm_malloc(sizeof(memorybuffer));
69     if (!t)
70         return NULL;
71 
72     t->length = 0;
73     t->next = NULL;
74     return t;
75 }
76 
membufwrite(memorybuffer * const b,void * data,int bytes)77 static void membufwrite(memorybuffer * const b, void *data, int bytes)
78 {
79     uint16_t w;
80     int32_t l;
81     char *c;
82 
83     if (b->next) {              /* memory buffer full - use next buffer */
84         membufwrite(b->next, data, bytes);
85         return;
86     }
87 
88     if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
89         || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
90 
91         /* buffer full and no next allocated... allocate and initialise next
92          * buffer */
93         b->next = newmembuf();
94         membufwrite(b->next, data, bytes);
95         return;
96     }
97 
98     switch (bytes) {
99     case -4:                   /* convert to little-endian */
100         l = *(int32_t *)data;
101         b->buffer[b->length++] = l & 0xFF;
102         l >>= 8;
103         b->buffer[b->length++] = l & 0xFF;
104         l >>= 8;
105         b->buffer[b->length++] = l & 0xFF;
106         l >>= 8;
107         b->buffer[b->length++] = l & 0xFF;
108         break;
109 
110     case -2:
111         w = *(uint16_t *) data;
112         b->buffer[b->length++] = w & 0xFF;
113         w >>= 8;
114         b->buffer[b->length++] = w & 0xFF;
115         break;
116 
117     default:
118         c = data;
119         while (bytes--)
120             b->buffer[b->length++] = *c++;
121         break;
122     }
123 }
124 
membufdump(memorybuffer * b,FILE * fp)125 static void membufdump(memorybuffer * b, FILE * fp)
126 {
127     if (!b)
128         return;
129 
130     nasm_write(b->buffer, b->length, fp);
131     membufdump(b->next, fp);
132 }
133 
membuflength(memorybuffer * b)134 static int membuflength(memorybuffer * b)
135 {
136     if (!b)
137         return 0;
138     return b->length + membuflength(b->next);
139 }
140 
freemembuf(memorybuffer * b)141 static void freemembuf(memorybuffer * b)
142 {
143     if (!b)
144         return;
145     freemembuf(b->next);
146     nasm_free(b);
147 }
148 
149 /* =========================================================================
150    General purpose routines and variables used by the library functions
151    ========================================================================= */
152 
153 /*
154  * translateint32_t() and translateint16_t()
155  *
156  * translate from little endian to local representation
157  */
translateint32_t(int32_t in)158 int32_t translateint32_t(int32_t in)
159 {
160     int32_t r;
161     uint8_t *i;
162 
163     i = (uint8_t *)&in;
164     r = i[3];
165     r = (r << 8) + i[2];
166     r = (r << 8) + i[1];
167     r = (r << 8) + *i;
168 
169     return r;
170 }
171 
translateint16_t(uint16_t in)172 uint16_t translateint16_t(uint16_t in)
173 {
174     uint16_t r;
175     uint8_t *i;
176 
177     i = (uint8_t *)&in;
178     r = (i[1] << 8) + i[0];
179 
180     return r;
181 }
182 
183 /* Segment types */
184 static char *knownsegtypes[8] = {
185     "NULL", "text", "data", "object comment",
186     "linked comment", "loader comment",
187     "symbolic debug", "line number debug"
188 };
189 
190 /* Get a textual string describing the segment type */
translatesegmenttype(uint16_t type)191 char *translatesegmenttype(uint16_t type)
192 {
193     if (type < 8)
194         return knownsegtypes[type];
195     if (type < 0x0020)
196         return "reserved";
197     if (type < 0x1000)
198         return "reserved - Moscow";
199     if (type < 0x8000)
200         return "reserved - system dependant";
201     if (type < 0xFFFF)
202         return "reserved - other";
203     if (type == 0xFFFF)
204         return "invalid type code";
205     return "type code out of range";
206 }
207 
208 /* This signature is written to the start of RDOFF files */
209 const char *RDOFFId = RDOFF2_SIGNATURE;
210 
211 /* Error messages. Must correspond to the codes defined in rdoff.h */
212 const char *rdf_errors[11] = {
213     /* 0 */ "no error occurred",
214     /* 1 */ "could not open file",
215     /* 2 */ "invalid file format",
216     /* 3 */ "error reading file",
217     /* 4 */ "unknown error",
218     /* 5 */ "header not read",
219     /* 6 */ "out of memory",
220     /* 7 */ "RDOFF v1 not supported",
221     /* 8 */ "unknown extended header record",
222     /* 9 */ "header record of known type but unknown length",
223     /* 10 */ "no such segment"
224 };
225 
226 int rdf_errno = 0;
227 
228 /* ========================================================================
229  * Hook for nasm_error() to work
230  * ======================================================================== */
nasm_verror(errflags severity,const char * fmt,va_list val)231 void nasm_verror(errflags severity, const char *fmt, va_list val)
232 {
233     severity &= ERR_MASK;
234 
235     vfprintf(stderr, fmt, val);
236     if (severity >= ERR_FATAL)
237         exit(severity - ERR_FATAL + 1);
238 }
239 
nasm_verror_critical(errflags severity,const char * fmt,va_list val)240 fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list val)
241 {
242     nasm_verror(severity, fmt, val);
243     abort();
244 }
245 
rdoff_init(void)246 void rdoff_init(void)
247 {
248 
249 }
250 
251 /* ========================================================================
252    The library functions
253    ======================================================================== */
254 
rdfopen(rdffile * f,const char * name)255 int rdfopen(rdffile * f, const char *name)
256 {
257     FILE *fp;
258 
259     fp = fopen(name, "rb");
260     if (!fp)
261         return rdf_errno = RDF_ERR_OPEN;
262 
263     return rdfopenhere(f, fp, NULL, name);
264 }
265 
rdfopenhere(rdffile * f,FILE * fp,int * refcount,const char * name)266 int rdfopenhere(rdffile * f, FILE * fp, int *refcount, const char *name)
267 {
268     char buf[8];
269     int32_t initpos;
270     int32_t l;
271     uint16_t s;
272 
273     if (translateint32_t(0x01020304) != 0x01020304) {
274         /* fix this to be portable! */
275         fputs("*** this program requires a little endian machine\n",
276               stderr);
277         fprintf(stderr, "01020304h = %08"PRIx32"h\n", translateint32_t(0x01020304));
278         exit(3);
279     }
280 
281     f->fp = fp;
282     initpos = ftell(fp);
283 
284     /* read header */
285     if (fread(buf, 1, 6, f->fp) != 6) {
286         fclose(f->fp);
287         return rdf_errno = RDF_ERR_READ;
288     }
289     buf[6] = 0;
290 
291     if (strcmp(buf, RDOFFId)) {
292         fclose(f->fp);
293         if (!strcmp(buf, "RDOFF1"))
294             return rdf_errno = RDF_ERR_VER;
295         return rdf_errno = RDF_ERR_FORMAT;
296     }
297 
298     if (fread(&l, 1, 4, f->fp) != 4
299         || fread(&f->header_len, 1, 4, f->fp) != 4) {
300         fclose(f->fp);
301         return rdf_errno = RDF_ERR_READ;
302     }
303 
304     f->header_ofs = ftell(f->fp);
305     f->eof_offset = f->header_ofs + translateint32_t(l) - 4;
306 
307     if (fseek(f->fp, f->header_len, SEEK_CUR)) {
308         fclose(f->fp);
309         return rdf_errno = RDF_ERR_FORMAT;      /* seek past end of file...? */
310     }
311 
312     if (fread(&s, 1, 2, f->fp) != 2) {
313         fclose(f->fp);
314         return rdf_errno = RDF_ERR_READ;
315     }
316 
317     f->nsegs = 0;
318 
319     while (s != 0) {
320         f->seg[f->nsegs].type = s;
321         if (fread(&f->seg[f->nsegs].number, 1, 2, f->fp) != 2 ||
322             fread(&f->seg[f->nsegs].reserved, 1, 2, f->fp) != 2 ||
323             fread(&f->seg[f->nsegs].length, 1, 4, f->fp) != 4) {
324             fclose(f->fp);
325             return rdf_errno = RDF_ERR_READ;
326         }
327 
328         f->seg[f->nsegs].offset = ftell(f->fp);
329         if (fseek(f->fp, f->seg[f->nsegs].length, SEEK_CUR)) {
330             fclose(f->fp);
331             return rdf_errno = RDF_ERR_FORMAT;
332         }
333         f->nsegs++;
334 
335         if (fread(&s, 1, 2, f->fp) != 2) {
336             fclose(f->fp);
337             return rdf_errno = RDF_ERR_READ;
338         }
339     }
340 
341     if (f->eof_offset != ftell(f->fp) + 8) {    /* +8 = skip null segment header */
342         fprintf(stderr, "warning: eof_offset [%"PRId32"] and actual eof offset "
343                 "[%ld] don't match\n", f->eof_offset, ftell(f->fp) + 8);
344     }
345     fseek(f->fp, initpos, SEEK_SET);
346     f->header_loc = NULL;
347 
348     f->name = nasm_strdup(name);
349     f->refcount = refcount;
350     if (refcount)
351         (*refcount)++;
352     return RDF_OK;
353 }
354 
rdfclose(rdffile * f)355 int rdfclose(rdffile * f)
356 {
357     if (!f->refcount || !--(*f->refcount)) {
358         fclose(f->fp);
359         f->fp = NULL;
360     }
361     nasm_free(f->name);
362 
363     return 0;
364 }
365 
366 /*
367  * Print the message for last error (from rdf_errno)
368  */
rdfperror(const char * app,const char * name)369 void rdfperror(const char *app, const char *name)
370 {
371     fprintf(stderr, "%s:%s: %s\n", app, name, rdf_errors[rdf_errno]);
372     if (rdf_errno == RDF_ERR_OPEN || rdf_errno == RDF_ERR_READ) {
373         perror(app);
374     }
375 }
376 
377 /*
378  * Find the segment by its number.
379  * Returns segment array index, or -1 if segment with such number was not found.
380  */
rdffindsegment(rdffile * f,int segno)381 int rdffindsegment(rdffile * f, int segno)
382 {
383     int i;
384     for (i = 0; i < f->nsegs; i++)
385         if (f->seg[i].number == segno)
386             return i;
387     return -1;
388 }
389 
390 /*
391  * Load the segment. Returns status.
392  */
rdfloadseg(rdffile * f,int segment,void * buffer)393 int rdfloadseg(rdffile * f, int segment, void *buffer)
394 {
395     int32_t fpos;
396     size_t slen;
397 
398     switch (segment) {
399     case RDOFF_HEADER:
400         fpos = f->header_ofs;
401         slen = f->header_len;
402         f->header_loc = (uint8_t *) buffer;
403         f->header_fp = 0;
404         break;
405     default:
406         if (segment < f->nsegs) {
407             fpos = f->seg[segment].offset;
408             slen = f->seg[segment].length;
409             f->seg[segment].data = (uint8_t *) buffer;
410         } else {
411             return rdf_errno = RDF_ERR_SEGMENT;
412         }
413     }
414 
415     if (fseek(f->fp, fpos, SEEK_SET))
416         return rdf_errno = RDF_ERR_UNKNOWN;
417 
418     if (fread(buffer, 1, slen, f->fp) != slen)
419         return rdf_errno = RDF_ERR_READ;
420 
421     return RDF_OK;
422 }
423 
424 /* Macros for reading integers from header in memory */
425 
426 #define RI8(v) v = f->header_loc[f->header_fp++]
427 #define RI16(v) { v = (f->header_loc[f->header_fp] + \
428 		       (f->header_loc[f->header_fp+1] << 8)); \
429 		  f->header_fp += 2; }
430 
431 #define RI32(v) { v = (f->header_loc[f->header_fp] + \
432 		       (f->header_loc[f->header_fp+1] << 8) + \
433 		       (f->header_loc[f->header_fp+2] << 16) + \
434 		       (f->header_loc[f->header_fp+3] << 24)); \
435 		  f->header_fp += 4; }
436 
437 #define RS(str,max) { for(i=0;i<max;i++){\
438   RI8(str[i]); if (!str[i]) break;} str[i]=0; }
439 
440 /*
441  * Read a header record.
442  * Returns the address of record, or NULL in case of error.
443  */
rdfgetheaderrec(rdffile * f)444 rdfheaderrec *rdfgetheaderrec(rdffile * f)
445 {
446     static rdfheaderrec r;
447     int i;
448 
449     if (!f->header_loc) {
450         rdf_errno = RDF_ERR_HEADER;
451         return NULL;
452     }
453 
454     if (f->header_fp >= f->header_len)
455         return 0;
456 
457     RI8(r.type);
458     RI8(r.g.reclen);
459 
460     switch (r.type) {
461     case RDFREC_RELOC:         /* Relocation record */
462     case RDFREC_SEGRELOC:
463         if (r.r.reclen != 8) {
464             rdf_errno = RDF_ERR_RECLEN;
465             return NULL;
466         }
467         RI8(r.r.segment);
468         RI32(r.r.offset);
469         RI8(r.r.length);
470         RI16(r.r.refseg);
471         break;
472 
473     case RDFREC_IMPORT:        /* Imported symbol record */
474     case RDFREC_FARIMPORT:
475         RI8(r.i.flags);
476         RI16(r.i.segment);
477         RS(r.i.label, EXIM_LABEL_MAX);
478         break;
479 
480     case RDFREC_GLOBAL:        /* Exported symbol record */
481         RI8(r.e.flags);
482         RI8(r.e.segment);
483         RI32(r.e.offset);
484         RS(r.e.label, EXIM_LABEL_MAX);
485         break;
486 
487     case RDFREC_DLL:           /* DLL record */
488         RS(r.d.libname, MODLIB_NAME_MAX);
489         break;
490 
491     case RDFREC_BSS:           /* BSS reservation record */
492         if (r.r.reclen != 4) {
493             rdf_errno = RDF_ERR_RECLEN;
494             return NULL;
495         }
496         RI32(r.b.amount);
497         break;
498 
499     case RDFREC_MODNAME:       /* Module name record */
500         RS(r.m.modname, MODLIB_NAME_MAX);
501         break;
502 
503     case RDFREC_COMMON:        /* Common variable */
504         RI16(r.c.segment);
505         RI32(r.c.size);
506         RI16(r.c.align);
507         RS(r.c.label, EXIM_LABEL_MAX);
508         break;
509 
510     default:
511 #ifdef STRICT_ERRORS
512         rdf_errno = RDF_ERR_RECTYPE;    /* unknown header record */
513         return NULL;
514 #else
515         for (i = 0; i < r.g.reclen; i++)
516             RI8(r.g.data[i]);
517 #endif
518     }
519     return &r;
520 }
521 
522 /*
523  * Rewind to the beginning of the file
524  */
rdfheaderrewind(rdffile * f)525 void rdfheaderrewind(rdffile * f)
526 {
527     f->header_fp = 0;
528 }
529 
rdfnewheader(void)530 rdf_headerbuf *rdfnewheader(void)
531 {
532     rdf_headerbuf *hb = nasm_malloc(sizeof(rdf_headerbuf));
533     if (hb == NULL)
534         return NULL;
535 
536     hb->buf = newmembuf();
537     hb->nsegments = 0;
538     hb->seglength = 0;
539 
540     return hb;
541 }
542 
rdfaddheader(rdf_headerbuf * h,rdfheaderrec * r)543 int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
544 {
545 #ifndef STRICT_ERRORS
546     int i;
547 #endif
548     membufwrite(h->buf, &r->type, 1);
549     membufwrite(h->buf, &r->g.reclen, 1);
550 
551     switch (r->type) {
552     case RDFREC_GENERIC:       /* generic */
553         membufwrite(h->buf, &r->g.data, r->g.reclen);
554         break;
555     case RDFREC_RELOC:
556     case RDFREC_SEGRELOC:
557         membufwrite(h->buf, &r->r.segment, 1);
558         membufwrite(h->buf, &r->r.offset, -4);
559         membufwrite(h->buf, &r->r.length, 1);
560         membufwrite(h->buf, &r->r.refseg, -2);  /* 9 bytes written */
561         break;
562 
563     case RDFREC_IMPORT:        /* import */
564     case RDFREC_FARIMPORT:
565         membufwrite(h->buf, &r->i.flags, 1);
566         membufwrite(h->buf, &r->i.segment, -2);
567         membufwrite(h->buf, &r->i.label, strlen(r->i.label) + 1);
568         break;
569 
570     case RDFREC_GLOBAL:        /* export */
571         membufwrite(h->buf, &r->e.flags, 1);
572         membufwrite(h->buf, &r->e.segment, 1);
573         membufwrite(h->buf, &r->e.offset, -4);
574         membufwrite(h->buf, &r->e.label, strlen(r->e.label) + 1);
575         break;
576 
577     case RDFREC_DLL:           /* DLL */
578         membufwrite(h->buf, &r->d.libname, strlen(r->d.libname) + 1);
579         break;
580 
581     case RDFREC_BSS:           /* BSS */
582         membufwrite(h->buf, &r->b.amount, -4);
583         break;
584 
585     case RDFREC_MODNAME:       /* Module name */
586         membufwrite(h->buf, &r->m.modname, strlen(r->m.modname) + 1);
587         break;
588 
589     default:
590 #ifdef STRICT_ERRORS
591         return rdf_errno = RDF_ERR_RECTYPE;
592 #else
593         for (i = 0; i < r->g.reclen; i++)
594             membufwrite(h->buf, r->g.data[i], 1);
595 #endif
596     }
597     return 0;
598 }
599 
rdfaddsegment(rdf_headerbuf * h,int32_t seglength)600 int rdfaddsegment(rdf_headerbuf * h, int32_t seglength)
601 {
602     h->nsegments++;
603     h->seglength += seglength;
604     return 0;
605 }
606 
rdfwriteheader(FILE * fp,rdf_headerbuf * h)607 int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
608 {
609     int32_t l, l2;
610 
611     nasm_write(RDOFFId, strlen(RDOFFId), fp);
612 
613     l = membuflength(h->buf);
614     l2 = l + 14 + 10 * h->nsegments + h->seglength;
615     fwriteint32_t(l, fp);
616     fwriteint32_t(l2, fp);
617 
618     membufdump(h->buf, fp);
619 
620     return 0;                   /* no error handling in here... CHANGE THIS! */
621 }
622 
rdfdoneheader(rdf_headerbuf * h)623 void rdfdoneheader(rdf_headerbuf * h)
624 {
625     freemembuf(h->buf);
626     nasm_free(h);
627 }
628