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.
9 /* TODO: The functions in this module assume they are running
10 * on a little-endian machine. This should be fixed to
21 #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
22 #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), \
25 /* ========================================================================
26 * Code for memory buffers (for delayed writing of header until we know
28 * ======================================================================== */
31 memorybuffer
* newmembuf(){
34 t
= malloc(sizeof(memorybuffer
));
41 void membufwrite(memorybuffer
*b
, void *data
, int bytes
) {
45 if (b
->next
) { /* memory buffer full - use next buffer */
46 membufwrite(b
->next
,data
,bytes
);
49 if ((bytes
< 0 && b
->length
- bytes
> BUF_BLOCK_LEN
)
50 || (bytes
> 0 && b
->length
+ bytes
> BUF_BLOCK_LEN
)) {
52 /* buffer full and no next allocated... allocate and initialise next
55 b
->next
= newmembuf();
56 membufwrite(b
->next
,data
,bytes
);
60 case -4: /* convert to little-endian */
62 b
->buffer
[b
->length
++] = l
& 0xFF;
64 b
->buffer
[b
->length
++] = l
& 0xFF;
66 b
->buffer
[b
->length
++] = l
& 0xFF;
68 b
->buffer
[b
->length
++] = l
& 0xFF;
72 w
= * (int16
*) data
;
73 b
->buffer
[b
->length
++] = w
& 0xFF;
75 b
->buffer
[b
->length
++] = w
& 0xFF;
80 b
->buffer
[b
->length
++] = *(* (unsigned char **) &data
);
82 (* (unsigned char **) &data
)++ ;
88 void membufdump(memorybuffer
*b
,FILE *fp
)
92 fwrite (b
->buffer
, 1, b
->length
, fp
);
94 membufdump(b
->next
,fp
);
97 int membuflength(memorybuffer
*b
)
100 return b
->length
+ membuflength(b
->next
);
103 void freemembuf(memorybuffer
*b
)
110 /* =========================================================================
111 General purpose routines and variables used by the library functions
112 ========================================================================= */
114 long translatelong(long in
) { /* translate from little endian to
115 local representation */
119 i
= (unsigned char *)&in
;
128 const char *RDOFFId
= "RDOFF1"; /* written to the start of RDOFF files */
130 const char *rdf_errors
[7] = {
131 "no error occurred","could not open file","invalid file format",
132 "error reading file","unknown error","header not read",
137 /* ========================================================================
138 The library functions
139 ======================================================================== */
141 int rdfopen(rdffile
*f
, const char *name
)
145 fp
= fopen(name
,"rb");
146 if (!fp
) return rdf_errno
= 1; /* error 1: file open error */
148 return rdfopenhere(f
,fp
,NULL
,"");
151 int rdfopenhere(rdffile
*f
, FILE *fp
, int *refcount
, char *name
)
156 if (translatelong(0x01020304) != 0x01020304)
157 { /* fix this to be portable! */
158 fputs("*** this program requires a little endian machine\n",stderr
);
159 fprintf(stderr
,"01020304h = %08lxh\n",translatelong(0x01020304));
166 fread(buf
,6,1,f
->fp
); /* read header */
169 if (strcmp(buf
,RDOFFId
)) {
171 return rdf_errno
= 2; /* error 2: invalid file format */
174 if (fread(&f
->header_len
,1,4,f
->fp
) != 4) {
176 return rdf_errno
= 3; /* error 3: file read error */
179 f
->header_ofs
= ftell(f
->fp
);
181 if (fseek(f
->fp
,f
->header_len
,SEEK_CUR
)) {
183 return rdf_errno
= 2; /* seek past end of file...? */
186 if (fread(&f
->code_len
,1,4,f
->fp
) != 4) {
188 return rdf_errno
= 3;
191 f
->code_ofs
= ftell(f
->fp
);
192 if (fseek(f
->fp
,f
->code_len
,SEEK_CUR
)) {
194 return rdf_errno
= 2;
197 if (fread(&f
->data_len
,1,4,f
->fp
) != 4) {
199 return rdf_errno
= 3;
202 f
->data_ofs
= ftell(f
->fp
);
203 fseek(f
->fp
,initpos
,SEEK_SET
);
204 f
->header_loc
= NULL
;
206 f
->name
= newstr(name
);
207 f
->refcount
= refcount
;
208 if (refcount
) (*refcount
)++;
212 int rdfclose(rdffile
*f
)
214 if (! f
->refcount
|| ! *--f
->refcount
)
221 void rdfperror(const char *app
,const char *name
)
223 fprintf(stderr
,"%s:%s: %s\n",app
,name
,rdf_errors
[rdf_errno
]);
224 if (rdf_errno
== 1 || rdf_errno
== 3)
231 int rdfloadseg(rdffile
*f
,int segment
,void *buffer
)
238 fpos
= f
->header_ofs
;
239 slen
= f
->header_len
;
240 f
->header_loc
= (char *)buffer
;
256 if (fseek(f
->fp
,fpos
,SEEK_SET
))
257 return rdf_errno
= 4;
259 if (fread(buffer
,1,slen
,f
->fp
) != slen
)
260 return rdf_errno
= 3;
265 /* Macros for reading integers from header in memory */
267 #define RI8(v) v = f->header_loc[f->header_fp++]
268 #define RI16(v) { v = (f->header_loc[f->header_fp] + \
269 (f->header_loc[f->header_fp+1] << 8)); \
272 #define RI32(v) { v = (f->header_loc[f->header_fp] + \
273 (f->header_loc[f->header_fp+1] << 8) + \
274 (f->header_loc[f->header_fp+2] << 16) + \
275 (f->header_loc[f->header_fp+3] << 24)); \
278 #define RS(str,max) { for(i=0;i<max;i++){\
279 RI8(str[i]); if (!str[i]) break;} str[i]=0; }
281 rdfheaderrec
*rdfgetheaderrec(rdffile
*f
)
283 static rdfheaderrec r
;
286 if (!f
->header_loc
) {
291 if (f
->header_fp
>= f
->header_len
) return 0;
295 case 1: /* Relocation record */
302 case 2: /* Imported symbol record */
307 case 3: /* Exported symbol record */
313 case 4: /* DLL record */
317 case 5: /* BSS reservation record */
322 rdf_errno
= 2; /* invalid file */
328 void rdfheaderrewind(rdffile
*f
)
334 rdf_headerbuf
* rdfnewheader(void)
339 int rdfaddheader(rdf_headerbuf
* h
, rdfheaderrec
* r
)
344 membufwrite(h
,&r
->type
,1);
345 membufwrite(h
,&r
->r
.segment
,1);
346 membufwrite(h
,&r
->r
.offset
,-4);
347 membufwrite(h
,&r
->r
.length
,1);
348 membufwrite(h
,&r
->r
.refseg
,-2); /* 9 bytes written */
352 membufwrite(h
,&r
->type
,1);
353 membufwrite(h
,&r
->i
.segment
,-2);
354 membufwrite(h
,&r
->i
.label
,strlen(r
->i
.label
) + 1);
358 membufwrite(h
,&r
->type
,1);
359 membufwrite(h
,&r
->e
.segment
,1);
360 membufwrite(h
,&r
->e
.offset
,-4);
361 membufwrite(h
,&r
->e
.label
,strlen(r
->e
.label
) + 1);
365 membufwrite(h
,&r
->type
,1);
366 membufwrite(h
,&r
->d
.libname
,strlen(r
->d
.libname
) + 1);
370 membufwrite(h
,&r
->type
,1);
371 membufwrite(h
,&r
->b
.amount
,-4);
375 return (rdf_errno
= 2);
380 int rdfwriteheader(FILE * fp
, rdf_headerbuf
* h
)
384 fwrite (RDOFFId
, 1, strlen(RDOFFId
), fp
) ;
386 l
= translatelong ( membuflength (h
) );
387 fwrite (&l
, 4, 1, fp
);
391 return 0; /* no error handling in here... CHANGE THIS! */
394 void rdfdoneheader(rdf_headerbuf
* h
)