diff options
Diffstat (limited to 'src/Unwind/DwarfParser.hpp')
-rw-r--r-- | src/Unwind/DwarfParser.hpp | 724 |
1 files changed, 0 insertions, 724 deletions
diff --git a/src/Unwind/DwarfParser.hpp b/src/Unwind/DwarfParser.hpp deleted file mode 100644 index f6ef738..0000000 --- a/src/Unwind/DwarfParser.hpp +++ /dev/null @@ -1,724 +0,0 @@ -//===--------------------------- DwarfParser.hpp --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -// -// Parses DWARF CFIs (FDEs and CIEs). -// -//===----------------------------------------------------------------------===// - -#ifndef __DWARF_PARSER_HPP__ -#define __DWARF_PARSER_HPP__ - -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include <vector> - -#include "libunwind.h" -#include "dwarf2.h" - -#include "AddressSpace.hpp" - -namespace libunwind { - -/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. -/// See Dwarf Spec for details: -/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html -/// -template <typename A> -class CFI_Parser { -public: - typedef typename A::pint_t pint_t; - - /// Information encoded in a CIE (Common Information Entry) - struct CIE_Info { - pint_t cieStart; - pint_t cieLength; - pint_t cieInstructions; - uint8_t pointerEncoding; - uint8_t lsdaEncoding; - uint8_t personalityEncoding; - uint8_t personalityOffsetInCIE; - pint_t personality; - uint32_t codeAlignFactor; - int dataAlignFactor; - bool isSignalFrame; - bool fdesHaveAugmentationData; - uint8_t returnAddressRegister; - }; - - /// Information about an FDE (Frame Description Entry) - struct FDE_Info { - pint_t fdeStart; - pint_t fdeLength; - pint_t fdeInstructions; - pint_t pcStart; - pint_t pcEnd; - pint_t lsda; - }; - - enum { - kMaxRegisterNumber = 120 - }; - enum RegisterSavedWhere { - kRegisterUnused, - kRegisterInCFA, - kRegisterOffsetFromCFA, - kRegisterInRegister, - kRegisterAtExpression, - kRegisterIsExpression - }; - struct RegisterLocation { - RegisterSavedWhere location; - int64_t value; - }; - /// Information about a frame layout and registers saved determined - /// by "running" the dwarf FDE "instructions" - struct PrologInfo { - uint32_t cfaRegister; - int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset - int64_t cfaExpression; // CFA = expression - uint32_t spExtraArgSize; - uint32_t codeOffsetAtStackDecrement; - bool registersInOtherRegisters; - bool sameValueUsed; - RegisterLocation savedRegisters[kMaxRegisterNumber]; - }; - - struct PrologInfoStackEntry { - PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i) - : next(n), info(i) {} - PrologInfoStackEntry *next; - PrologInfo info; - }; - - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, - CIE_Info *cieInfo); - static const char *decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo); - static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, - PrologInfo *results); - - static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); - -private: - static bool parseInstructions(A &addressSpace, pint_t instructions, - pint_t instructionsEnd, const CIE_Info &cieInfo, - pint_t pcoffset, - PrologInfoStackEntry *&rememberStack, - PrologInfo *results); -}; - -/// Parse a FDE into a CIE_Info and an FDE_Info -template <typename A> -const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { - pint_t p = fdeStart; - pint_t cfiLength = (pint_t)addressSpace.get32(p); - p += 4; - if (cfiLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cfiLength = (pint_t)addressSpace.get64(p); - p += 8; - } - if (cfiLength == 0) - return "FDE has zero length"; // end marker - uint32_t ciePointer = addressSpace.get32(p); - if (ciePointer == 0) - return "FDE is really a CIE"; // this is a CIE not an FDE - pint_t nextCFI = p + cfiLength; - pint_t cieStart = p - ciePointer; - const char *err = parseCIE(addressSpace, cieStart, cieInfo); - if (err != NULL) - return err; - p += 4; - // parse pc begin and range - pint_t pcStart = - addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); - pint_t pcRange = - addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); - // parse rest of info - fdeInfo->lsda = 0; - // check for augmentation length - if (cieInfo->fdesHaveAugmentationData) { - pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { - // peek at value (without indirection). Zero means no lsda - pint_t lsdaStart = p; - if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != - 0) { - // reset pointer and re-parse lsda address - p = lsdaStart; - fdeInfo->lsda = - addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); - } - } - p = endOfAug; - } - fdeInfo->fdeStart = fdeStart; - fdeInfo->fdeLength = nextCFI - fdeStart; - fdeInfo->fdeInstructions = p; - fdeInfo->pcStart = pcStart; - fdeInfo->pcEnd = pcStart + pcRange; - return NULL; // success -} - -/// Scan an eh_frame section to find an FDE for a pc -template <typename A> -bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uint32_t sectionLength, pint_t fdeHint, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { - //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); - pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; - const pint_t ehSectionEnd = p + sectionLength; - while (p < ehSectionEnd) { - pint_t currentCFI = p; - //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); - pint_t cfiLength = addressSpace.get32(p); - p += 4; - if (cfiLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cfiLength = (pint_t)addressSpace.get64(p); - p += 8; - } - if (cfiLength == 0) - return false; // end marker - uint32_t id = addressSpace.get32(p); - if (id == 0) { - // skip over CIEs - p += cfiLength; - } else { - // process FDE to see if it covers pc - pint_t nextCFI = p + cfiLength; - uint32_t ciePointer = addressSpace.get32(p); - pint_t cieStart = p - ciePointer; - // validate pointer to CIE is within section - if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) { - if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) { - p += 4; - // parse pc begin and range - pint_t pcStart = - addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); - pint_t pcRange = addressSpace.getEncodedP( - p, nextCFI, cieInfo->pointerEncoding & 0x0F); - // test if pc is within the function this FDE covers - if ((pcStart < pc) && (pc <= pcStart + pcRange)) { - // parse rest of info - fdeInfo->lsda = 0; - // check for augmentation length - if (cieInfo->fdesHaveAugmentationData) { - pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); - pint_t endOfAug = p + augLen; - if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { - // peek at value (without indirection). Zero means no lsda - pint_t lsdaStart = p; - if (addressSpace.getEncodedP( - p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) { - // reset pointer and re-parse lsda address - p = lsdaStart; - fdeInfo->lsda = addressSpace - .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); - } - } - p = endOfAug; - } - fdeInfo->fdeStart = currentCFI; - fdeInfo->fdeLength = nextCFI - currentCFI; - fdeInfo->fdeInstructions = p; - fdeInfo->pcStart = pcStart; - fdeInfo->pcEnd = pcStart + pcRange; - return true; - } else { - // pc is not in begin/range, skip this FDE - } - } else { - // malformed CIE, now augmentation describing pc range encoding - } - } else { - // malformed FDE. CIE is bad - } - p = nextCFI; - } - } - return false; -} - -/// Extract info from a CIE -template <typename A> -const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, - CIE_Info *cieInfo) { - cieInfo->pointerEncoding = 0; - cieInfo->lsdaEncoding = DW_EH_PE_omit; - cieInfo->personalityEncoding = 0; - cieInfo->personalityOffsetInCIE = 0; - cieInfo->personality = 0; - cieInfo->codeAlignFactor = 0; - cieInfo->dataAlignFactor = 0; - cieInfo->isSignalFrame = false; - cieInfo->fdesHaveAugmentationData = false; - cieInfo->cieStart = cie; - pint_t p = cie; - pint_t cieLength = (pint_t)addressSpace.get32(p); - p += 4; - pint_t cieContentEnd = p + cieLength; - if (cieLength == 0xffffffff) { - // 0xffffffff means length is really next 8 bytes - cieLength = (pint_t)addressSpace.get64(p); - p += 8; - cieContentEnd = p + cieLength; - } - if (cieLength == 0) - return NULL; - // CIE ID is always 0 - if (addressSpace.get32(p) != 0) - return "CIE ID is not zero"; - p += 4; - // Version is always 1 or 3 - uint8_t version = addressSpace.get8(p); - if ((version != 1) && (version != 3)) - return "CIE version is not 1 or 3"; - ++p; - // save start of augmentation string and find end - pint_t strStart = p; - while (addressSpace.get8(p) != 0) - ++p; - ++p; - // parse code aligment factor - cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd); - // parse data alignment factor - cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); - // parse return address register - uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd); - assert(raReg < 255 && "return address register too large"); - cieInfo->returnAddressRegister = (uint8_t)raReg; - // parse augmentation data based on augmentation string - const char *result = NULL; - if (addressSpace.get8(strStart) == 'z') { - // parse augmentation data length - addressSpace.getULEB128(p, cieContentEnd); - for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) { - switch (addressSpace.get8(s)) { - case 'z': - cieInfo->fdesHaveAugmentationData = true; - break; - case 'P': - cieInfo->personalityEncoding = addressSpace.get8(p); - ++p; - cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie); - cieInfo->personality = addressSpace - .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); - break; - case 'L': - cieInfo->lsdaEncoding = addressSpace.get8(p); - ++p; - break; - case 'R': - cieInfo->pointerEncoding = addressSpace.get8(p); - ++p; - break; - case 'S': - cieInfo->isSignalFrame = true; - break; - default: - // ignore unknown letters - break; - } - } - } - cieInfo->cieLength = cieContentEnd - cieInfo->cieStart; - cieInfo->cieInstructions = p; - return result; -} - - -/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE -template <typename A> -bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, - const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, - PrologInfo *results) { - // clear results - memset(results, '\0', sizeof(PrologInfo)); - PrologInfoStackEntry *rememberStack = NULL; - - // parse CIE then FDE instructions - return parseInstructions(addressSpace, cieInfo.cieInstructions, - cieInfo.cieStart + cieInfo.cieLength, cieInfo, - (pint_t)(-1), rememberStack, results) && - parseInstructions(addressSpace, fdeInfo.fdeInstructions, - fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, - upToPC - fdeInfo.pcStart, rememberStack, results); -} - -/// "run" the dwarf instructions -template <typename A> -bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, - pint_t instructionsEnd, - const CIE_Info &cieInfo, pint_t pcoffset, - PrologInfoStackEntry *&rememberStack, - PrologInfo *results) { - const bool logDwarf = false; - pint_t p = instructions; - pint_t codeOffset = 0; - PrologInfo initialState = *results; - if (logDwarf) - fprintf(stderr, "parseInstructions(instructions=0x%0" PRIx64 ")\n", - (uint64_t)instructionsEnd); - - // see Dwarf Spec, section 6.4.2 for details on unwind opcodes - while ((p < instructionsEnd) && (codeOffset < pcoffset)) { - uint64_t reg; - uint64_t reg2; - int64_t offset; - uint64_t length; - uint8_t opcode = addressSpace.get8(p); - uint8_t operand; - PrologInfoStackEntry *entry; - ++p; - switch (opcode) { - case DW_CFA_nop: - if (logDwarf) - fprintf(stderr, "DW_CFA_nop\n"); - break; - case DW_CFA_set_loc: - codeOffset = - addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); - if (logDwarf) - fprintf(stderr, "DW_CFA_set_loc\n"); - break; - case DW_CFA_advance_loc1: - codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); - p += 1; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); - break; - case DW_CFA_advance_loc2: - codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); - p += 2; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); - break; - case DW_CFA_advance_loc4: - codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); - p += 4; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); - break; - case DW_CFA_offset_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_offset_extended(reg=%" PRIu64 ", offset=%" PRId64 ")\n", - reg, offset); - break; - case DW_CFA_restore_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - ; - if (reg > kMaxRegisterNumber) { - fprintf( - stderr, - "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg] = initialState.savedRegisters[reg]; - if (logDwarf) - fprintf(stderr, "DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); - break; - case DW_CFA_undefined: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_undefined dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterUnused; - if (logDwarf) - fprintf(stderr, "DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); - break; - case DW_CFA_same_value: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_same_value dwarf unwind, reg too big\n"); - return false; - } - // <rdar://problem/8456377> DW_CFA_same_value unsupported - // "same value" means register was stored in frame, but its current - // value has not changed, so no need to restore from frame. - // We model this as if the register was never saved. - results->savedRegisters[reg].location = kRegisterUnused; - // set flag to disable conversion to compact unwind - results->sameValueUsed = true; - if (logDwarf) - fprintf(stderr, "DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); - break; - case DW_CFA_register: - reg = addressSpace.getULEB128(p, instructionsEnd); - reg2 = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_register dwarf unwind, reg too big\n"); - return false; - } - if (reg2 > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_register dwarf unwind, reg2 too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterInRegister; - results->savedRegisters[reg].value = (int64_t)reg2; - // set flag to disable conversion to compact unwind - results->registersInOtherRegisters = true; - if (logDwarf) - fprintf(stderr, "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", - reg, reg2); - break; - case DW_CFA_remember_state: - // avoid operator new, because that would be an upward dependency - entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry)); - if (entry != NULL) { - entry->next = rememberStack; - entry->info = *results; - rememberStack = entry; - } else { - return false; - } - if (logDwarf) - fprintf(stderr, "DW_CFA_remember_state\n"); - break; - case DW_CFA_restore_state: - if (rememberStack != NULL) { - PrologInfoStackEntry *top = rememberStack; - *results = top->info; - rememberStack = top->next; - free((char *)top); - } else { - return false; - } - if (logDwarf) - fprintf(stderr, "DW_CFA_restore_state\n"); - break; - case DW_CFA_def_cfa: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n"); - return false; - } - results->cfaRegister = (uint32_t)reg; - results->cfaRegisterOffset = (int32_t)offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", - reg, offset); - break; - case DW_CFA_def_cfa_register: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf( - stderr, - "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n"); - return false; - } - results->cfaRegister = (uint32_t)reg; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); - break; - case DW_CFA_def_cfa_offset: - results->cfaRegisterOffset = (int32_t) - addressSpace.getULEB128(p, instructionsEnd); - results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n", - results->cfaRegisterOffset); - break; - case DW_CFA_def_cfa_expression: - results->cfaRegister = 0; - results->cfaExpression = (int64_t)p; - length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%" PRIx64 - ", length=%" PRIu64 ")\n", - results->cfaExpression, length); - break; - case DW_CFA_expression: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_expression dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterAtExpression; - results->savedRegisters[reg].value = (int64_t)p; - length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if (logDwarf) - fprintf(stderr, "DW_CFA_expression(reg=%" PRIu64 - ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); - break; - case DW_CFA_offset_extended_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf( - stderr, - "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n"); - return false; - } - offset = - addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%" PRIu64 - ", offset=%" PRId64 ")\n", - reg, offset); - break; - case DW_CFA_def_cfa_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = - addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n"); - return false; - } - results->cfaRegister = (uint32_t)reg; - results->cfaRegisterOffset = (int32_t)offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_def_cfa_sf(reg=%" PRIu64 ", offset=%" PRId64 ")\n", reg, - offset); - break; - case DW_CFA_def_cfa_offset_sf: - results->cfaRegisterOffset = (int32_t) - (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor); - results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; - if (logDwarf) - fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n", - results->cfaRegisterOffset); - break; - case DW_CFA_val_offset: - reg = addressSpace.getULEB128(p, instructionsEnd); - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_val_offset(reg=%" PRIu64 ", offset=%" PRId64 "\n", reg, - offset); - break; - case DW_CFA_val_offset_sf: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n"); - return false; - } - offset = - addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, - "DW_CFA_val_offset_sf(reg=%" PRIu64 ", offset=%" PRId64 "\n", - reg, offset); - break; - case DW_CFA_val_expression: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, - "malformed DW_CFA_val_expression dwarf unwind, reg too big\n"); - return false; - } - results->savedRegisters[reg].location = kRegisterIsExpression; - results->savedRegisters[reg].value = (int64_t)p; - length = addressSpace.getULEB128(p, instructionsEnd); - p += length; - if (logDwarf) - fprintf(stderr, "DW_CFA_val_expression(reg=%" PRIu64 - ", expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); - break; - case DW_CFA_GNU_args_size: - length = addressSpace.getULEB128(p, instructionsEnd); - results->spExtraArgSize = (uint32_t)length; - if (logDwarf) - fprintf(stderr, "DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); - break; - case DW_CFA_GNU_negative_offset_extended: - reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { - fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf " - "unwind, reg too big\n"); - return false; - } - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = -offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", - offset); - break; - default: - operand = opcode & 0x3F; - switch (opcode & 0xC0) { - case DW_CFA_offset: - reg = operand; - offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) - * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; - if (logDwarf) - fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", - operand, offset); - break; - case DW_CFA_advance_loc: - codeOffset += operand * cieInfo.codeAlignFactor; - if (logDwarf) - fprintf(stderr, "DW_CFA_advance_loc: new offset=%" PRIu64 "\n", - (uint64_t)codeOffset); - break; - case DW_CFA_restore: - reg = operand; - results->savedRegisters[reg] = initialState.savedRegisters[reg]; - if (logDwarf) - fprintf(stderr, "DW_CFA_restore(reg=%" PRIu64 ")\n", reg); - break; - default: - if (logDwarf) - fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode); - return false; - } - } - } - - return true; -} - -} // namespace libunwind - -#endif // __DWARF_PARSER_HPP__ |