#include #include #include #include #include #include "config.h" #include "linker.h" #include "types.h" #include "exceptions.h" #include "hash.h" /* Les quelques structures de données utiles */ typedef struct object_t { Uint32 s_text, s_data, s_bss, *text, *data, textstart, datastart, bssstart; } object_t; typedef struct symbol_t { char *name; int objindex; Uint32 offset; int type; struct symbol_t *next; } symbol_t; /* Et les variables globales */ Uint32 startpoint = -1, textsize = 0, datasize = 0, bsssize = 0; object_t **objects; symbol_t *symbols, *psymbols; int objindex = 0, nbrsymbs = 0; _TableauVariable symbs; /* Quelques fonctions pour nous simplifier la vie... */ static FILE *openfilewriting(char *name) { FILE *f; if (!(f = fopen(name, "wb"))) { pushcontext(strerror(errno)); exception(1, _("Error writing file")); } return f; } static FILE *openfilereading(char *name) { FILE *f; if (!(f = fopen(name, "rb"))) { pushcontext(strerror(errno)); exception(1, _("Error reading file")); } return f; } static void writeword(Uint32 a, FILE * f) { if (fwrite(&a, sizeof(unsigned long int), 1, f) != 1) { if (ferror(f)) { pushcontext(strerror(errno)); } exception(1, _("Error writing file")); } } static Uint32 readword(FILE * f) { Uint32 a; if (fread(&a, sizeof(a), 1, f) != 1) { exception(1, _("premature end of file")); } return a; } static char *readstring(FILE * f) { Uint32 s; char *r; int i; s = readword(f); r = (char *) Emalloc(s + 1); for (i = 0; i < s; i++) { r[i] = readword(f); } r[i] = '\0'; return r; } /* Rajoute un symbole dans la pile */ static void addsymbol(char *name, int offset, int type) { symbol_t *newsymbol; newsymbol = (symbol_t *) Emalloc(sizeof(symbol_t)); newsymbol->next = NULL; newsymbol->type = type; newsymbol->offset = offset; newsymbol->objindex = objindex; newsymbol->name = name; psymbols->next = newsymbol; psymbols = newsymbol; if (newsymbol->type & 1) { nbrsymbs++; } else { InsererVarDansTab(&symbs, CreerElement(name, newsymbol)); } } /* Rajoute un fichier dans les structures */ void addfile(char *nom) { FILE *f; Uint32 start, nbsymbols, type, offset; int i; char *snom, errctx[BUFSIZ]; f = openfilereading(nom); sprintf(errctx, _("Processing file %s"), nom); pushcontext(errctx); if (readword(f) != 0x4f424e4e) { exception(1, _("Bad signature")); } readword(f); /* Taille du fichier */ start = readword(f); if ((startpoint != -1) && (start != -1)) { exception(1, _("Startpoint already defined.")); } startpoint = start + textsize; objects[objindex]->s_text = readword(f); objects[objindex]->s_data = readword(f); objects[objindex]->s_bss = readword(f); readword(f); /* Taille de la table des symboles */ nbsymbols = readword(f); pushcontext(_("Reading symbols")); for (i = 0; i < nbsymbols; i++) { type = readword(f); offset = readword(f); snom = readstring(f); addsymbol(snom, offset, type); } popcontext(); objects[objindex]->textstart = textsize; objects[objindex]->datastart = datasize; objects[objindex]->bssstart = bsssize; objects[objindex]->text = (Uint32 *) Emalloc(objects[objindex]->s_text * sizeof(Uint32)); objects[objindex]->data = (Uint32 *) Emalloc(objects[objindex]->s_data * sizeof(Uint32)); pushcontext(_("Reading text and data segments")); for (i = 0; i < objects[objindex]->s_text; i++) { objects[objindex]->text[i] = readword(f); } for (i = 0; i < objects[objindex]->s_data; i++) { objects[objindex]->data[i] = readword(f); } popcontext(); fclose(f); textsize += objects[objindex]->s_text; datasize += objects[objindex]->s_data; bsssize += objects[objindex]->s_bss; objindex++; popcontext(); } /* Simplification de vie... */ static void dumptab(Uint32 * tab, int s, FILE * f) { int i; for (i = 0; i < s; i++) { writeword(tab[i], f); } } /* Nous dumpons la mémoire dans le fichier */ static void dumptext(object_t * obj, FILE * f) { dumptab(obj->text, obj->s_text, f); } static void dumpdata(object_t * obj, FILE * f) { dumptab(obj->data, obj->s_data, f); } /* Cette fonction va calculer les quelques relogements statiques et dynamiques que nous a laissé l'assembleur */ static void dumprelog(FILE * f) { symbol_t *s = symbols, *t; char trouve, err[BUFSIZ]; Uint32 decal; for (s = s->next; s; s = s->next) { if (s->type & 1) { t = (symbol_t *) NomVarToVar(s->name, symbs, &trouve); if (!trouve) { sprintf(err, _("Symbol %s not found"), s->name); exception(1, err); } switch (s->type) { case 1: /* text */ switch (t->type) { case 0: decal = objects[t->objindex]->textstart + t->offset; break; case 2: decal = textsize + objects[t->objindex]->datastart + t->offset; break; case 4: decal = textsize + datasize + objects[t->objindex]->bssstart + t->offset; break; default: exception(1, _("Internal error")); break; } #ifdef DEBUG fprintf(stderr, "Relogement effectué sur %i (text), de %i octets pour le symbole %s\n", s->offset, decal, s->name); #endif objects[s->objindex]->text[s->offset] += decal; writeword(objects[s->objindex]->textstart + s->offset, f); break; case 3: /* data */ switch (t->type) { case 0: decal = objects[t->objindex]->textstart + t->offset; break; case 2: decal = textsize + objects[t->objindex]->datastart + t->offset; break; case 4: decal = textsize + datasize + objects[t->objindex]->bssstart + t->offset; break; default: exception(1, _("Internal error")); break; } #ifdef DEBUG fprintf(stderr, "Relogement effectué sur %i (data), de %i octets pour le symbole %s\n", s->offset, decal, s->name); #endif objects[s->objindex]->data[s->offset] += decal; writeword(textsize + objects[s->objindex]->datastart + s->offset, f); break; default: exception(1, _("Internal error")); break; } } } } /* Cette fonction sert à écrire le fichier de sortie. */ void dumpfile(char *nom) { FILE *f; int i; pushcontext(_("Writing output file")); f = openfilewriting(nom); if (startpoint == -1) { exception(1, _("No startpoint defined.")); } pushcontext(_("Writing headers")); writeword(0x58454e4e, f); writeword(nbrsymbs + textsize + datasize + 7, f); writeword(startpoint, f); writeword(textsize, f); writeword(datasize, f); writeword(bsssize, f); writeword(nbrsymbs, f); popcontext(); pushcontext(_("Writing relocating informations")); dumprelog(f); popcontext(); pushcontext(_("Writing text segments")); for (i = 0; i < objindex; i++) { dumptext(objects[i], f); } popcontext(); pushcontext(_("Writing data segments")); for (i = 0; i < objindex; i++) { dumpdata(objects[i], f); } popcontext(); popcontext(); fprintf(stderr, _ ("Statistics: %i words of text, %i words of data and reserving %i words\n"), textsize, datasize, bsssize); fprintf(stderr, _ ("Output file size: %i words containing %i relocating offsets.\n"), ftell(f) >> 2, nbrsymbs); fclose(f); } /* Fonctions d'initialisations et de libération de mémoire */ void init(int n) { int i; Initialise(&symbs); objects = (object_t **) Emalloc(n * sizeof(object_t *)); psymbols = symbols = (symbol_t *) Emalloc(sizeof(symbol_t)); for (i = 0; i < n; i++) { objects[i] = (object_t *) Emalloc(sizeof(object_t)); objects[i]->s_text = objects[i]->s_data = objects[i]->s_bss = objects[i]->textstart = objects[i]->datastart = 0; objects[i]->text = objects[i]->data = NULL; } symbols->next = NULL; } void free_symbol(symbol_t * s) { if (s->next) free_symbol(s); free(s->name); free(s); } void flush(void) { int i; DetruitTab(&symbs); for (i = 0; i < objindex; i++) { if (objects[i]->text) free(objects[i]->text); if (objects[i]->data) ; free(objects[i]->data); free(objects[i]); } free(objects); }