std::string current_executable_directory() { #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) std::string path = current_executable_path(); return path.substr(0, path.find_last_of("/")); #else // XXX: How do you do this on your platform? return std::string(); #endif }
bool get_embedded_data(const char* section, embedded_data* desc, const std::string& filename /*= "" */) { auto const fname = filename.empty() ? current_executable_path() : filename; #if defined(__CYGWIN__) || defined(__MINGW__) || defined(_MSC_VER) HMODULE moduleHandle = GetModuleHandleA(fname.data()); HGLOBAL loadedResource; HRSRC resourceInfo; DWORD resourceSize; resourceInfo = FindResource(moduleHandle, section, RT_RCDATA); if (!resourceInfo) { return false; } loadedResource = LoadResource(moduleHandle, resourceInfo); if (!loadedResource) { return false; } resourceSize = SizeofResource(moduleHandle, resourceInfo); desc->m_filename = fname; desc->m_handle = loadedResource; desc->m_len = resourceSize; return true; #elif !defined(__APPLE__) // LINUX/ELF folly::symbolizer::ElfFile file; if (file.openNoThrow(fname.c_str()) != 0) return false; auto const shdr = file.getSectionByName(section); if (shdr == nullptr) return false; desc->m_filename = fname; desc->m_start = shdr->sh_offset; desc->m_len = shdr->sh_size; return true; #else // __APPLE__ const struct section_64 *sect = getsectbyname("__text", section); if (sect) { desc->m_filename = fname; desc->m_start = sect->offset; desc->m_len = sect->size; return !desc->m_filename.empty(); } #endif // __APPLE__ return false; }
void HeapProfileRequestHandler::handleRequest(Transport *transport) { const char *url = transport->getCommand().c_str(); if (!strcmp(url, "hhprof/start")) { // if we can place the request, send a 200 if (handleStartRequest(transport)) { transport->sendString("OK\n", 200); } else { transport->sendString("Resource Unavailable\n", 503); } } else if (!strcmp(url, "pprof/cmdline")) { // the first thing pprof does when you call the script is find out // the name of the binary running on the remote server transport->sendString(current_executable_path(), 200); } else if (!strcmp(url, "pprof/heap")) { // the next thing pprof does is hit this endpoint and get a profile // dump ProfileController::waitForProfile([&](const ProfileDump& dump) { transport->sendString(dump.toPProfFormat(), 200); }); } else if (!strcmp(url, "pprof/symbol")) { // lastly, pprof hits this endpoint three times. the first time, it // hits with a HEAD request, which gives it some knowledge as to the // presence of the endpoint. then it hits with a GET request, and // expects the number of defined symbols in response. finally, it // hits with a POST request, with the POST data being a plus-separated // list of addresses for which it wants symbols if (transport->getMethod() == Transport::Method::HEAD) { transport->sendString("OK\n", 200); } else if (transport->getMethod() == Transport::Method::GET) { // actual number of sumbols is not really relevant // from the pprof documentation, pprof only considers values // that are either zero or non-zero transport->sendString("num_symbols: 1\n", 200); } else if (transport->getMethod() == Transport::Method::POST) { // split the post data by '+' character and resolve the symbol // for each int size; auto data = static_cast<const char *>(transport->getPostData(size)); std::string res; std::vector<folly::StringPiece> addrs; folly::split('+', folly::StringPiece(data, size), addrs); for (const auto &addr : addrs) { // for each address we get from pprof, it expects a line formatted // like the following // <address>\t<symbol name> if (!addr.size()) { continue; } std::string val(addr.data(), addr.size()); SrcKey sk = SrcKey::fromAtomicInt( static_cast<uint64_t>(std::stoll(val, 0, 16)) ); folly::toAppend(addr, "\t", sk.getSymbol(), "\n", &res); } transport->sendString(res, 200); if (RuntimeOption::ClientExecutionMode() && RuntimeOption::HHProfServerProfileClientMode) { std::unique_lock<std::mutex> lock(s_clientMutex); s_cond = true; s_clientWaitq.notify_all(); } } } else if (!strcmp(url, "hhprof/stop")) { // user has requested cancellation of the current profile dump ProfileController::cancelRequest(); transport->sendString("OK\n", 200); } else { // the pprof server doesn't understand any other endpoints so just error // out Logger::Warning(folly::format( "Unknown HHProf endpoint requested, command was: {}", url ).str()); transport->sendString("Not Found\n", 404); } }
void StandardExtension::initMisc() { HHVM_FALIAS(HH\\server_warmup_status, server_warmup_status); HHVM_FE(connection_aborted); HHVM_FE(connection_status); HHVM_FE(connection_timeout); HHVM_FE(constant); HHVM_FE(define); HHVM_FE(defined); HHVM_FE(ignore_user_abort); HHVM_FE(pack); HHVM_FE(sleep); HHVM_FE(usleep); HHVM_FE(time_nanosleep); HHVM_FE(time_sleep_until); HHVM_FE(uniqid); HHVM_FE(unpack); HHVM_FE(sys_getloadavg); HHVM_FE(token_get_all); HHVM_FE(token_name); HHVM_FE(hphp_to_string); HHVM_FALIAS(__SystemLib\\max2, SystemLib_max2); HHVM_FALIAS(__SystemLib\\min2, SystemLib_min2); HHVM_RC_INT(PHP_MAXPATHLEN, PATH_MAX); Native::registerConstant<KindOfBoolean>(makeStaticString("PHP_DEBUG"), #if DEBUG true #else false #endif ); bindTokenConstants(); HHVM_RC_INT(T_PAAMAYIM_NEKUDOTAYIM, get_user_token_id(T_DOUBLE_COLON)); HHVM_RC_INT(UPLOAD_ERR_OK, 0); HHVM_RC_INT(UPLOAD_ERR_INI_SIZE, 1); HHVM_RC_INT(UPLOAD_ERR_FORM_SIZE, 2); HHVM_RC_INT(UPLOAD_ERR_PARTIAL, 3); HHVM_RC_INT(UPLOAD_ERR_NO_FILE, 4); HHVM_RC_INT(UPLOAD_ERR_NO_TMP_DIR, 6); HHVM_RC_INT(UPLOAD_ERR_CANT_WRITE, 7); HHVM_RC_INT(UPLOAD_ERR_EXTENSION, 8); HHVM_RC_INT(CREDITS_GROUP, 1 << 0); HHVM_RC_INT(CREDITS_GENERAL, 1 << 1); HHVM_RC_INT(CREDITS_SAPI, 1 << 2); HHVM_RC_INT(CREDITS_MODULES, 1 << 3); HHVM_RC_INT(CREDITS_DOCS, 1 << 4); HHVM_RC_INT(CREDITS_FULLPAGE, 1 << 5); HHVM_RC_INT(CREDITS_QA, 1 << 6); HHVM_RC_INT(CREDITS_ALL, 0xFFFFFFFF); HHVM_RC_INT(INI_SYSTEM, IniSetting::PHP_INI_SYSTEM); HHVM_RC_INT(INI_PERDIR, IniSetting::PHP_INI_PERDIR); HHVM_RC_INT(INI_USER, IniSetting::PHP_INI_USER); HHVM_RC_INT(INI_ALL, IniSetting::PHP_INI_SYSTEM | IniSetting::PHP_INI_PERDIR | IniSetting::PHP_INI_USER); HHVM_RC_STR(PHP_BINARY, current_executable_path()); HHVM_RC_STR(PHP_BINDIR, current_executable_directory()); HHVM_RC_STR(PHP_OS, HHVM_FN(php_uname)("s").toString().toCppString()); HHVM_RC_STR(PHP_SAPI, RuntimeOption::ExecutionMode); HHVM_RC_INT(PHP_INT_SIZE, sizeof(int64_t)); HHVM_RC_INT(PHP_INT_MIN, k_PHP_INT_MIN); HHVM_RC_INT(PHP_INT_MAX, k_PHP_INT_MAX); HHVM_RC_INT_SAME(PHP_MAJOR_VERSION); HHVM_RC_INT_SAME(PHP_MINOR_VERSION); HHVM_RC_INT_SAME(PHP_RELEASE_VERSION); HHVM_RC_STR_SAME(PHP_EXTRA_VERSION); HHVM_RC_STR_SAME(PHP_VERSION); HHVM_RC_INT_SAME(PHP_VERSION_ID); // FIXME: These values are hardcoded from their previous IDL values // Grab their correct values from the system as appropriate HHVM_RC_STR(PHP_EOL, "\n"); HHVM_RC_STR(PHP_CONFIG_FILE_PATH, ""); HHVM_RC_STR(PHP_CONFIG_FILE_SCAN_DIR, ""); HHVM_RC_STR(PHP_DATADIR, ""); HHVM_RC_STR(PHP_EXTENSION_DIR, ""); HHVM_RC_STR(PHP_LIBDIR, ""); HHVM_RC_STR(PHP_LOCALSTATEDIR, ""); HHVM_RC_STR(PHP_PREFIX, ""); HHVM_RC_STR(PHP_SHLIB_SUFFIX, "so"); HHVM_RC_STR(PHP_SYSCONFDIR, ""); HHVM_RC_STR(PEAR_EXTENSION_DIR, ""); HHVM_RC_STR(PEAR_INSTALL_DIR, ""); loadSystemlib("std_misc"); }
void DebugInfo::generatePidMapOverlay() { if (!m_perfMap || !pidMapOverlayStart) return; std::string self = current_executable_path(); bfd* abfd = bfd_openr(self.c_str(), nullptr); #ifdef BFD_DECOMPRESS abfd->flags |= BFD_DECOMPRESS; #endif char **match = nullptr; if (!bfd_check_format(abfd, bfd_archive) && bfd_check_format_matches(abfd, bfd_object, &match)) { std::vector<asymbol*> sorted; long storage_needed = bfd_get_symtab_upper_bound (abfd); if (storage_needed <= 0) return; auto symbol_table = (asymbol**)malloc(storage_needed); long number_of_symbols = bfd_canonicalize_symtab(abfd, symbol_table); for (long i = 0; i < number_of_symbols; i++) { auto sym = symbol_table[i]; if (sym->flags & (BSF_INDIRECT | BSF_SECTION_SYM | BSF_FILE | BSF_DEBUGGING_RELOC | BSF_OBJECT)) { continue; } auto sec = sym->section; if (!(sec->flags & (SEC_ALLOC|SEC_LOAD|SEC_CODE))) continue; auto addr = sec->vma + sym->value; if (addr < uintptr_t(pidMapOverlayStart) || addr >= uintptr_t(pidMapOverlayEnd)) { continue; } sorted.push_back(sym); } std::sort(sorted.begin(), sorted.end(), [](asymbol* a, asymbol* b) { auto addra = a->section->vma + a->value; auto addrb = b->section->vma + b->value; if (addra != addrb) return addra < addrb; return strncmp("_ZN4HPHP", a->name, 8) && !strncmp("_ZN4HPHP", b->name, 8); }); for (size_t i = 0; i < sorted.size(); i++) { auto sym = sorted[i]; auto addr = sym->section->vma + sym->value; int status; char* demangled = abi::__cxa_demangle(sym->name, nullptr, nullptr, &status); if (status != 0) demangled = const_cast<char*>(sym->name); unsigned size; if (i + 1 < sorted.size()) { auto s2 = sorted[i + 1]; size = s2->section->vma + s2->value - addr; } else { size = uintptr_t(pidMapOverlayEnd) - addr; } if (!size) continue; fprintf(m_perfMap, "%lx %x %s\n", long(addr), size, demangled); if (status == 0) free(demangled); } free(symbol_table); free(match); } bfd_close(abfd); return; }
void StandardExtension::initMisc() { HHVM_FALIAS(HH\\server_warmup_status, server_warmup_status); HHVM_FE(connection_aborted); HHVM_FE(connection_status); HHVM_FE(connection_timeout); HHVM_FE(constant); HHVM_FE(define); HHVM_FE(defined); HHVM_FE(ignore_user_abort); HHVM_FE(pack); HHVM_FE(sleep); HHVM_FE(usleep); HHVM_FE(time_nanosleep); HHVM_FE(time_sleep_until); HHVM_FE(uniqid); HHVM_FE(unpack); HHVM_FE(sys_getloadavg); HHVM_FE(token_get_all); HHVM_FE(token_name); HHVM_FE(hphp_to_string); HHVM_FALIAS(__SystemLib\\max2, SystemLib_max2); HHVM_FALIAS(__SystemLib\\min2, SystemLib_min2); Native::registerConstant<KindOfDouble>(makeStaticString("INF"), k_INF); Native::registerConstant<KindOfDouble>(makeStaticString("NAN"), k_NAN); Native::registerConstant<KindOfInt64>( makeStaticString("PHP_MAXPATHLEN"), MAXPATHLEN); Native::registerConstant<KindOfBoolean>(makeStaticString("PHP_DEBUG"), #if DEBUG true #else false #endif ); bindTokenConstants(); Native::registerConstant<KindOfInt64>(s_T_PAAMAYIM_NEKUDOTAYIM.get(), get_user_token_id(T_DOUBLE_COLON)); HHVM_RC_STR(PHP_BINARY, current_executable_path()); HHVM_RC_STR(PHP_BINDIR, current_executable_directory()); HHVM_RC_STR(PHP_OS, HHVM_FN(php_uname)("s").toString().toCppString()); HHVM_RC_STR(PHP_SAPI, RuntimeOption::ExecutionMode); HHVM_RC_INT(PHP_INT_SIZE, sizeof(int64_t)); HHVM_RC_INT(PHP_INT_MIN, k_PHP_INT_MIN); HHVM_RC_INT(PHP_INT_MAX, k_PHP_INT_MAX); HHVM_RC_INT_SAME(PHP_MAJOR_VERSION); HHVM_RC_INT_SAME(PHP_MINOR_VERSION); HHVM_RC_INT_SAME(PHP_RELEASE_VERSION); HHVM_RC_STR_SAME(PHP_EXTRA_VERSION); HHVM_RC_STR_SAME(PHP_VERSION); HHVM_RC_INT_SAME(PHP_VERSION_ID); // FIXME: These values are hardcoded from their previous IDL values // Grab their correct values from the system as appropriate HHVM_RC_STR(PHP_EOL, "\n"); HHVM_RC_STR(PHP_CONFIG_FILE_PATH, ""); HHVM_RC_STR(PHP_CONFIG_FILE_SCAN_DIR, ""); HHVM_RC_STR(PHP_DATADIR, ""); HHVM_RC_STR(PHP_EXTENSION_DIR, ""); HHVM_RC_STR(PHP_LIBDIR, ""); HHVM_RC_STR(PHP_LOCALSTATEDIR, ""); HHVM_RC_STR(PHP_PREFIX, ""); HHVM_RC_STR(PHP_SHLIB_SUFFIX, "so"); HHVM_RC_STR(PHP_SYSCONFDIR, ""); HHVM_RC_STR(PEAR_EXTENSION_DIR, ""); HHVM_RC_STR(PEAR_INSTALL_DIR, ""); loadSystemlib("std_misc"); }