/// computePCBegin - return the address of FDE's pc /// @ref binutils gold: ehframe.cc:222 uint32_t EhFrameHdr::computePCBegin(const EhFrame::FDE& pFDE, const MemoryRegion& pEhFrameRegion) { uint8_t fde_encoding = pFDE.getCIE().getFDEEncode(); unsigned int eh_value = fde_encoding & 0x7; // check the size to read in if (eh_value == llvm::dwarf::DW_EH_PE_absptr) { eh_value = DW_EH_PE_udata4; } size_t pc_size = 0x0; switch (eh_value) { case DW_EH_PE_udata2: pc_size = 2; break; case DW_EH_PE_udata4: pc_size = 4; break; case DW_EH_PE_udata8: pc_size = 8; break; default: // TODO break; } SizeTraits<32>::Address pc = 0x0; const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() + pFDE.getOffset() + pFDE.getDataStart(); std::memcpy(&pc, offset, pc_size); // adjust the signed value bool is_signed = (fde_encoding & llvm::dwarf::DW_EH_PE_signed) != 0x0; if (DW_EH_PE_udata2 == eh_value && is_signed) pc = (pc ^ 0x8000) - 0x8000; // handle eh application switch (fde_encoding & 0x70) { case DW_EH_PE_absptr: break; case DW_EH_PE_pcrel: pc += m_EhFrame.addr() + pFDE.getOffset() + pFDE.getDataStart(); break; case DW_EH_PE_datarel: // TODO break; default: // TODO break; } return pc; }
void EhFrame::addFDE(EhFrame::FDE& pFDE, bool pAlsoAddFragment) { pFDE.getCIE().add(pFDE); if (pAlsoAddFragment) addFragment(pFDE); }