Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: third_party/libc++abi/src/Unwind/DwarfParser.hpp

Issue 75213003: Add libc++ and libc++abi to third-party. (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===--------------------------- DwarfParser.hpp --------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //
9 // Parses DWARF CFIs (FDEs and CIEs).
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef __DWARF_PARSER_HPP__
14 #define __DWARF_PARSER_HPP__
15
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include <vector>
21
22 #include "libunwind.h"
23 #include "dwarf2.h"
24
25 #include "AddressSpace.hpp"
26
27 namespace libunwind {
28
29 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
30 /// See Dwarf Spec for details:
31 /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic /ehframechpt.html
32 ///
33 template <typename A>
34 class CFI_Parser {
35 public:
36 typedef typename A::pint_t pint_t;
37
38 /// Information encoded in a CIE (Common Information Entry)
39 struct CIE_Info {
40 pint_t cieStart;
41 pint_t cieLength;
42 pint_t cieInstructions;
43 uint8_t pointerEncoding;
44 uint8_t lsdaEncoding;
45 uint8_t personalityEncoding;
46 uint8_t personalityOffsetInCIE;
47 pint_t personality;
48 uint32_t codeAlignFactor;
49 int dataAlignFactor;
50 bool isSignalFrame;
51 bool fdesHaveAugmentationData;
52 };
53
54 /// Information about an FDE (Frame Description Entry)
55 struct FDE_Info {
56 pint_t fdeStart;
57 pint_t fdeLength;
58 pint_t fdeInstructions;
59 pint_t pcStart;
60 pint_t pcEnd;
61 pint_t lsda;
62 };
63
64 enum {
65 kMaxRegisterNumber = 120
66 };
67 enum RegisterSavedWhere {
68 kRegisterUnused,
69 kRegisterInCFA,
70 kRegisterOffsetFromCFA,
71 kRegisterInRegister,
72 kRegisterAtExpression,
73 kRegisterIsExpression
74 };
75 struct RegisterLocation {
76 RegisterSavedWhere location;
77 int64_t value;
78 };
79 /// Information about a frame layout and registers saved determined
80 /// by "running" the dwarf FDE "instructions"
81 struct PrologInfo {
82 uint32_t cfaRegister;
83 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffs et
84 int64_t cfaExpression; // CFA = expression
85 uint32_t spExtraArgSize;
86 uint32_t codeOffsetAtStackDecrement;
87 bool registersInOtherRegisters;
88 bool sameValueUsed;
89 RegisterLocation savedRegisters[kMaxRegisterNumber];
90 };
91
92 struct PrologInfoStackEntry {
93 PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
94 : next(n), info(i) {}
95 PrologInfoStackEntry *next;
96 PrologInfo info;
97 };
98
99 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
100 uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
101 CIE_Info *cieInfo);
102 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
103 FDE_Info *fdeInfo, CIE_Info *cieInfo);
104 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
105 const CIE_Info &cieInfo, pint_t upToPC,
106 PrologInfo *results);
107
108 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
109
110 private:
111 static bool parseInstructions(A &addressSpace, pint_t instructions,
112 pint_t instructionsEnd, const CIE_Info &cieInfo,
113 pint_t pcoffset,
114 PrologInfoStackEntry *&rememberStack,
115 PrologInfo *results);
116 };
117
118 /// Parse a FDE into a CIE_Info and an FDE_Info
119 template <typename A>
120 const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
121 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
122 pint_t p = fdeStart;
123 pint_t cfiLength = (pint_t)addressSpace.get32(p);
124 p += 4;
125 if (cfiLength == 0xffffffff) {
126 // 0xffffffff means length is really next 8 bytes
127 cfiLength = (pint_t)addressSpace.get64(p);
128 p += 8;
129 }
130 if (cfiLength == 0)
131 return "FDE has zero length"; // end marker
132 uint32_t ciePointer = addressSpace.get32(p);
133 if (ciePointer == 0)
134 return "FDE is really a CIE"; // this is a CIE not an FDE
135 pint_t nextCFI = p + cfiLength;
136 pint_t cieStart = p - ciePointer;
137 const char *err = parseCIE(addressSpace, cieStart, cieInfo);
138 if (err != NULL)
139 return err;
140 p += 4;
141 // parse pc begin and range
142 pint_t pcStart =
143 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
144 pint_t pcRange =
145 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
146 // parse rest of info
147 fdeInfo->lsda = 0;
148 // check for augmentation length
149 if (cieInfo->fdesHaveAugmentationData) {
150 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
151 pint_t endOfAug = p + augLen;
152 if (cieInfo->lsdaEncoding != 0) {
153 // peek at value (without indirection). Zero means no lsda
154 pint_t lsdaStart = p;
155 if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
156 0) {
157 // reset pointer and re-parse lsda address
158 p = lsdaStart;
159 fdeInfo->lsda =
160 addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
161 }
162 }
163 p = endOfAug;
164 }
165 fdeInfo->fdeStart = fdeStart;
166 fdeInfo->fdeLength = nextCFI - fdeStart;
167 fdeInfo->fdeInstructions = p;
168 fdeInfo->pcStart = pcStart;
169 fdeInfo->pcEnd = pcStart + pcRange;
170 return NULL; // success
171 }
172
173 /// Scan an eh_frame section to find an FDE for a pc
174 template <typename A>
175 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
176 uint32_t sectionLength, pint_t fdeHint,
177 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
178 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
179 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
180 const pint_t ehSectionEnd = p + sectionLength;
181 while (p < ehSectionEnd) {
182 pint_t currentCFI = p;
183 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
184 pint_t cfiLength = addressSpace.get32(p);
185 p += 4;
186 if (cfiLength == 0xffffffff) {
187 // 0xffffffff means length is really next 8 bytes
188 cfiLength = (pint_t)addressSpace.get64(p);
189 p += 8;
190 }
191 if (cfiLength == 0)
192 return false; // end marker
193 uint32_t id = addressSpace.get32(p);
194 if (id == 0) {
195 // skip over CIEs
196 p += cfiLength;
197 } else {
198 // process FDE to see if it covers pc
199 pint_t nextCFI = p + cfiLength;
200 uint32_t ciePointer = addressSpace.get32(p);
201 pint_t cieStart = p - ciePointer;
202 // validate pointer to CIE is within section
203 if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
204 if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
205 p += 4;
206 // parse pc begin and range
207 pint_t pcStart =
208 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
209 pint_t pcRange = addressSpace.getEncodedP(
210 p, nextCFI, cieInfo->pointerEncoding & 0x0F);
211 // test if pc is within the function this FDE covers
212 if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
213 // parse rest of info
214 fdeInfo->lsda = 0;
215 // check for augmentation length
216 if (cieInfo->fdesHaveAugmentationData) {
217 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
218 pint_t endOfAug = p + augLen;
219 if (cieInfo->lsdaEncoding != 0) {
220 // peek at value (without indirection). Zero means no lsda
221 pint_t lsdaStart = p;
222 if (addressSpace.getEncodedP(
223 p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
224 // reset pointer and re-parse lsda address
225 p = lsdaStart;
226 fdeInfo->lsda = addressSpace
227 .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
228 }
229 }
230 p = endOfAug;
231 }
232 fdeInfo->fdeStart = currentCFI;
233 fdeInfo->fdeLength = nextCFI - currentCFI;
234 fdeInfo->fdeInstructions = p;
235 fdeInfo->pcStart = pcStart;
236 fdeInfo->pcEnd = pcStart + pcRange;
237 return true;
238 } else {
239 // pc is not in begin/range, skip this FDE
240 }
241 } else {
242 // malformed CIE, now augmentation describing pc range encoding
243 }
244 } else {
245 // malformed FDE. CIE is bad
246 }
247 p = nextCFI;
248 }
249 }
250 return false;
251 }
252
253 /// Extract info from a CIE
254 template <typename A>
255 const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
256 CIE_Info *cieInfo) {
257 cieInfo->pointerEncoding = 0;
258 cieInfo->lsdaEncoding = 0;
259 cieInfo->personalityEncoding = 0;
260 cieInfo->personalityOffsetInCIE = 0;
261 cieInfo->personality = 0;
262 cieInfo->codeAlignFactor = 0;
263 cieInfo->dataAlignFactor = 0;
264 cieInfo->isSignalFrame = false;
265 cieInfo->fdesHaveAugmentationData = false;
266 cieInfo->cieStart = cie;
267 pint_t p = cie;
268 pint_t cieLength = (pint_t)addressSpace.get32(p);
269 p += 4;
270 pint_t cieContentEnd = p + cieLength;
271 if (cieLength == 0xffffffff) {
272 // 0xffffffff means length is really next 8 bytes
273 cieLength = (pint_t)addressSpace.get64(p);
274 p += 8;
275 cieContentEnd = p + cieLength;
276 }
277 if (cieLength == 0)
278 return NULL;
279 // CIE ID is always 0
280 if (addressSpace.get32(p) != 0)
281 return "CIE ID is not zero";
282 p += 4;
283 // Version is always 1 or 3
284 uint8_t version = addressSpace.get8(p);
285 if ((version != 1) && (version != 3))
286 return "CIE version is not 1 or 3";
287 ++p;
288 // save start of augmentation string and find end
289 pint_t strStart = p;
290 while (addressSpace.get8(p) != 0)
291 ++p;
292 ++p;
293 // parse code aligment factor
294 cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd) ;
295 // parse data alignment factor
296 cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
297 // parse return address register
298 addressSpace.getULEB128(p, cieContentEnd);
299 // parse augmentation data based on augmentation string
300 const char *result = NULL;
301 if (addressSpace.get8(strStart) == 'z') {
302 // parse augmentation data length
303 addressSpace.getULEB128(p, cieContentEnd);
304 for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
305 switch (addressSpace.get8(s)) {
306 case 'z':
307 cieInfo->fdesHaveAugmentationData = true;
308 break;
309 case 'P':
310 cieInfo->personalityEncoding = addressSpace.get8(p);
311 ++p;
312 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
313 cieInfo->personality = addressSpace
314 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
315 break;
316 case 'L':
317 cieInfo->lsdaEncoding = addressSpace.get8(p);
318 ++p;
319 break;
320 case 'R':
321 cieInfo->pointerEncoding = addressSpace.get8(p);
322 ++p;
323 break;
324 case 'S':
325 cieInfo->isSignalFrame = true;
326 break;
327 default:
328 // ignore unknown letters
329 break;
330 }
331 }
332 }
333 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
334 cieInfo->cieInstructions = p;
335 return result;
336 }
337
338
339 /// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
340 template <typename A>
341 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
342 const FDE_Info &fdeInfo,
343 const CIE_Info &cieInfo, pint_t upToPC,
344 PrologInfo *results) {
345 // clear results
346 bzero(results, sizeof(PrologInfo));
347 PrologInfoStackEntry *rememberStack = NULL;
348
349 // parse CIE then FDE instructions
350 return parseInstructions(addressSpace, cieInfo.cieInstructions,
351 cieInfo.cieStart + cieInfo.cieLength, cieInfo,
352 (pint_t)(-1), rememberStack, results) &&
353 parseInstructions(addressSpace, fdeInfo.fdeInstructions,
354 fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
355 upToPC - fdeInfo.pcStart, rememberStack, results);
356 }
357
358 /// "run" the dwarf instructions
359 template <typename A>
360 bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
361 pint_t instructionsEnd,
362 const CIE_Info &cieInfo, pint_t pcoffset,
363 PrologInfoStackEntry *&rememberStack,
364 PrologInfo *results) {
365 const bool logDwarf = false;
366 pint_t p = instructions;
367 pint_t codeOffset = 0;
368 PrologInfo initialState = *results;
369 if (logDwarf)
370 fprintf(stderr, "parseInstructions(instructions=0x%0llX)\n",
371 (uint64_t) instructionsEnd);
372
373 // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
374 while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
375 uint64_t reg;
376 uint64_t reg2;
377 int64_t offset;
378 uint64_t length;
379 uint8_t opcode = addressSpace.get8(p);
380 uint8_t operand;
381 PrologInfoStackEntry *entry;
382 ++p;
383 switch (opcode) {
384 case DW_CFA_nop:
385 if (logDwarf)
386 fprintf(stderr, "DW_CFA_nop\n");
387 break;
388 case DW_CFA_set_loc:
389 codeOffset =
390 addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
391 if (logDwarf)
392 fprintf(stderr, "DW_CFA_set_loc\n");
393 break;
394 case DW_CFA_advance_loc1:
395 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
396 p += 1;
397 if (logDwarf)
398 fprintf(stderr, "DW_CFA_advance_loc1: new offset=%llu\n",
399 (uint64_t)codeOffset);
400 break;
401 case DW_CFA_advance_loc2:
402 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
403 p += 2;
404 if (logDwarf)
405 fprintf(stderr, "DW_CFA_advance_loc2: new offset=%llu\n",
406 (uint64_t)codeOffset);
407 break;
408 case DW_CFA_advance_loc4:
409 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
410 p += 4;
411 if (logDwarf)
412 fprintf(stderr, "DW_CFA_advance_loc4: new offset=%llu\n",
413 (uint64_t)codeOffset);
414 break;
415 case DW_CFA_offset_extended:
416 reg = addressSpace.getULEB128(p, instructionsEnd);
417 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
418 * cieInfo.dataAlignFactor;
419 if (reg > kMaxRegisterNumber) {
420 fprintf(stderr,
421 "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
422 return false;
423 }
424 results->savedRegisters[reg].location = kRegisterInCFA;
425 results->savedRegisters[reg].value = offset;
426 if (logDwarf)
427 fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg,
428 offset);
429 break;
430 case DW_CFA_restore_extended:
431 reg = addressSpace.getULEB128(p, instructionsEnd);
432 ;
433 if (reg > kMaxRegisterNumber) {
434 fprintf(
435 stderr,
436 "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
437 return false;
438 }
439 results->savedRegisters[reg] = initialState.savedRegisters[reg];
440 if (logDwarf)
441 fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg);
442 break;
443 case DW_CFA_undefined:
444 reg = addressSpace.getULEB128(p, instructionsEnd);
445 if (reg > kMaxRegisterNumber) {
446 fprintf(stderr,
447 "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
448 return false;
449 }
450 results->savedRegisters[reg].location = kRegisterUnused;
451 if (logDwarf)
452 fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg);
453 break;
454 case DW_CFA_same_value:
455 reg = addressSpace.getULEB128(p, instructionsEnd);
456 if (reg > kMaxRegisterNumber) {
457 fprintf(stderr,
458 "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
459 return false;
460 }
461 // <rdar://problem/8456377> DW_CFA_same_value unsupported
462 // "same value" means register was stored in frame, but its current
463 // value has not changed, so no need to restore from frame.
464 // We model this as if the register was never saved.
465 results->savedRegisters[reg].location = kRegisterUnused;
466 // set flag to disable conversion to compact unwind
467 results->sameValueUsed = true;
468 if (logDwarf)
469 fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg);
470 break;
471 case DW_CFA_register:
472 reg = addressSpace.getULEB128(p, instructionsEnd);
473 reg2 = addressSpace.getULEB128(p, instructionsEnd);
474 if (reg > kMaxRegisterNumber) {
475 fprintf(stderr,
476 "malformed DW_CFA_register dwarf unwind, reg too big\n");
477 return false;
478 }
479 if (reg2 > kMaxRegisterNumber) {
480 fprintf(stderr,
481 "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
482 return false;
483 }
484 results->savedRegisters[reg].location = kRegisterInRegister;
485 results->savedRegisters[reg].value = (int64_t)reg2;
486 // set flag to disable conversion to compact unwind
487 results->registersInOtherRegisters = true;
488 if (logDwarf)
489 fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2);
490 break;
491 case DW_CFA_remember_state:
492 // avoid operator new, because that would be an upward dependency
493 entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
494 if (entry != NULL) {
495 entry->next = rememberStack;
496 entry->info = *results;
497 rememberStack = entry;
498 } else {
499 return false;
500 }
501 if (logDwarf)
502 fprintf(stderr, "DW_CFA_remember_state\n");
503 break;
504 case DW_CFA_restore_state:
505 if (rememberStack != NULL) {
506 PrologInfoStackEntry *top = rememberStack;
507 *results = top->info;
508 rememberStack = top->next;
509 free((char *)top);
510 } else {
511 return false;
512 }
513 if (logDwarf)
514 fprintf(stderr, "DW_CFA_restore_state\n");
515 break;
516 case DW_CFA_def_cfa:
517 reg = addressSpace.getULEB128(p, instructionsEnd);
518 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
519 if (reg > kMaxRegisterNumber) {
520 fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
521 return false;
522 }
523 results->cfaRegister = (uint32_t)reg;
524 results->cfaRegisterOffset = (int32_t)offset;
525 if (logDwarf)
526 fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset);
527 break;
528 case DW_CFA_def_cfa_register:
529 reg = addressSpace.getULEB128(p, instructionsEnd);
530 if (reg > kMaxRegisterNumber) {
531 fprintf(
532 stderr,
533 "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
534 return false;
535 }
536 results->cfaRegister = (uint32_t)reg;
537 if (logDwarf)
538 fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg);
539 break;
540 case DW_CFA_def_cfa_offset:
541 results->cfaRegisterOffset = (int32_t)
542 addressSpace.getULEB128(p, instructionsEnd);
543 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
544 if (logDwarf)
545 fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n",
546 results->cfaRegisterOffset);
547 break;
548 case DW_CFA_def_cfa_expression:
549 results->cfaRegister = 0;
550 results->cfaExpression = (int64_t)p;
551 length = addressSpace.getULEB128(p, instructionsEnd);
552 p += length;
553 if (logDwarf)
554 fprintf(stderr,
555 "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n",
556 results->cfaExpression, length);
557 break;
558 case DW_CFA_expression:
559 reg = addressSpace.getULEB128(p, instructionsEnd);
560 if (reg > kMaxRegisterNumber) {
561 fprintf(stderr,
562 "malformed DW_CFA_expression dwarf unwind, reg too big\n");
563 return false;
564 }
565 results->savedRegisters[reg].location = kRegisterAtExpression;
566 results->savedRegisters[reg].value = (int64_t)p;
567 length = addressSpace.getULEB128(p, instructionsEnd);
568 p += length;
569 if (logDwarf)
570 fprintf(stderr,
571 "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n",
572 reg, results->savedRegisters[reg].value, length);
573 break;
574 case DW_CFA_offset_extended_sf:
575 reg = addressSpace.getULEB128(p, instructionsEnd);
576 if (reg > kMaxRegisterNumber) {
577 fprintf(
578 stderr,
579 "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
580 return false;
581 }
582 offset =
583 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
584 results->savedRegisters[reg].location = kRegisterInCFA;
585 results->savedRegisters[reg].value = offset;
586 if (logDwarf)
587 fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n",
588 reg, offset);
589 break;
590 case DW_CFA_def_cfa_sf:
591 reg = addressSpace.getULEB128(p, instructionsEnd);
592 offset =
593 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
594 if (reg > kMaxRegisterNumber) {
595 fprintf(stderr,
596 "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
597 return false;
598 }
599 results->cfaRegister = (uint32_t)reg;
600 results->cfaRegisterOffset = (int32_t)offset;
601 if (logDwarf)
602 fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg,
603 offset);
604 break;
605 case DW_CFA_def_cfa_offset_sf:
606 results->cfaRegisterOffset = (int32_t)
607 (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
608 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
609 if (logDwarf)
610 fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n",
611 results->cfaRegisterOffset);
612 break;
613 case DW_CFA_val_offset:
614 reg = addressSpace.getULEB128(p, instructionsEnd);
615 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
616 * cieInfo.dataAlignFactor;
617 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
618 results->savedRegisters[reg].value = offset;
619 if (logDwarf)
620 fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg,
621 offset);
622 break;
623 case DW_CFA_val_offset_sf:
624 reg = addressSpace.getULEB128(p, instructionsEnd);
625 if (reg > kMaxRegisterNumber) {
626 fprintf(stderr,
627 "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
628 return false;
629 }
630 offset =
631 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
632 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
633 results->savedRegisters[reg].value = offset;
634 if (logDwarf)
635 fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg,
636 offset);
637 break;
638 case DW_CFA_val_expression:
639 reg = addressSpace.getULEB128(p, instructionsEnd);
640 if (reg > kMaxRegisterNumber) {
641 fprintf(stderr,
642 "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
643 return false;
644 }
645 results->savedRegisters[reg].location = kRegisterIsExpression;
646 results->savedRegisters[reg].value = (int64_t)p;
647 length = addressSpace.getULEB128(p, instructionsEnd);
648 p += length;
649 if (logDwarf)
650 fprintf(
651 stderr,
652 "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n",
653 reg, results->savedRegisters[reg].value, length);
654 break;
655 case DW_CFA_GNU_args_size:
656 length = addressSpace.getULEB128(p, instructionsEnd);
657 results->spExtraArgSize = (uint32_t)length;
658 if (logDwarf)
659 fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", length);
660 break;
661 case DW_CFA_GNU_negative_offset_extended:
662 reg = addressSpace.getULEB128(p, instructionsEnd);
663 if (reg > kMaxRegisterNumber) {
664 fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf "
665 "unwind, reg too big\n");
666 return false;
667 }
668 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
669 * cieInfo.dataAlignFactor;
670 results->savedRegisters[reg].location = kRegisterInCFA;
671 results->savedRegisters[reg].value = -offset;
672 if (logDwarf)
673 fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset);
674 break;
675 default:
676 operand = opcode & 0x3F;
677 switch (opcode & 0xC0) {
678 case DW_CFA_offset:
679 reg = operand;
680 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
681 * cieInfo.dataAlignFactor;
682 results->savedRegisters[reg].location = kRegisterInCFA;
683 results->savedRegisters[reg].value = offset;
684 if (logDwarf)
685 fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand,
686 offset);
687 break;
688 case DW_CFA_advance_loc:
689 codeOffset += operand * cieInfo.codeAlignFactor;
690 if (logDwarf)
691 fprintf(stderr, "DW_CFA_advance_loc: new offset=%llu\n",
692 (uint64_t)codeOffset);
693 break;
694 case DW_CFA_restore:
695 reg = operand;
696 results->savedRegisters[reg] = initialState.savedRegisters[reg];
697 if (logDwarf)
698 fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg);
699 break;
700 default:
701 if (logDwarf)
702 fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
703 return false;
704 }
705 }
706 }
707
708 return true;
709 }
710
711 } // namespace libunwind
712
713 #endif // __DWARF_PARSER_HPP__
OLDNEW
« no previous file with comments | « third_party/libc++abi/src/Unwind/DwarfInstructions.hpp ('k') | third_party/libc++abi/src/Unwind/Registers.hpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698