diff --git a/.gitignore b/.gitignore index 3ff5c78..8adee49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ phpspy *~ \#*\# -.\#* \ No newline at end of file +.\#* +out +.vs \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ab6e705 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required (VERSION 3.11) + +project ("phpspy") + +set(CMAKE_C_STANDARD 11) + +include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/vendor) +add_definitions(-DPHPSPY_WIN32) + +# pcre2 +include(FetchContent) +FetchContent_Declare( + pcre + GIT_REPOSITORY https://github.com/PCRE2Project/pcre2.git + GIT_TAG 6ae58beca071f13ccfed31d03b3f479ab520639b #pcre2-10.44 + GIT_SUBMODULES "" +) +FetchContent_MakeAvailable(pcre) + +add_executable(phpspy basic.c phpspy.c pgrep.c addr_objdump.c event_fout.c event_callgrind.c vendor/getopt.c) + +target_link_libraries(phpspy pcre2-posix) \ No newline at end of file diff --git a/addr_objdump.c b/addr_objdump.c index 881a0ea..da5ea4f 100644 --- a/addr_objdump.c +++ b/addr_objdump.c @@ -1,8 +1,12 @@ #include "phpspy.h" #include +#ifndef PHPSPY_WIN32 static int get_php_bin_path(pid_t pid, char *path_root, char *path); static int get_php_base_addr(pid_t pid, char *path_root, char *path, uint64_t *raddr); +#else +static int get_php_info(pid_t pid, char *php_bin_path, char *php_dll_path, uint64_t *raddr); +#endif static int get_symbol_offset(char *path_root, const char *symbol, uint64_t *raddr); static int popen_read_line(char *buf, size_t buf_size, char *cmd_fmt, ...); @@ -58,6 +62,7 @@ int get_symbol_addr(addr_memo_t *memo, pid_t pid, const char *symbol, uint64_t * php_bin_path = memo->php_bin_path; php_bin_path_root = memo->php_bin_path_root; php_base_addr = &memo->php_base_addr; +#ifndef PHPSPY_WIN32 if (*php_bin_path == '\0' && get_php_bin_path(pid, php_bin_path_root, php_bin_path) != 0) { return 1; } else if (*php_base_addr == 0 && get_php_base_addr(pid, php_bin_path_root, php_bin_path, php_base_addr) != 0) { @@ -65,10 +70,20 @@ int get_symbol_addr(addr_memo_t *memo, pid_t pid, const char *symbol, uint64_t * } else if (get_symbol_offset(php_bin_path_root, symbol, &addr_offset) != 0) { return 1; } +#else + char *php_dll_path = memo->php_dll_path; + if (*php_bin_path == '\0' && get_php_info(pid, php_bin_path, php_dll_path, php_base_addr) != 0) { + return 1; + } else if (get_symbol_offset(php_dll_path, symbol, &addr_offset) != 0) { + return 1; + } +#endif *raddr = *php_base_addr + addr_offset; return 0; } +#ifndef PHPSPY_WIN32 + static int get_php_bin_path(pid_t pid, char *path_root, char *path) { char buf[PHPSPY_STR_SIZE]; char libname[PHPSPY_STR_SIZE]; @@ -143,6 +158,64 @@ static int get_symbol_offset(char *path_root, const char *symbol, uint64_t *radd return 0; } +#else + +static int get_php_info(pid_t pid, char *php_bin_path, char *php_dll_path, uint64_t *raddr) { + HANDLE hModuleSnap = INVALID_HANDLE_VALUE; + MODULEENTRY32 me32; + + hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); + if (hModuleSnap == INVALID_HANDLE_VALUE) { + log_error("CreateToolhelp32Snapshot (of modules) failed. Error: %lu \n", GetLastError()); + return 1; + } + + me32.dwSize = sizeof(MODULEENTRY32); + + if (!Module32First(hModuleSnap, &me32)) { + printf("Module32First failed. Error: %lu \n", GetLastError()); + CloseHandle(hModuleSnap); // Clean the snapshot object. + return 1; + } + + do { + if (strncmp(me32.szModule, "php", 3) == 0 && strncmp(me32.szModule + 4, ".dll", 4) == 0) { + strncpy(php_dll_path, me32.szExePath, PHPSPY_STR_SIZE - 1); + *raddr = (uint64_t) me32.modBaseAddr; + } else if (strncmp(me32.szModule, "php.exe", 7) == 0 || strncmp(me32.szModule, "php-cgi.exe", 11) == 0) { + char *last_slash = strrchr(me32.szExePath, '\\'); + *last_slash = '\0'; + strncpy_s(php_bin_path, PHPSPY_STR_SIZE, me32.szExePath, sizeof(me32.szExePath) - 1); + strncat(php_bin_path, "\\php.exe", 8); + } + } while (Module32Next(hModuleSnap, &me32)); + + CloseHandle(hModuleSnap); + + return 0; +} + +static int get_symbol_offset(char *path_root, const char *symbol, uint64_t *raddr) { + char buf[PHPSPY_STR_SIZE]; + char arg_buf[PHPSPY_STR_SIZE]; + char hex_string[PHPSPY_STR_SIZE]; + char *cmd_fmt = "dumpbin /exports %s | findstr %s"; + + if (popen_read_line(buf, sizeof(buf), cmd_fmt, path_root, symbol) != 0) { + log_error("get_symbol_offset: Failed\n"); + return 1; + } + if (sscanf_s(buf, "%*s %*s %s", hex_string, sizeof(hex_string)) == -1) { + log_error("get_symbol_offset: sscanf_s Failed\n"); + return 1; + } + *raddr = strtoull(hex_string, NULL, 16); + return 0; +} + + +#endif + static int popen_read_line(char *buf, size_t buf_size, char *cmd_fmt, ...) { FILE *fp; char cmd[PHPSPY_STR_SIZE]; diff --git a/basic.c b/basic.c new file mode 100644 index 0000000..55e3505 --- /dev/null +++ b/basic.c @@ -0,0 +1,67 @@ +#include +#ifdef PHPSPY_WIN32 + +void nanosleep(struct timespec *ts, void *null) { + long ns = (ts->tv_sec * 1000000000UL) + (ts->tv_nsec * 1UL); + Sleep(ns / 1000000L); +} + +int asprintf(char **ret, char *fmt, ...) { + va_list arg; + int rv; + + va_start(arg, fmt); + rv = vsnprintf(NULL, 0, fmt, arg); + if (rv >= 0 && (*ret = malloc(rv + 1))) { + vsnprintf(*ret, rv + 1, fmt, arg); + } + else { + rv = rv < 0 ? rv : -1; + } + va_end(arg); + + return rv; +} + +int gettimeofday(struct timeval *p, void *z) +{ + union { + unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } _now; + + if (p) { + GetSystemTimeAsFileTime(&_now.ft); + _now.ns100 -= 116444736000000000ull; + _now.ns100 /= 10; + p->tv_sec = _now.ns100 / 1000000ul; + p->tv_usec = (long)(_now.ns100 % 1000000ul); + } + + return 0; +} + +int phpspy_thread_create(phpspy_thread_t *thread, phpspy_thread_attr_t *attr, phpspy_thread_func start_routine(void *), void* arg) +{ + *thread = (HANDLE*)_beginthreadex(attr, 0, start_routine, arg, 0, NULL); + if (*thread) { + return 0; + } else { + return (int)GetLastError(); + } +} + +int phpspy_cond_timedwait(phpspy_cond_t *cond, phpspy_mutex_t *mutex, const struct timespec *abstime) +{ + DWORD milliseconds = INFINITE; + if (abstime) { + milliseconds = abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000L; + } + if (SleepConditionVariableCS(cond, mutex, milliseconds)) { + return 0; + } else { + return (int)GetLastError(); + } +} + +#endif /* PHPSPY_WIN32 */ diff --git a/basic.h b/basic.h new file mode 100644 index 0000000..8c21e2f --- /dev/null +++ b/basic.h @@ -0,0 +1,118 @@ +#ifndef BASIC_H +#define BASIC_H + +#include +#include + +#ifndef PHPSPY_WIN32 +#define PHPSPY_PACK __attribute__((__packed__)) +#ifndef gettid +#define gettid() syscall(SYS_gettid) +#endif +#endif + + +#ifdef PHPSPY_WIN32 + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define popen _popen +#define pclose _pclose +#define dup _dup +#define dup2 _dup2 + +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#endif + +#define PHPSPY_PACK +#define gettid() GetCurrentThreadId() +#define getpid() GetCurrentProcessId() +#define PIPE_BUF 4096 + +struct timezone +{ + int tz_minuteswest; /* of Greenwich */ + int tz_dsttime; /* type of dst correction to apply */ +}; + +typedef uint32_t pid_t; +typedef __int64 ssize_t; + +void nanosleep(struct timespec *ts, void *null); +int asprintf(char** ret, char* fmt, ...); +int gettimeofday(struct timeval* p, void* z); + +#endif + + +/* Thread */ +#ifndef PHPSPY_WIN32 + +typedef pthread_t phpspy_thread_t; +typedef pthread_attr_t phpspy_thread_attr_t; +typedef void *phpspy_thread_func; +#define PHPSPY_THREAD_RETNULL NULL; + +typedef pthread_mutex_t phpspy_mutex_t; +typedef pthread_mutexattr_t phpspy_mutexattr_t; +typedef pthread_cond_t phpspy_cond_t; +typedef pthread_condattr_t phpspy_condattr_t; + +#define phpspy_thread_create pthread_create +#define phpspy_thread_wait pthread_join +#define phpspy_mutex_init pthread_mutex_init +#define phpspy_mutex_destroy pthread_mutex_destroy +#define phpspy_mutex_lock pthread_mutex_lock +#define phpspy_mutex_unlock pthread_mutex_unlock +#define phpspy_cond_init pthread_cond_init +#define phpspy_cond_destroy pthread_cond_destroy +#define phpspy_cond_timedwait pthread_cond_timedwait +#define phpspy_cond_signal pthread_cond_signal +#define phpspy_cond_broadcast pthread_cond_broadcast + +#define phpspy_atomic_add64(ptr, value) __atomic_add_fetch(ptr, value, __ATOMIC_SEQ_CST); + +#endif + + +#ifdef PHPSPY_WIN32 + +typedef HANDLE phpspy_thread_t; +typedef SECURITY_ATTRIBUTES phpspy_thread_attr_t; +typedef unsigned __stdcall phpspy_thread_func; +#define PHPSPY_THREAD_RETNULL 0; + +typedef CRITICAL_SECTION phpspy_mutex_t; +typedef void phpspy_mutexattr_t; +typedef CONDITION_VARIABLE phpspy_cond_t; +typedef void phpspy_condattr_t; + +int phpspy_thread_create(phpspy_thread_t* thread, phpspy_thread_attr_t* attr, phpspy_thread_func start_routine(void*), void* arg); +#define phpspy_thread_wait(thread, value_ptr) WaitForSingleObject(thread, INFINITE) +#define phpspy_mutex_init(mutex, attr) InitializeCriticalSection(mutex) +#define phpspy_mutex_destroy(mutex) DeleteCriticalSection(mutex) +#define phpspy_mutex_lock(mutex) EnterCriticalSection(mutex) +#define phpspy_mutex_unlock(mutex) LeaveCriticalSection(mutex) +#define phpspy_cond_init(cond, attr) InitializeConditionVariable(cond) +#define phpspy_cond_destroy(cond) (void)cond +int phpspy_cond_timedwait(phpspy_cond_t* cond, phpspy_mutex_t* mutex, const struct timespec* abstime); +#define phpspy_cond_signal(cond) WakeConditionVariable(cond) +#define phpspy_cond_broadcast(cond) WakeAllConditionVariable(cond) + +#define phpspy_atomic_add64(ptr, value) _InlineInterlockedAdd64(ptr, value); + +#endif +/* Thread */ + +#endif diff --git a/event_fout.c b/event_fout.c index 3875f41..5190e59 100644 --- a/event_fout.c +++ b/event_fout.c @@ -12,7 +12,7 @@ typedef struct event_handler_fout_udata_s { static int event_handler_fout_write(event_handler_fout_udata_t *udata); static int event_handler_fout_snprintf(char **s, size_t *n, size_t *ret_len, int repl_delim, const char *fmt, ...); static int event_handler_fout_open(int *fd); -static pthread_mutex_t event_handler_fout_mutex = PTHREAD_MUTEX_INITIALIZER; +static phpspy_mutex_t event_handler_fout_mutex; int event_handler_fout(struct trace_context_s *context, int event_type) { int rv, fd; @@ -39,6 +39,7 @@ int event_handler_fout(struct trace_context_s *context, int event_type) { udata->use_mutex = context->event_handler_opts != NULL && strchr(context->event_handler_opts, 'm') != NULL ? 1 : 0; context->event_udata = udata; + phpspy_mutex_init(&event_handler_fout_mutex, NULL); break; case PHPSPY_TRACE_EVENT_STACK_BEGIN: udata->cur = udata->buf; @@ -140,6 +141,7 @@ int event_handler_fout(struct trace_context_s *context, int event_type) { close(udata->fd); free(udata->buf); free(udata); + phpspy_mutex_destroy(&event_handler_fout_mutex); break; } return PHPSPY_OK; @@ -158,7 +160,7 @@ static int event_handler_fout_write(event_handler_fout_udata_t *udata) { } if (udata->use_mutex) { - pthread_mutex_lock(&event_handler_fout_mutex); + phpspy_mutex_lock(&event_handler_fout_mutex); } if (write(udata->fd, udata->buf, write_len) != write_len) { @@ -167,7 +169,7 @@ static int event_handler_fout_write(event_handler_fout_udata_t *udata) { } if (udata->use_mutex) { - pthread_mutex_unlock(&event_handler_fout_mutex); + phpspy_mutex_unlock(&event_handler_fout_mutex); } return rv; @@ -227,8 +229,11 @@ static int event_handler_fout_open(int *fd) { } else { path = opt_path_output; } - +#ifdef PHPSPY_WIN32 + tfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); +#else tfd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif errno_saved = errno; if (apath) { diff --git a/pgrep.c b/pgrep.c index 2d2cc29..bc49587 100644 --- a/pgrep.c +++ b/pgrep.c @@ -2,22 +2,22 @@ static int wait_for_turn(char producer_or_consumer); static void pgrep_for_pids(); -static void *run_work_thread(void *arg); +static phpspy_thread_func run_work_thread(void *arg); static int is_already_attached(int pid); static void init_work_threads(); static void deinit_work_threads(); static int block_all_signals(); static void handle_signal(int signum); -static void *run_signal_thread(void *arg); +static phpspy_thread_func run_signal_thread(void *arg); static int *avail_pids = NULL; static int *attached_pids = NULL; -static pthread_t *work_threads = NULL; -static pthread_t signal_thread; +static phpspy_thread_t*work_threads = NULL; +static phpspy_thread_t signal_thread; static int avail_pids_count = 0; -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t can_produce = PTHREAD_COND_INITIALIZER; -static pthread_cond_t can_consume = PTHREAD_COND_INITIALIZER; +static phpspy_mutex_t mutex; +static phpspy_cond_t can_produce; +static phpspy_cond_t can_consume; static int done_pipe[2] = { -1, -1 }; int main_pgrep() { @@ -28,25 +28,27 @@ int main_pgrep() { exit(1); } - pthread_create(&signal_thread, NULL, run_signal_thread, NULL); + phpspy_thread_create(&signal_thread, NULL, run_signal_thread, NULL); block_all_signals(); init_work_threads(); for (i = 0; i < opt_num_workers; i++) { - pthread_create(&work_threads[i], NULL, run_work_thread, (void*)i); + phpspy_thread_create(&work_threads[i], NULL, run_work_thread, (void*)i); } if (opt_time_limit_ms > 0) { +#ifndef PHPSPY_WIN32 alarm(PHPSPY_MAX(1, opt_time_limit_ms / 1000)); +#endif } pgrep_for_pids(); for (i = 0; i < opt_num_workers; i++) { - pthread_join(work_threads[i], NULL); + phpspy_thread_wait(work_threads[i], NULL); } - pthread_join(signal_thread, NULL); + phpspy_thread_wait(signal_thread, NULL); deinit_work_threads(); @@ -55,24 +57,26 @@ int main_pgrep() { } static int wait_for_turn(char producer_or_consumer) { - struct timespec timeout; - pthread_mutex_lock(&mutex); + struct timespec timeout = { 2, 0 }; + phpspy_mutex_lock(&mutex); while (!done) { if (producer_or_consumer == 'p' && avail_pids_count < opt_num_workers) { break; } else if (avail_pids_count > 0) { break; } +#ifndef PHPSPY_WIN32 clock_gettime(CLOCK_REALTIME, &timeout); timeout.tv_sec += 2; - pthread_cond_timedwait( +#endif + phpspy_cond_timedwait( producer_or_consumer == 'p' ? &can_produce : &can_consume, &mutex, &timeout ); } if (done) { - pthread_mutex_unlock(&mutex); + phpspy_mutex_unlock(&mutex); return 1; } return 0; @@ -81,11 +85,17 @@ static int wait_for_turn(char producer_or_consumer) { static void pgrep_for_pids() { FILE *pcmd; char *pgrep_cmd; - char line[64]; +#ifndef PHPSPY_WIN32 + char cmd_fmt[24] = "pgrep %s"; +#else + char cmd_fmt[24] = "tasklist | findstr %s"; + char pid_buf[8]; +#endif + char line[128]; int pid; int found; - struct timespec timeout; - if (asprintf(&pgrep_cmd, "pgrep %s", opt_pgrep_args) < 0) { + struct timespec timeout = {2, 0}; + if (asprintf(&pgrep_cmd, cmd_fmt, opt_pgrep_args) < 0) { errno = ENOMEM; perror("asprintf"); exit(1); @@ -96,41 +106,51 @@ static void pgrep_for_pids() { if ((pcmd = popen(pgrep_cmd, "r")) != NULL) { while (avail_pids_count < opt_num_workers && fgets(line, sizeof(line), pcmd) != NULL) { if (strlen(line) < 1 || *line == '\n') continue; +#ifdef PHPSPY_WIN32 + sscanf_s(line, "%*s %s", pid_buf, sizeof(pid_buf)); + pid = atoi(pid_buf); +#else pid = atoi(line); +#endif + if (!pid) continue; if (is_already_attached(pid)) continue; avail_pids[avail_pids_count++] = pid; found += 1; } + /* fflush */ + while (fgets(line, sizeof(line), pcmd) != NULL); pclose(pcmd); } if (found > 0) { - pthread_cond_broadcast(&can_consume); + phpspy_cond_broadcast(&can_consume); } else { +#ifndef PHPSPY_WIN32 clock_gettime(CLOCK_REALTIME, &timeout); timeout.tv_sec += 2; - pthread_cond_timedwait( +#endif + phpspy_cond_timedwait( &can_produce, &mutex, &timeout ); } - pthread_mutex_unlock(&mutex); + phpspy_mutex_unlock(&mutex); } free(pgrep_cmd); } -static void *run_work_thread(void *arg) { +static phpspy_thread_func run_work_thread(void *arg) { int worker_num; worker_num = (long)arg; while (!done) { if (wait_for_turn('c')) break; attached_pids[worker_num] = avail_pids[--avail_pids_count]; - pthread_cond_signal(&can_produce); - pthread_mutex_unlock(&mutex); + phpspy_cond_signal(&can_produce); + phpspy_mutex_unlock(&mutex); main_pid(attached_pids[worker_num]); attached_pids[worker_num] = 0; } - return NULL; + return PHPSPY_THREAD_RETNULL; } static int is_already_attached(int pid) { @@ -148,31 +168,33 @@ static int is_already_attached(int pid) { static void init_work_threads() { avail_pids = calloc(opt_num_workers, sizeof(int)); attached_pids = calloc(opt_num_workers, sizeof(int)); - work_threads = calloc(opt_num_workers, sizeof(pthread_t)); + work_threads = calloc(opt_num_workers, sizeof(phpspy_thread_t)); if (!avail_pids || !attached_pids || !work_threads) { errno = ENOMEM; perror("calloc"); exit(1); } - pthread_mutex_init(&mutex, NULL); - pthread_cond_init(&can_produce, NULL); - pthread_cond_init(&can_consume, NULL); + phpspy_mutex_init(&mutex, NULL); + phpspy_cond_init(&can_produce, NULL); + phpspy_cond_init(&can_consume, NULL); } static void deinit_work_threads() { free(avail_pids); free(attached_pids); free(work_threads); - pthread_mutex_destroy(&mutex); - pthread_cond_destroy(&can_produce); - pthread_cond_destroy(&can_consume); + phpspy_mutex_destroy(&mutex); + phpspy_cond_destroy(&can_produce); + phpspy_cond_destroy(&can_consume); } static int block_all_signals() { +#ifndef PHPSPY_WIN32 int rv; sigset_t set; try(rv, sigfillset(&set)); try(rv, sigprocmask(SIG_BLOCK, &set, NULL)); +#endif return 0; } @@ -190,7 +212,8 @@ static void handle_signal(int signum) { write_done_pipe(); } -static void *run_signal_thread(void *arg) { +static phpspy_thread_func run_signal_thread(void *arg) { +#ifndef PHPSPY_WIN32 int rv, ignore; fd_set rfds; struct timeval tv; @@ -230,6 +253,7 @@ static void *run_signal_thread(void *arg) { pthread_cond_broadcast(&can_consume); pthread_cond_broadcast(&can_produce); pthread_mutex_unlock(&mutex); +#endif - return NULL; + return PHPSPY_THREAD_RETNULL; } diff --git a/php_structs_70.h b/php_structs_70.h index 3e217bf..84ca5c4 100644 --- a/php_structs_70.h +++ b/php_structs_70.h @@ -19,9 +19,13 @@ typedef struct _zend_array_70 zend_array_70; typedef struct _zend_alloc_globals_70 zend_alloc_globals_70; typedef struct _zend_mm_heap_70 zend_mm_heap_70; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_70 { +struct PHPSPY_PACK _zend_array_70 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_70 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_70 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_70 { +struct PHPSPY_PACK _zend_executor_globals_70 { uint8_t pad0[304]; /* 0 +304 */ zend_array_70 symbol_table; /* 304 +36 */ uint8_t pad1[140]; /* 340 +140 */ zend_execute_data_70 *current_execute_data; /* 480 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_70 { +struct PHPSPY_PACK _zend_execute_data_70 { zend_op_70 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_70 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_70 { zend_array_70 *symbol_table; /* 64 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_70 { +struct PHPSPY_PACK _zend_op_array_70 { uint8_t pad0[72]; /* 0 +72 */ int last_var; /* 72 +4 */ uint8_t pad1[4]; /* 76 +4 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_70 { uint32_t line_start; /* 128 +4 */ }; -union __attribute__((__packed__)) _zend_function_70 { +union PHPSPY_PACK _zend_function_70 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_70 { zend_op_array_70 op_array; /* 0 +208 */ }; -struct __attribute__((__packed__)) _zend_class_entry_70 { +struct PHPSPY_PACK _zend_class_entry_70 { uint8_t pad0[8]; /* 0 +8 */ zend_string_70 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_70 { +struct PHPSPY_PACK _zend_string_70 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_70 { +struct PHPSPY_PACK _zend_op_70 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_70 { +struct PHPSPY_PACK _sapi_request_info_70 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_70 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_70 { +struct PHPSPY_PACK _sapi_globals_struct_70 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_70 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_70 { +union PHPSPY_PACK _zend_value_70 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_70 *str; /* 0 +8 */ zend_array_70 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_70 { +struct PHPSPY_PACK _zval_70 { zend_value_70 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_70 { } u2; }; -struct __attribute__((__packed__)) _Bucket_70 { +struct PHPSPY_PACK _Bucket_70 { zval_70 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_70 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_70 { +struct PHPSPY_PACK _zend_alloc_globals_70 { zend_mm_heap_70 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_70 { +struct PHPSPY_PACK _zend_mm_heap_70 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_71.h b/php_structs_71.h index bb7d5a4..7783a95 100644 --- a/php_structs_71.h +++ b/php_structs_71.h @@ -19,9 +19,13 @@ typedef struct _zend_array_71 zend_array_71; typedef struct _zend_alloc_globals_71 zend_alloc_globals_71; typedef struct _zend_mm_heap_71 zend_mm_heap_71; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_71 { +struct PHPSPY_PACK _zend_array_71 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_71 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_71 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_71 { +struct PHPSPY_PACK _zend_executor_globals_71 { uint8_t pad0[304]; /* 0 +304 */ zend_array_71 symbol_table; /* 304 +36 */ uint8_t pad1[140]; /* 340 +140 */ zend_execute_data_71 *current_execute_data; /* 480 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_71 { +struct PHPSPY_PACK _zend_execute_data_71 { zend_op_71 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_71 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_71 { zend_array_71 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_71 { +struct PHPSPY_PACK _zend_op_array_71 { uint8_t pad0[72]; /* 0 +72 */ int last_var; /* 72 +4 */ uint8_t pad1[4]; /* 76 +4 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_71 { uint32_t line_start; /* 128 +4 */ }; -union __attribute__((__packed__)) _zend_function_71 { +union PHPSPY_PACK _zend_function_71 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_71 { zend_op_array_71 op_array; /* 0 +208 */ }; -struct __attribute__((__packed__)) _zend_class_entry_71 { +struct PHPSPY_PACK _zend_class_entry_71 { uint8_t pad0[8]; /* 0 +8 */ zend_string_71 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_71 { +struct PHPSPY_PACK _zend_string_71 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_71 { +struct PHPSPY_PACK _zend_op_71 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_71 { +struct PHPSPY_PACK _sapi_request_info_71 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_71 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_71 { +struct PHPSPY_PACK _sapi_globals_struct_71 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_71 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_71 { +union PHPSPY_PACK _zend_value_71 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_71 *str; /* 0 +8 */ zend_array_71 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_71 { +struct PHPSPY_PACK _zval_71 { zend_value_71 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_71 { } u2; }; -struct __attribute__((__packed__)) _Bucket_71 { +struct PHPSPY_PACK _Bucket_71 { zval_71 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_71 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_71 { +struct PHPSPY_PACK _zend_alloc_globals_71 { zend_mm_heap_71 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_71 { +struct PHPSPY_PACK _zend_mm_heap_71 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_72.h b/php_structs_72.h index 92af308..3d7bec2 100644 --- a/php_structs_72.h +++ b/php_structs_72.h @@ -19,9 +19,13 @@ typedef struct _zend_array_72 zend_array_72; typedef struct _zend_alloc_globals_72 zend_alloc_globals_72; typedef struct _zend_mm_heap_72 zend_mm_heap_72; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_72 { +struct PHPSPY_PACK _zend_array_72 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_72 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_72 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_72 { +struct PHPSPY_PACK _zend_executor_globals_72 { uint8_t pad0[304]; /* 0 +304 */ zend_array_72 symbol_table; /* 304 +36 */ uint8_t pad1[140]; /* 340 +140 */ zend_execute_data_72 *current_execute_data; /* 480 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_72 { +struct PHPSPY_PACK _zend_execute_data_72 { zend_op_72 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_72 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_72 { zend_array_72 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_72 { +struct PHPSPY_PACK _zend_op_array_72 { uint8_t pad0[72]; /* 0 +72 */ int last_var; /* 72 +4 */ uint8_t pad1[4]; /* 76 +4 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_72 { uint32_t line_start; /* 128 +4 */ }; -union __attribute__((__packed__)) _zend_function_72 { +union PHPSPY_PACK _zend_function_72 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_72 { zend_op_array_72 op_array; /* 0 +224 */ }; -struct __attribute__((__packed__)) _zend_class_entry_72 { +struct PHPSPY_PACK _zend_class_entry_72 { uint8_t pad0[8]; /* 0 +8 */ zend_string_72 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_72 { +struct PHPSPY_PACK _zend_string_72 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_72 { +struct PHPSPY_PACK _zend_op_72 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_72 { +struct PHPSPY_PACK _sapi_request_info_72 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_72 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_72 { +struct PHPSPY_PACK _sapi_globals_struct_72 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_72 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_72 { +union PHPSPY_PACK _zend_value_72 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_72 *str; /* 0 +8 */ zend_array_72 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_72 { +struct PHPSPY_PACK _zval_72 { zend_value_72 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_72 { } u2; }; -struct __attribute__((__packed__)) _Bucket_72 { +struct PHPSPY_PACK _Bucket_72 { zval_72 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_72 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_72 { +struct PHPSPY_PACK _zend_alloc_globals_72 { zend_mm_heap_72 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_72 { +struct PHPSPY_PACK _zend_mm_heap_72 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_73.h b/php_structs_73.h index 5b80e8d..24b6ef3 100644 --- a/php_structs_73.h +++ b/php_structs_73.h @@ -19,9 +19,13 @@ typedef struct _zend_array_73 zend_array_73; typedef struct _zend_alloc_globals_73 zend_alloc_globals_73; typedef struct _zend_mm_heap_73 zend_mm_heap_73; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_73 { +struct PHPSPY_PACK _zend_array_73 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_73 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_73 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_73 { +struct PHPSPY_PACK _zend_executor_globals_73 { uint8_t pad0[304]; /* 0 +304 */ zend_array_73 symbol_table; /* 304 +36 */ uint8_t pad1[148]; /* 340 +148 */ zend_execute_data_73 *current_execute_data; /* 488 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_73 { +struct PHPSPY_PACK _zend_execute_data_73 { zend_op_73 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_73 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_73 { zend_array_73 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_73 { +struct PHPSPY_PACK _zend_op_array_73 { uint8_t pad0[52]; /* 0 +52 */ int last_var; /* 52 +4 */ uint8_t pad1[32]; /* 56 +32 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_73 { uint32_t line_start; /* 136 +4 */ }; -union __attribute__((__packed__)) _zend_function_73 { +union PHPSPY_PACK _zend_function_73 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_73 { zend_op_array_73 op_array; /* 0 +216 */ }; -struct __attribute__((__packed__)) _zend_class_entry_73 { +struct PHPSPY_PACK _zend_class_entry_73 { uint8_t pad0[8]; /* 0 +8 */ zend_string_73 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_73 { +struct PHPSPY_PACK _zend_string_73 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_73 { +struct PHPSPY_PACK _zend_op_73 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_73 { +struct PHPSPY_PACK _sapi_request_info_73 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_73 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_73 { +struct PHPSPY_PACK _sapi_globals_struct_73 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_73 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_73 { +union PHPSPY_PACK _zend_value_73 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_73 *str; /* 0 +8 */ zend_array_73 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_73 { +struct PHPSPY_PACK _zval_73 { zend_value_73 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_73 { } u2; }; -struct __attribute__((__packed__)) _Bucket_73 { +struct PHPSPY_PACK _Bucket_73 { zval_73 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_73 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_73 { +struct PHPSPY_PACK _zend_alloc_globals_73 { zend_mm_heap_73 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_73 { +struct PHPSPY_PACK _zend_mm_heap_73 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_74.h b/php_structs_74.h index 6876dc2..1358f8d 100644 --- a/php_structs_74.h +++ b/php_structs_74.h @@ -19,9 +19,13 @@ typedef struct _zend_array_74 zend_array_74; typedef struct _zend_alloc_globals_74 zend_alloc_globals_74; typedef struct _zend_mm_heap_74 zend_mm_heap_74; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_74 { +struct PHPSPY_PACK _zend_array_74 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_74 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_74 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_74 { +struct PHPSPY_PACK _zend_executor_globals_74 { uint8_t pad0[304]; /* 0 +304 */ zend_array_74 symbol_table; /* 304 +36 */ uint8_t pad1[148]; /* 340 +148 */ zend_execute_data_74 *current_execute_data; /* 488 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_74 { +struct PHPSPY_PACK _zend_execute_data_74 { zend_op_74 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_74 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_74 { zend_array_74 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_74 { +struct PHPSPY_PACK _zend_op_array_74 { uint8_t pad0[52]; /* 0 +52 */ int last_var; /* 52 +4 */ uint8_t pad1[40]; /* 56 +40 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_74 { uint32_t line_start; /* 144 +4 */ }; -union __attribute__((__packed__)) _zend_function_74 { +union PHPSPY_PACK _zend_function_74 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_74 { zend_op_array_74 op_array; /* 0 +224 */ }; -struct __attribute__((__packed__)) _zend_class_entry_74 { +struct PHPSPY_PACK _zend_class_entry_74 { uint8_t pad0[8]; /* 0 +8 */ zend_string_74 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_74 { +struct PHPSPY_PACK _zend_string_74 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_74 { +struct PHPSPY_PACK _zend_op_74 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_74 { +struct PHPSPY_PACK _sapi_request_info_74 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_74 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_74 { +struct PHPSPY_PACK _sapi_globals_struct_74 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_74 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_74 { +union PHPSPY_PACK _zend_value_74 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_74 *str; /* 0 +8 */ zend_array_74 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_74 { +struct PHPSPY_PACK _zval_74 { zend_value_74 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_74 { } u2; }; -struct __attribute__((__packed__)) _Bucket_74 { +struct PHPSPY_PACK _Bucket_74 { zval_74 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_74 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_74 { +struct PHPSPY_PACK _zend_alloc_globals_74 { zend_mm_heap_74 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_74 { +struct PHPSPY_PACK _zend_mm_heap_74 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_80.h b/php_structs_80.h index 20d17f5..019deb7 100644 --- a/php_structs_80.h +++ b/php_structs_80.h @@ -19,9 +19,13 @@ typedef struct _zend_array_80 zend_array_80; typedef struct _zend_alloc_globals_80 zend_alloc_globals_80; typedef struct _zend_mm_heap_80 zend_mm_heap_80; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_80 { +struct PHPSPY_PACK _zend_array_80 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_80 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_80 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_80 { +struct PHPSPY_PACK _zend_executor_globals_80 { uint8_t pad0[304]; /* 0 +304 */ zend_array_80 symbol_table; /* 304 +36 */ uint8_t pad1[148]; /* 340 +148 */ zend_execute_data_80 *current_execute_data; /* 488 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_80 { +struct PHPSPY_PACK _zend_execute_data_80 { zend_op_80 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_80 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_80 { zend_array_80 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_80 { +struct PHPSPY_PACK _zend_op_array_80 { uint8_t pad0[60]; /* 0 +60 */ int last_var; /* 60 +4 */ uint8_t pad1[40]; /* 64 +40 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_80 { uint32_t line_start; /* 152 +4 */ }; -union __attribute__((__packed__)) _zend_function_80 { +union PHPSPY_PACK _zend_function_80 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_80 { zend_op_array_80 op_array; /* 0 +232 */ }; -struct __attribute__((__packed__)) _zend_class_entry_80 { +struct PHPSPY_PACK _zend_class_entry_80 { uint8_t pad0[8]; /* 0 +8 */ zend_string_80 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_80 { +struct PHPSPY_PACK _zend_string_80 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_80 { +struct PHPSPY_PACK _zend_op_80 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_80 { +struct PHPSPY_PACK _sapi_request_info_80 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_80 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_80 { +struct PHPSPY_PACK _sapi_globals_struct_80 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_80 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_80 { +union PHPSPY_PACK _zend_value_80 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_80 *str; /* 0 +8 */ zend_array_80 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_80 { +struct PHPSPY_PACK _zval_80 { zend_value_80 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_80 { } u2; }; -struct __attribute__((__packed__)) _Bucket_80 { +struct PHPSPY_PACK _Bucket_80 { zval_80 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_80 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_80 { +struct PHPSPY_PACK _zend_alloc_globals_80 { zend_mm_heap_80 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_80 { +struct PHPSPY_PACK _zend_mm_heap_80 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_81.h b/php_structs_81.h index 9bc86f6..6ef7bea 100644 --- a/php_structs_81.h +++ b/php_structs_81.h @@ -19,9 +19,13 @@ typedef struct _zend_array_81 zend_array_81; typedef struct _zend_alloc_globals_81 zend_alloc_globals_81; typedef struct _zend_mm_heap_81 zend_mm_heap_81; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_81 { +struct PHPSPY_PACK _zend_array_81 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_81 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_81 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_81 { +struct PHPSPY_PACK _zend_executor_globals_81 { uint8_t pad0[304]; /* 0 +304 */ zend_array_81 symbol_table; /* 304 +36 */ uint8_t pad1[148]; /* 340 +148 */ zend_execute_data_81 *current_execute_data; /* 488 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_81 { +struct PHPSPY_PACK _zend_execute_data_81 { zend_op_81 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_81 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_81 { zend_array_81 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_81 { +struct PHPSPY_PACK _zend_op_array_81 { uint8_t pad0[60]; /* 0 +60 */ int last_var; /* 60 +4 */ uint8_t pad1[40]; /* 64 +40 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_81 { uint32_t line_start; /* 152 +4 */ }; -union __attribute__((__packed__)) _zend_function_81 { +union PHPSPY_PACK _zend_function_81 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_81 { zend_op_array_81 op_array; /* 0 +240 */ }; -struct __attribute__((__packed__)) _zend_class_entry_81 { +struct PHPSPY_PACK _zend_class_entry_81 { uint8_t pad0[8]; /* 0 +8 */ zend_string_81 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_81 { +struct PHPSPY_PACK _zend_string_81 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_81 { +struct PHPSPY_PACK _zend_op_81 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_81 { +struct PHPSPY_PACK _sapi_request_info_81 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_81 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_81 { +struct PHPSPY_PACK _sapi_globals_struct_81 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_81 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_81 { +union PHPSPY_PACK _zend_value_81 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_81 *str; /* 0 +8 */ zend_array_81 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_81 { +struct PHPSPY_PACK _zval_81 { zend_value_81 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_81 { } u2; }; -struct __attribute__((__packed__)) _Bucket_81 { +struct PHPSPY_PACK _Bucket_81 { zval_81 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_81 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_81 { +struct PHPSPY_PACK _zend_alloc_globals_81 { zend_mm_heap_81 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_81 { +struct PHPSPY_PACK _zend_mm_heap_81 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_82.h b/php_structs_82.h index f4f7f88..ed4944c 100644 --- a/php_structs_82.h +++ b/php_structs_82.h @@ -19,9 +19,13 @@ typedef struct _zend_array_82 zend_array_82; typedef struct _zend_alloc_globals_82 zend_alloc_globals_82; typedef struct _zend_mm_heap_82 zend_mm_heap_82; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_82 { +struct PHPSPY_PACK _zend_array_82 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_82 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_82 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_82 { +struct PHPSPY_PACK _zend_executor_globals_82 { uint8_t pad0[304]; /* 0 +304 */ zend_array_82 symbol_table; /* 304 +36 */ uint8_t pad1[148]; /* 340 +148 */ zend_execute_data_82 *current_execute_data; /* 488 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_82 { +struct PHPSPY_PACK _zend_execute_data_82 { zend_op_82 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_82 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_82 { zend_array_82 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_82 { +struct PHPSPY_PACK _zend_op_array_82 { uint8_t pad0[76]; /* 0 +76 */ int last_var; /* 76 +4 */ uint8_t pad1[32]; /* 80 +32 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_82 { uint32_t line_start; /* 160 +4 */ }; -union __attribute__((__packed__)) _zend_function_82 { +union PHPSPY_PACK _zend_function_82 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_82 { zend_op_array_82 op_array; /* 0 +248 */ }; -struct __attribute__((__packed__)) _zend_class_entry_82 { +struct PHPSPY_PACK _zend_class_entry_82 { uint8_t pad0[8]; /* 0 +8 */ zend_string_82 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_82 { +struct PHPSPY_PACK _zend_string_82 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_82 { +struct PHPSPY_PACK _zend_op_82 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_82 { +struct PHPSPY_PACK _sapi_request_info_82 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_82 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_82 { +struct PHPSPY_PACK _sapi_globals_struct_82 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_82 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_82 { +union PHPSPY_PACK _zend_value_82 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_82 *str; /* 0 +8 */ zend_array_82 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_82 { +struct PHPSPY_PACK _zval_82 { zend_value_82 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_82 { } u2; }; -struct __attribute__((__packed__)) _Bucket_82 { +struct PHPSPY_PACK _Bucket_82 { zval_82 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_82 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_82 { +struct PHPSPY_PACK _zend_alloc_globals_82 { zend_mm_heap_82 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_82 { +struct PHPSPY_PACK _zend_mm_heap_82 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_83.h b/php_structs_83.h index a8960b3..5cca8e0 100644 --- a/php_structs_83.h +++ b/php_structs_83.h @@ -19,9 +19,13 @@ typedef struct _zend_array_83 zend_array_83; typedef struct _zend_alloc_globals_83 zend_alloc_globals_83; typedef struct _zend_mm_heap_83 zend_mm_heap_83; +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_83 { +struct PHPSPY_PACK _zend_array_83 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_83 *arData; /* 16 +8 */ @@ -30,14 +34,14 @@ struct __attribute__((__packed__)) _zend_array_83 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_83 { +struct PHPSPY_PACK _zend_executor_globals_83 { uint8_t pad0[304]; /* 0 +304 */ zend_array_83 symbol_table; /* 304 +36 */ uint8_t pad1[148]; /* 340 +148 */ zend_execute_data_83 *current_execute_data; /* 488 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_83 { +struct PHPSPY_PACK _zend_execute_data_83 { zend_op_83 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_83 *func; /* 24 +8 */ @@ -46,7 +50,7 @@ struct __attribute__((__packed__)) _zend_execute_data_83 { zend_array_83 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_83 { +struct PHPSPY_PACK _zend_op_array_83 { uint8_t pad0[72]; /* 0 +72 */ int last_var; /* 72 +4 */ uint8_t pad1[28]; /* 76 +28 */ @@ -56,7 +60,7 @@ struct __attribute__((__packed__)) _zend_op_array_83 { uint32_t line_start; /* 152 +4 */ }; -union __attribute__((__packed__)) _zend_function_83 { +union PHPSPY_PACK _zend_function_83 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +70,23 @@ union __attribute__((__packed__)) _zend_function_83 { zend_op_array_83 op_array; /* 0 +240 */ }; -struct __attribute__((__packed__)) _zend_class_entry_83 { +struct PHPSPY_PACK _zend_class_entry_83 { uint8_t pad0[8]; /* 0 +8 */ zend_string_83 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_83 { +struct PHPSPY_PACK _zend_string_83 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_83 { +struct PHPSPY_PACK _zend_op_83 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_83 { +struct PHPSPY_PACK _sapi_request_info_83 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +95,21 @@ struct __attribute__((__packed__)) _sapi_request_info_83 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_83 { +struct PHPSPY_PACK _sapi_globals_struct_83 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_83 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_83 { +union PHPSPY_PACK _zend_value_83 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_83 *str; /* 0 +8 */ zend_array_83 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_83 { +struct PHPSPY_PACK _zval_83 { zend_value_83 value; /* 0 +8 */ union { struct { @@ -118,20 +122,24 @@ struct __attribute__((__packed__)) _zval_83 { } u2; }; -struct __attribute__((__packed__)) _Bucket_83 { +struct PHPSPY_PACK _Bucket_83 { zval_83 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_83 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_83 { +struct PHPSPY_PACK _zend_alloc_globals_83 { zend_mm_heap_83 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_83 { +struct PHPSPY_PACK _zend_mm_heap_83 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/php_structs_84.h b/php_structs_84.h index 532bb79..c7a2cf8 100644 --- a/php_structs_84.h +++ b/php_structs_84.h @@ -19,9 +19,14 @@ typedef struct _zend_array_84 zend_array_84; typedef struct _zend_alloc_globals_84 zend_alloc_globals_84; typedef struct _zend_mm_heap_84 zend_mm_heap_84; + +#ifdef PHPSPY_WIN32 +#pragma pack(push, 1) +#endif + /* Assumes 8-byte pointers */ /* offset length */ -struct __attribute__((__packed__)) _zend_array_84 { +struct PHPSPY_PACK _zend_array_84 { uint8_t pad0[12]; /* 0 +12 */ uint32_t nTableMask; /* 12 +4 */ Bucket_84 *arData; /* 16 +8 */ @@ -30,14 +35,14 @@ struct __attribute__((__packed__)) _zend_array_84 { uint32_t nTableSize; /* 32 +4 */ }; -struct __attribute__((__packed__)) _zend_executor_globals_84 { +struct PHPSPY_PACK _zend_executor_globals_84 { uint8_t pad0[304]; /* 0 +304 */ zend_array_84 symbol_table; /* 304 +36 */ uint8_t pad1[148]; /* 340 +148 */ zend_execute_data_84 *current_execute_data; /* 488 +8 */ }; -struct __attribute__((__packed__)) _zend_execute_data_84 { +struct PHPSPY_PACK _zend_execute_data_84 { zend_op_84 *opline; /* 0 +8 */ uint8_t pad0[16]; /* 8 +16 */ zend_function_84 *func; /* 24 +8 */ @@ -46,7 +51,7 @@ struct __attribute__((__packed__)) _zend_execute_data_84 { zend_array_84 *symbol_table; /* 56 +8 */ }; -struct __attribute__((__packed__)) _zend_op_array_84 { +struct PHPSPY_PACK _zend_op_array_84 { uint8_t pad0[80]; /* 0 +80 */ int last_var; /* 80 +4 */ uint8_t pad1[28]; /* 84 +28 */ @@ -56,7 +61,7 @@ struct __attribute__((__packed__)) _zend_op_array_84 { uint32_t line_start; /* 160 +4 */ }; -union __attribute__((__packed__)) _zend_function_84 { +union PHPSPY_PACK _zend_function_84 { uint8_t type; /* 0 +1 */ struct { uint8_t pad0[8]; /* 0 +8 */ @@ -66,23 +71,23 @@ union __attribute__((__packed__)) _zend_function_84 { zend_op_array_84 op_array; /* 0 +240 */ }; -struct __attribute__((__packed__)) _zend_class_entry_84 { +struct PHPSPY_PACK _zend_class_entry_84 { uint8_t pad0[8]; /* 0 +8 */ zend_string_84 *name; /* 8 +8 */ }; -struct __attribute__((__packed__)) _zend_string_84 { +struct PHPSPY_PACK _zend_string_84 { uint8_t pad0[16]; /* 0 +16 */ size_t len; /* 16 +8 */ char val[1]; /* 24 +1 */ }; -struct __attribute__((__packed__)) _zend_op_84 { +struct PHPSPY_PACK _zend_op_84 { uint8_t pad0[24]; /* 0 +24 */ uint32_t lineno; /* 24 +4 */ }; -struct __attribute__((__packed__)) _sapi_request_info_84 { +struct PHPSPY_PACK _sapi_request_info_84 { uint8_t pad0[8]; /* 0 +8 */ char *query_string; /* 8 +8 */ char *cookie_data; /* 16 +8 */ @@ -91,21 +96,21 @@ struct __attribute__((__packed__)) _sapi_request_info_84 { char *request_uri; /* 40 +8 */ }; -struct __attribute__((__packed__)) _sapi_globals_struct_84 { +struct PHPSPY_PACK _sapi_globals_struct_84 { uint8_t pad0[8]; /* 0 +8 */ sapi_request_info_84 request_info; /* 8 +48 */ uint8_t pad1[384]; /* 56 +384 */ double global_request_time; /* 440 +8 */ }; -union __attribute__((__packed__)) _zend_value_84 { +union PHPSPY_PACK _zend_value_84 { long lval; /* 0 +8 */ double dval; /* 0 +8 */ zend_string_84 *str; /* 0 +8 */ zend_array_84 *arr; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zval_84 { +struct PHPSPY_PACK _zval_84 { zend_value_84 value; /* 0 +8 */ union { struct { @@ -118,20 +123,24 @@ struct __attribute__((__packed__)) _zval_84 { } u2; }; -struct __attribute__((__packed__)) _Bucket_84 { +struct PHPSPY_PACK _Bucket_84 { zval_84 val; /* 0 +16 */ uint64_t h; /* 16 +8 */ zend_string_84 *key; /* 24 +8 */ }; -struct __attribute__((__packed__)) _zend_alloc_globals_84 { +struct PHPSPY_PACK _zend_alloc_globals_84 { zend_mm_heap_84 *mm_heap; /* 0 +8 */ }; -struct __attribute__((__packed__)) _zend_mm_heap_84 { +struct PHPSPY_PACK _zend_mm_heap_84 { uint8_t pad0[16]; /* 0 +16 */ size_t size; /* 16 +8 */ size_t peak; /* 24 +8 */ }; +#ifdef PHPSPY_WIN32 +#pragma pack(pop) +#endif + #endif diff --git a/phpspy.c b/phpspy.c index 9f4e74c..3824f8e 100644 --- a/phpspy.c +++ b/phpspy.c @@ -1,9 +1,11 @@ #include "phpspy.h" +#ifndef PHPSPY_WIN32 #define TB_IMPL #define TB_OPT_V1_COMPAT #include #undef TB_IMPL +#endif pid_t opt_pid = -1; char *opt_pgrep_args = NULL; @@ -52,7 +54,11 @@ static int main_fork(int argc, char **argv); static void cleanup(); static int pause_pid(pid_t pid); static int unpause_pid(pid_t pid); +#ifndef PHPSPY_WIN32 static void redirect_child_stdio(int proc_fd, char *opt_path); +#else +static void redirect_child_stdio(HANDLE *std, char *opt_path); +#endif static int find_addresses(trace_target_t *target); static void clock_get(struct timespec *ts); static void clock_add(struct timespec *a, struct timespec *b, struct timespec *res); @@ -83,7 +89,9 @@ int main(int argc, char **argv) { parse_opts(argc, argv); if (opt_top_mode != 0) { +#ifndef PHPSPY_WIN32 rv = main_top(argc, argv); +#endif } else if (opt_pid != -1) { rv = main_pid(opt_pid); } else if (opt_pgrep_args != NULL) { @@ -445,7 +453,7 @@ int main_pid(pid_t pid) { /* maybe apply trace limit */ if (opt_trace_limit > 0 && rv == PHPSPY_OK) { if (in_pgrep_mode) { - __atomic_add_fetch(&trace_count, 1, __ATOMIC_SEQ_CST); + phpspy_atomic_add64(&trace_count, 1); } else { trace_count += 1; } @@ -478,6 +486,7 @@ int main_pid(pid_t pid) { return PHPSPY_OK; } +#ifndef PHPSPY_WIN32 static int main_fork(int argc, char **argv) { int rv, status; pid_t fork_pid; @@ -490,7 +499,8 @@ static int main_fork(int argc, char **argv) { execvp(argv[optind], argv + optind); perror("execvp"); exit(1); - } else if (fork_pid < 0) { + } + else if (fork_pid < 0) { perror("fork"); exit(1); } @@ -503,6 +513,57 @@ static int main_fork(int argc, char **argv) { waitpid(fork_pid, NULL, 0); return rv; } +#else +static int main_fork(int argc, char** argv) { + int rv; + char cmd[PHPSPY_STR_SIZE] = { 0 }; + char argv_buf[PHPSPY_STR_SIZE] = { 0 }; + + argv += optind; + while (*argv) { + snprintf(argv_buf, sizeof(argv_buf), "%s ", *argv++); + strcat(cmd, argv_buf); + } + + STARTUPINFO si; + PROCESS_INFORMATION pi; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + redirect_child_stdio(&si.hStdOutput, opt_path_child_out); + redirect_child_stdio(&si.hStdError, opt_path_child_err); + si.dwFlags |= STARTF_USESTDHANDLES; + ZeroMemory(&pi, sizeof(pi)); + + if (!CreateProcess( + NULL, + cmd, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &si, + &pi + )) { + printf("CreateProcess failed (%d).\n", GetLastError()); + return 1; + } + /* TODO to be optimized */ + Sleep(1000); + rv = main_pid(pi.dwProcessId); + + WaitForSingleObject(pi.hProcess, INFINITE); + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + + return rv; +} +#endif static void cleanup() { varpeek_entry_t *entry, *entry_tmp; @@ -529,6 +590,7 @@ static void cleanup() { } static int pause_pid(pid_t pid) { +#ifndef PHPSPY_WIN32 int rv; if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { rv = errno; @@ -539,22 +601,28 @@ static int pause_pid(pid_t pid) { perror("waitpid"); return PHPSPY_ERR; } +#endif return PHPSPY_OK; } static int unpause_pid(pid_t pid) { +#ifndef PHPSPY_WIN32 int rv; if (ptrace(PTRACE_DETACH, pid, 0, 0) == -1) { rv = errno; perror("ptrace"); return PHPSPY_ERR + (rv == ESRCH ? PHPSPY_ERR_PID_DEAD : 0); } +#endif return PHPSPY_OK; } +#ifndef PHPSPY_WIN32 static void redirect_child_stdio(int proc_fd, char *opt_path) { +#else +static void redirect_child_stdio(HANDLE *std, char* opt_path) { +#endif char *redir_path; - FILE *redir_file; if (strcmp(opt_path, "-") == 0) { return; } else if (strstr(opt_path, "%d") != NULL) { @@ -569,6 +637,9 @@ static void redirect_child_stdio(int proc_fd, char *opt_path) { exit(1); } } +#ifndef PHPSPY_WIN32 + FILE *redir_file; + if ((redir_file = fopen(redir_path, "w")) == NULL) { perror("fopen"); free(redir_path); @@ -576,6 +647,22 @@ static void redirect_child_stdio(int proc_fd, char *opt_path) { } dup2(fileno(redir_file), proc_fd); fclose(redir_file); +#else + SECURITY_ATTRIBUTES sa; + HANDLE redir_file; + + ZeroMemory(&sa, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + + redir_file = CreateFile(redir_path, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (redir_file == INVALID_HANDLE_VALUE) { + perror("fopen"); + free(redir_path); + exit(1); + } + *std = redir_file; +#endif free(redir_path); } @@ -603,18 +690,36 @@ static int find_addresses(trace_target_t *target) { target->basic_functions_module_addr = 0; } log_error_enabled = 1; + +#ifdef PHPSPY_WIN32 + strncpy(target->php_bin_path, memo.php_bin_path, PHPSPY_STR_SIZE - 1); +#endif + return PHPSPY_OK; } -static void clock_get(struct timespec *ts) { +static void clock_get(struct timespec* ts) { +#ifndef PHPSPY_WIN32 if (clock_gettime(CLOCK_MONOTONIC_RAW, ts) == -1) { perror("clock_gettime"); ts->tv_sec = 0; ts->tv_nsec = 0; } +#else + LARGE_INTEGER pf, pc; + QueryPerformanceFrequency(&pf); + QueryPerformanceCounter(&pc); + + ts->tv_sec = pc.QuadPart / pf.QuadPart; + ts->tv_nsec = (int)(((pc.QuadPart % pf.QuadPart) * 1000000000L + (pf.QuadPart >> 1)) / pf.QuadPart); + if (ts->tv_nsec >= 1000000000L) { + ts->tv_sec++; + ts->tv_nsec -= 1000000000L; + } +#endif } -static void clock_add(struct timespec *a, struct timespec *b, struct timespec *res) { +static void clock_add(struct timespec* a, struct timespec* b, struct timespec* res) { res->tv_sec = a->tv_sec + b->tv_sec; res->tv_nsec = a->tv_nsec + b->tv_nsec; if (res->tv_nsec >= 1000000000L) { @@ -623,7 +728,7 @@ static void clock_add(struct timespec *a, struct timespec *b, struct timespec *r } } -static int clock_diff(struct timespec *a, struct timespec *b) { +static int clock_diff(struct timespec* a, struct timespec* b) { if (a->tv_sec == b->tv_sec) { if (a->tv_nsec == b->tv_nsec) { return 0; @@ -633,7 +738,7 @@ static int clock_diff(struct timespec *a, struct timespec *b) { return a->tv_sec > b->tv_sec ? 1 : -1; } -static void calc_sleep_time(struct timespec *end, struct timespec *start, struct timespec *sleep) { +static void calc_sleep_time(struct timespec* end, struct timespec* start, struct timespec* sleep) { long end_ns, start_ns, sleep_ns; if (end->tv_sec == start->tv_sec) { sleep_ns = opt_sleep_ns - (end->tv_nsec - start->tv_nsec); @@ -721,6 +826,7 @@ static void glopeek_add(char *glospec) { HASH_ADD_STR(glopeek_map, key, gentry); } +#ifndef PHPSPY_WIN32 static int copy_proc_mem(pid_t pid, const char *what, void *raddr, void *laddr, size_t size) { struct iovec local[1]; struct iovec remote[1]; @@ -747,6 +853,32 @@ static int copy_proc_mem(pid_t pid, const char *what, void *raddr, void *laddr, return PHPSPY_OK; } +#else + +static int copy_proc_mem(pid_t pid, const char *what, void *raddr, void *laddr, size_t size) { + size_t bytesRead; + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (hProcess == NULL) { + printf("Could not open process with PID %lu.\n", pid); + return PHPSPY_ERR; + } + BOOL rv = ReadProcessMemory(hProcess, raddr, laddr, size, &bytesRead); + CloseHandle(hProcess); + + if (!rv) { + if (bytesRead == 0) { + perror("process_vm_readv"); + return PHPSPY_ERR | PHPSPY_ERR_PID_DEAD; + } + log_error("copy_proc_mem: Failed to copy %s; err=%d raddr=%p size=%lu\n", what, GetLastError(), raddr, size); + return PHPSPY_ERR; + } + + return PHPSPY_OK; +} + +#endif + #ifndef USE_ZEND static int get_php_version(trace_target_t *target) { struct _zend_module_entry basic_functions_module; @@ -767,6 +899,7 @@ static int get_php_version(trace_target_t *target) { /* Try greping binary */ if (phpv[0] == '\0') { +#ifndef PHPSPY_WIN32 char libname[PHPSPY_STR_SIZE]; if (shell_escape(opt_libname_awk_patt, libname, sizeof(libname), "opt_libname_awk_patt")) { return PHPSPY_ERR; @@ -787,7 +920,9 @@ static int get_php_version(trace_target_t *target) { log_error("get_php_version: snprintf overflow\n"); return PHPSPY_ERR; } - +#else + snprintf(version_cmd, sizeof(version_cmd), "%s -r \"echo phpversion();\"", target->php_bin_path); +#endif if ((pcmd = popen(version_cmd, "r")) == NULL) { perror("get_php_version: popen"); return PHPSPY_ERR; diff --git a/phpspy.h b/phpspy.h index 276f06a..216b41d 100644 --- a/phpspy.h +++ b/phpspy.h @@ -7,9 +7,7 @@ #include #include -#include #include -#include #include #include #include @@ -17,6 +15,13 @@ #include #include #include +#include +#include +#include + +#ifndef PHPSPY_WIN32 +#include +#include #include #include #include @@ -25,10 +30,10 @@ #include #include #include -#include #include #include #include +#endif #ifdef USE_ZEND #include
@@ -51,12 +56,6 @@ #include #endif -#ifndef gettid -#define gettid() syscall(SYS_gettid) -#endif - -#include - #define try(__rv, __call) do { if (((__rv) = (__call)) != 0) return (__rv); } while(0) #define try_break(__rv, __call) do { if (((__rv) = (__call)) != 0) break; } while(0) @@ -163,6 +162,9 @@ typedef struct trace_target_s { uint64_t sapi_globals_addr; uint64_t alloc_globals_addr; uint64_t basic_functions_module_addr; +#ifdef PHPSPY_WIN32 + char php_bin_path[PHPSPY_STR_SIZE]; +#endif } trace_target_t; typedef struct trace_context_s { @@ -183,12 +185,15 @@ typedef struct trace_context_s { typedef struct addr_memo_s { char php_bin_path[PHPSPY_STR_SIZE]; +#ifdef PHPSPY_WIN32 + char php_dll_path[PHPSPY_STR_SIZE]; +#endif char php_bin_path_root[PHPSPY_STR_SIZE]; uint64_t php_base_addr; } addr_memo_t; #ifndef USE_ZEND -struct __attribute__((__packed__)) _zend_module_entry { +struct PHPSPY_PACK _zend_module_entry { uint8_t pad0[88]; const char *version; }; diff --git a/vendor/getopt.c b/vendor/getopt.c new file mode 100644 index 0000000..e368d69 --- /dev/null +++ b/vendor/getopt.c @@ -0,0 +1,562 @@ +/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "getopt_win.h" +#include +#include +#include + +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +#undef optreset /* see getopt.h */ +#define optreset __mingw_optreset +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#ifndef __CYGWIN__ +#define __progname __argv[0] +#else +extern char __declspec(dllimport) *__progname; +#endif + +#ifdef __CYGWIN__ +static char EMSG[] = ""; +#else +#define EMSG "" +#endif + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +static void +_vwarnx(const char *fmt,va_list ap) +{ + (void)fprintf(stderr,"%s: ",__progname); + if (fmt != NULL) + (void)vfprintf(stderr,fmt,ap); + (void)fprintf(stderr,"\n"); +} + +static void +warnx(const char *fmt,...) +{ + va_list ap; + va_start(ap,fmt); + _vwarnx(fmt,ap); + va_end(ap); +} + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, ambiguous, match; + +#define IDENTICAL_INTERPRETATION(_x, _y) \ + (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ + long_options[(_x)].flag == long_options[(_y)].flag && \ + long_options[(_x)].val == long_options[(_y)].val) + + current_argv = place; + match = -1; + ambiguous = 0; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + ambiguous = 0; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else if (!IDENTICAL_INTERPRETATION(i, match)) + ambiguous = 1; + } + if (ambiguous) { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +#undef IDENTICAL_INTERPRETATION +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + const char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + * + * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or + * optreset != 0 for GNU compatibility. + */ + if (posixly_correct == -1 || optreset != 0) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} \ No newline at end of file diff --git a/vendor/getopt_win.h b/vendor/getopt_win.h new file mode 100644 index 0000000..5143ac6 --- /dev/null +++ b/vendor/getopt_win.h @@ -0,0 +1,105 @@ +#ifndef __GETOPT_H__ +/** + * DISCLAIMER + * This file has no copyright assigned and is placed in the Public Domain. + * This file is a part of the w64 mingw-runtime package. + * + * The w64 mingw-runtime package and its code is distributed in the hope that it + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define __GETOPT_H__ + + /* All the headers include this file. */ +#include + +#if defined( WINGETOPT_SHARED_LIB ) +# if defined( BUILDING_WINGETOPT_DLL ) +# define WINGETOPT_API __declspec(dllexport) +# else +# define WINGETOPT_API __declspec(dllimport) +# endif +#else +# define WINGETOPT_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + WINGETOPT_API extern int optind; /* index of first non-option in argv */ + WINGETOPT_API extern int optopt; /* single option character, as parsed */ + WINGETOPT_API extern int opterr; /* flag to enable built-in diagnostics... */ + /* (user may set to zero, to suppress) */ + + WINGETOPT_API extern char* optarg; /* pointer to argument of current option */ + + extern int getopt(int nargc, char* const* nargv, const char* options); + +#ifdef _BSD_SOURCE + /* + * BSD adds the non-standard `optreset' feature, for reinitialisation + * of `getopt' parsing. We support this feature, for applications which + * proclaim their BSD heritage, before including this header; however, + * to maintain portability, developers are advised to avoid it. + */ +# define optreset __mingw_optreset + extern int optreset; +#endif +#ifdef __cplusplus +} +#endif +/* + * POSIX requires the `getopt' API to be specified in `unistd.h'; + * thus, `unistd.h' includes this header. However, we do not want + * to expose the `getopt_long' or `getopt_long_only' APIs, when + * included in this manner. Thus, close the standard __GETOPT_H__ + * declarations block, and open an additional __GETOPT_LONG_H__ + * specific block, only when *not* __UNISTD_H_SOURCED__, in which + * to declare the extended API. + */ +#endif /* !defined(__GETOPT_H__) */ + +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) +#define __GETOPT_LONG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + struct option /* specification for a long form option... */ + { + const char* name; /* option name, without leading hyphens */ + int has_arg; /* does it take an argument? */ + int* flag; /* where to save its status, or NULL */ + int val; /* its associated status value */ + }; + + enum /* permitted values for its `has_arg' field... */ + { + no_argument = 0, /* option never takes an argument */ + required_argument, /* option always requires an argument */ + optional_argument /* option may take an argument */ + }; + + extern int getopt_long(int nargc, char* const* nargv, const char* options, + const struct option* long_options, int* idx); + extern int getopt_long_only(int nargc, char* const* nargv, const char* options, + const struct option* long_options, int* idx); + /* + * Previous MinGW implementation had... + */ +#ifndef HAVE_DECL_GETOPT + /* + * ...for the long form API only; keep this for compatibility. + */ +# define HAVE_DECL_GETOPT 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ \ No newline at end of file