interp.c revision 1.1 1 1.1 christos /* Simulator for Analog Devices Blackfin processors.
2 1.1 christos
3 1.1 christos Copyright (C) 2005-2014 Free Software Foundation, Inc.
4 1.1 christos Contributed by Analog Devices, Inc.
5 1.1 christos
6 1.1 christos This file is part of simulators.
7 1.1 christos
8 1.1 christos This program is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3 of the License, or
11 1.1 christos (at your option) any later version.
12 1.1 christos
13 1.1 christos This program is distributed in the hope that it will be useful,
14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1 christos GNU General Public License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.1 christos #include "config.h"
22 1.1 christos
23 1.1 christos #include <stdio.h>
24 1.1 christos #include <stdlib.h>
25 1.1 christos #include <string.h>
26 1.1 christos #include <signal.h>
27 1.1 christos #include <errno.h>
28 1.1 christos #include <fcntl.h>
29 1.1 christos #include <unistd.h>
30 1.1 christos #include <sys/time.h>
31 1.1 christos
32 1.1 christos #include "gdb/callback.h"
33 1.1 christos #include "gdb/signals.h"
34 1.1 christos #include "sim-main.h"
35 1.1 christos #include "sim-hw.h"
36 1.1 christos
37 1.1 christos #include "targ-vals.h"
38 1.1 christos
39 1.1 christos /* The numbers here do not matter. They just need to be unique. */
40 1.1 christos #define CB_SYS_ioctl 201
41 1.1 christos #define CB_SYS_mmap2 202
42 1.1 christos #define CB_SYS_munmap 203
43 1.1 christos #define CB_SYS_dup2 204
44 1.1 christos #define CB_SYS_getuid 205
45 1.1 christos #define CB_SYS_getuid32 206
46 1.1 christos #define CB_SYS_getgid 207
47 1.1 christos #define CB_SYS_getgid32 208
48 1.1 christos #define CB_SYS_setuid 209
49 1.1 christos #define CB_SYS_setuid32 210
50 1.1 christos #define CB_SYS_setgid 211
51 1.1 christos #define CB_SYS_setgid32 212
52 1.1 christos #define CB_SYS_pread 213
53 1.1 christos #define CB_SYS__llseek 214
54 1.1 christos #define CB_SYS_getcwd 215
55 1.1 christos #define CB_SYS_stat64 216
56 1.1 christos #define CB_SYS_lstat64 217
57 1.1 christos #define CB_SYS_fstat64 218
58 1.1 christos #define CB_SYS_ftruncate64 219
59 1.1 christos #define CB_SYS_gettimeofday 220
60 1.1 christos #define CB_SYS_access 221
61 1.1 christos #include "linux-targ-map.h"
62 1.1 christos #include "linux-fixed-code.h"
63 1.1 christos
64 1.1 christos #include "elf/common.h"
65 1.1 christos #include "elf/external.h"
66 1.1 christos #include "elf/internal.h"
67 1.1 christos #include "elf/bfin.h"
68 1.1 christos #include "elf-bfd.h"
69 1.1 christos
70 1.1 christos #include "dv-bfin_cec.h"
71 1.1 christos #include "dv-bfin_mmu.h"
72 1.1 christos
73 1.1 christos #ifndef HAVE_GETUID
74 1.1 christos # define getuid() 0
75 1.1 christos #endif
76 1.1 christos #ifndef HAVE_GETGID
77 1.1 christos # define getgid() 0
78 1.1 christos #endif
79 1.1 christos #ifndef HAVE_GETEUID
80 1.1 christos # define geteuid() 0
81 1.1 christos #endif
82 1.1 christos #ifndef HAVE_GETEGID
83 1.1 christos # define getegid() 0
84 1.1 christos #endif
85 1.1 christos #ifndef HAVE_SETUID
86 1.1 christos # define setuid(uid) -1
87 1.1 christos #endif
88 1.1 christos #ifndef HAVE_SETGID
89 1.1 christos # define setgid(gid) -1
90 1.1 christos #endif
91 1.1 christos
92 1.1 christos static const char cb_linux_stat_map_32[] =
93 1.1 christos /* Linux kernel 32bit layout: */
94 1.1 christos "st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2:st_gid,2:st_rdev,2:"
95 1.1 christos "space,2:st_size,4:st_blksize,4:st_blocks,4:st_atime,4:st_atimensec,4:"
96 1.1 christos "st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:space,4";
97 1.1 christos /* uClibc public ABI 32bit layout:
98 1.1 christos "st_dev,8:space,2:space,2:st_ino,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:"
99 1.1 christos "st_rdev,8:space,2:space,2:st_size,4:st_blksiez,4:st_blocks,4:st_atime,4:"
100 1.1 christos "st_atimensec,4:st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:"
101 1.1 christos "space,4"; */
102 1.1 christos static const char cb_linux_stat_map_64[] =
103 1.1 christos "st_dev,8:space,4:space,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:st_rdev,8:"
104 1.1 christos "space,4:st_size,8:st_blksize,4:st_blocks,8:st_atime,4:st_atimensec,4:"
105 1.1 christos "st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:st_ino,8";
106 1.1 christos static const char cb_libgloss_stat_map_32[] =
107 1.1 christos "st_dev,2:st_ino,2:st_mode,4:st_nlink,2:st_uid,2:st_gid,2:st_rdev,2:"
108 1.1 christos "st_size,4:st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:"
109 1.1 christos "space,4:st_blksize,4:st_blocks,4:space,8";
110 1.1 christos static const char *stat_map_32, *stat_map_64;
111 1.1 christos
112 1.1 christos /* Count the number of arguments in an argv. */
113 1.1 christos static int
114 1.1 christos count_argc (const char * const *argv)
115 1.1 christos {
116 1.1 christos int i;
117 1.1 christos
118 1.1 christos if (! argv)
119 1.1 christos return -1;
120 1.1 christos
121 1.1 christos for (i = 0; argv[i] != NULL; ++i)
122 1.1 christos continue;
123 1.1 christos return i;
124 1.1 christos }
125 1.1 christos
126 1.1 christos /* Read/write functions for system call interface. */
127 1.1 christos
128 1.1 christos static int
129 1.1 christos syscall_read_mem (host_callback *cb, struct cb_syscall *sc,
130 1.1 christos unsigned long taddr, char *buf, int bytes)
131 1.1 christos {
132 1.1 christos SIM_DESC sd = (SIM_DESC) sc->p1;
133 1.1 christos SIM_CPU *cpu = (SIM_CPU *) sc->p2;
134 1.1 christos
135 1.1 christos MAYBE_TRACE (CORE, cpu, "DBUS FETCH (syscall) %i bytes @ 0x%08lx", bytes, taddr);
136 1.1 christos
137 1.1 christos return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
138 1.1 christos }
139 1.1 christos
140 1.1 christos static int
141 1.1 christos syscall_write_mem (host_callback *cb, struct cb_syscall *sc,
142 1.1 christos unsigned long taddr, const char *buf, int bytes)
143 1.1 christos {
144 1.1 christos SIM_DESC sd = (SIM_DESC) sc->p1;
145 1.1 christos SIM_CPU *cpu = (SIM_CPU *) sc->p2;
146 1.1 christos
147 1.1 christos MAYBE_TRACE (CORE, cpu, "DBUS STORE (syscall) %i bytes @ 0x%08lx", bytes, taddr);
148 1.1 christos
149 1.1 christos return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
150 1.1 christos }
151 1.1 christos
152 1.1 christos /* Simulate a monitor trap, put the result into r0 and errno into r1
153 1.1 christos return offset by which to adjust pc. */
154 1.1 christos
155 1.1 christos void
156 1.1 christos bfin_syscall (SIM_CPU *cpu)
157 1.1 christos {
158 1.1 christos SIM_DESC sd = CPU_STATE (cpu);
159 1.1 christos const char * const *argv = (void *)STATE_PROG_ARGV (sd);
160 1.1 christos host_callback *cb = STATE_CALLBACK (sd);
161 1.1 christos bu32 args[6];
162 1.1 christos CB_SYSCALL sc;
163 1.1 christos char *p;
164 1.1 christos char _tbuf[1024 * 3], *tbuf = _tbuf, tstr[1024];
165 1.1 christos int fmt_ret_hex = 0;
166 1.1 christos
167 1.1 christos CB_SYSCALL_INIT (&sc);
168 1.1 christos
169 1.1 christos if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
170 1.1 christos {
171 1.1 christos /* Linux syscall. */
172 1.1 christos sc.func = PREG (0);
173 1.1 christos sc.arg1 = args[0] = DREG (0);
174 1.1 christos sc.arg2 = args[1] = DREG (1);
175 1.1 christos sc.arg3 = args[2] = DREG (2);
176 1.1 christos sc.arg4 = args[3] = DREG (3);
177 1.1 christos /*sc.arg5 =*/ args[4] = DREG (4);
178 1.1 christos /*sc.arg6 =*/ args[5] = DREG (5);
179 1.1 christos }
180 1.1 christos else
181 1.1 christos {
182 1.1 christos /* libgloss syscall. */
183 1.1 christos sc.func = PREG (0);
184 1.1 christos sc.arg1 = args[0] = GET_LONG (DREG (0));
185 1.1 christos sc.arg2 = args[1] = GET_LONG (DREG (0) + 4);
186 1.1 christos sc.arg3 = args[2] = GET_LONG (DREG (0) + 8);
187 1.1 christos sc.arg4 = args[3] = GET_LONG (DREG (0) + 12);
188 1.1 christos /*sc.arg5 =*/ args[4] = GET_LONG (DREG (0) + 16);
189 1.1 christos /*sc.arg6 =*/ args[5] = GET_LONG (DREG (0) + 20);
190 1.1 christos }
191 1.1 christos sc.p1 = (PTR) sd;
192 1.1 christos sc.p2 = (PTR) cpu;
193 1.1 christos sc.read_mem = syscall_read_mem;
194 1.1 christos sc.write_mem = syscall_write_mem;
195 1.1 christos
196 1.1 christos /* Common cb_syscall() handles most functions. */
197 1.1 christos switch (cb_target_to_host_syscall (cb, sc.func))
198 1.1 christos {
199 1.1 christos case CB_SYS_exit:
200 1.1 christos tbuf += sprintf (tbuf, "exit(%i)", args[0]);
201 1.1 christos sim_engine_halt (sd, cpu, NULL, PCREG, sim_exited, sc.arg1);
202 1.1 christos
203 1.1 christos #ifdef CB_SYS_argc
204 1.1 christos case CB_SYS_argc:
205 1.1 christos tbuf += sprintf (tbuf, "argc()");
206 1.1 christos sc.result = count_argc (argv);
207 1.1 christos break;
208 1.1 christos case CB_SYS_argnlen:
209 1.1 christos {
210 1.1 christos tbuf += sprintf (tbuf, "argnlen(%u)", args[0]);
211 1.1 christos if (sc.arg1 < count_argc (argv))
212 1.1 christos sc.result = strlen (argv[sc.arg1]);
213 1.1 christos else
214 1.1 christos sc.result = -1;
215 1.1 christos }
216 1.1 christos break;
217 1.1 christos case CB_SYS_argn:
218 1.1 christos {
219 1.1 christos tbuf += sprintf (tbuf, "argn(%u)", args[0]);
220 1.1 christos if (sc.arg1 < count_argc (argv))
221 1.1 christos {
222 1.1 christos const char *argn = argv[sc.arg1];
223 1.1 christos int len = strlen (argn);
224 1.1 christos int written = sc.write_mem (cb, &sc, sc.arg2, argn, len + 1);
225 1.1 christos if (written == len + 1)
226 1.1 christos sc.result = sc.arg2;
227 1.1 christos else
228 1.1 christos sc.result = -1;
229 1.1 christos }
230 1.1 christos else
231 1.1 christos sc.result = -1;
232 1.1 christos }
233 1.1 christos break;
234 1.1 christos #endif
235 1.1 christos
236 1.1 christos case CB_SYS_gettimeofday:
237 1.1 christos {
238 1.1 christos struct timeval _tv, *tv = &_tv;
239 1.1 christos struct timezone _tz, *tz = &_tz;
240 1.1 christos
241 1.1 christos tbuf += sprintf (tbuf, "gettimeofday(%#x, %#x)", args[0], args[1]);
242 1.1 christos
243 1.1 christos if (sc.arg1 == 0)
244 1.1 christos tv = NULL;
245 1.1 christos if (sc.arg2 == 0)
246 1.1 christos tz = NULL;
247 1.1 christos sc.result = gettimeofday (tv, tz);
248 1.1 christos
249 1.1 christos if (sc.result == 0)
250 1.1 christos {
251 1.1 christos bu32 t;
252 1.1 christos
253 1.1 christos if (tv)
254 1.1 christos {
255 1.1 christos t = tv->tv_sec;
256 1.1 christos sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
257 1.1 christos t = tv->tv_usec;
258 1.1 christos sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
259 1.1 christos }
260 1.1 christos
261 1.1 christos if (sc.arg2)
262 1.1 christos {
263 1.1 christos t = tz->tz_minuteswest;
264 1.1 christos sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
265 1.1 christos t = tz->tz_dsttime;
266 1.1 christos sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
267 1.1 christos }
268 1.1 christos }
269 1.1 christos else
270 1.1 christos goto sys_finish;
271 1.1 christos }
272 1.1 christos break;
273 1.1 christos
274 1.1 christos case CB_SYS_ioctl:
275 1.1 christos /* XXX: hack just enough to get basic stdio w/uClibc ... */
276 1.1 christos tbuf += sprintf (tbuf, "ioctl(%i, %#x, %u)", args[0], args[1], args[2]);
277 1.1 christos if (sc.arg2 == 0x5401)
278 1.1 christos {
279 1.1 christos sc.result = !isatty (sc.arg1);
280 1.1 christos sc.errcode = 0;
281 1.1 christos }
282 1.1 christos else
283 1.1 christos {
284 1.1 christos sc.result = -1;
285 1.1 christos sc.errcode = TARGET_EINVAL;
286 1.1 christos }
287 1.1 christos break;
288 1.1 christos
289 1.1 christos case CB_SYS_mmap2:
290 1.1 christos {
291 1.1 christos static bu32 heap = BFIN_DEFAULT_MEM_SIZE / 2;
292 1.1 christos
293 1.1 christos fmt_ret_hex = 1;
294 1.1 christos tbuf += sprintf (tbuf, "mmap2(%#x, %u, %#x, %#x, %i, %u)",
295 1.1 christos args[0], args[1], args[2], args[3], args[4], args[5]);
296 1.1 christos
297 1.1 christos sc.errcode = 0;
298 1.1 christos
299 1.1 christos if (sc.arg4 & 0x20 /*MAP_ANONYMOUS*/)
300 1.1 christos /* XXX: We don't handle zeroing, but default is all zeros. */;
301 1.1 christos else if (args[4] >= MAX_CALLBACK_FDS)
302 1.1 christos sc.errcode = TARGET_ENOSYS;
303 1.1 christos else
304 1.1 christos {
305 1.1 christos #ifdef HAVE_PREAD
306 1.1 christos char *data = xmalloc (sc.arg2);
307 1.1 christos
308 1.1 christos /* XXX: Should add a cb->pread. */
309 1.1 christos if (pread (cb->fdmap[args[4]], data, sc.arg2, args[5] << 12) == sc.arg2)
310 1.1 christos sc.write_mem (cb, &sc, heap, data, sc.arg2);
311 1.1 christos else
312 1.1 christos sc.errcode = TARGET_EINVAL;
313 1.1 christos
314 1.1 christos free (data);
315 1.1 christos #else
316 1.1 christos sc.errcode = TARGET_ENOSYS;
317 1.1 christos #endif
318 1.1 christos }
319 1.1 christos
320 1.1 christos if (sc.errcode)
321 1.1 christos {
322 1.1 christos sc.result = -1;
323 1.1 christos break;
324 1.1 christos }
325 1.1 christos
326 1.1 christos sc.result = heap;
327 1.1 christos heap += sc.arg2;
328 1.1 christos /* Keep it page aligned. */
329 1.1 christos heap = ALIGN (heap, 4096);
330 1.1 christos
331 1.1 christos break;
332 1.1 christos }
333 1.1 christos
334 1.1 christos case CB_SYS_munmap:
335 1.1 christos /* XXX: meh, just lie for mmap(). */
336 1.1 christos tbuf += sprintf (tbuf, "munmap(%#x, %u)", args[0], args[1]);
337 1.1 christos sc.result = 0;
338 1.1 christos break;
339 1.1 christos
340 1.1 christos case CB_SYS_dup2:
341 1.1 christos tbuf += sprintf (tbuf, "dup2(%i, %i)", args[0], args[1]);
342 1.1 christos if (sc.arg1 >= MAX_CALLBACK_FDS || sc.arg2 >= MAX_CALLBACK_FDS)
343 1.1 christos {
344 1.1 christos sc.result = -1;
345 1.1 christos sc.errcode = TARGET_EINVAL;
346 1.1 christos }
347 1.1 christos else
348 1.1 christos {
349 1.1 christos sc.result = dup2 (cb->fdmap[sc.arg1], cb->fdmap[sc.arg2]);
350 1.1 christos goto sys_finish;
351 1.1 christos }
352 1.1 christos break;
353 1.1 christos
354 1.1 christos case CB_SYS__llseek:
355 1.1 christos tbuf += sprintf (tbuf, "llseek(%i, %u, %u, %#x, %u)",
356 1.1 christos args[0], args[1], args[2], args[3], args[4]);
357 1.1 christos sc.func = TARGET_LINUX_SYS_lseek;
358 1.1 christos if (sc.arg2)
359 1.1 christos {
360 1.1 christos sc.result = -1;
361 1.1 christos sc.errcode = TARGET_EINVAL;
362 1.1 christos }
363 1.1 christos else
364 1.1 christos {
365 1.1 christos sc.arg2 = sc.arg3;
366 1.1 christos sc.arg3 = args[4];
367 1.1 christos cb_syscall (cb, &sc);
368 1.1 christos if (sc.result != -1)
369 1.1 christos {
370 1.1 christos bu32 z = 0;
371 1.1 christos sc.write_mem (cb, &sc, args[3], (void *)&sc.result, 4);
372 1.1 christos sc.write_mem (cb, &sc, args[3] + 4, (void *)&z, 4);
373 1.1 christos }
374 1.1 christos }
375 1.1 christos break;
376 1.1 christos
377 1.1 christos /* XXX: Should add a cb->pread. */
378 1.1 christos case CB_SYS_pread:
379 1.1 christos tbuf += sprintf (tbuf, "pread(%i, %#x, %u, %i)",
380 1.1 christos args[0], args[1], args[2], args[3]);
381 1.1 christos if (sc.arg1 >= MAX_CALLBACK_FDS)
382 1.1 christos {
383 1.1 christos sc.result = -1;
384 1.1 christos sc.errcode = TARGET_EINVAL;
385 1.1 christos }
386 1.1 christos else
387 1.1 christos {
388 1.1 christos long old_pos, read_result, read_errcode;
389 1.1 christos
390 1.1 christos /* Get current filepos. */
391 1.1 christos sc.func = TARGET_LINUX_SYS_lseek;
392 1.1 christos sc.arg2 = 0;
393 1.1 christos sc.arg3 = SEEK_CUR;
394 1.1 christos cb_syscall (cb, &sc);
395 1.1 christos if (sc.result == -1)
396 1.1 christos break;
397 1.1 christos old_pos = sc.result;
398 1.1 christos
399 1.1 christos /* Move to the new pos. */
400 1.1 christos sc.func = TARGET_LINUX_SYS_lseek;
401 1.1 christos sc.arg2 = args[3];
402 1.1 christos sc.arg3 = SEEK_SET;
403 1.1 christos cb_syscall (cb, &sc);
404 1.1 christos if (sc.result == -1)
405 1.1 christos break;
406 1.1 christos
407 1.1 christos /* Read the data. */
408 1.1 christos sc.func = TARGET_LINUX_SYS_read;
409 1.1 christos sc.arg2 = args[1];
410 1.1 christos sc.arg3 = args[2];
411 1.1 christos cb_syscall (cb, &sc);
412 1.1 christos read_result = sc.result;
413 1.1 christos read_errcode = sc.errcode;
414 1.1 christos
415 1.1 christos /* Move back to the old pos. */
416 1.1 christos sc.func = TARGET_LINUX_SYS_lseek;
417 1.1 christos sc.arg2 = old_pos;
418 1.1 christos sc.arg3 = SEEK_SET;
419 1.1 christos cb_syscall (cb, &sc);
420 1.1 christos
421 1.1 christos sc.result = read_result;
422 1.1 christos sc.errcode = read_errcode;
423 1.1 christos }
424 1.1 christos break;
425 1.1 christos
426 1.1 christos case CB_SYS_getcwd:
427 1.1 christos tbuf += sprintf (tbuf, "getcwd(%#x, %u)", args[0], args[1]);
428 1.1 christos
429 1.1 christos p = alloca (sc.arg2);
430 1.1 christos if (getcwd (p, sc.arg2) == NULL)
431 1.1 christos {
432 1.1 christos sc.result = -1;
433 1.1 christos sc.errcode = TARGET_EINVAL;
434 1.1 christos }
435 1.1 christos else
436 1.1 christos {
437 1.1 christos sc.write_mem (cb, &sc, sc.arg1, p, sc.arg2);
438 1.1 christos sc.result = sc.arg1;
439 1.1 christos }
440 1.1 christos break;
441 1.1 christos
442 1.1 christos case CB_SYS_stat64:
443 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
444 1.1 christos strcpy (tstr, "???");
445 1.1 christos tbuf += sprintf (tbuf, "stat64(%#x:\"%s\", %u)", args[0], tstr, args[1]);
446 1.1 christos cb->stat_map = stat_map_64;
447 1.1 christos sc.func = TARGET_LINUX_SYS_stat;
448 1.1 christos cb_syscall (cb, &sc);
449 1.1 christos cb->stat_map = stat_map_32;
450 1.1 christos break;
451 1.1 christos case CB_SYS_lstat64:
452 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
453 1.1 christos strcpy (tstr, "???");
454 1.1 christos tbuf += sprintf (tbuf, "lstat64(%#x:\"%s\", %u)", args[0], tstr, args[1]);
455 1.1 christos cb->stat_map = stat_map_64;
456 1.1 christos sc.func = TARGET_LINUX_SYS_lstat;
457 1.1 christos cb_syscall (cb, &sc);
458 1.1 christos cb->stat_map = stat_map_32;
459 1.1 christos break;
460 1.1 christos case CB_SYS_fstat64:
461 1.1 christos tbuf += sprintf (tbuf, "fstat64(%#x, %u)", args[0], args[1]);
462 1.1 christos cb->stat_map = stat_map_64;
463 1.1 christos sc.func = TARGET_LINUX_SYS_fstat;
464 1.1 christos cb_syscall (cb, &sc);
465 1.1 christos cb->stat_map = stat_map_32;
466 1.1 christos break;
467 1.1 christos
468 1.1 christos case CB_SYS_ftruncate64:
469 1.1 christos tbuf += sprintf (tbuf, "ftruncate64(%u, %u)", args[0], args[1]);
470 1.1 christos sc.func = TARGET_LINUX_SYS_ftruncate;
471 1.1 christos cb_syscall (cb, &sc);
472 1.1 christos break;
473 1.1 christos
474 1.1 christos case CB_SYS_getuid:
475 1.1 christos case CB_SYS_getuid32:
476 1.1 christos tbuf += sprintf (tbuf, "getuid()");
477 1.1 christos sc.result = getuid ();
478 1.1 christos goto sys_finish;
479 1.1 christos case CB_SYS_getgid:
480 1.1 christos case CB_SYS_getgid32:
481 1.1 christos tbuf += sprintf (tbuf, "getgid()");
482 1.1 christos sc.result = getgid ();
483 1.1 christos goto sys_finish;
484 1.1 christos case CB_SYS_setuid:
485 1.1 christos sc.arg1 &= 0xffff;
486 1.1 christos case CB_SYS_setuid32:
487 1.1 christos tbuf += sprintf (tbuf, "setuid(%u)", args[0]);
488 1.1 christos sc.result = setuid (sc.arg1);
489 1.1 christos goto sys_finish;
490 1.1 christos case CB_SYS_setgid:
491 1.1 christos sc.arg1 &= 0xffff;
492 1.1 christos case CB_SYS_setgid32:
493 1.1 christos tbuf += sprintf (tbuf, "setgid(%u)", args[0]);
494 1.1 christos sc.result = setgid (sc.arg1);
495 1.1 christos goto sys_finish;
496 1.1 christos
497 1.1 christos case CB_SYS_getpid:
498 1.1 christos tbuf += sprintf (tbuf, "getpid()");
499 1.1 christos sc.result = getpid ();
500 1.1 christos goto sys_finish;
501 1.1 christos case CB_SYS_kill:
502 1.1 christos tbuf += sprintf (tbuf, "kill(%u, %i)", args[0], args[1]);
503 1.1 christos /* Only let the app kill itself. */
504 1.1 christos if (sc.arg1 != getpid ())
505 1.1 christos {
506 1.1 christos sc.result = -1;
507 1.1 christos sc.errcode = TARGET_EPERM;
508 1.1 christos }
509 1.1 christos else
510 1.1 christos {
511 1.1 christos #ifdef HAVE_KILL
512 1.1 christos sc.result = kill (sc.arg1, sc.arg2);
513 1.1 christos goto sys_finish;
514 1.1 christos #else
515 1.1 christos sc.result = -1;
516 1.1 christos sc.errcode = TARGET_ENOSYS;
517 1.1 christos #endif
518 1.1 christos }
519 1.1 christos break;
520 1.1 christos
521 1.1 christos case CB_SYS_open:
522 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
523 1.1 christos strcpy (tstr, "???");
524 1.1 christos tbuf += sprintf (tbuf, "open(%#x:\"%s\", %#x, %o)",
525 1.1 christos args[0], tstr, args[1], args[2]);
526 1.1 christos goto case_default;
527 1.1 christos case CB_SYS_close:
528 1.1 christos tbuf += sprintf (tbuf, "close(%i)", args[0]);
529 1.1 christos goto case_default;
530 1.1 christos case CB_SYS_read:
531 1.1 christos tbuf += sprintf (tbuf, "read(%i, %#x, %u)", args[0], args[1], args[2]);
532 1.1 christos goto case_default;
533 1.1 christos case CB_SYS_write:
534 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1]))
535 1.1 christos strcpy (tstr, "???");
536 1.1 christos tbuf += sprintf (tbuf, "write(%i, %#x:\"%s\", %u)",
537 1.1 christos args[0], args[1], tstr, args[2]);
538 1.1 christos goto case_default;
539 1.1 christos case CB_SYS_lseek:
540 1.1 christos tbuf += sprintf (tbuf, "lseek(%i, %i, %i)", args[0], args[1], args[2]);
541 1.1 christos goto case_default;
542 1.1 christos case CB_SYS_unlink:
543 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
544 1.1 christos strcpy (tstr, "???");
545 1.1 christos tbuf += sprintf (tbuf, "unlink(%#x:\"%s\")", args[0], tstr);
546 1.1 christos goto case_default;
547 1.1 christos case CB_SYS_truncate:
548 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
549 1.1 christos strcpy (tstr, "???");
550 1.1 christos tbuf += sprintf (tbuf, "truncate(%#x:\"%s\", %i)", args[0], tstr, args[1]);
551 1.1 christos goto case_default;
552 1.1 christos case CB_SYS_ftruncate:
553 1.1 christos tbuf += sprintf (tbuf, "ftruncate(%i, %i)", args[0], args[1]);
554 1.1 christos goto case_default;
555 1.1 christos case CB_SYS_rename:
556 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
557 1.1 christos strcpy (tstr, "???");
558 1.1 christos tbuf += sprintf (tbuf, "rename(%#x:\"%s\", ", args[0], tstr);
559 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1]))
560 1.1 christos strcpy (tstr, "???");
561 1.1 christos tbuf += sprintf (tbuf, "%#x:\"%s\")", args[1], tstr);
562 1.1 christos goto case_default;
563 1.1 christos case CB_SYS_stat:
564 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
565 1.1 christos strcpy (tstr, "???");
566 1.1 christos tbuf += sprintf (tbuf, "stat(%#x:\"%s\", %#x)", args[0], tstr, args[1]);
567 1.1 christos goto case_default;
568 1.1 christos case CB_SYS_fstat:
569 1.1 christos tbuf += sprintf (tbuf, "fstat(%i, %#x)", args[0], args[1]);
570 1.1 christos goto case_default;
571 1.1 christos case CB_SYS_lstat:
572 1.1 christos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
573 1.1 christos strcpy (tstr, "???");
574 1.1 christos tbuf += sprintf (tbuf, "lstat(%#x:\"%s\", %#x)", args[0], tstr, args[1]);
575 1.1 christos goto case_default;
576 1.1 christos case CB_SYS_pipe:
577 1.1 christos tbuf += sprintf (tbuf, "pipe(%#x, %#x)", args[0], args[1]);
578 1.1 christos goto case_default;
579 1.1 christos
580 1.1 christos default:
581 1.1 christos tbuf += sprintf (tbuf, "???_%i(%#x, %#x, %#x, %#x, %#x, %#x)", sc.func,
582 1.1 christos args[0], args[1], args[2], args[3], args[4], args[5]);
583 1.1 christos case_default:
584 1.1 christos cb_syscall (cb, &sc);
585 1.1 christos break;
586 1.1 christos
587 1.1 christos sys_finish:
588 1.1 christos if (sc.result == -1)
589 1.1 christos {
590 1.1 christos cb->last_errno = errno;
591 1.1 christos sc.errcode = cb->get_errno (cb);
592 1.1 christos }
593 1.1 christos }
594 1.1 christos
595 1.1 christos TRACE_EVENTS (cpu, "syscall_%i(%#x, %#x, %#x, %#x, %#x, %#x) = %li (error = %i)",
596 1.1 christos sc.func, args[0], args[1], args[2], args[3], args[4], args[5],
597 1.1 christos sc.result, sc.errcode);
598 1.1 christos
599 1.1 christos tbuf += sprintf (tbuf, " = ");
600 1.1 christos if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
601 1.1 christos {
602 1.1 christos if (sc.result == -1)
603 1.1 christos {
604 1.1 christos tbuf += sprintf (tbuf, "-1 (error = %i)", sc.errcode);
605 1.1 christos if (sc.errcode == cb_host_to_target_errno (cb, ENOSYS))
606 1.1 christos {
607 1.1 christos sim_io_eprintf (sd, "bfin-sim: %#x: unimplemented syscall %i\n",
608 1.1 christos PCREG, sc.func);
609 1.1 christos }
610 1.1 christos SET_DREG (0, -sc.errcode);
611 1.1 christos }
612 1.1 christos else
613 1.1 christos {
614 1.1 christos if (fmt_ret_hex)
615 1.1 christos tbuf += sprintf (tbuf, "%#lx", sc.result);
616 1.1 christos else
617 1.1 christos tbuf += sprintf (tbuf, "%lu", sc.result);
618 1.1 christos SET_DREG (0, sc.result);
619 1.1 christos }
620 1.1 christos }
621 1.1 christos else
622 1.1 christos {
623 1.1 christos tbuf += sprintf (tbuf, "%lu (error = %i)", sc.result, sc.errcode);
624 1.1 christos SET_DREG (0, sc.result);
625 1.1 christos SET_DREG (1, sc.result2);
626 1.1 christos SET_DREG (2, sc.errcode);
627 1.1 christos }
628 1.1 christos
629 1.1 christos TRACE_SYSCALL (cpu, "%s", _tbuf);
630 1.1 christos }
631 1.1 christos
632 1.1 christos void
633 1.1 christos trace_register (SIM_DESC sd,
634 1.1 christos sim_cpu *cpu,
635 1.1 christos const char *fmt,
636 1.1 christos ...)
637 1.1 christos {
638 1.1 christos va_list ap;
639 1.1 christos trace_printf (sd, cpu, "%s %s",
640 1.1 christos "reg: ",
641 1.1 christos TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
642 1.1 christos va_start (ap, fmt);
643 1.1 christos trace_vprintf (sd, cpu, fmt, ap);
644 1.1 christos va_end (ap);
645 1.1 christos trace_printf (sd, cpu, "\n");
646 1.1 christos }
647 1.1 christos
648 1.1 christos /* Execute a single instruction. */
649 1.1 christos
650 1.1 christos static sim_cia
651 1.1 christos step_once (SIM_CPU *cpu)
652 1.1 christos {
653 1.1 christos SIM_DESC sd = CPU_STATE (cpu);
654 1.1 christos bu32 insn_len, oldpc = PCREG;
655 1.1 christos int i;
656 1.1 christos bool ssstep;
657 1.1 christos
658 1.1 christos if (TRACE_ANY_P (cpu))
659 1.1 christos trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu),
660 1.1 christos NULL, 0, " "); /* Use a space for gcc warnings. */
661 1.1 christos
662 1.1 christos /* Handle hardware single stepping when lower than EVT3, and when SYSCFG
663 1.1 christos has already had the SSSTEP bit enabled. */
664 1.1 christos ssstep = false;
665 1.1 christos if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT
666 1.1 christos && (SYSCFGREG & SYSCFG_SSSTEP))
667 1.1 christos {
668 1.1 christos int ivg = cec_get_ivg (cpu);
669 1.1 christos if (ivg == -1 || ivg > 3)
670 1.1 christos ssstep = true;
671 1.1 christos }
672 1.1 christos
673 1.1 christos #if 0
674 1.1 christos /* XXX: Is this what happens on the hardware ? */
675 1.1 christos if (cec_get_ivg (cpu) == EVT_EMU)
676 1.1 christos cec_return (cpu, EVT_EMU);
677 1.1 christos #endif
678 1.1 christos
679 1.1 christos BFIN_CPU_STATE.did_jump = false;
680 1.1 christos
681 1.1 christos insn_len = interp_insn_bfin (cpu, oldpc);
682 1.1 christos
683 1.1 christos /* If we executed this insn successfully, then we always decrement
684 1.1 christos the loop counter. We don't want to update the PC though if the
685 1.1 christos last insn happened to be a change in code flow (jump/etc...). */
686 1.1 christos if (!BFIN_CPU_STATE.did_jump)
687 1.1 christos SET_PCREG (hwloop_get_next_pc (cpu, oldpc, insn_len));
688 1.1 christos for (i = 1; i >= 0; --i)
689 1.1 christos if (LCREG (i) && oldpc == LBREG (i))
690 1.1 christos {
691 1.1 christos SET_LCREG (i, LCREG (i) - 1);
692 1.1 christos if (LCREG (i))
693 1.1 christos break;
694 1.1 christos }
695 1.1 christos
696 1.1 christos ++ PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu));
697 1.1 christos
698 1.1 christos /* Handle hardware single stepping only if we're still lower than EVT3.
699 1.1 christos XXX: May not be entirely correct wrt EXCPT insns. */
700 1.1 christos if (ssstep)
701 1.1 christos {
702 1.1 christos int ivg = cec_get_ivg (cpu);
703 1.1 christos if (ivg == -1 || ivg > 3)
704 1.1 christos {
705 1.1 christos INSN_LEN = 0;
706 1.1 christos cec_exception (cpu, VEC_STEP);
707 1.1 christos }
708 1.1 christos }
709 1.1 christos
710 1.1 christos return oldpc;
711 1.1 christos }
712 1.1 christos
713 1.1 christos void
714 1.1 christos sim_engine_run (SIM_DESC sd,
715 1.1 christos int next_cpu_nr, /* ignore */
716 1.1 christos int nr_cpus, /* ignore */
717 1.1 christos int siggnal) /* ignore */
718 1.1 christos {
719 1.1 christos bu32 ticks;
720 1.1 christos SIM_CPU *cpu;
721 1.1 christos
722 1.1 christos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
723 1.1 christos
724 1.1 christos cpu = STATE_CPU (sd, 0);
725 1.1 christos
726 1.1 christos while (1)
727 1.1 christos {
728 1.1 christos step_once (cpu);
729 1.1 christos /* Process any events -- can't use tickn because it may
730 1.1 christos advance right over the next event. */
731 1.1 christos for (ticks = 0; ticks < CYCLE_DELAY; ++ticks)
732 1.1 christos if (sim_events_tick (sd))
733 1.1 christos sim_events_process (sd);
734 1.1 christos }
735 1.1 christos }
736 1.1 christos
737 1.1 christos /* Cover function of sim_state_free to free the cpu buffers as well. */
738 1.1 christos
739 1.1 christos static void
740 1.1 christos free_state (SIM_DESC sd)
741 1.1 christos {
742 1.1 christos if (STATE_MODULES (sd) != NULL)
743 1.1 christos sim_module_uninstall (sd);
744 1.1 christos sim_cpu_free_all (sd);
745 1.1 christos sim_state_free (sd);
746 1.1 christos }
747 1.1 christos
748 1.1 christos /* Create an instance of the simulator. */
749 1.1 christos
750 1.1 christos static void
751 1.1 christos bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
752 1.1 christos {
753 1.1 christos memset (&cpu->state, 0, sizeof (cpu->state));
754 1.1 christos
755 1.1 christos PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0;
756 1.1 christos
757 1.1 christos bfin_model_cpu_init (sd, cpu);
758 1.1 christos
759 1.1 christos /* Set default stack to top of scratch pad. */
760 1.1 christos SET_SPREG (BFIN_DEFAULT_MEM_SIZE);
761 1.1 christos SET_KSPREG (BFIN_DEFAULT_MEM_SIZE);
762 1.1 christos SET_USPREG (BFIN_DEFAULT_MEM_SIZE);
763 1.1 christos
764 1.1 christos /* This is what the hardware likes. */
765 1.1 christos SET_SYSCFGREG (0x30);
766 1.1 christos }
767 1.1 christos
768 1.1 christos SIM_DESC
769 1.1 christos sim_open (SIM_OPEN_KIND kind, host_callback *callback,
770 1.1 christos struct bfd *abfd, char **argv)
771 1.1 christos {
772 1.1 christos char c;
773 1.1 christos int i;
774 1.1 christos SIM_DESC sd = sim_state_alloc (kind, callback);
775 1.1 christos
776 1.1 christos /* The cpu data is kept in a separately allocated chunk of memory. */
777 1.1 christos if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
778 1.1 christos {
779 1.1 christos free_state (sd);
780 1.1 christos return 0;
781 1.1 christos }
782 1.1 christos
783 1.1 christos {
784 1.1 christos /* XXX: Only first core gets profiled ? */
785 1.1 christos SIM_CPU *cpu = STATE_CPU (sd, 0);
786 1.1 christos STATE_WATCHPOINTS (sd)->pc = &PCREG;
787 1.1 christos STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PCREG);
788 1.1 christos }
789 1.1 christos
790 1.1 christos if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
791 1.1 christos {
792 1.1 christos free_state (sd);
793 1.1 christos return 0;
794 1.1 christos }
795 1.1 christos
796 1.1 christos /* XXX: Default to the Virtual environment. */
797 1.1 christos if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
798 1.1 christos STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
799 1.1 christos
800 1.1 christos /* These options override any module options.
801 1.1 christos Obviously ambiguity should be avoided, however the caller may wish to
802 1.1 christos augment the meaning of an option. */
803 1.1 christos #define e_sim_add_option_table(sd, options) \
804 1.1 christos do { \
805 1.1 christos extern const OPTION options[]; \
806 1.1 christos sim_add_option_table (sd, NULL, options); \
807 1.1 christos } while (0)
808 1.1 christos e_sim_add_option_table (sd, bfin_mmu_options);
809 1.1 christos e_sim_add_option_table (sd, bfin_mach_options);
810 1.1 christos
811 1.1 christos /* getopt will print the error message so we just have to exit if this fails.
812 1.1 christos FIXME: Hmmm... in the case of gdb we need getopt to call
813 1.1 christos print_filtered. */
814 1.1 christos if (sim_parse_args (sd, argv) != SIM_RC_OK)
815 1.1 christos {
816 1.1 christos free_state (sd);
817 1.1 christos return 0;
818 1.1 christos }
819 1.1 christos
820 1.1 christos /* Allocate external memory if none specified by user.
821 1.1 christos Use address 4 here in case the user wanted address 0 unmapped. */
822 1.1 christos if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
823 1.1 christos {
824 1.1 christos bu16 emuexcpt = 0x25;
825 1.1 christos sim_do_commandf (sd, "memory-size 0x%lx", BFIN_DEFAULT_MEM_SIZE);
826 1.1 christos sim_write (sd, 0, (void *)&emuexcpt, 2);
827 1.1 christos }
828 1.1 christos
829 1.1 christos /* Check for/establish the a reference program image. */
830 1.1 christos if (sim_analyze_program (sd,
831 1.1 christos (STATE_PROG_ARGV (sd) != NULL
832 1.1 christos ? *STATE_PROG_ARGV (sd)
833 1.1 christos : NULL), abfd) != SIM_RC_OK)
834 1.1 christos {
835 1.1 christos free_state (sd);
836 1.1 christos return 0;
837 1.1 christos }
838 1.1 christos
839 1.1 christos /* Establish any remaining configuration options. */
840 1.1 christos if (sim_config (sd) != SIM_RC_OK)
841 1.1 christos {
842 1.1 christos free_state (sd);
843 1.1 christos return 0;
844 1.1 christos }
845 1.1 christos
846 1.1 christos if (sim_post_argv_init (sd) != SIM_RC_OK)
847 1.1 christos {
848 1.1 christos free_state (sd);
849 1.1 christos return 0;
850 1.1 christos }
851 1.1 christos
852 1.1 christos /* CPU specific initialization. */
853 1.1 christos for (i = 0; i < MAX_NR_PROCESSORS; ++i)
854 1.1 christos {
855 1.1 christos SIM_CPU *cpu = STATE_CPU (sd, i);
856 1.1 christos bfin_initialize_cpu (sd, cpu);
857 1.1 christos }
858 1.1 christos
859 1.1 christos return sd;
860 1.1 christos }
861 1.1 christos
862 1.1 christos void
863 1.1 christos sim_close (SIM_DESC sd, int quitting)
864 1.1 christos {
865 1.1 christos sim_module_uninstall (sd);
866 1.1 christos }
867 1.1 christos
868 1.1 christos /* Some utils don't like having a NULL environ. */
869 1.1 christos static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
870 1.1 christos
871 1.1 christos static bu32 fdpic_load_offset;
872 1.1 christos
873 1.1 christos static bool
874 1.1 christos bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
875 1.1 christos bu32 *elf_addrs, char **ldso_path)
876 1.1 christos {
877 1.1 christos bool ret;
878 1.1 christos int i;
879 1.1 christos
880 1.1 christos Elf_Internal_Ehdr *iehdr;
881 1.1 christos Elf32_External_Ehdr ehdr;
882 1.1 christos Elf_Internal_Phdr *phdrs;
883 1.1 christos unsigned char *data;
884 1.1 christos long phdr_size;
885 1.1 christos int phdrc;
886 1.1 christos bu32 nsegs;
887 1.1 christos
888 1.1 christos bu32 max_load_addr;
889 1.1 christos
890 1.1 christos unsigned char null[4] = { 0, 0, 0, 0 };
891 1.1 christos
892 1.1 christos ret = false;
893 1.1 christos *ldso_path = NULL;
894 1.1 christos
895 1.1 christos /* See if this an FDPIC ELF. */
896 1.1 christos phdrs = NULL;
897 1.1 christos if (!abfd)
898 1.1 christos goto skip_fdpic_init;
899 1.1 christos if (bfd_seek (abfd, 0, SEEK_SET) != 0)
900 1.1 christos goto skip_fdpic_init;
901 1.1 christos if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
902 1.1 christos goto skip_fdpic_init;
903 1.1 christos iehdr = elf_elfheader (abfd);
904 1.1 christos if (!(iehdr->e_flags & EF_BFIN_FDPIC))
905 1.1 christos goto skip_fdpic_init;
906 1.1 christos
907 1.1 christos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
908 1.1 christos sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n",
909 1.1 christos bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]);
910 1.1 christos
911 1.1 christos /* Grab the Program Headers to set up the loadsegs on the stack. */
912 1.1 christos phdr_size = bfd_get_elf_phdr_upper_bound (abfd);
913 1.1 christos if (phdr_size == -1)
914 1.1 christos goto skip_fdpic_init;
915 1.1 christos phdrs = xmalloc (phdr_size);
916 1.1 christos phdrc = bfd_get_elf_phdrs (abfd, phdrs);
917 1.1 christos if (phdrc == -1)
918 1.1 christos goto skip_fdpic_init;
919 1.1 christos
920 1.1 christos /* Push the Ehdr onto the stack. */
921 1.1 christos *sp -= sizeof (ehdr);
922 1.1 christos elf_addrs[3] = *sp;
923 1.1 christos sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr));
924 1.1 christos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
925 1.1 christos sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);
926 1.1 christos
927 1.1 christos /* Since we're relocating things ourselves, we need to relocate
928 1.1 christos the start address as well. */
929 1.1 christos elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset;
930 1.1 christos
931 1.1 christos /* And the Exec's Phdrs onto the stack. */
932 1.1 christos if (STATE_PROG_BFD (sd) == abfd)
933 1.1 christos {
934 1.1 christos elf_addrs[4] = elf_addrs[0];
935 1.1 christos
936 1.1 christos phdr_size = iehdr->e_phentsize * iehdr->e_phnum;
937 1.1 christos if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0)
938 1.1 christos goto skip_fdpic_init;
939 1.1 christos data = xmalloc (phdr_size);
940 1.1 christos if (bfd_bread (data, phdr_size, abfd) != phdr_size)
941 1.1 christos goto skip_fdpic_init;
942 1.1 christos *sp -= phdr_size;
943 1.1 christos elf_addrs[1] = *sp;
944 1.1 christos elf_addrs[2] = phdrc;
945 1.1 christos sim_write (sd, *sp, data, phdr_size);
946 1.1 christos free (data);
947 1.1 christos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
948 1.1 christos sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp);
949 1.1 christos }
950 1.1 christos
951 1.1 christos /* Now push all the loadsegs. */
952 1.1 christos nsegs = 0;
953 1.1 christos max_load_addr = 0;
954 1.1 christos for (i = phdrc; i >= 0; --i)
955 1.1 christos if (phdrs[i].p_type == PT_LOAD)
956 1.1 christos {
957 1.1 christos Elf_Internal_Phdr *p = &phdrs[i];
958 1.1 christos bu32 paddr, vaddr, memsz, filesz;
959 1.1 christos
960 1.1 christos paddr = p->p_paddr + fdpic_load_offset;
961 1.1 christos vaddr = p->p_vaddr;
962 1.1 christos memsz = p->p_memsz;
963 1.1 christos filesz = p->p_filesz;
964 1.1 christos
965 1.1 christos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
966 1.1 christos sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n",
967 1.1 christos i, vaddr, paddr, filesz, memsz);
968 1.1 christos
969 1.1 christos data = xmalloc (memsz);
970 1.1 christos if (memsz != filesz)
971 1.1 christos memset (data + filesz, 0, memsz - filesz);
972 1.1 christos
973 1.1 christos if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
974 1.1 christos && bfd_bread (data, filesz, abfd) == filesz)
975 1.1 christos sim_write (sd, paddr, data, memsz);
976 1.1 christos
977 1.1 christos free (data);
978 1.1 christos
979 1.1 christos max_load_addr = MAX (paddr + memsz, max_load_addr);
980 1.1 christos
981 1.1 christos *sp -= 12;
982 1.1 christos sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr */
983 1.1 christos sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr */
984 1.1 christos sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz */
985 1.1 christos ++nsegs;
986 1.1 christos }
987 1.1 christos else if (phdrs[i].p_type == PT_DYNAMIC)
988 1.1 christos {
989 1.1 christos elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset;
990 1.1 christos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
991 1.1 christos sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]);
992 1.1 christos }
993 1.1 christos else if (phdrs[i].p_type == PT_INTERP)
994 1.1 christos {
995 1.1 christos uint32_t off = phdrs[i].p_offset;
996 1.1 christos uint32_t len = phdrs[i].p_filesz;
997 1.1 christos
998 1.1 christos *ldso_path = xmalloc (len);
999 1.1 christos if (bfd_seek (abfd, off, SEEK_SET) != 0
1000 1.1 christos || bfd_bread (*ldso_path, len, abfd) != len)
1001 1.1 christos {
1002 1.1 christos free (*ldso_path);
1003 1.1 christos *ldso_path = NULL;
1004 1.1 christos }
1005 1.1 christos else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
1006 1.1 christos sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
1007 1.1 christos }
1008 1.1 christos
1009 1.1 christos /* Update the load offset with a few extra pages. */
1010 1.1 christos fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000);
1011 1.1 christos fdpic_load_offset += 0x10000;
1012 1.1 christos
1013 1.1 christos /* Push the summary loadmap info onto the stack last. */
1014 1.1 christos *sp -= 4;
1015 1.1 christos sim_write (sd, *sp+0, null, 2); /* loadmap.version */
1016 1.1 christos sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs */
1017 1.1 christos
1018 1.1 christos ret = true;
1019 1.1 christos skip_fdpic_init:
1020 1.1 christos free (phdrs);
1021 1.1 christos
1022 1.1 christos return ret;
1023 1.1 christos }
1024 1.1 christos
1025 1.1 christos static void
1026 1.1 christos bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd,
1027 1.1 christos const char * const *argv, const char * const *env)
1028 1.1 christos {
1029 1.1 christos /* XXX: Missing host -> target endian ... */
1030 1.1 christos /* Linux starts the user app with the stack:
1031 1.1 christos argc
1032 1.1 christos argv[0] -- pointers to the actual strings
1033 1.1 christos argv[1..N]
1034 1.1 christos NULL
1035 1.1 christos env[0]
1036 1.1 christos env[1..N]
1037 1.1 christos NULL
1038 1.1 christos auxvt[0].type -- ELF Auxiliary Vector Table
1039 1.1 christos auxvt[0].value
1040 1.1 christos auxvt[1..N]
1041 1.1 christos AT_NULL
1042 1.1 christos 0
1043 1.1 christos argv[0..N][0..M] -- actual argv/env strings
1044 1.1 christos env[0..N][0..M]
1045 1.1 christos FDPIC loadmaps -- for FDPIC apps
1046 1.1 christos So set things up the same way. */
1047 1.1 christos int i, argc, envc;
1048 1.1 christos bu32 argv_flat, env_flat;
1049 1.1 christos
1050 1.1 christos bu32 sp, sp_flat;
1051 1.1 christos
1052 1.1 christos /* start, at_phdr, at_phnum, at_base, at_entry, pt_dynamic */
1053 1.1 christos bu32 elf_addrs[6];
1054 1.1 christos bu32 auxvt;
1055 1.1 christos bu32 exec_loadmap, ldso_loadmap;
1056 1.1 christos char *ldso_path;
1057 1.1 christos
1058 1.1 christos unsigned char null[4] = { 0, 0, 0, 0 };
1059 1.1 christos
1060 1.1 christos host_callback *cb = STATE_CALLBACK (sd);
1061 1.1 christos
1062 1.1 christos elf_addrs[0] = elf_addrs[4] = bfd_get_start_address (abfd);
1063 1.1 christos elf_addrs[1] = elf_addrs[2] = elf_addrs[3] = elf_addrs[5] = 0;
1064 1.1 christos
1065 1.1 christos /* Keep the load addresses consistent between runs. Also make sure we make
1066 1.1 christos space for the fixed code region (part of the Blackfin Linux ABI). */
1067 1.1 christos fdpic_load_offset = 0x1000;
1068 1.1 christos
1069 1.1 christos /* First try to load this as an FDPIC executable. */
1070 1.1 christos sp = SPREG;
1071 1.1 christos if (!bfin_fdpic_load (sd, cpu, STATE_PROG_BFD (sd), &sp, elf_addrs, &ldso_path))
1072 1.1 christos goto skip_fdpic_init;
1073 1.1 christos exec_loadmap = sp;
1074 1.1 christos
1075 1.1 christos /* If that worked, then load the fixed code region. We only do this for
1076 1.1 christos FDPIC ELFs atm because they are PIEs and let us relocate them without
1077 1.1 christos manual fixups. FLAT files however require location processing which
1078 1.1 christos we do not do ourselves, and they link with a VMA of 0. */
1079 1.1 christos sim_write (sd, 0x400, bfin_linux_fixed_code, sizeof (bfin_linux_fixed_code));
1080 1.1 christos
1081 1.1 christos /* If the FDPIC needs an interpreter, then load it up too. */
1082 1.1 christos if (ldso_path)
1083 1.1 christos {
1084 1.1 christos const char *ldso_full_path = concat (simulator_sysroot, ldso_path, NULL);
1085 1.1 christos struct bfd *ldso_bfd;
1086 1.1 christos
1087 1.1 christos ldso_bfd = bfd_openr (ldso_full_path, STATE_TARGET (sd));
1088 1.1 christos if (!ldso_bfd)
1089 1.1 christos {
1090 1.1 christos sim_io_eprintf (sd, "bfin-sim: bfd open failed: %s\n", ldso_full_path);
1091 1.1 christos goto static_fdpic;
1092 1.1 christos }
1093 1.1 christos if (!bfd_check_format (ldso_bfd, bfd_object))
1094 1.1 christos sim_io_eprintf (sd, "bfin-sim: bfd format not valid: %s\n", ldso_full_path);
1095 1.1 christos bfd_set_arch_info (ldso_bfd, STATE_ARCHITECTURE (sd));
1096 1.1 christos
1097 1.1 christos if (!bfin_fdpic_load (sd, cpu, ldso_bfd, &sp, elf_addrs, &ldso_path))
1098 1.1 christos sim_io_eprintf (sd, "bfin-sim: FDPIC ldso failed to load: %s\n", ldso_full_path);
1099 1.1 christos if (ldso_path)
1100 1.1 christos sim_io_eprintf (sd, "bfin-sim: FDPIC ldso (%s) needs an interpreter (%s) !?\n",
1101 1.1 christos ldso_full_path, ldso_path);
1102 1.1 christos
1103 1.1 christos ldso_loadmap = sp;
1104 1.1 christos }
1105 1.1 christos else
1106 1.1 christos static_fdpic:
1107 1.1 christos ldso_loadmap = 0;
1108 1.1 christos
1109 1.1 christos /* Finally setup the registers required by the FDPIC ABI. */
1110 1.1 christos SET_DREG (7, 0); /* Zero out FINI funcptr -- ldso will set this up. */
1111 1.1 christos SET_PREG (0, exec_loadmap); /* Exec loadmap addr. */
1112 1.1 christos SET_PREG (1, ldso_loadmap); /* Interp loadmap addr. */
1113 1.1 christos SET_PREG (2, elf_addrs[5]); /* PT_DYNAMIC map addr. */
1114 1.1 christos
1115 1.1 christos auxvt = 1;
1116 1.1 christos SET_SPREG (sp);
1117 1.1 christos skip_fdpic_init:
1118 1.1 christos sim_pc_set (cpu, elf_addrs[0]);
1119 1.1 christos
1120 1.1 christos /* Figure out how much storage the argv/env strings need. */
1121 1.1 christos argc = count_argc (argv);
1122 1.1 christos if (argc == -1)
1123 1.1 christos argc = 0;
1124 1.1 christos argv_flat = argc; /* NUL bytes */
1125 1.1 christos for (i = 0; i < argc; ++i)
1126 1.1 christos argv_flat += strlen (argv[i]);
1127 1.1 christos
1128 1.1 christos if (!env)
1129 1.1 christos env = simple_env;
1130 1.1 christos envc = count_argc (env);
1131 1.1 christos env_flat = envc; /* NUL bytes */
1132 1.1 christos for (i = 0; i < envc; ++i)
1133 1.1 christos env_flat += strlen (env[i]);
1134 1.1 christos
1135 1.1 christos /* Push the Auxiliary Vector Table between argv/env and actual strings. */
1136 1.1 christos sp_flat = sp = ALIGN (SPREG - argv_flat - env_flat - 4, 4);
1137 1.1 christos if (auxvt)
1138 1.1 christos {
1139 1.1 christos # define AT_PUSH(at, val) \
1140 1.1 christos auxvt_size += 8; \
1141 1.1 christos sp -= 4; \
1142 1.1 christos auxvt = (val); \
1143 1.1 christos sim_write (sd, sp, (void *)&auxvt, 4); \
1144 1.1 christos sp -= 4; \
1145 1.1 christos auxvt = (at); \
1146 1.1 christos sim_write (sd, sp, (void *)&auxvt, 4)
1147 1.1 christos unsigned int egid = getegid (), gid = getgid ();
1148 1.1 christos unsigned int euid = geteuid (), uid = getuid ();
1149 1.1 christos bu32 auxvt_size = 0;
1150 1.1 christos AT_PUSH (AT_NULL, 0);
1151 1.1 christos AT_PUSH (AT_SECURE, egid != gid || euid != uid);
1152 1.1 christos AT_PUSH (AT_EGID, egid);
1153 1.1 christos AT_PUSH (AT_GID, gid);
1154 1.1 christos AT_PUSH (AT_EUID, euid);
1155 1.1 christos AT_PUSH (AT_UID, uid);
1156 1.1 christos AT_PUSH (AT_ENTRY, elf_addrs[4]);
1157 1.1 christos AT_PUSH (AT_FLAGS, 0);
1158 1.1 christos AT_PUSH (AT_BASE, elf_addrs[3]);
1159 1.1 christos AT_PUSH (AT_PHNUM, elf_addrs[2]);
1160 1.1 christos AT_PUSH (AT_PHENT, sizeof (Elf32_External_Phdr));
1161 1.1 christos AT_PUSH (AT_PHDR, elf_addrs[1]);
1162 1.1 christos AT_PUSH (AT_CLKTCK, 100); /* XXX: This ever not 100 ? */
1163 1.1 christos AT_PUSH (AT_PAGESZ, 4096);
1164 1.1 christos AT_PUSH (AT_HWCAP, 0);
1165 1.1 christos #undef AT_PUSH
1166 1.1 christos }
1167 1.1 christos SET_SPREG (sp);
1168 1.1 christos
1169 1.1 christos /* Push the argc/argv/env after the auxvt. */
1170 1.1 christos sp -= ((1 + argc + 1 + envc + 1) * 4);
1171 1.1 christos SET_SPREG (sp);
1172 1.1 christos
1173 1.1 christos /* First push the argc value. */
1174 1.1 christos sim_write (sd, sp, (void *)&argc, 4);
1175 1.1 christos sp += 4;
1176 1.1 christos
1177 1.1 christos /* Then the actual argv strings so we know where to point argv[]. */
1178 1.1 christos for (i = 0; i < argc; ++i)
1179 1.1 christos {
1180 1.1 christos unsigned len = strlen (argv[i]) + 1;
1181 1.1 christos sim_write (sd, sp_flat, (void *)argv[i], len);
1182 1.1 christos sim_write (sd, sp, (void *)&sp_flat, 4);
1183 1.1 christos sp_flat += len;
1184 1.1 christos sp += 4;
1185 1.1 christos }
1186 1.1 christos sim_write (sd, sp, null, 4);
1187 1.1 christos sp += 4;
1188 1.1 christos
1189 1.1 christos /* Then the actual env strings so we know where to point env[]. */
1190 1.1 christos for (i = 0; i < envc; ++i)
1191 1.1 christos {
1192 1.1 christos unsigned len = strlen (env[i]) + 1;
1193 1.1 christos sim_write (sd, sp_flat, (void *)env[i], len);
1194 1.1 christos sim_write (sd, sp, (void *)&sp_flat, 4);
1195 1.1 christos sp_flat += len;
1196 1.1 christos sp += 4;
1197 1.1 christos }
1198 1.1 christos
1199 1.1 christos /* Set some callbacks. */
1200 1.1 christos cb->syscall_map = cb_linux_syscall_map;
1201 1.1 christos cb->errno_map = cb_linux_errno_map;
1202 1.1 christos cb->open_map = cb_linux_open_map;
1203 1.1 christos cb->signal_map = cb_linux_signal_map;
1204 1.1 christos cb->stat_map = stat_map_32 = cb_linux_stat_map_32;
1205 1.1 christos stat_map_64 = cb_linux_stat_map_64;
1206 1.1 christos }
1207 1.1 christos
1208 1.1 christos static void
1209 1.1 christos bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, const char * const *argv)
1210 1.1 christos {
1211 1.1 christos /* Pass the command line via a string in R0 like Linux expects. */
1212 1.1 christos int i;
1213 1.1 christos bu8 byte;
1214 1.1 christos bu32 cmdline = BFIN_L1_SRAM_SCRATCH;
1215 1.1 christos
1216 1.1 christos SET_DREG (0, cmdline);
1217 1.1 christos if (argv && argv[0])
1218 1.1 christos {
1219 1.1 christos i = 1;
1220 1.1 christos byte = ' ';
1221 1.1 christos while (argv[i])
1222 1.1 christos {
1223 1.1 christos bu32 len = strlen (argv[i]);
1224 1.1 christos sim_write (sd, cmdline, (void *)argv[i], len);
1225 1.1 christos cmdline += len;
1226 1.1 christos sim_write (sd, cmdline, &byte, 1);
1227 1.1 christos ++cmdline;
1228 1.1 christos ++i;
1229 1.1 christos }
1230 1.1 christos }
1231 1.1 christos byte = 0;
1232 1.1 christos sim_write (sd, cmdline, &byte, 1);
1233 1.1 christos }
1234 1.1 christos
1235 1.1 christos static void
1236 1.1 christos bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu)
1237 1.1 christos {
1238 1.1 christos host_callback *cb = STATE_CALLBACK (sd);
1239 1.1 christos
1240 1.1 christos cb->stat_map = stat_map_32 = cb_libgloss_stat_map_32;
1241 1.1 christos stat_map_64 = NULL;
1242 1.1 christos }
1243 1.1 christos
1244 1.1 christos SIM_RC
1245 1.1 christos sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
1246 1.1 christos char **argv, char **env)
1247 1.1 christos {
1248 1.1 christos SIM_CPU *cpu = STATE_CPU (sd, 0);
1249 1.1 christos SIM_ADDR addr;
1250 1.1 christos
1251 1.1 christos /* Set the PC. */
1252 1.1 christos if (abfd != NULL)
1253 1.1 christos addr = bfd_get_start_address (abfd);
1254 1.1 christos else
1255 1.1 christos addr = 0;
1256 1.1 christos sim_pc_set (cpu, addr);
1257 1.1 christos
1258 1.1 christos /* Standalone mode (i.e. `bfin-...-run`) will take care of the argv
1259 1.1 christos for us in sim_open() -> sim_parse_args(). But in debug mode (i.e.
1260 1.1 christos 'target sim' with `bfin-...-gdb`), we need to handle it. */
1261 1.1 christos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
1262 1.1 christos {
1263 1.1 christos freeargv (STATE_PROG_ARGV (sd));
1264 1.1 christos STATE_PROG_ARGV (sd) = dupargv (argv);
1265 1.1 christos }
1266 1.1 christos
1267 1.1 christos switch (STATE_ENVIRONMENT (sd))
1268 1.1 christos {
1269 1.1 christos case USER_ENVIRONMENT:
1270 1.1 christos bfin_user_init (sd, cpu, abfd, (void *)argv, (void *)env);
1271 1.1 christos break;
1272 1.1 christos case OPERATING_ENVIRONMENT:
1273 1.1 christos bfin_os_init (sd, cpu, (void *)argv);
1274 1.1 christos break;
1275 1.1 christos default:
1276 1.1 christos bfin_virtual_init (sd, cpu);
1277 1.1 christos break;
1278 1.1 christos }
1279 1.1 christos
1280 1.1 christos return SIM_RC_OK;
1281 1.1 christos }
1282