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
19 /* ========================================================================
20 * Code for memory buffers (for delayed writing of header until we know
22 * ======================================================================== */
25 memorybuffer
* newmembuf(){
28 t
= malloc(sizeof(memorybuffer
));
35 void membufwrite(memorybuffer
*b
, void *data
, int bytes
) {
39 if (b
->next
) { /* memory buffer full - use next buffer */
40 membufwrite(b
->next
,data
,bytes
);
43 if ((bytes
< 0 && b
->length
- bytes
> BUF_BLOCK_LEN
)
44 || (bytes
> 0 && b
->length
+ bytes
> BUF_BLOCK_LEN
)) {
46 /* buffer full and no next allocated... allocate and initialise next
49 b
->next
= newmembuf();
50 membufwrite(b
->next
,data
,bytes
);
54 case -4: /* convert to little-endian */
56 b
->buffer
[b
->length
++] = l
& 0xFF;
58 b
->buffer
[b
->length
++] = l
& 0xFF;
60 b
->buffer
[b
->length
++] = l
& 0xFF;
62 b
->buffer
[b
->length
++] = l
& 0xFF;
66 w
= * (int16
*) data
;
67 b
->buffer
[b
->length
++] = w
& 0xFF;
69 b
->buffer
[b
->length
++] = w
& 0xFF;
74 b
->buffer
[b
->length
++] = *(* (unsigned char **) &data
);
76 (* (unsigned char **) &data
)++ ;
82 void membufdump(memorybuffer
*b
,FILE *fp
)
86 fwrite (b
->buffer
, 1, b
->length
, fp
);
88 membufdump(b
->next
,fp
);
91 int membuflength(memorybuffer
*b
)
94 return b
->length
+ membuflength(b
->next
);
97 void freemembuf(memorybuffer
*b
)
104 /* =========================================================================
105 General purpose routines and variables used by the library functions
106 ========================================================================= */
108 long translatelong(long in
) { /* translate from little endian to
109 local representation */
113 i
= (unsigned char *)&in
;
122 const char *RDOFFId
= "RDOFF1"; /* written to the start of RDOFF files */
124 const char *rdf_errors
[7] = {
125 "no error occurred","could not open file","invalid file format",
126 "error reading file","unknown error","header not read",
131 /* ========================================================================
132 The library functions
133 ======================================================================== */
135 int rdfopen(rdffile
*f
, const char *name
)
139 if (translatelong(0x01020304) != 0x01020304)
140 { /* fix this to be portable! */
141 fputs("*** this program requires a little endian machine\n",stderr
);
142 fprintf(stderr
,"01020304h = %08lxh\n",translatelong(0x01020304));
147 f
->fp
= fopen(name
,"rb");
148 if (!f
->fp
) return rdf_errno
= 1; /* error 1: file open error */
150 fread(buf
,6,1,f
->fp
); /* read header */
153 if (strcmp(buf
,RDOFFId
)) {
155 return rdf_errno
= 2; /* error 2: invalid file format */
158 if (fread(&f
->header_len
,1,4,f
->fp
) != 4) {
160 return rdf_errno
= 3; /* error 3: file read error */
163 if (fseek(f
->fp
,f
->header_len
,SEEK_CUR
)) {
165 return rdf_errno
= 2; /* seek past end of file...? */
168 if (fread(&f
->code_len
,1,4,f
->fp
) != 4) {
170 return rdf_errno
= 3;
173 f
->code_ofs
= ftell(f
->fp
);
174 if (fseek(f
->fp
,f
->code_len
,SEEK_CUR
)) {
176 return rdf_errno
= 2;
179 if (fread(&f
->data_len
,1,4,f
->fp
) != 4) {
181 return rdf_errno
= 3;
184 f
->data_ofs
= ftell(f
->fp
);
186 f
->header_loc
= NULL
;
190 int rdfclose(rdffile
*f
)
196 void rdfperror(const char *app
,const char *name
)
198 fprintf(stderr
,"%s:%s: %s\n",app
,name
,rdf_errors
[rdf_errno
]);
201 int rdfloadseg(rdffile
*f
,int segment
,void *buffer
)
209 slen
= f
->header_len
;
210 f
->header_loc
= (char *)buffer
;
226 if (fseek(f
->fp
,fpos
,SEEK_SET
))
227 return rdf_errno
= 4;
229 if (fread(buffer
,1,slen
,f
->fp
) != slen
)
230 return rdf_errno
= 3;
235 /* Macros for reading integers from header in memory */
237 #define RI8(v) v = f->header_loc[f->header_fp++]
238 #define RI16(v) { v = (f->header_loc[f->header_fp] + \
239 (f->header_loc[f->header_fp+1] << 8)); \
242 #define RI32(v) { v = (f->header_loc[f->header_fp] + \
243 (f->header_loc[f->header_fp+1] << 8) + \
244 (f->header_loc[f->header_fp+2] << 16) + \
245 (f->header_loc[f->header_fp+3] << 24)); \
248 #define RS(str,max) { for(i=0;i<max;i++){\
249 RI8(str[i]); if (!str[i]) break;} str[i]=0; }
251 rdfheaderrec
*rdfgetheaderrec(rdffile
*f
)
253 static rdfheaderrec r
;
256 if (!f
->header_loc
) {
261 if (f
->header_fp
>= f
->header_len
) return 0;
265 case 1: /* Relocation record */
272 case 2: /* Imported symbol record */
277 case 3: /* Exported symbol record */
283 case 4: /* DLL record */
287 case 5: /* BSS reservation record */
292 rdf_errno
= 2; /* invalid file */
298 void rdfheaderrewind(rdffile
*f
)
304 rdf_headerbuf
* rdfnewheader(void)
309 int rdfaddheader(rdf_headerbuf
* h
, rdfheaderrec
* r
)
314 membufwrite(h
,&r
->type
,1);
315 membufwrite(h
,&r
->r
.segment
,1);
316 membufwrite(h
,&r
->r
.offset
,-4);
317 membufwrite(h
,&r
->r
.length
,1);
318 membufwrite(h
,&r
->r
.refseg
,-2); /* 9 bytes written */
322 membufwrite(h
,&r
->type
,1);
323 membufwrite(h
,&r
->i
.segment
,-2);
324 membufwrite(h
,&r
->i
.label
,strlen(r
->i
.label
) + 1);
328 membufwrite(h
,&r
->type
,1);
329 membufwrite(h
,&r
->e
.segment
,1);
330 membufwrite(h
,&r
->e
.offset
,-4);
331 membufwrite(h
,&r
->e
.label
,strlen(r
->e
.label
) + 1);
335 membufwrite(h
,&r
->type
,1);
336 membufwrite(h
,&r
->d
.libname
,strlen(r
->d
.libname
) + 1);
340 membufwrite(h
,&r
->type
,1);
341 membufwrite(h
,&r
->b
.amount
,-4);
345 return (rdf_errno
= 2);
350 int rdfwriteheader(FILE * fp
, rdf_headerbuf
* h
)
354 fwrite (RDOFFId
, 1, strlen(RDOFFId
), fp
) ;
356 l
= translatelong ( membuflength (h
) );
357 fwrite (&l
, 4, 1, fp
);
361 return 0; /* no error handling in here... CHANGE THIS! */
364 void rdfdoneheader(rdf_headerbuf
* h
)