OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [binutils/] [ld/] [ld.c] - Blame information for rev 33

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 hellwig
/*
2
 * ld.c -- ECO32 linking loader
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <stdarg.h>
10
#include <ctype.h>
11
#include <unistd.h>
12
 
13
#include "../include/a.out.h"
14
 
15
 
16
/**************************************************************/
17
 
18
 
19
#define MAX_STRLEN      200
20
 
21
#define PAGE_SHIFT      12
22
#define PAGE_SIZE       (1 << PAGE_SHIFT)
23
#define PAGE_MASK       (PAGE_SIZE - 1)
24
#define PAGE_ROUND(n)   (((n) + PAGE_SIZE - 1) & ~PAGE_MASK)
25
 
26
#define MSB     ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
27
 
28
 
29
/**************************************************************/
30
 
31
 
32
int debugLink = 0;
33
int debugFixup = 0;
34
 
35
int withHeader = 1;
36
 
37
char codeName[L_tmpnam];
38
char dataName[L_tmpnam];
39
char *outName = NULL;
40
char *mapName = NULL;
41
char *inName = NULL;
42
 
43
FILE *codeFile = NULL;
44
FILE *dataFile = NULL;
45
FILE *outFile = NULL;
46
FILE *mapFile = NULL;
47
FILE *inFile = NULL;
48
 
49
unsigned int segPtr[4] = { 0, 0, 0, 0 };
50
int segStartDefined[4] = { 0, 0, 0, 0 };
51
unsigned int segStart[4] = { 0, 0, 0, 0 };
52
char *segName[4] = { "ABS", "CODE", "DATA", "BSS" };
53
char *methodName[5] = { "H16", "L16", "R16", "R26", "W32" };
54
 
55
 
56
typedef struct reloc {
57
  int segment;                  /* in which segment to relocate */
58
  unsigned int offset;          /* where in the segment to relocate */
59
  int method;                   /* how to relocate */
60
  int value;                    /* additive part of value */
61
  int type;                     /* 0: base is a segment */
62
                                /* 1: base is a symbol */
63
  union {                       /* relocation relative to .. */
64
    int segment;                /* .. a segment */
65
    struct symbol *symbol;      /* .. a symbol */
66
  } base;
67
  struct reloc *next;           /* next relocation */
68
} Reloc;
69
 
70
 
71
typedef struct symbol {
72
  char *name;                   /* name of symbol */
73
  int type;                     /* if MSB = 0: the symbol's segment */
74
                                /* if MSB = 1: the symbol is undefined */
75
  int value;                    /* if symbol defined: the symbol's value */
76
                                /* if symbol not defined: meaningless */
77
  struct symbol *left;          /* left son in binary search tree */
78
  struct symbol *right;         /* right son in binary search tree */
79
} Symbol;
80
 
81
 
82
/**************************************************************/
83
 
84
 
85
void error(char *fmt, ...) {
86
  va_list ap;
87
 
88
  va_start(ap, fmt);
89
  fprintf(stderr, "Error: ");
90
  vfprintf(stderr, fmt, ap);
91
  fprintf(stderr, "\n");
92
  va_end(ap);
93
  if (codeFile != NULL) {
94
    fclose(codeFile);
95
    codeFile = NULL;
96
  }
97
  if (dataFile != NULL) {
98
    fclose(dataFile);
99
    dataFile = NULL;
100
  }
101
  if (outFile != NULL) {
102
    fclose(outFile);
103
    outFile = NULL;
104
  }
105
  if (mapFile != NULL) {
106
    fclose(mapFile);
107
    mapFile = NULL;
108
  }
109
  if (inFile != NULL) {
110
    fclose(inFile);
111
    inFile = NULL;
112
  }
113
  if (codeName != NULL) {
114
    unlink(codeName);
115
  }
116
  if (dataName != NULL) {
117
    unlink(dataName);
118
  }
119
  if (outName != NULL) {
120
    unlink(outName);
121
  }
122
  if (mapName != NULL) {
123
    unlink(mapName);
124
  }
125
  exit(1);
126
}
127
 
128
 
129
void *allocateMemory(unsigned int size) {
130
  void *p;
131
 
132
  p = malloc(size);
133
  if (p == NULL) {
134
    error("out of memory");
135
  }
136
  return p;
137
}
138
 
139
 
140
void freeMemory(void *p) {
141
  free(p);
142
}
143
 
144
 
145
/**************************************************************/
146
 
147
 
148
Reloc *relocs = NULL;
149
 
150
 
151
void addReloc(int segment, RelocRecord *relRec, Symbol **symMap) {
152
  Reloc *rel;
153
 
154
  rel = allocateMemory(sizeof(Reloc));
155
  rel->segment = segment;
156
  rel->offset = relRec->offset + segPtr[segment];
157
  rel->method = relRec->method;
158
  rel->value = relRec->value;
159
  if ((relRec->base & MSB) == 0) {
160
    /* relocation is relative to a segment */
161
    rel->type = 0;
162
    rel->base.segment = relRec->base;
163
    rel->value += segPtr[relRec->base];
164
  } else {
165
    /* relocation is relative to a symbol */
166
    rel->type = 1;
167
    rel->base.symbol = symMap[relRec->base & ~MSB];
168
  }
169
  rel->next = relocs;
170
  relocs = rel;
171
}
172
 
173
 
174
void linkSymbol(Reloc *rel) {
175
  Symbol *sym;
176
 
177
  /* check if this is a reference to a symbol */
178
  if (rel->type != 1) {
179
    /* no: nothing to do here */
180
    return;
181
  }
182
  /* get information from the symbol table record */
183
  sym = rel->base.symbol;
184
  if (sym->type & MSB) {
185
    error("undefined symbol '%s'", sym->name);
186
  }
187
  /* output debugging info */
188
  if (debugLink) {
189
    printf("DEBUG: link '%s' (s:%s, v:%08X)\n",
190
           sym->name, segName[sym->type], sym->value);
191
    printf("       (s:%s, o:%08X, m:%s, v:%08X --> %08X, b:%s)\n",
192
           segName[rel->segment], rel->offset, methodName[rel->method],
193
           rel->value, rel->value + sym->value, segName[sym->type]);
194
  }
195
  /* update relocation information */
196
  rel->value += sym->value;
197
  rel->type = 0;
198
  rel->base.segment = sym->type;
199
}
200
 
201
 
202
void linkSymbols(void) {
203
  Reloc *rel;
204
 
205
  rel = relocs;
206
  while (rel != NULL) {
207
    linkSymbol(rel);
208
    rel = rel->next;
209
  }
210
}
211
 
212
 
213
void fixupRef(Reloc *rel) {
214
  FILE *file;
215
  unsigned int value;
216
  unsigned int final;
217
 
218
  /* determine the segment in which to do fixup */
219
  switch (rel->segment) {
220
    case SEGMENT_ABS:
221
      /* this should never happen */
222
      error("cannot do fixup in ABS");
223
      break;
224
    case SEGMENT_CODE:
225
      file = codeFile;
226
      break;
227
    case SEGMENT_DATA:
228
      file = dataFile;
229
      break;
230
    case SEGMENT_BSS:
231
      /* this should never happen */
232
      error("cannot do fixup in BSS");
233
      break;
234
    default:
235
      /* this should never happen */
236
      error("illegal segment in doFixup()");
237
      break;
238
  }
239
  /* check that the base is indeed a segment */
240
  if (rel->type != 0) {
241
    /* this should never happen */
242
    error("fixup cannot handle reference to symbol");
243
  }
244
  /* now patch according to method */
245
  switch (rel->method) {
246
    case METHOD_H16:
247
      value = rel->value + segStart[rel->base.segment];
248
      final = (value >> 16) & 0x0000FFFF;
249
      fseek(file, rel->offset + 2, SEEK_SET);
250
      fputc((final >> 8) & 0xFF, file);
251
      fputc((final >> 0) & 0xFF, file);
252
      break;
253
    case METHOD_L16:
254
      value = rel->value + segStart[rel->base.segment];
255
      final = value & 0x0000FFFF;
256
      fseek(file, rel->offset + 2, SEEK_SET);
257
      fputc((final >> 8) & 0xFF, file);
258
      fputc((final >> 0) & 0xFF, file);
259
      break;
260
    case METHOD_R16:
261
      value = (rel->value - (rel->offset + 4)) / 4;
262
      final = value & 0x0000FFFF;
263
      fseek(file, rel->offset + 2, SEEK_SET);
264
      fputc((final >> 8) & 0xFF, file);
265
      fputc((final >> 0) & 0xFF, file);
266
      break;
267
    case METHOD_R26:
268
      value = (rel->value - (rel->offset + 4)) / 4;
269
      fseek(file, rel->offset, SEEK_SET);
270
      final = (fgetc(file) << 24) & 0xFC000000;
271
      final |= value & 0x03FFFFFF;
272
      fseek(file, -1, SEEK_CUR);
273
      fputc((final >> 24) & 0xFF, file);
274
      fputc((final >> 16) & 0xFF, file);
275
      fputc((final >>  8) & 0xFF, file);
276
      fputc((final >>  0) & 0xFF, file);
277
      break;
278
    case METHOD_W32:
279
      value = rel->value + segStart[rel->base.segment];
280
      final = value;
281
      fseek(file, rel->offset, SEEK_SET);
282
      fputc((final >> 24) & 0xFF, file);
283
      fputc((final >> 16) & 0xFF, file);
284
      fputc((final >>  8) & 0xFF, file);
285
      fputc((final >>  0) & 0xFF, file);
286
      break;
287
    default:
288
      /* this should never happen */
289
      error("illegal method in doFixup()");
290
      break;
291
  }
292
  /* output debugging info */
293
  if (debugFixup) {
294
    printf("DEBUG: fixup (s:%s, o:%08X, m:%s, v:%08X), %08X --> %08X\n",
295
           segName[rel->segment], rel->offset, methodName[rel->method],
296
           rel->value, value, final);
297
  }
298
}
299
 
300
 
301
void relocateSegments(void) {
302
  Reloc *rel;
303
 
304
  /* determine start of segments */
305
  if (!segStartDefined[SEGMENT_CODE]) {
306
    segStart[SEGMENT_CODE] = 0;
307
    segStartDefined[SEGMENT_CODE] = 1;
308
  }
309
  if (!segStartDefined[SEGMENT_DATA]) {
310
    segStart[SEGMENT_DATA] = segStart[SEGMENT_CODE] +
311
                             PAGE_ROUND(segPtr[SEGMENT_CODE]);
312
    segStartDefined[SEGMENT_DATA] = 1;
313
  }
314
  if (!segStartDefined[SEGMENT_BSS]) {
315
    segStart[SEGMENT_BSS] = segStart[SEGMENT_DATA] +
316
                            segPtr[SEGMENT_DATA];
317
    segStartDefined[SEGMENT_BSS] = 1;
318
  }
319
  /* fixup all references (which now are only relative to segments) */
320
  while (relocs != NULL) {
321
    rel = relocs;
322
    relocs = rel->next;
323
    fixupRef(rel);
324
    freeMemory(rel);
325
  }
326
}
327
 
328
 
329
/**************************************************************/
330
 
331
 
332
Symbol *symbolTable = NULL;
333
 
334
 
335
Symbol *newSymbol(char *name) {
336
  Symbol *p;
337
 
338
  p = allocateMemory(sizeof(Symbol));
339
  p->name = allocateMemory(strlen(name) + 1);
340
  strcpy(p->name, name);
341
  p->type = MSB;
342
  p->value = 0;
343
  p->left = NULL;
344
  p->right = NULL;
345
  return p;
346
}
347
 
348
 
349
Symbol *lookupEnter(char *name) {
350
  Symbol *p, *q, *r;
351
  int cmp;
352
 
353
  p = symbolTable;
354
  if (p == NULL) {
355
    r = newSymbol(name);
356
    symbolTable = r;
357
    return r;
358
  }
359
  while (1) {
360
    q = p;
361
    cmp = strcmp(name, q->name);
362
    if (cmp == 0) {
363
      return q;
364
    }
365
    if (cmp < 0) {
366
      p = q->left;
367
    } else {
368
      p = q->right;
369
    }
370
    if (p == NULL) {
371
      r = newSymbol(name);
372
      if (cmp < 0) {
373
        q->left = r;
374
      } else {
375
        q->right = r;
376
      }
377
      return r;
378
    }
379
  }
380
}
381
 
382
 
383
void walkTree(Symbol *s, void (*fp)(Symbol *sp)) {
384
  if (s == NULL) {
385
    return;
386
  }
387
  walkTree(s->left, fp);
388
  (*fp)(s);
389
  walkTree(s->right, fp);
390
}
391
 
392
 
393
void walkSymbols(void (*fp)(Symbol *sym)) {
394
  walkTree(symbolTable, fp);
395
}
396
 
397
 
398
/**************************************************************/
399
 
400
 
401
unsigned int read4FromEco(unsigned char *p) {
402
  return (unsigned int) p[0] << 24 |
403
         (unsigned int) p[1] << 16 |
404
         (unsigned int) p[2] <<  8 |
405
         (unsigned int) p[3] <<  0;
406
}
407
 
408
 
409
void write4ToEco(unsigned char *p, unsigned int data) {
410
  p[0] = data >> 24;
411
  p[1] = data >> 16;
412
  p[2] = data >>  8;
413
  p[3] = data >>  0;
414
}
415
 
416
 
417
void conv4FromEcoToNative(unsigned char *p) {
418
  unsigned int data;
419
 
420
  data = read4FromEco(p);
421
  * (unsigned int *) p = data;
422
}
423
 
424
 
425
void conv4FromNativeToEco(unsigned char *p) {
426
  unsigned int data;
427
 
428
  data = * (unsigned int *) p;
429
  write4ToEco(p, data);
430
}
431
 
432
 
433
/**************************************************************/
434
 
435
 
436
#define CODE_START(h)   (sizeof(ExecHeader))
437
#define DATA_START(h)   (CODE_START(h) + (h).csize)
438
#define CRELOC_START(h) (DATA_START(h) + (h).dsize)
439
#define DRELOC_START(h) (CRELOC_START(h) + (h).crsize)
440
#define SYMTBL_START(h) (DRELOC_START(h) + (h).drsize)
441
#define STRING_START(h) (SYMTBL_START(h) + (h).symsize)
442
 
443
 
444
ExecHeader inHeader;
445
Symbol **symMap;
446
 
447
 
448
void readHeader(void) {
449
  if (fseek(inFile, 0, SEEK_SET) < 0) {
450
    error("cannot seek to exec header");
451
  }
452
  if (fread(&inHeader, sizeof(ExecHeader), 1, inFile) != 1) {
453
    error("cannot read exec header");
454
  }
455
  conv4FromEcoToNative((unsigned char *) &inHeader.magic);
456
  conv4FromEcoToNative((unsigned char *) &inHeader.csize);
457
  conv4FromEcoToNative((unsigned char *) &inHeader.dsize);
458
  conv4FromEcoToNative((unsigned char *) &inHeader.bsize);
459
  conv4FromEcoToNative((unsigned char *) &inHeader.crsize);
460
  conv4FromEcoToNative((unsigned char *) &inHeader.drsize);
461
  conv4FromEcoToNative((unsigned char *) &inHeader.symsize);
462
  conv4FromEcoToNative((unsigned char *) &inHeader.strsize);
463
  if (inHeader.magic != EXEC_MAGIC) {
464
    error("wrong magic number in exec header");
465
  }
466
}
467
 
468
 
469
void readCode(void) {
470
  unsigned char *buffer;
471
 
472
  if (fseek(inFile, CODE_START(inHeader), SEEK_SET) < 0) {
473
    error("cannot seek to code section");
474
  }
475
  buffer = allocateMemory(inHeader.csize);
476
  if (fread(buffer, 1, inHeader.csize, inFile) != inHeader.csize) {
477
    error("cannot read code segment");
478
  }
479
  if (fwrite(buffer, 1, inHeader.csize, codeFile) != inHeader.csize) {
480
    error("cannot write code segment");
481
  }
482
  freeMemory(buffer);
483
}
484
 
485
 
486
void readData(void) {
487
  unsigned char *buffer;
488
 
489
  if (fseek(inFile, DATA_START(inHeader), SEEK_SET) < 0) {
490
    error("cannot seek to data section");
491
  }
492
  buffer = allocateMemory(inHeader.dsize);
493
  if (fread(buffer, 1, inHeader.dsize, inFile) != inHeader.dsize) {
494
    error("cannot read data segment");
495
  }
496
  if (fwrite(buffer, 1, inHeader.dsize, dataFile) != inHeader.dsize) {
497
    error("cannot write data segment");
498
  }
499
  freeMemory(buffer);
500
}
501
 
502
 
503
void readCodeRelocs(void) {
504
  int n, i;
505
  RelocRecord relRec;
506
 
507
  if (fseek(inFile, CRELOC_START(inHeader), SEEK_SET) < 0) {
508
    error("cannot seek to code relocation section");
509
  }
510
  n = inHeader.crsize / sizeof(RelocRecord);
511
  for (i = 0; i < n; i++) {
512
    if (fread(&relRec, sizeof(RelocRecord), 1, inFile) != 1) {
513
      error("cannot read code relocation records");
514
    }
515
    conv4FromEcoToNative((unsigned char *) &relRec.offset);
516
    conv4FromEcoToNative((unsigned char *) &relRec.method);
517
    conv4FromEcoToNative((unsigned char *) &relRec.value);
518
    conv4FromEcoToNative((unsigned char *) &relRec.base);
519
    addReloc(SEGMENT_CODE, &relRec, symMap);
520
  }
521
}
522
 
523
 
524
void readDataRelocs(void) {
525
  int n, i;
526
  RelocRecord relRec;
527
 
528
  if (fseek(inFile, DRELOC_START(inHeader), SEEK_SET) < 0) {
529
    error("cannot seek to data relocation section");
530
  }
531
  n = inHeader.drsize / sizeof(RelocRecord);
532
  for (i = 0; i < n; i++) {
533
    if (fread(&relRec, sizeof(RelocRecord), 1, inFile) != 1) {
534
      error("cannot read data relocation records");
535
    }
536
    conv4FromEcoToNative((unsigned char *) &relRec.offset);
537
    conv4FromEcoToNative((unsigned char *) &relRec.method);
538
    conv4FromEcoToNative((unsigned char *) &relRec.value);
539
    conv4FromEcoToNative((unsigned char *) &relRec.base);
540
    addReloc(SEGMENT_DATA, &relRec, symMap);
541
  }
542
}
543
 
544
 
545
void readString(unsigned int offset, char *buffer, int size) {
546
  long pos;
547
  int c;
548
 
549
  pos = ftell(inFile);
550
  if (fseek(inFile, STRING_START(inHeader) + offset, SEEK_SET) < 0) {
551
    error("cannot seek to string");
552
  }
553
  do {
554
    c = fgetc(inFile);
555
    if (c == EOF) {
556
      error("unexpected end of file");
557
    }
558
    *buffer++ = c;
559
    if (--size == 0) {
560
      error("string buffer overflow");
561
    }
562
  } while (c != 0);
563
  fseek(inFile, pos, SEEK_SET);
564
}
565
 
566
 
567
void readSymbols(void) {
568
  int n, i;
569
  SymbolRecord symRec;
570
  char strBuf[MAX_STRLEN];
571
  Symbol *sym;
572
 
573
  if (fseek(inFile, SYMTBL_START(inHeader), SEEK_SET) < 0) {
574
    error("cannot seek to symbol table section");
575
  }
576
  n = inHeader.symsize / sizeof(SymbolRecord);
577
  symMap = allocateMemory(n * sizeof(Symbol *));
578
  for (i = 0; i < n; i++) {
579
    if (fread(&symRec, sizeof(SymbolRecord), 1, inFile) != 1) {
580
      error("cannot read symbol table");
581
    }
582
    conv4FromEcoToNative((unsigned char *) &symRec.name);
583
    conv4FromEcoToNative((unsigned char *) &symRec.type);
584
    conv4FromEcoToNative((unsigned char *) &symRec.value);
585
    readString(symRec.name, strBuf, MAX_STRLEN);
586
    sym = lookupEnter(strBuf);
587
    if ((symRec.type & MSB) == 0) {
588
      /* the symbol is defined in this symbol record */
589
      if ((sym->type & MSB) == 0) {
590
        /* the symbol was already defined in the table */
591
        error("symbol '%s' multiply defined", sym->name);
592
      } else {
593
        /* the symbol was not yet defined in the table, so define it now */
594
        /* the segment is copied directly from the file */
595
        /* the value is the sum of the value given in the file */
596
        /* and this module's segment start of the symbol's segment */
597
        sym->type = symRec.type;
598
        sym->value = symRec.value + segPtr[symRec.type];
599
      }
600
    } else {
601
      /* the symbol is undefined in this symbol record */
602
      /* nothing to do here: lookupEnter already entered */
603
      /* the symbol into the symbol table, if necessary */
604
    }
605
    /* in any case remember the symbol table entry, so that */
606
    /* a symbol index in a relocation record can be resolved */
607
    symMap[i] = sym;
608
  }
609
}
610
 
611
 
612
void readModule(void) {
613
  /* read the file header to determine the sizes */
614
  readHeader();
615
  /* read and transfer the code and data segments */
616
  readCode();
617
  readData();
618
  /* read and build the symbol table and a symbol map */
619
  readSymbols();
620
  /* read and build a list of relocation records */
621
  readCodeRelocs();
622
  readDataRelocs();
623
  /* free the symbol map, it is no longer needed */
624
  freeMemory(symMap);
625
  /* update accumulated segment sizes */
626
  segPtr[SEGMENT_CODE] += inHeader.csize;
627
  segPtr[SEGMENT_DATA] += inHeader.dsize;
628
  segPtr[SEGMENT_BSS] += inHeader.bsize;
629
}
630
 
631
 
632
/**************************************************************/
633
 
634
 
635
void printSymbol(Symbol *s) {
636
  fprintf(mapFile, "%-32s", s->name);
637
  if (s->type & MSB) {
638
    /* symbol is undefined */
639
    fprintf(mapFile, "%-15s", "UNDEFINED");
640
  } else {
641
    /* symbol is defined */
642
    switch (s->type) {
643
      case SEGMENT_ABS:
644
        fprintf(mapFile, "%-15s", "ABS");
645
        break;
646
      case SEGMENT_CODE:
647
        fprintf(mapFile, "%-15s", "CODE");
648
        break;
649
      case SEGMENT_DATA:
650
        fprintf(mapFile, "%-15s", "DATA");
651
        break;
652
      case SEGMENT_BSS:
653
        fprintf(mapFile, "%-15s", "BSS");
654
        break;
655
      default:
656
        error("illegal symbol segment in printToMap()");
657
    }
658
  }
659
  fprintf(mapFile, "0x%08X", s->value);
660
  fprintf(mapFile, "\n");
661
}
662
 
663
 
664
void printToMapFile(void) {
665
  walkSymbols(printSymbol);
666
  fprintf(mapFile, "\n");
667
  fprintf(mapFile, "CODE     start 0x%08X     size 0x%08X\n",
668
          segStart[SEGMENT_CODE], segPtr[SEGMENT_CODE]);
669
  fprintf(mapFile, "DATA     start 0x%08X     size 0x%08X\n",
670
          segStart[SEGMENT_DATA], segPtr[SEGMENT_DATA]);
671
  fprintf(mapFile, "BSS      start 0x%08X     size 0x%08X\n",
672
          segStart[SEGMENT_BSS], segPtr[SEGMENT_BSS]);
673
}
674
 
675
 
676
/**************************************************************/
677
 
678
 
679
void writeHeader(void) {
680
  ExecHeader outHeader;
681
 
682
  if (withHeader) {
683
    outHeader.magic = EXEC_MAGIC;
684
    outHeader.csize = segPtr[SEGMENT_CODE];
685
    outHeader.dsize = segPtr[SEGMENT_DATA];
686
    outHeader.bsize = segPtr[SEGMENT_BSS];
687
    outHeader.crsize = 0;
688
    outHeader.drsize = 0;
689
    outHeader.symsize = 0;
690
    outHeader.strsize = 0;
691
    conv4FromNativeToEco((unsigned char *) &outHeader.magic);
692
    conv4FromNativeToEco((unsigned char *) &outHeader.csize);
693
    conv4FromNativeToEco((unsigned char *) &outHeader.dsize);
694
    conv4FromNativeToEco((unsigned char *) &outHeader.bsize);
695
    conv4FromNativeToEco((unsigned char *) &outHeader.crsize);
696
    conv4FromNativeToEco((unsigned char *) &outHeader.drsize);
697
    conv4FromNativeToEco((unsigned char *) &outHeader.symsize);
698
    conv4FromNativeToEco((unsigned char *) &outHeader.strsize);
699
    fwrite(&outHeader, sizeof(ExecHeader), 1, outFile);
700
  }
701
}
702
 
703
 
704
void writeCode(void) {
705
  int data;
706
 
707
  rewind(codeFile);
708
  while (1) {
709
    data = fgetc(codeFile);
710
    if (data == EOF) {
711
      break;
712
    }
713
    fputc(data, outFile);
714
  }
715
}
716
 
717
 
718
void writeData(void) {
719
  int data;
720
 
721
  rewind(dataFile);
722
  while (1) {
723
    data = fgetc(dataFile);
724
    if (data == EOF) {
725
      break;
726
    }
727
    fputc(data, outFile);
728
  }
729
}
730
 
731
 
732
/**************************************************************/
733
 
734
 
735
int readNumber(char *str, unsigned int *np) {
736
  int base;
737
  int value;
738
  int digit;
739
 
740
  base = 10;
741
  value = 0;
742
  if (*str == '0') {
743
    str++;
744
    if (*str == 'x' || *str == 'X') {
745
      base = 16;
746
      str++;
747
    } else
748
    if (isdigit((int) *str)) {
749
      base = 8;
750
    } else
751
    if (*str == '\0') {
752
      *np = value;
753
      return 1;
754
    } else {
755
      return 0;
756
    }
757
  }
758
  while (isxdigit((int) *str)) {
759
    digit = *str++ - '0';
760
    if (digit >= 'A' - '0') {
761
      if (digit >= 'a' - '0') {
762
        digit += '0' - 'a' + 10;
763
      } else {
764
        digit += '0' - 'A' + 10;
765
      }
766
    }
767
    if (digit >= base) {
768
      return 0;
769
    }
770
    value *= base;
771
    value += digit;
772
  }
773
  if (*str == '\0') {
774
    *np = value;
775
    return 1;
776
  } else {
777
    return 0;
778
  }
779
}
780
 
781
 
782
void usage(char *myself) {
783
  fprintf(stderr, "Usage: %s\n", myself);
784
  fprintf(stderr, "         [-h]             do not write object header\n");
785
  fprintf(stderr, "         [-o objfile]     set output file name\n");
786
  fprintf(stderr, "         [-m mapfile]     produce map file\n");
787
  fprintf(stderr, "         [-rc addr]       relocate code segment\n");
788
  fprintf(stderr, "         [-rd addr]       relocate data segment\n");
789
  fprintf(stderr, "         [-rb addr]       relocate bss segment\n");
790
  fprintf(stderr, "         file             object file name\n");
791
  fprintf(stderr, "         [files...]       additional object files\n");
792
  exit(1);
793
}
794
 
795
 
796
int main(int argc, char *argv[]) {
797
  int i;
798
  char *argp;
799
  unsigned int *ssp;
800
  int *ssdp;
801
 
802
  tmpnam(codeName);
803
  tmpnam(dataName);
804
  outName = "a.out";
805
  for (i = 1; i < argc; i++) {
806
    argp = argv[i];
807
    if (*argp != '-') {
808
      break;
809
    }
810
    argp++;
811
    switch (*argp) {
812
      case 'h':
813
        withHeader = 0;
814
        break;
815
      case 'o':
816
        if (i == argc - 1) {
817
          usage(argv[0]);
818
        }
819
        outName = argv[++i];
820
        break;
821
      case 'm':
822
        if (i == argc - 1) {
823
          usage(argv[0]);
824
        }
825
        mapName = argv[++i];
826
        break;
827
      case 'r':
828
        if (argp[1] == 'c') {
829
          ssp = &segStart[SEGMENT_CODE];
830
          ssdp = &segStartDefined[SEGMENT_CODE];
831
        } else
832
        if (argp[1] == 'd') {
833
          ssp = &segStart[SEGMENT_DATA];
834
          ssdp = &segStartDefined[SEGMENT_DATA];
835
        } else
836
        if (argp[1] == 'b') {
837
          ssp = &segStart[SEGMENT_BSS];
838
          ssdp = &segStartDefined[SEGMENT_BSS];
839
        } else {
840
          usage(argv[0]);
841
        }
842
        if (i == argc - 1) {
843
          usage(argv[0]);
844
        }
845
        if (!readNumber(argv[++i], ssp)) {
846
          error("cannot read number given with option '-%s'", argp);
847
        }
848
        *ssdp = 1;
849
        break;
850
      default:
851
        usage(argv[0]);
852
    }
853
  }
854
  if (i == argc) {
855
    usage(argv[0]);
856
  }
857
  codeFile = fopen(codeName, "w+b");
858
  if (codeFile == NULL) {
859
    error("cannot create temporary code file '%s'", codeName);
860
  }
861
  dataFile = fopen(dataName, "w+b");
862
  if (dataFile == NULL) {
863
    error("cannot create temporary data file '%s'", dataName);
864
  }
865
  outFile = fopen(outName, "wb");
866
  if (outFile == NULL) {
867
    error("cannot open output file '%s'", outName);
868
  }
869
  if (mapName != NULL) {
870
    mapFile = fopen(mapName, "wt");
871
    if (mapFile == NULL) {
872
      error("cannot open map file '%s'", mapName);
873
    }
874
  }
875
  do {
876
    inName = argv[i];
877
    if (*inName == '-') {
878
      usage(argv[0]);
879
    }
880
    inFile = fopen(inName, "rb");
881
    if (inFile == NULL) {
882
      error("cannot open input file '%s'", inName);
883
    }
884
    fprintf(stderr, "Reading module '%s'...\n", inName);
885
    readModule();
886
    if (inFile != NULL) {
887
      fclose(inFile);
888
      inFile = NULL;
889
    }
890
  } while (++i < argc);
891
  fprintf(stderr, "Linking modules...\n");
892
  linkSymbols();
893
  fprintf(stderr, "Relocating segments...\n");
894
  relocateSegments();
895
  writeHeader();
896
  writeCode();
897
  writeData();
898
  if (mapFile != NULL) {
899
    printToMapFile();
900
  }
901
  if (codeFile != NULL) {
902
    fclose(codeFile);
903
    codeFile = NULL;
904
  }
905
  if (dataFile != NULL) {
906
    fclose(dataFile);
907
    dataFile = NULL;
908
  }
909
  if (outFile != NULL) {
910
    fclose(outFile);
911
    outFile = NULL;
912
  }
913
  if (mapFile != NULL) {
914
    fclose(mapFile);
915
    mapFile = NULL;
916
  }
917
  if (codeName != NULL) {
918
    unlink(codeName);
919
  }
920
  if (dataName != NULL) {
921
    unlink(dataName);
922
  }
923
  return 0;
924
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.