]> Git Repo - binutils.git/blob - ld/testsuite/ld-empic/run.c
19990502 sourceware import
[binutils.git] / ld / testsuite / ld-empic / run.c
1 /* Load and run a MIPS position independent ECOFF file.
2    Written by Ian Lance Taylor <[email protected]>
3    Public domain.  */
4
5 /* This program will load an ECOFF file into memory and execute it.
6    The file must have been compiled using the GNU -membedded-pic
7    switch to produce position independent code.  This will only work
8    if this program is run on a MIPS system with the same endianness as
9    the ECOFF file.  The ECOFF file must be complete.  System calls may
10    not work correctly.
11
12    There are further restrictions on the file (they could be removed
13    by doing some additional programming).  The file must be aligned
14    such that it does not require any gaps introduced in the data
15    segment; the GNU linker produces such files by default.  However,
16    the file must not assume that the text or data segment is aligned
17    on a page boundary.  The start address must be at the start of the
18    text segment.
19
20    The ECOFF file is run by calling it as though it were a function.
21    The address of the data segment is passed as the only argument.
22    The file is expected to return an integer value, which will be
23    printed.  */
24
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28
29 /* Structures used in ECOFF files.  We assume that a short is two
30    bytes and an int is four bytes.  This is not much of an assumption,
31    since we already assume that we are running on a MIPS host with the
32    same endianness as the file we are examining.  */
33
34 struct ecoff_filehdr {
35   unsigned short f_magic;       /* magic number                 */
36   unsigned short f_nscns;       /* number of sections           */
37   unsigned int f_timdat;        /* time & date stamp            */
38   unsigned int f_symptr;        /* file pointer to symtab       */
39   unsigned int f_nsyms;         /* number of symtab entries     */
40   unsigned short f_opthdr;      /* sizeof(optional hdr)         */
41   unsigned short f_flags;       /* flags                        */
42 };
43
44 struct ecoff_aouthdr
45 {
46   unsigned short magic;         /* type of file                         */
47   unsigned short vstamp;        /* version stamp                        */
48   unsigned int tsize;           /* text size in bytes, padded to FW bdry*/
49   unsigned int dsize;           /* initialized data "  "                */
50   unsigned int bsize;           /* uninitialized data "   "             */
51   unsigned int entry;           /* entry pt.                            */
52   unsigned int text_start;      /* base of text used for this file */
53   unsigned int data_start;      /* base of data used for this file */
54   unsigned int bss_start;       /* base of bss used for this file */
55   unsigned int gprmask;         /* ?? */
56   unsigned int cprmask[4];      /* ?? */
57   unsigned int gp_value;        /* value for gp register */
58 };
59
60 #define ECOFF_SCNHDR_SIZE (40)
61
62 static void
63 die (s)
64      char *s;
65 {
66   perror (s);
67   exit (1);
68 }
69
70 int
71 main (argc, argv)
72      int argc;
73      char **argv;
74 {
75   FILE *f;
76   struct stat s;
77   char *z;
78   struct ecoff_filehdr *fh;
79   struct ecoff_aouthdr *ah;
80   unsigned int toff;
81   char *t, *d;
82   int (*pfn) ();
83   int ret;
84
85   if (argc != 2)
86     {
87       fprintf (stderr, "Usage: %s file\n", argv[0]);
88       exit (1);
89     }
90
91   f = fopen (argv[1], "r");
92   if (f == NULL)
93     die (argv[1]);
94
95   if (stat (argv[1], &s) < 0)
96     die ("stat");
97
98   z = (char *) malloc (s.st_size);
99   if (z == NULL)
100     die ("malloc");
101
102   if (fread (z, 1, s.st_size, f) != s.st_size)
103     die ("fread");
104
105   /* We need to figure out the start of the text segment, which is the
106      location we are going to call, and the start of the data segment,
107      which we are going to pass as an argument.  We also need the size
108      and start address of the bss segment.  This information is all in
109      the ECOFF a.out header.  */
110
111   fh = (struct ecoff_filehdr *) z;
112   if (fh->f_opthdr != sizeof (struct ecoff_aouthdr))
113     {
114       fprintf (stderr, "%s: unexpected opthdr size: is %u, want %u\n",
115                argv[1], (unsigned int) fh->f_opthdr,
116                (unsigned int) sizeof (struct ecoff_aouthdr));
117       exit (1);
118     }
119
120   ah = (struct ecoff_aouthdr *) (z + sizeof (struct ecoff_filehdr));
121   if (ah->magic != 0413)
122     {
123       fprintf (stderr, "%s: bad aouthdr magic number 0%o (want 0413)\n",
124                argv[1], (unsigned int) ah->magic);
125       exit (1);
126     }
127
128   /* We should clear the bss segment at this point.  This is the
129      ah->bsize bytes starting at ah->bss_start, To do this correctly,
130      we would have to make sure our memory block is large enough.  It
131      so happens that our test case does not have any additional pages
132      for the bss segment--it is contained within the data segment.
133      So, we don't bother.  */
134   if (ah->bsize != 0)
135     {
136       fprintf (stderr,
137                "%s: bss segment is %u bytes; non-zero sizes not supported\n",
138                argv[1], ah->bsize);
139       exit (1);
140     }
141
142   /* The text section starts just after all the headers, rounded to a
143      16 byte boundary.  */
144   toff = (sizeof (struct ecoff_filehdr) + sizeof (struct ecoff_aouthdr)
145           + fh->f_nscns * ECOFF_SCNHDR_SIZE);
146   toff += 15;
147   toff &=~ 15;
148   t = z + toff;
149
150   /* The tsize field gives us the start of the data segment.  */
151   d = z + ah->tsize;
152
153   /* Call the code as a function.  */
154   pfn = (int (*) ()) t;
155   ret = (*pfn) (d);
156
157   printf ("%s ran and returned %d\n", argv[1], ret);
158
159   exit (0);
160 }
This page took 0.031232 seconds and 4 git commands to generate.