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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [cpu/] [common/] [parse.c] - Blame information for rev 73

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

Line No. Rev Author Line
1 19 jeremybenn
/* parse.c -- Architecture independent load
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
#include "port.h"
30
 
31
/* System includes */
32
#include <stdlib.h>
33
 
34
/* Package includes */
35
#include "parse.h"
36
#include "sim-config.h"
37
#include "debug.h"
38
#include "abstract.h"
39
#include "opcode/or32.h"
40
#include "coff.h"
41
#include "elf.h"
42
#include "labels.h"
43
 
44
 
45
DECLARE_DEBUG_CHANNEL (coff)
46
 
47
#define MEMORY_LEN  0x100000000ULL
48
 
49
/*!Whether to do immediate statistics. This seems to be for local debugging
50
   of parse.c */
51
#define IMM_STATS 0
52
 
53
/*!Unused mem memory marker. It is used when allocating program and data
54
   memory during parsing */
55
static unsigned int  freemem;
56
 
57
/*!Translation table provided by microkernel. Only used if simulating
58
   microkernel. */
59
static oraddr_t  transl_table;
60
 
61
/*!Used to signal whether during loading of programs a translation fault
62
   occured. */
63
static uint32_t  transl_error;
64
 
65
#if IMM_STATS
66
static int       bcnt[33][3] = { 0 };
67
static int       bsum[3]     = { 0 };
68
static uint32_t  movhi       = 0;
69
#endif  /* IMM_STATS */
70
 
71
/*---------------------------------------------------------------------------*/
72
/*!Copy a string with null termination
73
 
74
   This function is very similar to strncpy, except it null terminates the
75
   string. A global function also used by the CUC.
76
 
77
   @param[in] dst  The destination string
78
   @param[in] src  The source string
79
   @param[in] n    Number of chars to copy EXCLUDING the null terminator
80
                   (i.e. dst had better have room for n+1 chars)
81
 
82
   @return  A pointer to dst                                                 */
83
/*---------------------------------------------------------------------------*/
84
char *
85
strstrip (char       *dst,
86
          const char *src,
87
          int         n)
88
{
89
  strncpy (dst, src, n);
90
  *(dst + n) = '\0';
91
 
92
  return  dst;
93
 
94
}       /* strstrip () */
95
 
96
/*---------------------------------------------------------------------------*/
97
/*!Translate logical to physical addresses for the loader
98
 
99
   Used only by the simulator loader to translate logical addresses into
100
   physical.  If loadcode() is called with valid @c virtphy_transl pointer to
101
   a table of translations then translate() performs translation otherwise
102
   physical address is equal to logical.
103
 
104
   @param[in] laddr       Logical address
105
   @param[in] breakpoint  Unused
106
 
107
   @return  The physical address                                             */
108
/*---------------------------------------------------------------------------*/
109
static oraddr_t
110
translate (oraddr_t  laddr,
111
           int      *breakpoint)
112
{
113
  int i;
114
 
115
  /* No translation (i.e. when loading kernel into simulator) */
116
  if (transl_table == 0)
117
    {
118
      return laddr;
119
    }
120
 
121
  /* Try to find our translation in the table. */
122
  for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16)
123
    {
124
      if ((laddr & ~(PAGE_SIZE - 1)) == eval_direct32 (transl_table + i, 0, 0))
125
        {
126
          /* Page modified */
127
          set_direct32 (transl_table + i + 8, -2, 0, 0);
128
          PRINTF ("found paddr=%" PRIx32 "\n",
129
                  eval_direct32 (transl_table + i + 4, 0, 0) |
130
                  (laddr & (PAGE_SIZE - 1)));
131
          return  (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) |
132
                  (laddr & (oraddr_t) (PAGE_SIZE - 1));
133
        }
134
    }
135
 
136
  /* Allocate new phy page for us. */
137
  for (i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16)
138
    {
139
      if (eval_direct32 (transl_table + i + 8, 0, 0) == 0)
140
        {
141
          /* VPN */
142
          set_direct32 (transl_table + i, laddr & ~(PAGE_SIZE - 1), 0, 0);
143
          /* PPN */
144
          set_direct32 (transl_table + i + 4, (i / 16) * PAGE_SIZE, 0, 0);
145
          /* Page modified */
146
          set_direct32 (transl_table + i + 8, -2, 0, 0);
147
          PRINTF ("newly allocated ppn=%" PRIx32 "\n",
148
                  eval_direct32 (transl_table + i + 4, 0, 0));
149
          PRINTF ("newly allocated .ppn=%" PRIxADDR "\n", transl_table + i + 4);
150
          PRINTF ("newly allocated ofs=%" PRIxADDR "\n",
151
                  (laddr & (PAGE_SIZE - 1)));
152
          PRINTF ("newly allocated paddr=%" PRIx32 "\n",
153
                  eval_direct32 (transl_table + i + 4, 0,
154
                                 0) | (laddr & (PAGE_SIZE - 1)));
155
          return  (oraddr_t) eval_direct32 (transl_table + i + 4, 0, 0) |
156
                  (laddr & (oraddr_t) (PAGE_SIZE - 1));
157
        }
158
    }
159
 
160
  /* If we come this far then all phy memory is used and we can't find our
161
     page nor allocate new page. */
162
  transl_error = 1;
163
  PRINTF ("can't translate %" PRIxADDR "\n", laddr);
164
  exit (1);
165
 
166
  return  -1;
167
 
168
}       /* translate() */
169
 
170
#if IMM_STATS
171
static int
172
bits (uint32_t val)
173
{
174
  int i = 1;
175
  if (!val)
176
    return 0;
177
  while (val != 0 && (int32_t) val != -1)
178
    {
179
      i++;
180
      val = (int32_t) val >> 1;
181
    }
182
  return i;
183
}
184
 
185
static void
186
check_insn (uint32_t insn)
187
{
188
  int insn_index = insn_decode (insn);
189
  struct insn_op_struct *opd = op_start[insn_index];
190
  uint32_t data = 0;
191
  int dis = 0;
192
  const char *name;
193
  if (!insn || insn_index < 0)
194
    return;
195
  name = insn_name (insn_index);
196
  if (strcmp (name, "l.nop") == 0 || strcmp (name, "l.sys") == 0)
197
    return;
198
 
199
  while (1)
200
    {
201
      uint32_t tmp = 0 unsigned int nbits = 0;
202
      while (1)
203
        {
204
          tmp |=
205
            ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) <<
206
            nbits;
207
          nbits += opd->data;
208
          if (opd->type & OPTYPE_OP)
209
            break;
210
          opd++;
211
        }
212
 
213
      /* Do we have to sign extend? */
214
      if (opd->type & OPTYPE_SIG)
215
        {
216
          int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
217
          if (tmp & (1 << sbit))
218
            tmp |= 0xFFFFFFFF << sbit;
219
        }
220
      if (opd->type & OPTYPE_DIS)
221
        {
222
          /* We have to read register later.  */
223
          data += tmp;
224
          dis = 1;
225
        }
226
      else
227
        {
228
          if (!(opd->type & OPTYPE_REG) || dis)
229
            {
230
              if (!dis)
231
                data = tmp;
232
              if (strcmp (name, "l.movhi") == 0)
233
                {
234
                  movhi = data << 16;
235
                }
236
              else
237
                {
238
                  data |= movhi;
239
                  //PRINTF ("%08x %s\n", data, name);
240
                  if (!(or32_opcodes[insn_index].flags & OR32_IF_DELAY))
241
                    {
242
                      bcnt[bits (data)][0]++;
243
                      bsum[0]++;
244
                    }
245
                  else
246
                    {
247
                      if (strcmp (name, "l.bf") == 0
248
                          || strcmp (name, "l.bnf") == 0)
249
                        {
250
                          bcnt[bits (data)][1]++;
251
                          bsum[1]++;
252
                        }
253
                      else
254
                        {
255
                          bcnt[bits (data)][2]++;
256
                          bsum[2]++;
257
                        }
258
                    }
259
                }
260
            }
261
          data = 0;
262
          dis = 0;
263
        }
264
      if (opd->type & OPTYPE_LAST)
265
        {
266
          return;
267
        }
268
      opd++;
269
    }
270
}
271
#endif
272
 
273
/*---------------------------------------------------------------------------*/
274
/*!Add an instruction to the program
275
 
276
  @note insn must be in big endian format
277
 
278
  @param[in] address     The address to use
279
  @param[in] insn        The instruction to add
280
  @param[in] breakpoint  Not used (it is passed to the translate() function,
281
                         which also does not use it.                         */
282
/*---------------------------------------------------------------------------*/
283
static void
284
addprogram (oraddr_t  address,
285
            uint32_t  insn,
286
            int      *breakpoint)
287
{
288
  int vaddr = (!runtime.sim.filename) ? translate (address, breakpoint) :
289
                                        translate (freemem, breakpoint);
290
 
291
  /* We can't have set_program32 functions since it is not gauranteed that the
292
     section we're loading is aligned on a 4-byte boundry */
293
  set_program8 (vaddr, (insn >> 24) & 0xff);
294
  set_program8 (vaddr + 1, (insn >> 16) & 0xff);
295
  set_program8 (vaddr + 2, (insn >> 8) & 0xff);
296
  set_program8 (vaddr + 3, insn & 0xff);
297
 
298
#if IMM_STATS
299
  check_insn (insn);
300
#endif
301
 
302
  if (runtime.sim.filename)
303
    {
304
      freemem += insn_len (insn_decode (insn));
305
    }
306
}       /* addprogram () */
307
 
308
 
309
/*---------------------------------------------------------------------------*/
310
/*!Load big-endian COFF file
311
 
312
   @param[in] filename  File to load
313
   @param[in] sections  Number of sections in file                           */
314
/*---------------------------------------------------------------------------*/
315
static void
316
readfile_coff (char  *filename,
317
               short  sections)
318
{
319
  FILE *inputfs;
320
  char inputbuf[4];
321
  uint32_t insn;
322
  int32_t sectsize;
323
  COFF_AOUTHDR coffaouthdr;
324
  struct COFF_scnhdr coffscnhdr;
325
  int len;
326
  int firstthree = 0;
327
  int breakpoint = 0;
328
 
329
  if (!(inputfs = fopen (filename, "r")))
330
    {
331
      perror ("readfile_coff");
332
      exit (1);
333
    }
334
 
335
  if (fseek (inputfs, sizeof (struct COFF_filehdr), SEEK_SET) == -1)
336
    {
337
      fclose (inputfs);
338
      perror ("readfile_coff");
339
      exit (1);
340
    }
341
 
342
  if (fread (&coffaouthdr, sizeof (coffaouthdr), 1, inputfs) != 1)
343
    {
344
      fclose (inputfs);
345
      perror ("readfile_coff");
346
      exit (1);
347
    }
348
 
349
  while (sections--)
350
    {
351
      uint32_t scnhdr_pos =
352
        sizeof (struct COFF_filehdr) + sizeof (coffaouthdr) +
353
        sizeof (struct COFF_scnhdr) * firstthree;
354
      if (fseek (inputfs, scnhdr_pos, SEEK_SET) == -1)
355
        {
356
          fclose (inputfs);
357
          perror ("readfile_coff");
358
          exit (1);
359
        }
360
      if (fread (&coffscnhdr, sizeof (struct COFF_scnhdr), 1, inputfs) != 1)
361
        {
362
          fclose (inputfs);
363
          perror ("readfile_coff");
364
          exit (1);
365
        }
366
      PRINTF ("Section: %s,", coffscnhdr.s_name);
367
      PRINTF (" paddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_paddr));
368
      PRINTF (" vaddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_vaddr));
369
      PRINTF (" size: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_size));
370
      PRINTF (" scnptr: 0x%.8lx\n", COFF_LONG_H (coffscnhdr.s_scnptr));
371
 
372
      sectsize = COFF_LONG_H (coffscnhdr.s_size);
373
      ++firstthree;
374
 
375
      /* loading section */
376
      freemem = COFF_LONG_H (coffscnhdr.s_paddr);
377
      if (fseek (inputfs, COFF_LONG_H (coffscnhdr.s_scnptr), SEEK_SET) == -1)
378
        {
379
          fclose (inputfs);
380
          perror ("readfile_coff");
381
          exit (1);
382
        }
383
      while (sectsize > 0
384
             && (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs)))
385
        {
386
          insn = COFF_LONG_H (inputbuf);
387
          len = insn_len (insn_decode (insn));
388
          if (len == 2)
389
            {
390
              fseek (inputfs, -2, SEEK_CUR);
391
            }
392
 
393
          addprogram (freemem, insn, &breakpoint);
394
          sectsize -= len;
395
        }
396
    }
397
  if (firstthree < 3)
398
    {
399
      PRINTF ("One or more missing sections. At least");
400
      PRINTF (" three sections expected (.text, .data, .bss).\n");
401
      exit (1);
402
    }
403
  if (firstthree > 3)
404
    {
405
      PRINTF ("Warning: one or more extra sections. These");
406
      PRINTF (" sections were handled as .data sections.\n");
407
    }
408
 
409
  fclose (inputfs);
410
  PRINTF ("Finished loading COFF.\n");
411
  return;
412
 
413
}       /* readfile_coff () */
414
 
415
 
416
/* Load symbols from big-endian COFF file. */
417
 
418
static void
419
readsyms_coff (char *filename, uint32_t symptr, uint32_t syms)
420
{
421
  FILE *inputfs;
422
  struct COFF_syment coffsymhdr;
423
  int count = 0;
424
  uint32_t nsyms = syms;
425
  if (!(inputfs = fopen (filename, "r")))
426
    {
427
      perror ("readsyms_coff");
428
      exit (1);
429
    }
430
 
431
  if (fseek (inputfs, symptr, SEEK_SET) == -1)
432
    {
433
      fclose (inputfs);
434
      perror ("readsyms_coff");
435
      exit (1);
436
    }
437
 
438
  while (syms--)
439
    {
440
      int i, n;
441
      if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1)
442
        {
443
          fclose (inputfs);
444
          perror ("readsyms_coff");
445
          exit (1);
446
        }
447
 
448
      n = (unsigned char) coffsymhdr.e_numaux[0];
449
 
450
      /* check whether this symbol belongs to a section and is external
451
         symbol; ignore all others */
452
      if (COFF_SHORT_H (coffsymhdr.e_scnum) >= 0
453
          && coffsymhdr.e_sclass[0] == C_EXT)
454
        {
455
          if (*((uint32_t *) coffsymhdr.e.e.e_zeroes))
456
            {
457
              if (strlen (coffsymhdr.e.e_name)
458
                  && strlen (coffsymhdr.e.e_name) < 9)
459
                add_label (COFF_LONG_H (coffsymhdr.e_value),
460
                           coffsymhdr.e.e_name);
461
            }
462
          else
463
            {
464
              uint32_t fpos = ftell (inputfs);
465
 
466
              if (fseek
467
                  (inputfs,
468
                   symptr + nsyms * COFF_SYMESZ +
469
                   COFF_LONG_H (coffsymhdr.e.e.e_offset), SEEK_SET) == 0)
470
                {
471
                  char tmp[33], *s = &tmp[0];
472
                  while (s != &tmp[32])
473
                    if ((*(s++) = fgetc (inputfs)) == 0)
474
                      break;
475
                  tmp[32] = 0;
476
                  add_label (COFF_LONG_H (coffsymhdr.e_value), &tmp[0]);
477
                }
478
              fseek (inputfs, fpos, SEEK_SET);
479
            }
480
        }
481
 
482
      for (i = 0; i < n; i++)
483
        if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1)
484
          {
485
            fclose (inputfs);
486
            perror ("readsyms_coff3");
487
            exit (1);
488
          }
489
      syms -= n;
490
      count += n;
491
    }
492
 
493
  fclose (inputfs);
494
  PRINTF ("Finished loading symbols.\n");
495
  return;
496
}
497
 
498
static void
499
readfile_elf (char *filename)
500
{
501
 
502
  FILE *inputfs;
503
  struct elf32_hdr elfhdr;
504
  struct elf32_phdr *elf_phdata = NULL;
505
  struct elf32_shdr *elf_spnt, *elf_shdata;
506
  struct elf32_sym *sym_tbl = (struct elf32_sym *) 0;
507
  uint32_t syms = 0;
508
  char *str_tbl = (char *) 0;
509
  char *s_str = (char *) 0;
510
  int breakpoint = 0;
511
  uint32_t inputbuf;
512
  uint32_t padd;
513
  uint32_t insn;
514
  int i, j, sectsize, len;
515
 
516
  if (!(inputfs = fopen (filename, "r")))
517
    {
518
      perror ("readfile_elf");
519
      exit (1);
520
    }
521
 
522
  if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) != 1)
523
    {
524
      perror ("readfile_elf");
525
      exit (1);
526
    }
527
 
528
  if ((elf_shdata =
529
       (struct elf32_shdr *) malloc (ELF_SHORT_H (elfhdr.e_shentsize) *
530
                                     ELF_SHORT_H (elfhdr.e_shnum))) == NULL)
531
    {
532
      perror ("readfile_elf");
533
      exit (1);
534
    }
535
 
536
  if (fseek (inputfs, ELF_LONG_H (elfhdr.e_shoff), SEEK_SET) != 0)
537
    {
538
      perror ("readfile_elf");
539
      exit (1);
540
    }
541
 
542
  if (fread
543
      (elf_shdata,
544
       ELF_SHORT_H (elfhdr.e_shentsize) * ELF_SHORT_H (elfhdr.e_shnum), 1,
545
       inputfs) != 1)
546
    {
547
      perror ("readfile_elf");
548
      exit (1);
549
    }
550
 
551
  if (ELF_LONG_H (elfhdr.e_phoff))
552
    {
553
      if ((elf_phdata =
554
           (struct elf32_phdr *) malloc (ELF_SHORT_H (elfhdr.e_phnum) *
555
                                         ELF_SHORT_H (elfhdr.e_phentsize))) ==
556
          NULL)
557
        {
558
          perror ("readfile_elf");
559
          exit (1);
560
        }
561
 
562
      if (fseek (inputfs, ELF_LONG_H (elfhdr.e_phoff), SEEK_SET) != 0)
563
        {
564
          perror ("readfile_elf");
565
          exit (1);
566
        }
567
 
568
      if (fread
569
          (elf_phdata,
570
           ELF_SHORT_H (elfhdr.e_phnum) * ELF_SHORT_H (elfhdr.e_phentsize),
571
           1, inputfs) != 1)
572
        {
573
          perror ("readfile_elf");
574
          exit (1);
575
        }
576
    }
577
 
578
  for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum);
579
       i++, elf_spnt++)
580
    {
581
 
582
      if (ELF_LONG_H (elf_spnt->sh_type) == SHT_STRTAB)
583
        {
584
          if (NULL != str_tbl)
585
            {
586
              free (str_tbl);
587
            }
588
 
589
          if ((str_tbl =
590
               (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL)
591
            {
592
              perror ("readfile_elf");
593
              exit (1);
594
            }
595
 
596
          if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
597
              0)
598
            {
599
              perror ("readfile_elf");
600
              exit (1);
601
            }
602
 
603
          if (fread (str_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) !=
604
              1)
605
            {
606
              perror ("readfile_elf");
607
              exit (1);
608
            }
609
        }
610
      else if (ELF_LONG_H (elf_spnt->sh_type) == SHT_SYMTAB)
611
        {
612
 
613
          if (NULL != sym_tbl)
614
            {
615
              free (sym_tbl);
616
            }
617
 
618
          if ((sym_tbl =
619
               (struct elf32_sym *) malloc (ELF_LONG_H (elf_spnt->sh_size)))
620
              == NULL)
621
            {
622
              perror ("readfile_elf");
623
              exit (1);
624
            }
625
 
626
          if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
627
              0)
628
            {
629
              perror ("readfile_elf");
630
              exit (1);
631
            }
632
 
633
          if (fread (sym_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) !=
634
              1)
635
            {
636
              perror ("readfile_elf");
637
              exit (1);
638
            }
639
 
640
          syms =
641
            ELF_LONG_H (elf_spnt->sh_size) /
642
            ELF_LONG_H (elf_spnt->sh_entsize);
643
        }
644
    }
645
 
646
  if (ELF_SHORT_H (elfhdr.e_shstrndx) != SHN_UNDEF)
647
    {
648
      elf_spnt = &elf_shdata[ELF_SHORT_H (elfhdr.e_shstrndx)];
649
 
650
      if ((s_str = (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL)
651
        {
652
          perror ("readfile_elf");
653
          exit (1);
654
        }
655
 
656
      if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != 0)
657
        {
658
          perror ("readfile_elf");
659
          exit (1);
660
        }
661
 
662
      if (fread (s_str, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != 1)
663
        {
664
          perror ("readfile_elf");
665
          exit (1);
666
        }
667
    }
668
 
669
 
670
  for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum);
671
       i++, elf_spnt++)
672
    {
673
 
674
      if ((ELF_LONG_H (elf_spnt->sh_type) & SHT_PROGBITS)
675
          && (ELF_LONG_H (elf_spnt->sh_flags) & SHF_ALLOC))
676
        {
677
 
678
          padd = ELF_LONG_H (elf_spnt->sh_addr);
679
          for (j = 0; j < ELF_SHORT_H (elfhdr.e_phnum); j++)
680
            {
681
              if (ELF_LONG_H (elf_phdata[j].p_offset) &&
682
                  ELF_LONG_H (elf_phdata[j].p_offset) <=
683
                  ELF_LONG_H (elf_spnt->sh_offset)
684
                  && (ELF_LONG_H (elf_phdata[j].p_offset) +
685
                      ELF_LONG_H (elf_phdata[j].p_memsz)) >
686
                  ELF_LONG_H (elf_spnt->sh_offset))
687
                padd =
688
                  ELF_LONG_H (elf_phdata[j].p_paddr) +
689
                  ELF_LONG_H (elf_spnt->sh_offset) -
690
                  ELF_LONG_H (elf_phdata[j].p_offset);
691
            }
692
 
693
 
694
 
695
          if (ELF_LONG_H (elf_spnt->sh_name) && s_str)
696
            PRINTF ("Section: %s,", &s_str[ELF_LONG_H (elf_spnt->sh_name)]);
697
          else
698
            PRINTF ("Section: noname,");
699
          PRINTF (" vaddr: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_addr));
700
          PRINTF (" paddr: 0x%" PRIx32, padd);
701
          PRINTF (" offset: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_offset));
702
          PRINTF (" size: 0x%.8lx\n", ELF_LONG_H (elf_spnt->sh_size));
703
 
704
          freemem = padd;
705
          sectsize = ELF_LONG_H (elf_spnt->sh_size);
706
 
707
          if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
708
              0)
709
            {
710
              perror ("readfile_elf");
711
              free (elf_phdata);
712
              exit (1);
713
            }
714
 
715
          while (sectsize > 0
716
                 && (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs)))
717
            {
718
              insn = ELF_LONG_H (inputbuf);
719
              addprogram (freemem, insn, &breakpoint);
720
              sectsize -= 4;
721
            }
722
        }
723
    }
724
 
725
  if (str_tbl)
726
    {
727
      i = 0;
728
      while (syms--)
729
        {
730
          if (sym_tbl[i].st_name && sym_tbl[i].st_info
731
              && ELF_SHORT_H (sym_tbl[i].st_shndx) < 0x8000)
732
            {
733
              add_label (ELF_LONG_H (sym_tbl[i].st_value),
734
                         &str_tbl[ELF_LONG_H (sym_tbl[i].st_name)]);
735
            }
736
          i++;
737
        }
738
    }
739
 
740
  if (NULL != str_tbl)
741
    {
742
      free (str_tbl);
743
    }
744
 
745
  if (NULL != sym_tbl)
746
    {
747
      free (sym_tbl);
748
    }
749
 
750
  free (s_str);
751
  free (elf_phdata);
752
  free (elf_shdata);
753
 
754
}
755
 
756
/* Identify file type and call appropriate readfile_X routine. It only
757
handles orX-coff-big executables at the moment. */
758
 
759
static void
760
identifyfile (char *filename)
761
{
762
  FILE *inputfs;
763
  struct COFF_filehdr coffhdr;
764
  struct elf32_hdr elfhdr;
765
 
766
  if (!(inputfs = fopen (filename, "r")))
767
    {
768
      perror (filename);
769
      fflush (stdout);
770
      fflush (stderr);
771
      exit (1);
772
    }
773
 
774
  if (fread (&coffhdr, sizeof (coffhdr), 1, inputfs) == 1)
775
    {
776
      if (COFF_SHORT_H (coffhdr.f_magic) == 0x17a)
777
        {
778
          uint32_t opthdr_size;
779
          PRINTF ("COFF magic: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_magic));
780
          PRINTF ("COFF flags: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_flags));
781
          PRINTF ("COFF symptr: 0x%.8lx\n", COFF_LONG_H (coffhdr.f_symptr));
782
          if ((COFF_SHORT_H (coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC)
783
            {
784
              PRINTF ("This COFF is not an executable.\n");
785
              exit (1);
786
            }
787
          opthdr_size = COFF_SHORT_H (coffhdr.f_opthdr);
788
          if (opthdr_size != sizeof (COFF_AOUTHDR))
789
            {
790
              PRINTF ("COFF optional header is missing or not recognized.\n");
791
              PRINTF ("COFF f_opthdr: 0x%" PRIx32 "\n", opthdr_size);
792
              exit (1);
793
            }
794
          fclose (inputfs);
795
          readfile_coff (filename, COFF_SHORT_H (coffhdr.f_nscns));
796
          readsyms_coff (filename, COFF_LONG_H (coffhdr.f_symptr),
797
                         COFF_LONG_H (coffhdr.f_nsyms));
798
          return;
799
        }
800
      else
801
        {
802
          PRINTF ("Not COFF file format\n");
803
          fseek (inputfs, 0, SEEK_SET);
804
        }
805
    }
806
  if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) == 1)
807
    {
808
      if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45
809
          && elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46)
810
        {
811
          PRINTF ("ELF type: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_type));
812
          PRINTF ("ELF machine: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_machine));
813
          PRINTF ("ELF version: 0x%.8lx\n", ELF_LONG_H (elfhdr.e_version));
814
          PRINTF ("ELF sec = %d\n", ELF_SHORT_H (elfhdr.e_shnum));
815
          if (ELF_SHORT_H (elfhdr.e_type) != ET_EXEC)
816
            {
817
              PRINTF ("This ELF is not an executable.\n");
818
              exit (1);
819
            }
820
          fclose (inputfs);
821
          readfile_elf (filename);
822
          return;
823
        }
824
      else
825
        {
826
          PRINTF ("Not ELF file format.\n");
827
          fseek (inputfs, 0, SEEK_SET);
828
        }
829
    }
830
 
831
  perror ("identifyfile2");
832
  fclose (inputfs);
833
 
834
  return;
835
}
836
 
837
 
838
/*---------------------------------------------------------------------------*/
839
/*!Load file to memory
840
 
841
   Loads file to memory starting at address startaddr and returns freemem.
842
 
843
   @param[in] filename        File to load
844
   @param[in] startaddr       Start address at which to load
845
   @param[in] virtphy_transl  Virtual to physical transation table if
846
                              required. Only used for microkernel simulation,
847
                              and not used in Ork1sim at present (set to NULL)
848
 
849
   @return  zero on success, negative on failure.                            */
850
/*---------------------------------------------------------------------------*/
851
uint32_t
852
loadcode (char *filename, oraddr_t startaddr, oraddr_t virtphy_transl)
853
{
854
  int breakpoint = 0;
855
 
856
  transl_error = 0;
857
  transl_table = virtphy_transl;
858
  freemem      = startaddr;
859
  PRINTF ("loadcode: filename %s  startaddr=%" PRIxADDR "  virtphy_transl=%"
860
          PRIxADDR "\n", filename, startaddr, virtphy_transl);
861
  identifyfile (filename);
862
 
863
#if IMM_STATS
864
  {
865
    int i = 0, a = 0, b = 0, c = 0;
866
    PRINTF ("index:arith/branch/jump\n");
867
    for (i = 0; i < 33; i++)
868
      PRINTF ("%2i:\t%3.0f%% / %3.0f%%/ %3.0f%%\t%5i / %5i / %5i\n", i,
869
              100. * (a += bcnt[i][0]) / bsum[0], 100. * (b +=
870
                                                          bcnt[i][1]) /
871
              bsum[1], 100. * (c +=
872
                               bcnt[i][2]) / bsum[2], bcnt[i][0],
873
              bcnt[i][1], bcnt[i][2]);
874
    PRINTF ("\nsum %i %i %i\n", bsum[0], bsum[1], bsum[2]);
875
  }
876
#endif
877
 
878
  if (transl_error)
879
    return -1;
880
  else
881
    return translate (freemem, &breakpoint);
882
 
883
}

powered by: WebSVN 2.1.0

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