--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __CODE_INJECT_H__
+#define __CODE_INJECT_H__
+
+int v3_insert_code_inject (void *ginfo, void *code, int size, char *bin_file,
+ int is_dyn, int is_exec_hooked, int func_offset);
+
+#ifdef __V3VEE__
+
+#define E_NEED_PF -2
+
+#define MMAP_SIZE 86
+#define MUNMAP_SIZE 22
+#define VMMCALL_SIZE 10
+
+#define PAGES_BACK 50
+#define ELF_MAG_SIZE 4
+#define NO_MMAP 0
+#define MMAP_COMPLETE 1
+
+struct v3_code_injects {
+ struct list_head code_inject_list;
+ struct list_head hooked_code_injects;
+ int active;
+};
+
+
+// TODO: adjust size of boolean members
+struct v3_code_inject_info {
+
+ // pointer to ELF and its size
+ void *code;
+ int code_size;
+
+
+ // indicates this is a hooked inject
+ int is_exec_hooked;
+ char * bin_file;
+
+ // important offsets to ELF sections
+ // for the injected code
+ int func_offset;
+ int got_offset;
+ int plt_offset;
+
+
+ int is_dyn;
+ addr_t code_region_gva;
+ // continuation-style function for
+ // page fault handling
+ struct v3_cont *cont;
+
+
+ // the following are for saving context
+ char *old_code;
+ struct v3_gprs regs;
+ struct v3_ctrl_regs ctrl_regs;
+ uint64_t rip;
+
+ struct list_head inject_node;
+
+ int in_progress;
+};
+
+struct v3_cont {
+ addr_t check_addr;
+ int (*cont_func)(struct guest_info * core, struct v3_code_inject_info * inject,
+ addr_t check);
+};
+
+int v3_remove_code_inject(struct v3_vm_info * vm, struct v3_code_inject_info * inject);
+int v3_do_inject(struct guest_info * core, struct v3_code_inject_info * inject, int mmap_state);
+int v3_do_static_inject(struct guest_info * core, struct v3_code_inject_info * inject,
+ int mmap_state, addr_t region_gva);
+int v3_handle_guest_inject(struct guest_info * core, void * priv_data);
+
+#endif /* ! __V3VEE__ */
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2012, Kyle C. Hale <kh@u.northwestern.edu>
+ * Copyright (c) 2012, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __ENV_INJECT_H__
+#define __ENV_INJECT_H__
+
+int v3_insert_env_inject (void *ginfo, char ** strings, int num_strings, char * bin_name);
+
+#ifdef __V3VEE__
+
+struct v3_env_injects {
+ struct list_head env_inject_list;
+};
+
+
+struct v3_env_inject_info {
+ char ** env_vars;
+ int num_env_vars;
+ struct list_head inject_node;
+ char * bin_name;
+};
+
+int v3_remove_env_inject (struct v3_vm_info * vm, struct v3_env_inject_info * inject);
+
+#endif /* ! __V3VEE__ */
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __EXECVE_HOOK_H__
+#define __EXECVE_HOOK_H__
+
+#ifdef __V3VEE__
+
+struct v3_exec_hooks {
+ struct list_head hook_list;
+ struct hashtable * bin_table;
+};
+
+
+struct exec_hook {
+ int (*handler)(struct guest_info * core, void * priv_data);
+ struct list_head hook_node;
+ void * priv_data;
+};
+
+
+int v3_execve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data);
+
+#endif
+
+int v3_hook_executable (struct v3_vm_info * vm,
+ const uchar_t * binfile,
+ int (*handler)(struct guest_info * core, void * priv_data),
+ void * priv_data);
+
+int v3_unhook_executable (struct v3_vm_info * core, const uchar_t * binfile);
+#endif
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __PROCESS_ENVIRONMENT_H__
+#define __PROCESS_ENVIRONMENT_H__
+
+#ifdef __V3VEE__
+
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_types.h>
+#include <palacios/vm_guest.h>
+
+
+struct v3_execve_varchunk {
+ char ** argv;
+ char ** envp;
+ uint_t argc;
+ uint_t envc;
+ uint_t bytes;
+ int active;
+};
+
+int v3_replace_arg (struct guest_info * core, uint_t argnum, const char * newval);
+int v3_replace_env (struct guest_info * core, const char * envname, const char * newval);
+
+int v3_inject_strings (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt);
+
+addr_t v3_prepare_guest_stack (struct guest_info * core, uint_t bytes_needed);
+
+
+#endif
+
+#endif
+
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __SW_INTR_H__
+#define __SW_INTR_H__
+
+#include <palacios/vmm.h>
+
+#define SW_INTR_SYSCALL_VEC 0x80
+
+int v3_handle_swintr (struct guest_info * core);
+
+int v3_hook_swintr (struct guest_info * core,
+ uint8_t vector,
+ int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
+ void * priv_data);
+int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector);
+
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __SYSCALL_HIJACK_H__
+#define __SYSCALL_HIJACK_H__
+
+#define STAR_MSR 0xc0000081 /* Legacy mode SYSCALL target */
+#define LSTAR_MSR 0xc0000082 /* Long mode SYSCALL target */
+#define CSTAR_MSR 0xc0000083 /* compat mode SYSCALL target */
+#define SF_MASK_MSR 0xc0000084 /* EFLAGS mask for syscall */
+#define SYSENTER_CS_MSR 0x00000174 /* SYSENTER/EXIT are for legacy mode only on AMD */
+#define SYSENTER_ESP_MSR 0x00000175
+#define SYSENTER_EIP_MSR 0x00000176
+
+/* Intel specific */
+#define IA32_SYSENTER_CS_MSR 0x00000174
+#define IA32_SYSENTER_ESP_MSR 0x00000175
+#define IA32_SYSENTER_EIP_MSR 0x00000176
+
+#define MAX_CHARS 256
+#ifndef max
+ #define max(a, b) ( ((a) > (b)) ? (a) : (b) )
+#endif
+
+#define SYSCALL_INT_VECTOR 0x80
+#define SYSCALL_CPUID_NUM 0x80000001
+#define SYSENTER_CPUID_NUM 0x00000001
+
+#define SYSCALL_MAGIC_ADDR 0xffffffffffffffff
+
+#define KERNEL_PHYS_LOAD_ADDR 0x1000000
+
+
+struct v3_syscall_info {
+ uint64_t target_addr;
+ uint8_t syscall_map_injected;
+ char * syscall_page_backup;
+ uint8_t * syscall_map;
+ addr_t syscall_stub;
+ // state save area
+ addr_t ssa;
+};
+
+int v3_hook_syscall (struct guest_info * core,
+ uint_t syscall_nr,
+ int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data),
+ void * priv_data);
+
+int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr);
+int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data);
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __SYSCALL_REF_H__
+#define __SYSCALL_REF_H__
+
+char * get_linux_syscall_name32 (uint_t syscall_nr);
+char * get_linux_syscall_name64 (uint_t syscall_nr);
+
+
+/* 32bit syscalls */
+#define SYS32_RESTART_SYSCALL 0
+#define SYS32_EXIT 1
+#define SYS32_FORK 2
+#define SYS32_READ 3
+#define SYS32_WRITE 4
+#define SYS32_OPEN 5
+#define SYS32_CLOSE 6
+#define SYS32_WAITPID 7
+#define SYS32_CREAT 8
+#define SYS32_LINK 9
+#define SYS32_UNLINK 10
+#define SYS32_EXECVE 11
+#define SYS32_CHDIR 12
+#define SYS32_TIME 13
+#define SYS32_MKNOD 14
+#define SYS32_CHMOD 15
+#define SYS32_LCHOWN 16
+#define SYS32_BREAK 17
+#define SYS32_OLDSTAT 18
+#define SYS32_LSEEK 19
+#define SYS32_GETPID 20
+#define SYS32_MOUNT 21
+#define SYS32_UMOUNT 22
+#define SYS32_SETUID 23
+#define SYS32_GETUID 24
+#define SYS32_STIME 25
+#define SYS32_PTRACE 26
+#define SYS32_ALARM 27
+#define SYS32_OLDFSTAT 28
+#define SYS32_PAUSE 29
+#define SYS32_UTIME 30
+#define SYS32_STTY 31
+#define SYS32_GTTY 32
+#define SYS32_ACCESS 33
+#define SYS32_NICE 34
+#define SYS32_FTIME 35
+#define SYS32_SYNC 36
+#define SYS32_KILL 37
+#define SYS32_RENAME 38
+#define SYS32_MKDIR 39
+#define SYS32_RMDIR 40
+#define SYS32_DUP 41
+#define SYS32_PIPE 42
+#define SYS32_TIMES 43
+#define SYS32_PROF 44
+#define SYS32_BRK 45
+#define SYS32_SETGID 46
+#define SYS32_GETGID 47
+#define SYS32_SIGNAL 48
+#define SYS32_GETEUID 49
+#define SYS32_GETEGID 50
+#define SYS32_ACCT 51
+#define SYS32_UMOUNT2 52
+#define SYS32_LOCK 53
+#define SYS32_IOCTL 54
+#define SYS32_FCNTL 55
+#define SYS32_MPX 56
+#define SYS32_SETPGID 57
+#define SYS32_ULIMIT 58
+#define SYS32_OLDOLDUNAME 59
+#define SYS32_UMASK 60
+#define SYS32_CHROOT 61
+#define SYS32_USTAT 62
+#define SYS32_DUP2 63
+#define SYS32_GETPPID 64
+#define SYS32_GETPGRP 65
+#define SYS32_SETSID 66
+#define SYS32_SIGACTION 67
+#define SYS32_SGETMASK 68
+#define SYS32_SSETMASK 69
+#define SYS32_SETREUID 70
+#define SYS32_SETREGID 71
+#define SYS32_SIGSUSPEND 72
+#define SYS32_SIGPENDING 73
+#define SYS32_SETHOSTNAME 74
+#define SYS32_SETRLIMIT 75
+#define SYS32_GETRLIMIT 76
+#define SYS32_GETRUSAGE 77
+#define SYS32_GETTIMEOFDAY 78
+#define SYS32_SETTIMEOFDAY 79
+#define SYS32_GETGROUPS 80
+#define SYS32_SETGROUPS 81
+#define SYS32_SELECT 82
+#define SYS32_SYMLINK 83
+#define SYS32_OLDLSTAT 84
+#define SYS32_READLINK 85
+#define SYS32_USELIB 86
+#define SYS32_SWAPON 87
+#define SYS32_REBOOT 88
+#define SYS32_READDIR 89
+#define SYS32_MMAP 90
+#define SYS32_MUNMAP 91
+#define SYS32_TRUNCATE 92
+#define SYS32_FTRUNCATE 93
+#define SYS32_FCHMOD 94
+#define SYS32_FCHOWN 95
+#define SYS32_GETPRIORITY 96
+#define SYS32_SETPRIORITY 97
+#define SYS32_PROFIL 98
+#define SYS32_STATFS 99
+#define SYS32_FSTATFS 100
+#define SYS32_IOPERM 101
+#define SYS32_SOCKETCALL 102
+#define SYS32_SYSLOG 103
+#define SYS32_SETITIMER 104
+#define SYS32_GETITIMER 105
+#define SYS32_STAT 106
+#define SYS32_LSTAT 107
+#define SYS32_FSTAT 108
+#define SYS32_OLDUNAME 109
+#define SYS32_IOPL 110
+#define SYS32_VHANGUP 111
+#define SYS32_IDLE 112
+#define SYS32_VM86OLD 113
+#define SYS32_WAIT4 114
+#define SYS32_SWAPOFF 115
+#define SYS32_SYSINFO 116
+#define SYS32_IPC 117
+#define SYS32_FSYNC 118
+#define SYS32_SIGRETURN 119
+#define SYS32_CLONE 120
+#define SYS32_SETDOMAINNAME 121
+#define SYS32_UNAME 122
+#define SYS32_MODIFY_LDT 123
+#define SYS32_ADJTIMEX 124
+#define SYS32_MPROTECT 125
+#define SYS32_SIGPROCMASK 126
+#define SYS32_CREATE_MODULE 127
+#define SYS32_INIT_MODULE 128
+#define SYS32_DELETE_MODULE 129
+#define SYS32_GET_KERNEL_SYMS 130
+#define SYS32_QUOTACTL 131
+#define SYS32_GETPGID 132
+#define SYS32_FCHDIR 133
+#define SYS32_BDFLUSH 134
+#define SYS32_SYSFS 135
+#define SYS32_PERSONALITY 136
+#define SYS32_AFS_SYSCALL 137
+#define SYS32_SETFSUID 138
+#define SYS32_SETFSGID 139
+#define SYS32__LLSEEK 140
+#define SYS32_GETDENTS 141
+#define SYS32__NEWSELECT 142
+#define SYS32_FLOCK 143
+#define SYS32_MSYNC 144
+#define SYS32_READV 145
+#define SYS32_WRITEV 146
+#define SYS32_GETSID 147
+#define SYS32_FDATASYNC 148
+#define SYS32__SYSCTL 149
+#define SYS32_MLOCK 150
+#define SYS32_MUNLOCK 151
+#define SYS32_MLOCKALL 152
+#define SYS32_MUNLOCKALL 153
+#define SYS32_SCHED_SETPARAM 154
+#define SYS32_SCHED_GETPARAM 155
+#define SYS32_SCHED_SETSCHEDULER 156
+#define SYS32_SCHED_GETSCHEDULER 157
+#define SYS32_SCHED_YIELD 158
+#define SYS32_SCHED_GET_PRIORITY_MAX 159
+#define SYS32_SCHED_GET_PRIORITY_MIN 160
+#define SYS32_SCHED_RR_GET_INTERVAL 161
+#define SYS32_NANOSLEEP 162
+#define SYS32_MREMAP 163
+#define SYS32_SETRESUID 164
+#define SYS32_GETRESUID 165
+#define SYS32_VM86 166
+#define SYS32_QUERY_MODULE 167
+#define SYS32_POLL 168
+#define SYS32_NFSSERVCTL 169
+#define SYS32_SETRESGID 170
+#define SYS32_GETRESGID 171
+#define SYS32_PRCTL 172
+#define SYS32_RT_SIGRETURN 173
+#define SYS32_RT_SIGACTION 174
+#define SYS32_RT_SIGPROCMASK 175
+#define SYS32_RT_SIGPENDING 176
+#define SYS32_RT_SIGTIMEDWAIT 177
+#define SYS32_RT_SIGQUEUEINFO 178
+#define SYS32_RT_SIGSUSPEND 179
+#define SYS32_PREAD64 180
+#define SYS32_PWRITE64 181
+#define SYS32_CHOWN 182
+#define SYS32_GETCWD 183
+#define SYS32_CAPGET 184
+#define SYS32_CAPSET 185
+#define SYS32_SIGALTSTACK 186
+#define SYS32_SENDFILE 187
+#define SYS32_GETPMSG 188
+#define SYS32_PUTPMSG 189
+#define SYS32_VFORK 190
+#define SYS32_UGETRLIMIT 191
+#define SYS32_MMAP2 192
+#define SYS32_TRUNCATE64 193
+#define SYS32_FTRUNCATE64 194
+#define SYS32_STAT64 195
+#define SYS32_LSTAT64 196
+#define SYS32_FSTAT64 197
+#define SYS32_LCHOWN32 198
+#define SYS32_GETUID32 199
+#define SYS32_GETGID32 200
+#define SYS32_GETEUID32 201
+#define SYS32_GETEGID32 202
+#define SYS32_SETREUID32 203
+#define SYS32_SETREGID32 204
+#define SYS32_GETGROUPS32 205
+#define SYS32_SETGROUPS32 206
+#define SYS32_FCHOWN32 207
+#define SYS32_SETRESUID32 208
+#define SYS32_GETRESUID32 209
+#define SYS32_SETRESGID32 210
+#define SYS32_GETRESGID32 211
+#define SYS32_CHOWN32 212
+#define SYS32_SETUID32 213
+#define SYS32_SETGID32 214
+#define SYS32_SETFSUID32 215
+#define SYS32_SETFSGID32 216
+#define SYS32_PIVOT_ROOT 217
+#define SYS32_MINCORE 218
+#define SYS32_MADVISE1 219
+#define SYS32_GETDENTS64 220
+#define SYS32_FCNTL64 221
+#define SYS32_GETTID 224
+#define SYS32_READAHEAD 225
+#define SYS32_SETXATTR 226
+#define SYS32_LSETXATTR 227
+#define SYS32_FSETXATTR 228
+#define SYS32_GETXATTR 229
+#define SYS32_LGETXATTR 230
+#define SYS32_FGETXATTR 231
+#define SYS32_LISTXATTR 232
+#define SYS32_LLISTXATTR 233
+#define SYS32_FLISTXATTR 234
+#define SYS32_REMOVEXATTR 235
+#define SYS32_LREMOVEXATTR 236
+#define SYS32_FREMOVEXATTR 237
+#define SYS32_TKILL 238
+#define SYS32_SENDFILE64 239
+#define SYS32_FUTEX 240
+#define SYS32_SCHED_SETAFFINITY 241
+#define SYS32_SCHED_GETAFFINITY 242
+#define SYS32_SET_THREAD_AREA 243
+#define SYS32_GET_THREAD_AREA 244
+#define SYS32_IO_SETUP 245
+#define SYS32_IO_DESTROY 246
+#define SYS32_IO_GETEVENTS 247
+#define SYS32_IO_SUBMIT 248
+#define SYS32_IO_CANCEL 249
+#define SYS32_FADVISE64 250
+#define SYS32_EXIT_GROUP 252
+#define SYS32_LOOKUP_DCOOKIE 253
+#define SYS32_EPOLL_CREATE 254
+#define SYS32_EPOLL_CTL 255
+#define SYS32_EPOLL_WAIT 256
+#define SYS32_REMAP_FILE_PAGES 257
+#define SYS32_SET_TID_ADDRESS 258
+#define SYS32_TIMER_CREATE 259
+#define SYS32_TIMER_SETTIME 260
+#define SYS32_TIMER_GETTIME 261
+#define SYS32_TIMER_GETOVERRUN 262
+#define SYS32_TIMER_DELETE 263
+#define SYS32_CLOCK_SETTIME 264
+#define SYS32_CLOCK_GETTIME 265
+#define SYS32_CLOCK_GETRES 266
+#define SYS32_CLOCK_NANOSLEEP 267
+#define SYS32_STATFS64 268
+#define SYS32_FSTATFS64 269
+#define SYS32_TGKILL 270
+#define SYS32_UTIMES 271
+#define SYS32_FADVISE64_64 272
+#define SYS32_VSERVER 273
+#define SYS32_MBIND 274
+#define SYS32_GET_MEMPOLICY 275
+#define SYS32_SET_MEMPOLICY 276
+#define SYS32_MQ_OPEN 277
+#define SYS32_MQ_UNLINK 278
+#define SYS32_MQ_TIMEDSEND 279
+#define SYS32_MQ_TIMEDRECEIVE 280
+#define SYS32_MQ_NOTIFY 281
+#define SYS32_MQ_GETSETATTR 282
+#define SYS32_KEXEC_LOAD 283
+#define SYS32_WAITID 284
+#define SYS32_SYS32_SETALTROOT 285
+#define SYS32_ADD_KEY 286
+#define SYS32_REQUEST_KEY 287
+#define SYS32_KEYCTL 288
+#define SYS32_IOPRIO_SET 289
+#define SYS32_IOPRIO_GET 290
+#define SYS32_INOTIFY_INIT 291
+#define SYS32_INOTIFY_ADD_WATCH 292
+#define SYS32_INOTIFY_RM_WATCH 293
+#define SYS32_MIGRATE_PAGES 294
+#define SYS32_OPENAT 295
+#define SYS32_MKDIRAT 296
+#define SYS32_MKNODAT 297
+#define SYS32_FCHOWNAT 298
+#define SYS32_FUTIMESAT 299
+#define SYS32_FSTATAT64 300
+#define SYS32_UNLINKAT 301
+#define SYS32_RENAMEAT 302
+#define SYS32_LINKAT 303
+#define SYS32_SYMLINKAT 304
+#define SYS32_READLINKAT 305
+#define SYS32_FCHMODAT 306
+#define SYS32_FACCESSAT 307
+#define SYS32_PSELECT6 308
+#define SYS32_PPOLL 309
+#define SYS32_UNSHARE 310
+#define SYS32_SET_ROBUST_LIST 311
+#define SYS32_GET_ROBUST_LIST 312
+#define SYS32_SPLICE 313
+#define SYS32_SYNC_FILE_RANGE 314
+#define SYS32_TEE 315
+#define SYS32_VMSPLICE 316
+#define SYS32_MOVE_PAGES 317
+#define SYS32_GETCPU 318
+#define SYS32_EPOLL_PWAIT 319
+#define SYS32_UTIMENSAT 320
+#define SYS32_SIGNALFD 321
+#define SYS32_TIMERFD_CREATE 322
+#define SYS32_EVENTFD 323
+#define SYS32_FALLOCATE 324
+#define SYS32_TIMERFD_SETTIME 325
+#define SYS32_TIMERFD_GETTIME 326
+#define SYS32_SIGNALFD4 327
+#define SYS32_EVENTFD2 328
+#define SYS32_EPOLL_CREATE1 329
+#define SYS32_DUP3 330
+#define SYS32_PIPE2 331
+#define SYS32_INOTIFY_INIT1 332
+#define SYS32_PREADV 333
+#define SYS32_PWRITEV 334
+#define SYS32_RT_TGSIGQUEUEINFO 335
+#define SYS32_PERF_EVENT_OPEN 336
+
+/* 64bit syscalls */
+#define SYS64_READ 0
+#define SYS64_WRITE 1
+#define SYS64_OPEN 2
+#define SYS64_CLOSE 3
+#define SYS64_STAT 4
+#define SYS64_FSTAT 5
+#define SYS64_LSTAT 6
+#define SYS64_POLL 7
+#define SYS64_LSEEK 8
+#define SYS64_MMAP 9
+#define SYS64_MPROTECT 10
+#define SYS64_MUNMAP 11
+#define SYS64_BRK 12
+#define SYS64_RT_SIGACTION 13
+#define SYS64_RT_SIGPROCMASK 14
+#define SYS64_RT_SIGRETURN 15
+#define SYS64_IOCTL 16
+#define SYS64_PREAD64 17
+#define SYS64_PWRITE64 18
+#define SYS64_READV 19
+#define SYS64_WRITEV 20
+#define SYS64_ACCESS 21
+#define SYS64_PIPE 22
+#define SYS64_SELECT 23
+#define SYS64_SCHED_YIELD 24
+#define SYS64_MREMAP 25
+#define SYS64_MSYNC 26
+#define SYS64_MINCORE 27
+#define SYS64_MADVISE 28
+#define SYS64_SHMGET 29
+#define SYS64_SHMAT 30
+#define SYS64_SHMCTL 31
+#define SYS64_DUP 32
+#define SYS64_DUP2 33
+#define SYS64_PAUSE 34
+#define SYS64_NANOSLEEP 35
+#define SYS64_GETITIMER 36
+#define SYS64_ALARM 37
+#define SYS64_SETITIMER 38
+#define SYS64_GETPID 39
+#define SYS64_SENDFILE 40
+#define SYS64_SOCKET 41
+#define SYS64_CONNECT 42
+#define SYS64_ACCEPT 43
+#define SYS64_SENDTO 44
+#define SYS64_RECVFROM 45
+#define SYS64_SENDMSG 46
+#define SYS64_RECVMSG 47
+#define SYS64_SHUTDOWN 48
+#define SYS64_BIND 49
+#define SYS64_LISTEN 50
+#define SYS64_GETSOCKNAME 51
+#define SYS64_GETPEERNAME 52
+#define SYS64_SOCKETPAIR 53
+#define SYS64_SETSOCKOPT 54
+#define SYS64_GETSOCKOPT 55
+#define SYS64_CLONE 56
+#define SYS64_FORK 57
+#define SYS64_VFORK 58
+#define SYS64_EXECVE 59
+#define SYS64_EXIT 60
+#define SYS64_WAIT4 61
+#define SYS64_KILL 62
+#define SYS64_UNAME 63
+#define SYS64_SEMGET 64
+#define SYS64_SEMOP 65
+#define SYS64_SEMCTL 66
+#define SYS64_SHMDT 67
+#define SYS64_MSGGET 68
+#define SYS64_MSGSND 69
+#define SYS64_MSGRCV 70
+#define SYS64_MSGCTL 71
+#define SYS64_FCNTL 72
+#define SYS64_FLOCK 73
+#define SYS64_FSYNC 74
+#define SYS64_FDATASYNC 75
+#define SYS64_TRUNCATE 76
+#define SYS64_FTRUNCATE 77
+#define SYS64_GETDENTS 78
+#define SYS64_GETCWD 79
+#define SYS64_CHDIR 80
+#define SYS64_FCHDIR 81
+#define SYS64_RENAME 82
+#define SYS64_MKDIR 83
+#define SYS64_RMDIR 84
+#define SYS64_CREAT 85
+#define SYS64_LINK 86
+#define SYS64_UNLINK 87
+#define SYS64_SYMLINK 88
+#define SYS64_READLINK 89
+#define SYS64_CHMOD 90
+#define SYS64_FCHMOD 91
+#define SYS64_CHOWN 92
+#define SYS64_FCHOWN 93
+#define SYS64_LCHOWN 94
+#define SYS64_UMASK 95
+#define SYS64_GETTIMEOFDAY 96
+#define SYS64_GETRLIMIT 97
+#define SYS64_GETRUSAGE 98
+#define SYS64_SYSINFO 99
+#define SYS64_TIMES 100
+#define SYS64_PTRACE 101
+#define SYS64_GETUID 102
+#define SYS64_SYSLOG 103
+#define SYS64_GETGID 104
+#define SYS64_SETUID 105
+#define SYS64_SETGID 106
+#define SYS64_GETEUID 107
+#define SYS64_GETEGID 108
+#define SYS64_SETPGID 109
+#define SYS64_GETPPID 110
+#define SYS64_GETPGRP 111
+#define SYS64_SETSID 112
+#define SYS64_SETREUID 113
+#define SYS64_SETREGID 114
+#define SYS64_GETGROUPS 115
+#define SYS64_SETGROUPS 116
+#define SYS64_SETRESUID 117
+#define SYS64_GETRESUID 118
+#define SYS64_SETRESGID 119
+#define SYS64_GETRESGID 120
+#define SYS64_GETPGID 121
+#define SYS64_SETFSUID 122
+#define SYS64_SETFSGID 123
+#define SYS64_GETSID 124
+#define SYS64_CAPGET 125
+#define SYS64_CAPSET 126
+#define SYS64_RT_SIGPENDING 127
+#define SYS64_RT_SIGTIMEDWAIT 128
+#define SYS64_RT_SIGQUEUEINFO 129
+#define SYS64_RT_SIGSUSPEND 130
+#define SYS64_SIGALTSTACK 131
+#define SYS64_UTIME 132
+#define SYS64_MKNOD 133
+#define SYS64_USELIB 134
+#define SYS64_PERSONALITY 135
+#define SYS64_USTAT 136
+#define SYS64_STATFS 137
+#define SYS64_FSTATFS 138
+#define SYS64_SYSFS 139
+#define SYS64_GETPRIORITY 140
+#define SYS64_SETPRIORITY 141
+#define SYS64_SCHED_SETPARAM 142
+#define SYS64_SCHED_GETPARAM 143
+#define SYS64_SCHED_SETSCHEDULER 144
+#define SYS64_SCHED_GETSCHEDULER 145
+#define SYS64_SCHED_GET_PRIORITY_MAX 146
+#define SYS64_SCHED_GET_PRIORITY_MIN 147
+#define SYS64_SCHED_RR_GET_INTERVAL 148
+#define SYS64_MLOCK 149
+#define SYS64_MUNLOCK 150
+#define SYS64_MLOCKALL 151
+#define SYS64_MUNLOCKALL 152
+#define SYS64_VHANGUP 153
+#define SYS64_MODIFY_LDT 154
+#define SYS64_PIVOT_ROOT 155
+#define SYS64__SYSCTL 156
+#define SYS64_PRCTL 157
+#define SYS64_ARCH_PRCTL 158
+#define SYS64_ADJTIMEX 159
+#define SYS64_SETRLIMIT 160
+#define SYS64_CHROOT 161
+#define SYS64_SYNC 162
+#define SYS64_ACCT 163
+#define SYS64_SETTIMEOFDAY 164
+#define SYS64_MOUNT 165
+#define SYS64_UMOUNT2 166
+#define SYS64_SWAPON 167
+#define SYS64_SWAPOFF 168
+#define SYS64_REBOOT 169
+#define SYS64_SETHOSTNAME 170
+#define SYS64_SETDOMAINNAME 171
+#define SYS64_IOPL 172
+#define SYS64_IOPERM 173
+#define SYS64_CREATE_MODULE 174
+#define SYS64_INIT_MODULE 175
+#define SYS64_DELETE_MODULE 176
+#define SYS64_GET_KERNEL_SYMS 177
+#define SYS64_QUERY_MODULE 178
+#define SYS64_QUOTACTL 179
+#define SYS64_NFSSERVCTL 180
+#define SYS64_GETPMSG 181
+#define SYS64_PUTPMSG 182
+#define SYS64_AFS_SYSCALL 183
+#define SYS64_TUXCALL 184
+#define SYS64_SECURITY 185
+#define SYS64_GETTID 186
+#define SYS64_READAHEAD 187
+#define SYS64_SETXATTR 188
+#define SYS64_LSETXATTR 189
+#define SYS64_FSETXATTR 190
+#define SYS64_GETXATTR 191
+#define SYS64_LGETXATTR 192
+#define SYS64_FGETXATTR 193
+#define SYS64_LISTXATTR 194
+#define SYS64_LLISTXATTR 195
+#define SYS64_FLISTXATTR 196
+#define SYS64_REMOVEXATTR 197
+#define SYS64_LREMOVEXATTR 198
+#define SYS64_FREMOVEXATTR 199
+#define SYS64_TKILL 200
+#define SYS64_TIME 201
+#define SYS64_FUTEX 202
+#define SYS64_SCHED_SETAFFINITY 203
+#define SYS64_SCHED_GETAFFINITY 204
+#define SYS64_SET_THREAD_AREA 205
+#define SYS64_IO_SETUP 206
+#define SYS64_IO_DESTROY 207
+#define SYS64_IO_GETEVENTS 208
+#define SYS64_IO_SUBMIT 209
+#define SYS64_IO_CANCEL 210
+#define SYS64_GET_THREAD_AREA 211
+#define SYS64_LOOKUP_DCOOKIE 212
+#define SYS64_EPOLL_CREATE 213
+#define SYS64_EPOLL_CTL_OLD 214
+#define SYS64_EPOLL_WAIT_OLD 215
+#define SYS64_REMAP_FILE_PAGES 216
+#define SYS64_GETDENTS64 217
+#define SYS64_SET_TID_ADDRESS 218
+#define SYS64_RESTART_SYSCALL 219
+#define SYS64_SEMTIMEDOP 220
+#define SYS64_FADVISE64 221
+#define SYS64_TIMER_CREATE 222
+#define SYS64_TIMER_SETTIME 223
+#define SYS64_TIMER_GETTIME 224
+#define SYS64_TIMER_GETOVERRUN 225
+#define SYS64_TIMER_DELETE 226
+#define SYS64_CLOCK_SETTIME 227
+#define SYS64_CLOCK_GETTIME 228
+#define SYS64_CLOCK_GETRES 229
+#define SYS64_CLOCK_NANOSLEEP 230
+#define SYS64_EXIT_GROUP 231
+#define SYS64_EPOLL_WAIT 232
+#define SYS64_EPOLL_CTL 233
+#define SYS64_TGKILL 234
+#define SYS64_UTIMES 235
+#define SYS64_VSERVER 236
+#define SYS64_MBIND 237
+#define SYS64_SET_MEMPOLICY 238
+#define SYS64_GET_MEMPOLICY 239
+#define SYS64_MQ_OPEN 240
+#define SYS64_MQ_UNLINK 241
+#define SYS64_MQ_TIMEDSEND 242
+#define SYS64_MQ_TIMEDRECEIVE 243
+#define SYS64_MQ_NOTIFY 244
+#define SYS64_MQ_GETSETATTR 245
+#define SYS64_KEXEC_LOAD 246
+#define SYS64_WAITID 247
+#define SYS64_ADD_KEY 248
+#define SYS64_REQUEST_KEY 249
+#define SYS64_KEYCTL 250
+#define SYS64_IOPRIO_SET 251
+#define SYS64_IOPRIO_GET 252
+#define SYS64_INOTIFY_INIT 253
+#define SYS64_INOTIFY_ADD_WATCH 254
+#define SYS64_INOTIFY_RM_WATCH 255
+#define SYS64_MIGRATE_PAGES 256
+#define SYS64_OPENAT 257
+#define SYS64_MKDIRAT 258
+#define SYS64_MKNODAT 259
+#define SYS64_FCHOWNAT 260
+#define SYS64_FUTIMESAT 261
+#define SYS64_NEWFSTATAT 262
+#define SYS64_UNLINKAT 263
+#define SYS64_RENAMEAT 264
+#define SYS64_LINKAT 265
+#define SYS64_SYMLINKAT 266
+#define SYS64_READLINKAT 267
+#define SYS64_FCHMODAT 268
+#define SYS64_FACCESSAT 269
+#define SYS64_PSELECT6 270
+#define SYS64_PPOLL 271
+#define SYS64_UNSHARE 272
+#define SYS64_SET_ROBUST_LIST 273
+#define SYS64_GET_ROBUST_LIST 274
+#define SYS64_SPLICE 275
+#define SYS64_TEE 276
+#define SYS64_SYNC_FILE_RANGE 277
+#define SYS64_VMSPLICE 278
+#define SYS64_MOVE_PAGES 279
+#define SYS64_UTIMENSAT 280
+#define SYS64_EPOLL_PWAIT 281
+#define SYS64_SIGNALFD 282
+#define SYS64_TIMERFD_CREATE 283
+#define SYS64_EVENTFD 284
+#define SYS64_FALLOCATE 285
+#define SYS64_TIMERFD_SETTIME 286
+#define SYS64_TIMERFD_GETTIME 287
+#define SYS64_ACCEPT4 288
+#define SYS64_SIGNALFD4 289
+#define SYS64_EVENTFD2 290
+#define SYS64_EPOLL_CREATE1 291
+#define SYS64_DUP3 292
+#define SYS64_PIPE2 293
+#define SYS64_INOTIFY_INIT1 294
+#define SYS64_PREADV 295
+#define SYS64_PWRITEV 296
+#define SYS64_RT_TGSIGQUEUEINFO 297
+#define SYS64_PERF_EVENT_OPEN 298
+
+
+#endif
--- /dev/null
+menu GEARS
+
+config GEARS
+ bool "Enable GEARS in Palacios"
+ default n
+ help
+ This is the Guest Examination and Revision Services, an extension used
+ to modify guest code and implement guest-context VMM services in Palacios
+
+config EXT_SW_INTERRUPTS
+ bool "Enable interception and hooking of software interrupts"
+ depends on GEARS
+ default n
+ help
+ This feature will cause the VMM to intercept the execution
+ of software interrupts (i.e. the INTn instruction) and enable
+ any INT vector to be hooked. Extension name is "swintr_intercept"
+
+config DEBUG_EXT_SW_INTERRUPTS
+ bool "Enable debugging of software interrupt interception code"
+ depends on GEARS
+ depends on EXT_SW_INTERRUPTS
+ default n
+ help
+ This will enable useful debugging printouts for software
+ intercept code
+
+config EXT_SWINTR_PASSTHROUGH
+ bool "Hook all unhandled sofware interrupts for passthrough"
+ depends on GEARS
+ depends on EXT_SW_INTERRUPTS
+ default n
+ help
+ If enabled, this will cause all software interrupts
+ (INT instruction vectors) to be hooked for passthrough.
+ May reduce performance but useful for debugging.
+
+config EXT_SYSCALL_HIJACK
+ bool "Enable System Call Hijacking"
+ default n
+ depends on GEARS
+ depends on EXT_SW_INTERRUPTS
+ help
+ Enable the VMM to hijack system calls executed by the guest.
+ If enabled, the VMM will hook execution of INT 80
+
+
+config EXT_SELECTIVE_SYSCALL_EXIT
+ bool "Enable dynamic selective exiting of system calls"
+ default n
+ depends on GEARS
+ depends on EXT_SYSCALL_HIJACK
+ help
+ If enabled, this option will allow the VMM to selectively
+ enable and disable exiting on specific system calls.
+
+config DEBUG_EXT_SYSCALL_HIJACK
+ bool "Enable Syscall Hijack Debug in Palacios"
+ depends on GEARS
+ depends on EXT_SYSCALL_HIJACK
+ default n
+ help
+ Enable Debugging printouts for syscall hijacking code
+ in Palacios
+
+
+config EXT_SYSCALL_PASSTHROUGH
+ bool "Hook all unhandled system calls for passthrough"
+ depends on GEARS
+ depends on EXT_SYSCALL_HIJACK
+ default n
+ help
+ If enabled, this option will cause all system calls
+ that are not explicitly hooked to be hooked for
+ passthrough. This is useful for debugging.
+
+config EXT_EXECVE_HOOK
+ bool "Hook calls to execve"
+ depends on GEARS
+ depends on EXT_SYSCALL_HIJACK
+ default n
+ help
+ This option will cause the interception of all calls
+ to the execve system call
+
+config EXT_ENV_INJECT
+ bool "Enable environment variable injection"
+ depends on GEARS
+ depends on EXT_EXECVE_HOOK
+ default n
+ help
+ Enables development extension for overriding env vars
+ for certain executables
+
+config EXT_CODE_INJECT
+ bool "Allow code injection"
+ depends on GEARS
+ depends on EXT_SYSCALL_HIJACK
+ default n
+ help
+ This option will allow code to be injected and run in the
+ guest context
+
+endmenu
--- /dev/null
+obj-$(V3_CONFIG_EXT_SW_INTERRUPTS) += ext_sw_intr.o
+obj-$(V3_CONFIG_EXT_SYSCALL_HIJACK) += ext_syscall_hijack.o
+obj-$(V3_CONFIG_EXT_EXECVE_HOOK) += ext_execve_hook.o
+obj-$(V3_CONFIG_EXT_EXECVE_HOOK) += ext_process_environment.o
+obj-$(V3_CONFIG_EXT_CODE_INJECT) += ext_code_inject.o
+obj-$(V3_CONFIG_EXT_ENV_INJECT) += ext_env_inject.o
+
--- /dev/null
+/* This file defines standard ELF types, structures, and macros.
+ Copyright (C) 1995-2003,2004,2005,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _ELF_H_
+#define _ELF_H_
+
+
+#include <palacios/vmm_types.h>
+
+#define __ELF_SIZE 32
+
+#define ElfW(type) _ElfW (Elf, __ELF_SIZE, type)
+#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
+#define _ElfW_1(e,w,t) e##w##t
+
+/* Standard ELF types. */
+
+/* Type for a 16-bit quantity. */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities. */
+typedef uint32_t Elf32_Word;
+typedef sint32_t Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef sint32_t Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities. */
+typedef uint64_t Elf32_Xword;
+typedef sint64_t Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef sint64_t Elf64_Sxword;
+
+/* Type of addresses. */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets. */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities. */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type for version symbol information. */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+
+/* The ELF file header. This appears at the start of every ELF file. */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf64_Half e_type; /* Object file type */
+ Elf64_Half e_machine; /* Architecture */
+ Elf64_Word e_version; /* Object file version */
+ Elf64_Addr e_entry; /* Entry point virtual address */
+ Elf64_Off e_phoff; /* Program header table file offset */
+ Elf64_Off e_shoff; /* Section header table file offset */
+ Elf64_Word e_flags; /* Processor-specific flags */
+ Elf64_Half e_ehsize; /* ELF header size in bytes */
+ Elf64_Half e_phentsize; /* Program header table entry size */
+ Elf64_Half e_phnum; /* Program header table entry count */
+ Elf64_Half e_shentsize; /* Section header table entry size */
+ Elf64_Half e_shnum; /* Section header table entry count */
+ Elf64_Half e_shstrndx; /* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array. The EI_* macros are indices into the
+ array. The macros under each EI_* macro are the values the byte
+ may have. */
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7f /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word. */
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+#define ELFCLASSNUM 3
+
+#define EI_DATA 5 /* Data encoding byte index */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+#define ELFDATANUM 3
+
+#define EI_VERSION 6 /* File version byte index */
+ /* Value must be EV_CURRENT */
+
+#define EI_OSABI 7 /* OS ABI identification */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_SYSV 0 /* Alias. */
+#define ELFOSABI_HPUX 1 /* HP-UX */
+#define ELFOSABI_NETBSD 2 /* NetBSD. */
+#define ELFOSABI_LINUX 3 /* Linux. */
+#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
+#define ELFOSABI_AIX 7 /* IBM AIX. */
+#define ELFOSABI_IRIX 8 /* SGI Irix. */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
+#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+#define EI_ABIVERSION 8 /* ABI version */
+
+#define EI_PAD 9 /* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type). */
+
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_NUM 5 /* Number of defined types */
+#define ET_LOOS 0xfe00 /* OS-specific range start */
+#define ET_HIOS 0xfeff /* OS-specific range end */
+#define ET_LOPROC 0xff00 /* Processor-specific range start */
+#define ET_HIPROC 0xffff /* Processor-specific range end */
+
+/* Legal values for e_machine (architecture). */
+
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 big-endian */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
+
+#define EM_PARISC 15 /* HPPA */
+#define EM_VPP500 17 /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+#define EM_960 19 /* Intel 80960 */
+#define EM_PPC 20 /* PowerPC */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_S390 22 /* IBM S390 */
+
+#define EM_V800 36 /* NEC V800 series */
+#define EM_FR20 37 /* Fujitsu FR20 */
+#define EM_RH32 38 /* TRW RH-32 */
+#define EM_RCE 39 /* Motorola RCE */
+#define EM_ARM 40 /* ARM */
+#define EM_FAKE_ALPHA 41 /* Digital Alpha */
+#define EM_SH 42 /* Hitachi SH */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_TRICORE 44 /* Siemens Tricore */
+#define EM_ARC 45 /* Argonaut RISC Core */
+#define EM_H8_300 46 /* Hitachi H8/300 */
+#define EM_H8_300H 47 /* Hitachi H8/300H */
+#define EM_H8S 48 /* Hitachi H8S */
+#define EM_H8_500 49 /* Hitachi H8/500 */
+#define EM_IA_64 50 /* Intel Merced */
+#define EM_MIPS_X 51 /* Stanford MIPS-X */
+#define EM_COLDFIRE 52 /* Motorola Coldfire */
+#define EM_68HC12 53 /* Motorola M68HC12 */
+#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP 55 /* Siemens PCP */
+#define EM_NCPU 56 /* Sony nCPU embeeded RISC */
+#define EM_NDR1 57 /* Denso NDR1 microprocessor */
+#define EM_STARCORE 58 /* Motorola Start*Core processor */
+#define EM_ME16 59 /* Toyota ME16 processor */
+#define EM_ST100 60 /* STMicroelectronic ST100 processor */
+#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64 62 /* AMD x86-64 architecture */
+#define EM_PDSP 63 /* Sony DSP Processor */
+
+#define EM_FX66 66 /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
+#define EM_SVX 73 /* Silicon Graphics SVx */
+#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX 75 /* Digital VAX */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY 81 /* Harvard University machine-independent object files */
+#define EM_PRISM 82 /* SiTera Prism */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30 84 /* Fujitsu FR30 */
+#define EM_D10V 85 /* Mitsubishi D10V */
+#define EM_D30V 86 /* Mitsubishi D30V */
+#define EM_V850 87 /* NEC v850 */
+#define EM_M32R 88 /* Mitsubishi M32R */
+#define EM_MN10300 89 /* Matsushita MN10300 */
+#define EM_MN10200 90 /* Matsushita MN10200 */
+#define EM_PJ 91 /* picoJava */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
+#define EM_NUM 95
+
+/* If it is necessary to assign new unofficial EM_* values, please
+ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+ chances of collision with official or non-GNU unofficial values. */
+
+#define EM_ALPHA 0x9026
+
+/* Legal values for e_version (version). */
+
+#define EV_NONE 0 /* Invalid ELF version */
+#define EV_CURRENT 1 /* Current version */
+#define EV_NUM 2
+
+/* Section header. */
+
+typedef struct
+{
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+ Elf64_Word sh_name; /* Section name (string tbl index) */
+ Elf64_Word sh_type; /* Section type */
+ Elf64_Xword sh_flags; /* Section flags */
+ Elf64_Addr sh_addr; /* Section virtual addr at execution */
+ Elf64_Off sh_offset; /* Section file offset */
+ Elf64_Xword sh_size; /* Section size in bytes */
+ Elf64_Word sh_link; /* Link to another section */
+ Elf64_Word sh_info; /* Additional section information */
+ Elf64_Xword sh_addralign; /* Section alignment */
+ Elf64_Xword sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices. */
+
+#define SHN_UNDEF 0 /* Undefined section */
+#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
+#define SHN_LOPROC 0xff00 /* Start of processor-specific */
+#define SHN_BEFORE 0xff00 /* Order section before all others
+ (Solaris). */
+#define SHN_AFTER 0xff01 /* Order section after all others
+ (Solaris). */
+#define SHN_HIPROC 0xff1f /* End of processor-specific */
+#define SHN_LOOS 0xff20 /* Start of OS-specific */
+#define SHN_HIOS 0xff3f /* End of OS-specific */
+#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
+#define SHN_COMMON 0xfff2 /* Associated symbol is common */
+#define SHN_XINDEX 0xffff /* Index is in extra table. */
+#define SHN_HIRESERVE 0xffff /* End of reserved indices */
+
+/* Legal values for sh_type (section type). */
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program data */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Dynamic linking information */
+#define SHT_NOTE 7 /* Notes */
+#define SHT_NOBITS 8 /* Program space with no data (bss) */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY 14 /* Array of constructors */
+#define SHT_FINI_ARRAY 15 /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
+#define SHT_GROUP 17 /* Section group */
+#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
+#define SHT_NUM 19 /* Number of defined types. */
+#define SHT_LOOS 0x60000000 /* Start OS-specific. */
+#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
+#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
+#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
+#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
+#define SHT_SUNW_move 0x6ffffffa
+#define SHT_SUNW_COMDAT 0x6ffffffb
+#define SHT_SUNW_syminfo 0x6ffffffc
+#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
+#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
+#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
+#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
+#define SHT_HIOS 0x6fffffff /* End OS-specific type */
+#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
+#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
+#define SHT_LOUSER 0x80000000 /* Start of application-specific */
+#define SHT_HIUSER 0x8fffffff /* End of application-specific */
+
+/* Legal values for sh_flags (section flags). */
+
+#define SHF_WRITE (1 << 0) /* Writable */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable */
+#define SHF_MERGE (1 << 4) /* Might be merged */
+#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
+#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling
+ required */
+#define SHF_GROUP (1 << 9) /* Section is member of a group. */
+#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
+#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
+#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
+#define SHF_ORDERED (1 << 30) /* Special ordering requirement
+ (Solaris). */
+#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
+ referenced or allocated (Solaris).*/
+
+/* Section group handling. */
+#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
+
+/* Symbol table entry. */
+
+typedef struct
+{
+ Elf32_Word st_name; /* Symbol name (string tbl index) */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf32_Section st_shndx; /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+ Elf64_Word st_name; /* Symbol name (string tbl index) */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf64_Section st_shndx; /* Section index */
+ Elf64_Addr st_value; /* Symbol value */
+ Elf64_Xword st_size; /* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+ every dynamic symbol. */
+
+typedef struct
+{
+ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf32_Half si_flags; /* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
+ Elf64_Half si_flags; /* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto. */
+#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
+#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags. */
+#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
+ loaded */
+/* Syminfo version values. */
+#define SYMINFO_NONE 0
+#define SYMINFO_CURRENT 1
+#define SYMINFO_NUM 2
+
+
+/* How to extract and insert information held in the st_info field. */
+
+#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val) ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
+#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding). */
+
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* Weak symbol */
+#define STB_NUM 3 /* Number of defined types. */
+#define STB_LOOS 10 /* Start of OS-specific */
+#define STB_HIOS 12 /* End of OS-specific */
+#define STB_LOPROC 13 /* Start of processor-specific */
+#define STB_HIPROC 15 /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type). */
+
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol's name is file name */
+#define STT_COMMON 5 /* Symbol is a common data object */
+#define STT_TLS 6 /* Symbol is thread-local data object*/
+#define STT_NUM 7 /* Number of defined types. */
+#define STT_LOOS 10 /* Start of OS-specific */
+#define STT_HIOS 12 /* End of OS-specific */
+#define STT_LOPROC 13 /* Start of processor-specific */
+#define STT_HIPROC 15 /* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+ of a symbol hash table section. This special index value indicates
+ the end of a chain, meaning no further symbols are found in that bucket. */
+
+#define STN_UNDEF 0 /* End of a chain. */
+
+
+/* How to extract and insert information held in the st_other field. */
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+
+/* For ELF64 the definitions are the same. */
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field. */
+#define STV_DEFAULT 0 /* Default symbol visibility rules */
+#define STV_INTERNAL 1 /* Processor specific hidden class */
+#define STV_HIDDEN 2 /* Sym unavailable in other modules */
+#define STV_PROTECTED 3 /* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+ Elf64_Rela structures, so we'll leave them out until Novell (or
+ whoever) gets their act together. */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA). */
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+ Elf32_Sword r_addend; /* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Address */
+ Elf64_Xword r_info; /* Relocation type and symbol index */
+ Elf64_Sxword r_addend; /* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field. */
+
+#define ELF32_R_SYM(val) ((val) >> 8)
+#define ELF32_R_TYPE(val) ((val) & 0xff)
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header. */
+
+typedef struct
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+ Elf64_Word p_type; /* Segment type */
+ Elf64_Word p_flags; /* Segment flags */
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Xword p_filesz; /* Segment size in file */
+ Elf64_Xword p_memsz; /* Segment size in memory */
+ Elf64_Xword p_align; /* Segment alignment */
+} Elf64_Phdr;
+
+/* Legal values for p_type (segment type). */
+
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_TLS 7 /* Thread-local storage segment */
+#define PT_NUM 8 /* Number of defined types */
+#define PT_LOOS 0x60000000 /* Start of OS-specific */
+#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
+#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
+#define PT_LOSUNW 0x6ffffffa
+#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
+#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
+#define PT_HISUNW 0x6fffffff
+#define PT_HIOS 0x6fffffff /* End of OS-specific */
+#define PT_LOPROC 0x70000000 /* Start of processor-specific */
+#define PT_HIPROC 0x7fffffff /* End of processor-specific */
+
+/* Legal values for p_flags (segment flags). */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKOS 0x0ff00000 /* OS-specific */
+#define PF_MASKPROC 0xf0000000 /* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+#define NT_PRXREG 4 /* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT 4 /* Contains copy of task structure */
+#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV 6 /* Contains copy of auxv array */
+#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
+#define NT_ASRS 8 /* Contains copy of asrset struct */
+#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
+#define NT_PSINFO 13 /* Contains copy of psinfo struct */
+#define NT_PRCRED 14 /* Contains copy of prcred struct */
+#define NT_UTSNAME 15 /* Contains copy of utsname struct */
+#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/
+
+/* Legal values for the note segment descriptor types for object files. */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+
+/* Dynamic section entry. */
+
+typedef struct
+{
+ Elf32_Sword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf32_Word d_val; /* Integer value */
+ Elf32_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Dynamic entry type */
+ union
+ {
+ Elf64_Xword d_val; /* Integer value */
+ Elf64_Addr d_ptr; /* Address value */
+ } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type). */
+
+#define DT_NULL 0 /* Marks end of dynamic section */
+#define DT_NEEDED 1 /* Name of needed library */
+#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
+#define DT_PLTGOT 3 /* Processor defined value */
+#define DT_HASH 4 /* Address of symbol hash table */
+#define DT_STRTAB 5 /* Address of string table */
+#define DT_SYMTAB 6 /* Address of symbol table */
+#define DT_RELA 7 /* Address of Rela relocs */
+#define DT_RELASZ 8 /* Total size of Rela relocs */
+#define DT_RELAENT 9 /* Size of one Rela reloc */
+#define DT_STRSZ 10 /* Size of string table */
+#define DT_SYMENT 11 /* Size of one symbol table entry */
+#define DT_INIT 12 /* Address of init function */
+#define DT_FINI 13 /* Address of termination function */
+#define DT_SONAME 14 /* Name of shared object */
+#define DT_RPATH 15 /* Library search path (deprecated) */
+#define DT_SYMBOLIC 16 /* Start symbol search here */
+#define DT_REL 17 /* Address of Rel relocs */
+#define DT_RELSZ 18 /* Total size of Rel relocs */
+#define DT_RELENT 19 /* Size of one Rel reloc */
+#define DT_PLTREL 20 /* Type of reloc in PLT */
+#define DT_DEBUG 21 /* For debugging; unspecified */
+#define DT_TEXTREL 22 /* Reloc might modify .text */
+#define DT_JMPREL 23 /* Address of PLT relocs */
+#define DT_BIND_NOW 24 /* Process relocations of object */
+#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
+#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH 29 /* Library search path */
+#define DT_FLAGS 30 /* Flags for the object being loaded */
+#define DT_ENCODING 32 /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
+#define DT_NUM 34 /* Number used */
+#define DT_LOOS 0x6000000d /* Start of OS-specific */
+#define DT_HIOS 0x6ffff000 /* End of OS-specific */
+#define DT_LOPROC 0x70000000 /* Start of processor-specific */
+#define DT_HIPROC 0x7fffffff /* End of processor-specific */
+#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
+ approach. */
+#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
+#define DT_CHECKSUM 0x6ffffdf8
+#define DT_PLTPADSZ 0x6ffffdf9
+#define DT_MOVEENT 0x6ffffdfa
+#define DT_MOVESZ 0x6ffffdfb
+#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
+#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
+ the following DT_* entry. */
+#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
+#define DT_VALRNGHI 0x6ffffdff
+#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+ Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+ If any adjustment is made to the ELF object after it has been
+ built these entries will need to be adjusted. */
+#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */
+#define DT_TLSDESC_PLT 0x6ffffef6
+#define DT_TLSDESC_GOT 0x6ffffef7
+#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
+#define DT_CONFIG 0x6ffffefa /* Configuration information. */
+#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */
+#define DT_AUDIT 0x6ffffefc /* Object auditing. */
+#define DT_PLTPAD 0x6ffffefd /* PLT padding. */
+#define DT_MOVETAB 0x6ffffefe /* Move table. */
+#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
+#define DT_ADDRRNGHI 0x6ffffeff
+#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
+#define DT_ADDRNUM 11
+
+/* The versioning entry types. The next are defined as part of the
+ GNU extension. */
+#define DT_VERSYM 0x6ffffff0
+
+#define DT_RELACOUNT 0x6ffffff9
+#define DT_RELCOUNT 0x6ffffffa
+
+/* These were chosen by Sun. */
+#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
+#define DT_VERDEF 0x6ffffffc /* Address of version definition
+ table */
+#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
+#define DT_VERNEED 0x6ffffffe /* Address of table with needed
+ versions */
+#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+ range. Be compatible. */
+#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
+#define DT_FILTER 0x7fffffff /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM 3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry. */
+#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */
+#define DF_TEXTREL 0x00000004 /* Object contains text relocations */
+#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */
+#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+ entry in the dynamic section. */
+#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
+#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
+#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
+#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
+#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
+#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
+#define DF_1_TRANS 0x00000200
+#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */
+#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */
+#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */
+#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/
+#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */
+#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */
+#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */
+
+/* Flags for the feature selection in DT_FEATURE_1. */
+#define DTF_1_PARINIT 0x00000001
+#define DTF_1_CONFEXP 0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
+#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
+#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not
+ generally available. */
+
+/* Version definition sections. */
+
+typedef struct
+{
+ Elf32_Half vd_version; /* Version revision */
+ Elf32_Half vd_flags; /* Version information */
+ Elf32_Half vd_ndx; /* Version Index */
+ Elf32_Half vd_cnt; /* Number of associated aux entries */
+ Elf32_Word vd_hash; /* Version name hash value */
+ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf32_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+ Elf64_Half vd_version; /* Version revision */
+ Elf64_Half vd_flags; /* Version information */
+ Elf64_Half vd_ndx; /* Version Index */
+ Elf64_Half vd_cnt; /* Number of associated aux entries */
+ Elf64_Word vd_hash; /* Version name hash value */
+ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
+ Elf64_Word vd_next; /* Offset in bytes to next verdef
+ entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision). */
+#define VER_DEF_NONE 0 /* No version */
+#define VER_DEF_CURRENT 1 /* Current version */
+#define VER_DEF_NUM 2 /* Given version number */
+
+/* Legal values for vd_flags (version information flags). */
+#define VER_FLG_BASE 0x1 /* Version definition of file itself */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+/* Versym symbol index values. */
+#define VER_NDX_LOCAL 0 /* Symbol is local. */
+#define VER_NDX_GLOBAL 1 /* Symbol is global. */
+#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */
+#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */
+
+/* Auxialiary version information. */
+
+typedef struct
+{
+ Elf32_Word vda_name; /* Version or dependency names */
+ Elf32_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+ Elf64_Word vda_name; /* Version or dependency names */
+ Elf64_Word vda_next; /* Offset in bytes to next verdaux
+ entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section. */
+
+typedef struct
+{
+ Elf32_Half vn_version; /* Version of structure */
+ Elf32_Half vn_cnt; /* Number of associated aux entries */
+ Elf32_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf32_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+ Elf64_Half vn_version; /* Version of structure */
+ Elf64_Half vn_cnt; /* Number of associated aux entries */
+ Elf64_Word vn_file; /* Offset of filename for this
+ dependency */
+ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
+ Elf64_Word vn_next; /* Offset in bytes to next verneed
+ entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision). */
+#define VER_NEED_NONE 0 /* No version */
+#define VER_NEED_CURRENT 1 /* Current version */
+#define VER_NEED_NUM 2 /* Given version number */
+
+/* Auxiliary needed version information. */
+
+typedef struct
+{
+ Elf32_Word vna_hash; /* Hash value of dependency name */
+ Elf32_Half vna_flags; /* Dependency specific information */
+ Elf32_Half vna_other; /* Unused */
+ Elf32_Word vna_name; /* Dependency name string offset */
+ Elf32_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+ Elf64_Word vna_hash; /* Hash value of dependency name */
+ Elf64_Half vna_flags; /* Dependency specific information */
+ Elf64_Half vna_other; /* Unused */
+ Elf64_Word vna_name; /* Dependency name string offset */
+ Elf64_Word vna_next; /* Offset in bytes to next vernaux
+ entry */
+} Elf64_Vernaux;
+
+
+/* Legal values for vna_flags. */
+#define VER_FLG_WEAK 0x2 /* Weak version identifier */
+
+
+/* Auxiliary vector. */
+
+/* This vector is normally only used by the program interpreter. The
+ usual definition in an ABI supplement uses the name auxv_t. The
+ vector is not usually defined in a standard <elf.h> file, but it
+ can't hurt. We rename it to avoid conflicts. The sizes of these
+ types are an arrangement between the exec server and the program
+ interpreter, so we don't fully specify them here. */
+
+typedef struct
+{
+ uint32_t a_type; /* Entry type */
+ union
+ {
+ uint32_t a_val; /* Integer value */
+ /* We use to have pointer elements added here. We cannot do that,
+ though, since it does not work when using 32-bit definitions
+ on 64-bit platforms and vice versa. */
+ } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+ uint64_t a_type; /* Entry type */
+ union
+ {
+ uint64_t a_val; /* Integer value */
+ /* We use to have pointer elements added here. We cannot do that,
+ though, since it does not work when using 32-bit definitions
+ on 64-bit platforms and vice versa. */
+ } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type). */
+
+#define AT_NULL 0 /* End of vector */
+#define AT_IGNORE 1 /* Entry should be ignored */
+#define AT_EXECFD 2 /* File descriptor of program */
+#define AT_PHDR 3 /* Program headers for program */
+#define AT_PHENT 4 /* Size of program header entry */
+#define AT_PHNUM 5 /* Number of program headers */
+#define AT_PAGESZ 6 /* System page size */
+#define AT_BASE 7 /* Base address of interpreter */
+#define AT_FLAGS 8 /* Flags */
+#define AT_ENTRY 9 /* Entry point of program */
+#define AT_NOTELF 10 /* Program is not ELF */
+#define AT_UID 11 /* Real uid */
+#define AT_EUID 12 /* Effective uid */
+#define AT_GID 13 /* Real gid */
+#define AT_EGID 14 /* Effective gid */
+#define AT_CLKTCK 17 /* Frequency of times() */
+
+/* Some more special a_type values describing the hardware. */
+#define AT_PLATFORM 15 /* String identifying platform. */
+#define AT_HWCAP 16 /* Machine dependent hints about
+ processor capabilities. */
+
+/* This entry gives some information about the FPU initialization
+ performed by the kernel. */
+#define AT_FPUCW 18 /* Used FPU control word. */
+
+/* Cache block sizes. */
+#define AT_DCACHEBSIZE 19 /* Data cache block size. */
+#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */
+#define AT_UCACHEBSIZE 21 /* Unified cache block size. */
+
+/* A special ignored value for PPC, used by the kernel to control the
+ interpretation of the AUXV. Must be > 16. */
+#define AT_IGNOREPPC 22 /* Entry should be ignored. */
+
+#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
+
+/* Pointer to the global system page used for system calls and other
+ nice things. */
+#define AT_SYSINFO 32
+#define AT_SYSINFO_EHDR 33
+
+/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
+ log2 of line size; mask those to get cache size. */
+#define AT_L1I_CACHESHAPE 34
+#define AT_L1D_CACHESHAPE 35
+#define AT_L2_CACHESHAPE 36
+#define AT_L3_CACHESHAPE 37
+
+/* Note section contents. Each entry in the note section begins with
+ a header of a fixed form. */
+
+typedef struct
+{
+ Elf32_Word n_namesz; /* Length of the note's name. */
+ Elf32_Word n_descsz; /* Length of the note's descriptor. */
+ Elf32_Word n_type; /* Type of the note. */
+} Elf32_Nhdr;
+
+typedef struct
+{
+ Elf64_Word n_namesz; /* Length of the note's name. */
+ Elf64_Word n_descsz; /* Length of the note's descriptor. */
+ Elf64_Word n_type; /* Type of the note. */
+} Elf64_Nhdr;
+
+/* Known names of notes. */
+
+/* Solaris entries in the note section have this name. */
+#define ELF_NOTE_SOLARIS "SUNW Solaris"
+
+/* Note entries for GNU systems have this name. */
+#define ELF_NOTE_GNU "GNU"
+
+
+/* Defined types of notes for Solaris. */
+
+/* Value of descriptor (one word) is desired pagesize for the binary. */
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+/* Defined note types for GNU systems. */
+
+/* ABI information. The descriptor consists of words:
+ word 0: OS descriptor
+ word 1: major version of the ABI
+ word 2: minor version of the ABI
+ word 3: subminor version of the ABI
+*/
+#define ELF_NOTE_ABI 1
+
+/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI
+ note section entry. */
+#define ELF_NOTE_OS_LINUX 0
+#define ELF_NOTE_OS_GNU 1
+#define ELF_NOTE_OS_SOLARIS2 2
+#define ELF_NOTE_OS_FREEBSD 3
+
+
+/* Move records. */
+typedef struct
+{
+ Elf32_Xword m_value; /* Symbol value. */
+ Elf32_Word m_info; /* Size and index. */
+ Elf32_Word m_poffset; /* Symbol offset. */
+ Elf32_Half m_repeat; /* Repeat count. */
+ Elf32_Half m_stride; /* Stride info. */
+} Elf32_Move;
+
+typedef struct
+{
+ Elf64_Xword m_value; /* Symbol value. */
+ Elf64_Xword m_info; /* Size and index. */
+ Elf64_Xword m_poffset; /* Symbol offset. */
+ Elf64_Half m_repeat; /* Repeat count. */
+ Elf64_Half m_stride; /* Stride info. */
+} Elf64_Move;
+
+/* Macro to construct move records. */
+#define ELF32_M_SYM(info) ((info) >> 8)
+#define ELF32_M_SIZE(info) ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info) ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info) ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size)
+
+
+/* Intel 80386 specific definitions. */
+
+/* i386 relocs. */
+
+#define R_386_NONE 0 /* No reloc */
+#define R_386_32 1 /* Direct 32 bit */
+#define R_386_PC32 2 /* PC relative 32 bit */
+#define R_386_GOT32 3 /* 32 bit GOT entry */
+#define R_386_PLT32 4 /* 32 bit PLT address */
+#define R_386_COPY 5 /* Copy symbol at runtime */
+#define R_386_GLOB_DAT 6 /* Create GOT entry */
+#define R_386_JMP_SLOT 7 /* Create PLT entry */
+#define R_386_RELATIVE 8 /* Adjust by program base */
+#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
+#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT 11
+#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
+#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
+ block offset */
+#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block
+ offset */
+#define R_386_TLS_LE 17 /* Offset relative to static TLS
+ block */
+#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of
+ general dynamic thread local data */
+#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of
+ local dynamic thread local data
+ in LE code */
+#define R_386_16 20
+#define R_386_PC16 21
+#define R_386_8 22
+#define R_386_PC8 23
+#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic
+ thread local data */
+#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL 26 /* Relocation for call to
+ __tls_get_addr() */
+#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic
+ thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30 /* Relocation for call to
+ __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */
+#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS
+ block offset */
+#define R_386_TLS_LE_32 34 /* Negated offset relative to static
+ TLS block */
+#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
+#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
+/* Keep this the last entry. */
+#define R_386_NUM 38
+
+
+/* Legal values for l_flags. */
+
+#define LL_NONE 0
+#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
+#define LL_REQUIRE_MINOR (1 << 2)
+#define LL_EXPORTS (1 << 3)
+#define LL_DELAY_LOAD (1 << 4)
+#define LL_DELTA (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT. */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+
+/* AMD x86-64 relocations. */
+#define R_X86_64_NONE 0 /* No reloc */
+#define R_X86_64_64 1 /* Direct 64 bit */
+#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
+#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
+#define R_X86_64_PLT32 4 /* 32 bit PLT address */
+#define R_X86_64_COPY 5 /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
+ offset to GOT */
+#define R_X86_64_32 10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
+#define R_X86_64_16 12 /* Direct 16 bit zero extended */
+#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
+#define R_X86_64_8 14 /* Direct 8 bit sign extended */
+#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */
+#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset
+ to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset
+ to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset
+ to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */
+
+#define R_X86_64_NUM 24
+
+struct link_map {
+
+ Elf64_Addr l_addr;
+ char *l_name;
+ Elf64_Dyn *l_ld;
+ struct link_map *l_next, *l_prev;
+};
+
+#endif /* elf.h */
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#include <palacios/vmm.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_intr.h>
+#include <palacios/vmm_extensions.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vmm_types.h>
+#include <palacios/vmm_hypercall.h>
+#include <palacios/vmcb.h>
+
+#include <gears/code_inject.h>
+#include <gears/execve_hook.h>
+#include <gears/sw_intr.h>
+
+#include "elf.h"
+
+struct v3_code_injects code_injects;
+
+static char mmap_code[] = "\xb8\xc0\x00\x00\x00\x31\xdb\xb9"
+ "\x00\x00\x10\x00\xba\x01\x00\x00"
+ "\x00\xbd\x02\x00\x00\x00\x09\xea"
+ "\xbd\x04\x00\x00\x00\x09\xea\xbe"
+ "\x02\x00\x00\x00\xbd\x20\x00\x00"
+ "\x00\x09\xee\xbf\xff\xff\xff\xff"
+ "\x31\xed\xcd\x80\x89\xc3\xb9\x00"
+ "\x00\x10\x00\xc7\x00\xef\xbe\xad"
+ "\xde\x05\x00\x10\x00\x00\x81\xe9"
+ "\x00\x10\x00\x00\x75\xed\xb8\x00"
+ "\xf0\x00\x00\x0f\x01\xd9";
+
+static char munmap_code[] = "\xb8\x5b\x00\x00\x00\xb9\x00\x00"
+ "\x10\x00\xcd\x80\x89\xc3\xb8\x03"
+ "\xf0\x00\x00\x0f\x01\xd9";
+
+static char vmmcall_code[] = "\x48\xc7\xc0\x02\xf0\x00\x00\x0f"
+ "\x01\xd9";
+
+static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
+
+
+/*
+ * the presence of this is kind of a hack, and exists because
+ * when one of the below hypercall handlers is invoked, we don't
+ * have an elegant way of deciding which inject queue (normal or exec-hooked)
+ * to pull the first element from, so we have this place marker
+ *
+ * This could be ugly with more than one core...
+ */
+static struct v3_code_inject_info * current_inject;
+
+
+static int free_code_inject (struct v3_vm_info * vm, struct v3_code_inject_info * inject) {
+ list_del(&(inject->inject_node));
+ V3_Free(inject);
+ return 0;
+}
+
+
+/*
+ * helper function to save a chunk of code in an inject object's state and
+ * overwrite it with something else (mostly for injecting hypercalls)
+ */
+static int v3_plant_code (struct guest_info * core, struct v3_code_inject_info * inject,
+ char * hva, char * code, uint_t size) {
+ int i;
+
+ // first back up old code
+ inject->old_code = (char*)V3_Malloc(size);
+ for (i = 0; i < size; i++)
+ inject->old_code[i] = *(hva + i);
+
+ // overwrite
+ for (i = 0; i < size; i++)
+ *(hva + i) = *(code + i);
+
+ return 0;
+}
+
+
+static int v3_restore_pre_mmap_state (struct guest_info * core, struct v3_code_inject_info * inject) {
+ int ret;
+ addr_t rip_hva, mmap_gva;
+
+ if ((mmap_gva = (addr_t)core->vm_regs.rbx) < 0) {
+ PrintError("Error running mmap in guest: v3_restore_pre_mmap_state\n");
+ return -1;
+ }
+
+ inject->code_region_gva = mmap_gva;
+
+ ret = v3_gva_to_hva(core,
+ get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
+ &rip_hva);
+ if (ret == -1) {
+ PrintError("Error translating RIP address: v3_restore_pre_mmap_state\n");
+ return -1;
+ }
+
+ // restore the code overwritten by mmap code
+ memcpy((void*)rip_hva, (void*)inject->old_code, MMAP_SIZE);
+ V3_Free(inject->old_code);
+
+ v3_do_static_inject(core, inject, MMAP_COMPLETE, mmap_gva);
+ return 0;
+}
+
+
+static int v3_restore_pre_inject_state (struct guest_info * core, struct v3_code_inject_info * inject) {
+ int ret;
+ addr_t rip_hva;
+
+ // restore original register state at int 80
+ memcpy(&core->vm_regs, &inject->regs, sizeof(struct v3_gprs));
+ memcpy(&core->ctrl_regs, &inject->ctrl_regs, sizeof(struct v3_ctrl_regs));
+
+ ret = v3_gva_to_hva(core,
+ get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
+ &rip_hva);
+ if (ret == -1) {
+ PrintError("Error translating RIP address: v3_pre_inject_state\n");
+ return -1;
+ }
+
+ // increment original rip by 2 to skip the int 80
+ core->rip = inject->rip + 2;
+ return 0;
+}
+
+
+/*
+ * This function completes stage 1 of the inject. It is invoked when code to
+ * mmap space for the real code has been injected and has completed. This mmap
+ * code will hypercall back into Placios, getting us here.
+ */
+static int mmap_init_handler (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
+ struct v3_code_inject_info * inject = current_inject;
+ v3_restore_pre_mmap_state(core, inject);
+ return 0;
+}
+
+
+/*
+ * This function is stage 3 of the injection process. It is invoked when the injected code
+ * has run to completeion and run a hypercall at its tail to get back into the
+ * VMM. After this, it only remains to unmap the space we injected it into (the
+ * 4th and final stage)
+ */
+static int inject_code_finish (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
+ struct v3_code_inject_info * inject = current_inject;
+ addr_t hva;
+
+ // is the original int 80 page still paged in?
+ if (v3_gva_to_hva(core,
+ get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
+ &hva) == -1) {
+ PrintError("No mapping in shadow page table: inject_code_finish\n");
+ return -1;
+ }
+
+ inject->old_code = V3_Malloc(MUNMAP_SIZE);
+ if (!inject->old_code) {
+ PrintError("Problem mallocing old code segment\n");
+ return -1;
+ }
+
+ // save old code and overwrite with munmap
+ v3_plant_code(core, inject, (char*)hva, munmap_code, MUNMAP_SIZE);
+
+ // set rbx with gva of code region
+ core->vm_regs.rbx = inject->code_region_gva;
+
+ // set rip back
+ core->rip = inject->rip;
+ return 0;
+}
+
+
+//
+// this is 4th and final stage of the code injection process. It is invoked after code
+// has been injected to run the munmap system call on our previosuly allocated
+// memory chunk. It results in the clean
+// up and removal of the current inject's structures and state, and its
+// removal from any injection queues
+//
+static int munmap_finish (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
+ struct v3_code_inject_info * inject = current_inject;
+ int i = 0;
+ addr_t hva;
+
+ if (core->vm_regs.rbx < 0) {
+ PrintError("Problem munmapping injected code\n");
+ return -1;
+ }
+
+ if (v3_gva_to_hva(core,
+ get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
+ &hva) == -1) {
+ PrintError("No mapping in shadow page table: inject_code_finish\n");
+ return -1;
+ }
+
+ for (i = 0; i < MUNMAP_SIZE; i++)
+ *(char*)(hva + i) = *(char*)(inject->old_code + i);
+
+ V3_Free(inject->old_code);
+
+ v3_restore_pre_inject_state(core, inject);
+
+ // clean up
+ v3_remove_code_inject(core->vm_info, inject);
+ current_inject = NULL;
+
+ // raise the original int 80 again, causing an exec
+ return v3_raise_swintr(core, SW_INTR_SYSCALL_VEC);
+}
+
+
+/*
+ * This function is comprises stage 2 of the injection process. Here, the
+ * injected code is copied one page at a time. Each time a new page must be
+ * copied, Palacios injects a page fault for it to bring it into the guest and
+ * host page tables. The fault address will be somewhere in our previously
+ * mmap'd region, but we will jump back to the same RIP every time, which
+ * contains the hypercall that invokes this function.
+ */
+static int mmap_pf_handler (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
+ struct v3_code_inject_info * inject = current_inject;
+ pf_error_t err;
+ int i, offset = core->vm_regs.rbx;
+ addr_t hva, gva = core->vm_regs.rcx;
+ memset((void*)&err, 0, sizeof(pf_error_t));
+
+ // was page fault handled by guest kernel?
+ if (v3_gva_to_hva(core,
+ get_addr_linear(core, gva, &(core->segments.ds)),
+ &hva) == -1) {
+ PrintError("No mapping in shadow page table: mmap_pf_handler\n");
+ return -1;
+ }
+
+ if (offset >= inject->code_size) {
+ core->rip = gva - offset + inject->func_offset;
+
+ // restore registers (here, really just for sane ebp/esp)
+ memcpy(&core->vm_regs, &inject->regs, sizeof(struct v3_gprs));
+ memcpy(&core->ctrl_regs, &inject->ctrl_regs, sizeof(struct v3_ctrl_regs));
+
+ if (v3_gva_to_hva(core,
+ get_addr_linear(core, inject->rip, &(core->segments.cs)),
+ &hva) == -1) {
+ PrintError("No mapping for old RIP in shadow page table: mmap_pf_handler: %p\n", (void*)inject->rip);
+ return -1;
+ }
+
+ // restore the hypercall with original int 80 code
+ for (i = 0; i < VMMCALL_SIZE; i++)
+ *(char*)(hva + i) = *(char*)(inject->old_code + i);
+
+ V3_Free(inject->old_code);
+
+ if (v3_gva_to_hva(core,
+ get_addr_linear(core, core->rip, &(core->segments.cs)),
+ &hva) == -1) {
+ PrintError("No mapping for new RIP in shadow page table: mmap_pf_handler: %p\n", (void*)core->rip);
+ return -1;
+ }
+
+ return 0;
+ }
+
+ // copy the next page of code
+ for (i = 0; i < PAGE_SIZE; i++)
+ *(char*)(hva + i) = *(char*)(inject->code + offset + i);
+
+
+ core->vm_regs.rbx += PAGE_SIZE;
+ core->vm_regs.rcx += PAGE_SIZE;
+
+ // to account for rip being incremented by hcall handler
+ core->rip -= VMMCALL_SIZE;
+
+ // inject the page fault for next page
+ err.user = 1;
+ err.write = 1;
+ v3_inject_guest_pf(core, gva + PAGE_SIZE, err);
+
+ return 0;
+}
+
+
+static int init_code_inject (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
+ struct v3_code_injects * injects = &code_injects;
+ INIT_LIST_HEAD(&(injects->code_inject_list));
+ INIT_LIST_HEAD(&(injects->hooked_code_injects));
+
+ injects->active = 1;
+
+ current_inject = NULL;
+
+ v3_register_hypercall(vm, 0xf000, mmap_init_handler, NULL);
+ v3_register_hypercall(vm, 0xf001, inject_code_finish, NULL);
+ v3_register_hypercall(vm, 0xf002, mmap_pf_handler, NULL);
+ v3_register_hypercall(vm, 0xf003, munmap_finish, NULL);
+ return 0;
+}
+
+
+static int deinit_code_inject (struct v3_vm_info * vm, void * priv_data) {
+ struct v3_code_injects * injects = &code_injects;
+ struct v3_code_inject_info * inject = NULL;
+ struct v3_code_inject_info * tmp = NULL;
+
+ list_for_each_entry_safe(inject, tmp, &(injects->code_inject_list), inject_node) {
+ free_code_inject(vm, inject);
+ }
+
+ list_for_each_entry_safe(inject, tmp, &(injects->hooked_code_injects), inject_node) {
+ free_code_inject(vm, inject);
+ }
+
+ v3_remove_hypercall(vm, 0xf000);
+ v3_remove_hypercall(vm, 0xf001);
+ v3_remove_hypercall(vm, 0xf002);
+ v3_remove_hypercall(vm, 0xf003);
+ return 0;
+}
+
+
+
+
+/* KCH currently unused */
+/* this dynamic linking stuff will eventually be moved out of this file... */
+static addr_t v3_get_dyn_entry (struct guest_info * core, addr_t elf_gva, addr_t elf_hva,
+ int section_code) {
+ ElfW(Ehdr) *ehdr;
+ ElfW(Phdr) *phdr, *phdr_cursor;
+ ElfW(Dyn) *dyn = NULL;
+ int i, j, num_dyn;
+ addr_t hva;
+
+ ehdr = (ElfW(Ehdr)*)elf_hva;
+ phdr = (ElfW(Phdr)*)(elf_hva + ehdr->e_phoff);
+ phdr_cursor = phdr;
+
+ //PrintDebug("num phdrs: %d\n", ehdr->e_phnum);
+ for (i = 0; i < ehdr->e_phnum; i++, phdr_cursor++) {
+ if (phdr_cursor->p_type == PT_DYNAMIC) {
+ num_dyn = phdr_cursor->p_filesz / sizeof(ElfW(Dyn));
+ dyn = (ElfW(Dyn)*)(elf_hva + phdr_cursor->p_offset);
+
+ // make sure this addr is paged in
+ if (v3_gva_to_gpa(core, elf_gva + phdr_cursor->p_offset, &hva) == -1) {
+ PrintError("Dynamic segment isn't paged in\n");
+ return 0;
+ }
+
+ for (j = 0; j < num_dyn; j++, dyn++) {
+ if (dyn->d_tag == section_code) {
+ switch (section_code) {
+ case DT_STRSZ:
+ case DT_SYMENT:
+ case DT_PLTREL:
+ return (addr_t)dyn->d_un.d_val;
+ default:
+ return (addr_t)dyn->d_un.d_ptr;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+
+static int v3_do_resolve (struct guest_info * core, addr_t elf_gva, addr_t elf_hva) {
+
+ addr_t got_gva, symtab_gva, strtab_gva;
+
+ if ((got_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_PLTGOT)) == 0) {
+ PrintError("Problem getting at PLTGOT in v3_do_resolve\n");
+ return -1;
+ }
+
+
+ if ((strtab_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_STRTAB)) == 0) {
+ PrintError("Problem getting at PLTGOT in v3_do_resolve\n");
+ return -1;
+ }
+
+ if ((symtab_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_SYMTAB)) == 0) {
+ PrintError("Problem getting at PLTGOT in v3_do_resolve\n");
+ return -1;
+ }
+
+
+ PrintDebug("Got gva: %p\n", (void*)got_gva);
+ PrintDebug("Symtab gva: %p\n", (void*)symtab_gva);
+ PrintDebug("Strtab gva: %p\n", (void*)strtab_gva);
+ return 0;
+}
+
+static int v3_do_cont (struct guest_info * core, struct v3_code_inject_info * inject, addr_t check) {
+
+ addr_t hva;
+ pf_error_t err_code;
+ int ret;
+
+ ret = v3_gva_to_gpa(core, check, &hva);
+
+ // page fault wasn't handled by kernel??
+ if (ret == -1) {
+ PrintError("ERROR: no mapping in guest page table!\n");
+ return -1;
+ }
+
+ ret = v3_gva_to_hva(core,
+ get_addr_linear(core, check, &(core->segments.cs)),
+ &hva);
+
+ // this should never happen...
+ if (ret == -1) {
+ PrintError("ERROR: no mapping in shadow page table\n");
+ return -1;
+ }
+
+ if (strncmp(elf_magic, (char*)hva, ELF_MAG_SIZE) != 0) {
+
+ check -= PAGE_SIZE;
+ inject->cont->check_addr = check;
+ inject->cont->cont_func = v3_do_cont;
+
+ memset((void*)&err_code, 0, sizeof(pf_error_t));
+ err_code.user = 1;
+
+ if (v3_inject_guest_pf(core, check, err_code) < 0) {
+ PrintError("Problem injecting pf\n");
+ return -1;
+ }
+
+ return E_NEED_PF;
+ }
+
+ PrintDebug("Found ELF!\n");
+ V3_Free(inject->cont);
+ inject->cont = NULL;
+ return v3_do_resolve(core, check, hva);
+}
+
+
+/*
+ * mmap_state: 0 = no inject space in procces yet
+ * 1 = code segment space mmap'd, still need data
+ * 2 = code & data segments mmap'd, ready to inject real code
+ *
+ */
+//
+// return E_NEED_PF up the call stack to signal page fault injection
+// (so rip doesn't get incremented and sw_intr doesn't get injected
+//
+int v3_do_inject (struct guest_info * core, struct v3_code_inject_info * inject, int mmap_state) {
+ addr_t rip_hva, elf_hva, elf_gva;
+ int ret = 0, i = 0;
+ pf_error_t err_code;
+
+ memset((void*)&err_code, 0, sizeof(pf_error_t));
+
+ ret = v3_gva_to_hva(core,
+ get_addr_linear(core, (addr_t)core->rip, &(core->segments.cs)),
+ &rip_hva);
+ if (ret == -1) {
+ PrintError("Error translating RIP address in v3_do_inject\n");
+ return -1;
+ }
+
+ elf_gva = (addr_t)(core->rip & 0xfffffffffffff000);
+
+ for (i = 0; i < PAGES_BACK; i++, elf_gva -= PAGE_SIZE) {
+
+ ret = v3_gva_to_hva(core,
+ get_addr_linear(core, elf_gva, &(core->segments.cs)),
+ &elf_hva);
+
+ // need to page in
+ if (ret == -1) {
+
+ PrintDebug("Found a page we need to fault in\n");
+ inject->cont = (struct v3_cont *)V3_Malloc(sizeof(struct v3_cont));
+ ret = v3_gva_to_gpa(core, elf_gva, &elf_hva);
+
+ if (ret == -1) {
+ PrintDebug("no mapping in guest page table\n");
+ }
+
+ inject->cont->check_addr = elf_gva;
+ inject->cont->cont_func = v3_do_cont;
+ err_code.user = 1;
+
+ PrintDebug("Injecting pf for addr: %p\n", (void*) elf_gva);
+
+ if (v3_inject_guest_pf(core, elf_gva, err_code) < 0) {
+ PrintError("Problem injecting pf\n");
+ return -1;
+ }
+
+ return E_NEED_PF;
+ }
+
+ if (strncmp(elf_magic, (char*)elf_hva, ELF_MAG_SIZE) == 0) {
+ PrintDebug("Found elf_magic!\n");
+ break;
+ }
+
+ }
+
+
+ V3_Free(inject->cont);
+ inject->cont = NULL;
+ return v3_do_resolve(core, elf_gva, elf_hva);
+
+ PrintDebug("Planting code\n");
+ v3_plant_code(core, inject, (char*)rip_hva, mmap_code, MMAP_SIZE);
+
+ PrintDebug("Saving register context\n");
+ PrintDebug("First 8 bytes 0x%lx\n", *(long*)rip_hva);
+ /* may need to save v3_ctrl registers too... */
+ memcpy(&inject->regs, &core->vm_regs, sizeof(struct v3_gprs));
+ inject->rip = core->rip;
+
+ /* jump to injected code */
+ PrintDebug("Jumping to injected code\n");
+ return 0;
+}
+
+
+/*
+ * mmap_state: NO_MMAP = no inject space mmap'd in procces yet
+ * MMAP_COMPLETE = mmap complete, time to do real inject
+ *
+ */
+int v3_do_static_inject (struct guest_info * core, struct v3_code_inject_info * inject,
+ int mmap_state, addr_t region_gva) {
+ addr_t rip_hva;
+ int ret;
+
+
+ ret = v3_gva_to_hva(core,
+ get_addr_linear(core, (addr_t)core->rip, &(core->segments.cs)),
+ &rip_hva);
+ if (ret == -1) {
+ PrintError("Error translating RIP address: v3_do_static_inject\n");
+ return -1;
+ }
+
+ switch (mmap_state) {
+ case NO_MMAP:
+ {
+ // inject mmap code
+ v3_plant_code(core, inject, (char*)rip_hva, mmap_code, MMAP_SIZE);
+
+ // save registers (gprs and ctrl regs, and rip)
+ memcpy(&inject->regs, &core->vm_regs, sizeof(struct v3_gprs));
+ memcpy(&inject->ctrl_regs, &core->ctrl_regs, sizeof(struct v3_ctrl_regs));
+ inject->rip = core->rip;
+
+ // jump to mmap code, and squash original swintr
+ return E_NEED_PF;
+ }
+ case MMAP_COMPLETE:
+ {
+ pf_error_t err_code;
+ memset((void*)&err_code, 0, sizeof(pf_error_t));
+
+ ret = v3_gva_to_hva(core,
+ get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
+ &rip_hva);
+ if (ret == -1) {
+ PrintError("Error translating RIP address: v3_do_static_inject\n");
+ return -1;
+ }
+
+ // inject hypercall code
+ v3_plant_code(core, inject, (char*)rip_hva, vmmcall_code, VMMCALL_SIZE);
+
+ /* store current copy offset in rbx, fault gva in rcx */
+ core->vm_regs.rbx = 0;
+ core->vm_regs.rcx = region_gva;
+
+ err_code.user = 1;
+ err_code.write = 1;
+
+ // inject the first page fault for the code block
+ if (v3_inject_guest_pf(core, region_gva, err_code) < 0) {
+ PrintError("Problem injecting page fault in v3_do_static_inject\n");
+ return -1;
+ }
+
+ // returning here will run hypercall 0xf002
+ // This will get us back in v3_mmap_pf_handler
+ core->rip = inject->rip;
+ return 0;
+ }
+ default:
+ PrintError("Invalid mmap state\n");
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * This function is invoked in one of two ways:
+ * 1. A syscall has been intercepted and we've popped off the next pending
+ * inject
+ * 2. An exec has been intercepted and we've popped off the next hooked inject
+ *
+ */
+int v3_handle_guest_inject (struct guest_info * core, void * priv_data) {
+ struct v3_code_inject_info * inject = (struct v3_code_inject_info *)priv_data;
+
+ /* eventually this should turn into a mutex lock */
+ if (current_inject) {
+ PrintError("An inject is already in progress\n");
+ return -1;
+ } else {
+ current_inject = inject;
+ inject->in_progress = 1;
+ }
+
+ if (!inject->is_dyn) {
+ return v3_do_static_inject(core, inject, 0, (addr_t)NULL);
+ } else {
+ if (inject->cont)
+ return inject->cont->cont_func(core, inject, inject->cont->check_addr);
+ else
+ return v3_do_inject(core, inject, 0);
+ }
+
+ return 0;
+}
+
+
+int v3_insert_code_inject (void * ginfo, void * code, int size,
+ char * bin_file, int is_dyn, int is_exec_hooked, int func_offset) {
+ struct v3_code_injects * injects = &code_injects;
+ struct v3_vm_info * vm = (struct v3_vm_info *)ginfo;
+ struct v3_code_inject_info * inject;
+
+ if (!injects->active) {
+ PrintError("Code injection has not been initialized\n");
+ return -1;
+ }
+
+ inject = V3_Malloc(sizeof(struct v3_code_inject_info));
+ if (!inject) {
+ PrintError("Error allocating inject info in v3_insert_code_inject\n");
+ return -1;
+ }
+
+ memset(inject, 0, sizeof(struct v3_code_inject_info));
+
+ inject->code = code;
+ inject->code_size = size;
+ inject->is_dyn = is_dyn;
+ inject->func_offset = func_offset;
+ inject->bin_file = bin_file;
+ inject->is_exec_hooked = is_exec_hooked;
+
+ if (is_exec_hooked) {
+ v3_hook_executable(vm, bin_file, v3_handle_guest_inject, (void*)inject);
+ list_add_tail(&(inject->inject_node), &(injects->hooked_code_injects));
+ } else {
+ list_add_tail(&(inject->inject_node), &(injects->code_inject_list));
+ }
+
+ return 0;
+}
+
+
+int v3_remove_code_inject (struct v3_vm_info * vm, struct v3_code_inject_info * inject) {
+
+ PrintDebug("Removing and freeing code inject\n");
+ if (inject->is_exec_hooked) {
+ if (v3_unhook_executable(vm, inject->bin_file) < 0) {
+ PrintError("Problem unhooking executable in v3_remove_code_inject\n");
+ return -1;
+ }
+ }
+
+ free_code_inject(vm, inject);
+ return 0;
+}
+
+
+static struct v3_extension_impl code_inject_impl = {
+ .name = "code_inject",
+ .init = init_code_inject,
+ .deinit = deinit_code_inject,
+ .core_init = NULL,
+ .core_deinit = NULL,
+ .on_entry = NULL,
+ .on_exit = NULL
+};
+register_extension(&code_inject_impl);
+
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+#include <palacios/vmm.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_intr.h>
+#include <palacios/vmm_extensions.h>
+
+#include <gears/process_environment.h>
+#include <gears/execve_hook.h>
+#include <gears/env_inject.h>
+
+static struct v3_env_injects env_injects;
+
+static int free_env_inject (struct v3_vm_info * vm, struct v3_env_inject_info * inject) {
+ list_del(&(inject->inject_node));
+ V3_Free(inject);
+ return 0;
+}
+
+static int v3_env_inject_handler (struct guest_info * core, void * priv_data) {
+ int i = 0;
+ struct v3_env_inject_info * inject = (struct v3_env_inject_info*)priv_data;
+
+ for (; i < inject->num_env_vars; i++) {
+ PrintDebug("Envvar[%d]: %s\n", i, inject->env_vars[i]);
+ }
+
+ int ret = v3_inject_strings(core, (const char**)NULL,
+ (const char**)inject->env_vars, 0, inject->num_env_vars);
+ if (ret == -1) {
+ PrintDebug("Error injecting strings in v3_env_inject_handler\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int init_env_inject (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
+ struct v3_env_injects * injects = &env_injects;
+ INIT_LIST_HEAD(&(injects->env_inject_list));
+ return 0;
+}
+
+
+static int deinit_env_inject (struct v3_vm_info * vm, void * priv_data) {
+ struct v3_env_injects * injects = &env_injects;
+ struct v3_env_inject_info * inject = NULL;
+ struct v3_env_inject_info * tmp = NULL;
+
+ list_for_each_entry_safe(inject, tmp, &(injects->env_inject_list), inject_node) {
+ free_env_inject(vm, inject);
+ }
+
+ return 0;
+}
+
+
+int v3_insert_env_inject (void * ginfo, char ** strings, int num_strings, char * bin_name) {
+ struct v3_env_injects * injects = &env_injects;
+ struct v3_env_inject_info * inject = V3_Malloc(sizeof(struct v3_env_inject_info));
+
+ memset(inject, 0, sizeof(struct v3_env_inject_info));
+
+ inject->env_vars = strings;
+ inject->num_env_vars = num_strings;
+ inject->bin_name = bin_name;
+
+ list_add(&(inject->inject_node), &(injects->env_inject_list));
+
+ v3_hook_executable((struct v3_vm_info *)ginfo, bin_name, v3_env_inject_handler, (void*)inject);
+
+ return 0;
+}
+
+
+int v3_remove_env_inject (struct v3_vm_info * vm, struct v3_env_inject_info * inject) {
+
+ if (v3_unhook_executable(vm, inject->bin_name) < 0) {
+ PrintError("Problem unhooking executable in v3_remove_env_inject\n");
+ return -1;
+ }
+
+ free_env_inject(vm, inject);
+ return 0;
+}
+
+
+static struct v3_extension_impl env_inject_impl = {
+ .name = "env_inject",
+ .init = init_env_inject,
+ .deinit = deinit_env_inject,
+ .core_init = NULL,
+ .core_deinit = NULL,
+ .on_entry = NULL,
+ .on_exit = NULL
+};
+
+register_extension(&env_inject_impl);
+
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_string.h>
+#include <palacios/vmm_hashtable.h>
+#include <palacios/vmm_extensions.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vm_guest_mem.h>
+
+#include <gears/syscall_hijack.h>
+#include <gears/execve_hook.h>
+#include <gears/syscall_ref.h>
+
+#ifdef V3_CONFIG_EXT_CODE_INJECT
+#include <gears/code_inject.h>
+#endif
+
+static struct v3_exec_hooks exec_hooks;
+
+static int free_hook (struct v3_vm_info * vm, struct exec_hook * hook) {
+ list_del(&(hook->hook_node));
+ V3_Free(hook);
+ return 0;
+}
+
+static uint_t exec_hash_fn (addr_t key) {
+ return v3_hash_long(key, sizeof(void *) * 8);
+}
+
+
+static int exec_eq_fn (addr_t key1, addr_t key2) {
+ return (key1 == key2);
+}
+
+
+static int init_exec_hooks (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
+
+ return 0;
+}
+
+static int init_exec_hooks_core (struct guest_info * core, void * priv_data) {
+ struct v3_exec_hooks * hooks = &exec_hooks;
+ INIT_LIST_HEAD(&(hooks->hook_list));
+ hooks->bin_table = v3_create_htable(0, exec_hash_fn, exec_eq_fn);
+
+ if (hooks->bin_table == NULL) {
+ PrintError("Problem creating execve hash table\n");
+ return -1;
+ }
+
+ if (core->cpu_mode == LONG || core->cpu_mode == LONG_32_COMPAT) {
+ PrintDebug("Hooking execve 64\n");
+ v3_hook_syscall(core, SYS64_EXECVE, v3_execve_handler, NULL);
+ } else {
+ PrintDebug("Hooking execve, cpu mode: %x\n", core->cpu_mode);
+ v3_hook_syscall(core, SYS32_EXECVE, v3_execve_handler, NULL);
+ }
+ return 0;
+}
+
+static int deinit_exec_hooks_core (struct guest_info * core, void * priv_data) {
+ struct v3_exec_hooks * hooks = &exec_hooks;
+ struct exec_hook * hook = NULL;
+ struct exec_hook * tmp = NULL;
+
+ list_for_each_entry_safe(hook, tmp, &(hooks->hook_list), hook_node) {
+ free_hook(core->vm_info, hook);
+ }
+
+ v3_free_htable(hooks->bin_table, 0, 0);
+
+ return 0;
+}
+
+
+int v3_hook_executable (struct v3_vm_info * vm,
+ const uchar_t * binfile,
+ int (*handler)(struct guest_info * core, void * priv_data),
+ void * priv_data)
+{
+ struct exec_hook * hook = V3_Malloc(sizeof(struct exec_hook));
+ struct v3_exec_hooks * hooks = &exec_hooks;
+ addr_t key;
+
+ memset(hook, 0, sizeof(struct exec_hook));
+
+ hook->handler = handler;
+ hook->priv_data = priv_data;
+
+ // we hash the name of the file to produce a key
+ key = v3_hash_buffer((uchar_t*)binfile, strlen(binfile));
+
+ v3_htable_insert(hooks->bin_table, key, (addr_t)hook);
+ list_add(&(hook->hook_node), &(hooks->hook_list));
+
+ return 0;
+}
+
+
+int v3_unhook_executable (struct v3_vm_info * vm, const uchar_t * binfile) {
+ struct exec_hook * hook;
+ struct v3_exec_hooks * hooks = &exec_hooks;
+ addr_t key;
+
+ key = v3_hash_buffer((uchar_t*)binfile, strlen((uchar_t*)binfile));
+ if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) {
+ free_hook(vm, hook);
+ } else {
+ PrintError("Could not unhook executable '%s'\n", binfile);
+ return -1;
+ }
+
+ if (v3_htable_remove(hooks->bin_table, key, 0) == (addr_t)NULL) {
+ PrintError("Error trying to remove key from htable: v3_unhook_executable\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct v3_extension_impl execve_impl = {
+ .name = "execve_intercept",
+ .init = init_exec_hooks,
+ .deinit = NULL,
+ .core_init = init_exec_hooks_core,
+ .core_deinit = deinit_exec_hooks_core,
+ .on_entry = NULL,
+ .on_exit = NULL
+};
+
+register_extension(&execve_impl);
+
+
+int v3_execve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
+ addr_t hva, key;
+ struct v3_exec_hooks * hooks = &exec_hooks;
+ struct exec_hook * hook;
+ int ret;
+
+
+ // TODO: make sure this returns immediately if we're not booted up already
+ if (core->mem_mode == PHYSICAL_MEM) {
+ ret = v3_gpa_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);
+ } else {
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);
+ }
+
+ if (ret == -1) {
+ PrintError("Error translating file path in sysexecve handler\n");
+ return 0;
+ }
+
+ key = v3_hash_buffer((uchar_t*)hva, strlen((uchar_t*)hva));
+ if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) {
+
+ ret = hook->handler(core, hook->priv_data);
+ if (ret == -1) {
+ PrintDebug("Error handling execve hook\n");
+ return -1;
+ }
+
+#ifdef V3_CONFIG_EXT_CODE_INJECT
+ if (ret == E_NEED_PF) {
+ return E_NEED_PF;
+ }
+#endif
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vm_guest_mem.h>
+
+#include <gears/process_environment.h>
+
+static struct v3_execve_varchunk var_dump;
+
+
+/* KCH: currently only checks if we can perform a user-mode write
+ return 1 on success */
+static int v3_gva_can_access(struct guest_info * core, addr_t gva) {
+
+ v3_reg_t guest_cr3 = 0;
+ pf_error_t access_type;
+ pt_access_status_t access_status;
+
+ access_type.write = 1;
+ access_type.user = 1;
+
+ if (core->mem_mode == PHYSICAL_MEM) {
+ return -1;
+ }
+
+ if (core->shdw_pg_mode == SHADOW_PAGING) {
+ guest_cr3 = core->shdw_pg_state.guest_cr3;
+ } else {
+ guest_cr3 = core->ctrl_regs.cr3;
+ }
+
+ // guest is in paged mode
+ switch (core->cpu_mode) {
+ case PROTECTED:
+ if (v3_check_guest_pt_32(core, guest_cr3, gva, access_type, &access_status) == -1) {
+ return -1;
+ }
+ break;
+ case PROTECTED_PAE:
+ if (v3_check_guest_pt_32pae(core, guest_cr3, gva, access_type, &access_status) == -1) {
+ return -1;
+ }
+ break;
+ case LONG:
+ case LONG_32_COMPAT:
+ case LONG_16_COMPAT:
+ if (v3_check_guest_pt_64(core, guest_cr3, gva, access_type, &access_status) == -1) {
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ if (access_status != PT_ACCESS_OK) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static int v3_copy_chunk_guest32(struct guest_info * core, addr_t gva, uint_t argcnt, uint_t envcnt) {
+
+ int ret = 0, i = 0;
+ addr_t hva;
+ uint32_t tmp_args[var_dump.argc];
+ uint32_t tmp_envs[var_dump.envc];
+
+ PrintDebug("Initiating copy into guest (32bit)\n");
+
+ ret = v3_gva_to_hva(core, get_addr_linear(core, gva, &(core->segments.ds)), &hva);
+ if (ret == -1) {
+ PrintDebug("Error translating gva in v3_copy_chunk_2guest\n");
+ return -1;
+ }
+
+ // copy the env strings (we're moving top-down through the stack)
+ char * host_cursor = (char*) hva;
+ uint32_t guest_cursor = (uint32_t) gva;
+ host_cursor -= strlen(var_dump.envp[i]) + 1;
+ guest_cursor -= strlen(var_dump.envp[i]) + 1;
+ while (i < var_dump.envc) {
+ //PrintDebug("Copying envvar#%d: %s\n", i, var_dump.envp[i]);
+ strcpy(host_cursor, var_dump.envp[i]);
+ tmp_envs[i] = guest_cursor;
+ i++;
+ if (i != var_dump.envc) {
+ host_cursor -= strlen(var_dump.envp[i]) + 1;
+ guest_cursor -= strlen(var_dump.envp[i]) + 1;
+ }
+ }
+
+ // then the arg strings
+ i = 0;
+ host_cursor -= strlen(var_dump.argv[i]) + 1;
+ guest_cursor -= strlen(var_dump.argv[i]) + 1;
+ while (i < var_dump.argc) {
+ //PrintDebug("Copying arg #%d: %s\n", i, var_dump.argv[i]);
+ strcpy(host_cursor, var_dump.argv[i]);
+ tmp_args[i] = guest_cursor;
+ i++;
+ if (i != var_dump.argc) {
+ host_cursor -= strlen(var_dump.argv[i]) + 1;
+ guest_cursor -= strlen(var_dump.argv[i]) + 1;
+ }
+ }
+
+
+ // padding
+ host_cursor--;
+ guest_cursor--;
+ while ((long)host_cursor % 4) {
+ *host_cursor = 0;
+ host_cursor--;
+ guest_cursor--;
+ }
+
+ // null ptr
+ host_cursor -= 4;
+ guest_cursor -= 4;
+ *((uint32_t*)host_cursor) = 0;
+
+ host_cursor -= 4;
+ guest_cursor -= 4;
+ for (i = 0; i < var_dump.envc; i++) {
+ *((uint32_t*)host_cursor) = tmp_envs[i];
+ host_cursor -= 4;
+ guest_cursor -= 4;
+ }
+
+ core->vm_regs.rdx = guest_cursor + 4;
+
+ *((uint32_t*)host_cursor) = 0;
+ host_cursor -= 4;
+ guest_cursor -= 4;
+ for (i = 0; i < var_dump.argc; i++) {
+ *((uint32_t*)host_cursor) = tmp_args[i];
+ host_cursor -= 4;
+ guest_cursor -= 4;
+ }
+
+ core->vm_regs.rcx = guest_cursor + 4;
+
+ // free up our temporary storage in the VMM
+ for (i = 0; i < var_dump.argc; i++) {
+ V3_Free(var_dump.argv[i]);
+ }
+ for (i = 0; i < var_dump.envc; i++) {
+ V3_Free(var_dump.envp[i]);
+ }
+
+ V3_Free(var_dump.envp);
+ V3_Free(var_dump.argv);
+ return 0;
+}
+
+
+static int v3_copy_chunk_vmm32(struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
+
+ addr_t envp, argv;
+ uint_t argc = 0, envc = 0, bytes = 0;
+ char * cursor;
+
+ PrintDebug("Initiating copy into vmm\n");
+
+ int ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rdx, &(core->segments.ds)), &envp);
+ if (ret == -1) {
+ PrintDebug("Error translating address in rdx\n");
+ return 0;
+ }
+
+ ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rcx, &(core->segments.ds)), &argv);
+ if (ret == -1) {
+ PrintDebug("Error translating address in rcx\n");
+ return 0;
+ }
+
+ cursor = (char*)argv;
+ while (*((uint32_t*)cursor) != 0) {
+ addr_t argvn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &argvn);
+ if (ret == -1) {
+ PrintDebug("Error translating address for argvn\n");
+ }
+ argc++;
+ cursor += 4;
+ }
+
+ /* account for new args */
+ argc += argcnt;
+ var_dump.argv = (char**)V3_Malloc(sizeof(char*)*argc);
+ var_dump.argc = argc;
+ bytes += sizeof(uint32_t)*argc;
+
+ cursor = (char*)argv;
+ int i = 0;
+ while (*((uint32_t*)cursor) != 0) {
+ addr_t argvn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &argvn);
+ if (ret == -1) {
+ PrintDebug("Error translating argvn address\n");
+ }
+
+ /* malloc room for the string */
+ char * tmpstr = (char*)V3_Malloc(strlen((char*)argvn) + 1);
+
+ /* copy the pointer */
+ var_dump.argv[i] = tmpstr;
+
+ /* copy the string */
+ strncpy(tmpstr, (char*)argvn, strlen((char*)argvn) + 1);
+ i++;
+ cursor += 4;
+ bytes += strlen((char*)argvn) + 1;
+ }
+
+ /* stick in new arg strings */
+ int j = 0;
+ while (j < argcnt) {
+ char * tmpstr = (char*)V3_Malloc(strlen(argstrs[j]) + 1);
+ strncpy(tmpstr, argstrs[i], strlen(argstrs[j]) + 1);
+ var_dump.argv[i] = tmpstr;
+ bytes += strlen(argstrs[j]) + 1;
+ i++; j++;
+ }
+
+
+ cursor = (char*)envp;
+ while (*((uint32_t*)cursor) != 0) {
+ addr_t envpn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &envpn);
+ if (ret == -1) {
+ PrintDebug("Error translating address for envpn\n");
+ }
+ envc++;
+ cursor += 4;
+ }
+
+ envc += envcnt;
+ var_dump.envp = (char**)V3_Malloc(sizeof(char*)*envc);
+ var_dump.envc = envc;
+ bytes += sizeof(uint32_t)*envc;
+
+ cursor = (char*)envp;
+ i = 0;
+ while (*((uint32_t*)cursor) != 0) {
+ addr_t envpn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &envpn);
+ if (ret == -1) {
+ PrintDebug("Error translating address for envpn\n");
+ }
+
+ /* malloc room for the string */
+ char * tmpstr = (char*)V3_Malloc(strlen((char*)envpn) + 1);
+
+ /* copy the pointer */
+ var_dump.envp[i] = tmpstr;
+
+ /* deepcopy the string */
+ strncpy(tmpstr, (char*)envpn, strlen((char*)envpn) + 1);
+ i++;
+ cursor += 4;
+ bytes += strlen((char*)envpn) + 1;
+ }
+
+ /* put in our new env strings */
+ j = 0;
+ while (j < envcnt) {
+ char * tmpstr = (char*)V3_Malloc(strlen(envstrs[j]) + 1);
+ strncpy(tmpstr, envstrs[j], strlen(envstrs[j]) + 1);
+ var_dump.envp[i] = tmpstr;
+ bytes += strlen(envstrs[j]) + 1;
+ i++; j++;
+ }
+
+
+ /* account for padding for strings
+ and 2 null pointers */
+ bytes += (bytes % 4) + 8;
+ var_dump.bytes = bytes;
+ return bytes;
+}
+
+
+static int v3_inject_strings32 (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
+
+ addr_t inject_gva;
+ uint_t bytes_needed = 0;
+
+ /* copy out all of the arguments and the environment to the VMM */
+ if ((bytes_needed = v3_copy_chunk_vmm32(core, argstrs, envstrs, argcnt, envcnt)) == -1) {
+ PrintDebug("Error copying out environment and arguments\n");
+ return -1;
+ }
+
+ PrintDebug("environment successfully copied into VMM\n");
+
+ inject_gva = v3_prepare_guest_stack(core, bytes_needed);
+ if (!inject_gva) {
+ PrintDebug("Not enough space on user stack\n");
+ return -1;
+ }
+
+ v3_copy_chunk_guest32(core, inject_gva, argcnt, envcnt);
+
+ return 0;
+}
+
+
+static int v3_copy_chunk_guest64(struct guest_info * core, addr_t gva, uint_t argcnt, uint_t envcnt) {
+
+ int ret = 0, i = 0;
+ addr_t hva;
+ uint64_t tmp_args[var_dump.argc];
+ uint64_t tmp_envs[var_dump.envc];
+
+ PrintDebug("Initiating copy into guest (64bit)\n");
+
+ ret = v3_gva_to_hva(core, get_addr_linear(core, gva, &(core->segments.ds)), &hva);
+ if (ret == -1) {
+ PrintDebug("Error translating gva in v3_copy_chunk_2guest64\n");
+ return -1;
+ }
+
+ char * host_cursor = (char*) hva;
+ uint64_t guest_cursor = (uint64_t) gva;
+ host_cursor -= strlen(var_dump.envp[i]) + 1;
+ guest_cursor -= strlen(var_dump.envp[i]) + 1;
+ while (i < var_dump.envc) {
+ //PrintDebug("Copying envvar#%d: %s\n", i, var_dump.envp[i]);
+ strcpy(host_cursor, var_dump.envp[i]);
+ tmp_envs[i] = guest_cursor;
+ i++;
+ if (i != var_dump.envc) {
+ host_cursor -= strlen(var_dump.envp[i]) + 1;
+ guest_cursor -= strlen(var_dump.envp[i]) + 1;
+ }
+ }
+
+ i = 0;
+ host_cursor -= strlen(var_dump.argv[i]) + 1;
+ guest_cursor -= strlen(var_dump.argv[i]) + 1;
+ while (i < var_dump.argc) {
+ //PrintDebug("Copying arg #%d: %s\n", i, var_dump.argv[i]);
+ strcpy(host_cursor, var_dump.argv[i]);
+ tmp_args[i] = guest_cursor;
+ i++;
+ if (i != var_dump.argc) {
+ host_cursor -= strlen(var_dump.argv[i]) + 1;
+ guest_cursor -= strlen(var_dump.argv[i]) + 1;
+ }
+ }
+
+ // padding
+ host_cursor--;
+ guest_cursor--;
+ while ((long)host_cursor % 8) {
+ *host_cursor = 0;
+ host_cursor--;
+ guest_cursor--;
+ }
+
+ // one null ptr
+ host_cursor -= 8;
+ guest_cursor -= 8;
+ *((uint64_t*)host_cursor) = 0;
+
+ host_cursor -= 8;
+ guest_cursor -= 8;
+ for (i = 0; i < var_dump.envc; i++) {
+ *((uint64_t*)host_cursor) = tmp_envs[i];
+ host_cursor -= 8;
+ guest_cursor -= 8;
+ }
+
+ core->vm_regs.rdx = guest_cursor + 8;
+
+ *((uint64_t*)host_cursor) = 0;
+ host_cursor -= 8;
+ guest_cursor -= 8;
+ for (i = 0; i < var_dump.argc; i++) {
+ *((uint64_t*)host_cursor) = tmp_args[i];
+ host_cursor -= 8;
+ guest_cursor -= 8;
+ }
+
+ core->vm_regs.rcx = guest_cursor + 8;
+
+ for (i = 0; i < var_dump.argc; i++) {
+ V3_Free(var_dump.argv[i]);
+ }
+ for (i = 0; i < var_dump.envc; i++) {
+ V3_Free(var_dump.envp[i]);
+ }
+
+ V3_Free(var_dump.envp);
+ V3_Free(var_dump.argv);
+ return 0;
+}
+
+
+static int v3_copy_chunk_vmm64(struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
+
+ addr_t envp, argv;
+ uint_t argc = 0, envc = 0, bytes = 0;
+ char * cursor;
+
+ PrintDebug("Initiating copy into vmm\n");
+
+ int ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rdx, &(core->segments.ds)), &envp);
+ if (ret == -1) {
+ PrintDebug("Error translating address in rdx\n");
+ return 0;
+ }
+
+ ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rcx, &(core->segments.ds)), &argv);
+ if (ret == -1) {
+ PrintDebug("Error translating address in rcx\n");
+ return 0;
+ }
+
+ cursor = (char*)argv;
+ while (*((uint64_t*)cursor) != 0) {
+ addr_t argvn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &argvn);
+ if (ret == -1) {
+ PrintDebug("Error translating address for argvn\n");
+ }
+ argc++;
+ cursor += 8;
+ }
+
+ /* account for new strings */
+ argc += argcnt;
+ var_dump.argv = (char**)V3_Malloc(sizeof(char*)*argc);
+ var_dump.argc = argc;
+ bytes += sizeof(char*)*argc;
+
+ cursor = (char*)argv;
+ int i = 0;
+ while (*((uint64_t*)cursor) != 0) {
+ addr_t argvn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &argvn);
+ if (ret == -1) {
+ PrintDebug("Error translating argvn address\n");
+ }
+
+ /* malloc room for the string */
+ char * tmpstr = (char*)V3_Malloc(strlen((char*)argvn) + 1);
+
+ /* copy the pointer */
+ var_dump.argv[i] = tmpstr;
+
+ /* copy the string */
+ strncpy(tmpstr, (char*)argvn, strlen((char*)argvn) + 1);
+ i++;
+ cursor += 8;
+ bytes += strlen((char*)argvn) + 1;
+ }
+
+ /* stick in new arg strings */
+ int j = 0;
+ while (j < argcnt) {
+ char * tmpstr = (char*)V3_Malloc(strlen(argstrs[j]) + 1);
+ strncpy(tmpstr, argstrs[j], strlen(argstrs[j]) + 1);
+ var_dump.argv[i] = tmpstr;
+ bytes += strlen(argstrs[j]) + 1;
+ i++; j++;
+ }
+
+
+ cursor = (char*)envp;
+ while (*((uint64_t*)cursor) != 0) {
+ addr_t envpn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &envpn);
+ if (ret == -1) {
+ PrintDebug("Error translating address for envpn\n");
+ }
+ envc++;
+ cursor += 8;
+ }
+
+ envc += envcnt;
+ var_dump.envp = (char**)V3_Malloc(sizeof(char*)*envc);
+ var_dump.envc = envc;
+ bytes += sizeof(uint64_t)*(envc);
+
+
+ cursor = (char*)envp;
+ i = 0;
+ while (*((uint64_t*)cursor) != 0) {
+ addr_t envpn;
+ ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &envpn);
+ if (ret == -1) {
+ PrintDebug("Error translating address for envpn\n");
+ }
+
+ /* malloc room for the string */
+ char * tmpstr = (char*)V3_Malloc(strlen((char*)envpn) + 1);
+
+ /* copy the pointer */
+ var_dump.envp[i] = tmpstr;
+
+ /* deepcopy the string */
+ strncpy(tmpstr, (char*)envpn, strlen((char*)envpn) + 1);
+ i++;
+ cursor += 8;
+ bytes += strlen((char*)envpn) + 1;
+ }
+
+ /* stick in new env strings */
+ j = 0;
+ while (j < envcnt) {
+ char * tmpstr = (char*)V3_Malloc(strlen(envstrs[j]) + 1);
+ strncpy(tmpstr, envstrs[i], strlen(envstrs[j]) + 1);
+ var_dump.envp[i] = tmpstr;
+ bytes += strlen(envstrs[j]) + 1;
+ i++; j++;
+ }
+
+
+ /* account for padding for strings
+ and 2 null pointers */
+ bytes += (bytes % 8) + 16;
+ var_dump.bytes = bytes;
+ return bytes;
+}
+
+
+static int v3_inject_strings64 (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
+
+ addr_t inject_gva;
+ uint_t bytes_needed = 0;
+
+ /* copy out all of the arguments and the environment to the VMM */
+ if ((bytes_needed = v3_copy_chunk_vmm64(core, argstrs, envstrs, argcnt, envcnt)) == -1) {
+ PrintDebug("Error copying out environment and arguments\n");
+ return -1;
+ }
+
+ PrintDebug("environment successfully copied into VMM\n");
+
+ inject_gva = v3_prepare_guest_stack(core, bytes_needed);
+ if (!inject_gva) {
+ PrintDebug("Not enough space on user stack\n");
+ return -1;
+ }
+
+ v3_copy_chunk_guest64(core, inject_gva, argcnt, envcnt);
+ return 0;
+}
+
+
+addr_t v3_prepare_guest_stack (struct guest_info * core, uint_t bytes_needed) {
+
+ /* TODO: check if we've injected a page fault to get more stack space */
+
+ // do we have enough room between esp and the next page boundary?
+ uint_t rem_bytes = 4096 - (core->vm_regs.rsp % 4096);
+
+ if (rem_bytes >= bytes_needed) {
+ return (addr_t)core->vm_regs.rsp;
+ } else {
+ // not enough room, find out how many pages we need (ceiling)
+ uint_t num_pages = (bytes_needed + 4095) / 4096;
+
+ // check if num_pages are user & writable
+ int i = 0;
+ int pages_ok = 1;
+ addr_t gva = core->vm_regs.rsp + rem_bytes;
+ for (; i < num_pages; i++, gva -= 4096) {
+ if (!v3_gva_can_access(core, gva)) {
+ pages_ok = 0;
+ }
+ }
+
+ if (pages_ok) {
+ return (addr_t)core->vm_regs.rsp;
+ } else {
+
+ /*
+ // inject a page fault
+ pf_error_t fault_type = {
+ .write = 1,
+ .user = 1
+ };
+
+ // hoping Linux will allocate all pages in between gva and esp
+ v3_inject_guest_pf(core, gva - (num_pages*4096), fault_type);
+ */
+ return -1;
+ }
+ }
+}
+
+
+/* TODO: give these next to functions the ability to copy into guest stack */
+int v3_replace_arg (struct guest_info * core, uint_t argnum, const char * newval) {
+
+ return 0;
+}
+
+
+int v3_replace_env (struct guest_info * core, const char * envname, const char * newval) {
+
+ return 0;
+}
+
+
+int v3_inject_strings (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) {
+
+ if (core->cpu_mode == LONG) {
+ if (v3_inject_strings64(core, argstrs, envstrs, argcnt, envcnt) == -1) {
+ PrintDebug("Error injecting strings into environment (64)\n");
+ return -1;
+ }
+ } else {
+ if (v3_inject_strings32(core, argstrs, envstrs, argcnt, envcnt) == -1) {
+ PrintDebug("Error injecting strings into environment (32)\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmcb.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vmm_extensions.h>
+#include <palacios/vmm_intr.h>
+
+#include <gears/sw_intr.h>
+
+#ifdef V3_CONFIG_EXT_CODE_INJECT
+#include <gears/code_inject.h>
+#endif
+
+#ifndef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+
+static int init_swintr_intercept (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
+ return 0;
+}
+
+
+static int init_swintr_core_svm (struct guest_info * core, void * priv_data) {
+ vmcb_t * vmcb = (vmcb_t*)core->vmm_data;
+ vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
+
+ ctrl_area->instrs.INTn = 1;
+ return 0;
+}
+
+
+static int init_swintr_core_vmx (struct guest_info * core, void * priv_data) {
+ PrintError("Not implemented!\n");
+ return -1;
+}
+
+
+static int init_swintr_intercept_core (struct guest_info * core, void * priv_data) {
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+
+ switch (cpu_type) {
+ case V3_SVM_CPU:
+ case V3_SVM_REV3_CPU: {
+ if (init_swintr_core_svm(core, priv_data) == -1) {
+ PrintError("Problem initializing svm software interrupt intercept\n");
+ return -1;
+ }
+ break;
+ }
+ case V3_VMX_CPU:
+ case V3_VMX_EPT_CPU:
+ case V3_VMX_EPT_UG_CPU: {
+ if (init_swintr_core_vmx(core, priv_data) == -1) {
+ PrintError("Problem initializing vmx software interrupt intercept\n");
+ return -1;
+ }
+ break;
+ }
+ default:
+ PrintError("software interrupt interception not supported on this architecture\n");
+ return -1;
+ }
+ return 0;
+}
+
+
+struct v3_swintr_hook {
+ int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data);
+ void * priv_data;
+};
+
+
+static struct v3_swintr_hook * swintr_hooks[256];
+
+static inline struct v3_swintr_hook * get_swintr_hook (struct guest_info * core, uint8_t vector) {
+ return swintr_hooks[vector];
+}
+
+
+static struct v3_extension_impl swintr_impl = {
+ .name = "swintr_intercept",
+ .init = init_swintr_intercept,
+ .deinit = NULL,
+ .core_init = init_swintr_intercept_core,
+ .core_deinit = NULL,
+ .on_entry = NULL,
+ .on_exit = NULL
+};
+
+
+register_extension(&swintr_impl);
+
+
+int v3_handle_swintr (struct guest_info * core) {
+
+ int ret = 0;
+ void * instr_ptr = NULL;
+ struct x86_instr instr;
+
+ if (core->mem_mode == PHYSICAL_MEM) {
+ ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
+ } else {
+ ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
+ }
+
+ if (ret == -1) {
+ PrintError("V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip);
+ return -1;
+ }
+
+ if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) {
+ PrintError("V3 SWintr Handler: Decoding Error\n");
+ return -1;
+ }
+
+ uint8_t vector = instr.dst_operand.operand;
+
+ struct v3_swintr_hook * hook = swintr_hooks[vector];
+ if (hook == NULL) {
+#ifdef V3_CONFIG_EXT_SWINTR_PASSTHROUGH
+ if (v3_hook_passthrough_swintr(core, vector) == -1) {
+ PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n");
+ return -1;
+ }
+ hook = swintr_hooks[vector];
+#else
+ core->rip += instr.instr_length;
+ return v3_raise_swintr(core, vector);
+#endif
+ }
+
+ ret = hook->handler(core, vector, NULL);
+ if (ret == -1) {
+ PrintDebug("V3 SWintr Handler: Error in swintr hook\n");
+ return -1;
+ }
+
+#ifdef V3_CONFIG_EXT_CODE_INJECT
+// this is for injecting page faults
+// we don't want to increment rip or inject
+// the swint if we need to fault a page in
+ if (ret == E_NEED_PF) {
+ return 0;
+ }
+#endif
+ /* at some point we _may_ need to prioritize swints
+ so that they finish in time for the next
+ instruction... */
+ core->rip += instr.instr_length;
+ return v3_raise_swintr(core, vector);
+}
+
+
+
+int v3_hook_swintr (struct guest_info * core,
+ uint8_t vector,
+ int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
+ void * priv_data)
+{
+ struct v3_swintr_hook * hook = (struct v3_swintr_hook*)V3_Malloc(sizeof(struct v3_swintr_hook));
+
+ if (hook == NULL) {
+ return -1;
+ }
+
+ if (get_swintr_hook(core, vector) != NULL) {
+ PrintError("swint %d already hooked\n", vector);
+ return -1;
+ }
+
+ hook->handler = handler;
+ hook->priv_data = priv_data;
+
+ swintr_hooks[vector] = hook;
+
+ PrintDebug("Hooked Swintr #%d\n", vector);
+
+ return 0;
+}
+
+
+static int passthrough_swintr_handler (struct guest_info * core, uint8_t vector, void * priv_data) {
+ PrintDebug("[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n",
+ vector, (void*)core);
+ return 0;
+}
+
+
+int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector) {
+
+ int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL);
+
+ if (rc) {
+ PrintError("guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void*)core);
+ return -1;
+ } else {
+ PrintDebug("guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void*)core);
+ return 0;
+ }
+
+ /* shouldn't get here */
+ return 0;
+}
+
+
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Kyle C. Hale <kh@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_intr.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vmm_string.h>
+#include <palacios/vmm_shadow_paging.h>
+#include <palacios/vmm_extensions.h>
+#include <palacios/vmm_paging.h>
+#include <palacios/vmcb.h>
+#include <palacios/vmm_hypercall.h>
+
+
+#include <gears/syscall_hijack.h>
+#include <gears/sw_intr.h>
+#include <gears/syscall_ref.h>
+
+#ifdef V3_CONFIG_EXT_CODE_INJECT
+#include <gears/code_inject.h>
+#include <palacios/vmm_list.h>
+extern struct v3_code_injects code_injects;
+#endif
+
+#ifndef V3_CONFIG_DEBUG_EXT_SYSCALL_HIJACK
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+
+struct v3_syscall_hook {
+ int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data);
+ void * priv_data;
+};
+
+static struct v3_syscall_hook * syscall_hooks[512];
+
+#if defined(V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT) || defined(V3_CONFIG_EXT_SYSCALL_INSTR)
+static struct v3_syscall_info syscall_info;
+#endif
+
+static void print_arg (struct guest_info * core, v3_reg_t reg, uint8_t argnum) {
+
+ addr_t hva;
+ int ret = 0;
+
+ PrintDebug("\t ARG%d: INT - %ld\n", argnum, (long) reg);
+
+ if (core->mem_mode == PHYSICAL_MEM) {
+ ret = v3_gpa_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva);
+ }
+ else {
+ ret = v3_gva_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva);
+ }
+
+ PrintDebug("\t STR - ");
+ if (ret == -1) {
+ PrintDebug("\n");
+ return;
+ }
+
+ uint32_t c = max(MAX_CHARS, 4096 - (hva % 4096));
+ int i = 0;
+ for (; i < c && *((char*)(hva + i)) != 0; i++) {
+ PrintDebug("%c", *((char*)(hva + i)));
+ }
+ PrintDebug("\n");
+}
+
+
+static void print_syscall (uint8_t is64, struct guest_info * core) {
+
+ if (is64) {
+ PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name64(core->vm_regs.rax));
+ } else {
+ PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name32(core->vm_regs.rax));
+ }
+
+ print_arg(core, core->vm_regs.rbx, 1);
+ print_arg(core, core->vm_regs.rcx, 2);
+ print_arg(core, core->vm_regs.rdx, 3);
+}
+
+
+int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data) {
+
+ uint_t syscall_nr = (uint_t) core->vm_regs.rax;
+ int err = 0, ret = 0;
+
+ struct v3_syscall_hook * hook = syscall_hooks[syscall_nr];
+
+#ifdef V3_CONFIG_EXT_SYSCALL_INSTR
+ // address originally written to LSTAR
+ if (!vector)
+ core->rip = syscall_info.target_addr;
+#endif
+
+#ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT
+ PrintDebug("In v3_syscall_handler: syscall_nr - %d\n", syscall_nr);
+#endif
+
+
+ if (hook == NULL) {
+#ifdef V3_CONFIG_EXT_SYSCALL_PASSTHROUGH
+ if (v3_hook_passthrough_syscall(core, syscall_nr) == -1) {
+ PrintDebug("Error hooking passthrough syscall\n");
+ return -1;
+ }
+ hook = syscall_hooks[syscall_nr];
+#endif
+
+/*
+ * if this syscall isn't hooked, pop off a pending inject
+ * and run it
+ */
+#ifdef V3_CONFIG_EXT_CODE_INJECT
+ struct v3_code_injects * injects = &code_injects;
+ struct v3_code_inject_info * inject = NULL;
+
+ if (list_empty(&(injects->code_inject_list))) {
+ return 0;
+ } else {
+
+ inject = (struct v3_code_inject_info*) list_first_entry(
+ &(injects->code_inject_list),
+ struct v3_code_inject_info,
+ inject_node);
+
+ if (inject == NULL) {
+ PrintError("Problem getting inject from inject list\n");
+ return -1;
+ }
+
+ if (inject->in_progress)
+ return 0;
+
+ // do the inject and don't fall over if there's an inject already in
+ // progress
+ if ((ret = v3_handle_guest_inject(core, (void*)inject)) == -1) {
+ PrintError("Could not run code injection: v3_syscall_handler\n");
+ return 0;
+ } else {
+ return ret;
+ }
+ }
+#else
+ return 0;
+#endif
+ }
+
+ err = hook->handler(core, syscall_nr, hook->priv_data);
+ if (err == -1) {
+ PrintDebug("V3 Syscall Handler: Error in syscall hook\n");
+ return -1;
+ }
+
+#ifdef V3_CONFIG_EXT_CODE_INJECT
+ if (err == E_NEED_PF)
+ return E_NEED_PF;
+#endif
+ return 0;
+}
+
+
+#ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT
+static int v3_handle_lstar_write (struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+ syscall_info.target_addr = (uint64_t) ((((uint64_t)src.hi) << 32) | src.lo);
+
+ PrintDebug("LSTAR Write: %p\n", (void*)syscall_info.target_addr);
+ core->ctrl_regs.lstar = syscall_info.target_addr;
+ return 0;
+}
+
+
+// virtualize the lstar
+static int v3_handle_lstar_read (struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
+ PrintDebug("LSTAR Read\n");
+ dst->value = syscall_info.target_addr;
+ return 0;
+}
+
+
+static int syscall_setup (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
+ addr_t syscall_stub, syscall_map, ssa;
+
+ syscall_stub = (addr_t)core->vm_regs.rbx;
+ syscall_map = (addr_t)core->vm_regs.rcx;
+ ssa = (addr_t)core->vm_regs.rdx;
+
+ PrintDebug("made it to syscall setup hypercall\n");
+ PrintDebug("\t&syscall_stub (rbx): %p\n\t&syscall_map (rcx): %p\n", (void*)syscall_stub, (void*)syscall_map);
+ PrintDebug("\t&ssa (rdx): %p\n", (void*)ssa);
+
+ syscall_info.syscall_stub = syscall_stub;
+ syscall_info.syscall_map = (uint8_t*)syscall_map;
+ syscall_info.ssa = ssa;
+
+ /* return the original syscall entry point */
+ core->vm_regs.rax = syscall_info.target_addr;
+
+ /* redirect syscalls henceforth */
+ core->ctrl_regs.lstar = syscall_stub;
+ return 0;
+}
+
+
+static int syscall_cleanup (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
+
+ core->ctrl_regs.lstar = syscall_info.target_addr;
+ PrintDebug("original syscall entry point restored\n");
+ return 0;
+}
+
+
+static int sel_syscall_handle (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
+ int ret;
+ addr_t hva;
+ struct v3_gprs regs;
+
+ PrintDebug("caught a selectively exited syscall!\n");
+ ret = v3_gva_to_hva(core, get_addr_linear(core, syscall_info.ssa, &(core->segments.ds)), &hva);
+ if (ret == -1) {
+ PrintError("Problem translating state save area address in sel_syscall_handle\n");
+ return -1;
+ }
+
+ /* setup registers for handler routines. They should be in the same state
+ * as when the system call was originally invoked */
+ memcpy((void*)®s, (void*)&core->vm_regs, sizeof(struct v3_gprs));
+ memcpy((void*)&core->vm_regs, (void*)hva, sizeof(struct v3_gprs));
+
+ v3_print_guest_state(core);
+
+ // TODO: call syscall-independent handler
+
+ memcpy((void*)hva, (void*)&core->vm_regs, sizeof(struct v3_gprs));
+ memcpy((void*)&core->vm_regs, (void*)®s,sizeof(struct v3_gprs));
+ return 0;
+}
+
+
+#endif
+
+static int init_syscall_hijack (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
+#ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT
+ v3_register_hypercall(vm, 0x5CA11, sel_syscall_handle, NULL);
+ v3_register_hypercall(vm, 0x5CA12, syscall_setup, NULL);
+ v3_register_hypercall(vm, 0x5CA13, syscall_cleanup, NULL);
+#endif
+ return 0;
+}
+
+
+
+#ifdef V3_CONFIG_EXT_SYSCALL_INSTR
+static int v3_handle_lstar_write (struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
+ PrintDebug("KCH: LSTAR Write\n");
+ //PrintDebug("\tvalue: 0x%x%x\n", src.hi, src.lo);
+ syscall_info.target_addr = (uint64_t) ((((uint64_t)src.hi) << 32) | src.lo);
+
+ // Set LSTAR value seen by hardware while the guest is running
+ PrintDebug("replacing with %lx\n", SYSCALL_MAGIC_ADDR);
+ core->ctrl_regs.lstar = SYSCALL_MAGIC_ADDR;
+ return 0;
+}
+
+static int v3_handle_lstar_read (struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
+ PrintDebug("KCH: LSTAR Read\n");
+ dst->value = syscall_info.target_addr;
+ return 0;
+}
+#endif
+
+
+static int init_syscall_hijack_core (struct guest_info * core, void * priv_data) {
+
+#ifdef V3_CONFIG_EXT_SW_INTERRUPTS
+ v3_hook_swintr(core, SYSCALL_INT_VECTOR, v3_syscall_handler, NULL);
+#endif
+
+#if defined(V3_CONFIG_EXT_SYSCALL_INSTR) || defined(V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT)
+ v3_hook_msr(core->vm_info, LSTAR_MSR,
+ &v3_handle_lstar_read,
+ &v3_handle_lstar_write,
+ core);
+#endif
+
+ return 0;
+}
+
+static int deinit_syscall_hijack (struct v3_vm_info * vm, void * priv_data) {
+ return 0;
+}
+
+
+static struct v3_extension_impl syscall_impl = {
+ .name = "syscall_intercept",
+ .init = init_syscall_hijack,
+ .deinit = deinit_syscall_hijack,
+ .core_init = init_syscall_hijack_core,
+ .core_deinit = NULL,
+ .on_entry = NULL,
+ .on_exit = NULL
+};
+
+register_extension(&syscall_impl);
+
+
+static inline struct v3_syscall_hook * get_syscall_hook (struct guest_info * core, uint_t syscall_nr) {
+ return syscall_hooks[syscall_nr];
+}
+
+
+int v3_hook_syscall (struct guest_info * core,
+ uint_t syscall_nr,
+ int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data),
+ void * priv_data)
+{
+ struct v3_syscall_hook * hook = (struct v3_syscall_hook *)V3_Malloc(sizeof(struct v3_syscall_hook));
+
+
+ if (hook == NULL) {
+ return -1;
+ }
+
+ if (get_syscall_hook(core, syscall_nr) != NULL) {
+ PrintError("System Call #%d already hooked\n", syscall_nr);
+ return -1;
+ }
+
+ hook->handler = handler;
+ hook->priv_data = priv_data;
+
+ syscall_hooks[syscall_nr] = hook;
+
+ PrintDebug("Hooked Syscall #%d\n", syscall_nr);
+
+ return 0;
+}
+
+
+static int passthrough_syscall_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
+ print_syscall(core->cpu_mode == LONG, core);
+ return 0;
+}
+
+
+int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr) {
+
+ int rc = v3_hook_syscall(core, syscall_nr, passthrough_syscall_handler, NULL);
+
+ if (rc) {
+ PrintError("failed to hook syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core);
+ return -1;
+ } else {
+ PrintDebug("hooked syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core);
+ return 0;
+ }
+
+ /* shouldn't get here */
+ return 0;
+}
+
+
+
+char * get_linux_syscall_name32 (uint_t syscall_nr) {
+
+ switch (syscall_nr) {
+
+ case 0: return "restart_syscall"; break;
+ case 1: return "exit"; break;
+ case 2: return "fork"; break;
+ case 3: return "read"; break;
+ case 4: return "write"; break;
+ case 5: return "open"; break;
+ case 6: return "close"; break;
+ case 7: return "waitpid"; break;
+ case 8: return "creat"; break;
+ case 9: return "link"; break;
+ case 10: return "unlink"; break;
+ case 11: return "execve"; break;
+ case 12: return "chdir"; break;
+ case 13: return "time"; break;
+ case 14: return "mknod"; break;
+ case 15: return "chmod"; break;
+ case 16: return "lchown"; break;
+ case 17: return "break"; break;
+ case 18: return "oldstat"; break;
+ case 19: return "lseek"; break;
+ case 20: return "getpid"; break;
+ case 21: return "mount"; break;
+ case 22: return "umount"; break;
+ case 23: return "setuid"; break;
+ case 24: return "getuid"; break;
+ case 25: return "stime"; break;
+ case 26: return "ptrace"; break;
+ case 27: return "alarm"; break;
+ case 28: return "oldfstat"; break;
+ case 29: return "pause"; break;
+ case 30: return "utime"; break;
+ case 31: return "stty"; break;
+ case 32: return "gtty"; break;
+ case 33: return "access"; break;
+ case 34: return "nice"; break;
+ case 35: return "ftime"; break;
+ case 36: return "sync"; break;
+ case 37: return "kill"; break;
+ case 38: return "rename"; break;
+ case 39: return "mkdir"; break;
+ case 40: return "rmdir"; break;
+ case 41: return "dup"; break;
+ case 42: return "pipe"; break;
+ case 43: return "times"; break;
+ case 44: return "prof"; break;
+ case 45: return "brk"; break;
+ case 46: return "setgid"; break;
+ case 47: return "getgid"; break;
+ case 48: return "signal"; break;
+ case 49: return "geteuid"; break;
+ case 50: return "getegid"; break;
+ case 51: return "acct"; break;
+ case 52: return "umount2"; break;
+ case 53: return "lock"; break;
+ case 54: return "ioctl"; break;
+ case 55: return "fcntl"; break;
+ case 56: return "mpx"; break;
+ case 57: return "setpgid"; break;
+ case 58: return "ulimit"; break;
+ case 59: return "oldolduname"; break;
+ case 60: return "umask"; break;
+ case 61: return "chroot"; break;
+ case 62: return "ustat"; break;
+ case 63: return "dup2"; break;
+ case 64: return "getppid"; break;
+ case 65: return "getpgrp"; break;
+ case 66: return "setsid"; break;
+ case 67: return "sigaction"; break;
+ case 68: return "sgetmask"; break;
+ case 69: return "ssetmask"; break;
+ case 70: return "setreuid"; break;
+ case 71: return "setregid"; break;
+ case 72: return "sigsuspend"; break;
+ case 73: return "sigpending"; break;
+ case 74: return "sethostname"; break;
+ case 75: return "setrlimit"; break;
+ case 76: return "getrlimit"; break;
+ case 77: return "getrusage"; break;
+ case 78: return "gettimeofday"; break;
+ case 79: return "settimeofday"; break;
+ case 80: return "getgroups"; break;
+ case 81: return "setgroups"; break;
+ case 82: return "select"; break;
+ case 83: return "symlink"; break;
+ case 84: return "oldlstat"; break;
+ case 85: return "readlink"; break;
+ case 86: return "uselib"; break;
+ case 87: return "swapon"; break;
+ case 88: return "reboot"; break;
+ case 89: return "readdir"; break;
+ case 90: return "mmap"; break;
+ case 91: return "munmap"; break;
+ case 92: return "truncate"; break;
+ case 93: return "ftruncate"; break;
+ case 94: return "fchmod"; break;
+ case 95: return "fchown"; break;
+ case 96: return "getpriority"; break;
+ case 97: return "setpriority"; break;
+ case 98: return "profil"; break;
+ case 99: return "statfs"; break;
+ case 100: return "fstatfs"; break;
+ case 101: return "ioperm"; break;
+ case 102: return "socketcall"; break;
+ case 103: return "syslog"; break;
+ case 104: return "setitimer"; break;
+ case 105: return "getitimer"; break;
+ case 106: return "stat"; break;
+ case 107: return "lstat"; break;
+ case 108: return "fstat"; break;
+ case 109: return "olduname"; break;
+ case 110: return "iopl"; break;
+ case 111: return "vhangup"; break;
+ case 112: return "idle"; break;
+ case 113: return "vm86old"; break;
+ case 114: return "wait4"; break;
+ case 115: return "swapoff"; break;
+ case 116: return "sysinfo"; break;
+ case 117: return "ipc"; break;
+ case 118: return "fsync"; break;
+ case 119: return "sigreturn"; break;
+ case 120: return "clone"; break;
+ case 121: return "setdomainname"; break;
+ case 122: return "uname"; break;
+ case 123: return "modify_ldt"; break;
+ case 124: return "adjtimex"; break;
+ case 125: return "mprotect"; break;
+ case 126: return "sigprocmask"; break;
+ case 127: return "create_module"; break;
+ case 128: return "init_module"; break;
+ case 129: return "delete_module"; break;
+ case 130: return "get_kernel_syms"; break;
+ case 131: return "quotactl"; break;
+ case 132: return "getpgid"; break;
+ case 133: return "fchdir"; break;
+ case 134: return "bdflush"; break;
+ case 135: return "sysfs"; break;
+ case 136: return "personality"; break;
+ case 137: return "afs_syscall"; break;
+ case 138: return "setfsuid"; break;
+ case 139: return "setfsgid"; break;
+ case 140: return "_llseek"; break;
+ case 141: return "getdents"; break;
+ case 142: return "_newselect"; break;
+ case 143: return "flock"; break;
+ case 144: return "msync"; break;
+ case 145: return "readv"; break;
+ case 146: return "writev"; break;
+ case 147: return "getsid"; break;
+ case 148: return "fdatasync"; break;
+ case 149: return "_sysctl"; break;
+ case 150: return "mlock"; break;
+ case 151: return "munlock"; break;
+ case 152: return "mlockall"; break;
+ case 153: return "munlockall"; break;
+ case 154: return "sched_setparam"; break;
+ case 155: return "sched_getparam"; break;
+ case 156: return "sched_setscheduler"; break;
+ case 157: return "sched_getscheduler"; break;
+ case 158: return "sched_yield"; break;
+ case 159: return "sched_get_priority_max"; break;
+ case 160: return "sched_get_priority_min"; break;
+ case 161: return "sched_rr_get_interval"; break;
+ case 162: return "nanosleep"; break;
+ case 163: return "mremap"; break;
+ case 164: return "setresuid"; break;
+ case 165: return "getresuid"; break;
+ case 166: return "vm86"; break;
+ case 167: return "query_module"; break;
+ case 168: return "poll"; break;
+ case 169: return "nfsservctl"; break;
+ case 170: return "setresgid"; break;
+ case 171: return "getresgid"; break;
+ case 172: return "prctl"; break;
+ case 173: return "rt_sigreturn"; break;
+ case 174: return "rt_sigaction"; break;
+ case 175: return "rt_sigprocmask"; break;
+ case 176: return "rt_sigpending"; break;
+ case 177: return "rt_sigtimedwait"; break;
+ case 178: return "rt_sigqueueinfo"; break;
+ case 179: return "rt_sigsuspend"; break;
+ case 180: return "pread64"; break;
+ case 181: return "pwrite64"; break;
+ case 182: return "chown"; break;
+ case 183: return "getcwd"; break;
+ case 184: return "capget"; break;
+ case 185: return "capset"; break;
+ case 186: return "sigaltstack"; break;
+ case 187: return "sendfile"; break;
+ case 188: return "getpmsg"; break;
+ case 189: return "putpmsg"; break;
+ case 190: return "vfork"; break;
+ case 191: return "ugetrlimit"; break;
+ case 192: return "mmap2"; break;
+ case 193: return "truncate64"; break;
+ case 194: return "ftruncate64"; break;
+ case 195: return "stat64"; break;
+ case 196: return "lstat64"; break;
+ case 197: return "fstat64"; break;
+ case 198: return "lchown32"; break;
+ case 199: return "getuid32"; break;
+ case 200: return "getgid32"; break;
+ case 201: return "geteuid32"; break;
+ case 202: return "getegid32"; break;
+ case 203: return "setreuid32"; break;
+ case 204: return "setregid32"; break;
+ case 205: return "getgroups32"; break;
+ case 206: return "setgroups32"; break;
+ case 207: return "fchown32"; break;
+ case 208: return "setresuid32"; break;
+ case 209: return "getresuid32"; break;
+ case 210: return "setresgid32"; break;
+ case 211: return "getresgid32"; break;
+ case 212: return "chown32"; break;
+ case 213: return "setuid32"; break;
+ case 214: return "setgid32"; break;
+ case 215: return "setfsuid32"; break;
+ case 216: return "setfsgid32"; break;
+ case 217: return "pivot_root"; break;
+ case 218: return "mincore"; break;
+ case 219: return "madvise1"; break;
+ case 220: return "getdents64"; break;
+ case 221: return "fcntl64"; break;
+ case 224: return "gettid"; break;
+ case 225: return "readahead"; break;
+ case 226: return "setxattr"; break;
+ case 227: return "lsetxattr"; break;
+ case 228: return "fsetxattr"; break;
+ case 229: return "getxattr"; break;
+ case 230: return "lgetxattr"; break;
+ case 231: return "fgetxattr"; break;
+ case 232: return "listxattr"; break;
+ case 233: return "llistxattr"; break;
+ case 234: return "flistxattr"; break;
+ case 235: return "removexattr"; break;
+ case 236: return "lremovexattr"; break;
+ case 237: return "fremovexattr"; break;
+ case 238: return "tkill"; break;
+ case 239: return "sendfile64"; break;
+ case 240: return "futex"; break;
+ case 241: return "sched_setaffinity"; break;
+ case 242: return "sched_getaffinity"; break;
+ case 243: return "set_thread_area"; break;
+ case 244: return "get_thread_area"; break;
+ case 245: return "io_setup"; break;
+ case 246: return "io_destroy"; break;
+ case 247: return "io_getevents"; break;
+ case 248: return "io_submit"; break;
+ case 249: return "io_cancel"; break;
+ case 250: return "fadvise64"; break;
+ case 252: return "exit_group"; break;
+ case 253: return "lookup_dcookie"; break;
+ case 254: return "epoll_create"; break;
+ case 255: return "epoll_ctl"; break;
+ case 256: return "epoll_wait"; break;
+ case 257: return "remap_file_pages"; break;
+ case 258: return "set_tid_address"; break;
+ case 259: return "timer_create"; break;
+ case 260: return "timer_settime"; break;
+ case 261: return "timer_gettime"; break;
+ case 262: return "timer_getoverrun"; break;
+ case 263: return "timer_delete"; break;
+ case 264: return "clock_settime"; break;
+ case 265: return "clock_gettime"; break;
+ case 266: return "clock_getres"; break;
+ case 267: return "clock_nanosleep"; break;
+ case 268: return "statfs64"; break;
+ case 269: return "fstatfs64"; break;
+ case 270: return "tgkill"; break;
+ case 271: return "utimes"; break;
+ case 272: return "fadvise64_64"; break;
+ case 273: return "vserver"; break;
+ case 274: return "mbind"; break;
+ case 275: return "get_mempolicy"; break;
+ case 276: return "set_mempolicy"; break;
+ case 277: return "mq_open"; break;
+ case 278: return "mq_unlink"; break;
+ case 279: return "mq_timedsend"; break;
+ case 280: return "mq_timedreceive"; break;
+ case 281: return "mq_notify"; break;
+ case 282: return "mq_getsetattr"; break;
+ case 283: return "kexec_load"; break;
+ case 284: return "waitid"; break;
+ case 285: return "sys_setaltroot"; break;
+ case 286: return "add_key"; break;
+ case 287: return "request_key"; break;
+ case 288: return "keyctl"; break;
+ case 289: return "ioprio_set"; break;
+ case 290: return "ioprio_get"; break;
+ case 291: return "inotify_init"; break;
+ case 292: return "inotify_add_watch"; break;
+ case 293: return "inotify_rm_watch"; break;
+ case 294: return "migrate_pages"; break;
+ case 295: return "openat"; break;
+ case 296: return "mkdirat"; break;
+ case 297: return "mknodat"; break;
+ case 298: return "fchownat"; break;
+ case 299: return "futimesat"; break;
+ case 300: return "fstatat64"; break;
+ case 301: return "unlinkat"; break;
+ case 302: return "renameat"; break;
+ case 303: return "linkat"; break;
+ case 304: return "symlinkat"; break;
+ case 305: return "readlinkat"; break;
+ case 306: return "fchmodat"; break;
+ case 307: return "faccessat"; break;
+ case 308: return "pselect6"; break;
+ case 309: return "ppoll"; break;
+ case 310: return "unshare"; break;
+ case 311: return "set_robust_list"; break;
+ case 312: return "get_robust_list"; break;
+ case 313: return "splice"; break;
+ case 314: return "sync_file_range"; break;
+ case 315: return "tee"; break;
+ case 316: return "vmsplice"; break;
+ case 317: return "move_pages"; break;
+ case 318: return "getcpu"; break;
+ case 319: return "epoll_pwait"; break;
+ case 320: return "utimensat"; break;
+ case 321: return "signalfd"; break;
+ case 322: return "timerfd_create"; break;
+ case 323: return "eventfd"; break;
+ case 324: return "fallocate"; break;
+ case 325: return "timerfd_settime"; break;
+ case 326: return "timerfd_gettime"; break;
+ case 327: return "signalfd4"; break;
+ case 328: return "eventfd2"; break;
+ case 329: return "epoll_create1"; break;
+ case 330: return "dup3"; break;
+ case 331: return "pipe2"; break;
+ case 332: return "inotify_init1"; break;
+ case 333: return "preadv"; break;
+ case 334: return "pwritev"; break;
+ case 335: return "rt_tgsigqueueinfo"; break;
+ case 336: return "perf_event_open"; break;
+ default: return "UNKNOWN"; break;
+ }
+}
+
+
+char * get_linux_syscall_name64 (uint_t syscall_nr) {
+
+ switch (syscall_nr) {
+
+ case 0: return "read"; break;
+ case 1: return "write"; break;
+ case 2: return "open"; break;
+ case 3: return "close"; break;
+ case 4: return "stat"; break;
+ case 5: return "fstat"; break;
+ case 6: return "lstat"; break;
+ case 7: return "poll"; break;
+ case 8: return "lseek"; break;
+ case 9: return "mmap"; break;
+ case 10: return "mprotect"; break;
+ case 11: return "munmap"; break;
+ case 12: return "brk"; break;
+ case 13: return "rt_sigaction"; break;
+ case 14: return "rt_sigprocmask"; break;
+ case 15: return "rt_sigreturn"; break;
+ case 16: return "ioctl"; break;
+ case 17: return "pread64"; break;
+ case 18: return "pwrite64"; break;
+ case 19: return "readv"; break;
+ case 20: return "writev"; break;
+ case 21: return "access"; break;
+ case 22: return "pipe"; break;
+ case 23: return "select"; break;
+ case 24: return "sched_yield"; break;
+ case 25: return "mremap"; break;
+ case 26: return "msync"; break;
+ case 27: return "mincore"; break;
+ case 28: return "madvise"; break;
+ case 29: return "shmget"; break;
+ case 30: return "shmat"; break;
+ case 31: return "shmctl"; break;
+ case 32: return "dup"; break;
+ case 33: return "dup2"; break;
+ case 34: return "pause"; break;
+ case 35: return "nanosleep"; break;
+ case 36: return "getitimer"; break;
+ case 37: return "alarm"; break;
+ case 38: return "setitimer"; break;
+ case 39: return "getpid"; break;
+ case 40: return "sendfile"; break;
+ case 41: return "socket"; break;
+ case 42: return "connect"; break;
+ case 43: return "accept"; break;
+ case 44: return "sendto"; break;
+ case 45: return "recvfrom"; break;
+ case 46: return "sendmsg"; break;
+ case 47: return "recvmsg"; break;
+ case 48: return "shutdown"; break;
+ case 49: return "bind"; break;
+ case 50: return "listen"; break;
+ case 51: return "getsockname"; break;
+ case 52: return "getpeername"; break;
+ case 53: return "socketpair"; break;
+ case 54: return "setsockopt"; break;
+ case 55: return "getsockopt"; break;
+ case 56: return "clone"; break;
+ case 57: return "fork"; break;
+ case 58: return "vfork"; break;
+ case 59: return "execve"; break;
+ case 60: return "exit"; break;
+ case 61: return "wait4"; break;
+ case 62: return "kill"; break;
+ case 63: return "uname"; break;
+ case 64: return "semget"; break;
+ case 65: return "semop"; break;
+ case 66: return "semctl"; break;
+ case 67: return "shmdt"; break;
+ case 68: return "msgget"; break;
+ case 69: return "msgsnd"; break;
+ case 70: return "msgrcv"; break;
+ case 71: return "msgctl"; break;
+ case 72: return "fcntl"; break;
+ case 73: return "flock"; break;
+ case 74: return "fsync"; break;
+ case 75: return "fdatasync"; break;
+ case 76: return "truncate"; break;
+ case 77: return "ftruncate"; break;
+ case 78: return "getdents"; break;
+ case 79: return "getcwd"; break;
+ case 80: return "chdir"; break;
+ case 81: return "fchdir"; break;
+ case 82: return "rename"; break;
+ case 83: return "mkdir"; break;
+ case 84: return "rmdir"; break;
+ case 85: return "creat"; break;
+ case 86: return "link"; break;
+ case 87: return "unlink"; break;
+ case 88: return "symlink"; break;
+ case 89: return "readlink"; break;
+ case 90: return "chmod"; break;
+ case 91: return "fchmod"; break;
+ case 92: return "chown"; break;
+ case 93: return "fchown"; break;
+ case 94: return "lchown"; break;
+ case 95: return "umask"; break;
+ case 96: return "gettimeofday"; break;
+ case 97: return "getrlimit"; break;
+ case 98: return "getrusage"; break;
+ case 99: return "sysinfo"; break;
+ case 100: return "times"; break;
+ case 101: return "ptrace"; break;
+ case 102: return "getuid"; break;
+ case 103: return "syslog"; break;
+ case 104: return "getgid"; break;
+ case 105: return "setuid"; break;
+ case 106: return "setgid"; break;
+ case 107: return "geteuid"; break;
+ case 108: return "getegid"; break;
+ case 109: return "setpgid"; break;
+ case 110: return "getppid"; break;
+ case 111: return "getpgrp"; break;
+ case 112: return "setsid"; break;
+ case 113: return "setreuid"; break;
+ case 114: return "setregid"; break;
+ case 115: return "getgroups"; break;
+ case 116: return "setgroups"; break;
+ case 117: return "setresuid"; break;
+ case 118: return "getresuid"; break;
+ case 119: return "setresgid"; break;
+ case 120: return "getresgid"; break;
+ case 121: return "getpgid"; break;
+ case 122: return "setfsuid"; break;
+ case 123: return "setfsgid"; break;
+ case 124: return "getsid"; break;
+ case 125: return "capget"; break;
+ case 126: return "capset"; break;
+ case 127: return "rt_sigpending"; break;
+ case 128: return "rt_sigtimedwait"; break;
+ case 129: return "rt_sigqueueinfo"; break;
+ case 130: return "rt_sigsuspend"; break;
+ case 131: return "sigaltstack"; break;
+ case 132: return "utime"; break;
+ case 133: return "mknod"; break;
+ case 134: return "uselib"; break;
+ case 135: return "personality"; break;
+ case 136: return "ustat"; break;
+ case 137: return "statfs"; break;
+ case 138: return "fstatfs"; break;
+ case 139: return "sysfs"; break;
+ case 140: return "getpriority"; break;
+ case 141: return "setpriority"; break;
+ case 142: return "sched_setparam"; break;
+ case 143: return "sched_getparam"; break;
+ case 144: return "sched_setscheduler"; break;
+ case 145: return "sched_getscheduler"; break;
+ case 146: return "sched_get_priority_max"; break;
+ case 147: return "sched_get_priority_min"; break;
+ case 148: return "sched_rr_get_interval"; break;
+ case 149: return "mlock"; break;
+ case 150: return "munlock"; break;
+ case 151: return "mlockall"; break;
+ case 152: return "munlockall"; break;
+ case 153: return "vhangup"; break;
+ case 154: return "modify_ldt"; break;
+ case 155: return "pivot_root"; break;
+ case 156: return "_sysctl"; break;
+ case 157: return "prctl"; break;
+ case 158: return "arch_prctl"; break;
+ case 159: return "adjtimex"; break;
+ case 160: return "setrlimit"; break;
+ case 161: return "chroot"; break;
+ case 162: return "sync"; break;
+ case 163: return "acct"; break;
+ case 164: return "settimeofday"; break;
+ case 165: return "mount"; break;
+ case 166: return "umount2"; break;
+ case 167: return "swapon"; break;
+ case 168: return "swapoff"; break;
+ case 169: return "reboot"; break;
+ case 170: return "sethostname"; break;
+ case 171: return "setdomainname"; break;
+ case 172: return "iopl"; break;
+ case 173: return "ioperm"; break;
+ case 174: return "create_module"; break;
+ case 175: return "init_module"; break;
+ case 176: return "delete_module"; break;
+ case 177: return "get_kernel_syms"; break;
+ case 178: return "query_module"; break;
+ case 179: return "quotactl"; break;
+ case 180: return "nfsservctl"; break;
+ case 181: return "getpmsg"; break;
+ case 182: return "putpmsg"; break;
+ case 183: return "afs_syscall"; break;
+ case 184: return "tuxcall"; break;
+ case 185: return "security"; break;
+ case 186: return "gettid"; break;
+ case 187: return "readahead"; break;
+ case 188: return "setxattr"; break;
+ case 189: return "lsetxattr"; break;
+ case 190: return "fsetxattr"; break;
+ case 191: return "getxattr"; break;
+ case 192: return "lgetxattr"; break;
+ case 193: return "fgetxattr"; break;
+ case 194: return "listxattr"; break;
+ case 195: return "llistxattr"; break;
+ case 196: return "flistxattr"; break;
+ case 197: return "removexattr"; break;
+ case 198: return "lremovexattr"; break;
+ case 199: return "fremovexattr"; break;
+ case 200: return "tkill"; break;
+ case 201: return "time"; break;
+ case 202: return "futex"; break;
+ case 203: return "sched_setaffinity"; break;
+ case 204: return "sched_getaffinity"; break;
+ case 205: return "set_thread_area"; break;
+ case 206: return "io_setup"; break;
+ case 207: return "io_destroy"; break;
+ case 208: return "io_getevents"; break;
+ case 209: return "io_submit"; break;
+ case 210: return "io_cancel"; break;
+ case 211: return "get_thread_area"; break;
+ case 212: return "lookup_dcookie"; break;
+ case 213: return "epoll_create"; break;
+ case 214: return "epoll_ctl_old"; break;
+ case 215: return "epoll_wait_old"; break;
+ case 216: return "remap_file_pages"; break;
+ case 217: return "getdents64"; break;
+ case 218: return "set_tid_address"; break;
+ case 219: return "restart_syscall"; break;
+ case 220: return "semtimedop"; break;
+ case 221: return "fadvise64"; break;
+ case 222: return "timer_create"; break;
+ case 223: return "timer_settime"; break;
+ case 224: return "timer_gettime"; break;
+ case 225: return "timer_getoverrun"; break;
+ case 226: return "timer_delete"; break;
+ case 227: return "clock_settime"; break;
+ case 228: return "clock_gettime"; break;
+ case 229: return "clock_getres"; break;
+ case 230: return "clock_nanosleep"; break;
+ case 231: return "exit_group"; break;
+ case 232: return "epoll_wait"; break;
+ case 233: return "epoll_ctl"; break;
+ case 234: return "tgkill"; break;
+ case 235: return "utimes"; break;
+ case 236: return "vserver"; break;
+ case 237: return "mbind"; break;
+ case 238: return "set_mempolicy"; break;
+ case 239: return "get_mempolicy"; break;
+ case 240: return "mq_open"; break;
+ case 241: return "mq_unlink"; break;
+ case 242: return "mq_timedsend"; break;
+ case 243: return "mq_timedreceive"; break;
+ case 244: return "mq_notify"; break;
+ case 246: return "kexec_load"; break;
+ case 247: return "waitid"; break;
+ case 248: return "add_key"; break;
+ case 249: return "request_key"; break;
+ case 250: return "keyctl"; break;
+ case 251: return "ioprio_set"; break;
+ case 252: return "ioprio_get"; break;
+ case 253: return "inotify_init"; break;
+ case 254: return "inotify_add_watch"; break;
+ case 255: return "inotify_rm_watch"; break;
+ case 256: return "migrate_pages"; break;
+ case 257: return "openat"; break;
+ case 258: return "mkdirat"; break;
+ case 259: return "mknodat"; break;
+ case 260: return "fchownat"; break;
+ case 261: return "futimesat"; break;
+ case 262: return "newfstatat"; break;
+ case 263: return "unlinkat"; break;
+ case 264: return "renameat"; break;
+ case 265: return "linkat"; break;
+ case 266: return "symlinkat"; break;
+ case 267: return "readlinkat"; break;
+ case 268: return "fchmodat"; break;
+ case 269: return "faccessat"; break;
+ case 270: return "pselect6"; break;
+ case 271: return "ppoll"; break;
+ case 272: return "unshare"; break;
+ case 273: return "set_robust_list"; break;
+ case 274: return "get_robust_list"; break;
+ case 275: return "splice"; break;
+ case 276: return "tee"; break;
+ case 277: return "sync_file_range"; break;
+ case 278: return "vmsplice"; break;
+ case 279: return "move_pages"; break;
+ case 280: return "utimensat"; break;
+ case 281: return "epoll_pwait"; break;
+ case 282: return "signalfd"; break;
+ case 283: return "timerfd_create"; break;
+ case 284: return "eventfd"; break;
+ case 285: return "fallocate"; break;
+ case 286: return "timerfd_settime"; break;
+ case 287: return "timerfd_gettime"; break;
+ case 288: return "accept4"; break;
+ case 289: return "signalfd4"; break;
+ case 290: return "eventfd2"; break;
+ case 291: return "epoll_create1"; break;
+ case 292: return "dup3"; break;
+ case 293: return "pipe2"; break;
+ case 294: return "inotify_init1"; break;
+ case 295: return "preadv"; break;
+ case 296: return "pwritev"; break;
+ case 297: return "rt_tgsigqueueinfo"; break;
+ case 298: return "perf_event_open"; break;
+ default: return "UNKNOWN"; break;
+ }
+}