PowerPC64 ld segfault with code in non-executable sections
[external/binutils.git] / sim / ppc / os_emul.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, see <http://www.gnu.org/licenses/>.
17  
18     */
19
20
21 #ifndef _OS_EMUL_C_
22 #define _OS_EMUL_C_
23
24 #include "cpu.h"
25 #include "idecode.h"
26 #include "os_emul.h"
27
28 #include "emul_generic.h"
29 #include "emul_netbsd.h"
30 #include "emul_unix.h"
31 #include "emul_chirp.h"
32 #include "emul_bugapi.h"
33
34 static const os_emul *(os_emulations[]) = {
35   &emul_chirp,
36   &emul_bugapi,
37   &emul_netbsd,
38   &emul_solaris,
39   &emul_linux,
40   0
41 };
42
43
44 INLINE_OS_EMUL\
45 (os_emul *)
46 os_emul_create(const char *file_name,
47                device *root)
48 {
49   const char *emulation_name = NULL;
50   bfd *image;
51   os_emul *chosen_emulation = NULL;
52
53   bfd_init(); /* would never hurt */
54
55   /* open the file */
56   image = bfd_openr(file_name, NULL);
57   if (image == NULL) {
58     bfd_perror(file_name);
59     error("nothing loaded\n");
60   }
61
62   /* check it is an executable */
63   if (!bfd_check_format(image, bfd_object)) {
64     TRACE(trace_tbd,
65           ("FIXME - should check more than just bfd_check_format\n"));
66     TRACE(trace_os_emul,
67           ("%s not an executable, assumeing a device file\n", file_name));
68     bfd_close(image);
69     image = NULL;
70   }
71
72   /* if a device file, load that before trying the emulations on */
73   if (image == NULL) {
74     psim_merge_device_file(root, file_name);
75   }
76
77   /* see if the device tree already specifies the required emulation */
78   if (tree_find_property(root, "/openprom/options/os-emul") != NULL)
79     emulation_name =
80       tree_find_string_property(root, "/openprom/options/os-emul");
81   else
82     emulation_name = NULL;
83
84   /* go through each emulation to see if they reconize it. FIXME -
85      should have some sort of imported table from a separate file */
86   {
87     os_emul_data *emul_data;
88     const os_emul **possible_emulation;
89     chosen_emulation = NULL;
90     for (possible_emulation = os_emulations, emul_data = NULL;
91          *possible_emulation != NULL && emul_data == NULL;
92          possible_emulation++) {
93       emul_data = (*possible_emulation)->create(root,
94                                                 image,
95                                                 emulation_name);
96       if (emul_data != NULL) {
97         chosen_emulation = ZALLOC(os_emul);
98         *chosen_emulation = **possible_emulation;
99         chosen_emulation->data = emul_data;
100       }
101     }
102   }
103
104   /* clean up */
105   if (image != NULL)
106     bfd_close(image);
107   return chosen_emulation;
108 }
109
110 INLINE_OS_EMUL\
111 (void)
112 os_emul_init(os_emul *emulation,
113              int nr_cpus)
114 {
115   if (emulation != (os_emul*)0)
116     emulation->init(emulation->data, nr_cpus);
117 }
118
119 INLINE_OS_EMUL\
120 (void)
121 os_emul_system_call(cpu *processor,
122                     unsigned_word cia)
123 {
124   os_emul *emulation = cpu_os_emulation(processor);
125   if (emulation != (os_emul*)0 && emulation->system_call != 0)
126     emulation->system_call(processor, cia, emulation->data);
127   else
128     error("System call emulation not available\n");
129 }
130
131 INLINE_OS_EMUL\
132 (int)
133 os_emul_instruction_call(cpu *processor,
134                          unsigned_word cia,
135                          unsigned_word ra)
136 {
137   os_emul *emulation = cpu_os_emulation(processor);
138   if (emulation != (os_emul*)0 && emulation->instruction_call != 0)
139     return emulation->instruction_call(processor, cia, ra, emulation->data);
140   else
141     return 0;
142 }
143
144
145 #endif /* _OS_EMUL_C_ */