#include "sysdep.h" #include "pe-mdso.h" #include #include #include #include #include #include #include #include extern char * program_name; extern int xatexit(void (*)(void)); static char pe_mdso_tmp_lib_name[] = "/tmp/mdso_XXXXXXXXXXXX"; static char pe_perk_tmp_def_name[] = "/tmp/perk_XXXXXXXXXXXX"; static struct pe_driver_ctx * pe_dctx; struct pe_mdso_lib { dev_t st_dev; ino_t st_ino; char ar_name[24]; }; struct pe_mdso_lib * pe_mdso_lib_arr; struct pe_mdso_lib * pe_mdso_lib_ptr; struct pe_mdso_lib * pe_mdso_lib_cap; static int pe_mdso_perk_init(void) { char * argv[2]; if (pe_dctx) return 0; argv[0] = program_name; argv[1] = 0; return pe_get_driver_ctx(argv,0,0,0,&pe_dctx); } static void pe_mdso_cache_unlink(void) { struct pe_mdso_lib * pe_mdso; for (pe_mdso=pe_mdso_lib_arr; pe_mdsoar_name); } static int pe_mdso_cache_alloc(void) { void * prev; size_t size; size_t nlib; if (pe_mdso_lib_cap > pe_mdso_lib_ptr) return 0; prev = pe_mdso_lib_arr; nlib = pe_mdso_lib_cap - pe_mdso_lib_arr; size = nlib * sizeof(struct pe_mdso_lib); if (!(pe_mdso_lib_arr = calloc(nlib+2,sizeof(struct pe_mdso_lib)))) return -1; if (!prev) xatexit(pe_mdso_cache_unlink); memcpy(pe_mdso_lib_arr,prev,size); pe_mdso_lib_ptr = &pe_mdso_lib_arr[nlib]; pe_mdso_lib_cap = &pe_mdso_lib_arr[nlib+2]; return 0; } const char * pe_mdso_input_name(const char * input_name) { int fdin; int fdout; char * libname; char * argv[8]; struct stat st; struct pe_mdso_lib * pe_mdso; struct pe_unit_ctx * pe_uctx; struct pe_fd_ctx pe_fdctx; struct mdso_driver_ctx * mdso_dctx; /* perk driver context */ if (pe_mdso_perk_init() < 0) return 0; /* defer when input_name cannot be opened */ if ((fdin = open(input_name,O_RDONLY)) < 0) return input_name; /* stat */ if (fstat(fdin,&st) < 0) { close(fdin); pe_free_unit_ctx(pe_uctx); pe_output_error_vector(pe_dctx); return 0; } /* repeated input argument? */ for (pe_mdso=pe_mdso_lib_arr; pe_mdsost_dev == st.st_dev) && (pe_mdso->st_ino == st.st_ino)) { close(fdin); return pe_mdso->ar_name; } } /* defer when perk object/image context cannot be created */ if (pe_get_unit_ctx(pe_dctx,input_name,&pe_uctx) < 0) { close(fdin); return input_name; } /* defer when input file is not an image */ switch (pe_uctx->meta->m_subtype) { case PE_SUBTYPE_DLL: case PE_SUBTYPE_EXE: break; default: close(fdin); pe_free_unit_ctx(pe_uctx); return input_name; } /* image bits */ switch (pe_uctx->meta->m_abi) { case PE_ABI_PE32: argv[1] = "-m32"; break; case PE_ABI_PE64: argv[1] = "-m64"; break; default: close(fdin); pe_free_unit_ctx(pe_uctx); return 0; } /* perk driver fd context (get) */ if ((pe_get_driver_fdctx(pe_dctx,&pe_fdctx)) < 0) { close(fdin); pe_free_unit_ctx(pe_uctx); pe_output_error_vector(pe_dctx); return 0; } /* template init */ memset (&pe_perk_tmp_def_name[10],'X',12); memset (&pe_mdso_tmp_lib_name[10],'X',12); /* perk .def file (create) */ if ((pe_fdctx.fdout = mkstemp(pe_perk_tmp_def_name)) < 0) { close(fdin); pe_free_unit_ctx(pe_uctx); pe_output_error_vector(pe_dctx); return 0; } /* perk driver fd context (set) */ if ((pe_set_driver_fdctx(pe_dctx,&pe_fdctx)) < 0) { close(fdin); pe_free_unit_ctx(pe_uctx); pe_output_error_vector(pe_dctx); return 0; } /* perk .def file (populate) */ if (pe_output_export_symbols(pe_dctx,pe_uctx->meta) < 0) { close(fdin); pe_free_unit_ctx(pe_uctx); pe_output_error_vector(pe_dctx); return 0; }; /* done with perk */ close(fdin); pe_free_unit_ctx(pe_uctx); /* libname */ if ((libname = strrchr(input_name,'/'))) libname++; else if ((libname = strrchr(input_name,'\\'))) libname++; else libname = (char *)input_name; /* cache alloc (as needed) */ if (pe_mdso_cache_alloc() < 0) return 0; /* mdso lib file (create) */ if ((fdout = mkstemp(pe_mdso_tmp_lib_name)) < 0) return 0; /* mdso driver context (argv[1] already set, see above) */ argv[0] = program_name; argv[2] = "--libname"; argv[3] = libname; argv[4] = "--implib"; argv[5] = pe_mdso_tmp_lib_name; argv[6] = pe_perk_tmp_def_name; argv[7] = 0; if (mdso_get_driver_ctx(argv,0,0,0,&mdso_dctx) < 0) { close(fdout); return 0; } /* mdso lib file (generate) */ if (mdso_create_implib_archive(mdso_dctx) < 0) { close(fdout); mdso_output_error_vector(mdso_dctx); mdso_free_driver_ctx(mdso_dctx); return 0; } /* cache */ strcpy(pe_mdso_lib_ptr->ar_name,pe_mdso_tmp_lib_name); pe_mdso_lib_ptr->st_dev = st.st_dev; pe_mdso_lib_ptr->st_ino = st.st_ino; pe_mdso_lib_ptr++; /* all done */ unlink(pe_perk_tmp_def_name); mdso_free_driver_ctx(mdso_dctx); close(fdout); return pe_mdso_tmp_lib_name; }