declare_folded_class NO LONGER _in_file
[hiphop-php.git] / hphp / util / abi-cxx.cpp
blob6ab4885b0d6b98c5b42f3098521f84cc5d283c40
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #include "hphp/util/abi-cxx.h"
18 #include <algorithm>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <cstring>
22 #include <memory>
23 #include <mutex>
24 #include <string>
26 #ifdef _MSC_VER
27 # include <windows.h>
28 # include <dbghelp.h>
29 #else
30 # include <cxxabi.h>
31 # include <execinfo.h>
32 #endif
34 #include <folly/Demangle.h>
35 #include <folly/Format.h>
37 #include "hphp/util/functional.h"
38 #include "hphp/util/compatibility.h"
39 #include "hphp/util/hash-map.h"
41 #ifdef FACEBOOK
42 #include <folly/experimental/symbolizer/Symbolizer.h>
43 #endif
45 namespace HPHP {
47 //////////////////////////////////////////////////////////////////////
49 namespace {
51 typedef std::lock_guard<std::mutex> G;
52 std::mutex nameCacheLock;
53 hphp_fast_map<void*, std::string, pointer_hash<void>> nameCache;
57 //////////////////////////////////////////////////////////////////////
59 void registerNativeFunctionName(void* codeAddr, const std::string& name) {
60 G g(nameCacheLock);
61 nameCache[codeAddr] = name;
64 std::string getNativeFunctionName(void* codeAddr) {
66 G g(nameCacheLock);
67 auto it = nameCache.find(codeAddr);
68 if (it != end(nameCache)) return it->second;
70 std::string functionName;
72 #ifdef _MSC_VER
73 HANDLE process = GetCurrentProcess();
74 SYMBOL_INFO *symbol;
75 DWORD64 addr_disp = 0;
77 // syminitialize and symcleanup should really be once per process
78 SymInitialize(process, nullptr, TRUE);
80 symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
81 symbol->MaxNameLen = 255;
82 symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
84 if(SymFromAddr(process, (DWORD64) codeAddr, &addr_disp, symbol)) {
85 functionName.assign(symbol->Name);
87 int status;
88 char* demangledName = (char*)calloc(1024, sizeof(char));
89 status = !(int)UnDecorateSymbolName(
90 symbol->Name, demangledName, 1023, UNDNAME_COMPLETE);
91 SCOPE_EXIT { free(demangledName); };
92 if (status == 0) functionName.assign(demangledName);
95 free(symbol);
97 SymCleanup(process);
98 #elif defined(FACEBOOK)
100 folly::symbolizer::Symbolizer symbolizer;
101 folly::symbolizer::SymbolizedFrame frame;
102 if (symbolizer.symbolize(uintptr_t(codeAddr), frame)) {
103 functionName = folly::demangle(frame.name).toStdString();
106 #else
107 void* buf[1] = {codeAddr};
108 char** symbols = backtrace_symbols(buf, 1);
110 if (symbols != nullptr) {
112 // the output from backtrace_symbols looks like this:
113 // ../path/hhvm/hhvm(_ZN4HPHP2VM6Transl17interpOneIterInitEv+0) [0x17cebe9]
115 // we first want to extract the mangled name from it to get this:
116 // _ZN4HPHP2VM6Transl17interpOneIterInitEv
118 // and then pass this to abi::__cxa_demangle to get the demangled name:
119 // HPHP::jit::interpOneIterInit()
121 // Sometimes, though, backtrace_symbols can't find the function name
122 // and ends up giving us a blank mangled name, like this:
123 // ../path/hhvm/hhvm() [0x17e4d01]
124 // or this: [0x7fffca800130]
126 char* start = strchr(*symbols, '(');
127 if (start) {
128 start++;
129 char* end = strchr(start, '+');
130 if (end != nullptr) {
131 functionName.assign(start, end);
132 int status;
133 char* demangledName = abi::__cxa_demangle(functionName.c_str(),
134 0, 0, &status);
135 SCOPE_EXIT { free(demangledName); };
136 if (status == 0) functionName.assign(demangledName);
141 // backtrace_symbols requires that we free the array of strings but not the
142 // strings themselves.
143 free(symbols);
144 #endif
146 if (functionName.empty()) functionName = folly::format("{}", codeAddr).str();
148 G g(nameCacheLock);
149 return nameCache[codeAddr] = functionName;
152 //////////////////////////////////////////////////////////////////////