OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 TYPE_STRTAB = 3, | 194 TYPE_STRTAB = 3, |
195 TYPE_RELA = 4, | 195 TYPE_RELA = 4, |
196 TYPE_HASH = 5, | 196 TYPE_HASH = 5, |
197 TYPE_DYNAMIC = 6, | 197 TYPE_DYNAMIC = 6, |
198 TYPE_NOTE = 7, | 198 TYPE_NOTE = 7, |
199 TYPE_NOBITS = 8, | 199 TYPE_NOBITS = 8, |
200 TYPE_REL = 9, | 200 TYPE_REL = 9, |
201 TYPE_SHLIB = 10, | 201 TYPE_SHLIB = 10, |
202 TYPE_DYNSYM = 11, | 202 TYPE_DYNSYM = 11, |
203 TYPE_LOPROC = 0x70000000, | 203 TYPE_LOPROC = 0x70000000, |
204 TYPE_X86_64_UNWIND = 0x70000001, | |
204 TYPE_HIPROC = 0x7fffffff, | 205 TYPE_HIPROC = 0x7fffffff, |
205 TYPE_LOUSER = 0x80000000, | 206 TYPE_LOUSER = 0x80000000, |
206 TYPE_HIUSER = 0xffffffff | 207 TYPE_HIUSER = 0xffffffff |
207 }; | 208 }; |
208 | 209 |
209 enum Flags { | 210 enum Flags { |
210 FLAG_WRITE = 1, | 211 FLAG_WRITE = 1, |
211 FLAG_ALLOC = 2, | 212 FLAG_ALLOC = 2, |
212 FLAG_EXEC = 4 | 213 FLAG_EXEC = 4 |
213 }; | 214 }; |
(...skipping 945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1159 | 1160 |
1160 void GDBJITInterface::RegisterDetailedLineInfo(Code* code, | 1161 void GDBJITInterface::RegisterDetailedLineInfo(Code* code, |
1161 GDBJITLineInfo* line_info) { | 1162 GDBJITLineInfo* line_info) { |
1162 ASSERT(!IsLineInfoTagged(line_info)); | 1163 ASSERT(!IsLineInfoTagged(line_info)); |
1163 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); | 1164 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true); |
1164 ASSERT(e->value == NULL); | 1165 ASSERT(e->value == NULL); |
1165 e->value = TagLineInfo(line_info); | 1166 e->value = TagLineInfo(line_info); |
1166 } | 1167 } |
1167 | 1168 |
1168 | 1169 |
1170 #ifdef V8_TARGET_ARCH_X64 | |
1171 | |
1172 | |
1173 class UnwindInfoSection : public ELFSection { | |
1174 public: | |
1175 explicit UnwindInfoSection(UnwindInfoInterface::UnwindInformation *); | |
1176 explicit UnwindInfoSection(uintptr_t begin, uintptr_t end); | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
2 argument constructors don't need explicit.
| |
1177 virtual bool WriteBody(Writer *w); | |
1178 | |
1179 private: | |
1180 UnwindInfoInterface::UnwindInformation *info_; | |
1181 uintptr_t begin_, length_; | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
uintptr_t begin_;
uintptr_t length_;
| |
1182 bool is_code_stub_; | |
1183 | |
1184 // DWARF3 Specification, Table 7.23 | |
1185 enum CFIInstructions { | |
1186 DW_CFA_ADVANCE_LOC = 0X40, | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
style nit: 0X -> 0x
| |
1187 DW_CFA_OFFSET = 0X80, | |
1188 DW_CFA_RESTORE = 0XC0, | |
1189 DW_CFA_NOP = 0X00, | |
1190 DW_CFA_SET_LOC = 0X01, | |
1191 DW_CFA_ADVANCE_LOC1 = 0X02, | |
1192 DW_CFA_ADVANCE_LOC2 = 0X03, | |
1193 DW_CFA_ADVANCE_LOC4 = 0X04, | |
1194 DW_CFA_OFFSET_EXTENDED = 0X05, | |
1195 DW_CFA_RESTORE_EXTENDED = 0X06, | |
1196 DW_CFA_UNDEFINED = 0X07, | |
1197 DW_CFA_SAME_VALUE = 0X08, | |
1198 DW_CFA_REGISTER = 0X09, | |
1199 DW_CFA_REMEMBER_STATE = 0X0A, | |
1200 DW_CFA_RESTORE_STATE = 0X0B, | |
1201 DW_CFA_DEF_CFA = 0X0C, | |
1202 DW_CFA_DEF_CFA_REGISTER = 0X0D, | |
1203 DW_CFA_DEF_CFA_OFFSET = 0X0E, | |
1204 | |
1205 DW_CFA_DEF_CFA_EXPRESSION = 0X0F, | |
1206 DW_CFA_EXPRESSION = 0X10, | |
1207 DW_CFA_OFFSET_EXTENDED_SF = 0X11, | |
1208 DW_CFA_DEF_CFA_SF = 0X12, | |
1209 DW_CFA_DEF_CFA_OFFSET_SF = 0X13, | |
1210 DW_CFA_VAL_OFFSET = 0X14, | |
1211 DW_CFA_VAL_OFFSET_SF = 0X15, | |
1212 DW_CFA_VAL_EXPRESSION = 0X16 | |
1213 }; | |
1214 | |
1215 // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36 | |
1216 enum RegisterMapping { | |
1217 // Only the relevant ones have been added to reduce clutter. | |
1218 AMD64_RBP = 6, | |
1219 AMD64_RSP = 7, | |
1220 AMD64_RA = 16 | |
1221 }; | |
1222 | |
1223 enum CFIConstants { | |
1224 CIE_ID = 0, | |
1225 CIE_VERSION = 1, | |
1226 CODE_ALIGN_FACTOR = 1, | |
1227 DATA_ALIGN_FACTOR = 1, | |
1228 RETURN_ADDRESS_REGISTER = AMD64_RA | |
1229 }; | |
1230 }; | |
1231 | |
1232 | |
1233 UnwindInfoSection::UnwindInfoSection(UnwindInfoInterface::UnwindInformation | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
I think the right way to format this will be
Unw
| |
1234 *info) | |
1235 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), info_(info), | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
either all on a single line or each initializer on
| |
1236 is_code_stub_(false) { } | |
1237 | |
1238 | |
1239 UnwindInfoSection::UnwindInfoSection(uintptr_t begin, uintptr_t length) | |
1240 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), begin_(begin), | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
ditto
| |
1241 length_(length), is_code_stub_(true) { } | |
1242 | |
1243 | |
1244 bool UnwindInfoSection::WriteBody(Writer *w) { | |
1245 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); | |
1246 uint32_t cie_position = w->position(), align; | |
1247 | |
1248 // Write out the CIE header. Currently no 'common instructions' are | |
1249 // emitted onto the CIE; every FDE has its own set of instructions. | |
1250 | |
1251 w->Write<uint32_t>(CIE_ID); | |
1252 w->Write<uint8_t>(CIE_VERSION); | |
1253 w->Write<uint8_t>(0); // Augmentation string. | |
1254 w->WriteSLEB128(CODE_ALIGN_FACTOR); | |
1255 w->WriteSLEB128(DATA_ALIGN_FACTOR); | |
1256 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER); | |
1257 | |
1258 align = (w->position() - cie_position) % kPointerSize; | |
1259 if (align) { | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
We don't rely on implicit int->bool convertions, s
| |
1260 for (uint32_t i = 0; i < (kPointerSize - align); i++) { | |
1261 w->Write<uint8_t>(DW_CFA_NOP); | |
1262 } | |
1263 } | |
1264 ASSERT((w->position() - cie_position) % kPointerSize == 0); | |
1265 cie_length_slot.set(w->position() - cie_position); | |
1266 | |
1267 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>(); | |
1268 int fde_position = w->position(); | |
1269 w->Write<int32_t>(fde_position - cie_position + 4); // Pointer to CIE | |
1270 | |
1271 // The (only) FDE for this function | |
1272 | |
1273 if (!is_code_stub_) { | |
1274 w->Write<uintptr_t>(info_->begin_); | |
1275 w->Write<uintptr_t> | |
1276 (info_->state_offsets_[UnwindInfoInterface::UNWIND_STATE_AFTER_RETURN]); | |
1277 | |
1278 // The CFA is the frame-pointer of the current function. This seemed the | |
1279 // most straightforward since (it seems) both the full-codegen and the | |
1280 // classic codegen maintain the frame-pointer. | |
1281 | |
1282 // -- The first state, just after the control has been transferred to the | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
Can you split this into four different functions f
| |
1283 // -- the function. | |
1284 | |
1285 // RBP for this function will be the value of RSP after pushing the RBP | |
1286 // for the previous function. The previous RBP has not been pushed yet. | |
1287 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF); | |
1288 w->WriteULEB128(AMD64_RSP); | |
1289 w->WriteSLEB128(-kPointerSize); | |
1290 | |
1291 // The RA is stored at location CFA + kCallerPCOffset. This is an invariant, | |
1292 // and hence omitted from the next states. | |
1293 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1294 w->WriteULEB128(AMD64_RA); | |
1295 w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset); | |
1296 | |
1297 // The RBP of the previous function is still in RBP. | |
1298 w->Write<uint8_t>(DW_CFA_SAME_VALUE); | |
1299 w->WriteULEB128(AMD64_RBP); | |
1300 | |
1301 // Last location described by this entry. | |
1302 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1303 w->Write<uint64_t> | |
1304 (info_->begin_ + info_->state_offsets_ | |
1305 [UnwindInfoInterface::UNWIND_STATE_AFTER_RBP_PUSH]); | |
1306 | |
1307 // -- The second state, just after RBP has been pushed. | |
1308 | |
1309 // RBP / CFA for this function is now the current RSP, so just set the | |
1310 // offset from the previous rule (from -8) to 0. | |
1311 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET); | |
1312 w->WriteULEB128(0); | |
1313 | |
1314 // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant | |
1315 // in this and the next state, and hence omitted in the next state. | |
1316 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1317 w->WriteULEB128(AMD64_RBP); | |
1318 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset); | |
1319 | |
1320 // Last location described by this entry. | |
1321 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1322 w->Write<uint64_t> | |
1323 (info_->begin_ + info_->state_offsets_ | |
1324 [UnwindInfoInterface::UNWIND_STATE_AFTER_RBP_SET]); | |
1325 | |
1326 // -- The third state, after the RBP has been set. | |
1327 | |
1328 // The CFA can now directly be set to RBP. | |
1329 w->Write<uint8_t>(DW_CFA_DEF_CFA); | |
1330 w->WriteULEB128(AMD64_RBP); | |
1331 w->WriteULEB128(0); | |
1332 | |
1333 // Last location described by this entry. | |
1334 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1335 w->Write<uint64_t> | |
1336 (info_->begin_ + info_->state_offsets_ | |
1337 [UnwindInfoInterface::UNWIND_STATE_AFTER_RBP_POP]); | |
1338 | |
1339 // -- The fourth (final) state. The RBP has been popped (just before issuing | |
1340 // a return. | |
1341 | |
1342 // The CFA can is now calculated in the same way as in the first state. | |
1343 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF); | |
1344 w->WriteULEB128(AMD64_RSP); | |
1345 w->WriteSLEB128(-kPointerSize); | |
1346 | |
1347 // The RBP | |
1348 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1349 w->WriteULEB128(AMD64_RBP); | |
1350 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset); | |
1351 | |
1352 // Last location described by this entry. | |
1353 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1354 w->Write<uint64_t> | |
1355 (info_->begin_ + | |
1356 info_->state_offsets_[UnwindInfoInterface::UNWIND_STATE_AFTER_RETURN]); | |
1357 } else { | |
1358 // This is a code-stub. Unwind information for code-stubs is not divided | |
1359 // into stages, we just tell GDB to unwind using the frame pointer. | |
1360 w->Write<uintptr_t>(begin_); | |
1361 w->Write<uintptr_t>(length_); | |
1362 | |
1363 // The CFA is the current function's RBP | |
1364 w->Write<uint8_t>(DW_CFA_DEF_CFA); | |
1365 w->WriteULEB128(AMD64_RBP); | |
1366 w->WriteULEB128(0); | |
1367 | |
1368 // These assumptions are not true at the code-stub entry and exit. However, | |
1369 // we are assuming that the debugger will halt code-stubs only at their | |
1370 // call sites. | |
1371 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1372 w->WriteULEB128(AMD64_RA); | |
1373 w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset); | |
1374 | |
1375 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED); | |
1376 w->WriteULEB128(AMD64_RBP); | |
1377 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset); | |
1378 | |
1379 // The last location described by this entry. | |
1380 w->Write<uint8_t>(DW_CFA_SET_LOC); | |
1381 w->Write<uint64_t>(begin_ + length_); | |
1382 } | |
1383 | |
1384 if ((align = (w->position() - fde_position) % kPointerSize)) { | |
Vyacheslav Egorov (Chromium)
2011/01/25 12:50:11
I think we usually avoid assignments in expression
| |
1385 for (uint32_t i = 0; i < (kPointerSize - align); i++) | |
1386 w->Write<uint8_t>(DW_CFA_NOP); | |
1387 } | |
1388 | |
1389 ASSERT((w->position() - fde_position) % kPointerSize == 0); | |
1390 fde_length_slot.set(w->position() - fde_position); | |
1391 | |
1392 return true; | |
1393 } | |
1394 | |
1395 | |
1396 UnwindInfoInterface::UnwindInformationList *UnwindInfoInterface::info_ = NULL; | |
1397 | |
1398 | |
1399 static void SaveUnwindInfo(UnwindInfoSection *section) { | |
1400 ELF elf; | |
1401 elf.AddSection(section); | |
1402 Writer w(&elf); | |
1403 elf.Write(&w); | |
1404 JITCodeEntry *entry = CreateCodeEntry(w.buffer(), w.position()); | |
1405 RegisterCodeEntry(entry); | |
1406 } | |
1407 | |
1408 | |
1409 UnwindInfoInterface::~UnwindInfoInterface() { | |
1410 ASSERT(info_ != NULL); | |
1411 | |
1412 UnwindInfoSection unwind_section(&info_->data_); | |
1413 SaveUnwindInfo(&unwind_section); | |
1414 UnwindInformationList *tmp = info_->next_; | |
1415 delete info_; | |
1416 info_ = tmp; | |
1417 } | |
1418 | |
1419 | |
1420 void UnwindInfoInterface::SetCodeStub(uintptr_t b, uintptr_t l) { | |
1421 UnwindInfoSection unwind_section(b, l); | |
1422 SaveUnwindInfo(&unwind_section); | |
1423 } | |
1424 | |
1425 | |
1426 #endif // V8_TARGET_ARCH_X64 | |
1427 | |
1428 | |
1169 } } // namespace v8::internal | 1429 } } // namespace v8::internal |
1170 #endif | 1430 #endif |
OLD | NEW |