//===-------------------------- DwarfInstructions.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.
//
//
// Processor specific interpretation of dwarf unwind info.
//
//===----------------------------------------------------------------------===//
#ifndef __DWARF_INSTRUCTIONS_HPP__
#define __DWARF_INSTRUCTIONS_HPP__
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "dwarf2.h"
#include "AddressSpace.hpp"
#include "Registers.hpp"
#include "DwarfParser.hpp"
#include "config.h"
namespace libunwind {
/// DwarfInstructions maps abtract dwarf unwind instructions to a particular
/// architecture
template <typename A, typename R>
class DwarfInstructions {
public:
typedef typename A::pint_t pint_t;
typedef typename A::sint_t sint_t;
static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
R ®isters);
private:
enum {
DW_X86_64_RET_ADDR = 16
};
enum {
DW_X86_RET_ADDR = 8
};
typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;
typedef typename CFI_Parser<A>::PrologInfo PrologInfo;
typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
static pint_t evaluateExpression(pint_t expression, A &addressSpace,
const R ®isters,
pint_t initialStackValue);
static pint_t getSavedRegister(A &addressSpace, const R ®isters,
pint_t cfa, const RegisterLocation &savedReg);
static double getSavedFloatRegister(A &addressSpace, const R ®isters,
pint_t cfa, const RegisterLocation &savedReg);
static v128 getSavedVectorRegister(A &addressSpace, const R ®isters,
pint_t cfa, const RegisterLocation &savedReg);
// x86 specific variants
static int lastRestoreReg(const Registers_x86 &);
static bool isReturnAddressRegister(int regNum, const Registers_x86 &);
static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
const Registers_x86 &);
// x86_64 specific variants
static int lastRestoreReg(const Registers_x86_64 &);
static bool isReturnAddressRegister(int regNum, const Registers_x86_64 &);
static pint_t getCFA(A &addressSpace,
const PrologInfo &prolog,
const Registers_x86_64 &);
// ppc specific variants
static int lastRestoreReg(const Registers_ppc &);
static bool isReturnAddressRegister(int regNum, const Registers_ppc &);
static pint_t getCFA(A &addressSpace,
const PrologInfo &prolog,
const Registers_ppc &);
// arm64 specific variants
static bool isReturnAddressRegister(int regNum, const Registers_arm64 &);
static int lastRestoreReg(const Registers_arm64 &);
static pint_t getCFA(A &addressSpace,
const PrologInfo &prolog,
const Registers_arm64 &);
};
template <typename A, typename R>
typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
A &addressSpace, const R ®isters, pint_t cfa,
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
return addressSpace.getP(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
return addressSpace.getP(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
return evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa);
case CFI_Parser<A>::kRegisterInRegister:
return registers.getRegister((int)savedReg.value);
case CFI_Parser<A>::kRegisterUnused:
case CFI_Parser<A>::kRegisterOffsetFromCFA:
// FIX ME
break;
}
_LIBUNWIND_ABORT("unsupported restore location for register");
}
template <typename A, typename R>
double DwarfInstructions<A, R>::getSavedFloatRegister(
A &addressSpace, const R ®isters, pint_t cfa,
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterAtExpression:
return addressSpace.getDouble(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
case CFI_Parser<A>::kRegisterIsExpression:
case CFI_Parser<A>::kRegisterUnused