void ruby_init_loadpath_safe(int safe_level) { VALUE load_path; extern const char ruby_initial_load_paths[]; const char *paths = ruby_initial_load_paths; #if defined LOAD_RELATIVE # if defined HAVE_DLADDR || (defined __CYGWIN__ && defined CCP_WIN_A_TO_POSIX) # define VARIABLE_LIBPATH 1 # else # define VARIABLE_LIBPATH 0 # endif # if VARIABLE_LIBPATH char *libpath; VALUE sopath; # else char libpath[MAXPATHLEN + 1]; size_t baselen; # endif char *p; #if defined _WIN32 || defined __CYGWIN__ # if VARIABLE_LIBPATH sopath = rb_str_tmp_new(MAXPATHLEN); libpath = RSTRING_PTR(sopath); GetModuleFileName(libruby, libpath, MAXPATHLEN); # else GetModuleFileName(libruby, libpath, sizeof libpath); # endif #elif defined(__EMX__) _execname(libpath, sizeof(libpath) - 1); #elif defined(HAVE_DLADDR) Dl_info dli; if (dladdr(expand_include_path, &dli)) { VALUE fname = rb_str_new_cstr(dli.dli_fname); sopath = rb_file_absolute_path(fname, Qnil); rb_str_resize(fname, 0); } else { sopath = rb_str_new(0, 0); } libpath = RSTRING_PTR(sopath); #endif #if !VARIABLE_LIBPATH libpath[sizeof(libpath) - 1] = '\0'; #endif #if defined DOSISH translit_char(libpath, '\\', '/'); #elif defined __CYGWIN__ { # if VARIABLE_LIBPATH const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE; size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0); if (newsize > 0) { VALUE rubylib = rb_str_tmp_new(newsize); p = RSTRING_PTR(rubylib); if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) { rb_str_resize(sopath, 0); sopath = rubylib; libpath = p; } } # else char rubylib[FILENAME_MAX]; cygwin_conv_to_posix_path(libpath, rubylib); strncpy(libpath, rubylib, sizeof(libpath)); # endif } #endif p = strrchr(libpath, '/'); if (p) { *p = 0; if (p - libpath > 3 && !(STRCASECMP(p - 4, "/bin") && strcmp(p - 4, "/lib"))) { p -= 4; *p = 0; } } #if !VARIABLE_LIBPATH else { strlcpy(libpath, ".", sizeof(libpath)); p = libpath + 1; } baselen = p - libpath; #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen) #else rb_str_set_len(sopath, p - libpath); #define BASEPATH() rb_str_dup(sopath) #endif #define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), path, len) #else #define RUBY_RELATIVE(path, len) rubylib_mangled_path(path, len) #endif #define incpush(path) rb_ary_push(load_path, (path)) load_path = GET_VM()->load_path; if (safe_level == 0) { ruby_push_include(getenv("RUBYLIB"), identical_path); } while (*paths) { size_t len = strlen(paths); incpush(RUBY_RELATIVE(paths, len)); paths += len + 1; } }
jint AWT_OnLoad(JavaVM *vm, void *reserved) { Dl_info dlinfo; char buf[MAXPATHLEN]; int32_t len; char *p, *tk = 0; JNI_OnLoad_type *JNI_OnLoad_ptr; struct utsname name; JNIEnv *env = (JNIEnv *)JNU_GetEnv(vm, JNI_VERSION_1_2); void *v; char *envvar; jstring fmanager = NULL; jstring fmProp = NULL; if (awtHandle != NULL) { /* Avoid several loading attempts */ return JNI_VERSION_1_2; } jvm = vm; /* Get address of this library and the directory containing it. */ dladdr((void *)JNI_OnLoad, &dlinfo); realpath((char *)dlinfo.dli_fname, buf); len = strlen(buf); p = strrchr(buf, '/'); /* * 1. Set the "sun.font.fontmanager" system property, * 2. Choose the library image name. */ fmProp = (*env)->NewStringUTF(env, "sun.font.fontmanager"); /* Check if toolkit is specified in env variable */ #ifdef MACOSX envvar = getenv("AWT_TOOLKIT"); if (envvar && strstr(envvar, "XToolkit")) { #endif fmanager = (*env)->NewStringUTF(env, "sun.awt.X11FontManager"); tk = "/xawt/libmawt"; #ifdef MACOSX } else { fmanager = (*env)->NewStringUTF(env, "sun.font.CFontManager"); tk = "/lwawt/liblwawt"; } #endif if (fmanager && fmProp) { JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", fmProp, fmanager); } /* Calculate library name to load */ #ifndef MACOSX if (AWTIsHeadless()) { strcpy(p, "/headless/libmawt"); } else if (tk) { #endif strcpy(p, tk); #ifndef MACOSX } #endif #ifdef MACOSX strcat(p, ".dylib"); #else strcat(p, ".so"); #endif if (tk) { JNU_CallStaticMethodByName(env, NULL, "java/lang/System", "load", "(Ljava/lang/String;)V", JNU_NewStringPlatform(env, buf)); awtHandle = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); } return JNI_VERSION_1_2; }
void test_dl(int step) { Dl_info di; dladdr(free, &di); printf("di.dli_fname %s\n", di.dli_fname); printf("di.dli_sname %s\n", di.dli_sname); }
bool dynamic_link( const char* library, const dynamic_link_descriptor descriptors[], size_t n, size_t required, dynamic_link_handle *handle ) { // Get library handle in case it is already loaded into the current process #if _WIN32||_WIN64 dynamic_link_handle library_handle = GetModuleHandle( library ); #else dynamic_link_handle library_handle = dlopen( NULL, RTLD_LAZY ); #endif /* _WIN32||_WIN64 */ // Get descriptors from the library if ( library_handle && dynamic_link( library_handle, descriptors, n, required ) ) { #if !__TBB_DYNAMIC_LOAD_ENABLED && !__TBB_TASK_CPP_DIRECTLY_INCLUDED return true; #else // The library have been loaded by another module and contains requested symbols. // But after we obtained the library's handle it can be unloaded by another thread // invalidating our handle copy. Therefore we need to pin the library in memory. #if _WIN32||_WIN64 char library_full_name[ MAX_PATH+1 ]; // Get library's name from earlier found handle if ( GetModuleFileName( library_handle, library_full_name, MAX_PATH+1 ) ) { // Pin the library library_handle = LoadLibrary( library_full_name ); if ( library_handle == NULL ) { int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_lib_not_found, library_full_name, err ); } // if } // if #else /* !WIN */ Dl_info info; // Get library's name from earlier found symbol if ( dladdr( (void*)*descriptors[0].handler, &info ) ) { // Pin the library library_handle = dlopen( info.dli_fname, RTLD_LAZY ); if ( library_handle == NULL ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_lib_not_found, info.dli_fname, err ); } // if } // if #endif /* !WIN */ else { // The library have been unloaded by another thread library_handle = 0; } if ( library_handle ) { // If original library was unloaded before we pinned it // and then another module loaded in its place, the earlier // found symbols would become invalid. So revalidate them. if ( !dynamic_link( library_handle, descriptors, n, required ) ) { // Wrong library. dynamic_unlink(library_handle); library_handle = 0; } } if ( !library_handle ) { // Failed to pin the library, so clear the descriptors too. for( size_t i=0; i<n; ++i ) *descriptors[i].handler = 0; } #endif /* __TBB_DYNAMIC_LOAD_ENABLED */ } else { library_handle = 0; } #if __TBB_DYNAMIC_LOAD_ENABLED || __TBB_TASK_CPP_DIRECTLY_INCLUDED if ( !library_handle ) { #if _WIN32||_WIN64 // Prevent Windows from displaying silly message boxes if it fails to load library // (e.g. because of MS runtime problems - one of those crazy manifest related ones) #if _XBOX library_handle = LoadLibrary (library); #else library_handle = NULL; // Construct absolute path to the library to avoid security issue. size_t const len = MAX_PATH + 1; char path[ len ]; size_t rc = abs_path( library, path, len ); if ( 0 < rc && rc < len ) { UINT prev_mode = SetErrorMode (SEM_FAILCRITICALERRORS); library_handle = LoadLibrary (path); SetErrorMode (prev_mode); if ( library_handle == NULL ) { int err = GetLastError(); DYNAMIC_LINK_WARNING( dl_lib_not_found, path, err ); } // if } // if #endif /* !_XBOX */ #else /* !WIN */ library_handle = dlopen( library, RTLD_LAZY ); if ( library_handle == NULL ) { char const * err = dlerror(); DYNAMIC_LINK_WARNING( dl_lib_not_found, library, err ); } // if #endif /* !WIN */ if( library_handle ) { if( !dynamic_link( library_handle, descriptors, n, required ) ) { // The loaded library does not contain all the expected entry points dynamic_unlink( library_handle ); library_handle = NULL; } } } #endif /* __TBB_DYNAMIC_LOAD_ENABLED */ if ( library_handle ) { if ( handle ) *handle = library_handle; #if __TBB_BUILD else handles.add_handle( library_handle ); #endif /* __TBB_BUILD */ return true; } return false; }
void LLVMState::show_machine_code(void* buffer, size_t size) { #if defined(IS_X86) || defined(IS_X8664) #ifndef RBX_WINDOWS ud_t ud; ud_init(&ud); #ifdef IS_64BIT_ARCH ud_set_mode(&ud, 64); #else ud_set_mode(&ud, 32); #endif ud_set_syntax(&ud, UD_SYN_ATT); ud_set_input_buffer(&ud, reinterpret_cast<uint8_t*>(buffer), size); while(ud_disassemble(&ud)) { void* address = reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(buffer) + ud_insn_off(&ud)); llvm::outs() << format("%10p", address) << " "; llvm::outs() << format("%-24s", ud_insn_asm(&ud)); if(ud.operand[0].type == UD_OP_JIMM) { const void* addr = (const void*)((uintptr_t)buffer + ud.pc + (int)ud.operand[0].lval.udword); llvm::outs() << " ; " << addr; if(ud.mnemonic == UD_Icall) { Dl_info info; if(dladdr((void*)addr, &info)) { int status = 0; char* cpp_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &status); if(status >= 0) { // Chop off the arg info from the signature output char *paren = strstr(cpp_name, "("); *paren = 0; llvm::outs() << " " << cpp_name; free(cpp_name); } else { llvm::outs() << " " << info.dli_sname; } } } } for(uint8_t i = 0; i < 2; i++) { if(ud.operand[i].type == UD_OP_IMM) { Dl_info info; if(dladdr((void*)ud.operand[i].lval.uqword, &info)) { llvm::outs() << " ; " << info.dli_sname; break; // only do one } } } llvm::outs() << "\n"; } #endif // !RBX_WINDOWS #else JITDisassembler disassembler(buffer, size); std::string output = disassembler.print_machine_code(); std::cout << output; #endif // !IS_X86 }
EAPI Eina_Prefix * eina_prefix_new(const char *argv0, void *symbol, const char *envprefix, const char *sharedir, const char *magicsharefile, const char *pkg_bin, const char *pkg_lib, const char *pkg_data, const char *pkg_locale) { Eina_Prefix *pfx; char *p, buf[4096], *tmp, *magic = NULL; struct stat st; const char *p1, *p2; const char *pkg_bin_p = NULL; const char *pkg_lib_p = NULL; const char *pkg_data_p = NULL; const char *pkg_locale_p = NULL; const char *bindir = "bin"; const char *libdir = "lib"; const char *datadir = "share"; const char *localedir = "share"; DBG("EINA PREFIX: argv0=%s, symbol=%p, magicsharefile=%s, envprefix=%s", argv0, symbol, magicsharefile, envprefix); pfx = calloc(1, sizeof(Eina_Prefix)); if (!pfx) return NULL; /* if provided with a share dir use datadir/sharedir as the share dir */ if (sharedir) { int len; len = snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", datadir, sharedir); if (len > 0) { #ifdef _WIN32 /* on win32 convert / to \ for path here */ for (p = buf + strlen(datadir) + strlen(DSEP_S); *p; p++) { if (*p == '/') *p = DSEP_C; } #endif tmp = alloca(len + 1); strcpy(tmp, buf); datadir = tmp; } } if (magicsharefile) { magic = alloca(strlen(magicsharefile)); strcpy(magic, magicsharefile); #ifdef _WIN32 /* on win32 convert / to \ for path here */ for (p = magic; *p; p++) { if (*p == '/') *p = DSEP_C; } #endif } /* look at compile-time package bin/lib/datadir etc. and figure out the * bin, lib and data dirs from these, if possible. i.e. * bin = /usr/local/bin * lib = /usr/local/lib * data = /usr/local/share/enlightenment * thus they all have a common prefix string of /usr/local/ and * bindir = bin * libdir = lib * datadir = share/enlightenment * this addresses things like libdir is lib64 or lib32 or other such * junk distributions like to do so then: * bin = /usr/local/bin * lib = /usr/local/lib64 * data = /usr/local/share/enlightenment * then * bindir = bin * libdir = lib64 * datadir = share/enlightennment * in theory this should also work with debians new multiarch style like * bindir = bin * libdir = lib/i386-linux-gnu * or * libdir = lib/x86_64-linux-gnu * all with a common prefix that can be relocated */ /* 1. check last common char in bin and lib strings */ for (p1 = pkg_bin, p2 = pkg_lib; *p1 && *p2; p1++, p2++) { if (*p1 != *p2) { pkg_bin_p = p1; pkg_lib_p = p2; break; } } /* 1. check last common char in bin and data strings */ for (p1 = pkg_bin, p2 = pkg_data; *p1 && *p2; p1++, p2++) { if (*p1 != *p2) { pkg_data_p = p2; break; } } /* 1. check last common char in bin and locale strings */ for (p1 = pkg_bin, p2 = pkg_locale; *p1 && *p2; p1++, p2++) { if (*p1 != *p2) { pkg_locale_p = p2; break; } } /* 2. if all the common string offsets match we compiled with a common prefix */ if (((pkg_bin_p - pkg_bin) == (pkg_lib_p - pkg_lib)) && ((pkg_bin_p - pkg_bin) == (pkg_data_p - pkg_data)) && ((pkg_bin_p - pkg_bin) == (pkg_locale_p - pkg_locale)) ) { bindir = pkg_bin_p; libdir = pkg_lib_p; datadir = pkg_data_p; localedir = pkg_locale_p; DBG("Prefix relative bindir = %s", bindir); DBG("Prefix relative libdir = %s", libdir); DBG("Prefix relative datadir = %s", datadir); DBG("Prefix relative localedir = %s", localedir); } /* 3. some galoot thought it awesome not to give us a common prefix at compile time * so fall back to the compile time directories. we are no longer relocatable */ else { STRDUP_REP(pfx->prefix_path_bin, pkg_bin); STRDUP_REP(pfx->prefix_path_lib, pkg_lib); STRDUP_REP(pfx->prefix_path_data, pkg_data); STRDUP_REP(pfx->prefix_path_locale, pkg_locale); pfx->no_common_prefix = 1; DBG("Can't work out a common prefix - compiled in fallback"); } /* if user provides env vars - then use that or also more specific sub * dirs for bin, lib, data and locale */ if ((envprefix) && (_get_env_vars(pfx, envprefix, bindir, libdir, datadir, localedir) > 0)) { pfx->env_used = 1; return pfx; } #ifdef HAVE_DLADDR DBG("Try dladdr on %p", symbol); if (symbol) { Dl_info info_dl; if (dladdr(symbol, &info_dl)) { DBG("Dlinfo worked"); if (info_dl.dli_fname) { DBG("Dlinfo dli_fname = %s", info_dl.dli_fname); # ifdef _WIN32 if (info_dl.dli_fname[0] && (info_dl.dli_fname[1] == ':')) # else if (info_dl.dli_fname[0] == DSEP_C) # endif { INF("Dlsym gave full path = %s", info_dl.dli_fname); STRDUP_REP(pfx->exe_path, info_dl.dli_fname); } } } } #endif /* no env var - examine process and possible argv0 */ if ((argv0) && (!pfx->exe_path) && (symbol)) { #ifndef _WIN32 if (!_try_proc(pfx, symbol)) { #endif if (!_try_argv(pfx, argv0)) { _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); return pfx; } #ifndef _WIN32 } #endif } if (!pfx->exe_path) { WRN("Fallback - nothing found"); _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); return pfx; } /* _exe_path is now a full absolute path TO this exe - figure out rest */ /* if * exe = /blah/whatever/bin/exe * or * exe = /blah/whatever/lib/libexe.so * then * prefix = /blah/whatever * bin_dir = /blah/whatever/bin * data_dir = /blah/whatever/share/enlightenment * lib_dir = /blah/whatever/lib */ DBG("From exe %s figure out the rest", pfx->exe_path); p = strrchr(pfx->exe_path, DSEP_C); if (p) { p--; while (p >= pfx->exe_path) { if (*p == DSEP_C) { pfx->prefix_path = malloc(p - pfx->exe_path + 1); if (pfx->prefix_path) { strncpy(pfx->prefix_path, pfx->exe_path, p - pfx->exe_path); pfx->prefix_path[p - pfx->exe_path] = 0; DBG("Have prefix = %s", pfx->prefix_path); /* bin */ snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", pfx->prefix_path, bindir); STRDUP_REP(pfx->prefix_path_bin, buf); DBG("Have bin = %s", pfx->prefix_path_bin); /* lib */ snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", pfx->prefix_path, libdir); STRDUP_REP(pfx->prefix_path_lib, buf); DBG("Have lib = %s", pfx->prefix_path_lib); /* locale */ snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", pfx->prefix_path, localedir); STRDUP_REP(pfx->prefix_path_locale, buf); DBG("Have locale = %s", pfx->prefix_path_locale); /* check if magic file is there - then our guess is right */ if (magic) { DBG("Magic = %s", magic); snprintf(buf, sizeof(buf), "%s" DSEP_S "%s" DSEP_S "%s", pfx->prefix_path, datadir, magic); DBG("Check in %s", buf); } if ((!magic) || (stat(buf, &st) == 0)) { if (buf[0]) DBG("Magic path %s stat passed", buf); else DBG("No magic file"); snprintf(buf, sizeof(buf), "%s" DSEP_S "%s", pfx->prefix_path, datadir); STRDUP_REP(pfx->prefix_path_data, buf); } /* magic file not there. time to start hunting! */ else { WRN("Magic failed"); _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); } } else { WRN("No Prefix path (alloc fail)"); _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); } return pfx; } p--; } } WRN("Final fallback"); _fallback(pfx, pkg_bin, pkg_lib, pkg_data, pkg_locale, envprefix); return pfx; }
/* * Sets $funamep to the name of the function $addr is contained within. * If $fnamep is not NULL sets it to the name of the DSO where function * is defined. Returns 1 if everything is OK, 0 if the name was not * found, or -1 if it is not to be reported. */ static int addr2name(char const **fnamep, char const **funamep, void const *addr) { static struct dso_st *seen; Dl_info info; char const *fname; struct dso_st *dso; /* Find the file that defined the function of $addr. */ if (fnamep) *fnamep = "[???]"; if (!dladdr(addr, &info)) /* We're in trouble, don't do anything. */ return report_function(NULL) ? 0 : -1; if (!info.dli_fname) /* Should not happen either. */ return report_function(NULL) ? 0 : -1; /* Check whether calls to this DSO is to be reported here * to avoid opening it unnecessarily. */ if (!(fname = report_dso(info.dli_fname))) return -1; if (fnamep) *fnamep = fname; if (info.dli_sname) { /* dladdr() managed to do the hard work for us. */ *funamep = info.dli_sname; return report_function(*funamep) ? 1 : -1; } else if (info.dli_saddr) /* info.dli_addr may be more accurate than $addr. */ addr = info.dli_saddr; /* It is up to us to find out the function name from info.dli_fname. * First we need to get contextual information we cache in $seen. */ for (dso = seen; ; dso = dso->next) { if (dso == NULL) { int hfile; off_t fsize; void const *file; struct dso_st newdso; /* Never saw this DSO before, let's meet. * TODO I think .dli_fname becomes incorrect * if the program chdir()ed elsewhere. */ if (!getdso(&newdso, info.dli_fname, &hfile, &file, &fsize)) return report_function(NULL) ? 0 : -1; *funamep = getsym(&newdso, info.dli_fbase, addr); /* Try to remember it. */ if ((dso = malloc(sizeof(*dso))) != NULL) { memcpy(dso, &newdso, sizeof(*dso)); dso->next = seen; seen = dso; } else { /* Failed, clean up what getdso() did. */ LOGIT("malloc(%zu): %m", sizeof(*dso)); munmap((void *)file, fsize); close(hfile); } return report_function(*funamep) ? *funamep != NULL : -1; } else if (dso->fname == info.dli_fname) { /* info.dli_fname pointers point to some program * header and are the same for all invocations. */ *funamep = getsym(dso, info.dli_fbase, addr); return report_function(*funamep) ? *funamep != NULL : -1; } /* if */ } /* for */ } /* addr2name */
struct ast_vector_string *__ast_bt_get_symbols(void **addresses, size_t num_frames) { struct ast_vector_string *return_strings; int stackfr; bfd *bfdobj; long allocsize; char msg[MSG_BUFF_LEN]; static pthread_mutex_t bfd_mutex = PTHREAD_MUTEX_INITIALIZER; return_strings = malloc(sizeof(struct ast_vector_string)); if (!return_strings) { return NULL; } if (AST_VECTOR_INIT(return_strings, num_frames)) { free(return_strings); return NULL; } for (stackfr = 0; stackfr < num_frames; stackfr++) { int symbolcount; struct bfd_data data = { .return_strings = return_strings, .msg = msg, .pc = (bfd_vma)(uintptr_t) addresses[stackfr], .found = 0, .dynamic = 0, }; msg[0] = '\0'; if (!dladdr((void *)(uintptr_t) data.pc, &data.dli)) { continue; } data.libname = strrchr(data.dli.dli_fname, '/'); if (!data.libname) { data.libname = data.dli.dli_fname; } else { data.libname++; } pthread_mutex_lock(&bfd_mutex); /* Using do while(0) here makes it easier to escape and clean up */ do { bfdobj = bfd_openr(data.dli.dli_fname, NULL); if (!bfdobj) { break; } /* bfd_check_format does more than check. It HAS to be called */ if (!bfd_check_format(bfdobj, bfd_object)) { break; } data.has_syms = !!(bfd_get_file_flags(bfdobj) & HAS_SYMS); data.dynamic = !!(bfd_get_file_flags(bfdobj) & DYNAMIC); if (!data.has_syms) { break; } allocsize = data.dynamic ? bfd_get_dynamic_symtab_upper_bound(bfdobj) : bfd_get_symtab_upper_bound(bfdobj); if (allocsize < 0) { break; } data.syms = malloc(allocsize); if (!data.syms) { break; } symbolcount = data.dynamic ? bfd_canonicalize_dynamic_symtab(bfdobj, data.syms) : bfd_canonicalize_symtab(bfdobj, data.syms); if (symbolcount < 0) { break; } bfd_map_over_sections(bfdobj, process_section, &data); } while(0); if (bfdobj) { bfd_close(bfdobj); free(data.syms); data.syms = NULL; } pthread_mutex_unlock(&bfd_mutex); /* Default output, if we cannot find the information within BFD */ if (!data.found) { snprintf(msg, sizeof(msg), "%s %s()", data.libname, S_OR(data.dli.dli_sname, "<unknown>")); AST_VECTOR_APPEND(return_strings, strdup(msg)); } } return return_strings; } #else struct ast_vector_string *__ast_bt_get_symbols(void **addresses, size_t num_frames) { char **strings; struct ast_vector_string *return_strings; int i; return_strings = malloc(sizeof(struct ast_vector_string)); if (!return_strings) { return NULL; } if (AST_VECTOR_INIT(return_strings, num_frames)) { free(return_strings); return NULL; } strings = backtrace_symbols(addresses, num_frames); if (strings) { for (i = 0; i < num_frames; i++) { AST_VECTOR_APPEND(return_strings, strdup(strings[i])); } free(strings); } return return_strings; }
int diag_backtrace(diag_output_t *o, diag_backtrace_param_t *p, diag_context_t *c) { char frame[128]; char addr_buf[20]; char offset_buf[20]; char name_buf[80]; char *name; const char *module_path, *module; int count, cur, rc; unw_context_t ctx; unw_cursor_t csr; unw_word_t ip, offp; #if DIAG_PLATFORM_LINUX || DIAG_PLATFORM_FREEBSD || DIAG_PLATFORM_MACOSX Dl_info info; #endif if (p->backtrace_count && p->backtrace_count < DIAG_BT_LIMIT) { count = p->backtrace_count; } else { count = DIAG_BT_LIMIT; } rc = unw_getcontext(&ctx); if (!rc) { rc = unw_init_local(&csr, &ctx); } if (rc) { return DIAG_ERR_INIT; } cur = 0; while ((rc = unw_step(&csr)) > 0) { cur++; if (cur > count) { break; } unw_get_reg(&csr, UNW_REG_IP, &ip); if (!ip) { break; } add_int(addr_buf, addr_buf + sizeof addr_buf - 1, ip, 16); rc = unw_get_proc_name(&csr, name_buf, sizeof name_buf, &offp); if (rc && rc != UNW_ENOMEM) { name = NULL; } else { name = name_buf; } module = module_path = NULL; #if DIAG_PLATFORM_LINUX || DIAG_PLATFORM_FREEBSD || DIAG_PLATFORM_MACOSX if (p->backtrace_fields & (DIAG_BTFIELDS_MODULE_PATH | DIAG_BTFIELDS_MODULE_NAME)) { if ((rc = dladdr((void *)ip, &info)) != 0) { module_path = info.dli_fname; module = strrchr(module_path, '/'); if (module) { module += 1; } } } #endif add_int(offset_buf, offset_buf + sizeof offset_buf - 1, offp, 16); output_frame(frame, frame + sizeof frame - 1, p->backtrace_fields, module_path, module, name, offset_buf, addr_buf); if (o->output_mode == DIAG_CALL_FN) { o->output_fn(o->user_data, frame); } else { write(o->outfile, frame, strlen(frame)); write(o->outfile, "\n", 1); } } return 0; }
void funk2_signal_segv_handler(int signum, siginfo_t* info, void* ptr) { int i; int f = 0; ucontext_t* ucontext = (ucontext_t*)ptr; Dl_info dlinfo; void** bp = 0; void* ip = 0; status("funk2_signal_segv_handler: Segmentation Fault!"); status("funk2_signal_segv_handler: info.si_signo = %d", signum); status("funk2_signal_segv_handler: info.si_errno = %d", info->si_errno); status("funk2_signal_segv_handler: info.si_code = %d", info->si_code); status("funk2_signal_segv_handler: info.si_addr = %p", info->si_addr); for(i = 0; i < NGREG; i++) { status("funk2_signal_segv_handler: reg[%02d] = 0x" REGFORMAT, i, ucontext->uc_mcontext.gregs[i]); } #ifndef SIGSEGV_NOSTACK # if defined(SIGSEGV_STACK_IA64) || defined(SIGSEGV_STACK_X86) # if defined(SIGSEGV_STACK_IA64) ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP]; bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP]; # elif defined(SIGSEGV_STACK_X86) ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP]; bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP]; # endif status("funk2_signal_segv_handler: Stack trace: bp=%p, ip=%p", bp, ip); while(bp) { const char* symname = "unknown_symbol"; const char* filename = "unknown_filename"; unsigned long dli_saddr = 0; if(dladdr(ip, &dlinfo)) { symname = dlinfo.dli_sname; filename = dlinfo.dli_fname; dli_saddr = (unsigned long)dlinfo.dli_saddr; } # ifndef NO_CPP_DEMANGLE int status_value; char* tmp = __cxa_demangle(symname, NULL, 0, &status_value); if (status_value == 0 && tmp) { symname = tmp; } # endif status("funk2_signal_segv_handler: % 2d: %p <%s+%lu> (%s)", ++f, ip, symname, (unsigned long)ip - (unsigned long)dli_saddr, filename); # ifndef NO_CPP_DEMANGLE if (tmp) { free(tmp); } # endif if(symname && !strcmp(symname, "main")) { break; } ip = bp[1]; bp = (void**)bp[0]; } # else status("funk2_signal_segv_handler: Stack trace (non-dedicated):"); sz = backtrace(bt, 20); strings = backtrace_symbols(bt, sz); for(i = 0; i < sz; ++i) status("funk2_signal_segv_handler: %s", strings[i]); # endif status("funk2_signal_segv_handler: End of stack trace."); #else status("funk2_signal_segv_handler: Not printing stack strace."); #endif }
static void signal_segv(int signum, siginfo_t* info, void*ptr) { size_t i; #if defined(NGREG) ucontext_t *ucontext = (ucontext_t*)ptr; #endif /* #if defined(NGREG) */ #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) int f = 0; Dl_info dlinfo; void **bp = 0; void *ip = 0; #endif #if defined(HAVE_EXECINFO_H) void *bt[20]; char **strings; size_t sz; #endif /* #if defined(HAVE_EXECINFO_H) */ openlog("memcached", LOG_PID, LOG_LOCAL0); syslog(LOG_ALERT, "Segmentation Fault!\n"); syslog(LOG_ALERT, "info.si_signo = %d\n", signum); syslog(LOG_ALERT, "info.si_errno = %d\n", info->si_errno); syslog(LOG_ALERT, "info.si_code = %d\n", info->si_code); syslog(LOG_ALERT, "info.si_addr = %p\n", info->si_addr); #if defined(NGREG) for(i = 0; i < NGREG; i++) syslog(LOG_ALERT, "reg[%02lu] = 0x" REGFORMAT "\n", i, ucontext->uc_mcontext.gregs[i]); #endif /* #if defined(NGREG) */ #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) # if defined(SIGSEGV_STACK_IA64) ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP]; bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP]; # elif defined(SIGSEGV_STACK_X86) ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP]; bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP]; # endif syslog(LOG_ALERT, "Stack trace:\n"); while(ip) { if(!dladdr(ip, &dlinfo)) break; const char *symname = dlinfo.dli_sname; #ifndef NO_CPP_DEMANGLE int status; char *tmp = __cxa_demangle(symname, NULL, 0, &status); if(status == 0 && tmp) symname = tmp; #endif syslog(LOG_ALERT, "% 2d: %p <%s+%u> (%s)\n", ++f, ip, symname, (unsigned)(ip - dlinfo.dli_saddr), dlinfo.dli_fname); #ifndef NO_CPP_DEMANGLE if(tmp) free(tmp); #endif if (bp == NULL) { break; } if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main")) break; ip = bp[1]; bp = (void**)bp[0]; } #endif syslog(LOG_ALERT, "End of stack trace\n"); closelog(); #if defined(HAVE_EXECINFO_H) openlog("memcached", LOG_PID, LOG_LOCAL0); syslog(LOG_ALERT, "Stack trace (non-dedicated):\n"); sz = backtrace(bt, 20); strings = backtrace_symbols(bt, sz); for(i = 0; i < sz; ++i) syslog(LOG_ALERT, "%s\n", strings[i]); syslog(LOG_ALERT, "End of stack trace (non-dedicated)\n"); closelog(); #endif /* #if defined(HAVE_EXECINFO_H) */ (void) i; /* consume i so we don't get a compiler warning. */ exit (-1); }
void runSuccess1() { Dl_info info; dladdr(NULL, &info); }
void runSuccess() { Dl_info info; dladdr(anystring(), &info); }
void runFailure() { Dl_info info; dladdr(anystring(), NULL); }
static void signal_segv(int signum, siginfo_t* info, void*ptr) { static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"}; size_t i; const char *si_code_str; ucontext_t *ucontext = (ucontext_t*)ptr; #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) int f = 0; Dl_info dlinfo; void **bp = 0; void *ip = 0; #else void *bt[20]; char **strings; size_t sz; #endif if (signum == SIGSEGV) { jack_error("Segmentation Fault!"); } else if (signum == SIGABRT) { jack_error("Abort!"); } else if (signum == SIGILL) { jack_error("Illegal instruction!"); } else if (signum == SIGFPE) { jack_error("Floating point exception!"); } else { jack_error("Unknown bad signal catched!"); } if (info->si_code >= 0 && info->si_code < 3) si_code_str = si_codes[info->si_code]; else si_code_str = "unknown"; jack_error("info.si_signo = %d", signum); jack_error("info.si_errno = %d", info->si_errno); jack_error("info.si_code = %d (%s)", info->si_code, si_code_str); jack_error("info.si_addr = %p", info->si_addr); #if !defined(__alpha__) && !defined(__ia64__) && !defined(__FreeBSD_kernel__) && !defined(__arm__) && !defined(__hppa__) && !defined(__sh__) for(i = 0; i < NGREG; i++) jack_error("reg[%02d] = 0x" REGFORMAT, i, #if defined(__powerpc__) ucontext->uc_mcontext.uc_regs[i] #elif defined(__sparc__) && defined(__arch64__) ucontext->uc_mcontext.mc_gregs[i] #else ucontext->uc_mcontext.gregs[i] #endif ); #endif /* alpha, ia64, kFreeBSD, arm, hppa */ #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) # if defined(SIGSEGV_STACK_IA64) ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP]; bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP]; # elif defined(SIGSEGV_STACK_X86) ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP]; bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP]; # endif jack_error("Stack trace:"); while(bp && ip) { if(!dladdr(ip, &dlinfo)) break; const char *symname = dlinfo.dli_sname; #ifndef NO_CPP_DEMANGLE int status; char *tmp = __cxa_demangle(symname, NULL, 0, &status); if(status == 0 && tmp) symname = tmp; #endif jack_error("% 2d: %p <%s+%u> (%s)", ++f, ip, symname, (unsigned)(ip - dlinfo.dli_saddr), dlinfo.dli_fname); #ifndef NO_CPP_DEMANGLE if(tmp) free(tmp); #endif if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main")) break; ip = bp[1]; bp = (void**)bp[0]; } #else jack_error("Stack trace (non-dedicated):"); sz = backtrace(bt, 20); strings = backtrace_symbols(bt, sz); for(i = 0; i < sz; ++i) jack_error("%s", strings[i]); #endif jack_error("End of stack trace"); exit (-1); }
cv::String CameraWrapperConnector::getPathLibFolder() { if (!pathLibFolder.empty()) return pathLibFolder; Dl_info dl_info; if(0 != dladdr((void *)nextFrame, &dl_info)) { LOGD("Library name: %s", dl_info.dli_fname); LOGD("Library base address: %p", dl_info.dli_fbase); const char* libName=dl_info.dli_fname; while( ((*libName)=='/') || ((*libName)=='.') ) libName++; char lineBuf[2048]; FILE* file = fopen("/proc/self/smaps", "rt"); if(file) { while (fgets(lineBuf, sizeof lineBuf, file) != NULL) { //verify that line ends with library name int lineLength = strlen(lineBuf); int libNameLength = strlen(libName); //trim end for(int i = lineLength - 1; i >= 0 && isspace(lineBuf[i]); --i) { lineBuf[i] = 0; --lineLength; } if (0 != strncmp(lineBuf + lineLength - libNameLength, libName, libNameLength)) { //the line does not contain the library name continue; } //extract path from smaps line char* pathBegin = strchr(lineBuf, '/'); if (0 == pathBegin) { LOGE("Strange error: could not find path beginning in lin \"%s\"", lineBuf); continue; } char* pathEnd = strrchr(pathBegin, '/'); pathEnd[1] = 0; LOGD("Libraries folder found: %s", pathBegin); fclose(file); return pathBegin; } fclose(file); LOGE("Could not find library path"); } else { LOGE("Could not read /proc/self/smaps"); } } else { LOGE("Could not get library name and base address"); } return cv::String(); }
NPError OSCALL NP_Initialize(NPNetscapeFuncs *browser) { const char *home; char logfile[PATH_MAX]; const char* dir; Dl_info library; struct attendant__initializer initializer; say("NP_Initialize"); /* Copy the browser NPAPI functions into our library. */ npn_get_url = browser->geturl; npn_post_url = browser->posturl; npn_request_read = browser->requestread; npn_new_stream = browser->newstream; npn_write = browser->write; npn_destroy_stream = browser->destroystream; npn_status = browser->status; npn_user_agent = browser->uagent; npn_mem_alloc = browser->memalloc; npn_mem_free = browser->memfree; npn_mem_flush = browser->memflush; npn_reload_plugins = browser->reloadplugins; npn_get_java_env = browser->getJavaEnv; npn_get_java_peer = browser->getJavaPeer; npn_get_url_notify = browser->geturlnotify; npn_post_url_notify = browser->posturlnotify; npn_get_value = browser->getvalue; npn_set_value = browser->setvalue; npn_invalidate_rect = browser->invalidaterect; npn_invalidate_region = browser->invalidateregion; npn_force_redraw = browser->forceredraw; npn_get_string_identifier = browser->getstringidentifier; npn_get_string_identifiers = browser->getstringidentifiers; npn_get_int_identifier = browser->getintidentifier; npn_identifier_is_string = browser->identifierisstring; npn_utf8_from_indentifier = browser->utf8fromidentifier; npn_int_from_identifier = browser->intfromidentifier; npn_create_object = browser->createobject; npn_retain_object = browser->retainobject; npn_release_object = browser->releaseobject; npn_invoke = browser->invoke; npn_invoke_default = browser->invokeDefault; npn_evaluate = browser->evaluate; npn_get_property = browser->getproperty; npn_set_property = browser->setproperty; npn_remove_property = browser->removeproperty; npn_has_property = browser->hasproperty; npn_has_method = browser->hasmethod; npn_release_variant_value = browser->releasevariantvalue; npn_set_exception = browser->setexception; npn_push_popups_enabled_state = browser->pushpopupsenabledstate; npn_pop_popups_enabled_state = browser->poppopupsenabledstate; npn_enumerate = browser->enumerate; npn_plugin_thread_async_call = browser->pluginthreadasynccall; npn_construct = browser->construct; npn_get_value_for_url = browser->getvalueforurl; npn_set_value_for_url = browser->setvalueforurl; npn_get_authentication_info = browser->getauthenticationinfo; npn_schedule_timer = browser->scheduletimer; npn_unschedule_timer = browser->unscheduletimer; npn_pop_up_context_menu = browser->popupcontextmenu; npn_convert_point = browser->convertpoint; npn_handle_event = browser->handleevent; npn_unfocus_instance = browser->unfocusinstance; npn_url_redirect_response = browser->urlredirectresponse; /* Create our mutex and signaling device. */ (void) pthread_mutex_init(&plugin.mutex, NULL); (void) pthread_cond_init(&plugin.cond, NULL); dladdr(NP_Initialize, &library); dir = library.dli_fname + strlen(library.dli_fname); while (*dir != '/') { dir--; } strncat(plugin.node, library.dli_fname, dir - library.dli_fname); strcat(plugin.node, "/node"); chmod(plugin.node, 0755); memset(&initializer, 0, sizeof(struct attendant__initializer)); strncat(initializer.relay, library.dli_fname, dir - library.dli_fname); strcat(initializer.relay, "/relay"); chmod(initializer.relay, 0755); strncat(plugin.monitor, library.dli_fname, dir - library.dli_fname); strcat(plugin.monitor, "/monitor.js"); initializer.starter = starter; initializer.connector = connector; initializer.canary = 31; attendant.initialize(&initializer); starter(0, -1); say("node: %s", plugin.node); say("relay: %s", initializer.relay); plugin.curl = curl_easy_init(); return NPERR_NO_ERROR; }
int test (FILE *out, int a) { fputs ("in modstatic2.c (test)\n", out); void *handle = dlopen ("modstatic2-nonexistent.so", RTLD_LAZY); if (handle == NULL) fprintf (out, "nonexistent: %s\n", dlerror ()); else exit (1); handle = dlopen ("modstatic2.so", RTLD_LAZY); if (handle == NULL) { fprintf (out, "%s\n", dlerror ()); exit (1); } int (*test2) (FILE *, int); test2 = dlsym (handle, "test"); if (test2 == NULL) { fprintf (out, "%s\n", dlerror ()); exit (1); } if (test2 != test) { fprintf (out, "test %p != test2 %p\n", test, test2); exit (1); } Dl_info info; int res = dladdr (test2, &info); if (res == 0) { fputs ("dladdr returned 0\n", out); exit (1); } else { if (strstr (info.dli_fname, "modstatic2.so") == NULL || strcmp (info.dli_sname, "test") != 0) { fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname); exit (1); } if (info.dli_saddr != (void *) test2) { fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2); exit (1); } } ElfW(Sym) *sym; void *symp; res = dladdr1 (test2, &info, &symp, RTLD_DL_SYMENT); if (res == 0) { fputs ("dladdr1 returned 0\n", out); exit (1); } else { if (strstr (info.dli_fname, "modstatic2.so") == NULL || strcmp (info.dli_sname, "test") != 0) { fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname); exit (1); } if (info.dli_saddr != (void *) test2) { fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test2); exit (1); } sym = symp; if (sym == NULL) { fputs ("sym == NULL\n", out); exit (1); } if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) { fprintf (out, "bind %d visibility %d\n", (int) ELF32_ST_BIND (sym->st_info), (int) ELF32_ST_VISIBILITY (sym->st_other)); exit (1); } } Lmid_t lmid; res = dlinfo (handle, RTLD_DI_LMID, &lmid); if (res != 0) { fprintf (out, "dlinfo returned %d %s\n", res, dlerror ()); exit (1); } else if (lmid != LM_ID_BASE) { fprintf (out, "lmid %d != %d\n", (int) lmid, (int) LM_ID_BASE); exit (1); } void *handle2 = dlopen (LIBDL_SO, RTLD_LAZY); if (handle2 == NULL) { fprintf (out, "libdl.so: %s\n", dlerror ()); exit (1); } #ifdef DO_VERSIONING if (dlvsym (handle2, "_dlfcn_hook", "GLIBC_PRIVATE") == NULL) { fprintf (out, "dlvsym: %s\n", dlerror ()); exit (1); } #endif void *(*dlsymfn) (void *, const char *); dlsymfn = dlsym (handle2, "dlsym"); if (dlsymfn == NULL) { fprintf (out, "dlsym \"dlsym\": %s\n", dlerror ()); exit (1); } void *test3 = dlsymfn (handle, "test"); if (test3 == NULL) { fprintf (out, "%s\n", dlerror ()); exit (1); } else if (test3 != (void *) test2) { fprintf (out, "test2 %p != test3 %p\n", test2, test3); exit (1); } dlclose (handle2); dlclose (handle); handle = dlmopen (LM_ID_BASE, "modstatic2.so", RTLD_LAZY); if (handle == NULL) { fprintf (out, "%s\n", dlerror ()); exit (1); } dlclose (handle); handle = dlmopen (LM_ID_NEWLM, "modstatic2.so", RTLD_LAZY); if (handle == NULL) fprintf (out, "LM_ID_NEWLM: %s\n", dlerror ()); else { fputs ("LM_ID_NEWLM unexpectedly succeeded\n", out); exit (1); } handle = dlopen ("modstatic.so", RTLD_LAZY); if (handle == NULL) { fprintf (out, "%s\n", dlerror ()); exit (1); } int (*test4) (int); test4 = dlsym (handle, "test"); if (test4 == NULL) { fprintf (out, "%s\n", dlerror ()); exit (1); } res = test4 (16); if (res != 16 + 16) { fprintf (out, "modstatic.so (test) returned %d\n", res); exit (1); } res = dladdr1 (test4, &info, &symp, RTLD_DL_SYMENT); if (res == 0) { fputs ("dladdr1 returned 0\n", out); exit (1); } else { if (strstr (info.dli_fname, "modstatic.so") == NULL || strcmp (info.dli_sname, "test") != 0) { fprintf (out, "fname %s sname %s\n", info.dli_fname, info.dli_sname); exit (1); } if (info.dli_saddr != (void *) test4) { fprintf (out, "saddr %p != test %p\n", info.dli_saddr, test4); exit (1); } sym = symp; if (sym == NULL) { fputs ("sym == NULL\n", out); exit (1); } if (ELF32_ST_BIND (sym->st_info) != STB_GLOBAL || ELF32_ST_VISIBILITY (sym->st_other) != STV_DEFAULT) { fprintf (out, "bind %d visibility %d\n", (int) ELF32_ST_BIND (sym->st_info), (int) ELF32_ST_VISIBILITY (sym->st_other)); exit (1); } } dlclose (handle); fputs ("leaving modstatic2.c (test)\n", out); return a + a; }
void print_VTable(void *dlhndl, vtable_info *vtable) { union classvtable_mem *vtablep; unsigned long vtbaseoffset; const char *vttypeinfo; fptr *vtvirtfuncs; void* vfuncp; Dl_info dlainfo; int i, j; int offset; int step; char* demngl; int size; int space; demngl = demangle(vtable->name); demngl[0] = toupper(demngl[0]); printf("%s\n", demngl); free(demngl); vtablep = dlsym(dlhndl, vtable->name); vtbaseoffset = vtablep->cat1.baseoffset; vttypeinfo = vtablep->cat1.typeinfo; vtvirtfuncs = vtablep->cat1.virtfuncs; size = vtable->size/sizeof(ptrdiff_t); printf("%s: %d entries\n", vtable->name, size); step = sizeof(ptrdiff_t); offset = 0; if (vtbaseoffset!=0) { printf("%d %luu\n", offset, vtbaseoffset); } else { printf("%d (int (*)(...)) 0\n", offset); } offset += step; if (dladdr(vttypeinfo, &dlainfo)) { demngl = demangle(dlainfo.dli_sname); if(opt_mangled==1 && opt_demangled==1) { printf("%d (int (*)(...)) (& %s) [%s]\n", offset, demngl, dlainfo.dli_sname); } else if(opt_demangled==1) { printf("%d (int (*)(...)) (& %s)\n", offset, demngl); } else { // show mangled name by default printf("%d (int (*)(...)) (& %s)\n", offset, dlainfo.dli_sname); } free(demngl); } else { if (vtbaseoffset!=0) printf("%d 0u\n", offset); else printf("%d (int (*)(...)) 0\n", offset); } for (i = 0; i <= size - 3; i++) { offset += step; vfuncp = fptr2ptrp(&vtvirtfuncs[i]); memset(&dlainfo, 0, sizeof(dlainfo)); space = 5 - integer_len(offset); if (dladdr(vfuncp, &dlainfo)) { printf("%d", offset); for (j = 0; j<=space; j++) { printf(" "); } if (dlainfo.dli_sname==NULL) { printf("(int (*)(...)) %p\n", (void*) (vfuncp-dlainfo.dli_fbase)); } else if (strstr(dlainfo.dli_sname, "__cxa_pure")) { printf("(int (*)(...)) %s\n", dlainfo.dli_sname); } else if (strstr(dlainfo.dli_sname, "_ZTI")) { demngl = demangle(dlainfo.dli_sname); if(opt_mangled==1 && opt_demangled==1) { printf("(int (*)(...)) (& %s) [%s]\n", demngl, dlainfo.dli_sname); } else if(opt_demangled==1) { printf("(int (*)(...)) (& %s)\n", demngl); } else { // show mangled name by default printf("(int (*)(...)) (& %s)\n", dlainfo.dli_sname); } free(demngl); } else { demngl = demangle(dlainfo.dli_sname); if(opt_mangled==1 && opt_demangled==1) { printf("(int (*)(...)) %s [%s]\n", demngl, dlainfo.dli_sname); } else if(opt_demangled==1) { printf("(int (*)(...)) %s\n", demngl); } else if(opt_mangled==1) { printf("(int (*)(...)) %s\n", dlainfo.dli_sname); } else { if(strstr(dlainfo.dli_sname, "_ZN") == NULL) { // _ZThn, _ZTv, __cxa, etc. // show mangled name by default printf("(int (*)(...)) %s\n", dlainfo.dli_sname); } else { printf("(int (*)(...)) %s\n", demngl); } } free(demngl); } } else { printf("%d", offset); for (j = 0; j<=space; j++) { printf(" "); } if (vfuncp == NULL) { printf("0u\n"); } else { if ((ptrdiff_t)vfuncp < 0) { printf("(int (*)(...)) -%016p\n", (void*) -(ptrdiff_t)vfuncp); } else { printf("(int (*)(...)) %016p\n", vfuncp); } } } } printf("\n\n"); }
SAMPGDK_EXPORT void *SAMPGDK_CALL sampgdk_get_plugin_handle(void *symbol) { Dl_info info; dladdr(symbol, &info); return dlopen(info.dli_fname, RTLD_NOW); }
void hpi::initialize_get_interface(vm_calls_t *callbacks) { #define args callbacks #define InitializeHPI hpi::initialize_get_interface // "$JDK/src/solaris/javavm/runtime/javai_md.c":32 (ver. 1.7 98/09/15) char buf[MAXPATHLEN]; Dl_info dlinfo; void *hpi_handle; GetInterfaceFunc& getintf = _get_interface; jint (JNICALL * DLL_Initialize)(GetInterfaceFunc *, void *); #if 1 //HotSpot change char *thread_type = strdup("native_threads"); os::jvm_path(buf, sizeof buf); #else //HotSpot change char *thread_type = getenv("_JVM_THREADS_TYPE"); if (thread_type) { /* Set by .java_wrapper. Remove for the sake of exec'd VMs. */ thread_type = strdup(thread_type); putenv("_JVM_THREADS_TYPE="); } else { /* Default thread type for the invocation API. */ thread_type = strdup("native_threads"); } dladdr((void *)InitializeHPI, &dlinfo); strcpy(buf, (char *)dlinfo.dli_fname); #endif //HotSpot change #ifdef PRODUCT const char * hpi_lib = "/libhpi.so"; #else char * ptr = strrchr(buf, '/'); assert(strstr(ptr, "/libjvm") == ptr, "invalid library name"); const char * hpi_lib = strstr(ptr, "_g") ? "/libhpi_g.so" : "/libhpi.so"; #endif *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ *(strrchr(buf, '/') + 1) = '\0'; /* get rid of hotspot */ strcat(buf, thread_type); strcat(buf, hpi_lib); /* we use RTLD_NOW because of bug 4032715 */ if (TraceHPI) tty->print("Loading HPI %s ", buf); hpi_handle = dlopen(buf, RTLD_NOW); if (hpi_handle == NULL) { if (TraceHPI) tty->print_cr("HPI dlopen failed: %s", dlerror()); goto bail; } DLL_Initialize = CAST_TO_FN_PTR(jint (JNICALL *)(GetInterfaceFunc *, void *), dlsym(hpi_handle, "DLL_Initialize")); if (TraceHPI && DLL_Initialize == NULL) tty->print_cr("HPI dlsym of DLL_Initialize failed: %s", dlerror()); if (DLL_Initialize == NULL || (*DLL_Initialize)(&getintf, args) < 0) { if (TraceHPI) tty->print_cr("HPI DLL_Initialize failed"); goto bail; } if (TraceHPI) tty->print_cr("HPI loaded successfully"); bail: free(thread_type); #undef args #undef InitializeHPI }
/** * Prints a stack backtrace for the current thread to the specified ostream. * * Does not malloc, does not throw. * * The format of the backtrace is: * * ----- BEGIN BACKTRACE ----- * JSON backtrace * Human-readable backtrace * ----- END BACKTRACE ----- * * The JSON backtrace will be a JSON object with a "backtrace" field, and optionally others. * The "backtrace" field is an array, whose elements are frame objects. A frame object has a * "b" field, which is the base-address of the library or executable containing the symbol, and * an "o" field, which is the offset into said library or executable of the symbol. * * The JSON backtrace may optionally contain additional information useful to a backtrace * analysis tool. For example, on Linux it contains a subobject named "somap", describing * the objects referenced in the "b" fields of the "backtrace" list. * * @param os ostream& to receive printed stack backtrace */ void printStackTrace(std::ostream& os) { static const char unknownFileName[] = "???"; void* addresses[maxBackTraceFrames]; Dl_info dlinfoForFrames[maxBackTraceFrames]; //////////////////////////////////////////////////////////// // Get the backtrace addresses. //////////////////////////////////////////////////////////// const int addressCount = backtrace(addresses, maxBackTraceFrames); if (addressCount == 0) { const int err = errno; os << "Unable to collect backtrace addresses (errno: " << err << ' ' << strerror(err) << ')' << std::endl; return; } //////////////////////////////////////////////////////////// // Collect symbol information for each backtrace address. //////////////////////////////////////////////////////////// os << std::hex << std::uppercase << '\n'; for (int i = 0; i < addressCount; ++i) { Dl_info& dlinfo(dlinfoForFrames[i]); if (!dladdr(addresses[i], &dlinfo)) { dlinfo.dli_fname = unknownFileName; dlinfo.dli_fbase = NULL; dlinfo.dli_sname = NULL; dlinfo.dli_saddr = NULL; } os << ' ' << addresses[i]; } os << "\n----- BEGIN BACKTRACE -----\n"; //////////////////////////////////////////////////////////// // Display the JSON backtrace //////////////////////////////////////////////////////////// os << "{\"backtrace\":["; for (int i = 0; i < addressCount; ++i) { const Dl_info& dlinfo = dlinfoForFrames[i]; const uintptr_t fileOffset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_fbase); if (i) os << ','; os << "{\"b\":\"" << uintptr_t(dlinfo.dli_fbase) << "\",\"o\":\"" << fileOffset << "\"}"; } os << ']'; if (soMapJson) os << ",\"processInfo\":" << *soMapJson; os << "}\n"; //////////////////////////////////////////////////////////// // Display the human-readable trace //////////////////////////////////////////////////////////// for (int i = 0; i < addressCount; ++i) { Dl_info& dlinfo(dlinfoForFrames[i]); os << ' '; if (dlinfo.dli_fbase) { os << getBaseName(dlinfo.dli_fname) << '('; if (dlinfo.dli_sname) { const uintptr_t offset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_saddr); os << dlinfo.dli_sname << "+0x" << offset; } else { const uintptr_t offset = uintptr_t(addresses[i]) - uintptr_t(dlinfo.dli_fbase); os << "+0x" << offset; } os << ')'; } else { os << unknownFileName; } os << " [" << addresses[i] << ']' << std::endl; } os << std::dec << std::nouppercase; os << "----- END BACKTRACE -----" << std::endl; }
std::string GetModuleFile(std::string moduleName) { std::string moduleFilePath = ""; // this will only be used if moduleFilePath stays empty const char* error = NULL; #if defined(linux) || defined(__APPLE__) #ifdef __APPLE__ #define SHARED_LIBRARY_EXTENSION "dylib" #else #define SHARED_LIBRARY_EXTENSION "so" #endif void* moduleAddress = NULL; // find an address in the module we are looking for if (moduleName.empty()) { // look for current module moduleAddress = (void*) GetModuleFile; } else { // look for specified module // add extension if it is not in the file name // it could also be "libXZY.so-1.2.3" // -> does not have to be the end, my friend if (moduleName.find("."SHARED_LIBRARY_EXTENSION) == std::string::npos) { moduleName = moduleName + "."SHARED_LIBRARY_EXTENSION; } // will not not try to load, but return the libs address // if it is already loaded, NULL otherwise moduleAddress = dlopen(moduleName.c_str(), RTLD_LAZY | RTLD_NOLOAD); if (moduleAddress == NULL) { // if not found, try with "lib" prefix moduleName = "lib" + moduleName; moduleAddress = dlopen(moduleName.c_str(), RTLD_LAZY | RTLD_NOLOAD); } } if (moduleAddress != NULL) { // fetch info about the module containing the address we just evaluated Dl_info moduleInfo; const int ret = dladdr(moduleAddress, &moduleInfo); if ((ret != 0) && (moduleInfo.dli_fname != NULL)) { moduleFilePath = moduleInfo.dli_fname; // required on APPLE; does not hurt elsewhere moduleFilePath = GetRealPath(moduleFilePath); } else { error = dlerror(); if (error == NULL) { error = "Unknown"; } } } else { error = "Not loaded"; } #elif WIN32 HMODULE hModule = NULL; if (moduleName.empty()) { hModule = GetCurrentModule(); } else { // If this fails, we get a NULL handle hModule = GetModuleHandle(moduleName.c_str()); } if (hModule != NULL) { // fetch module file name TCHAR moduleFile[MAX_PATH+1]; const int ret = ::GetModuleFileName(hModule, moduleFile, sizeof(moduleFile)); if ((ret != 0) && (ret != sizeof(moduleFile))) { moduleFilePath = std::string(moduleFile); } else { error = + "Unknown"; } } else { error = "Not found"; } #else #warning implement this (or use linux version) #endif if (moduleFilePath.empty()) { if (moduleName.empty()) { moduleName = "<current>"; } LOG_L(L_WARNING, "Failed to get file path of the module \"%s\", reason: %s", moduleName.c_str(), error); } return moduleFilePath; }
void ruby_init_loadpath_safe(int safe_level) { VALUE load_path; ID id_initial_load_path_mark; extern const char ruby_initial_load_paths[]; const char *paths = ruby_initial_load_paths; #if defined LOAD_RELATIVE # if defined HAVE_DLADDR || defined HAVE_CYGWIN_CONV_PATH # define VARIABLE_LIBPATH 1 # else # define VARIABLE_LIBPATH 0 # endif # if VARIABLE_LIBPATH char *libpath; VALUE sopath; # else char libpath[MAXPATHLEN + 1]; # endif size_t baselen; char *p; #if defined _WIN32 || defined __CYGWIN__ # if VARIABLE_LIBPATH sopath = rb_str_new(0, MAXPATHLEN); libpath = RSTRING_PTR(sopath); GetModuleFileName(libruby, libpath, MAXPATHLEN); # else GetModuleFileName(libruby, libpath, sizeof libpath); # endif #elif defined(__EMX__) _execname(libpath, sizeof(libpath) - 1); #elif defined(HAVE_DLADDR) Dl_info dli; if (dladdr((void *)(VALUE)expand_include_path, &dli)) { char fbuf[MAXPATHLEN]; char *f = dln_find_file_r(dli.dli_fname, getenv(PATH_ENV), fbuf, sizeof(fbuf)); VALUE fname = rb_str_new_cstr(f ? f : dli.dli_fname); rb_str_freeze(fname); sopath = rb_realpath_internal(Qnil, fname, 1); } else { sopath = rb_str_new(0, 0); } libpath = RSTRING_PTR(sopath); #endif #if !VARIABLE_LIBPATH libpath[sizeof(libpath) - 1] = '\0'; #endif #if defined DOSISH translit_char(libpath, '\\', '/'); #elif defined __CYGWIN__ { # if VARIABLE_LIBPATH const int win_to_posix = CCP_WIN_A_TO_POSIX | CCP_RELATIVE; size_t newsize = cygwin_conv_path(win_to_posix, libpath, 0, 0); if (newsize > 0) { VALUE rubylib = rb_str_new(0, newsize); p = RSTRING_PTR(rubylib); if (cygwin_conv_path(win_to_posix, libpath, p, newsize) == 0) { rb_str_resize(sopath, 0); sopath = rubylib; libpath = p; } } # else char rubylib[FILENAME_MAX]; cygwin_conv_to_posix_path(libpath, rubylib); strncpy(libpath, rubylib, sizeof(libpath)); # endif } #endif p = strrchr(libpath, '/'); if (p) { static const char bindir[] = "/bin"; #ifdef LIBDIR_BASENAME static const char libdir[] = "/"LIBDIR_BASENAME; #else static const char libdir[] = "/lib"; #endif const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1; const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir) - 1; *p = 0; if (p - libpath >= bindir_len && !STRCASECMP(p - bindir_len, bindir)) { p -= bindir_len; *p = 0; } else if (p - libpath >= libdir_len && !STRCASECMP(p - libdir_len, libdir)) { p -= libdir_len; *p = 0; } } #if !VARIABLE_LIBPATH else { strlcpy(libpath, ".", sizeof(libpath)); p = libpath + 1; } baselen = p - libpath; #define PREFIX_PATH() rb_str_new(libpath, baselen) #else baselen = p - libpath; rb_str_resize(sopath, baselen); libpath = RSTRING_PTR(sopath); #define PREFIX_PATH() sopath #endif #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen) #define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len)) #else static const char exec_prefix[] = RUBY_EXEC_PREFIX; #define RUBY_RELATIVE(path, len) rubylib_mangled_path((path), (len)) #define PREFIX_PATH() RUBY_RELATIVE(exec_prefix, sizeof(exec_prefix)-1) #endif load_path = GET_VM()->load_path; if (safe_level == 0) { #ifdef MANGLED_PATH rubylib_mangled_path("", 0); #endif ruby_push_include(getenv("RUBYLIB"), identical_path); } id_initial_load_path_mark = rb_intern_const("@gem_prelude_index"); while (*paths) { size_t len = strlen(paths); VALUE path = RUBY_RELATIVE(paths, len); rb_ivar_set(path, id_initial_load_path_mark, path); rb_ary_push(load_path, path); paths += len + 1; } rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), rb_obj_freeze(PREFIX_PATH())); }
bool CSignatureFunction::getLibraryInfo(const void *libPtr, DynLibInfo &lib) { uintptr_t baseAddr; if (libPtr == NULL) { return false; } #ifdef _WIN32 MEMORY_BASIC_INFORMATION info; IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS *pe; IMAGE_FILE_HEADER *file; IMAGE_OPTIONAL_HEADER *opt; if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION))) { return false; } baseAddr = reinterpret_cast<uintptr_t>(info.AllocationBase); // All this is for our insane sanity checks :o dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr); pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew); file = &pe->FileHeader; opt = &pe->OptionalHeader; // Check PE magic and signature if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { return false; } // Check architecture, which is 32-bit/x86 right now // Should change this for 64-bit if Valve gets their act together if (file->Machine != IMAGE_FILE_MACHINE_I386) { return false; } //For our purposes, this must be a dynamic library if ((file->Characteristics & IMAGE_FILE_DLL) == 0) { return false; } //Finally, we can do this lib.memorySize = opt->SizeOfImage; #else Dl_info info; Elf32_Ehdr *file; Elf32_Phdr *phdr; uint16_t phdrCount; if (!dladdr(libPtr, &info)) { return false; } if (!info.dli_fbase || !info.dli_fname) { return false; } // This is for our insane sanity checks :o baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase); file = reinterpret_cast<Elf32_Ehdr *>(baseAddr); // Check ELF magic if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0) { return false; } // Check ELF version if (file->e_ident[EI_VERSION] != EV_CURRENT) { return false; } // Check ELF architecture, which is 32-bit/x86 right now // Should change this for 64-bit if Valve gets their act together if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB) { return false; } // For our purposes, this must be a dynamic library/shared object if (file->e_type != ET_DYN) { return false; } phdrCount = file->e_phnum; phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff); for (uint16_t i = 0; i < phdrCount; i++) { Elf32_Phdr &hdr = phdr[i]; // We only really care about the segment with executable code if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R)) { // From glibc, elf/dl-load.c: // c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1) // & ~(GLRO(dl_pagesize) - 1)); // // In glibc, the segment file size is aligned up to the nearest page size and // added to the virtual address of the segment. We just want the size here. lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz); break; } } #endif lib.baseAddress = reinterpret_cast<void *>(baseAddr); return true; }
static int Init() { FILE *fp; char *p, buf[512]; Dl_info info; if (dladdr((void *)Init, &info) != 0) { strncpy(buf, info.dli_fname, sizeof(buf) - 8); buf[sizeof(buf) - 8] = '\0'; strcat(buf, ".conf"); } else strcpy(buf, DEFAULT_CONF_NAME); fp = fopen(buf, "r"); if (fp == NULL) return -1; BOOL bHost, bPort, bBonDriver, bChannelLock, bConnectTimeOut, bUseMagicPacket; BOOL bTargetHost, bTargetPort, bTargetMac; BOOL bPacketFifoSize, bTsFifoSize, bTsPacketBufSize; bHost = bPort = bBonDriver = bChannelLock = bConnectTimeOut = bUseMagicPacket = FALSE; bTargetHost = bTargetPort = bTargetMac = FALSE; bPacketFifoSize = bTsFifoSize = bTsPacketBufSize = FALSE; while (fgets(buf, sizeof(buf), fp)) { if (buf[0] == ';') continue; p = buf + strlen(buf) - 1; while (*p == '\r' || *p == '\n') *p-- = '\0'; if (!bHost && (strncmp(buf, "ADDRESS=", 8) == 0)) { p = &buf[8]; while (*p == ' ' || *p == '\t') p++; strncpy(g_Host, p, sizeof(g_Host) - 1); g_Host[sizeof(g_Host) - 1] = '\0'; bHost = TRUE; } else if (!bPort && (strncmp(buf, "PORT=", 5) == 0)) { p = &buf[5]; while (*p == ' ' || *p == '\t') p++; g_Port = atoi(p); bPort = TRUE; } else if (!bBonDriver && (strncmp(buf, "BONDRIVER=", 10) == 0)) { p = &buf[10]; while (*p == ' ' || *p == '\t') p++; strncpy(g_BonDriver, p, sizeof(g_BonDriver) - 1); g_BonDriver[sizeof(g_BonDriver) - 1] = '\0'; bBonDriver = TRUE; } else if (!bChannelLock && (strncmp(buf, "CHANNEL_LOCK=", 13) == 0)) { p = &buf[13]; while (*p == ' ' || *p == '\t') p++; g_ChannelLock = atoi(p); bChannelLock = TRUE; } else if (!bConnectTimeOut && (strncmp(buf, "CONNECT_TIMEOUT=", 16) == 0)) { p = &buf[16]; while (*p == ' ' || *p == '\t') p++; g_ConnectTimeOut = atoi(p); bConnectTimeOut = TRUE; } else if (!bUseMagicPacket && (strncmp(buf, "USE_MAGICPACKET=", 16) == 0)) { p = &buf[16]; while (*p == ' ' || *p == '\t') p++; g_UseMagicPacket = atoi(p); bUseMagicPacket = TRUE; } else if (!bTargetHost && (strncmp(buf, "TARGET_ADDRESS=", 15) == 0)) { p = &buf[15]; while (*p == ' ' || *p == '\t') p++; strncpy(g_TargetHost, p, sizeof(g_TargetHost) - 1); g_TargetHost[sizeof(g_TargetHost) - 1] = '\0'; bTargetHost = TRUE; } else if (!bTargetPort && (strncmp(buf, "TARGET_PORT=", 12) == 0)) { p = &buf[12]; while (*p == ' ' || *p == '\t') p++; g_TargetPort = atoi(p); bTargetPort = TRUE; } else if (!bTargetMac && (strncmp(buf, "TARGET_MACADDRESS=", 18) == 0)) { p = &buf[18]; while (*p == ' ' || *p == '\t') p++; char mac[32]; memset(mac, 0, sizeof(mac)); strncpy(mac, p, sizeof(mac) - 1); BOOL bErr = FALSE; for (int i = 0; i < 6 && !bErr; i++) { BYTE b = 0; p = &mac[i * 3]; for (int j = 0; j < 2 && !bErr; j++) { if ('0' <= *p && *p <= '9') b = b * 0x10 + (*p - '0'); else if ('A' <= *p && *p <= 'F') b = b * 0x10 + (*p - 'A' + 10); else if ('a' <= *p && *p <= 'f') b = b * 0x10 + (*p - 'a' + 10); else bErr = TRUE; p++; } g_TargetMac[i] = b; } if (!bErr) bTargetMac = TRUE; } else if (!bPacketFifoSize && (strncmp(buf, "PACKET_FIFO_SIZE=", 17) == 0)) { p = &buf[17]; while (*p == ' ' || *p == '\t') p++; g_PacketFifoSize = atoi(p); bPacketFifoSize = TRUE; } else if (!bTsFifoSize && (strncmp(buf, "TS_FIFO_SIZE=", 13) == 0)) { p = &buf[13]; while (*p == ' ' || *p == '\t') p++; g_TsFifoSize = atoi(p); bTsFifoSize = TRUE; } else if (!bTsPacketBufSize && (strncmp(buf, "TSPACKET_BUFSIZE=", 17) == 0)) { p = &buf[17]; while (*p == ' ' || *p == '\t') p++; g_TsPacketBufSize = atoi(p); bTsPacketBufSize = TRUE; } } fclose(fp); if (!bHost || !bPort || !bBonDriver) return -2; if (g_UseMagicPacket) { if (!bTargetMac) return -3; if (!bTargetHost) strcpy(g_TargetHost, g_Host); if (!bTargetPort) g_TargetPort = g_Port; } return 0; }
/** * Perform specify operation on the address. * * @param addr the address we're querying * @param op the operation to perform * * @return NULL on failure, an address whose interpretation is op-specific * otherwise. */ static const void * dl_util_query(const void *addr, enum dl_addr_op op) { if G_UNLIKELY(!dl_util_inited) dl_util_init(); #ifdef HAS_DLADDR { static Dl_info info; static const void *last_addr; int stid = thread_small_id(); /* * Cache results for a given address. This will help our stack * pretty-printing code which is going to gather the various * items at different times instead of doing one dladdr() call. * For a given stack item, we may therefore face various calls * for the same address. * * The rationale is that we may want to use different routines on * another platform without dladdr() some days and therefore we wish * to hide the existence of dladdr() and rather provide higher-level * services like dl_util_get_base(). */ if (addr != last_addr) { signal_handler_t old_sigsegv; int ret; ZERO(&info); /* * Protect against segmentation faults in dladdr(). * * We use signal_catch() instead of signal_set() because we * don't need extra information about the fault context. */ old_sigsegv = signal_catch(SIGSEGV, dl_util_got_signal); if (Sigsetjmp(dl_util_env[stid], TRUE)) { last_addr = NULL; return NULL; } ret = dladdr(deconstify_pointer(addr), &info); signal_set(SIGSEGV, old_sigsegv); if (0 == ret) { last_addr = NULL; return NULL; } last_addr = addr; } switch (op) { case DL_ADDR_GET_BASE: return info.dli_fbase; case DL_ADDR_GET_NAME: return info.dli_sname; case DL_ADDR_GET_PATH: return info.dli_fname; case DL_ADDR_GET_START: return info.dli_saddr; } } g_assert_not_reached(); #else /* !HAS_DLADDR */ (void) addr; (void) op; return NULL; #endif /* HAS_DLADDR */ }
SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states) { if (m_IgnoreLevel) { m_IgnoreLevel--; return SMCResult_Continue; } if (m_CustomLevel) { m_CustomLevel--; m_CustomHandler->ReadSMC_LeavingSection(states); return SMCResult_Continue; } switch (m_ParseState) { case PSTATE_GAMES: { m_ParseState = PSTATE_NONE; break; } case PSTATE_GAMEDEFS: { m_ParseState = PSTATE_GAMES; break; } case PSTATE_GAMEDEFS_CLASSES: { m_MatchedClasses = false; m_ParseState = PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_CLASSES_CLASS: { m_ParseState = PSTATE_GAMEDEFS_CLASSES; m_Class[0] = '\0'; break; } case PSTATE_GAMEDEFS_CUSTOM: { m_ParseState = PSTATE_GAMEDEFS; m_CustomHandler->ReadSMC_ParseEnd(false, false); break; } case PSTATE_GAMEDEFS_KEYS: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_OFFSETS: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_OFFSETS_OFFSET: { m_ParseState = PSTATE_GAMEDEFS_OFFSETS; break; } case PSTATE_GAMEDEFS_SUPPORTED: { if (!m_ShouldBeReadingDefault) { m_IgnoreLevel = 1; m_ParseState = PSTATE_GAMES; } else { m_ParseState = PSTATE_GAMEDEFS; } break; } case PSTATE_GAMEDEFS_SIGNATURES: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_SIGNATURES_SIG: { if (TempSig.library[0] == '\0') { strncopy(TempSig.library, "server", sizeof(TempSig.library)); } void *addressInBase = nullptr; if (strcmp(TempSig.library, "server") == 0) { addressInBase = reinterpret_cast<void*>(MDLL_Spawn); } else if (strcmp(TempSig.library, "engine") == 0) { addressInBase = reinterpret_cast<void*>(gpGlobals); } void *finalAddress = nullptr; if (!addressInBase) { AMXXLOG_Error("Unrecognized library \"%s\" (gameconf \"%s\")", TempSig.library, m_CurrentPath); } else if (TempSig.signature[0]) { if (TempSig.signature[0] == '@') { #if defined PLATFORM_WINDOWS MEMORY_BASIC_INFORMATION mem; if (VirtualQuery(addressInBase, &mem, sizeof(mem))) { finalAddress = g_MemUtils.ResolveSymbol(mem.AllocationBase, &TempSig.signature[1]); } else { AMXXLOG_Error("Unable to find library \"%s\" in memory (gameconf \"%s\")", TempSig.library, m_File); } #elif defined PLATFORM_POSIX Dl_info info; if (dladdr(addressInBase, &info) != 0) { void *handle = dlopen(info.dli_fname, RTLD_NOW); if (handle) { finalAddress = g_MemUtils.ResolveSymbol(handle, &TempSig.signature[1]); dlclose(handle); } else { AMXXLOG_Error("Unable to load library \"%s\" (gameconf \"%s\")", TempSig.library, m_File); } } else { AMXXLOG_Error("Unable to find library \"%s\" in memory (gameconf \"%s\")", TempSig.library, m_File); } #endif } if (!finalAddress) { finalAddress = g_MemUtils.DecodeAndFindPattern(addressInBase, TempSig.signature); } m_Sigs.replace(m_Offset, finalAddress); } m_ParseState = PSTATE_GAMEDEFS_SIGNATURES; break; } case PSTATE_GAMEDEFS_ADDRESSES: { m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS; break; } case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS: { m_ParseState = PSTATE_GAMEDEFS_ADDRESSES; if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0') { AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead); m_Addresses.replace(m_Address, addrConf); } break; } case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ: { m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS; break; } } return SMCResult_Continue; }
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib) { uintptr_t baseAddr; if (libPtr == NULL) { return false; } #ifdef PLATFORM_WINDOWS MEMORY_BASIC_INFORMATION info; IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS *pe; IMAGE_FILE_HEADER *file; IMAGE_OPTIONAL_HEADER *opt; if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION))) { return false; } baseAddr = reinterpret_cast<uintptr_t>(info.AllocationBase); /* All this is for our insane sanity checks :o */ dos = reinterpret_cast<IMAGE_DOS_HEADER *>(baseAddr); pe = reinterpret_cast<IMAGE_NT_HEADERS *>(baseAddr + dos->e_lfanew); file = &pe->FileHeader; opt = &pe->OptionalHeader; /* Check PE magic and signature */ if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { return false; } /* Check architecture, which is 32-bit/x86 right now * Should change this for 64-bit if Valve gets their act together */ if (file->Machine != IMAGE_FILE_MACHINE_I386) { return false; } /* For our purposes, this must be a dynamic library */ if ((file->Characteristics & IMAGE_FILE_DLL) == 0) { return false; } /* Finally, we can do this */ lib.memorySize = opt->SizeOfImage; #elif defined PLATFORM_LINUX Dl_info info; Elf32_Ehdr *file; Elf32_Phdr *phdr; uint16_t phdrCount; if (!dladdr(libPtr, &info)) { return false; } if (!info.dli_fbase || !info.dli_fname) { return false; } /* This is for our insane sanity checks :o */ baseAddr = reinterpret_cast<uintptr_t>(info.dli_fbase); file = reinterpret_cast<Elf32_Ehdr *>(baseAddr); /* Check ELF magic */ if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0) { return false; } /* Check ELF version */ if (file->e_ident[EI_VERSION] != EV_CURRENT) { return false; } /* Check ELF architecture, which is 32-bit/x86 right now * Should change this for 64-bit if Valve gets their act together */ if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB) { return false; } /* For our purposes, this must be a dynamic library/shared object */ if (file->e_type != ET_DYN) { return false; } phdrCount = file->e_phnum; phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff); for (uint16_t i = 0; i < phdrCount; i++) { Elf32_Phdr &hdr = phdr[i]; /* We only really care about the segment with executable code */ if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R)) { /* From glibc, elf/dl-load.c: * c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1) * & ~(GLRO(dl_pagesize) - 1)); * * In glibc, the segment file size is aligned up to the nearest page size and * added to the virtual address of the segment. We just want the size here. */ lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz); break; } } #elif defined PLATFORM_APPLE Dl_info info; struct mach_header *file; struct segment_command *seg; uint32_t cmd_count; if (!dladdr(libPtr, &info)) { return false; } if (!info.dli_fbase || !info.dli_fname) { return false; } /* This is for our insane sanity checks :o */ baseAddr = (uintptr_t)info.dli_fbase; file = (struct mach_header *)baseAddr; /* Check Mach-O magic */ if (file->magic != MH_MAGIC) { return false; } /* Check architecture (32-bit/x86) */ if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL) { return false; } /* For our purposes, this must be a dynamic library */ if (file->filetype != MH_DYLIB) { return false; } cmd_count = file->ncmds; seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header)); /* Add up memory sizes of mapped segments */ for (uint32_t i = 0; i < cmd_count; i++) { if (seg->cmd == LC_SEGMENT) { lib.memorySize += seg->vmsize; } seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize); } #endif lib.baseAddress = reinterpret_cast<void *>(baseAddr); return true; }
void xorg_backtrace(void) { unw_cursor_t cursor; unw_context_t context; unw_word_t off; unw_proc_info_t pip; int ret, i = 0; char procname[256]; const char *filename; Dl_info dlinfo; pip.unwind_info = NULL; ret = unw_getcontext(&context); if (ret) { ErrorFSigSafe("unw_getcontext failed: %s [%d]\n", unw_strerror(ret), ret); return; } ret = unw_init_local(&cursor, &context); if (ret) { ErrorFSigSafe("unw_init_local failed: %s [%d]\n", unw_strerror(ret), ret); return; } ErrorFSigSafe("\n"); ErrorFSigSafe("Backtrace:\n"); ret = unw_step(&cursor); while (ret > 0) { ret = unw_get_proc_info(&cursor, &pip); if (ret) { ErrorFSigSafe("unw_get_proc_info failed: %s [%d]\n", unw_strerror(ret), ret); break; } ret = unw_get_proc_name(&cursor, procname, 256, &off); if (ret && ret != -UNW_ENOMEM) { if (ret != -UNW_EUNSPEC) ErrorFSigSafe("unw_get_proc_name failed: %s [%d]\n", unw_strerror(ret), ret); procname[0] = '?'; procname[1] = 0; } if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname && *dlinfo.dli_fname) filename = dlinfo.dli_fname; else filename = "?"; ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname, ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off)); ret = unw_step(&cursor); if (ret < 0) ErrorFSigSafe("unw_step failed: %s [%d]\n", unw_strerror(ret), ret); } ErrorFSigSafe("\n"); }