diff options
Diffstat (limited to 'src/tests/shlib')
| -rw-r--r-- | src/tests/shlib/ChangeLog | 22 | ||||
| -rw-r--r-- | src/tests/shlib/t_loader.c | 199 |
2 files changed, 182 insertions, 39 deletions
diff --git a/src/tests/shlib/ChangeLog b/src/tests/shlib/ChangeLog index 82a123eca..32e9b4834 100644 --- a/src/tests/shlib/ChangeLog +++ b/src/tests/shlib/ChangeLog @@ -1,3 +1,25 @@ +2005-02-08 Ken Raeburn <raeburn@mit.edu> + + * t_loader.c (verbose): New variable. + (do_close_1): Drop filename argument. Change messages + accordingly, and only display them if verbose. Line up "done" + messages vertically. + (do_open_1): Likewise. Add library version argument, used when on + AIX, in combination with RTLD_MEMBER. + (do_open): Don't pass filename. Do pass library version; callers + changed. + (do_close): Don't pass filename. + (get_sym_1): Renamed from get_sym, added line number argument. + Print messages if verbose. + (get_sym): New macro. + (xbasename): Function deleted. + (HORIZ): New macro. + (main): Turn off output buffering. Print messages before and + after calling functions in loaded libraries. Disable first set of + tests, that don't call any functions. Test gssapi library without + loading any other libraries, then test it after loading com_err, + and unload com_err first. + 2005-02-02 Ken Raeburn <raeburn@mit.edu> * Makefile.in: New file. diff --git a/src/tests/shlib/t_loader.c b/src/tests/shlib/t_loader.c index 98c99682a..ecd6a4e83 100644 --- a/src/tests/shlib/t_loader.c +++ b/src/tests/shlib/t_loader.c @@ -7,6 +7,8 @@ #include "gssapi/gssapi.h" #define HAVE_DLOPEN 1 +static int verbose = 1; + #ifdef HAVE_DLFCN_H # include <dlfcn.h> #endif @@ -17,15 +19,15 @@ Return value is the library handle. On error, print a message and exit. */ -#define do_open(LIB,FLAGS) do_open_1(LIB,FLAGS,__FILE__,__LINE__) -static void *do_open_1(const char *libname, int lazy, - const char *file, int line); +#define do_open(LIB,REV,FLAGS) do_open_1(LIB,REV,FLAGS,__LINE__) +static void *do_open_1(const char *libname, const char *rev, int lazy, int line); /* Look up a function symbol in the library and return a pointer. The return value may need casting to the correct type. On error, print a message and exit. */ -static void *get_sym(void *libhandle, const char *sym); +static void *get_sym_1(void *libhandle, const char *sym, int line); +#define get_sym(LIB, NAME) get_sym_1(LIB, NAME, __LINE__) #define GET_FSYM(TYPE, LIB, NAME) ((TYPE) get_sym(LIB, NAME)) #define get_gfun(LIB, NAME) ((OM_uint32 KRB5_CALLCONV(*)()) get_sym(LIB, NAME)) @@ -33,17 +35,8 @@ static void *get_sym(void *libhandle, const char *sym); If the OS reports an error in doing so, print a message and exit. */ -#define do_close(X) do_close_1(X, __FILE__, __LINE__) -static void do_close_1(void *libhandle, const char *file, int line); - -static inline const char *xbasename(const char *path) -{ - const char *p = strrchr(path, '/'); - if (p) - return p+1; - else - return path; -} +#define do_close(X) do_close_1(X, __LINE__) +static void do_close_1(void *libhandle, int line); #ifdef HAVE_DLOPEN @@ -53,15 +46,23 @@ static inline const char *xbasename(const char *path) # define SHLIB_SUFFIX ".so" #endif -static void *do_open_1(const char *libname, int lazy, - const char *file, int line) +#define HORIZ 25 + +static void *do_open_1(const char *libname, const char *rev, + int lazy, int line) { void *p; char *namebuf; + size_t sz; - file = xbasename(file); - printf("from %s:%d: do_open(%s)\n", file, line, libname); - namebuf = malloc(strlen(SHLIB_SUFFIX) + strlen(libname) + 4); + if (verbose) + printf("from line %d: do_open(%s)...%*s", line, libname, + HORIZ-strlen(libname), ""); + sz = strlen(SHLIB_SUFFIX) + strlen(libname) + 4; +#ifdef _AIX + sz += strlen(rev) + 8; +#endif + namebuf = malloc(sz); if (namebuf == 0) { perror("malloc"); exit(1); @@ -69,41 +70,62 @@ static void *do_open_1(const char *libname, int lazy, strcpy(namebuf, "lib"); strcat(namebuf, libname); strcat(namebuf, SHLIB_SUFFIX); +#ifdef _AIX + strcat(namebuf, "(shr.o."); + strcat(namebuf, rev); + strcat(namebuf, ")"); +#endif - p = dlopen(namebuf, lazy ? RTLD_LAZY : RTLD_NOW); +#ifndef RTLD_MEMBER +#define RTLD_MEMBER 0 +#endif + p = dlopen(namebuf, (lazy ? RTLD_LAZY : RTLD_NOW) | RTLD_MEMBER); if (p == 0) { fprintf(stderr, "dlopen of %s failed: %s\n", namebuf, dlerror()); exit(1); } free(namebuf); + if (verbose) + printf("done: %p\n", p); return p; } #define SYM_PREFIX "" -static void *get_sym(void *libhandle, const char *symname) +static void *get_sym_1(void *libhandle, const char *symname, int line) { void *s; /* Bah. Fix this later, if we care. */ assert(strlen(SYM_PREFIX) == 0); + if (verbose) + printf("from line %d: get_sym(%s)...%*s", line, symname, + HORIZ-strlen(symname), ""); + s = dlsym(libhandle, symname); if (s == 0) { fprintf(stderr, "symbol %s not found\n", symname); exit(1); } + if (verbose) + printf("done: %p\n", s); return s; } -#define do_close(X) do_close_1(X, __FILE__, __LINE__) -static void do_close_1(void *libhandle, const char *file, int line) +static void do_close_1(void *libhandle, int line) { - file = xbasename(file); - printf("from %s:%d: do_close\n", file, line), fflush(stdout); + if (verbose) { + char pbuf[3*sizeof(libhandle)+4]; + sprintf(pbuf, "%p", libhandle); + printf("from line %d: do_close(%s)...%*s", line, pbuf, + HORIZ-1-strlen(pbuf), ""); + } if (dlclose(libhandle) != 0) { fprintf(stderr, "dlclose failed: %s\n", dlerror()); exit(1); } + if (verbose) + printf("done\n"); } #elif defined _WIN32 @@ -148,19 +170,24 @@ int main() { void *celib, *k5lib, *gsslib, *celib2; - celib = do_open("com_err", 0); - k5lib = do_open("krb5", 0); - gsslib = do_open("gssapi_krb5", 0); - celib2 = do_open("com_err", 0); + (void) setvbuf(stdout, 0, _IONBF, 0); + +#if 0 + /* Simplest test: Load, then unload out of order. */ + celib = do_open("com_err", "3.0", 0); + k5lib = do_open("krb5", "3.2", 0); + gsslib = do_open("gssapi_krb5", "2.2", 0); + celib2 = do_open("com_err", "3.0", 0); do_close(celib); do_close(k5lib); do_close(celib2); do_close(gsslib); +#endif - celib = do_open("com_err", 0); - k5lib = do_open("krb5", 0); - gsslib = do_open("gssapi_krb5", 0); - celib2 = do_open("com_err", 0); + celib = do_open("com_err", "3.0", 0); + k5lib = do_open("krb5", "3.2", 0); + gsslib = do_open("gssapi_krb5", "2.2", 0); + celib2 = do_open("com_err", "3.0", 0); do_close(celib2); { typedef krb5_error_code KRB5_CALLCONV (*ict)(krb5_context *); @@ -171,22 +198,29 @@ int main() krb5_context ctx; krb5_error_code err; +#define CALLING(S) (verbose ? printf("at line %d: calling %s...%*s", __LINE__, #S, (int)(HORIZ+1-strlen(#S)), "") : 0) +#define DONE() (verbose ? printf("done\n") : 0) + + CALLING(krb5_init_context); err = init_context(&ctx); + DONE(); if (err) { fprintf(stderr, "error 0x%lx initializing context\n", (unsigned long) err); exit(1); } + CALLING(krb5_free_context); free_context(ctx); + DONE(); } - celib2 = do_open("com_err", 0); + celib2 = do_open("com_err", "3.0", 0); do_close(celib); do_close(k5lib); do_close(celib2); do_close(gsslib); - celib = do_open("com_err", 1); - gsslib = do_open("gssapi_krb5", 1); + /* Test gssapi_krb5 without having loaded anything else. */ + gsslib = do_open("gssapi_krb5", "2.2", 1); { OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t, gss_ctx_id_t *, gss_name_t, @@ -221,7 +255,9 @@ int main() 10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04" }; + CALLING(gss_import_name); gmaj = import_name(&gmin, &target_name_buf, &service_name, &target); + DONE(); if (gmaj != GSS_S_COMPLETE) { fprintf(stderr, "import_name reports error major 0x%lx minor 0x%lx(%ld)\n", @@ -234,15 +270,100 @@ int main() we're ignoring the error and testing whether we're doing cleanup properly. (Though the internal cleanup needed in the two cases might be different.) */ + CALLING(gss_init_sec_context); gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target, GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER, NULL, &token, &retflags, NULL); + DONE(); /* Ignore success/failure indication. */ - if (token.length) + if (token.length) { + CALLING(gss_release_buffer); release_buffer(&gmin, &token); + DONE(); + } + CALLING(gss_release_name); release_name(&gmin, &target); - if (gctx != GSS_C_NO_CONTEXT) + DONE(); + if (gctx != GSS_C_NO_CONTEXT) { + CALLING(gss_delete_sec_context); delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER); + DONE(); + } + } + do_close(gsslib); + + /* Test gssapi_krb5 with com_err already loaded, then unload + com_err first. */ + celib = do_open("com_err", "3.0", 1); + gsslib = do_open("gssapi_krb5", "2.2", 1); + { + OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t, + gss_ctx_id_t *, gss_name_t, + gss_OID, + OM_uint32, OM_uint32, + gss_channel_bindings_t, + gss_buffer_t, gss_OID *, + gss_buffer_t, + OM_uint32 *, OM_uint32 *) + = get_gfun(gsslib, "gss_init_sec_context"); + OM_uint32 KRB5_CALLCONV (*import_name)(OM_uint32 *, gss_buffer_t, + gss_OID, gss_name_t *) + = get_gfun(gsslib, "gss_import_name"); + OM_uint32 KRB5_CALLCONV (*release_buffer)(OM_uint32 *, gss_buffer_t) + = get_gfun(gsslib, "gss_release_buffer"); + OM_uint32 KRB5_CALLCONV (*release_name)(OM_uint32 *, gss_name_t *) + = get_gfun(gsslib, "gss_release_name"); + OM_uint32 KRB5_CALLCONV (*delete_sec_context)(OM_uint32 *, + gss_ctx_id_t *, + gss_buffer_t) + = get_gfun(gsslib, "gss_delete_sec_context"); + + OM_uint32 gmaj, gmin; + OM_uint32 retflags; + gss_ctx_id_t gctx = GSS_C_NO_CONTEXT; + gss_buffer_desc token; + gss_name_t target; + static gss_buffer_desc target_name_buf = { + 9, "x@mit.edu" + }; + static gss_OID_desc service_name = { + 10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04" + }; + + CALLING(gss_import_name); + gmaj = import_name(&gmin, &target_name_buf, &service_name, &target); + DONE(); + if (gmaj != GSS_S_COMPLETE) { + fprintf(stderr, + "import_name reports error major 0x%lx minor 0x%lx(%ld)\n", + (unsigned long) gmaj, (unsigned long) gmin, + (signed long) gmin); + exit(1); + } + /* This will probably get different errors, depending on + whether we have tickets at the time. Doesn't matter much, + we're ignoring the error and testing whether we're doing + cleanup properly. (Though the internal cleanup needed in + the two cases might be different.) */ + CALLING(gss_init_sec_context); + gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target, + GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER, + NULL, &token, &retflags, NULL); + DONE(); + /* Ignore success/failure indication. */ + if (token.length) { + CALLING(gss_release_buffer); + release_buffer(&gmin, &token); + DONE(); + } + CALLING(gss_release_name); + release_name(&gmin, &target); + DONE(); + if (gctx != GSS_C_NO_CONTEXT) { + CALLING(gss_delete_sec_context); + delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER); + DONE(); + } } do_close(celib); do_close(gsslib); |
