From 3a2b29c2016a57e13d2e3d01fecf733705e5637b Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Fri, 24 Jan 2014 01:51:22 -0800 Subject: [PATCH 1/3] Add zend module api introspection to php-cli Add `--apino` option which outputs PHP's compiled Zend Module API info: $ sapi/cli/php --apino ZEND_MODULE_API_NO: 20131227 ZEND_DEBUG: enabled ZTS: enabled Add `--modinfo /path/to/module.so` which loads the .so (without attempting to register it as an extension) and output the corresponding Zend Module API info the module was compiled with. $ sapi/cli/php --modinfo /usr/libexec/php/hello.so ZEND_MODULE_API_NO: 20121212 ZEND_DEBUG: disabled ZTS: disabled --- sapi/cli/php_cli.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 7c971176b61b5..22c0c1d23d91d 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -116,6 +116,8 @@ PHPAPI extern char *php_ini_scanned_files; #define PHP_MODE_REFLECTION_EXT_INFO 11 #define PHP_MODE_REFLECTION_ZEND_EXTENSION 12 #define PHP_MODE_SHOW_INI_CONFIG 13 +#define PHP_MODE_APINO 14 +#define PHP_MODE_MODINFO 15 cli_shell_callbacks_t cli_shell_callbacks = { NULL, NULL, NULL }; PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks() @@ -170,6 +172,8 @@ const opt_struct OPTIONS[] = { {14, 1, "ri"}, {14, 1, "rextinfo"}, {15, 0, "ini"}, + {16, 0, "apino"}, + {17, 1, "modinfo"}, {'-', 0, NULL} /* end of args */ }; @@ -662,6 +666,7 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ zend_file_handle file_handle; int behavior = PHP_MODE_STANDARD; char *reflection_what = NULL; + char *extapi_module = NULL; volatile int request_started = 0; volatile int exit_status = 0; char *php_optarg = NULL, *orig_optarg = NULL; @@ -898,6 +903,13 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ case 15: behavior = PHP_MODE_SHOW_INI_CONFIG; break; + case 16: + behavior = PHP_MODE_APINO; + break; + case 17: + behavior = PHP_MODE_MODINFO; + extapi_module = php_optarg; + break; default: break; } @@ -1169,6 +1181,52 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ zend_printf("Additional .ini files parsed: %s\n", php_ini_scanned_files ? php_ini_scanned_files : "(none)"); break; } + case PHP_MODE_APINO: + { + zend_bool dbg = 0, zts = 0; +#ifdef ZEND_DEBUG + dbg = 1; +#endif +#ifdef ZTS + zts = 1; +#endif + zend_printf("ZEND_MODULE_API_NO: %d\n", ZEND_MODULE_API_NO); + zend_printf("ZEND_DEBUG: %s\n", dbg ? "enabled" : "disabled"); + zend_printf("ZTS: %s\n", zts ? "enabled" : "disabled"); + break; + } + case PHP_MODE_MODINFO: + { + DL_HANDLE handle = DL_LOAD(extapi_module); + if (!handle) { + const char *err = DL_ERROR(); + if (!err) { + err = "unknown error"; + } + zend_printf("Unable to load dynamic library '%s' - %s\n", + extapi_module, err); + exit_status=1; + goto err; + } + zend_module_entry *(*get_module)(void) = (zend_module_entry *(*)(void))DL_FETCH_SYMBOL(handle, "get_module"); + if (!get_module) { + get_module = (zend_module_entry *(*)(void))DL_FETCH_SYMBOL(handle, "_get_module"); + if (!get_module) { + zend_printf("Invalid library (maybe not a PHP library) '%s'\n", extapi_module); + exit_status=1; + DL_UNLOAD(handle); + goto err; + } + } + zend_module_entry *module = get_module(); + zend_printf("ZEND_MODULE_API_NO: %d\n", module->zend_api); + if (module->zend_api >= 20041030) { + zend_printf("ZEND_DEBUG: %s\n", module->zend_debug ? "enabled" : "disabled"); + zend_printf("ZTS: %s\n", module->zts ? "enabled" : "disabled"); + } + DL_UNLOAD(handle); + break; + } } } zend_end_try(); From 51339ceecee23ddebc1c68c875ff61e33cbe55b2 Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Fri, 24 Jan 2014 02:15:16 -0800 Subject: [PATCH 2/3] Document --apino/--modinfo options in --help --- sapi/cli/php_cli.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 22c0c1d23d91d..e0d9fc0239e30 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -549,6 +549,9 @@ static void php_cli_usage(char *argv0) " --rz Show information about Zend extension .\n" " --ri Show configuration for extension .\n" "\n" + " --apino Show the Module API details for this PHP instance.\n" + " --modinfo <.so> Show information for a Module without fully loading it.\n" + "\n" , prog, prog, prog, prog, prog, prog, prog); } /* }}} */ From 2d2152f160e3940973a0984746d6b4e2cdf40109 Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Fri, 24 Jan 2014 03:08:13 -0800 Subject: [PATCH 3/3] Split dlopen/dlsym into helper method. Reduce copypasta for shared code between dl() and `php --modinfo` --- ext/standard/dl.c | 91 ++++++++++++++++++++++++++-------------------- ext/standard/dl.h | 2 + sapi/cli/php_cli.c | 26 +++---------- 3 files changed, 59 insertions(+), 60 deletions(-) diff --git a/ext/standard/dl.c b/ext/standard/dl.c index 012592381b99b..36452295efe64 100644 --- a/ext/standard/dl.c +++ b/ext/standard/dl.c @@ -97,14 +97,61 @@ PHPAPI PHP_FUNCTION(dl) #define USING_ZTS 0 #endif +PHPAPI zend_module_entry *php_dl_get_module(const char *libpath, DL_HANDLE *phandle, + int error_type, const char *filename TSRMLS_DC) { + zend_module_entry *(*get_module)(void); + + /* load dynamic symbol */ + DL_HANDLE handle = DL_LOAD(libpath); + if (!handle) { +#if PHP_WIN32 + char *err = GET_DL_ERROR(); + if (err && (*err != "")) { + php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, err); + LocalFree(err); + } else { + php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, "Unknown reason"); + } +#else + php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, GET_DL_ERROR()); + GET_DL_ERROR(); /* free the buffer storing the error */ +#endif + return NULL; + } + + get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); + + /* Some OS prepend _ to symbol names while their dynamic linker + * does not do that automatically. Thus we check manually for + * _get_module. */ + + if (!get_module) { + get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module"); + } + + if (!get_module) { + if (DL_FETCH_SYMBOL(handle, "zend_extension_entry") || DL_FETCH_SYMBOL(handle, "_zend_extension_entry")) { + DL_UNLOAD(handle); + php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (appears to be a Zend Extension, try loading using zend_extension=%s from php.ini)", filename); + return NULL; + } + DL_UNLOAD(handle); + php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (maybe not a PHP library) '%s'", filename); + return NULL; + } + if (phandle) { + *phandle = handle; + } + return get_module(); +} + /* {{{ php_load_extension */ PHPAPI int php_load_extension(char *filename, int type, int start_now TSRMLS_DC) { - void *handle; + DL_HANDLE handle; char *libpath; zend_module_entry *module_entry; - zend_module_entry *(*get_module)(void); int error_type; char *extension_dir; @@ -140,47 +187,11 @@ PHPAPI int php_load_extension(char *filename, int type, int start_now TSRMLS_DC) return FAILURE; /* Not full path given or extension_dir is not set */ } - /* load dynamic symbol */ - handle = DL_LOAD(libpath); - if (!handle) { -#if PHP_WIN32 - char *err = GET_DL_ERROR(); - if (err && (*err != "")) { - php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, err); - LocalFree(err); - } else { - php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, "Unknown reason"); - } -#else - php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, GET_DL_ERROR()); - GET_DL_ERROR(); /* free the buffer storing the error */ -#endif - efree(libpath); - return FAILURE; - } + module_entry = php_dl_get_module(libpath, &handle, error_type, filename TSRMLS_CC); efree(libpath); - - get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); - - /* Some OS prepend _ to symbol names while their dynamic linker - * does not do that automatically. Thus we check manually for - * _get_module. */ - - if (!get_module) { - get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module"); - } - - if (!get_module) { - if (DL_FETCH_SYMBOL(handle, "zend_extension_entry") || DL_FETCH_SYMBOL(handle, "_zend_extension_entry")) { - DL_UNLOAD(handle); - php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (appears to be a Zend Extension, try loading using zend_extension=%s from php.ini)", filename); - return FAILURE; - } - DL_UNLOAD(handle); - php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (maybe not a PHP library) '%s'", filename); + if (!module_entry) { return FAILURE; } - module_entry = get_module(); if (module_entry->zend_api != ZEND_MODULE_API_NO) { /* Check for pre-4.1.0 module which has a slightly different module_entry structure :( */ struct pre_4_1_0_module_entry { diff --git a/ext/standard/dl.h b/ext/standard/dl.h index eee70472b5c22..634828fd5eeb2 100644 --- a/ext/standard/dl.h +++ b/ext/standard/dl.h @@ -23,6 +23,8 @@ #ifndef DL_H #define DL_H +PHPAPI zend_module_entry *php_dl_get_module(const char *libpath, DL_HANDLE *phandle, + int error_type, const char *filename TSRMLS_DC); PHPAPI int php_load_extension(char *filename, int type, int start_now TSRMLS_DC); PHPAPI void php_dl(char *file, int type, zval *return_value, int start_now TSRMLS_DC); diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index e0d9fc0239e30..f97cbb3c26902 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -1200,28 +1200,14 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ } case PHP_MODE_MODINFO: { - DL_HANDLE handle = DL_LOAD(extapi_module); - if (!handle) { - const char *err = DL_ERROR(); - if (!err) { - err = "unknown error"; - } - zend_printf("Unable to load dynamic library '%s' - %s\n", - extapi_module, err); - exit_status=1; + DL_HANDLE handle; + zend_module_entry *module = + php_dl_get_module(extapi_module, &handle, + E_WARNING, extapi_module TSRMLS_CC); + if (!module) { + exit_status = 1; goto err; } - zend_module_entry *(*get_module)(void) = (zend_module_entry *(*)(void))DL_FETCH_SYMBOL(handle, "get_module"); - if (!get_module) { - get_module = (zend_module_entry *(*)(void))DL_FETCH_SYMBOL(handle, "_get_module"); - if (!get_module) { - zend_printf("Invalid library (maybe not a PHP library) '%s'\n", extapi_module); - exit_status=1; - DL_UNLOAD(handle); - goto err; - } - } - zend_module_entry *module = get_module(); zend_printf("ZEND_MODULE_API_NO: %d\n", module->zend_api); if (module->zend_api >= 20041030) { zend_printf("ZEND_DEBUG: %s\n", module->zend_debug ? "enabled" : "disabled");