dwarf: don't emit a dummy .debug_loc section
[nasm.git] / rdoff / rdoff.c
blob77f2b42f5a2c154a4de157a9c5ded0b657d61c8e
1 /* ----------------------------------------------------------------------- *
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.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
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.
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.
32 * ----------------------------------------------------------------------- */
35 * rdoff.c library of routines for manipulating rdoff files
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.
43 #include "compiler.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <errno.h>
49 #include "rdfutils.h"
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'.
57 #define STRICT_ERRORS
59 /* ========================================================================
60 * Code for memory buffers (for delayed writing of header until we know
61 * how int32_t it is).
62 * ======================================================================== */
64 static memorybuffer *newmembuf(void)
66 memorybuffer *t;
68 t = nasm_malloc(sizeof(memorybuffer));
69 if (!t)
70 return NULL;
72 t->length = 0;
73 t->next = NULL;
74 return t;
77 static void membufwrite(memorybuffer * const b, void *data, int bytes)
79 uint16_t w;
80 int32_t l;
81 char *c;
83 if (b->next) { /* memory buffer full - use next buffer */
84 membufwrite(b->next, data, bytes);
85 return;
88 if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
89 || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
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;
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;
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;
117 default:
118 c = data;
119 while (bytes--)
120 b->buffer[b->length++] = *c++;
121 break;
125 static void membufdump(memorybuffer * b, FILE * fp)
127 if (!b)
128 return;
130 nasm_write(b->buffer, b->length, fp);
131 membufdump(b->next, fp);
134 static int membuflength(memorybuffer * b)
136 if (!b)
137 return 0;
138 return b->length + membuflength(b->next);
141 static void freemembuf(memorybuffer * b)
143 if (!b)
144 return;
145 freemembuf(b->next);
146 nasm_free(b);
149 /* =========================================================================
150 General purpose routines and variables used by the library functions
151 ========================================================================= */
154 * translateint32_t() and translateint16_t()
156 * translate from little endian to local representation
158 int32_t translateint32_t(int32_t in)
160 int32_t r;
161 uint8_t *i;
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;
169 return r;
172 uint16_t translateint16_t(uint16_t in)
174 uint16_t r;
175 uint8_t *i;
177 i = (uint8_t *)&in;
178 r = (i[1] << 8) + i[0];
180 return r;
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"
190 /* Get a textual string describing the segment type */
191 char *translatesegmenttype(uint16_t type)
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";
208 /* This signature is written to the start of RDOFF files */
209 const char *RDOFFId = RDOFF2_SIGNATURE;
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"
226 int rdf_errno = 0;
228 /* ========================================================================
229 * Hook for nasm_error() to work
230 * ======================================================================== */
231 void nasm_verror(errflags severity, const char *fmt, va_list val)
233 severity &= ERR_MASK;
235 vfprintf(stderr, fmt, val);
236 if (severity >= ERR_FATAL)
237 exit(severity - ERR_FATAL + 1);
240 fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list val)
242 nasm_verror(severity, fmt, val);
243 abort();
246 void rdoff_init(void)
251 /* ========================================================================
252 The library functions
253 ======================================================================== */
255 int rdfopen(rdffile * f, const char *name)
257 FILE *fp;
259 fp = fopen(name, "rb");
260 if (!fp)
261 return rdf_errno = RDF_ERR_OPEN;
263 return rdfopenhere(f, fp, NULL, name);
266 int rdfopenhere(rdffile * f, FILE * fp, int *refcount, const char *name)
268 char buf[8];
269 int32_t initpos;
270 int32_t l;
271 uint16_t s;
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);
281 f->fp = fp;
282 initpos = ftell(fp);
284 /* read header */
285 if (fread(buf, 1, 6, f->fp) != 6) {
286 fclose(f->fp);
287 return rdf_errno = RDF_ERR_READ;
289 buf[6] = 0;
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;
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;
304 f->header_ofs = ftell(f->fp);
305 f->eof_offset = f->header_ofs + translateint32_t(l) - 4;
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...? */
312 if (fread(&s, 1, 2, f->fp) != 2) {
313 fclose(f->fp);
314 return rdf_errno = RDF_ERR_READ;
317 f->nsegs = 0;
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;
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;
333 f->nsegs++;
335 if (fread(&s, 1, 2, f->fp) != 2) {
336 fclose(f->fp);
337 return rdf_errno = RDF_ERR_READ;
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);
345 fseek(f->fp, initpos, SEEK_SET);
346 f->header_loc = NULL;
348 f->name = nasm_strdup(name);
349 f->refcount = refcount;
350 if (refcount)
351 (*refcount)++;
352 return RDF_OK;
355 int rdfclose(rdffile * f)
357 if (!f->refcount || !--(*f->refcount)) {
358 fclose(f->fp);
359 f->fp = NULL;
361 nasm_free(f->name);
363 return 0;
367 * Print the message for last error (from rdf_errno)
369 void rdfperror(const char *app, const char *name)
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);
378 * Find the segment by its number.
379 * Returns segment array index, or -1 if segment with such number was not found.
381 int rdffindsegment(rdffile * f, int segno)
383 int i;
384 for (i = 0; i < f->nsegs; i++)
385 if (f->seg[i].number == segno)
386 return i;
387 return -1;
391 * Load the segment. Returns status.
393 int rdfloadseg(rdffile * f, int segment, void *buffer)
395 int32_t fpos;
396 size_t slen;
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;
415 if (fseek(f->fp, fpos, SEEK_SET))
416 return rdf_errno = RDF_ERR_UNKNOWN;
418 if (fread(buffer, 1, slen, f->fp) != slen)
419 return rdf_errno = RDF_ERR_READ;
421 return RDF_OK;
424 /* Macros for reading integers from header in memory */
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; }
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; }
437 #define RS(str,max) { for(i=0;i<max;i++){\
438 RI8(str[i]); if (!str[i]) break;} str[i]=0; }
441 * Read a header record.
442 * Returns the address of record, or NULL in case of error.
444 rdfheaderrec *rdfgetheaderrec(rdffile * f)
446 static rdfheaderrec r;
447 int i;
449 if (!f->header_loc) {
450 rdf_errno = RDF_ERR_HEADER;
451 return NULL;
454 if (f->header_fp >= f->header_len)
455 return 0;
457 RI8(r.type);
458 RI8(r.g.reclen);
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;
467 RI8(r.r.segment);
468 RI32(r.r.offset);
469 RI8(r.r.length);
470 RI16(r.r.refseg);
471 break;
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;
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;
487 case RDFREC_DLL: /* DLL record */
488 RS(r.d.libname, MODLIB_NAME_MAX);
489 break;
491 case RDFREC_BSS: /* BSS reservation record */
492 if (r.r.reclen != 4) {
493 rdf_errno = RDF_ERR_RECLEN;
494 return NULL;
496 RI32(r.b.amount);
497 break;
499 case RDFREC_MODNAME: /* Module name record */
500 RS(r.m.modname, MODLIB_NAME_MAX);
501 break;
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;
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
519 return &r;
523 * Rewind to the beginning of the file
525 void rdfheaderrewind(rdffile * f)
527 f->header_fp = 0;
530 rdf_headerbuf *rdfnewheader(void)
532 rdf_headerbuf *hb = nasm_malloc(sizeof(rdf_headerbuf));
533 if (hb == NULL)
534 return NULL;
536 hb->buf = newmembuf();
537 hb->nsegments = 0;
538 hb->seglength = 0;
540 return hb;
543 int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
545 #ifndef STRICT_ERRORS
546 int i;
547 #endif
548 membufwrite(h->buf, &r->type, 1);
549 membufwrite(h->buf, &r->g.reclen, 1);
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;
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;
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;
577 case RDFREC_DLL: /* DLL */
578 membufwrite(h->buf, &r->d.libname, strlen(r->d.libname) + 1);
579 break;
581 case RDFREC_BSS: /* BSS */
582 membufwrite(h->buf, &r->b.amount, -4);
583 break;
585 case RDFREC_MODNAME: /* Module name */
586 membufwrite(h->buf, &r->m.modname, strlen(r->m.modname) + 1);
587 break;
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
597 return 0;
600 int rdfaddsegment(rdf_headerbuf * h, int32_t seglength)
602 h->nsegments++;
603 h->seglength += seglength;
604 return 0;
607 int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
609 int32_t l, l2;
611 nasm_write(RDOFFId, strlen(RDOFFId), fp);
613 l = membuflength(h->buf);
614 l2 = l + 14 + 10 * h->nsegments + h->seglength;
615 fwriteint32_t(l, fp);
616 fwriteint32_t(l2, fp);
618 membufdump(h->buf, fp);
620 return 0; /* no error handling in here... CHANGE THIS! */
623 void rdfdoneheader(rdf_headerbuf * h)
625 freemembuf(h->buf);
626 nasm_free(h);