1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===- EhFrameHdr.cpp -----------------------------------------------------===// 2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// 3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// The MCLinker Project 4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// 5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This file is distributed under the University of Illinois Open Source 6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// License. See LICENSE.TXT for details. 7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// 8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===// 9affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/EhFrameHdr.h> 10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MemoryArea.h> 1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MemoryRegion.h> 1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/EhFrame.h> 1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h> 1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/Dwarf.h> 1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/DataTypes.h> 1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <algorithm> 2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <cstring> 2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 22affc150dc44fab1911775a49636d0ce85333b634Zonr Changusing namespace mcld; 2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaousing namespace llvm::dwarf; 24affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// Helper Function 2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaonamespace bit32 { 2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaotypedef std::pair<SizeTraits<32>::Address, SizeTraits<32>::Address> Entry; 3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EntryCompare(const Entry& pX, const Entry& pY) 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ return (pX.first < pY.first); } 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} // bit32 namespace 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// Template Specification Functions 3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// emitOutput<32> - write out eh_frame_hdr 4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaotemplate<> 4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid EhFrameHdr::emitOutput<32>(MemoryArea& pOutput) 43affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion* ehframehdr_region = 4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pOutput.request(m_EhFrameHdr.offset(), m_EhFrameHdr.size()); 4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion* ehframe_region = 4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pOutput.request(m_EhFrame.offset(), 4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_EhFrame.size()); 5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint8_t* data = (uint8_t*)ehframehdr_region->start(); 5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // version 5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao data[0] = 1; 5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // eh_frame_ptr_enc 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao data[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; 5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // eh_frame_ptr 5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t* eh_frame_ptr = (uint32_t*)(data + 4); 5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *eh_frame_ptr = m_EhFrame.addr() - (m_EhFrameHdr.addr() + 4); 6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // fde_count 6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t* fde_count = (uint32_t*)(data + 8); 6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (m_EhFrame.hasEhFrame()) 6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *fde_count = m_EhFrame.getEhFrame()->numOfFDEs(); 65f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines else 66f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines *fde_count = 0; 6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 68f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (0 == *fde_count) { 6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // fde_count_enc 70f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines data[2] = DW_EH_PE_omit; 7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // table_enc 72f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines data[3] = DW_EH_PE_omit; 7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // fde_count_enc 76f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines data[2] = DW_EH_PE_udata4; 7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // table_enc 78f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines data[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; 7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // prepare the binary search table 8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao typedef std::vector<bit32::Entry> SearchTableType; 8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SearchTableType search_table; 8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao EhFrame::const_fde_iterator fde, fde_end = m_EhFrame.getEhFrame()->fde_end(); 8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for(fde = m_EhFrame.getEhFrame()->fde_begin(); fde != fde_end; ++fde) { 8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(*fde != NULL); 8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SizeTraits<32>::Offset offset; 8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SizeTraits<32>::Address fde_pc; 8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SizeTraits<32>::Address fde_addr; 8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao offset = (*fde)->getOffset(); 9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fde_pc = computePCBegin(**fde, *ehframe_region); 9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fde_addr = m_EhFrame.addr() + offset; 9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao search_table.push_back(std::make_pair(fde_pc, fde_addr)); 9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao std::sort(search_table.begin(), search_table.end(), bit32::EntryCompare); 9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // write out the binary search table 9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t* bst = (uint32_t*)(data + 12); 9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SearchTableType::const_iterator entry, entry_end = search_table.end(); 10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao size_t id = 0; 10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (entry = search_table.begin(); entry != entry_end; ++entry) { 10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bst[id++] = (*entry).first - m_EhFrameHdr.addr(); 10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bst[id++] = (*entry).second - m_EhFrameHdr.addr(); 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pOutput.release(ehframehdr_region); 10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pOutput.release(ehframe_region); 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// EhFrameHdr 11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoEhFrameHdr::EhFrameHdr(LDSection& pEhFrameHdr, const LDSection& pEhFrame) 11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao : m_EhFrameHdr(pEhFrameHdr), m_EhFrame(pEhFrame) { 116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 118affc150dc44fab1911775a49636d0ce85333b634Zonr ChangEhFrameHdr::~EhFrameHdr() 119affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 120affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 122affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// @ref lsb core generic 4.1 123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// .eh_frame_hdr section format 124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// uint8_t : version 125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// uint8_t : eh_frame_ptr_enc 126affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// uint8_t : fde_count_enc 127affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// uint8_t : table_enc 128affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// uint32_t : eh_frame_ptr 129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// uint32_t : fde_count 130affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// __________________________ when fde_count > 0 131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// <uint32_t, uint32_t>+ : binary search table 132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/// sizeOutput - base on the fde count to size output 133affc150dc44fab1911775a49636d0ce85333b634Zonr Changvoid EhFrameHdr::sizeOutput() 134affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang size_t size = 12; 13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (m_EhFrame.hasEhFrame()) 13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao size += 8 * m_EhFrame.getEhFrame()->numOfFDEs(); 13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_EhFrameHdr.setSize(size); 139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// computePCBegin - return the address of FDE's pc 14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @ref binutils gold: ehframe.cc:222 14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaouint32_t EhFrameHdr::computePCBegin(const EhFrame::FDE& pFDE, 14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const MemoryRegion& pEhFrameRegion) 14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint8_t fde_encoding = pFDE.getCIE().getFDEEncode(); 14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao unsigned int eh_value = fde_encoding & 0x7; 14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // check the size to read in 15022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (eh_value == llvm::dwarf::DW_EH_PE_absptr) { 15122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao eh_value = DW_EH_PE_udata4; 15222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao size_t pc_size = 0x0; 15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao switch (eh_value) { 15622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case DW_EH_PE_udata2: 15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pc_size = 2; 15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case DW_EH_PE_udata4: 16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pc_size = 4; 16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 16222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case DW_EH_PE_udata8: 16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pc_size = 8; 16422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 16522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao default: 16622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // TODO 16722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 16822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SizeTraits<32>::Address pc = 0x0; 17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() + 17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pFDE.getOffset() + 17322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pFDE.getDataStart(); 17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao std::memcpy(&pc, offset, pc_size); 17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // adjust the signed value 17722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bool is_signed = (fde_encoding & llvm::dwarf::DW_EH_PE_signed) != 0x0; 17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (DW_EH_PE_udata2 == eh_value && is_signed) 17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pc = (pc ^ 0x8000) - 0x8000; 18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 18122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // handle eh application 18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao switch (fde_encoding & 0x70) 18322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao { 18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case DW_EH_PE_absptr: 18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case DW_EH_PE_pcrel: 18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pc += m_EhFrame.addr() + pFDE.getOffset() + pFDE.getDataStart(); 18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case DW_EH_PE_datarel: 19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // TODO 19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao default: 19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // TODO 19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return pc; 19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 198