source: trunk/xcache.c @ 1163

Last change on this file since 1163 was 1163, checked in by moo, 23 months ago

compatible with "the ionCube PHP Loader"

  • Property svn:eol-style set to native
File size: 21.9 KB
Line 
1/* {{{ macros */
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5
6#include <signal.h>
7
8#include "xcache.h"
9
10#ifdef HAVE_XCACHE_OPTIMIZER
11#   include "mod_optimizer/xc_optimizer.h"
12#endif
13#ifdef HAVE_XCACHE_CACHER
14#   include "mod_cacher/xc_cacher.h"
15#endif
16#ifdef HAVE_XCACHE_COVERAGER
17#   include "mod_coverager/xc_coverager.h"
18#endif
19#ifdef HAVE_XCACHE_DISASSEMBLER
20#   include "mod_disassembler/xc_disassembler.h"
21#endif
22
23#include "xcache_globals.h"
24#include "xcache/xc_extension.h"
25#include "xcache/xc_ini.h"
26#include "xcache/xc_const_string.h"
27#include "xcache/xc_opcode_spec.h"
28#include "xcache/xc_utils.h"
29#include "util/xc_stack.h"
30
31#include "php.h"
32#include "ext/standard/info.h"
33#include "ext/standard/php_string.h"
34#include "SAPI.h"
35/* }}} */
36
37/* {{{ globals */
38static char *xc_coredump_dir = NULL;
39static zend_bool xc_disable_on_crash = 0;
40
41static zend_compile_file_t *old_compile_file = NULL;
42
43zend_bool xc_test = 0;
44
45ZEND_DECLARE_MODULE_GLOBALS(xcache)
46
47/* }}} */
48
49static zend_op_array *xc_check_initial_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
50{
51    XG(initial_compile_file_called) = 1;
52    return old_compile_file(h, type TSRMLS_CC);
53}
54/* }}} */
55
56/* module helper function */
57static int xc_init_constant(int module_number TSRMLS_DC) /* {{{ */
58{
59    typedef struct {
60        const char *prefix;
61        zend_uchar (*getsize)();
62        const char *(*get)(zend_uchar i);
63    } xc_nameinfo_t;
64    xc_nameinfo_t nameinfos[] = {
65        { "",        xc_get_op_type_count,   xc_get_op_type   },
66        { "",        xc_get_data_type_count, xc_get_data_type },
67        { "",        xc_get_opcode_count,    xc_get_opcode    },
68        { "OPSPEC_", xc_get_op_spec_count,   xc_get_op_spec   },
69        { NULL, NULL, NULL }
70    };
71    int undefdone = 0;
72    xc_nameinfo_t *p;
73
74    for (p = nameinfos; p->getsize; p ++) {
75        zend_uchar i, count;
76        char const_name[96];
77        int const_name_len;
78
79        count = p->getsize();
80        for (i = 0; i < count; i ++) {
81            const char *name = p->get(i);
82            if (!name) continue;
83            if (strcmp(name, "UNDEF") == 0) {
84                if (undefdone) continue;
85                undefdone = 1;
86            }
87            const_name_len = snprintf(const_name, sizeof(const_name), "XC_%s%s", p->prefix, name);
88            zend_register_long_constant(const_name, const_name_len+1, i, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
89        }
90    }
91
92    zend_register_long_constant(ZEND_STRS("XC_SIZEOF_TEMP_VARIABLE"), sizeof(temp_variable), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
93    zend_register_stringl_constant(ZEND_STRS("XCACHE_VERSION"), ZEND_STRL(XCACHE_VERSION), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
94    zend_register_stringl_constant(ZEND_STRS("XCACHE_MODULES"), ZEND_STRL(XCACHE_MODULES), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
95    return 0;
96}
97/* }}} */
98/* {{{ PHP_GINIT_FUNCTION(xcache) */
99#pragma GCC push_options
100#pragma GCC diagnostic ignored "-Wshadow"
101
102#ifdef PHP_GINIT_FUNCTION
103static PHP_GINIT_FUNCTION(xcache)
104#else
105static void xc_init_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
106#endif
107{
108#pragma GCC pop_options
109
110    memset(xcache_globals, 0, sizeof(zend_xcache_globals));
111
112#ifdef HAVE_XCACHE_CONSTANT
113    zend_hash_init_ex(&xcache_globals->internal_constant_table, 1, NULL, (dtor_func_t) xc_zend_constant_dtor, 1, 0);
114#endif
115    zend_hash_init_ex(&xcache_globals->internal_function_table, 1, NULL, NULL, 1, 0);
116    zend_hash_init_ex(&xcache_globals->internal_class_table,    1, NULL, NULL, 1, 0);
117}
118/* }}} */
119/* {{{ PHP_GSHUTDOWN_FUNCTION(xcache) */
120static
121#ifdef PHP_GSHUTDOWN_FUNCTION
122PHP_GSHUTDOWN_FUNCTION(xcache)
123#else
124void xc_shutdown_globals(zend_xcache_globals* xcache_globals TSRMLS_DC)
125#endif
126{
127    size_t i;
128
129    if (xcache_globals->php_holds != NULL) {
130        for (i = 0; i < xcache_globals->php_holds_size; i ++) {
131            xc_stack_destroy(&xcache_globals->php_holds[i]);
132        }
133        free(xcache_globals->php_holds);
134        xcache_globals->php_holds = NULL;
135        xcache_globals->php_holds_size = 0;
136    }
137
138    if (xcache_globals->var_holds != NULL) {
139        for (i = 0; i < xcache_globals->var_holds_size; i ++) {
140            xc_stack_destroy(&xcache_globals->var_holds[i]);
141        }
142        free(xcache_globals->var_holds);
143        xcache_globals->var_holds = NULL;
144        xcache_globals->var_holds_size = 0;
145    }
146
147    if (xcache_globals->internal_table_copied) {
148#ifdef HAVE_XCACHE_CONSTANT
149        zend_hash_destroy(&xcache_globals->internal_constant_table);
150#endif
151        zend_hash_destroy(&xcache_globals->internal_function_table);
152        zend_hash_destroy(&xcache_globals->internal_class_table);
153    }
154}
155/* }}} */
156
157/* {{{ proto int xcache_get_refcount(mixed variable)
158   XCache internal uses only: Get reference count of variable */
159PHP_FUNCTION(xcache_get_refcount)
160{
161    zval *variable;
162    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) {
163        RETURN_NULL();
164    }
165
166    RETURN_LONG(Z_REFCOUNT(*variable));
167}
168/* }}} */
169/* {{{ proto bool xcache_get_isref(mixed variable)
170   XCache internal uses only: Check if variable data is marked referenced */
171#ifdef ZEND_BEGIN_ARG_INFO_EX
172ZEND_BEGIN_ARG_INFO_EX(arginfo_xcache_get_isref, 0, 0, 1)
173    ZEND_ARG_INFO(1, variable)
174ZEND_END_ARG_INFO()
175#else
176static unsigned char arginfo_xcache_get_isref[] = { 1, BYREF_FORCE };
177#endif
178
179PHP_FUNCTION(xcache_get_isref)
180{
181    zval *variable;
182    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variable) == FAILURE) {
183        RETURN_NULL();
184    }
185
186    RETURN_BOOL(Z_ISREF(*variable) && Z_REFCOUNT(*variable) >= 3);
187}
188/* }}} */
189#ifdef HAVE_XCACHE_DPRINT
190/* {{{ proto bool  xcache_dprint(mixed value)
191   Prints variable (or value) internal struct (debug only) */
192PHP_FUNCTION(xcache_dprint)
193{
194    zval *value;
195
196    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
197        return;
198    }
199    xc_dprint_zval(value, 0 TSRMLS_CC);
200}
201/* }}} */
202#endif
203/* {{{ proto string xcache_asm(string filename)
204 */
205#ifdef HAVE_XCACHE_ASSEMBLER
206PHP_FUNCTION(xcache_asm)
207{
208}
209#endif
210/* }}} */
211/* {{{ proto string xcache_encode(string filename)
212   Encode php file into XCache opcode encoded format */
213#ifdef HAVE_XCACHE_ENCODER
214PHP_FUNCTION(xcache_encode)
215{
216}
217#endif
218/* }}} */
219/* {{{ proto bool xcache_decode_file(string filename)
220   Decode(load) opcode from XCache encoded format file */
221#ifdef HAVE_XCACHE_DECODER
222PHP_FUNCTION(xcache_decode_file)
223{
224}
225#endif
226/* }}} */
227/* {{{ proto bool xcache_decode_string(string data)
228   Decode(load) opcode from XCache encoded format data */
229#ifdef HAVE_XCACHE_DECODER
230PHP_FUNCTION(xcache_decode_string)
231{
232}
233#endif
234/* }}} */
235/* {{{ xc_call_getter */
236typedef const char *(xc_name_getter_t)(zend_uchar type);
237static void xc_call_getter(xc_name_getter_t getter, int count, INTERNAL_FUNCTION_PARAMETERS)
238{
239    long spec;
240    const char *name;
241
242    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
243        return;
244    }
245    if (spec >= 0 && spec < count) {
246        name = getter((zend_uchar) spec);
247        if (name) {
248            /* RETURN_STRING */
249            int len = strlen(name);
250            return_value->value.str.len = len;
251            return_value->value.str.val = estrndup(name, len);
252            return_value->type = IS_STRING; 
253            return;
254        }
255    }
256    RETURN_NULL();
257}
258/* }}} */
259/* {{{ proto string xcache_get_op_type(int op_type) */
260PHP_FUNCTION(xcache_get_op_type)
261{
262    xc_call_getter(xc_get_op_type, xc_get_op_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
263}
264/* }}} */
265/* {{{ proto string xcache_get_data_type(int type) */
266PHP_FUNCTION(xcache_get_data_type)
267{
268    xc_call_getter(xc_get_data_type, xc_get_data_type_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
269}
270/* }}} */
271/* {{{ proto string xcache_get_opcode(int opcode) */
272PHP_FUNCTION(xcache_get_opcode)
273{
274    xc_call_getter(xc_get_opcode, xc_get_opcode_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
275}
276/* }}} */
277/* {{{ proto string xcache_get_op_spec(int op_type) */
278PHP_FUNCTION(xcache_get_op_spec)
279{
280    xc_call_getter(xc_get_op_spec, xc_get_op_spec_count(), INTERNAL_FUNCTION_PARAM_PASSTHRU);
281}
282/* }}} */
283/* {{{ proto string xcache_get_opcode_spec(int opcode) */
284PHP_FUNCTION(xcache_get_opcode_spec)
285{
286    long spec;
287    const xc_opcode_spec_t *opspec;
288
289    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &spec) == FAILURE) {
290        return;
291    }
292    if ((zend_uchar) spec <= xc_get_opcode_spec_count()) {
293        opspec = xc_get_opcode_spec((zend_uchar) spec);
294        if (opspec) {
295            array_init(return_value);
296            add_assoc_long_ex(return_value, ZEND_STRS("ext"), opspec->ext);
297            add_assoc_long_ex(return_value, ZEND_STRS("op1"), opspec->op1);
298            add_assoc_long_ex(return_value, ZEND_STRS("op2"), opspec->op2);
299            add_assoc_long_ex(return_value, ZEND_STRS("res"), opspec->res);
300            return;
301        }
302    }
303    RETURN_NULL();
304}
305/* }}} */
306/* {{{ proto mixed xcache_get_special_value(zval value)
307   XCache internal use only: For decompiler to get static value with type fixed */
308PHP_FUNCTION(xcache_get_special_value)
309{
310    zval *value;
311
312    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
313        return;
314    }
315
316    switch ((Z_TYPE_P(value) & IS_CONSTANT_TYPE_MASK)) {
317    case IS_CONSTANT:
318        *return_value = *value;
319        zval_copy_ctor(return_value);
320        return_value->type = UNISW(IS_STRING, UG(unicode) ? IS_UNICODE : IS_STRING);
321        break;
322
323    case IS_CONSTANT_ARRAY:
324        *return_value = *value;
325        zval_copy_ctor(return_value);
326        return_value->type = IS_ARRAY;
327        break;
328
329    default:
330        RETURN_NULL();
331    }
332}
333/* }}} */
334/* {{{ proto int xcache_get_type(zval value)
335   XCache internal use only for disassembler to get variable type in engine level */
336PHP_FUNCTION(xcache_get_type)
337{
338    zval *value;
339
340    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
341        return;
342    }
343
344    RETURN_LONG(Z_TYPE_P(value));
345}
346/* }}} */
347/* {{{ proto string xcache_coredump(int op_type) */
348PHP_FUNCTION(xcache_coredump)
349{
350    if (xc_test) {
351        raise(SIGSEGV);
352    }
353    else {
354        php_error_docref(NULL TSRMLS_CC, E_WARNING, "xcache.test must be enabled to test xcache_coredump()");
355    }
356}
357/* }}} */
358/* {{{ proto string xcache_is_autoglobal(string name) */
359PHP_FUNCTION(xcache_is_autoglobal)
360{
361    zval *name;
362
363    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &name) == FAILURE) {
364        return;
365    }
366
367#ifdef IS_UNICODE
368    convert_to_unicode(name);
369#else
370    convert_to_string(name);
371#endif
372
373    RETURN_BOOL(zend_u_hash_exists(CG(auto_globals), UG(unicode), Z_STRVAL_P(name), Z_STRLEN_P(name) + 1));
374}
375/* }}} */
376static zend_function_entry xcache_functions[] = /* {{{ */
377{
378    PHP_FE(xcache_coredump,          NULL)
379#ifdef HAVE_XCACHE_ASSEMBLER
380    PHP_FE(xcache_asm,               NULL)
381#endif
382#ifdef HAVE_XCACHE_ENCODER
383    PHP_FE(xcache_encode,            NULL)
384#endif
385#ifdef HAVE_XCACHE_DECODER
386    PHP_FE(xcache_decode_file,       NULL)
387    PHP_FE(xcache_decode_string,     NULL)
388#endif
389    PHP_FE(xcache_get_special_value, NULL)
390    PHP_FE(xcache_get_type,          NULL)
391    PHP_FE(xcache_get_op_type,       NULL)
392    PHP_FE(xcache_get_data_type,     NULL)
393    PHP_FE(xcache_get_opcode,        NULL)
394    PHP_FE(xcache_get_opcode_spec,   NULL)
395    PHP_FE(xcache_is_autoglobal,     NULL)
396    PHP_FE(xcache_get_refcount,      NULL)
397    PHP_FE(xcache_get_isref,         arginfo_xcache_get_isref)
398#ifdef HAVE_XCACHE_DPRINT
399    PHP_FE(xcache_dprint,            NULL)
400#endif
401    PHP_FE_END
402};
403/* }}} */
404
405#ifdef ZEND_WIN32
406#include "dbghelp.h"
407typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
408        CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
409        CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
410        CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
411        );
412
413static PTOP_LEVEL_EXCEPTION_FILTER oldFilter = NULL;
414static HMODULE dbghelpModule = NULL;
415static char crash_dumpPath[_MAX_PATH] = { 0 };
416static MINIDUMPWRITEDUMP dbghelp_MiniDumpWriteDump = NULL;
417
418static LONG WINAPI miniDumperFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) /* {{{ */
419{
420    HANDLE fileHandle;
421    LONG ret = EXCEPTION_CONTINUE_SEARCH;
422
423    SetUnhandledExceptionFilter(oldFilter);
424
425    /* create the file */
426    fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
427
428    if (fileHandle != INVALID_HANDLE_VALUE) {
429        MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
430        BOOL ok;
431
432        exceptionInformation.ThreadId = GetCurrentThreadId();
433        exceptionInformation.ExceptionPointers = pExceptionInfo;
434        exceptionInformation.ClientPointers = FALSE;
435
436        /* write the dump */
437        ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal|MiniDumpWithDataSegs|MiniDumpWithIndirectlyReferencedMemory, &exceptionInformation, NULL, NULL);
438        CloseHandle(fileHandle);
439        if (ok) {
440            zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath);
441            ret = EXCEPTION_EXECUTE_HANDLER;
442        }
443        else {
444            zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError());
445        }
446    }
447    else {
448        zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError());
449    }
450
451    if (xc_disable_on_crash) {
452        xc_disable_on_crash = 0;
453        xc_cacher_disable();
454    }
455
456    return ret;
457}
458/* }}} */
459
460static void xcache_restore_crash_handler() /* {{{ */
461{
462    if (oldFilter) {
463        SetUnhandledExceptionFilter(oldFilter);
464        oldFilter = NULL;
465    }
466}
467/* }}} */
468static void xcache_init_crash_handler() /* {{{ */
469{
470    /* firstly see if dbghelp.dll is around and has the function we need
471       look next to the EXE first, as the one in System32 might be old
472       (e.g. Windows 2000) */
473    char dbghelpPath[_MAX_PATH];
474
475    if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) {
476        char *slash = strchr(dbghelpPath, '\\');
477        if (slash) {
478            strcpy(slash + 1, "DBGHELP.DLL");
479            dbghelpModule = LoadLibrary(dbghelpPath);
480        }
481    }
482
483    if (!dbghelpModule) {
484        /* load any version we can */
485        dbghelpModule = LoadLibrary("DBGHELP.DLL");
486        if (!dbghelpModule) {
487            zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found");
488            return;
489        }
490    }
491
492    dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump");
493    if (!dbghelp_MiniDumpWriteDump) {
494        zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL too old. Get updated dll and put it aside of php_xcache.dll");
495        return;
496    }
497
498#ifdef XCACHE_VERSION_REVISION
499#define REVISION "r" XCACHE_VERSION_REVISION
500#else
501#define REVISION ""
502#endif
503    sprintf(crash_dumpPath, "%s\\php-%s-xcache-%s%s-%lu-%lu.dmp", xc_coredump_dir, zend_get_module_version("standard"), XCACHE_VERSION, REVISION, (unsigned long) time(NULL), (unsigned long) GetCurrentProcessId());
504#undef REVISION
505
506    oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter);
507}
508/* }}} */
509#else
510/* old signal handlers {{{ */
511typedef void (*xc_sighandler_t)(int);
512#define FOREACH_SIG(sig) static xc_sighandler_t old_##sig##_handler = NULL
513#include "util/xc_foreachcoresig.h"
514#undef FOREACH_SIG
515/* }}} */
516static void xcache_signal_handler(int sig);
517static void xcache_restore_crash_handler() /* {{{ */
518{
519#define FOREACH_SIG(sig) do { \
520    if (old_##sig##_handler != xcache_signal_handler) { \
521        signal(sig, old_##sig##_handler); \
522    } \
523    else { \
524        signal(sig, SIG_DFL); \
525    } \
526} while (0)
527#include "util/xc_foreachcoresig.h"
528#undef FOREACH_SIG
529}
530/* }}} */
531static void xcache_init_crash_handler() /* {{{ */
532{
533#define FOREACH_SIG(sig) \
534    old_##sig##_handler = signal(sig, xcache_signal_handler)
535#include "util/xc_foreachcoresig.h"
536#undef FOREACH_SIG
537}
538/* }}} */
539static void xcache_signal_handler(int sig) /* {{{ */
540{
541    xcache_restore_crash_handler();
542    if (xc_coredump_dir && xc_coredump_dir[0]) {
543        if (chdir(xc_coredump_dir) != 0) {
544            /* error, but nothing can do about it
545             * and should'nt print anything which might SEGV again */
546        }
547    }
548    if (xc_disable_on_crash) {
549        xc_disable_on_crash = 0;
550        xc_cacher_disable();
551    }
552    raise(sig);
553}
554/* }}} */
555#endif
556
557/* {{{ incompatible zend extensions handling */
558typedef struct {
559    const char *name;
560    startup_func_t old_startup;
561} xc_incompatible_zend_extension_info_t;
562static xc_incompatible_zend_extension_info_t xc_incompatible_zend_extensions[] = {
563    { "Zend Optimizer", NULL },
564    { "the ionCube PHP Loader", NULL }
565};
566
567static xc_incompatible_zend_extension_info_t *xc_get_incompatible_zend_extension_info(const char *name)
568{
569    size_t i;
570
571    for (i = 0; i < sizeof(xc_incompatible_zend_extensions) / sizeof(xc_incompatible_zend_extensions[0]); ++i) {
572        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = &xc_incompatible_zend_extensions[i];
573        if (strcmp(incompatible_zend_extension_info->name, name) == 0) {
574            return incompatible_zend_extension_info;
575        }
576    }
577
578    return NULL;
579}
580/* }}} */
581static int xc_incompatible_zend_extension_startup_hook(zend_extension *extension) /* {{{ */
582{
583    xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(extension->name);
584    int status;
585    zend_bool catched = 0;
586    zend_llist old_zend_extensions = zend_extensions;
587
588    /* restore */
589    extension->startup = incompatible_zend_extension_info->old_startup;
590    incompatible_zend_extension_info->old_startup = NULL;
591    assert(extension->startup);
592
593    /* hide all extensions from it */
594    zend_extensions.head = NULL;
595    zend_extensions.tail = NULL;
596    zend_extensions.count = 0;
597    zend_extensions.dtor = NULL;
598    zend_llist_add_element(&zend_extensions, extension);
599    extension = zend_get_extension(extension->name);
600
601    assert(extension->startup != xc_incompatible_zend_extension_startup_hook);
602    zend_try {
603        status = extension->startup(extension);
604    } zend_catch {
605        catched = 1;
606    } zend_end_try();
607
608    /* restore */
609    zend_extensions = old_zend_extensions;
610    if (catched) {
611        zend_bailout();
612    }
613    return status;
614}
615/* }}} */
616static int xc_zend_startup(zend_extension *extension) /* {{{ */
617{
618    zend_llist_position lpos;
619    zend_extension *ext;
620
621    ext = (zend_extension *) zend_extensions.head->data;
622    if (strcmp(ext->name, XCACHE_NAME) != 0) {
623        zend_error(E_WARNING, "XCache failed to load itself as the before \"%s\". compatibility downgraded", ext->name);
624    }
625
626    old_compile_file = zend_compile_file;
627    zend_compile_file = xc_check_initial_compile_file;
628
629    for (ext = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &lpos);
630            ext;
631            ext = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &lpos)) {
632        xc_incompatible_zend_extension_info_t *incompatible_zend_extension_info = xc_get_incompatible_zend_extension_info(ext->name);
633        if (incompatible_zend_extension_info) {
634            assert(!incompatible_zend_extension_info->old_startup);
635            incompatible_zend_extension_info->old_startup = ext->startup;
636            ext->startup = xc_incompatible_zend_extension_startup_hook;
637        }
638    }
639    return SUCCESS;
640}
641/* }}} */
642static void xc_zend_shutdown(zend_extension *extension) /* {{{ */
643{
644}
645/* }}} */
646/* {{{ zend extension definition structure */
647static zend_extension xc_zend_extension_entry = {
648    XCACHE_NAME,
649    XCACHE_VERSION,
650    XCACHE_AUTHOR,
651    XCACHE_URL,
652    XCACHE_COPYRIGHT,
653    xc_zend_startup,
654    xc_zend_shutdown,
655    NULL,           /* activate_func_t */
656    NULL,           /* deactivate_func_t */
657    NULL,           /* message_handler_func_t */
658    NULL,           /* op_array_handler_func_t */
659    NULL,           /* statement_handler_func_t */
660    NULL,           /* fcall_begin_handler_func_t */
661    NULL,           /* fcall_end_handler_func_t */
662    NULL,           /* op_array_ctor_func_t */
663    NULL,           /* op_array_dtor_func_t */
664    STANDARD_ZEND_EXTENSION_PROPERTIES
665};
666/* }}} */
667
668/* {{{ PHP_INI */
669PHP_INI_BEGIN()
670    PHP_INI_ENTRY1     ("xcache.coredump_directory",      "", PHP_INI_SYSTEM, xcache_OnUpdateString,   &xc_coredump_dir)
671    PHP_INI_ENTRY1_EX  ("xcache.disable_on_crash",       "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_disable_on_crash, zend_ini_boolean_displayer_cb)
672    PHP_INI_ENTRY1_EX  ("xcache.test",                   "0", PHP_INI_SYSTEM, xcache_OnUpdateBool,     &xc_test,             zend_ini_boolean_displayer_cb)
673    STD_PHP_INI_BOOLEAN("xcache.experimental",           "0", PHP_INI_ALL,    OnUpdateBool,        experimental,      zend_xcache_globals, xcache_globals)
674PHP_INI_END()
675/* }}} */
676static PHP_MINFO_FUNCTION(xcache) /* {{{ */
677{
678    php_info_print_table_start();
679    php_info_print_table_row(2, "XCache Version", XCACHE_VERSION);
680#ifdef XCACHE_VERSION_REVISION
681    php_info_print_table_row(2, "Revision", "r" XCACHE_VERSION_REVISION);
682#endif
683    php_info_print_table_row(2, "Modules Built", XCACHE_MODULES);
684    php_info_print_table_end();
685
686    DISPLAY_INI_ENTRIES();
687}
688/* }}} */
689static PHP_MINIT_FUNCTION(xcache) /* {{{ */
690{
691#ifndef PHP_GINIT
692    ZEND_INIT_MODULE_GLOBALS(xcache, xc_init_globals, xc_shutdown_globals);
693#endif
694    REGISTER_INI_ENTRIES();
695
696    if (xc_coredump_dir && xc_coredump_dir[0]) {
697        xcache_init_crash_handler();
698    }
699
700    if (strcmp(sapi_module.name, "cli") == 0) {
701        char *env;
702        if ((env = getenv("XCACHE_TEST")) != NULL) {
703            xc_test = atoi(env);
704        }
705    }
706
707    xc_init_constant(module_number TSRMLS_CC);
708    xc_shm_init_modules();
709
710    /* must be the first */
711    xcache_zend_extension_add(&xc_zend_extension_entry, 1);
712#ifdef HAVE_XCACHE_OPTIMIZER
713    xc_optimizer_startup_module();
714#endif
715#ifdef HAVE_XCACHE_CACHER
716    xc_cacher_startup_module();
717#endif
718#ifdef HAVE_XCACHE_COVERAGER
719    xc_coverager_startup_module();
720#endif
721#ifdef HAVE_XCACHE_DISASSEMBLER
722    xc_disassembler_startup_module();
723#endif
724
725    return SUCCESS;
726}
727/* }}} */
728static PHP_MSHUTDOWN_FUNCTION(xcache) /* {{{ */
729{
730    if (old_compile_file && zend_compile_file == xc_check_initial_compile_file) {
731        zend_compile_file = old_compile_file;
732        old_compile_file = NULL;
733    }
734
735    if (xc_coredump_dir && xc_coredump_dir[0]) {
736        xcache_restore_crash_handler();
737    }
738    if (xc_coredump_dir) {
739        pefree(xc_coredump_dir, 1);
740        xc_coredump_dir = NULL;
741    }
742#ifndef PHP_GINIT
743#   ifdef ZTS
744    ts_free_id(xcache_globals_id);
745#   else
746    xc_shutdown_globals(&xcache_globals TSRMLS_CC);
747#   endif
748#endif
749
750    UNREGISTER_INI_ENTRIES();
751    xcache_zend_extension_remove(&xc_zend_extension_entry);
752    return SUCCESS;
753}
754/* }}} */
755/* {{{ module dependencies */
756#ifdef STANDARD_MODULE_HEADER_EX
757static zend_module_dep xcache_module_deps[] = {
758    ZEND_MOD_REQUIRED("standard")
759    ZEND_MOD_CONFLICTS("apc")
760    ZEND_MOD_CONFLICTS("eAccelerator")
761    ZEND_MOD_CONFLICTS("Turck MMCache")
762    ZEND_MOD_END
763};
764#endif
765/* }}} */ 
766/* {{{ module definition structure */
767zend_module_entry xcache_module_entry = {
768#ifdef STANDARD_MODULE_HEADER_EX
769    STANDARD_MODULE_HEADER_EX,
770    NULL,
771    xcache_module_deps,
772#else
773    STANDARD_MODULE_HEADER,
774#endif
775    XCACHE_NAME,
776    xcache_functions,
777    PHP_MINIT(xcache),
778    PHP_MSHUTDOWN(xcache),
779    NULL, /* RINIT */
780    NULL, /* RSHUTDOWN */
781    PHP_MINFO(xcache),
782    XCACHE_VERSION,
783#ifdef PHP_GINIT
784    PHP_MODULE_GLOBALS(xcache),
785    PHP_GINIT(xcache),
786    PHP_GSHUTDOWN(xcache),
787#endif
788#ifdef ZEND_ENGINE_2
789    NULL /* ZEND_MODULE_POST_ZEND_DEACTIVATE_N */,
790#else
791    NULL,
792    NULL,
793#endif
794    STANDARD_MODULE_PROPERTIES_EX
795};
796
797#ifdef COMPILE_DL_XCACHE
798ZEND_GET_MODULE(xcache)
799#endif
800/* }}} */
Note: See TracBrowser for help on using the repository browser.