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