Chromium Code Reviews| 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 |