summaryrefslogtreecommitdiff
path: root/rdoff/rdoff.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-04-30 20:51:32 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-04-30 20:51:32 +0000
commitea6e34db64c7da7cb885197316c6b5e7d048bdb9 (patch)
tree78e728348f8fe09e394a51c3617e6261de0f4001 /rdoff/rdoff.c
downloadnasm-ea6e34db64c7da7cb885197316c6b5e7d048bdb9.tar.gz
NASM 0.91nasm-0.91
Diffstat (limited to 'rdoff/rdoff.c')
-rw-r--r--rdoff/rdoff.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/rdoff/rdoff.c b/rdoff/rdoff.c
new file mode 100644
index 00000000..9a969ad0
--- /dev/null
+++ b/rdoff/rdoff.c
@@ -0,0 +1,367 @@
+/* rdoff.c library of routines for manipulating rdoff files
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/* TODO: The functions in this module assume they are running
+ * on a little-endian machine. This should be fixed to
+ * make it portable.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rdoff.h"
+
+/* ========================================================================
+ * Code for memory buffers (for delayed writing of header until we know
+ * how long it is).
+ * ======================================================================== */
+
+
+memorybuffer * newmembuf(){
+ memorybuffer * t;
+
+ t = malloc(sizeof(memorybuffer));
+
+ t->length = 0;
+ t->next = NULL;
+ return t;
+}
+
+void membufwrite(memorybuffer *b, void *data, int bytes) {
+ int16 w;
+ long l;
+
+ if (b->next) { /* memory buffer full - use next buffer */
+ membufwrite(b->next,data,bytes);
+ return;
+ }
+ if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
+ || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
+
+ /* buffer full and no next allocated... allocate and initialise next
+ * buffer */
+
+ b->next = newmembuf();
+ membufwrite(b->next,data,bytes);
+ }
+
+ switch(bytes) {
+ case -4: /* convert to little-endian */
+ l = * (long *) data ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ break;
+
+ case -2:
+ w = * (int16 *) data ;
+ b->buffer[b->length++] = w & 0xFF;
+ w >>= 8 ;
+ b->buffer[b->length++] = w & 0xFF;
+ break;
+
+ default:
+ while(bytes--) {
+ b->buffer[b->length++] = *(* (unsigned char **) &data);
+
+ (* (unsigned char **) &data)++ ;
+ }
+ break;
+ }
+}
+
+void membufdump(memorybuffer *b,FILE *fp)
+{
+ if (!b) return;
+
+ fwrite (b->buffer, 1, b->length, fp);
+
+ membufdump(b->next,fp);
+}
+
+int membuflength(memorybuffer *b)
+{
+ if (!b) return 0;
+ return b->length + membuflength(b->next);
+}
+
+void freemembuf(memorybuffer *b)
+{
+ if (!b) return;
+ freemembuf(b->next);
+ free(b);
+}
+
+/* =========================================================================
+ General purpose routines and variables used by the library functions
+ ========================================================================= */
+
+long translatelong(long in) { /* translate from little endian to
+ local representation */
+ long r;
+ unsigned char *i;
+
+ i = (unsigned char *)&in;
+ r = i[3];
+ r = (r << 8) + i[2];
+ r = (r << 8) + i[1];
+ r = (r << 8) + *i;
+
+ return r;
+}
+
+const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */
+
+const char *rdf_errors[7] = {
+ "no error occurred","could not open file","invalid file format",
+ "error reading file","unknown error","header not read",
+ "out of memory"};
+
+int rdf_errno = 0;
+
+/* ========================================================================
+ The library functions
+ ======================================================================== */
+
+int rdfopen(rdffile *f, const char *name)
+{
+ char buf[8];
+
+ if (translatelong(0x01020304) != 0x01020304)
+ { /* fix this to be portable! */
+ fputs("*** this program requires a little endian machine\n",stderr);
+ fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304));
+ exit(3);
+ }
+
+
+ f->fp = fopen(name,"rb");
+ if (!f->fp) return rdf_errno = 1; /* error 1: file open error */
+
+ fread(buf,6,1,f->fp); /* read header */
+ buf[6] = 0;
+
+ if (strcmp(buf,RDOFFId)) {
+ fclose(f->fp);
+ return rdf_errno = 2; /* error 2: invalid file format */
+ }
+
+ if (fread(&f->header_len,1,4,f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = 3; /* error 3: file read error */
+ }
+
+ if (fseek(f->fp,f->header_len,SEEK_CUR)) {
+ fclose(f->fp);
+ return rdf_errno = 2; /* seek past end of file...? */
+ }
+
+ if (fread(&f->code_len,1,4,f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = 3;
+ }
+
+ f->code_ofs = ftell(f->fp);
+ if (fseek(f->fp,f->code_len,SEEK_CUR)) {
+ fclose(f->fp);
+ return rdf_errno = 2;
+ }
+
+ if (fread(&f->data_len,1,4,f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = 3;
+ }
+
+ f->data_ofs = ftell(f->fp);
+ rewind(f->fp);
+ f->header_loc = NULL;
+ return 0;
+}
+
+int rdfclose(rdffile *f)
+{
+ fclose(f->fp);
+ return 0;
+}
+
+void rdfperror(const char *app,const char *name)
+{
+ fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]);
+}
+
+int rdfloadseg(rdffile *f,int segment,void *buffer)
+{
+ long fpos;
+ long slen;
+
+ switch(segment) {
+ case RDOFF_HEADER:
+ fpos = 10;
+ slen = f->header_len;
+ f->header_loc = (char *)buffer;
+ f->header_fp = 0;
+ break;
+ case RDOFF_CODE:
+ fpos = f->code_ofs;
+ slen = f->code_len;
+ break;
+ case RDOFF_DATA:
+ fpos = f->data_ofs;
+ slen = f->data_len;
+ break;
+ default:
+ fpos = 0;
+ slen = 0;
+ }
+
+ if (fseek(f->fp,fpos,SEEK_SET))
+ return rdf_errno = 4;
+
+ if (fread(buffer,1,slen,f->fp) != slen)
+ return rdf_errno = 3;
+
+ return 0;
+}
+
+/* Macros for reading integers from header in memory */
+
+#define RI8(v) v = f->header_loc[f->header_fp++]
+#define RI16(v) { v = (f->header_loc[f->header_fp] + \
+ (f->header_loc[f->header_fp+1] << 8)); \
+ f->header_fp += 2; }
+
+#define RI32(v) { v = (f->header_loc[f->header_fp] + \
+ (f->header_loc[f->header_fp+1] << 8) + \
+ (f->header_loc[f->header_fp+2] << 16) + \
+ (f->header_loc[f->header_fp+3] << 24)); \
+ f->header_fp += 4; }
+
+#define RS(str,max) { for(i=0;i<max;i++){\
+ RI8(str[i]); if (!str[i]) break;} str[i]=0; }
+
+rdfheaderrec *rdfgetheaderrec(rdffile *f)
+{
+ static rdfheaderrec r;
+ int i;
+
+ if (!f->header_loc) {
+ rdf_errno = 5;
+ return NULL;
+ }
+
+ if (f->header_fp >= f->header_len) return 0;
+
+ RI8(r.type);
+ switch(r.type) {
+ case 1: /* Relocation record */
+ RI8(r.r.segment);
+ RI32(r.r.offset);
+ RI8(r.r.length);
+ RI16(r.r.refseg);
+ break;
+
+ case 2: /* Imported symbol record */
+ RI16(r.i.segment);
+ RS(r.i.label,32);
+ break;
+
+ case 3: /* Exported symbol record */
+ RI8(r.e.segment);
+ RI32(r.e.offset);
+ RS(r.e.label,32);
+ break;
+
+ case 4: /* DLL record */
+ RS(r.d.libname,127);
+ break;
+
+ case 5: /* BSS reservation record */
+ RI32(r.b.amount);
+ break;
+
+ default:
+ rdf_errno = 2; /* invalid file */
+ return NULL;
+ }
+ return &r;
+}
+
+void rdfheaderrewind(rdffile *f)
+{
+ f->header_fp = 0;
+}
+
+
+rdf_headerbuf * rdfnewheader(void)
+{
+ return newmembuf();
+}
+
+int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
+{
+ switch (r->type)
+ {
+ case 1:
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->r.segment,1);
+ membufwrite(h,&r->r.offset,-4);
+ membufwrite(h,&r->r.length,1);
+ membufwrite(h,&r->r.refseg,-2); /* 9 bytes written */
+ break;
+
+ case 2: /* import */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->i.segment,-2);
+ membufwrite(h,&r->i.label,strlen(r->i.label) + 1);
+ break ;
+
+ case 3: /* export */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->e.segment,1);
+ membufwrite(h,&r->e.offset,-4);
+ membufwrite(h,&r->e.label,strlen(r->e.label) + 1);
+ break ;
+
+ case 4: /* DLL */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1);
+ break ;
+
+ case 5: /* BSS */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->b.amount,-4);
+ break ;
+
+ default:
+ return (rdf_errno = 2);
+ }
+ return 0;
+}
+
+int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
+{
+ long l;
+
+ fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
+
+ l = translatelong ( membuflength (h) );
+ fwrite (&l, 4, 1, fp);
+
+ membufdump(h, fp);
+
+ return 0; /* no error handling in here... CHANGE THIS! */
+}
+
+void rdfdoneheader(rdf_headerbuf * h)
+{
+ freemembuf(h);
+}