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