Apply Nindent to all .c and .h files
[nasm/avx512.git] / rdoff / rdoff.c
blob8f19702dd45992340457faeed09b7350ae542993
1 /* rdoff.c library of routines for manipulating rdoff files
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
8 * Permission to use this file in your own projects is granted, as long
9 * as acknowledgement is given in an appropriate manner to its authors,
10 * with instructions of how to obtain a copy via ftp.
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.
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
23 #define RDOFF_UTILS
25 #include "rdoff.h"
27 #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
28 #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), \
29 s1),s2)
32 * Comment this out to allow the module to read & write header record types
33 * that it isn't aware of. With this defined, unrecognised header records
34 * will generate error number 8, reported as 'unknown extended header record'.
37 #define STRICT_ERRORS
39 /* ========================================================================
40 * Code for memory buffers (for delayed writing of header until we know
41 * how long it is).
42 * ======================================================================== */
44 memorybuffer *newmembuf()
46 memorybuffer *t;
48 t = malloc(sizeof(memorybuffer));
49 if (!t)
50 return NULL;
52 t->length = 0;
53 t->next = NULL;
54 return t;
57 void membufwrite(memorybuffer * const b, void *data, int bytes)
59 uint16 w;
60 long l;
62 if (b->next) { /* memory buffer full - use next buffer */
63 membufwrite(b->next, data, bytes);
64 return;
67 if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
68 || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
70 /* buffer full and no next allocated... allocate and initialise next
71 * buffer */
72 b->next = newmembuf();
73 membufwrite(b->next, data, bytes);
74 return;
77 switch (bytes) {
78 case -4: /* convert to little-endian */
79 l = *(long *)data;
80 b->buffer[b->length++] = l & 0xFF;
81 l >>= 8;
82 b->buffer[b->length++] = l & 0xFF;
83 l >>= 8;
84 b->buffer[b->length++] = l & 0xFF;
85 l >>= 8;
86 b->buffer[b->length++] = l & 0xFF;
87 break;
89 case -2:
90 w = *(uint16 *) data;
91 b->buffer[b->length++] = w & 0xFF;
92 w >>= 8;
93 b->buffer[b->length++] = w & 0xFF;
94 break;
96 default:
97 while (bytes--) {
98 b->buffer[b->length++] = *(*(unsigned char **)&data);
100 (*(unsigned char **)&data)++;
102 break;
106 void membufdump(memorybuffer * b, FILE * fp)
108 if (!b)
109 return;
111 fwrite(b->buffer, 1, b->length, fp);
113 membufdump(b->next, fp);
116 int membuflength(memorybuffer * b)
118 if (!b)
119 return 0;
120 return b->length + membuflength(b->next);
123 void freemembuf(memorybuffer * b)
125 if (!b)
126 return;
127 freemembuf(b->next);
128 free(b);
131 /* =========================================================================
132 General purpose routines and variables used by the library functions
133 ========================================================================= */
136 * translatelong() and translateshort()
138 * translate from little endian to local representation
140 long translatelong(long in)
142 long r;
143 unsigned char *i;
145 i = (unsigned char *)&in;
146 r = i[3];
147 r = (r << 8) + i[2];
148 r = (r << 8) + i[1];
149 r = (r << 8) + *i;
151 return r;
154 uint16 translateshort(uint16 in)
156 uint16 r;
157 unsigned char *i;
159 i = (unsigned char *)&in;
160 r = (i[1] << 8) + i[0];
162 return r;
165 /* Segment types */
166 static char *knownsegtypes[8] = {
167 "NULL", "text", "data", "object comment",
168 "linked comment", "loader comment",
169 "symbolic debug", "line number debug"
172 /* Get a textual string describing the segment type */
173 char *translatesegmenttype(uint16 type)
175 if (type < 8)
176 return knownsegtypes[type];
177 if (type < 0x0020)
178 return "reserved";
179 if (type < 0x1000)
180 return "reserved - Moscow";
181 if (type < 0x8000)
182 return "reserved - system dependant";
183 if (type < 0xFFFF)
184 return "reserved - other";
185 if (type == 0xFFFF)
186 return "invalid type code";
187 return "type code out of range";
190 /* This signature is written to the start of RDOFF files */
191 const char *RDOFFId = RDOFF2_SIGNATURE;
193 /* Error messages. Must correspond to the codes defined in rdoff.h */
194 const char *rdf_errors[11] = {
195 /* 0 */ "no error occurred",
196 /* 1 */ "could not open file",
197 /* 2 */ "invalid file format",
198 /* 3 */ "error reading file",
199 /* 4 */ "unknown error",
200 /* 5 */ "header not read",
201 /* 6 */ "out of memory",
202 /* 7 */ "RDOFF v1 not supported",
203 /* 8 */ "unknown extended header record",
204 /* 9 */ "header record of known type but unknown length",
205 /* 10 */ "no such segment"
208 int rdf_errno = 0;
210 /* ========================================================================
211 The library functions
212 ======================================================================== */
214 int rdfopen(rdffile * f, const char *name)
216 FILE *fp;
218 fp = fopen(name, "rb");
219 if (!fp)
220 return rdf_errno = RDF_ERR_OPEN;
222 return rdfopenhere(f, fp, NULL, name);
225 int rdfopenhere(rdffile * f, FILE * fp, int *refcount, const char *name)
227 char buf[8];
228 long initpos;
229 long l;
230 uint16 s;
232 if (translatelong(0x01020304) != 0x01020304) {
233 /* fix this to be portable! */
234 fputs("*** this program requires a little endian machine\n",
235 stderr);
236 fprintf(stderr, "01020304h = %08lxh\n", translatelong(0x01020304));
237 exit(3);
240 f->fp = fp;
241 initpos = ftell(fp);
243 fread(buf, 6, 1, f->fp); /* read header */
244 buf[6] = 0;
246 if (strcmp(buf, RDOFFId)) {
247 fclose(f->fp);
248 if (!strcmp(buf, "RDOFF1"))
249 return rdf_errno = RDF_ERR_VER;
250 return rdf_errno = RDF_ERR_FORMAT;
253 if (fread(&l, 1, 4, f->fp) != 4
254 || fread(&f->header_len, 1, 4, f->fp) != 4) {
255 fclose(f->fp);
256 return rdf_errno = RDF_ERR_READ;
259 f->header_ofs = ftell(f->fp);
260 f->eof_offset = f->header_ofs + translatelong(l) - 4;
262 if (fseek(f->fp, f->header_len, SEEK_CUR)) {
263 fclose(f->fp);
264 return rdf_errno = RDF_ERR_FORMAT; /* seek past end of file...? */
267 if (fread(&s, 1, 2, f->fp) != 2) {
268 fclose(f->fp);
269 return rdf_errno = RDF_ERR_READ;
272 f->nsegs = 0;
274 while (s != 0) {
275 f->seg[f->nsegs].type = s;
276 if (fread(&f->seg[f->nsegs].number, 1, 2, f->fp) != 2 ||
277 fread(&f->seg[f->nsegs].reserved, 1, 2, f->fp) != 2 ||
278 fread(&f->seg[f->nsegs].length, 1, 4, f->fp) != 4) {
279 fclose(f->fp);
280 return rdf_errno = RDF_ERR_READ;
283 f->seg[f->nsegs].offset = ftell(f->fp);
284 if (fseek(f->fp, f->seg[f->nsegs].length, SEEK_CUR)) {
285 fclose(f->fp);
286 return rdf_errno = RDF_ERR_FORMAT;
288 f->nsegs++;
290 if (fread(&s, 1, 2, f->fp) != 2) {
291 fclose(f->fp);
292 return rdf_errno = RDF_ERR_READ;
296 if (f->eof_offset != ftell(f->fp) + 8) { /* +8 = skip null segment header */
297 fprintf(stderr, "warning: eof_offset [%ld] and actual eof offset "
298 "[%ld] don't match\n", f->eof_offset, ftell(f->fp) + 8);
300 fseek(f->fp, initpos, SEEK_SET);
301 f->header_loc = NULL;
303 f->name = newstr(name);
304 f->refcount = refcount;
305 if (refcount)
306 (*refcount)++;
307 return RDF_OK;
310 int rdfclose(rdffile * f)
312 if (!f->refcount || !--(*f->refcount)) {
313 fclose(f->fp);
314 f->fp = NULL;
316 free(f->name);
318 return 0;
322 * Print the message for last error (from rdf_errno)
324 void rdfperror(const char *app, const char *name)
326 fprintf(stderr, "%s:%s: %s\n", app, name, rdf_errors[rdf_errno]);
327 if (rdf_errno == RDF_ERR_OPEN || rdf_errno == RDF_ERR_READ) {
328 perror(app);
333 * Find the segment by its number.
334 * Returns segment array index, or -1 if segment with such number was not found.
336 int rdffindsegment(rdffile * f, int segno)
338 int i;
339 for (i = 0; i < f->nsegs; i++)
340 if (f->seg[i].number == segno)
341 return i;
342 return -1;
346 * Load the segment. Returns status.
348 int rdfloadseg(rdffile * f, int segment, void *buffer)
350 long fpos, slen;
352 switch (segment) {
353 case RDOFF_HEADER:
354 fpos = f->header_ofs;
355 slen = f->header_len;
356 f->header_loc = (byte *) buffer;
357 f->header_fp = 0;
358 break;
359 default:
360 if (segment < f->nsegs) {
361 fpos = f->seg[segment].offset;
362 slen = f->seg[segment].length;
363 f->seg[segment].data = (byte *) buffer;
364 } else {
365 return rdf_errno = RDF_ERR_SEGMENT;
369 if (fseek(f->fp, fpos, SEEK_SET))
370 return rdf_errno = RDF_ERR_UNKNOWN;
372 if (fread(buffer, 1, slen, f->fp) != slen)
373 return rdf_errno = RDF_ERR_READ;
375 return RDF_OK;
378 /* Macros for reading integers from header in memory */
380 #define RI8(v) v = f->header_loc[f->header_fp++]
381 #define RI16(v) { v = (f->header_loc[f->header_fp] + \
382 (f->header_loc[f->header_fp+1] << 8)); \
383 f->header_fp += 2; }
385 #define RI32(v) { v = (f->header_loc[f->header_fp] + \
386 (f->header_loc[f->header_fp+1] << 8) + \
387 (f->header_loc[f->header_fp+2] << 16) + \
388 (f->header_loc[f->header_fp+3] << 24)); \
389 f->header_fp += 4; }
391 #define RS(str,max) { for(i=0;i<max;i++){\
392 RI8(str[i]); if (!str[i]) break;} str[i]=0; }
395 * Read a header record.
396 * Returns the address of record, or NULL in case of error.
398 rdfheaderrec *rdfgetheaderrec(rdffile * f)
400 static rdfheaderrec r;
401 int i;
403 if (!f->header_loc) {
404 rdf_errno = RDF_ERR_HEADER;
405 return NULL;
408 if (f->header_fp >= f->header_len)
409 return 0;
411 RI8(r.type);
412 RI8(r.g.reclen);
414 switch (r.type) {
415 case RDFREC_RELOC: /* Relocation record */
416 case RDFREC_SEGRELOC:
417 if (r.r.reclen != 8) {
418 rdf_errno = RDF_ERR_RECLEN;
419 return NULL;
421 RI8(r.r.segment);
422 RI32(r.r.offset);
423 RI8(r.r.length);
424 RI16(r.r.refseg);
425 break;
427 case RDFREC_IMPORT: /* Imported symbol record */
428 case RDFREC_FARIMPORT:
429 RI8(r.i.flags);
430 RI16(r.i.segment);
431 RS(r.i.label, EXIM_LABEL_MAX);
432 break;
434 case RDFREC_GLOBAL: /* Exported symbol record */
435 RI8(r.e.flags);
436 RI8(r.e.segment);
437 RI32(r.e.offset);
438 RS(r.e.label, EXIM_LABEL_MAX);
439 break;
441 case RDFREC_DLL: /* DLL record */
442 RS(r.d.libname, MODLIB_NAME_MAX);
443 break;
445 case RDFREC_BSS: /* BSS reservation record */
446 if (r.r.reclen != 4) {
447 rdf_errno = RDF_ERR_RECLEN;
448 return NULL;
450 RI32(r.b.amount);
451 break;
453 case RDFREC_MODNAME: /* Module name record */
454 RS(r.m.modname, MODLIB_NAME_MAX);
455 break;
457 case RDFREC_COMMON: /* Common variable */
458 RI16(r.c.segment);
459 RI32(r.c.size);
460 RI16(r.c.align);
461 RS(r.c.label, EXIM_LABEL_MAX);
462 break;
464 default:
465 #ifdef STRICT_ERRORS
466 rdf_errno = RDF_ERR_RECTYPE; /* unknown header record */
467 return NULL;
468 #else
469 for (i = 0; i < r.g.reclen; i++)
470 RI8(r.g.data[i]);
471 #endif
473 return &r;
477 * Rewind to the beginning of the file
479 void rdfheaderrewind(rdffile * f)
481 f->header_fp = 0;
484 rdf_headerbuf *rdfnewheader(void)
486 rdf_headerbuf *hb = malloc(sizeof(rdf_headerbuf));
487 if (hb == NULL)
488 return NULL;
490 hb->buf = newmembuf();
491 hb->nsegments = 0;
492 hb->seglength = 0;
494 return hb;
497 int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
499 #ifndef STRICT_ERRORS
500 int i;
501 #endif
502 membufwrite(h->buf, &r->type, 1);
503 membufwrite(h->buf, &r->g.reclen, 1);
505 switch (r->type) {
506 case RDFREC_GENERIC: /* generic */
507 membufwrite(h->buf, &r->g.data, r->g.reclen);
508 break;
509 case RDFREC_RELOC:
510 case RDFREC_SEGRELOC:
511 membufwrite(h->buf, &r->r.segment, 1);
512 membufwrite(h->buf, &r->r.offset, -4);
513 membufwrite(h->buf, &r->r.length, 1);
514 membufwrite(h->buf, &r->r.refseg, -2); /* 9 bytes written */
515 break;
517 case RDFREC_IMPORT: /* import */
518 case RDFREC_FARIMPORT:
519 membufwrite(h->buf, &r->i.flags, 1);
520 membufwrite(h->buf, &r->i.segment, -2);
521 membufwrite(h->buf, &r->i.label, strlen(r->i.label) + 1);
522 break;
524 case RDFREC_GLOBAL: /* export */
525 membufwrite(h->buf, &r->e.flags, 1);
526 membufwrite(h->buf, &r->e.segment, 1);
527 membufwrite(h->buf, &r->e.offset, -4);
528 membufwrite(h->buf, &r->e.label, strlen(r->e.label) + 1);
529 break;
531 case RDFREC_DLL: /* DLL */
532 membufwrite(h->buf, &r->d.libname, strlen(r->d.libname) + 1);
533 break;
535 case RDFREC_BSS: /* BSS */
536 membufwrite(h->buf, &r->b.amount, -4);
537 break;
539 case RDFREC_MODNAME: /* Module name */
540 membufwrite(h->buf, &r->m.modname, strlen(r->m.modname) + 1);
541 break;
543 default:
544 #ifdef STRICT_ERRORS
545 return rdf_errno = RDF_ERR_RECTYPE;
546 #else
547 for (i = 0; i < r->g.reclen; i++)
548 membufwrite(h->buf, r->g.data[i], 1);
549 #endif
551 return 0;
554 int rdfaddsegment(rdf_headerbuf * h, long seglength)
556 h->nsegments++;
557 h->seglength += seglength;
558 return 0;
561 int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
563 long l, l2;
565 fwrite(RDOFFId, 1, strlen(RDOFFId), fp);
567 l = membuflength(h->buf);
568 l2 = l + 14 + 10 * h->nsegments + h->seglength;
569 l = translatelong(l);
570 l2 = translatelong(l2);
571 fwrite(&l2, 4, 1, fp); /* object length */
572 fwrite(&l, 4, 1, fp); /* header length */
574 membufdump(h->buf, fp);
576 return 0; /* no error handling in here... CHANGE THIS! */
579 void rdfdoneheader(rdf_headerbuf * h)
581 freemembuf(h->buf);
582 free(h);