#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <sys/syscall.h>
#include "qemu.h"
#include "qemu-common.h"
char *exec_path;
int singlestep;
+#if defined(CONFIG_USE_GUEST_BASE)
+unsigned long mmap_min_addr = 0;
+unsigned long guest_base = 0;
+#endif
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
- exit (1);
+ _exit (1);
}
process_pending_signals (env);
}
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
- exit (1);
+ _exit (1);
}
process_pending_signals (env);
}
"-E var=value sets/modifies targets environment variable(s)\n"
"-U var unsets targets environment variable(s)\n"
"-0 argv0 forces target process argv[0] to be argv0\n"
+#if defined(CONFIG_USE_GUEST_BASE)
+ "-B address set guest_base address to address\n"
+#endif
"\n"
"Debug options:\n"
"-d options activate log (logfile=%s)\n"
" -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
"Note that if you provide several changes to single variable\n"
"last change will stay in effect.\n"
+#if defined(CONFIG_USE_GUEST_BASE)
+ "\n"
+ "You can use -B option to load target binary into different\n"
+ "address that is specified in elf headers. This can be useful\n"
+ "when target binary would be loaded to low addresses and\n"
+ "/proc/sys/vm/mmap_min_addr is set to higher. For example\n"
+ " qemu-" TARGET_ARCH " -B 0x100000 ...\n"
+ "loads target binary starting from the first meg.\n"
+#endif
,
TARGET_ARCH,
interp_prefix,
THREAD CPUState *thread_env;
+void task_settid(TaskState *ts)
+{
+ if (ts->ts_tid == 0) {
+#ifdef USE_NPTL
+ ts->ts_tid = (pid_t)syscall(SYS_gettid);
+#else
+ /* when no threads are used, tid becomes pid */
+ ts->ts_tid = getpid();
+#endif
+ }
+}
+
+void stop_all_tasks(void)
+{
+ /*
+ * We trust that when using NPTL, start_exclusive()
+ * handles thread stopping correctly.
+ */
+ start_exclusive();
+}
+
/* Assumes contents are already zeroed. */
void init_task_state(TaskState *ts)
{
int main(int argc, char **argv, char **envp)
{
- const char *filename;
+ char *filename = NULL;
const char *cpu_model;
struct target_pt_regs regs1, *regs = ®s1;
struct image_info info1, *info = &info1;
+ struct linux_binprm bprm;
TaskState ts1, *ts = &ts1;
CPUState *env;
int optind;
char **target_environ, **wrk;
char **target_argv;
int target_argc;
+ int drop_ld_preload = 0;
envlist_t *envlist = NULL;
const char *argv0 = NULL;
+ int argskip = 0;
int i;
if (argc <= 1)
for(item = cpu_log_items; item->mask != 0; item++) {
printf("%-10s %s\n", item->name, item->help);
}
- exit(1);
+ _exit(1);
}
cpu_set_log(mask);
} else if (!strcmp(r, "E")) {
} else if (!strcmp(r, "0")) {
r = argv[optind++];
argv0 = r;
+ } else if (!strcmp(r,"-sbox-call")) {
+ argskip++;
} else if (!strcmp(r, "s")) {
if (optind >= argc)
break;
if (qemu_host_page_size == 0 ||
(qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
fprintf(stderr, "page size must be a power of two\n");
- exit(1);
+ _exit(1);
}
} else if (!strcmp(r, "g")) {
if (optind >= argc)
#endif
exit(1);
}
+#if defined(CONFIG_USE_GUEST_BASE)
+ } else if (!strcmp(r, "B")) {
+ guest_base = strtol(argv[optind++], NULL, 0);
+#endif
} else if (!strcmp(r, "drop-ld-preload")) {
- (void) envlist_unsetenv(envlist, "LD_PRELOAD");
+ drop_ld_preload = 1;
+ } else if (!strcmp(r, "keep-ld-preload")) {
+ drop_ld_preload = 0;
} else if (!strcmp(r, "singlestep")) {
singlestep = 1;
} else if (!strcmp(r, "strace")) {
}
if (optind >= argc)
usage();
- filename = argv[optind];
- exec_path = argv[optind];
+ if (filename == NULL) {
+ filename = argv[optind];
+ exec_path = argv[optind];
+ } else {
+ argv0 = argv[optind];
+ }
+ if (drop_ld_preload) {
+ (void) envlist_unsetenv(envlist, "LD_PRELOAD");
+ }
/* Zero out regs */
memset(regs, 0, sizeof(struct target_pt_regs));
/* Zero out image_info */
memset(info, 0, sizeof(struct image_info));
+ memset(&bprm, 0, sizeof (bprm));
+
/* Scan interp_prefix dir for replacement files. */
init_paths(interp_prefix);
target_environ = envlist_to_environ(envlist, NULL);
envlist_free(envlist);
+#if defined(CONFIG_USE_GUEST_BASE)
+ /*
+ * Now that page sizes are configured in cpu_init() we can do
+ * proper page alignment for guest_base.
+ */
+ guest_base = HOST_PAGE_ALIGN(guest_base);
+
+ /*
+ * Read in mmap_min_addr kernel parameter and check
+ * whether it is set to some value > 0. This value is used
+ * later on when doing mmap(2)s to calculate where guest_base
+ * is to set, if needed.
+ *
+ * When user has explicitly set the quest base, we skip this
+ * test.
+ */
+ if (guest_base == 0) {
+ FILE *fp;
+
+ if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
+ unsigned long tmp;
+ if (fscanf(fp, "%lu", &tmp) == 1) {
+ mmap_min_addr = tmp;
+ qemu_log("kernel mmap_min_addr=%lu\n", mmap_min_addr);
+ }
+ fclose(fp);
+ }
+ }
+#endif /* CONFIG_USE_GUEST_BASE */
+
/*
* Prepare copy of argv vector for target.
*/
}
target_argv[target_argc] = NULL;
- if (loader_exec(filename, target_argv, target_environ, regs, info) != 0) {
+ memset(ts, 0, sizeof(TaskState));
+ init_task_state(ts);
+ /* build Task State */
+ ts->info = info;
+ ts->bprm = &bprm;
+ env->opaque = ts;
+ task_settid(ts);
+
+ if (loader_exec(filename, target_argv+argskip, target_environ, regs,
+ info, &bprm) != 0) {
printf("Error loading %s\n", filename);
_exit(1);
}
free(target_environ);
if (qemu_log_enabled()) {
+#if defined(CONFIG_USE_GUEST_BASE)
+ if (guest_base > 0) {
+ qemu_log("guest_base is set to 0x%lx\n", guest_base);
+ qemu_log(
+ "==========================================================\n"
+ "Note that all target addresses below are given in target\n"
+ "address space which is different from host by guest_base.\n"
+ "For example: target address 0x%lx becomes 0x%lx and so on.\n"
+ "==========================================================\n",
+ (uintptr_t)0x8000, (uintptr_t)g2h(0x8000));
+ }
+#endif
log_page_dump();
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
syscall_init();
signal_init();
- /* build Task State */
- memset(ts, 0, sizeof(TaskState));
- init_task_state(ts);
- ts->info = info;
- env->opaque = ts;
-
#if defined(TARGET_I386)
cpu_x86_set_cpl(env, 3);