existing libunwind used '0' in lsda_encoding as 'not present,'
whereas that is a valid encoding and does occur and would be
ignored. a missing encoding is actually 0xff.
The commit that addresses this is:
commit 8d4b51028d1a12b58d616f4b605254a877caafcf
Author: joerg <joerg>
Date:   Tue Mar 11 23:52:17 2014 +0000
    0 is a valid LSDA encoding and can be seen in statically linked
    programs. Initialize lsdaEncoding to DW_EH_PE_omit and check for that
    value to decide whether a value should be decoded.
more bugfixes are necessary. this update is up to:
commit b1f513eedd332426d88acbb118b6e9070966dcb9
Author: joerg <joerg>
Date:   Wed May 14 22:13:36 2014 +0000
    Lazy VFP processing works a lot better if the functions contain a return
    instruction.
		
	
			
		
			
				
	
	
		
			145 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===------------------------- UnwindCursor.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.
 | 
						|
//
 | 
						|
//
 | 
						|
// C++ interface to lower levels of libuwind
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#ifndef __UNWINDCURSOR_HPP__
 | 
						|
#define __UNWINDCURSOR_HPP__
 | 
						|
 | 
						|
#include <stdint.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#if !defined(__minix)
 | 
						|
#include <pthread.h>
 | 
						|
#endif /* !defined(__minix) */
 | 
						|
 | 
						|
#include "AddressSpace.hpp"
 | 
						|
#include "DwarfInstructions.hpp"
 | 
						|
#include "Registers.hpp"
 | 
						|
 | 
						|
namespace _Unwind {
 | 
						|
 | 
						|
template <typename A, typename R> class UnwindCursor {
 | 
						|
public:
 | 
						|
  UnwindCursor(R ®s, A &as)
 | 
						|
      : fRegisters(regs), fAddressSpace(as), fUnwindInfoMissing(false),
 | 
						|
        fIsSignalFrame(false) {
 | 
						|
    memset(&fInfo, 0, sizeof(fInfo));
 | 
						|
  }
 | 
						|
 | 
						|
  uint64_t getIP() const { return fRegisters.getIP(); }
 | 
						|
 | 
						|
  void setIP(uint64_t value) { return fRegisters.setIP(value); }
 | 
						|
 | 
						|
  uint64_t getSP() const { return fRegisters.getSP(); }
 | 
						|
 | 
						|
  void setSP(uint64_t value) { return fRegisters.setSP(value); }
 | 
						|
 | 
						|
  bool validReg(int regNum) { return fRegisters.validRegister(regNum); }
 | 
						|
 | 
						|
  uint64_t getReg(int regNum) { return fRegisters.getRegister(regNum); }
 | 
						|
 | 
						|
  void setReg(int regNum, uint64_t value) {
 | 
						|
    fRegisters.setRegister(regNum, value);
 | 
						|
  }
 | 
						|
 | 
						|
  step_result step() {
 | 
						|
    // Bottom of stack is defined as having no more unwind info.
 | 
						|
    if (fUnwindInfoMissing)
 | 
						|
      return UNW_STEP_END;
 | 
						|
 | 
						|
    // Apply unwinding to register set.
 | 
						|
    switch (this->stepWithDwarfFDE()) {
 | 
						|
    case UNW_STEP_FAILED:
 | 
						|
      return UNW_STEP_FAILED;
 | 
						|
    case UNW_STEP_END:
 | 
						|
      return UNW_STEP_END;
 | 
						|
    case UNW_STEP_SUCCESS:
 | 
						|
      this->setInfoBasedOnIPRegister(true);
 | 
						|
      if (fUnwindInfoMissing)
 | 
						|
        return UNW_STEP_END;
 | 
						|
 | 
						|
      if (fInfo.extra_args)
 | 
						|
        setSP(getSP() + fInfo.extra_args);
 | 
						|
      return UNW_STEP_SUCCESS;
 | 
						|
    }
 | 
						|
    __builtin_unreachable();
 | 
						|
  }
 | 
						|
 | 
						|
  void getInfo(unw_proc_info_t *info) { *info = fInfo; }
 | 
						|
 | 
						|
  bool isSignalFrame() { return fIsSignalFrame; }
 | 
						|
  void setInfoBasedOnIPRegister(bool isReturnAddress = false);
 | 
						|
 | 
						|
  void jumpto() { fRegisters.jumpto(); }
 | 
						|
 | 
						|
private:
 | 
						|
  typedef typename A::pint_t pint_t;
 | 
						|
  typedef uint32_t EncodedUnwindInfo;
 | 
						|
 | 
						|
  bool getInfoFromDwarfSection(pint_t, pint_t, uint32_t, uint32_t);
 | 
						|
 | 
						|
  step_result stepWithDwarfFDE() {
 | 
						|
    return DwarfInstructions<A, R>::stepWithDwarf(
 | 
						|
        fAddressSpace, this->getIP(), fInfo.unwind_info, fRegisters, &fInfo);
 | 
						|
  }
 | 
						|
 | 
						|
  unw_proc_info_t fInfo;
 | 
						|
  R fRegisters;
 | 
						|
  A &fAddressSpace;
 | 
						|
  bool fUnwindInfoMissing;
 | 
						|
  bool fIsSignalFrame;
 | 
						|
};
 | 
						|
 | 
						|
template <typename A, typename R>
 | 
						|
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
 | 
						|
  pint_t pc = this->getIP();
 | 
						|
 | 
						|
  // If the last line of a function is a "throw", the compiler sometimes
 | 
						|
  // emits no instructions after the call to __cxa_throw.  This means
 | 
						|
  // the return address is actually the start of the next function.
 | 
						|
  // To disambiguate this, back up the PC when we know it is a return
 | 
						|
  // address.
 | 
						|
  if (isReturnAddress)
 | 
						|
    --pc;
 | 
						|
 | 
						|
  pint_t fdeStart, data_base;
 | 
						|
  if (!fAddressSpace.findFDE(pc, fdeStart, data_base)) {
 | 
						|
    fUnwindInfoMissing = true;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  fInfo.data_base = data_base;
 | 
						|
 | 
						|
  typename CFI_Parser<A, R>::FDE_Info fdeInfo;
 | 
						|
  typename CFI_Parser<A, R>::CIE_Info cieInfo;
 | 
						|
  CFI_Parser<A, R>::decodeFDE(fAddressSpace, fdeStart, &fdeInfo, &cieInfo,
 | 
						|
                              &fInfo);
 | 
						|
  if (pc < fdeInfo.pcStart || pc > fdeInfo.pcEnd) {
 | 
						|
    fUnwindInfoMissing = true;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  fInfo.start_ip = fdeInfo.pcStart;
 | 
						|
 | 
						|
  typename CFI_Parser<A, R>::PrologInfo prolog;
 | 
						|
  if (!CFI_Parser<A, R>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo,
 | 
						|
                                              pc, &prolog, &fInfo)) {
 | 
						|
    fUnwindInfoMissing = true;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  // Save off parsed FDE info
 | 
						|
  fInfo.end_ip = fdeInfo.pcEnd;
 | 
						|
  fInfo.lsda = fdeInfo.lsda;
 | 
						|
  fInfo.handler = cieInfo.personality;
 | 
						|
  fInfo.extra_args = prolog.spExtraArgSize;
 | 
						|
  fInfo.unwind_info = fdeInfo.fdeStart;
 | 
						|
}
 | 
						|
 | 
						|
}; // namespace _Unwind
 | 
						|
 | 
						|
#endif // __UNWINDCURSOR_HPP__
 |