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

Subversion Repositories openrisc

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

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 220 jeremybenn
          PRINTFQ ("found paddr=%" PRIx32 "\n",
129 19 jeremybenn
                  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 220 jeremybenn
          PRINTFQ ("newly allocated ppn=%" PRIx32 "\n",
148 19 jeremybenn
                  eval_direct32 (transl_table + i + 4, 0, 0));
149 220 jeremybenn
          PRINTFQ ("newly allocated .ppn=%" PRIxADDR "\n", transl_table + i + 4);
150
          PRINTFQ ("newly allocated ofs=%" PRIxADDR "\n",
151 19 jeremybenn
                  (laddr & (PAGE_SIZE - 1)));
152 220 jeremybenn
          PRINTFQ ("newly allocated paddr=%" PRIx32 "\n",
153 19 jeremybenn
                  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 220 jeremybenn
  PRINTFQ ("can't translate %" PRIxADDR "\n", laddr);
164 19 jeremybenn
  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 230 jeremybenn
  int insn_index = or1ksim_insn_decode (insn);
189
  struct insn_op_struct *opd = or1ksim_op_start[insn_index];
190 19 jeremybenn
  uint32_t data = 0;
191
  int dis = 0;
192
  const char *name;
193
  if (!insn || insn_index < 0)
194
    return;
195 230 jeremybenn
  name = or1ksim_insn_name (insn_index);
196 19 jeremybenn
  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 230 jeremybenn
                  if (!(or1ksim_or32_opcodes[insn_index].flags & OR32_IF_DELAY))
241 19 jeremybenn
                    {
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 230 jeremybenn
      freemem += or1ksim_insn_len (or1ksim_insn_decode (insn));
305 19 jeremybenn
    }
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 220 jeremybenn
      PRINTFQ ("Section: %s,", coffscnhdr.s_name);
367
      PRINTFQ (" paddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_paddr));
368
      PRINTFQ (" vaddr: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_vaddr));
369
      PRINTFQ (" size: 0x%.8lx,", COFF_LONG_H (coffscnhdr.s_size));
370
      PRINTFQ (" scnptr: 0x%.8lx\n", COFF_LONG_H (coffscnhdr.s_scnptr));
371 19 jeremybenn
 
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 230 jeremybenn
          len = or1ksim_insn_len (or1ksim_insn_decode (insn));
388 19 jeremybenn
          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 220 jeremybenn
      PRINTFQ ("One or more missing sections. At least");
400
      PRINTFQ (" three sections expected (.text, .data, .bss).\n");
401 19 jeremybenn
      exit (1);
402
    }
403
  if (firstthree > 3)
404
    {
405 220 jeremybenn
      PRINTFQ ("Warning: one or more extra sections. These");
406
      PRINTFQ (" sections were handled as .data sections.\n");
407 19 jeremybenn
    }
408
 
409
  fclose (inputfs);
410 220 jeremybenn
  PRINTFQ ("Finished loading COFF.\n");
411 19 jeremybenn
  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 82 jeremybenn
          uint32_t *ref = ((uint32_t *) coffsymhdr.e.e.e_zeroes);
456
          if (*ref)
457 19 jeremybenn
            {
458
              if (strlen (coffsymhdr.e.e_name)
459
                  && strlen (coffsymhdr.e.e_name) < 9)
460
                add_label (COFF_LONG_H (coffsymhdr.e_value),
461
                           coffsymhdr.e.e_name);
462
            }
463
          else
464
            {
465
              uint32_t fpos = ftell (inputfs);
466
 
467
              if (fseek
468
                  (inputfs,
469
                   symptr + nsyms * COFF_SYMESZ +
470
                   COFF_LONG_H (coffsymhdr.e.e.e_offset), SEEK_SET) == 0)
471
                {
472
                  char tmp[33], *s = &tmp[0];
473
                  while (s != &tmp[32])
474
                    if ((*(s++) = fgetc (inputfs)) == 0)
475
                      break;
476
                  tmp[32] = 0;
477
                  add_label (COFF_LONG_H (coffsymhdr.e_value), &tmp[0]);
478
                }
479
              fseek (inputfs, fpos, SEEK_SET);
480
            }
481
        }
482
 
483
      for (i = 0; i < n; i++)
484
        if (fread (&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1)
485
          {
486
            fclose (inputfs);
487
            perror ("readsyms_coff3");
488
            exit (1);
489
          }
490
      syms -= n;
491
      count += n;
492
    }
493
 
494
  fclose (inputfs);
495 220 jeremybenn
  PRINTFQ ("Finished loading symbols.\n");
496 19 jeremybenn
  return;
497
}
498
 
499
static void
500
readfile_elf (char *filename)
501
{
502
 
503
  FILE *inputfs;
504
  struct elf32_hdr elfhdr;
505
  struct elf32_phdr *elf_phdata = NULL;
506
  struct elf32_shdr *elf_spnt, *elf_shdata;
507
  struct elf32_sym *sym_tbl = (struct elf32_sym *) 0;
508
  uint32_t syms = 0;
509
  char *str_tbl = (char *) 0;
510
  char *s_str = (char *) 0;
511
  int breakpoint = 0;
512
  uint32_t inputbuf;
513
  uint32_t padd;
514
  uint32_t insn;
515
  int i, j, sectsize, len;
516
 
517
  if (!(inputfs = fopen (filename, "r")))
518
    {
519
      perror ("readfile_elf");
520
      exit (1);
521
    }
522
 
523
  if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) != 1)
524
    {
525
      perror ("readfile_elf");
526
      exit (1);
527
    }
528
 
529
  if ((elf_shdata =
530
       (struct elf32_shdr *) malloc (ELF_SHORT_H (elfhdr.e_shentsize) *
531
                                     ELF_SHORT_H (elfhdr.e_shnum))) == NULL)
532
    {
533
      perror ("readfile_elf");
534
      exit (1);
535
    }
536
 
537
  if (fseek (inputfs, ELF_LONG_H (elfhdr.e_shoff), SEEK_SET) != 0)
538
    {
539
      perror ("readfile_elf");
540
      exit (1);
541
    }
542
 
543
  if (fread
544
      (elf_shdata,
545
       ELF_SHORT_H (elfhdr.e_shentsize) * ELF_SHORT_H (elfhdr.e_shnum), 1,
546
       inputfs) != 1)
547
    {
548
      perror ("readfile_elf");
549
      exit (1);
550
    }
551
 
552
  if (ELF_LONG_H (elfhdr.e_phoff))
553
    {
554
      if ((elf_phdata =
555
           (struct elf32_phdr *) malloc (ELF_SHORT_H (elfhdr.e_phnum) *
556
                                         ELF_SHORT_H (elfhdr.e_phentsize))) ==
557
          NULL)
558
        {
559
          perror ("readfile_elf");
560
          exit (1);
561
        }
562
 
563
      if (fseek (inputfs, ELF_LONG_H (elfhdr.e_phoff), SEEK_SET) != 0)
564
        {
565
          perror ("readfile_elf");
566
          exit (1);
567
        }
568
 
569
      if (fread
570
          (elf_phdata,
571
           ELF_SHORT_H (elfhdr.e_phnum) * ELF_SHORT_H (elfhdr.e_phentsize),
572
           1, inputfs) != 1)
573
        {
574
          perror ("readfile_elf");
575
          exit (1);
576
        }
577
    }
578
 
579
  for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum);
580
       i++, elf_spnt++)
581
    {
582
 
583
      if (ELF_LONG_H (elf_spnt->sh_type) == SHT_STRTAB)
584
        {
585
          if (NULL != str_tbl)
586
            {
587
              free (str_tbl);
588
            }
589
 
590
          if ((str_tbl =
591
               (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL)
592
            {
593
              perror ("readfile_elf");
594
              exit (1);
595
            }
596
 
597
          if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
598
              0)
599
            {
600
              perror ("readfile_elf");
601
              exit (1);
602
            }
603
 
604
          if (fread (str_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) !=
605
              1)
606
            {
607
              perror ("readfile_elf");
608
              exit (1);
609
            }
610
        }
611
      else if (ELF_LONG_H (elf_spnt->sh_type) == SHT_SYMTAB)
612
        {
613
 
614
          if (NULL != sym_tbl)
615
            {
616
              free (sym_tbl);
617
            }
618
 
619
          if ((sym_tbl =
620
               (struct elf32_sym *) malloc (ELF_LONG_H (elf_spnt->sh_size)))
621
              == NULL)
622
            {
623
              perror ("readfile_elf");
624
              exit (1);
625
            }
626
 
627
          if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
628
              0)
629
            {
630
              perror ("readfile_elf");
631
              exit (1);
632
            }
633
 
634
          if (fread (sym_tbl, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) !=
635
              1)
636
            {
637
              perror ("readfile_elf");
638
              exit (1);
639
            }
640
 
641
          syms =
642
            ELF_LONG_H (elf_spnt->sh_size) /
643
            ELF_LONG_H (elf_spnt->sh_entsize);
644
        }
645
    }
646
 
647
  if (ELF_SHORT_H (elfhdr.e_shstrndx) != SHN_UNDEF)
648
    {
649
      elf_spnt = &elf_shdata[ELF_SHORT_H (elfhdr.e_shstrndx)];
650
 
651
      if ((s_str = (char *) malloc (ELF_LONG_H (elf_spnt->sh_size))) == NULL)
652
        {
653
          perror ("readfile_elf");
654
          exit (1);
655
        }
656
 
657
      if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) != 0)
658
        {
659
          perror ("readfile_elf");
660
          exit (1);
661
        }
662
 
663
      if (fread (s_str, ELF_LONG_H (elf_spnt->sh_size), 1, inputfs) != 1)
664
        {
665
          perror ("readfile_elf");
666
          exit (1);
667
        }
668
    }
669
 
670
 
671
  for (i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H (elfhdr.e_shnum);
672
       i++, elf_spnt++)
673
    {
674
 
675
      if ((ELF_LONG_H (elf_spnt->sh_type) & SHT_PROGBITS)
676
          && (ELF_LONG_H (elf_spnt->sh_flags) & SHF_ALLOC))
677
        {
678
 
679
          padd = ELF_LONG_H (elf_spnt->sh_addr);
680
          for (j = 0; j < ELF_SHORT_H (elfhdr.e_phnum); j++)
681
            {
682
              if (ELF_LONG_H (elf_phdata[j].p_offset) &&
683
                  ELF_LONG_H (elf_phdata[j].p_offset) <=
684
                  ELF_LONG_H (elf_spnt->sh_offset)
685
                  && (ELF_LONG_H (elf_phdata[j].p_offset) +
686
                      ELF_LONG_H (elf_phdata[j].p_memsz)) >
687
                  ELF_LONG_H (elf_spnt->sh_offset))
688
                padd =
689
                  ELF_LONG_H (elf_phdata[j].p_paddr) +
690
                  ELF_LONG_H (elf_spnt->sh_offset) -
691
                  ELF_LONG_H (elf_phdata[j].p_offset);
692
            }
693
 
694
 
695
 
696
          if (ELF_LONG_H (elf_spnt->sh_name) && s_str)
697 220 jeremybenn
            {
698
              PRINTFQ ("Section: %s,", &s_str[ELF_LONG_H (elf_spnt->sh_name)]);
699
            }
700 19 jeremybenn
          else
701 220 jeremybenn
            {
702
              PRINTFQ ("Section: noname,");
703
            }
704 19 jeremybenn
 
705 220 jeremybenn
          PRINTFQ (" vaddr: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_addr));
706
          PRINTFQ (" paddr: 0x%" PRIx32, padd);
707
          PRINTFQ (" offset: 0x%.8lx,", ELF_LONG_H (elf_spnt->sh_offset));
708
          PRINTFQ (" size: 0x%.8lx\n", ELF_LONG_H (elf_spnt->sh_size));
709
 
710 19 jeremybenn
          freemem = padd;
711
          sectsize = ELF_LONG_H (elf_spnt->sh_size);
712
 
713
          if (fseek (inputfs, ELF_LONG_H (elf_spnt->sh_offset), SEEK_SET) !=
714
              0)
715
            {
716
              perror ("readfile_elf");
717
              free (elf_phdata);
718
              exit (1);
719
            }
720
 
721
          while (sectsize > 0
722
                 && (len = fread (&inputbuf, sizeof (inputbuf), 1, inputfs)))
723
            {
724
              insn = ELF_LONG_H (inputbuf);
725
              addprogram (freemem, insn, &breakpoint);
726
              sectsize -= 4;
727
            }
728
        }
729
    }
730
 
731
  if (str_tbl)
732
    {
733
      i = 0;
734
      while (syms--)
735
        {
736
          if (sym_tbl[i].st_name && sym_tbl[i].st_info
737
              && ELF_SHORT_H (sym_tbl[i].st_shndx) < 0x8000)
738
            {
739
              add_label (ELF_LONG_H (sym_tbl[i].st_value),
740
                         &str_tbl[ELF_LONG_H (sym_tbl[i].st_name)]);
741
            }
742
          i++;
743
        }
744
    }
745
 
746
  if (NULL != str_tbl)
747
    {
748
      free (str_tbl);
749
    }
750
 
751
  if (NULL != sym_tbl)
752
    {
753
      free (sym_tbl);
754
    }
755
 
756
  free (s_str);
757
  free (elf_phdata);
758
  free (elf_shdata);
759
 
760
}
761
 
762
/* Identify file type and call appropriate readfile_X routine. It only
763
handles orX-coff-big executables at the moment. */
764
 
765
static void
766
identifyfile (char *filename)
767
{
768
  FILE *inputfs;
769
  struct COFF_filehdr coffhdr;
770
  struct elf32_hdr elfhdr;
771
 
772
  if (!(inputfs = fopen (filename, "r")))
773
    {
774
      perror (filename);
775
      fflush (stdout);
776
      fflush (stderr);
777
      exit (1);
778
    }
779
 
780
  if (fread (&coffhdr, sizeof (coffhdr), 1, inputfs) == 1)
781
    {
782
      if (COFF_SHORT_H (coffhdr.f_magic) == 0x17a)
783
        {
784
          uint32_t opthdr_size;
785 220 jeremybenn
          PRINTFQ ("COFF magic: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_magic));
786
          PRINTFQ ("COFF flags: 0x%.4x\n", COFF_SHORT_H (coffhdr.f_flags));
787
          PRINTFQ ("COFF symptr: 0x%.8lx\n", COFF_LONG_H (coffhdr.f_symptr));
788 19 jeremybenn
          if ((COFF_SHORT_H (coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC)
789
            {
790 220 jeremybenn
              PRINTFQ ("This COFF is not an executable.\n");
791 19 jeremybenn
              exit (1);
792
            }
793
          opthdr_size = COFF_SHORT_H (coffhdr.f_opthdr);
794
          if (opthdr_size != sizeof (COFF_AOUTHDR))
795
            {
796 220 jeremybenn
              PRINTFQ ("COFF optional header is missing or not recognized.\n");
797
              PRINTFQ ("COFF f_opthdr: 0x%" PRIx32 "\n", opthdr_size);
798 19 jeremybenn
              exit (1);
799
            }
800
          fclose (inputfs);
801
          readfile_coff (filename, COFF_SHORT_H (coffhdr.f_nscns));
802
          readsyms_coff (filename, COFF_LONG_H (coffhdr.f_symptr),
803
                         COFF_LONG_H (coffhdr.f_nsyms));
804
          return;
805
        }
806
      else
807
        {
808 220 jeremybenn
          PRINTFQ ("Not COFF file format\n");
809 19 jeremybenn
          fseek (inputfs, 0, SEEK_SET);
810
        }
811
    }
812
  if (fread (&elfhdr, sizeof (elfhdr), 1, inputfs) == 1)
813
    {
814
      if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45
815
          && elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46)
816
        {
817 220 jeremybenn
          PRINTFQ ("ELF type: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_type));
818
          PRINTFQ ("ELF machine: 0x%.4x\n", ELF_SHORT_H (elfhdr.e_machine));
819
          PRINTFQ ("ELF version: 0x%.8lx\n", ELF_LONG_H (elfhdr.e_version));
820
          PRINTFQ ("ELF sec = %d\n", ELF_SHORT_H (elfhdr.e_shnum));
821 19 jeremybenn
          if (ELF_SHORT_H (elfhdr.e_type) != ET_EXEC)
822
            {
823 220 jeremybenn
              PRINTFQ ("This ELF is not an executable.\n");
824 19 jeremybenn
              exit (1);
825
            }
826
          fclose (inputfs);
827
          readfile_elf (filename);
828
          return;
829
        }
830
      else
831
        {
832 220 jeremybenn
          PRINTFQ ("Not ELF file format.\n");
833 19 jeremybenn
          fseek (inputfs, 0, SEEK_SET);
834
        }
835
    }
836
 
837
  perror ("identifyfile2");
838
  fclose (inputfs);
839
 
840
  return;
841
}
842
 
843
 
844
/*---------------------------------------------------------------------------*/
845
/*!Load file to memory
846
 
847
   Loads file to memory starting at address startaddr and returns freemem.
848
 
849
   @param[in] filename        File to load
850
   @param[in] startaddr       Start address at which to load
851
   @param[in] virtphy_transl  Virtual to physical transation table if
852
                              required. Only used for microkernel simulation,
853
                              and not used in Ork1sim at present (set to NULL)
854
 
855
   @return  zero on success, negative on failure.                            */
856
/*---------------------------------------------------------------------------*/
857
uint32_t
858
loadcode (char *filename, oraddr_t startaddr, oraddr_t virtphy_transl)
859
{
860
  int breakpoint = 0;
861
 
862
  transl_error = 0;
863
  transl_table = virtphy_transl;
864
  freemem      = startaddr;
865 220 jeremybenn
  PRINTFQ ("loadcode: filename %s  startaddr=%" PRIxADDR "  virtphy_transl=%"
866 19 jeremybenn
          PRIxADDR "\n", filename, startaddr, virtphy_transl);
867
  identifyfile (filename);
868
 
869
#if IMM_STATS
870
  {
871
    int i = 0, a = 0, b = 0, c = 0;
872 220 jeremybenn
    PRINTFQ ("index:arith/branch/jump\n");
873 19 jeremybenn
    for (i = 0; i < 33; i++)
874 220 jeremybenn
      PRINTFQ ("%2i:\t%3.0f%% / %3.0f%%/ %3.0f%%\t%5i / %5i / %5i\n", i,
875 19 jeremybenn
              100. * (a += bcnt[i][0]) / bsum[0], 100. * (b +=
876
                                                          bcnt[i][1]) /
877
              bsum[1], 100. * (c +=
878
                               bcnt[i][2]) / bsum[2], bcnt[i][0],
879
              bcnt[i][1], bcnt[i][2]);
880 220 jeremybenn
    PRINTFQ ("\nsum %i %i %i\n", bsum[0], bsum[1], bsum[2]);
881 19 jeremybenn
  }
882
#endif
883
 
884
  if (transl_error)
885
    return -1;
886
  else
887
    return translate (freemem, &breakpoint);
888
 
889
}

powered by: WebSVN 2.1.0

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