diff --git a/CMake/FindLibElf.cmake b/CMake/FindLibElf.cmake index 4a3b78fad..413401ea2 100644 --- a/CMake/FindLibElf.cmake +++ b/CMake/FindLibElf.cmake @@ -51,5 +51,14 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibElf DEFAULT_MSG LIBELF_LIBRARIES LIBELF_INCLUDE_DIRS) +SET(CMAKE_REQUIRED_LIBRARIES elf) +INCLUDE(CheckCXXSourceCompiles) +CHECK_CXX_SOURCE_COMPILES("#include +int main() { + Elf *e = (Elf*)0; + size_t sz; + elf_getshdrstrndx(e, &sz); + return 0; +}" ELF_GETSHDRSTRNDX) -mark_as_advanced(LIBELF_INCLUDE_DIRS LIBELF_LIBRARIES) +mark_as_advanced(LIBELF_INCLUDE_DIRS LIBELF_LIBRARIES ELF_GETSHDRSTRNDX) diff --git a/CMake/HPHPFindLibs.cmake b/CMake/HPHPFindLibs.cmake index 9cc8b85d9..6398e94dc 100644 --- a/CMake/HPHPFindLibs.cmake +++ b/CMake/HPHPFindLibs.cmake @@ -266,6 +266,9 @@ include_directories(${LIBDWARF_INCLUDE_DIRS}) find_package(LibElf REQUIRED) include_directories(${LIBELF_INCLUDE_DIRS}) +if (ELF_GETSHDRSTRNDX) + add_definitions("-DHAVE_ELF_GETSHDRSTRNDX") +endif() CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/utf8.h" U8T_DECOMPOSE RECENT_CCLIENT) if (NOT RECENT_CCLIENT) diff --git a/hphp/compiler/analysis/emitter.cpp b/hphp/compiler/analysis/emitter.cpp index 7520dcbe1..6536e0fca 100644 --- a/hphp/compiler/analysis/emitter.cpp +++ b/hphp/compiler/analysis/emitter.cpp @@ -7314,53 +7314,6 @@ static void batchCommit(std::vector& ues) { ues.clear(); } -static void emitSystemLib() { - if (!Option::WholeProgram) return; - - string slib = systemlib_path(); - if (slib.empty()) return; - - FILE* sl = fopen(slib.c_str(), "r"); - if (!sl) return; - fseek(sl, 0, SEEK_END); - long len = ftell(sl); - fseek(sl, 0, SEEK_SET); - - char *code = (char*)malloc(len + 1); - Option::WholeProgram = false; - SystemLib::s_inited = false; - - SCOPE_EXIT { - SystemLib::s_inited = true; - Option::WholeProgram = true; - free(code); - }; - - if (fread(code, len, 1, sl) != 1) { - throw Exception("Failed to read systemlib"); - } - - code[len] = 0; - AnalysisResultPtr ar(new AnalysisResult()); - Scanner scanner(code, len, RuntimeOption::ScannerType, "/:systemlib.php"); - Parser parser(scanner, "/:systemlib.php", ar, len); - parser.parse(); - FileScopePtr fsp = parser.getFileScope(); - fsp->setOuterScope(ar); - - ar->loadBuiltins(); - ar->setPhase(AnalysisResult::AnalyzeAll); - fsp->analyzeProgram(ar); - - int md5len; - char* md5str = string_md5(code, len, false, md5len); - MD5 md5(md5str); - free(md5str); - - UnitEmitter* ue = emitHHBCUnitEmitter(ar, fsp, md5); - Repo::get().commitUnit(ue, UnitOriginFile); -} - /** * This is the entry point for offline bytecode generation. */ @@ -7415,8 +7368,6 @@ void emitAllHHBC(AnalysisResultPtr ar) { break; } } - - emitSystemLib(); } else { dispatcher.waitEmpty(); } diff --git a/hphp/compiler/builtin_symbols.cpp b/hphp/compiler/builtin_symbols.cpp index 5e64f5c4d..a1ad7a1be 100644 --- a/hphp/compiler/builtin_symbols.cpp +++ b/hphp/compiler/builtin_symbols.cpp @@ -311,24 +311,6 @@ void BuiltinSymbols::ImportExtClasses(AnalysisResultPtr ar) { } } -void BuiltinSymbols::Parse(AnalysisResultPtr ar, - const std::string& phpBaseName, - const std::string& phpFileName) { - const char *baseName = s_strings.add(phpBaseName.c_str()); - const char *fileName = s_strings.add(phpFileName.c_str()); - try { - Scanner scanner(fileName, Option::ScannerType); - Compiler::Parser parser(scanner, baseName, ar); - if (!parser.parse()) { - Logger::Error("Unable to parse file %s: %s", fileName, - parser.getMessage().c_str()); - assert(false); - } - } catch (FileOpenException &e) { - Logger::Error("%s", e.getMessage().c_str()); - } -} - bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) { if (Loaded) return true; Loaded = true; @@ -346,17 +328,17 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar, bool extOnly /* = false */) { if (!extOnly) { ar = AnalysisResultPtr(new AnalysisResult()); ar->loadBuiltinFunctions(); - string slib = systemlib_path(); - if (slib.empty()) { - for (const char **cls = SystemClasses; *cls; cls++) { - string phpBaseName = "/system/classes/"; - phpBaseName += *cls; - phpBaseName += ".php"; - Parse(ar, phpBaseName, Option::GetSystemRoot() + phpBaseName); - } - } else { - Parse(ar, slib, slib); + string slib = get_systemlib(); + + Scanner scanner(slib.c_str(), slib.size(), + Option::ScannerType, "systemlib.php"); + Compiler::Parser parser(scanner, "systemlib.php", ar); + if (!parser.parse()) { + Logger::Error("Unable to parse systemlib.php: %s", + parser.getMessage().c_str()); + assert(false); } + ar->analyzeProgram(true); ar->inferTypes(); const StringToFileScopePtrMap &files = ar->getAllFiles(); diff --git a/hphp/compiler/builtin_symbols.h b/hphp/compiler/builtin_symbols.h index c2c0e4247..9290bffef 100644 --- a/hphp/compiler/builtin_symbols.h +++ b/hphp/compiler/builtin_symbols.h @@ -73,9 +73,6 @@ private: static const char *SystemClasses[]; static AnalysisResultPtr LoadGlobalSymbols(const char *fileName); - static void Parse(AnalysisResultPtr ar, - const std::string& phpBaseName, - const std::string& phpFileName); static StringToTypePtrMap s_superGlobals; diff --git a/hphp/hhvm/CMakeLists.txt b/hphp/hhvm/CMakeLists.txt index 6c168d681..d93f5bf02 100644 --- a/hphp/hhvm/CMakeLists.txt +++ b/hphp/hhvm/CMakeLists.txt @@ -5,6 +5,10 @@ list(APPEND CXX_SOURCES ${files}) add_executable(hhvm ${CXX_SOURCES}) target_link_libraries(hhvm hphp_analysis hphp_runtime_static ext_hhvm_static) -install(TARGETS hhvm DESTINATION bin) -install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/systemlib.php DESTINATION bin) +add_custom_command(TARGET hhvm POST_BUILD + COMMAND "objcopy" + ARGS "--add-section" "systemlib=${HPHP_HOME}/bin/systemlib.php" + "${CMAKE_CURRENT_SOURCE_DIR}/hhvm" + COMMENT "Embedding systemlib.php in hhvm") +install(TARGETS hhvm DESTINATION bin) diff --git a/hphp/hhvm/main.cpp b/hphp/hhvm/main.cpp index 74362a65c..6eeae27f0 100644 --- a/hphp/hhvm/main.cpp +++ b/hphp/hhvm/main.cpp @@ -16,9 +16,12 @@ #include "runtime/base/program_functions.h" #include "hhvm/process_init.h" -#include "runtime/vm/embedded_repo.h" #include "compiler/compiler.h" +#include "util/embedded_data.h" +#include "util/embedded_vfs.h" +#include "util/util.h" + int main(int argc, char** argv) { if (!argc) return 0; if (argc > 1 && !strcmp(argv[1], "--hphp")) { @@ -26,10 +29,16 @@ int main(int argc, char** argv) { return HPHP::compiler_main(argc - 1, argv + 1); } HPHP::register_process_init(); - std::string repo = HPHP::get_embedded_repo(); - if (repo.empty()) { + HPHP::Util::embedded_data data; + if (!HPHP::Util::get_embedded_data("repo", &data)) { return HPHP::execute_program(argc, argv); } + std::string repo; + HPHP::Util::string_printf(repo, "%s:%u:%u", + data.m_filename.c_str(), + (unsigned)data.m_start, (unsigned)data.m_len); + HPHP::sqlite3_embedded_initialize(nullptr, true); + std::vector args; args.push_back(argv[0]); args.push_back("-vRepo.Authoritative=true"); diff --git a/hphp/hhvm/process_init.cpp b/hphp/hhvm/process_init.cpp index 2132030b6..42cf1577d 100644 --- a/hphp/hhvm/process_init.cpp +++ b/hphp/hhvm/process_init.cpp @@ -123,37 +123,17 @@ void ProcessInit() { hhbc_ext_funcs_count); SystemLib::s_nativeFuncUnit = nativeFuncUnit; - // Search for systemlib.php in the following places: - // 1) ${HHVM_LIB_PATH}/systemlib.php - // 2) /systemlib.php (requires proc filesystem) - // 3) /systemlib.php - // - // HHVM_LIB_PATH allows a manual override at runtime. If systemlib.php - // exists next to the hhvm binary, that is likely to be the next best - // version to use. The realpath()-based lookup will succeed as long as the - // proc filesystem exists (e.g. on Linux and some FreeBSD configurations) - // and no hard links are in use for the executable. Failing all of those - // options, the HHVM_LIB_PATH_DEFAULT-based lookup will always succeed, - // assuming that the application was built and installed correctly. String currentDir = g_vmContext->getCwd(); - HPHP::Eval::PhpFile* file = nullptr; - string slib = RuntimeOption::RepoAuthoritative ? - string("/:systemlib.php") : systemlib_path(); + string slib = get_systemlib(); - if (!slib.empty()) { - file = g_vmContext->lookupPhpFile(String(slib).get(), - currentDir.data(), nullptr); - } - if (!file) { + if (slib.empty()) { // Die a horrible death. Logger::Error("Unable to find/load systemlib.php"); _exit(1); } - SystemLib::s_phpFile = file; - file->incRef(); - SystemLib::s_unit = file->unit(); + SystemLib::s_unit = compile_string(slib.c_str(), slib.size()); // Restore most settings before merging anything, // because of optimizations that depend on them diff --git a/hphp/runtime/base/program_functions.cpp b/hphp/runtime/base/program_functions.cpp index 1589e484d..900179177 100644 --- a/hphp/runtime/base/program_functions.cpp +++ b/hphp/runtime/base/program_functions.cpp @@ -34,6 +34,7 @@ #include "runtime/base/memory/memory_manager.h" #include "util/process.h" #include "util/capability.h" +#include "util/embedded_data.h" #include "util/timer.h" #include "util/stack_trace.h" #include "util/light_process.h" @@ -1116,30 +1117,29 @@ String canonicalize_path(CStrRef p, const char* root, int rootLen) { return path; } -static bool check_path(const char *path) { - if (!path) return false; - - string file = string(path) + "/systemlib.php"; - struct stat result; - if (stat(file.c_str(), &result)) { - return false; +// Search for systemlib.php in the following places: +// 1) ${HHVM_SYSTEMLIB} +// 2) section "systemlib" in the current executable +// and return its contents +string get_systemlib() { + if (char *file = getenv("HHVM_SYSTEMLIB")) { + std::ifstream ifs(file); + if (ifs.good()) { + return std::string(std::istreambuf_iterator(ifs), + std::istreambuf_iterator()); + } } - return S_ISREG(result.st_mode); -} -string systemlib_path() { - char *file; - char buf[PATH_MAX + 1]; - if (!check_path(file = getenv("HHVM_LIB_PATH")) && - !(realpath("/proc/self/exe", buf) && - check_path(file = dirname(buf))) -#ifdef HHVM_LIB_PATH_DEFAULT - && !(check_path(file = HHVM_LIB_PATH_DEFAULT)) -#endif - ) { - return ""; - } - return string(file) + "/systemlib.php"; + Util::embedded_data desc; + if (!Util::get_embedded_data("systemlib", &desc)) return ""; + + std::ifstream ifs(desc.m_filename); + if (!ifs.good()) return ""; + ifs.seekg(desc.m_start, std::ios::beg); + std::unique_ptr data(new char[desc.m_len]); + ifs.read(data.get(), desc.m_len); + string result(data.get(), desc.m_len); + return result; } /////////////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/base/program_functions.h b/hphp/runtime/base/program_functions.h index cc9a493f5..b0103a915 100644 --- a/hphp/runtime/base/program_functions.h +++ b/hphp/runtime/base/program_functions.h @@ -81,7 +81,7 @@ void hphp_thread_exit(); void hphp_session_exit(); void hphp_process_exit() ATTRIBUTE_COLD; bool hphp_is_warmup_enabled(); -std::string systemlib_path(); +std::string get_systemlib(); // Generated by hphp/util/generate_buildinfo.sh. extern const char* const kCompilerId; diff --git a/hphp/runtime/vm/translator/test/main.cpp b/hphp/runtime/vm/translator/test/main.cpp index fd8744f8a..a5e2b1b48 100644 --- a/hphp/runtime/vm/translator/test/main.cpp +++ b/hphp/runtime/vm/translator/test/main.cpp @@ -16,7 +16,20 @@ #include #include "hhvm/process_init.h" +#include + int main(int argc, char** argv) { + char buf[PATH_MAX]; + if (realpath("/proc/self/exe", buf)) { + for (int i = 0; i < 4; i++) { + char* p = strrchr(buf, '/'); + assert(p); + *p = 0; + } + std::string slib = buf; + slib += "/ext_hhvm/systemlib.php"; + setenv("HHVM_SYSTEMLIB", slib.c_str(), true); + } testing::InitGoogleTest(&argc, argv); HPHP::init_for_unit_test(); return RUN_ALL_TESTS(); diff --git a/hphp/system/lib/systemlib.cpp b/hphp/system/lib/systemlib.cpp index 55a3342cf..7d6b9c8dc 100644 --- a/hphp/system/lib/systemlib.cpp +++ b/hphp/system/lib/systemlib.cpp @@ -33,7 +33,6 @@ namespace HPHP { } bool SystemLib::s_inited = false; -HPHP::Eval::PhpFile* SystemLib::s_phpFile = nullptr; HPHP::VM::Unit* SystemLib::s_unit = nullptr; HPHP::VM::Unit* SystemLib::s_nativeFuncUnit = nullptr; HPHP::VM::Unit* SystemLib::s_nativeClassUnit = nullptr; diff --git a/hphp/system/lib/systemlib.h b/hphp/system/lib/systemlib.h index 747382635..cd87ec316 100644 --- a/hphp/system/lib/systemlib.h +++ b/hphp/system/lib/systemlib.h @@ -14,11 +14,11 @@ +----------------------------------------------------------------------+ */ -#include - #ifndef incl_HPHP_SYSTEMLIB_H_ #define incl_HPHP_SYSTEMLIB_H_ +#include + namespace HPHP { /////////////////////////////////////////////////////////////////////////////// @@ -71,7 +71,6 @@ namespace Eval { class SystemLib { public: static bool s_inited; - static HPHP::Eval::PhpFile* s_phpFile; static HPHP::VM::Unit* s_unit; static HPHP::VM::Unit* s_nativeFuncUnit; static HPHP::VM::Unit* s_nativeClassUnit; diff --git a/hphp/test/quick/Setprofile.php.expectf b/hphp/test/quick/Setprofile.php.expectf index b3a1d1704..3b0cb8b56 100644 --- a/hphp/test/quick/Setprofile.php.expectf +++ b/hphp/test/quick/Setprofile.php.expectf @@ -200,7 +200,7 @@ array(3) { [0]=> array(6) { ["file"]=> - string(%d) "%s" + string(%d) "%S" ["line"]=> int(42) ["function"]=> diff --git a/hphp/tools/generated_files.sh b/hphp/tools/generated_files.sh index a80719c3d..af06bf24e 100755 --- a/hphp/tools/generated_files.sh +++ b/hphp/tools/generated_files.sh @@ -13,7 +13,13 @@ check_err() VERBOSE=1 HHVM=$HPHP_HOME/hphp/hhvm/hhvm -[ ! -x "$HHVM" ] && HHVM=`which hhvm` +if [ -x "$HHVM" ]; then + export HHVM_SYSTEMLIB=$HPHP_HOME/bin/systemlib.php +else + HHVM=`which hhvm` + export HHVM_SYSTEMLIB=`dirname $HHVM`/systemlib.php +fi + [ ! -x "$HHVM" ] && check_err 1 "$HHVM is not executable" HPHP_TOOLS=$HPHP_HOME/hphp/tools/ diff --git a/hphp/runtime/vm/embedded_repo.cpp b/hphp/util/embedded_data.cpp similarity index 71% rename from hphp/runtime/vm/embedded_repo.cpp rename to hphp/util/embedded_data.cpp index a89c603c4..cfc5a9a8c 100644 --- a/hphp/runtime/vm/embedded_repo.cpp +++ b/hphp/util/embedded_data.cpp @@ -14,6 +14,8 @@ +----------------------------------------------------------------------+ */ +#include "util/embedded_data.h" + #include #include #include @@ -22,44 +24,46 @@ #include #include -#include -#include +namespace HPHP { namespace Util { -namespace HPHP { - -std::string get_embedded_repo() { +bool get_embedded_data(const char *section, embedded_data* desc) { GElf_Shdr shdr; size_t shstrndx; char *name; Elf_Scn *scn; - if (elf_version(EV_CURRENT) == EV_NONE) return ""; + if (elf_version(EV_CURRENT) == EV_NONE) return false; int fd = open("/proc/self/exe", O_RDONLY, 0); - if (fd < 0) return ""; + if (fd < 0) return false; Elf* e = elf_begin(fd, ELF_C_READ, nullptr); if (!e || elf_kind(e) != ELF_K_ELF || - !elf_getshstrndx(e, &shstrndx)) { - return ""; +#ifdef HAVE_ELF_GETSHDRSTRNDX + elf_getshdrstrndx(e, &shstrndx) +#else + !elf_getshstrndx(e, &shstrndx) +#endif + ) { + return false; } scn = nullptr; while ((scn = elf_nextscn(e, scn)) != nullptr) { if (gelf_getshdr(scn, &shdr) != &shdr || !(name = elf_strptr(e, shstrndx , shdr.sh_name))) { - return ""; + return false; } - if (!strcmp("repo", name)) { + if (!strcmp(section, name)) { GElf_Shdr ghdr; - if (gelf_getshdr(scn, &ghdr) != &ghdr) return ""; - char buf[512]; - sprintf(buf, "/proc/self/exe:%lu:%lu", ghdr.sh_offset, ghdr.sh_size); - sqlite3_embedded_initialize(nullptr, true); - return buf; + if (gelf_getshdr(scn, &ghdr) != &ghdr) return false; + desc->m_filename = "/proc/self/exe"; + desc->m_start = ghdr.sh_offset; + desc->m_len = ghdr.sh_size; + return true; } } - return ""; + return false; } -} +} } diff --git a/hphp/runtime/vm/embedded_repo.h b/hphp/util/embedded_data.h similarity index 83% rename from hphp/runtime/vm/embedded_repo.h rename to hphp/util/embedded_data.h index e48a92f21..b66271c6f 100644 --- a/hphp/runtime/vm/embedded_repo.h +++ b/hphp/util/embedded_data.h @@ -19,10 +19,16 @@ #include -namespace HPHP { +namespace HPHP { namespace Util { -std::string get_embedded_repo(); +struct embedded_data { + std::string m_filename; + uint32_t m_start; + uint32_t m_len; +}; -} +bool get_embedded_data(const char *section, embedded_data* desc); + +} } #endif