2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // OBJECT.C - Writing Object Files
4 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
20 extern int obj_format; // object file format to write
21 extern int prg_flag; // generate Atari ST direct executable
23 LONG symsize = 0; // Size of BSD symbol table
24 LONG strindx = 0x00000004; // BSD string table index
25 char * strtable; // Pointer to the symbol string table
26 char * objImage; // Global object image pointer
30 // Add an entry to the BSD symbol table
32 char * constr_bsdsymtab(char * buf, SYM * sym, int globflag)
34 chptr = buf; // Point to buffer for deposit longs
35 D_long(strindx); // Deposit the symbol string index
37 WORD w1 = sym->sattr; // Obtain symbol attribute
39 LONG z = 0; // Initialise resulting symbol flags
43 z = 0x02000000; // Set equated flag
49 case TEXT: z = 0x04000000; break; // Set TEXT segment flag
50 case DATA: z = 0x06000000; break; // Set DATA segment flag
51 case BSS : z = 0x08000000; break; // Set BSS segment flag
56 z |= 0x01000000; // Set global flag if requested
58 D_long(z); // Deposit symbol attribute
60 z = sym->svalue; // Obtain symbol value
61 w1 &= DATA | BSS; // Determine DATA or BSS flag
64 z += sect[TEXT].sloc; // If DATA or BSS add TEXT segment size
67 z += sect[DATA].sloc; // If BSS add DATA segment size
69 D_long(z); // Deposit symbol value
71 strcpy(strtable + strindx, sym->sname);
73 strindx += strlen(sym->sname) + 1; // Incr string index incl null terminate
74 buf += 12; // Increment buffer to next record
75 symsize += 12; // Increment symbol table size
84 #define AL_DEFINED 0x8000
85 #define AL_EQUATED 0x4000
86 #define AL_GLOBAL 0x2000
87 #define AL_EQUREG 0x1000
88 #define AL_EXTERN 0x0800
89 #define AL_DATA 0x0400
90 #define AL_TEXT 0x0200
92 #define AL_FILE 0x0080
94 LONG PRGFLAGS; /* PRGFLAGS as defined in Atari Compendium Chapter 2 */
95 /* Definition Bit(s) Meaning */
96 /* PF_FASTLOAD 0 If set, clear only the BSS area on program load, */
97 /* otherwise clear the entire heap. */
98 /* PF_TTRAMLOAD 1 If set, the program may be loaded into alternative RAM, */
99 /* otherwise it must be loaded into standard RAM. */
100 /* PF_TTRAMMEM 2 If set, the program's Malloc() requests may be satisfied */
101 /* from alternative RAM, otherwise they must be satisfied */
102 /* from standard RAM. */
103 /* - 3 Currently unused. */
104 /* See left. 4 & 5 If these bits are set to 0 (PF_PRIVATE), the processes' */
105 /* entire memory space will be considered private */
106 /* (when memory protection is enabled).If these bits are */
107 /* set to 1 (PF_GLOBAL), the processes' entire memory space */
108 /* will be readable and writable by any process (i.e. global). */
109 /* If these bits are set to 2 (PF_SUPERVISOR), the processes' */
110 /* entire memory space will only be readable and writable by */
111 /* itself and any other process in supervisor mode.If these */
112 /* bits are set to 3 (PF_READABLE), the processes' entire memory */
113 /* space will be readable by any application but only */
114 /* writable by itself. */
115 /* - 6-15 Currently unused. */
117 static WORD tdb_tab[] = {
119 AL_TEXT, /* TEXT segment based */
120 AL_DATA, 0, /* DATA segment based */
121 AL_BSS /* BSS segment based */
125 #define HDRSIZE 0x1C /* size of Alcyon header */
129 * Add entry to symbol table;
130 * if `globflag' is 1, make the symbol global;
131 * if in .PRG mode, adjust symbol values for fake link.
134 char * constr_symtab(register char * buf, SYM * sym, int globflag)
147 for(i=0; i<8 && *s; i++)
154 * Construct and deposit flag word
156 * o all symbols are AL_DEFINED
157 * o install T/D/B/A base
158 * o install 'equated'
159 * o commons (COMMON) are AL_EXTERN, but not BSS
160 * o exports (DEFINED) are AL_GLOBAL
161 * o imports (~DEFINED) are AL_EXTERN
165 w = AL_DEFINED | tdb_tab[w1 & TDB];
167 if (w1 & EQUATED) /* equated */
172 w |= AL_EXTERN | AL_GLOBAL; /* common symbol */
173 w &= ~AL_BSS; /* they're not BSS in Alcyon object files */
175 else if (w1 & DEFINED)
177 if (globflag) /* export the symbol */
180 else w |= AL_EXTERN; /* imported symbol */
187 if (prg_flag) /* relocate value in .PRG segment */
192 z += sect[TEXT].sloc;
195 z += sect[DATA].sloc;
198 *buf++ = z >> 24; /* deposit symbol value */
208 // Write an object file to the passed in file descriptor
209 // N.B.: Return value is ignored...
211 int WriteObject(int fd)
213 LONG t; // Scratch long
214 LONG tds; // TEXT & DATA segment size
215 int i; // Temporary int
216 CHUNK * cp; // Chunk (for gather)
217 char * buf; // Scratch area
218 char * p; // Temporary ptr
219 LONG ssize; // Size of symbols
220 LONG trsize, drsize; // Size of relocations
221 long unused; // For supressing 'write' warnings
225 printf("TEXT segment: %d bytes\n", sect[TEXT].sloc);
226 printf("DATA segment: %d bytes\n", sect[DATA].sloc);
227 printf("BSS segment: %d bytes\n", sect[BSS].sloc);
230 // Write requested object file...
231 if ((obj_format == BSD) || ((obj_format == ALCYON) && (prg_flag == 0)))
233 // Force BSD format from here onwards
238 printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
241 ssize = ((LONG)sy_assign(NULL, NULL)); // Assign index numbers to the symbols
242 tds = sect[TEXT].sloc + sect[DATA].sloc; // Get size of TEXT and DATA segment
243 buf = malloc(0x600000); // Allocate 6mb object file image memory
247 error("cannot allocate object file memory (in BSD mode)");
251 memset(buf, 0, 0x600000); // Reset allocated memory
252 objImage = buf; // Set global object image pointer
253 strtable = malloc(0x200000); // Allocate 2mb scratch buffer
255 if (strtable == NULL)
257 error("cannot allocate string table memory (in BSD mode)");
261 memset(strtable, 0, 0x200000); // Reset allocated memory
263 // Build object file header
264 chptr = buf; // Base of header
265 D_long(0x00000107); // Magic number
266 D_long(sect[TEXT].sloc); // TEXT size
267 D_long(sect[DATA].sloc); // DATA size
268 D_long(sect[BSS].sloc); // BSS size
269 D_long(0x00000000); // Symbol size
270 D_long(0x00000000); // First entry (0L)
271 D_long(0x00000000); // TEXT relocation size
272 D_long(0x00000000); // BSD relocation size
274 // Construct TEXT and DATA segments (without relocation changes)
275 p = buf + BSDHDRSIZE;
277 for(i=TEXT; i<=DATA; ++i)
279 for(cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext)
281 memcpy(p, cp->chptr, cp->ch_size);
286 // Do relocation tables (and make changes to segment data)
287 p = buf + (BSDHDRSIZE + tds); // Move obj image ptr to reloc info
288 trsize = bsdmarkimg(p, tds, sect[TEXT].sloc, TEXT);// Do TEXT relocation table
289 chptr = buf + 24; // Point to relocation hdr entry
290 D_long(trsize); // Write the relocation table size
291 p = buf + (BSDHDRSIZE + tds + trsize); // Move obj image ptr to reloc info
292 drsize = bsdmarkimg(p, tds, sect[TEXT].sloc, DATA);// Do DATA relocation table
293 chptr = buf + 28; // Point to relocation hdr entry
294 D_long(drsize); // Write the relocation table size
296 p = buf + (BSDHDRSIZE + tds + trsize + drsize);// Point to start of symbol table
297 sy_assign(p, constr_bsdsymtab); // Build symbol and string tables
298 chptr = buf + 16; // Point to sym table size hdr entry
299 D_long(symsize); // Write the symbol table size
301 // Point to string table
302 p = buf + (BSDHDRSIZE + tds + trsize + drsize + symsize);
304 memcpy(p, strtable, strindx); // Copy string table to object image
307 free(strtable); // Free allocated memory
309 chptr = p; // Point to string table size long
310 D_long(strindx); // Write string table size
312 // Write the BSD object file from the object image buffer
313 unused = write(fd, buf, BSDHDRSIZE + tds + trsize + drsize + symsize + strindx + 4);
316 free(buf); // Free allocated memory
319 else if (obj_format==ALCYON)
325 printf("TOS header : 28 bytes\n");
326 printf("Total : %d bytes\n", 28 + sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
330 printf("Total : %d bytes\n", sect[TEXT].sloc + sect[DATA].sloc + sect[BSS].sloc);
334 * Compute size of symbol table;
335 * assign numbers to the symbols...
340 ssize = ((LONG)sy_assign(NULL, NULL)) * 14;
343 * Alloc memory for header+text+data, symbol and
344 * relocation information construction.
346 t = tds = sect[TEXT].sloc + sect[DATA].sloc;
351 buf = (char *)((int)malloc(t + HDRSIZE) + HDRSIZE);
354 * Build object file header
355 * just before the text+data image
357 chptr = buf - HDRSIZE; /* -> base of header */
358 D_word(0x601a); /* 00 - magic number */
359 t = sect[TEXT].sloc; /* 02 - TEXT size */
361 t = sect[DATA].sloc; /* 06 - DATA size */
363 t = sect[BSS].sloc; /* 0a - BSS size */
365 D_long(ssize); /* 0e - symbol table size */
366 D_long(0); /* 12 - stack size (unused) */
367 D_long(PRGFLAGS); /* 16 - PRGFLAGS */
368 D_word(0); /* 1a - relocation information exists */
371 * Construct text and data segments;
372 * fixup relocatable longs in .PRG mode;
373 * finally write the header+text+data
377 for(i=TEXT; i<=DATA; i++)
379 for (cp=sect[i].sfcode; cp!=NULL; cp=cp->chnext)
381 memcpy(p, cp->chptr, cp->ch_size);
387 markimg(buf, tds, sect[TEXT].sloc, 0);
389 write(fd, buf - HDRSIZE, tds + HDRSIZE);
392 * Construct and write symbol table
396 sy_assign(buf, constr_symtab);
397 write(fd, buf, ssize);
401 * Construct and write relocation information;
402 * the size of it changes if we're writing a RELMODed executable.
404 tds = markimg(buf, tds, sect[TEXT].sloc, 1);