codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / runtime / vm / debug / dwarf.cpp
blobc647d15c95e3cdea4129975348c324258eb3ed03
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/runtime/vm/debug/dwarf.h"
18 #include <stdio.h>
19 #include "debug.h"
20 #include "hphp/runtime/vm/debug/gdb-jit.h"
22 #include "hphp/runtime/base/execution-context.h"
23 #include "hphp/runtime/vm/jit/translator.h"
24 #include "hphp/runtime/vm/jit/translator-inline.h"
26 #if (!defined(__APPLE__) && !defined(__FreeBSD__) && \
27 !defined(__CYGWIN__) && !defined(_MSC_VER))
28 #include "hphp/runtime/vm/debug/elfwriter.h"
29 #define USE_ELF_WRITER 1
30 #endif
32 using namespace HPHP::jit;
34 namespace HPHP {
35 namespace Debug {
37 int g_dwarfCallback(
38 LIBDWARF_CALLBACK_NAME_TYPE name, int size, Dwarf_Unsigned type,
39 Dwarf_Unsigned flags, Dwarf_Unsigned link, Dwarf_Unsigned info,
40 Dwarf_Unsigned *sect_name_index, Dwarf_Ptr handle, int *error) {
41 #ifdef USE_ELF_WRITER
42 ElfWriter *e = reinterpret_cast<ElfWriter *>(handle);
43 return e->dwarfCallback(name, size, type, flags, link, info);
44 #else
45 return 0;
46 #endif
49 void DwarfBuf::byte(uint8_t c) {
50 m_buf.push_back(c);
53 void DwarfBuf::clear() {
54 m_buf.clear();
57 int DwarfBuf::size() {
58 return m_buf.size();
61 uint8_t *DwarfBuf::getBuf() {
62 return m_buf.data();
65 void DwarfBuf::print() {
66 unsigned int i;
67 for (i = 0; i < m_buf.size(); i++)
68 printf("%x ", m_buf[i]);
69 printf("\n");
72 void DwarfBuf::dwarf_cfa_def_cfa(uint8_t reg, uint8_t offset) {
73 byte(DW_CFA_def_cfa);
74 byte(reg);
75 byte(offset);
78 void DwarfBuf::dwarf_cfa_same_value(uint8_t reg) {
79 byte(DW_CFA_same_value);
80 byte(reg);
83 void DwarfBuf::dwarf_cfa_offset_extended_sf(uint8_t reg, int8_t offset) {
84 byte(DW_CFA_offset_extended_sf);
85 byte(reg);
86 byte(offset & 0x7f);
89 const char *DwarfInfo::lookupFile(const Unit *unit) {
90 const char *file = nullptr;
91 if (unit && unit->filepath()) {
92 file = unit->filepath()->data();
94 if (file == nullptr || strlen(file) == 0) {
95 return "anonFile";
97 return file;
100 void DwarfInfo::addLineEntries(TCRange range,
101 const Unit *unit,
102 PC instr,
103 FunctionInfo* f) {
104 if (unit == nullptr || instr == nullptr) {
105 // For stubs, just add line 0
106 f->m_lineTable.push_back(LineEntry(range, 0));
107 return;
109 Offset offset = unit->offsetOf(instr);
111 int lineNum = unit->getLineNumber(offset);
112 if (lineNum >= 0) {
113 f->m_lineTable.push_back(LineEntry(range, lineNum));
117 void DwarfInfo::transferFuncs(DwarfChunk* from, DwarfChunk* to) {
118 unsigned int size = from->m_functions.size();
119 for (unsigned int i = 0; i < size; i++) {
120 FunctionInfo* f = from->m_functions[i];
121 f->m_chunk = to;
122 to->m_functions.push_back(f);
126 void DwarfInfo::compactChunks() {
127 unsigned int i, j;
128 for (i = 1; i < m_dwarfChunks.size(); i++) {
129 if (m_dwarfChunks[i] == nullptr) {
130 break;
133 if (i >= m_dwarfChunks.size()) {
134 m_dwarfChunks.push_back(nullptr);
136 DwarfChunk* chunk = new DwarfChunk();
137 for (j = 0; j < i; j++) {
138 transferFuncs(m_dwarfChunks[j], chunk);
139 // unregister chunk from gdb and free chunk
140 unregister_gdb_chunk(m_dwarfChunks[j]);
141 delete(m_dwarfChunks[j]);
142 m_dwarfChunks[j] = nullptr;
144 m_dwarfChunks[i] = chunk;
145 #ifdef USE_ELF_WRITER
146 // register compacted chunk with gdb
147 ElfWriter e = ElfWriter(chunk);
148 #endif
151 static Mutex s_lock(RankLeaf);
153 DwarfChunk* DwarfInfo::addTracelet(TCRange range,
154 folly::Optional<std::string> name,
155 const Func *func,
156 PC instr,
157 bool exit,
158 bool inPrologue) {
159 DwarfChunk* chunk = nullptr;
160 FunctionInfo* f = new FunctionInfo(range, exit);
161 const Unit* unit = func ? func->unit(): nullptr;
162 if (name) {
163 f->name = *name;
164 } else {
165 assert(func != nullptr);
166 f->name = lookupFunction(func, exit, inPrologue, true);
167 auto names = func->localNames();
168 for (int i = 0; i < func->numNamedLocals(); i++) {
169 f->m_namedLocals.push_back(names[i]->toCppString());
172 f->file = lookupFile(unit);
174 TCA start = range.begin();
175 const TCA end = range.end();
177 Lock lock(s_lock);
178 auto const it = m_functions.lower_bound(range.begin());
179 auto const fi = it->second;
180 if (it != m_functions.end() && fi->name == f->name &&
181 fi->file == f->file &&
182 start > fi->range.begin() &&
183 end > fi->range.end()) {
184 // XXX: verify that overlapping address come from jmp fixups
185 start = fi->range.end();
186 fi->range.extend(end);
187 m_functions[end] = fi;
188 m_functions.erase(it);
189 delete f;
190 f = m_functions[end];
191 assert(f->m_chunk != nullptr);
192 f->m_chunk->clearSynced();
193 f->clearPerfSynced();
194 } else {
195 m_functions[end] = f;
198 addLineEntries(TCRange(start, end, range.isAcold()), unit, instr, f);
200 if (f->m_chunk == nullptr) {
201 if (m_dwarfChunks.size() == 0 || m_dwarfChunks[0] == nullptr) {
202 // new chunk of base size
203 chunk = new DwarfChunk();
204 m_dwarfChunks.push_back(chunk);
205 } else if (m_dwarfChunks[0]->m_functions.size()
206 < RuntimeOption::EvalGdbSyncChunks) {
207 // reuse first chunk
208 chunk = m_dwarfChunks[0];
209 chunk->clearSynced();
210 } else {
211 // compact chunks
212 compactChunks();
213 m_dwarfChunks[0] = chunk = new DwarfChunk();
215 chunk->m_functions.push_back(f);
216 f->m_chunk = chunk;
219 #ifdef USE_ELF_WRITER
220 if (f->m_chunk->m_functions.size() >= RuntimeOption::EvalGdbSyncChunks) {
221 ElfWriter e = ElfWriter(f->m_chunk);
223 #endif
225 return f->m_chunk;
228 void DwarfInfo::syncChunks() {
229 unsigned int i;
230 Lock lock(s_lock);
231 for (i = 0; i < m_dwarfChunks.size(); i++) {
232 if (m_dwarfChunks[i] && !m_dwarfChunks[i]->isSynced()) {
233 unregister_gdb_chunk(m_dwarfChunks[i]);
234 #ifdef USE_ELF_WRITER
235 ElfWriter e = ElfWriter(m_dwarfChunks[i]);
236 #endif