DONE Check error cases (seg +seg , unknown + seg etc)
DONE Automatic symbols __code __data __bss __endcode __enddata __endbss
-- Need to add .code .equ and all the other .byte type stuff that is nice to have
+DONE - Need to add .code .equ and all the other .byte type stuff that is nice to have
+ - .include for asm hacking (or parse cpp #line)
+
Check that JR works with symbols properly (require they are in the same .o maybe)
x / 2 - y / 2 is done as (x - y) / 2 ?
-DONE Proper error messaeges needed
+DONE Proper error messages needed
+DONE Error checking
later:
need a syntax/operator for high/low byte of seg
output is then segbyteh or segbytel and follows same rules as segment
(what about mixing them ?)
+ PC relative 8 and 16bit addressing (including dealing with processors
+ using .+2 etc as the base).
+
DONE - Proper output logic
DONE - write an invalid header
DONE - for each segment
DONE versus our segment base for this object module (usual)
DONE versus other segment base for this module
DONE versus unresolved symbol
+ PC relative (not so much Z80)
Need to support relocations for 16bit and also 8bit ZP. Do we need to extend
the assembler to support relocations for high 8 / low 8 ? Probably not for Z80
link
DONE read each module header that we include
DONE load its symbols
-
DONE compute base of each versus segment
DONE compute base of segments (split I/D differs a bit etc)
-
DONE resolve all symbols we can
+DONE write out segments relocating and resolving
+DONE Unresolved symbols allowed for -r
-IP write out segments relocating and resolving
-
- Unresolved symbols allowed for -r
-
- scan each module header again
+ For debug scan each module header again and then
copy all the debug symbols (relocating as we go)
- Libraries
+DONE Libraries
+ Ranlib
static uint16_t arch_flags;
static uint8_t verbose;
static int err;
-static int syms = 1;
static int dbgsyms = 1;
+static int strip = 0;
static char *mapname;
static char *outname;
-void error(const char *p)
+static void error(const char *p)
{
if (processing)
fprintf(stderr, "While processing: %s\n", processing->path);
exit(err | 2);
}
-void *xmalloc(size_t s)
+static void *xmalloc(size_t s)
{
void *p = malloc(s);
if (p == NULL)
return p;
}
+static FILE *xfopen(const char *path, const char *mode)
+{
+ FILE *fp = fopen(path, mode);
+ if (fp == NULL) {
+ perror(path);
+ exit(err | 1);
+ }
+ return fp;
+}
+
+static void xfclose(FILE *fp)
+{
+ if (fclose(fp)) {
+ perror("fclose");
+ exit(err | 1);
+ }
+}
+
+static void xfseek(FILE *fp, off_t pos)
+{
+ if (fseek(fp, pos, SEEK_SET) < 0) {
+ perror("fseek");
+ exit(err | 1);
+ }
+}
+
static struct object *new_object(void)
{
struct object *o = xmalloc(sizeof(struct object));
/* Two definitions.. usually bad but allow duplicate absolutes */
if (((s->type | type) & S_SEGMENT) != ABSOLUTE || s->value != value) {
/* FIXME: expand to report files somehow ? */
- printf("%s: multiply defined.\n", id);
+ fprintf(stderr, "%s: multiply defined.\n", id);
}
/* Duplicate absolutes - just keep current entry */
return s;
static void insert_internal_symbol(char *name, int seg, uint16_t val)
{
- printf("%s is %X in seg %d\n", name, val, seg);
find_alloc_symbol(NULL, seg | S_PUBLIC, name, val);
}
o->path = path;
processing = o; /* For error reporting */
- fseek(fp, off, SEEK_SET);
+ xfseek(fp, off);
if (fread(&o->oh, sizeof(o->oh), 1, fp) != 1 || o->oh.o_magic != MAGIC_OBJ || o->oh.o_symbase == 0) {
/* A library may contain other things, just ignore them */
if (lib)
o->syment = (struct symbol **) xmalloc(sizeof(struct symbol *) * nsym);
o->nsym = nsym;
restart:
- fseek(fp, off + o->oh.o_symbase, SEEK_SET);
+ xfseek(fp, off + o->oh.o_symbase);
sp = o->syment;
for (i = 0; i < nsym; i++) {
type = fgetc(fp);
while (s != NULL) {
uint8_t seg = s->type & S_SEGMENT;
/* base will be 0 for absolute */
- if (s->definedby) {
- printf("%s moved by %x\n",
- s->name, s->definedby->base[seg]);
+ if (s->definedby)
s->value += s->definedby->base[seg];
- } else {
- printf("%s moved by %x\n",
- s->name, base[seg]);
+ else
s->value += base[seg];
- }
/* FIXME: check overflow */
s = s->next;
}
FILE *openobject(struct object *o)
{
- FILE *fp = fopen(o->path, "r");
- if (fp == NULL) {
- perror(o->path);
- exit(1);
- }
- fseek(fp, o->off, SEEK_SET);
+ FILE *fp = xfopen(o->path, "r");
+ xfseek(fp, o->off);
return fp;
}
FILE *ip = openobject(o); /* So we can hide library gloop */
if (verbose)
printf("Writing %s#%ld:%d\n", o->path, o->off, seg);
- fseek(ip, o->off + o->oh.o_segbase[seg], SEEK_SET);
+ xfseek(ip, o->off + o->oh.o_segbase[seg]);
relocate_stream(o, op, ip);
- fclose(ip);
+ xfclose(ip);
o = o->next;
}
if (ldmode != LD_ABSOLUTE) {
write_stream(op, CODE);
hdr.o_segbase[1] = ftell(op);
write_stream(op, DATA);
- if (syms) {
+ if (!strip) {
hdr.o_symbase = ftell(op);
write_symbols(op);
}
hdr.o_dbgbase = ftell(op);
hdr.o_magic = MAGIC_OBJ;
/* TODO: needs a special pass
- if (dbgsyms)
+ if (dbgsyms )
copy_debug_all(op, mp);*/
if (err == 0 && ldmode != LD_ABSOLUTE) {
- fseek(op, 0, SEEK_SET);
+ xfseek(op, 0);
fwrite(&hdr, sizeof(hdr), 1, op);
}
}
unsigned long size;
while(1) {
- fseek(fp, pos, SEEK_SET);
+ xfseek(fp, pos);
if (fread(&ah, sizeof(ah), 1, fp) == 0)
break;
if (ah.ar_fmag[0] != 96 || ah.ar_fmag[1] != '\n')
static void add_object(const char *name, off_t off, int lib)
{
static char x[SARMAG];
- FILE *fp = fopen(name, "r");
- if (fp == NULL) {
- perror(name);
- exit(1);
- }
+ FILE *fp = xfopen(name, "r");
if (off == 0 && !lib) {
/* Is it a bird, is it a plane ? */
fread(x, SARMAG, 1, fp);
if (memcmp(x, ARMAG, SARMAG) == 0) {
/* No it's a library */
process_library(name, fp);
- fclose(fp);
+ xfclose(fp);
return;
}
}
- fseek(fp, off, SEEK_SET);
+ xfseek(fp, off);
load_object(fp, off, lib, name);
- fclose(fp);
+ xfclose(fp);
}
int main(int argc, char *argv[])
arg0 = argv[0];
- while ((opt = getopt(argc, argv, "rbvo:m:")) != -1) {
+ while ((opt = getopt(argc, argv, "rbvtsio:m:c:")) != -1) {
switch (opt) {
case 'r':
ldmode = LD_RFLAG;
case 'b':
ldmode = LD_ABSOLUTE;
case 'v':
+ printf("FuzixLD 0.1\n");
+ break;
+ case 't':
verbose = 1;
break;
case 'o':
case 'm':
mapname = optarg;
break;
+ case 's':
+ strip = 1;
+ break;
+ case 'i':
+ split_id = 1;
+ break;
+ case 'c':
+ base[1] = atoi(optarg);
+ break;
default:
fprintf(stderr, "%s: name ...\n", argv[0]);
exit(1);
if (verbose)
printf("Writing output.\n");
- bp = fopen(outname, "w");
- if (bp == NULL) {
- perror(outname);
- exit(1);
- }
+ bp = xfopen(outname, "w");
if (mapname) {
- mp = fopen(mapname, "w");
- if (mp == NULL) {
- perror(mapname);
- exit(1);
- }
+ mp = xfopen(mapname, "w");
if (verbose)
printf("Writing map file.\n");
write_map_file(mp);
}
write_binary(bp,mp);
- fclose(bp);
+ xfclose(bp);
if (mp)
fclose(mp);
exit(err);