diff options
author | Pixel <> | 2001-04-16 14:25:48 +0000 |
---|---|---|
committer | Pixel <> | 2001-04-16 14:25:48 +0000 |
commit | 47f363829678a02111423cd5d374e6739d8ea500 (patch) | |
tree | 5c288a8902492e1a91d87ba4ab1cca658e39cbfa /lib/linker.c | |
parent | 27f796ab6a9f455bbd2a1c85088db5304cece75a (diff) |
Linker + bugfixes
Diffstat (limited to 'lib/linker.c')
-rw-r--r-- | lib/linker.c | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/lib/linker.c b/lib/linker.c new file mode 100644 index 0000000..5fe1162 --- /dev/null +++ b/lib/linker.c @@ -0,0 +1,314 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include "config.h" +#include "linker.h" +#include "types.h" +#include "exceptions.h" +#include "hash.h" + +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; + +Uint32 startpoint = -1, textsize = 0, datasize = 0, bsssize = 0; + +object_t ** objects; +symbol_t * symbols, * psymbols; +int objindex = 0, nbrsymbs = 0; + +_TableauVariable symbs; + +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; +} + +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)); + } +} + +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; + + 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(); +} + +static void dumptab(Uint32 * tab, int s, FILE * f) { + int i; + + for (i = 0; i < s; i++) { + writeword(tab[i], f); + } +} + +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); +} + +static void dumprelog(FILE * f) { + symbol_t * s = symbols, * t; + char trouve, err[BUFSIZ]; + + 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: + objects[s->objindex]->text[s->offset] += objects[t->objindex]->textstart + t->offset; + break; + case 2: + objects[s->objindex]->text[s->offset] += textsize + objects[t->objindex]->datastart + t->offset; + break; + case 4: + objects[s->objindex]->text[s->offset] += textsize + datasize + objects[t->objindex]->bssstart + t->offset; + break; + default: + exception(1, _("Internal error")); + break; + } + writeword(objects[s->objindex]->textstart + s->offset, f); + break; + case 3: /* data */ + switch(t->type) { + case 0: + objects[s->objindex]->data[s->offset] += objects[t->objindex]->textstart + t->offset; + break; + case 2: + objects[s->objindex]->data[s->offset] += textsize + objects[t->objindex]->datastart + t->offset; + break; + case 4: + objects[s->objindex]->data[s->offset] += textsize + datasize + objects[t->objindex]->bssstart + t->offset; + break; + default: + exception(1, _("Internal error")); + break; + } + writeword(textsize + objects[s->objindex]->datastart + s->offset, f); + break; + default: + exception(1, _("Internal error")); + break; + } + } + } +} + +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(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), nbrsymbs); + fclose(f); +} + +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); +} |