]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - ftl/FTLUnwindInfo.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / ftl / FTLUnwindInfo.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3 * Copyright (C) 2014 Samsung Electronics
4 * Copyright (C) 2014 University of Szeged
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * ==============================================================================
28 *
29 * University of Illinois/NCSA
30 * Open Source License
31 *
32 * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
33 *
34 * All rights reserved.
35 *
36 * Developed by:
37 *
38 * LLVM Team
39 *
40 * University of Illinois at Urbana-Champaign
41 *
42 * http://llvm.org
43 *
44 * Permission is hereby granted, free of charge, to any person obtaining a copy of
45 * this software and associated documentation files (the "Software"), to deal with
46 * the Software without restriction, including without limitation the rights to
47 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
48 * of the Software, and to permit persons to whom the Software is furnished to do
49 * so, subject to the following conditions:
50 *
51 * * Redistributions of source code must retain the above copyright notice,
52 * this list of conditions and the following disclaimers.
53 *
54 * * Redistributions in binary form must reproduce the above copyright notice,
55 * this list of conditions and the following disclaimers in the
56 * documentation and/or other materials provided with the distribution.
57 *
58 * * Neither the names of the LLVM Team, University of Illinois at
59 * Urbana-Champaign, nor the names of its contributors may be used to
60 * endorse or promote products derived from this Software without specific
61 * prior written permission.
62 *
63 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
65 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66 * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
69 * SOFTWARE.
70 *
71 * ==============================================================================
72 *
73 * Copyright (c) 2009-2014 by the contributors of LLVM/libc++abi project.
74 *
75 * Permission is hereby granted, free of charge, to any person obtaining a copy
76 * of this software and associated documentation files (the "Software"), to deal
77 * in the Software without restriction, including without limitation the rights
78 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79 * copies of the Software, and to permit persons to whom the Software is
80 * furnished to do so, subject to the following conditions:
81 *
82 * The above copyright notice and this permission notice shall be included in
83 * all copies or substantial portions of the Software.
84 *
85 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
88 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91 * THE SOFTWARE.
92 */
93
94#include "config.h"
95#include "FTLUnwindInfo.h"
96
97#if ENABLE(FTL_JIT)
98
99#if OS(DARWIN)
100#include <mach-o/compact_unwind_encoding.h>
101#endif
102#include <wtf/ListDump.h>
103
104namespace JSC { namespace FTL {
105
106UnwindInfo::UnwindInfo() { }
107UnwindInfo::~UnwindInfo() { }
108
109
110namespace {
111#if OS(DARWIN)
112struct CompactUnwind {
113 void* function;
114 uint32_t size;
115 compact_unwind_encoding_t encoding;
116 void* personality;
117 void* lsda;
118};
119#elif OS(LINUX)
120// DWARF unwind instructions
121enum {
122 DW_CFA_nop = 0x0,
123 DW_CFA_set_loc = 0x1,
124 DW_CFA_advance_loc1 = 0x2,
125 DW_CFA_advance_loc2 = 0x3,
126 DW_CFA_advance_loc4 = 0x4,
127 DW_CFA_offset_extended = 0x5,
128 DW_CFA_def_cfa = 0xC,
129 DW_CFA_def_cfa_register = 0xD,
130 DW_CFA_def_cfa_offset = 0xE,
131 DW_CFA_offset_extended_sf = 0x11,
132 DW_CFA_def_cfa_sf = 0x12,
133 DW_CFA_def_cfa_offset_sf = 0x13,
134 // high 2 bits are 0x1, lower 6 bits are delta
135 DW_CFA_advance_loc = 0x40,
136 // high 2 bits are 0x2, lower 6 bits are register
137 DW_CFA_offset = 0x80
138};
139
140enum {
141 DW_CFA_operand_mask = 0x3F // low 6 bits mask for opcode-encoded operands in DW_CFA_advance_loc and DW_CFA_offset
142};
143
144// FSF exception handling Pointer-Encoding constants
145enum {
146 DW_EH_PE_ptr = 0x00,
147 DW_EH_PE_uleb128 = 0x01,
148 DW_EH_PE_udata2 = 0x02,
149 DW_EH_PE_udata4 = 0x03,
150 DW_EH_PE_udata8 = 0x04,
151 DW_EH_PE_sleb128 = 0x09,
152 DW_EH_PE_sdata2 = 0x0A,
153 DW_EH_PE_sdata4 = 0x0B,
154 DW_EH_PE_sdata8 = 0x0C,
155 DW_EH_PE_absptr = 0x00,
156 DW_EH_PE_pcrel = 0x10,
157 DW_EH_PE_indirect = 0x80
158};
159
160enum {
161 DW_EH_PE_relative_mask = 0x70
162};
163
164// 64-bit x86_64 registers
165enum {
166 UNW_X86_64_rbx = 3,
167 UNW_X86_64_rbp = 6,
168 UNW_X86_64_r12 = 12,
169 UNW_X86_64_r13 = 13,
170 UNW_X86_64_r14 = 14,
171 UNW_X86_64_r15 = 15
172};
173
174enum {
175 DW_X86_64_RET_addr = 16
176};
177
178enum {
179 UNW_ARM64_x0 = 0,
180 UNW_ARM64_x1 = 1,
181 UNW_ARM64_x2 = 2,
182 UNW_ARM64_x3 = 3,
183 UNW_ARM64_x4 = 4,
184 UNW_ARM64_x5 = 5,
185 UNW_ARM64_x6 = 6,
186 UNW_ARM64_x7 = 7,
187 UNW_ARM64_x8 = 8,
188 UNW_ARM64_x9 = 9,
189 UNW_ARM64_x10 = 10,
190 UNW_ARM64_x11 = 11,
191 UNW_ARM64_x12 = 12,
192 UNW_ARM64_x13 = 13,
193 UNW_ARM64_x14 = 14,
194 UNW_ARM64_x15 = 15,
195 UNW_ARM64_x16 = 16,
196 UNW_ARM64_x17 = 17,
197 UNW_ARM64_x18 = 18,
198 UNW_ARM64_x19 = 19,
199 UNW_ARM64_x20 = 20,
200 UNW_ARM64_x21 = 21,
201 UNW_ARM64_x22 = 22,
202 UNW_ARM64_x23 = 23,
203 UNW_ARM64_x24 = 24,
204 UNW_ARM64_x25 = 25,
205 UNW_ARM64_x26 = 26,
206 UNW_ARM64_x27 = 27,
207 UNW_ARM64_x28 = 28,
208 UNW_ARM64_fp = 29,
209 UNW_ARM64_x30 = 30,
210 UNW_ARM64_sp = 31,
211 UNW_ARM64_v0 = 64,
212 UNW_ARM64_v1 = 65,
213 UNW_ARM64_v2 = 66,
214 UNW_ARM64_v3 = 67,
215 UNW_ARM64_v4 = 68,
216 UNW_ARM64_v5 = 69,
217 UNW_ARM64_v6 = 70,
218 UNW_ARM64_v7 = 71,
219 UNW_ARM64_v8 = 72,
220 UNW_ARM64_v9 = 73,
221 UNW_ARM64_v10 = 74,
222 UNW_ARM64_v11 = 75,
223 UNW_ARM64_v12 = 76,
224 UNW_ARM64_v13 = 77,
225 UNW_ARM64_v14 = 78,
226 UNW_ARM64_v15 = 79,
227 UNW_ARM64_v16 = 80,
228 UNW_ARM64_v17 = 81,
229 UNW_ARM64_v18 = 82,
230 UNW_ARM64_v19 = 83,
231 UNW_ARM64_v20 = 84,
232 UNW_ARM64_v21 = 85,
233 UNW_ARM64_v22 = 86,
234 UNW_ARM64_v23 = 87,
235 UNW_ARM64_v24 = 88,
236 UNW_ARM64_v25 = 89,
237 UNW_ARM64_v26 = 90,
238 UNW_ARM64_v27 = 91,
239 UNW_ARM64_v28 = 92,
240 UNW_ARM64_v29 = 93,
241 UNW_ARM64_v30 = 94,
242 UNW_ARM64_v31 = 95
243};
244
245static uint8_t get8(uintptr_t addr) { return *((uint8_t*)addr); }
246static uint16_t get16(uintptr_t addr) { return *((uint16_t*)addr); }
247static uint32_t get32(uintptr_t addr) { return *((uint32_t*)addr); }
248static uint64_t get64(uintptr_t addr) { return *((uint64_t*)addr); }
249
250static uintptr_t getP(uintptr_t addr)
251{
252 // FIXME: add support for 32 bit pointers on 32 bit architectures
253 return get64(addr);
254}
255
256static uint64_t getULEB128(uintptr_t& addr, uintptr_t end)
257{
258 const uint8_t* p = (uint8_t*)addr;
259 const uint8_t* pend = (uint8_t*)end;
260 uint64_t result = 0;
261 int bit = 0;
262 do {
263 uint64_t b;
264
265 RELEASE_ASSERT(p != pend); // truncated uleb128 expression
266
267 b = *p & 0x7f;
268
269 RELEASE_ASSERT(!(bit >= 64 || b << bit >> bit != b)); // malformed uleb128 expression
270
271 result |= b << bit;
272 bit += 7;
273 } while (*p++ >= 0x80);
274 addr = (uintptr_t)p;
275 return result;
276}
277
278static int64_t getSLEB128(uintptr_t& addr, uintptr_t end)
279{
280 const uint8_t* p = (uint8_t*)addr;
281 const uint8_t* pend = (uint8_t*)end;
282
283 int64_t result = 0;
284 int bit = 0;
285 uint8_t byte;
286 do {
287 RELEASE_ASSERT(p != pend); // truncated sleb128 expression
288
289 byte = *p++;
290 result |= ((byte & 0x7f) << bit);
291 bit += 7;
292 } while (byte & 0x80);
293 // sign extend negative numbers
294 if ((byte & 0x40))
295 result |= (-1LL) << bit;
296 addr = (uintptr_t)p;
297 return result;
298}
299
300static uintptr_t getEncodedP(uintptr_t& addr, uintptr_t end, uint8_t encoding)
301{
302 uintptr_t startAddr = addr;
303 const uint8_t* p = (uint8_t*)addr;
304 uintptr_t result;
305
306 // first get value
307 switch (encoding & 0x0F) {
308 case DW_EH_PE_ptr:
309 result = getP(addr);
310 p += sizeof(uintptr_t);
311 addr = (uintptr_t)p;
312 break;
313 case DW_EH_PE_uleb128:
314 result = getULEB128(addr, end);
315 break;
316 case DW_EH_PE_udata2:
317 result = get16(addr);
318 p += 2;
319 addr = (uintptr_t)p;
320 break;
321 case DW_EH_PE_udata4:
322 result = get32(addr);
323 p += 4;
324 addr = (uintptr_t)p;
325 break;
326 case DW_EH_PE_udata8:
327 result = get64(addr);
328 p += 8;
329 addr = (uintptr_t)p;
330 break;
331 case DW_EH_PE_sleb128:
332 result = getSLEB128(addr, end);
333 break;
334 case DW_EH_PE_sdata2:
335 result = (int16_t)get16(addr);
336 p += 2;
337 addr = (uintptr_t)p;
338 break;
339 case DW_EH_PE_sdata4:
340 result = (int32_t)get32(addr);
341 p += 4;
342 addr = (uintptr_t)p;
343 break;
344 case DW_EH_PE_sdata8:
345 result = get64(addr);
346 p += 8;
347 addr = (uintptr_t)p;
348 break;
349 default:
350 RELEASE_ASSERT_NOT_REACHED(); // unknown pointer encoding
351 }
352
353 // then add relative offset
354 switch (encoding & DW_EH_PE_relative_mask) {
355 case DW_EH_PE_absptr:
356 // do nothing
357 break;
358 case DW_EH_PE_pcrel:
359 result += startAddr;
360 break;
361 default:
362 RELEASE_ASSERT_NOT_REACHED(); // unsupported or unknown pointer encoding
363 }
364
365 if (encoding & DW_EH_PE_indirect)
366 result = getP(result);
367
368 return result;
369}
370
371// Information encoded in a CIE (Common Information Entry)
372struct CIE_Info {
373 uintptr_t cieStart;
374 uintptr_t cieLength;
375 uintptr_t cieInstructions;
376 uint8_t pointerEncoding;
377 uint8_t lsdaEncoding;
378 uint8_t personalityEncoding;
379 uint8_t personalityOffsetInCIE;
380 uintptr_t personality;
381 int dataAlignFactor;
382 bool fdesHaveAugmentationData;
383};
384
385// Information about an FDE (Frame Description Entry)
386struct FDE_Info {
387 uintptr_t fdeStart;
388 uintptr_t fdeLength;
389 uintptr_t fdeInstructions;
390 uintptr_t lsda;
391};
392
393// Information about a frame layout and registers saved determined
394// by "running" the dwarf FDE "instructions"
395#if CPU(ARM64)
396enum { MaxRegisterNumber = 120 };
397#elif CPU(X86_64)
398enum { MaxRegisterNumber = 17 };
399#else
400#error "Unrecognized architecture"
401#endif
402
403struct RegisterLocation {
404 bool saved;
405 int64_t offset;
406};
407
408struct PrologInfo {
409 uint32_t cfaRegister;
410 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
411 RegisterLocation savedRegisters[MaxRegisterNumber]; // from where to restore registers
412};
413
414static void parseCIE(uintptr_t cie, CIE_Info* cieInfo)
415{
416 cieInfo->pointerEncoding = 0;
417 cieInfo->lsdaEncoding = 0;
418 cieInfo->personalityEncoding = 0;
419 cieInfo->personalityOffsetInCIE = 0;
420 cieInfo->personality = 0;
421 cieInfo->dataAlignFactor = 0;
422 cieInfo->fdesHaveAugmentationData = false;
423 cieInfo->cieStart = cie;
424
425 uintptr_t p = cie;
426 uint64_t cieLength = get32(p);
427 p += 4;
428 uintptr_t cieContentEnd = p + cieLength;
429 if (cieLength == 0xffffffff) {
430 // 0xffffffff means length is really next 8 bytes
431 cieLength = get64(p);
432 p += 8;
433 cieContentEnd = p + cieLength;
434 }
435
436 RELEASE_ASSERT(cieLength);
437
438 // CIE ID is always 0
439 RELEASE_ASSERT(!get32(p)); // CIE ID is not zero
440 p += 4;
441 // Version is always 1 or 3
442 uint8_t version = get8(p);
443 RELEASE_ASSERT((version == 1) || (version == 3)); // CIE version is not 1 or 3
444
445 ++p;
446 // save start of augmentation string and find end
447 uintptr_t strStart = p;
448 while (get8(p))
449 ++p;
450 ++p;
451 // parse code aligment factor
452 getULEB128(p, cieContentEnd);
453 // parse data alignment factor
454 cieInfo->dataAlignFactor = getSLEB128(p, cieContentEnd);
455 // parse return address register
456 getULEB128(p, cieContentEnd);
457 // parse augmentation data based on augmentation string
458 if (get8(strStart) == 'z') {
459 // parse augmentation data length
460 getULEB128(p, cieContentEnd);
461 for (uintptr_t s = strStart; get8(s) != '\0'; ++s) {
462 switch (get8(s)) {
463 case 'z':
464 cieInfo->fdesHaveAugmentationData = true;
465 break;
466 case 'P': // FIXME: should assert on personality (just to keep in sync with the CU behaviour)
467 cieInfo->personalityEncoding = get8(p);
468 ++p;
469 cieInfo->personalityOffsetInCIE = p - cie;
470 cieInfo->personality = getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
471 break;
472 case 'L': // FIXME: should assert on LSDA (just to keep in sync with the CU behaviour)
473 cieInfo->lsdaEncoding = get8(p);
474 ++p;
475 break;
476 case 'R':
477 cieInfo->pointerEncoding = get8(p);
478 ++p;
479 break;
480 default:
481 // ignore unknown letters
482 break;
483 }
484 }
485 }
486 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
487 cieInfo->cieInstructions = p;
488}
489
490static void findFDE(uintptr_t pc, uintptr_t ehSectionStart, uint32_t sectionLength, FDE_Info* fdeInfo, CIE_Info* cieInfo)
491{
492 uintptr_t p = ehSectionStart;
493 const uintptr_t ehSectionEnd = p + sectionLength;
494 while (p < ehSectionEnd) {
495 uintptr_t currentCFI = p;
496 uint64_t cfiLength = get32(p);
497 p += 4;
498 if (cfiLength == 0xffffffff) {
499 // 0xffffffff means length is really next 8 bytes
500 cfiLength = get64(p);
501 p += 8;
502 }
503 RELEASE_ASSERT(cfiLength); // end marker reached before finding FDE for pc
504
505 uint32_t id = get32(p);
506 if (!id) {
507 // skip over CIEs
508 p += cfiLength;
509 } else {
510 // process FDE to see if it covers pc
511 uintptr_t nextCFI = p + cfiLength;
512 uint32_t ciePointer = get32(p);
513 uintptr_t cieStart = p - ciePointer;
514 // validate pointer to CIE is within section
515 RELEASE_ASSERT((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)); // malformed FDE. CIE is bad
516
517 parseCIE(cieStart, cieInfo);
518
519 p += 4;
520 // parse pc begin and range
521 uintptr_t pcStart = getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
522 uintptr_t pcRange = getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
523
524 // test if pc is within the function this FDE covers
525 // if pc is not in begin/range, skip this FDE
526 if ((pcStart <= pc) && (pc < pcStart+pcRange)) {
527 // parse rest of info
528 fdeInfo->lsda = 0;
529 // check for augmentation length
530 if (cieInfo->fdesHaveAugmentationData) {
531 uintptr_t augLen = getULEB128(p, nextCFI);
532 uintptr_t endOfAug = p + augLen;
533 if (cieInfo->lsdaEncoding) {
534 // peek at value (without indirection). Zero means no lsda
535 uintptr_t lsdaStart = p;
536 if (getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F)) {
537 // reset pointer and re-parse lsda address
538 p = lsdaStart;
539 fdeInfo->lsda = getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
540 }
541 }
542 p = endOfAug;
543 }
544 fdeInfo->fdeStart = currentCFI;
545 fdeInfo->fdeLength = nextCFI - currentCFI;
546 fdeInfo->fdeInstructions = p;
547
548 return; // FDE found
549 }
550
551 p = nextCFI;
552 }
553 }
554
555 RELEASE_ASSERT_NOT_REACHED(); // no FDE found for pc
556}
557
558static void executeDefCFARegister(uint64_t reg, PrologInfo* results)
559{
560 RELEASE_ASSERT(reg <= MaxRegisterNumber); // reg too big
561 results->cfaRegister = reg;
562}
563
564static void executeDefCFAOffset(int64_t offset, PrologInfo* results)
565{
566 RELEASE_ASSERT(offset <= 0x80000000); // cfa has negative offset (dwarf might contain epilog)
567 results->cfaRegisterOffset = offset;
568}
569
570static void executeOffset(uint64_t reg, int64_t offset, PrologInfo *results)
571{
572 if (reg > MaxRegisterNumber)
573 return;
574
575 RELEASE_ASSERT(!results->savedRegisters[reg].saved);
576 results->savedRegisters[reg].saved = true;
577 results->savedRegisters[reg].offset = offset;
578}
579
580static void parseInstructions(uintptr_t instructions, uintptr_t instructionsEnd, const CIE_Info& cieInfo, PrologInfo* results)
581{
582 uintptr_t p = instructions;
583
584 // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
585 while ((p < instructionsEnd)) {
586 uint64_t reg;
587 uint8_t opcode = get8(p);
588 uint8_t operand;
589 ++p;
590 switch (opcode) {
591 case DW_CFA_nop:
592 break;
593 case DW_CFA_set_loc:
594 getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
595 break;
596 case DW_CFA_advance_loc1:
597 p += 1;
598 break;
599 case DW_CFA_advance_loc2:
600 p += 2;
601 break;
602 case DW_CFA_advance_loc4:
603 p += 4;
604 break;
605 case DW_CFA_def_cfa:
606 executeDefCFARegister(getULEB128(p, instructionsEnd), results);
607 executeDefCFAOffset(getULEB128(p, instructionsEnd), results);
608 break;
609 case DW_CFA_def_cfa_sf:
610 executeDefCFARegister(getULEB128(p, instructionsEnd), results);
611 executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
612 break;
613 case DW_CFA_def_cfa_register:
614 executeDefCFARegister(getULEB128(p, instructionsEnd), results);
615 break;
616 case DW_CFA_def_cfa_offset:
617 executeDefCFAOffset(getULEB128(p, instructionsEnd), results);
618 break;
619 case DW_CFA_def_cfa_offset_sf:
620 executeDefCFAOffset(getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
621 break;
622 case DW_CFA_offset_extended:
623 reg = getULEB128(p, instructionsEnd);
624 executeOffset(reg, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
625 break;
626 case DW_CFA_offset_extended_sf:
627 reg = getULEB128(p, instructionsEnd);
628 executeOffset(reg, getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
629 break;
630 default:
631 operand = opcode & DW_CFA_operand_mask;
632 switch (opcode & ~DW_CFA_operand_mask) {
633 case DW_CFA_offset:
634 executeOffset(operand, getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor, results);
635 break;
636 case DW_CFA_advance_loc:
637 break;
638 default:
639 RELEASE_ASSERT_NOT_REACHED(); // unknown or unsupported CFA opcode
640 }
641 }
642 }
643}
644
645static void parseFDEInstructions(const FDE_Info& fdeInfo, const CIE_Info& cieInfo, PrologInfo* results)
646{
647 // clear results
648 bzero(results, sizeof(PrologInfo));
649
650 // parse CIE then FDE instructions
651 parseInstructions(cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, cieInfo, results);
652 parseInstructions(fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, results);
653}
654#endif
655} // anonymous namespace
656
657bool UnwindInfo::parse(void* section, size_t size, GeneratedFunction generatedFunction)
658{
659 m_registers.clear();
660 RELEASE_ASSERT(!!section);
661 if (!section)
662 return false;
663
664#if OS(DARWIN)
665 RELEASE_ASSERT(size >= sizeof(CompactUnwind));
666
667 CompactUnwind* data = bitwise_cast<CompactUnwind*>(section);
668
669 RELEASE_ASSERT(!data->personality); // We don't know how to handle this.
670 RELEASE_ASSERT(!data->lsda); // We don't know how to handle this.
671 RELEASE_ASSERT(data->function == generatedFunction); // The unwind data better be for our function.
672
673 compact_unwind_encoding_t encoding = data->encoding;
674 RELEASE_ASSERT(!(encoding & UNWIND_IS_NOT_FUNCTION_START));
675 RELEASE_ASSERT(!(encoding & UNWIND_HAS_LSDA));
676 RELEASE_ASSERT(!(encoding & UNWIND_PERSONALITY_MASK));
677
678#if CPU(X86_64)
679 RELEASE_ASSERT((encoding & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_RBP_FRAME);
680
681 int32_t offset = -((encoding & UNWIND_X86_64_RBP_FRAME_OFFSET) >> 16) * 8;
682 uint32_t nextRegisters = encoding;
683 for (unsigned i = 5; i--;) {
684 uint32_t currentRegister = nextRegisters & 7;
685 nextRegisters >>= 3;
686
687 switch (currentRegister) {
688 case UNWIND_X86_64_REG_NONE:
689 break;
690
691 case UNWIND_X86_64_REG_RBX:
692 m_registers.append(RegisterAtOffset(X86Registers::ebx, offset));
693 break;
694
695 case UNWIND_X86_64_REG_R12:
696 m_registers.append(RegisterAtOffset(X86Registers::r12, offset));
697 break;
698
699 case UNWIND_X86_64_REG_R13:
700 m_registers.append(RegisterAtOffset(X86Registers::r13, offset));
701 break;
702
703 case UNWIND_X86_64_REG_R14:
704 m_registers.append(RegisterAtOffset(X86Registers::r14, offset));
705 break;
706
707 case UNWIND_X86_64_REG_R15:
708 m_registers.append(RegisterAtOffset(X86Registers::r15, offset));
709 break;
710
711 case UNWIND_X86_64_REG_RBP:
712 m_registers.append(RegisterAtOffset(X86Registers::ebp, offset));
713 break;
714
715 default:
716 RELEASE_ASSERT_NOT_REACHED();
717 }
718
719 offset += 8;
720 }
721#elif CPU(ARM64)
722 RELEASE_ASSERT((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME);
723
724 m_registers.append(RegisterAtOffset(ARM64Registers::fp, 0));
725
726 int32_t offset = 0;
727 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
728 m_registers.append(RegisterAtOffset(ARM64Registers::x19, offset -= 8));
729 m_registers.append(RegisterAtOffset(ARM64Registers::x20, offset -= 8));
730 }
731 if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
732 m_registers.append(RegisterAtOffset(ARM64Registers::x21, offset -= 8));
733 m_registers.append(RegisterAtOffset(ARM64Registers::x22, offset -= 8));
734 }
735 if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
736 m_registers.append(RegisterAtOffset(ARM64Registers::x23, offset -= 8));
737 m_registers.append(RegisterAtOffset(ARM64Registers::x24, offset -= 8));
738 }
739 if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
740 m_registers.append(RegisterAtOffset(ARM64Registers::x25, offset -= 8));
741 m_registers.append(RegisterAtOffset(ARM64Registers::x26, offset -= 8));
742 }
743 if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
744 m_registers.append(RegisterAtOffset(ARM64Registers::x27, offset -= 8));
745 m_registers.append(RegisterAtOffset(ARM64Registers::x28, offset -= 8));
746 }
747 if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
748 m_registers.append(RegisterAtOffset(ARM64Registers::q8, offset -= 8));
749 m_registers.append(RegisterAtOffset(ARM64Registers::q9, offset -= 8));
750 }
751 if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
752 m_registers.append(RegisterAtOffset(ARM64Registers::q10, offset -= 8));
753 m_registers.append(RegisterAtOffset(ARM64Registers::q11, offset -= 8));
754 }
755 if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
756 m_registers.append(RegisterAtOffset(ARM64Registers::q12, offset -= 8));
757 m_registers.append(RegisterAtOffset(ARM64Registers::q13, offset -= 8));
758 }
759 if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
760 m_registers.append(RegisterAtOffset(ARM64Registers::q14, offset -= 8));
761 m_registers.append(RegisterAtOffset(ARM64Registers::q15, offset -= 8));
762 }
763#else
764#error "Unrecognized architecture"
765#endif
766
767#elif OS(LINUX)
768 FDE_Info fdeInfo;
769 CIE_Info cieInfo;
770 PrologInfo prolog;
771
772 findFDE((uintptr_t)generatedFunction, (uintptr_t)section, size, &fdeInfo, &cieInfo);
773 parseFDEInstructions(fdeInfo, cieInfo, &prolog);
774
775#if CPU(X86_64)
776 RELEASE_ASSERT(prolog.cfaRegister == UNW_X86_64_rbp);
777 RELEASE_ASSERT(prolog.cfaRegisterOffset == 16);
778 RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].saved);
779 RELEASE_ASSERT(prolog.savedRegisters[UNW_X86_64_rbp].offset == -prolog.cfaRegisterOffset);
780
781 for (int i = 0; i < MaxRegisterNumber; ++i) {
782 if (prolog.savedRegisters[i].saved) {
783 switch (i) {
784 case UNW_X86_64_rbx:
785 m_registers.append(RegisterAtOffset(X86Registers::ebx, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
786 break;
787 case UNW_X86_64_r12:
788 m_registers.append(RegisterAtOffset(X86Registers::r12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
789 break;
790 case UNW_X86_64_r13:
791 m_registers.append(RegisterAtOffset(X86Registers::r13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
792 break;
793 case UNW_X86_64_r14:
794 m_registers.append(RegisterAtOffset(X86Registers::r14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
795 break;
796 case UNW_X86_64_r15:
797 m_registers.append(RegisterAtOffset(X86Registers::r15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
798 break;
799 case UNW_X86_64_rbp:
800 m_registers.append(RegisterAtOffset(X86Registers::ebp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
801 break;
802 case DW_X86_64_RET_addr:
803 break;
804 default:
805 RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog
806 }
807 }
808 }
809#elif CPU(ARM64)
810 RELEASE_ASSERT(prolog.cfaRegister == UNW_ARM64_fp);
811 RELEASE_ASSERT(prolog.cfaRegisterOffset == 16);
812 RELEASE_ASSERT(prolog.savedRegisters[UNW_ARM64_fp].saved);
813 RELEASE_ASSERT(prolog.savedRegisters[UNW_ARM64_fp].offset == -prolog.cfaRegisterOffset);
814
815 for (int i = 0; i < MaxRegisterNumber; ++i) {
816 if (prolog.savedRegisters[i].saved) {
817 switch (i) {
818 case UNW_ARM64_x0:
819 m_registers.append(RegisterAtOffset(ARM64Registers::x0, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
820 break;
821 case UNW_ARM64_x1:
822 m_registers.append(RegisterAtOffset(ARM64Registers::x1, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
823 break;
824 case UNW_ARM64_x2:
825 m_registers.append(RegisterAtOffset(ARM64Registers::x2, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
826 break;
827 case UNW_ARM64_x3:
828 m_registers.append(RegisterAtOffset(ARM64Registers::x3, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
829 break;
830 case UNW_ARM64_x4:
831 m_registers.append(RegisterAtOffset(ARM64Registers::x4, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
832 break;
833 case UNW_ARM64_x5:
834 m_registers.append(RegisterAtOffset(ARM64Registers::x5, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
835 break;
836 case UNW_ARM64_x6:
837 m_registers.append(RegisterAtOffset(ARM64Registers::x6, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
838 break;
839 case UNW_ARM64_x7:
840 m_registers.append(RegisterAtOffset(ARM64Registers::x7, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
841 break;
842 case UNW_ARM64_x8:
843 m_registers.append(RegisterAtOffset(ARM64Registers::x8, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
844 break;
845 case UNW_ARM64_x9:
846 m_registers.append(RegisterAtOffset(ARM64Registers::x9, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
847 break;
848 case UNW_ARM64_x10:
849 m_registers.append(RegisterAtOffset(ARM64Registers::x10, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
850 break;
851 case UNW_ARM64_x11:
852 m_registers.append(RegisterAtOffset(ARM64Registers::x11, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
853 break;
854 case UNW_ARM64_x12:
855 m_registers.append(RegisterAtOffset(ARM64Registers::x12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
856 break;
857 case UNW_ARM64_x13:
858 m_registers.append(RegisterAtOffset(ARM64Registers::x13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
859 break;
860 case UNW_ARM64_x14:
861 m_registers.append(RegisterAtOffset(ARM64Registers::x14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
862 break;
863 case UNW_ARM64_x15:
864 m_registers.append(RegisterAtOffset(ARM64Registers::x15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
865 break;
866 case UNW_ARM64_x16:
867 m_registers.append(RegisterAtOffset(ARM64Registers::x16, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
868 break;
869 case UNW_ARM64_x17:
870 m_registers.append(RegisterAtOffset(ARM64Registers::x17, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
871 break;
872 case UNW_ARM64_x18:
873 m_registers.append(RegisterAtOffset(ARM64Registers::x18, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
874 break;
875 case UNW_ARM64_x19:
876 m_registers.append(RegisterAtOffset(ARM64Registers::x19, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
877 break;
878 case UNW_ARM64_x20:
879 m_registers.append(RegisterAtOffset(ARM64Registers::x20, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
880 break;
881 case UNW_ARM64_x21:
882 m_registers.append(RegisterAtOffset(ARM64Registers::x21, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
883 break;
884 case UNW_ARM64_x22:
885 m_registers.append(RegisterAtOffset(ARM64Registers::x22, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
886 break;
887 case UNW_ARM64_x23:
888 m_registers.append(RegisterAtOffset(ARM64Registers::x23, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
889 break;
890 case UNW_ARM64_x24:
891 m_registers.append(RegisterAtOffset(ARM64Registers::x24, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
892 break;
893 case UNW_ARM64_x25:
894 m_registers.append(RegisterAtOffset(ARM64Registers::x25, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
895 break;
896 case UNW_ARM64_x26:
897 m_registers.append(RegisterAtOffset(ARM64Registers::x26, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
898 break;
899 case UNW_ARM64_x27:
900 m_registers.append(RegisterAtOffset(ARM64Registers::x27, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
901 break;
902 case UNW_ARM64_x28:
903 m_registers.append(RegisterAtOffset(ARM64Registers::x28, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
904 break;
905 case UNW_ARM64_fp:
906 m_registers.append(RegisterAtOffset(ARM64Registers::fp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
907 break;
908 case UNW_ARM64_x30:
909 m_registers.append(RegisterAtOffset(ARM64Registers::x30, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
910 break;
911 case UNW_ARM64_sp:
912 m_registers.append(RegisterAtOffset(ARM64Registers::sp, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
913 break;
914 case UNW_ARM64_v0:
915 m_registers.append(RegisterAtOffset(ARM64Registers::q0, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
916 break;
917 case UNW_ARM64_v1:
918 m_registers.append(RegisterAtOffset(ARM64Registers::q1, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
919 break;
920 case UNW_ARM64_v2:
921 m_registers.append(RegisterAtOffset(ARM64Registers::q2, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
922 break;
923 case UNW_ARM64_v3:
924 m_registers.append(RegisterAtOffset(ARM64Registers::q3, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
925 break;
926 case UNW_ARM64_v4:
927 m_registers.append(RegisterAtOffset(ARM64Registers::q4, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
928 break;
929 case UNW_ARM64_v5:
930 m_registers.append(RegisterAtOffset(ARM64Registers::q5, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
931 break;
932 case UNW_ARM64_v6:
933 m_registers.append(RegisterAtOffset(ARM64Registers::q6, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
934 break;
935 case UNW_ARM64_v7:
936 m_registers.append(RegisterAtOffset(ARM64Registers::q7, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
937 break;
938 case UNW_ARM64_v8:
939 m_registers.append(RegisterAtOffset(ARM64Registers::q8, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
940 break;
941 case UNW_ARM64_v9:
942 m_registers.append(RegisterAtOffset(ARM64Registers::q9, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
943 break;
944 case UNW_ARM64_v10:
945 m_registers.append(RegisterAtOffset(ARM64Registers::q10, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
946 break;
947 case UNW_ARM64_v11:
948 m_registers.append(RegisterAtOffset(ARM64Registers::q11, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
949 break;
950 case UNW_ARM64_v12:
951 m_registers.append(RegisterAtOffset(ARM64Registers::q12, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
952 break;
953 case UNW_ARM64_v13:
954 m_registers.append(RegisterAtOffset(ARM64Registers::q13, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
955 break;
956 case UNW_ARM64_v14:
957 m_registers.append(RegisterAtOffset(ARM64Registers::q14, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
958 break;
959 case UNW_ARM64_v15:
960 m_registers.append(RegisterAtOffset(ARM64Registers::q15, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
961 break;
962 case UNW_ARM64_v16:
963 m_registers.append(RegisterAtOffset(ARM64Registers::q16, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
964 break;
965 case UNW_ARM64_v17:
966 m_registers.append(RegisterAtOffset(ARM64Registers::q17, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
967 break;
968 case UNW_ARM64_v18:
969 m_registers.append(RegisterAtOffset(ARM64Registers::q18, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
970 break;
971 case UNW_ARM64_v19:
972 m_registers.append(RegisterAtOffset(ARM64Registers::q19, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
973 break;
974 case UNW_ARM64_v20:
975 m_registers.append(RegisterAtOffset(ARM64Registers::q20, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
976 break;
977 case UNW_ARM64_v21:
978 m_registers.append(RegisterAtOffset(ARM64Registers::q21, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
979 break;
980 case UNW_ARM64_v22:
981 m_registers.append(RegisterAtOffset(ARM64Registers::q22, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
982 break;
983 case UNW_ARM64_v23:
984 m_registers.append(RegisterAtOffset(ARM64Registers::q23, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
985 break;
986 case UNW_ARM64_v24:
987 m_registers.append(RegisterAtOffset(ARM64Registers::q24, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
988 break;
989 case UNW_ARM64_v25:
990 m_registers.append(RegisterAtOffset(ARM64Registers::q25, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
991 break;
992 case UNW_ARM64_v26:
993 m_registers.append(RegisterAtOffset(ARM64Registers::q26, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
994 break;
995 case UNW_ARM64_v27:
996 m_registers.append(RegisterAtOffset(ARM64Registers::q27, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
997 break;
998 case UNW_ARM64_v28:
999 m_registers.append(RegisterAtOffset(ARM64Registers::q28, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
1000 break;
1001 case UNW_ARM64_v29:
1002 m_registers.append(RegisterAtOffset(ARM64Registers::q29, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
1003 break;
1004 case UNW_ARM64_v30:
1005 m_registers.append(RegisterAtOffset(ARM64Registers::q30, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
1006 break;
1007 case UNW_ARM64_v31:
1008 m_registers.append(RegisterAtOffset(ARM64Registers::q31, prolog.savedRegisters[i].offset + prolog.cfaRegisterOffset));
1009 break;
1010 default:
1011 RELEASE_ASSERT_NOT_REACHED(); // non-standard register being saved in prolog
1012 }
1013 }
1014 }
1015#else
1016#error "Unrecognized architecture"
1017#endif
1018
1019#endif
1020 std::sort(m_registers.begin(), m_registers.end());
1021 return true;
1022}
1023
1024void UnwindInfo::dump(PrintStream& out) const
1025{
1026 out.print(listDump(m_registers));
1027}
1028
1029RegisterAtOffset* UnwindInfo::find(Reg reg) const
1030{
1031 return tryBinarySearch<RegisterAtOffset, Reg>(m_registers, m_registers.size(), reg, RegisterAtOffset::getReg);
1032}
1033
1034unsigned UnwindInfo::indexOf(Reg reg) const
1035{
1036 if (RegisterAtOffset* pointer = find(reg))
1037 return pointer - m_registers.begin();
1038 return UINT_MAX;
1039}
1040
1041} } // namespace JSC::FTL
1042
1043#endif // ENABLE(FTL_JIT)
1044