]> git.sur5r.net Git - cc65/blob - src/ca65/objfile.c
Changed the object file and library format. There is now an additional
[cc65] / src / ca65 / objfile.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 objfile.c                                 */
4 /*                                                                           */
5 /*         Object file writing routines for the ca65 macroassembler          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 1998-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40
41 /* common */
42 #include "fname.h"
43 #include "objdefs.h"
44
45 /* ca65 */
46 #include "global.h"
47 #include "error.h"
48 #include "objfile.h"
49
50
51
52 /*****************************************************************************/
53 /*                                   Data                                    */
54 /*****************************************************************************/
55
56
57
58 /* File descriptor */
59 static FILE* F = 0;
60
61 /* Default extension */
62 #define OBJ_EXT ".o"
63
64 /* Header structure */
65 static ObjHeader Header = {
66     OBJ_MAGIC,          /* 32: Magic number */
67     OBJ_VERSION,        /* 16: Version number */
68     0,                  /* 16: flags */
69     0,                  /* 32: Offset to option table */
70     0,                  /* 32: Size of options */
71     0,                  /* 32: Offset to file table */
72     0,                  /* 32: Size of files */
73     0,                  /* 32: Offset to segment table */
74     0,                  /* 32: Size of segment table */
75     0,                  /* 32: Offset to import list */
76     0,                  /* 32: Size of import list */
77     0,                  /* 32: Offset to export list */
78     0,                  /* 32: Size of export list */
79     0,                  /* 32: Offset to list of debug symbols */
80     0,                  /* 32: Size of debug symbols */
81     0,                  /* 32: Offset to list of line infos */
82     0,                  /* 32: Size of line infos */
83     0,                  /* 32: Offset to string pool */
84     0                   /* 32: Size of string pool */
85 };
86
87
88
89 /*****************************************************************************/
90 /*                         Internally used functions                         */
91 /*****************************************************************************/
92
93
94
95 static void ObjWriteError (void)
96 /* Called on a write error. Will try to close and remove the file, then
97  * print a fatal error.
98  */
99 {
100     /* Remember the error */
101     int Error = errno;
102
103     /* Force a close of the file, ignoring errors */
104     fclose (F);
105
106     /* Try to remove the file, also ignoring errors */
107     remove (OutFile);
108
109     /* Now abort with a fatal error */
110     Fatal (FAT_CANNOT_WRITE_OUTPUT, OutFile, strerror (Error));
111 }
112
113
114
115 static void ObjWriteHeader (void)
116 /* Write the object file header to the current file position */
117 {
118     ObjWrite32 (Header.Magic);
119     ObjWrite16 (Header.Version);
120     ObjWrite16 (Header.Flags);
121     ObjWrite32 (Header.OptionOffs);
122     ObjWrite32 (Header.OptionSize);
123     ObjWrite32 (Header.FileOffs);
124     ObjWrite32 (Header.FileSize);
125     ObjWrite32 (Header.SegOffs);
126     ObjWrite32 (Header.SegSize);
127     ObjWrite32 (Header.ImportOffs);
128     ObjWrite32 (Header.ImportSize);
129     ObjWrite32 (Header.ExportOffs);
130     ObjWrite32 (Header.ExportSize);
131     ObjWrite32 (Header.DbgSymOffs);
132     ObjWrite32 (Header.DbgSymSize);
133     ObjWrite32 (Header.LineInfoOffs);
134     ObjWrite32 (Header.LineInfoSize);
135     ObjWrite32 (Header.StrPoolOffs);
136     ObjWrite32 (Header.StrPoolSize);
137 }
138
139
140
141 /*****************************************************************************/
142 /*                                   Code                                    */
143 /*****************************************************************************/
144
145
146
147 void ObjOpen (void)
148 /* Open the object file for writing, write a dummy header */
149 {
150     /* Do we have a name for the output file? */
151     if (OutFile == 0) {
152         /* We don't have an output name explicitly given, construct one from
153          * the name of the input file.
154          */
155         OutFile = MakeFilename (InFile, OBJ_EXT);
156     }
157
158     /* Create the output file */
159     F = fopen (OutFile, "w+b");
160     if (F == 0) {
161         Fatal (FAT_CANNOT_OPEN_OUTPUT, OutFile, strerror (errno));
162     }
163
164     /* Write a dummy header */
165     ObjWriteHeader ();
166 }
167
168
169
170 void ObjClose (void)
171 /* Write an update header and close the object file. */
172 {
173     /* Go back to the beginning */
174     if (fseek (F, 0, SEEK_SET) != 0) {
175         ObjWriteError ();
176     }
177
178     /* If we have debug infos, set the flag in the header */
179     if (DbgSyms) {
180         Header.Flags |= OBJ_FLAGS_DBGINFO;
181     }
182
183     /* Write the updated header */
184     ObjWriteHeader ();
185
186     /* Close the file */
187     if (fclose (F) != 0) {
188         ObjWriteError ();
189     }
190 }
191
192
193
194 void ObjWrite8 (unsigned V)
195 /* Write an 8 bit value to the file */
196 {
197     if (putc (V, F) == EOF) {
198         ObjWriteError ();
199     }
200 }
201
202
203
204 void ObjWrite16 (unsigned V)
205 /* Write a 16 bit value to the file */
206 {
207     ObjWrite8 (V);
208     ObjWrite8 (V >> 8);
209 }
210
211
212
213 void ObjWrite24 (unsigned long V)
214 /* Write a 24 bit value to the file */
215 {
216     ObjWrite8 (V);
217     ObjWrite8 (V >> 8);
218     ObjWrite8 (V >> 16);
219 }
220
221
222
223 void ObjWrite32 (unsigned long V)
224 /* Write a 32 bit value to the file */
225 {
226     ObjWrite8 (V);
227     ObjWrite8 (V >> 8);
228     ObjWrite8 (V >> 16);
229     ObjWrite8 (V >> 24);
230 }
231
232
233
234 void ObjWriteVar (unsigned long V)
235 /* Write a variable sized value to the file in special encoding */
236 {
237     /* We will write the value to the file in 7 bit chunks. If the 8th bit
238      * is clear, we're done, if it is set, another chunk follows. This will
239      * allow us to encode smaller values with less bytes, at the expense of
240      * needing 5 bytes if a 32 bit value is written to file.
241      */
242     do {
243         unsigned char C = (V & 0x7F);
244         V >>= 7;
245         if (V) {
246             C |= 0x80;
247         }
248         ObjWrite8 (C);
249     } while (V != 0);
250 }
251
252
253
254 void ObjWriteStr (const char* S)
255 /* Write a string to the object file */
256 {
257     unsigned Len = strlen (S);
258
259     /* Write the string with the length preceeded (this is easier for
260      * the reading routine than the C format since the length is known in
261      * advance).
262      */
263     ObjWriteVar (Len);
264     ObjWriteData (S, Len);
265 }
266
267
268
269 void ObjWriteData (const void* Data, unsigned Size)
270 /* Write literal data to the file */
271 {
272     if (fwrite (Data, 1, Size, F) != Size) {
273         ObjWriteError ();
274     }
275 }
276
277
278
279 void ObjWritePos (const FilePos* Pos)
280 /* Write a file position to the object file */
281 {
282     /* Write the data entries */
283     ObjWriteVar (Pos->Line);
284     ObjWriteVar (Pos->Col);
285     if (Pos->Name == 0) {
286         /* Position is outside file scope, use the main file instead */
287         ObjWriteVar (0);
288     } else {
289         ObjWriteVar (Pos->Name - 1);
290     }
291 }
292
293
294
295 void ObjStartOptions (void)
296 /* Mark the start of the option section */
297 {
298     Header.OptionOffs = ftell (F);
299 }
300
301
302
303 void ObjEndOptions (void)
304 /* Mark the end of the option section */
305 {
306     Header.OptionSize = ftell (F) - Header.OptionOffs;
307 }
308
309
310
311 void ObjStartFiles (void)
312 /* Mark the start of the files section */
313 {
314     Header.FileOffs = ftell (F);
315 }
316
317
318
319 void ObjEndFiles (void)
320 /* Mark the end of the files section */
321 {
322     Header.FileSize = ftell (F) - Header.FileOffs;
323 }
324
325
326
327 void ObjStartSegments (void)
328 /* Mark the start of the segment section */
329 {
330     Header.SegOffs = ftell (F);
331 }
332
333
334
335 void ObjEndSegments (void)
336 /* Mark the end of the segment section */
337 {
338     Header.SegSize = ftell (F) - Header.SegOffs;
339 }
340
341
342
343 void ObjStartImports (void)
344 /* Mark the start of the import section */
345 {
346     Header.ImportOffs = ftell (F);
347 }
348
349
350
351 void ObjEndImports (void)
352 /* Mark the end of the import section */
353 {
354     Header.ImportSize = ftell (F) - Header.ImportOffs;
355 }
356
357
358
359 void ObjStartExports (void)
360 /* Mark the start of the export section */
361 {
362     Header.ExportOffs = ftell (F);
363 }
364
365
366
367 void ObjEndExports (void)
368 /* Mark the end of the export section */
369 {
370     Header.ExportSize = ftell (F) - Header.ExportOffs;
371 }
372
373
374
375 void ObjStartDbgSyms (void)
376 /* Mark the start of the debug symbol section */
377 {
378     Header.DbgSymOffs = ftell (F);
379 }
380
381
382
383 void ObjEndDbgSyms (void)
384 /* Mark the end of the debug symbol section */
385 {
386     Header.DbgSymSize = ftell (F) - Header.DbgSymOffs;
387 }
388
389
390
391 void ObjStartLineInfos (void)
392 /* Mark the start of the line info section */
393 {
394     Header.LineInfoOffs = ftell (F);
395 }
396
397
398
399 void ObjEndLineInfos (void)
400 /* Mark the end of the line info section */
401 {
402     Header.LineInfoSize = ftell (F) - Header.LineInfoOffs;
403 }
404
405
406
407 void ObjStartStrPool (void)
408 /* Mark the start of the string pool section */
409 {
410     Header.StrPoolOffs = ftell (F);
411 }
412
413
414
415 void ObjEndStrPool (void)
416 /* Mark the end of the string pool section */
417 {
418     Header.StrPoolSize = ftell (F) - Header.StrPoolOffs;
419 }
420
421
422