122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===- EhFrameReader.cpp --------------------------------------------------===// 222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// 322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// The MCLinker Project 422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// 522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// This file is distributed under the University of Illinois Open Source 622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// License. See LICENSE.TXT for details. 722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// 822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/EhFrameReader.h> 1022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/ADT/StringRef.h> 1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/Dwarf.h> 1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/MC/MCLDInput.h> 1522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/EhFrame.h> 1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/LDSection.h> 1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MemoryArea.h> 1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Support/MsgHandling.h> 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaousing namespace mcld; 2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaousing namespace llvm::dwarf; 2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// Helper Functions 2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// skip_LEB128 - skip the first LEB128 encoded value from *pp, update *pp 2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// to the next character. 2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @return - false if we ran off the end of the string. 2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @ref - GNU gold 1.11, ehframe.h, Eh_frame::skip_leb128. 3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic bool 3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoskip_LEB128(EhFrameReader::ConstAddress* pp, EhFrameReader::ConstAddress pend) 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (EhFrameReader::ConstAddress p = *pp; p < pend; ++p) { 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == (*p & 0x80)) { 3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *pp = p + 1; 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// EhFrameReader 4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaotemplate<> EhFrameReader::Token 4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoEhFrameReader::scan<true>(ConstAddress pHandler, 4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t pOffset, 4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const MemoryRegion& pData) const 4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Token result; 5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.file_off = pOffset; 5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const uint32_t* data = (const uint32_t*)pHandler; 5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao size_t cur_idx = 0; 5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Length Field 5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t length = data[cur_idx++]; 5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == length) { 5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // terminator 6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.kind = Terminator; 6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.data_off = 4; 6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.size = 4; 6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return result; 6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Extended Field 6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t extended = 0x0; 6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0xFFFFFFFF == length) { 6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao extended = data[cur_idx++]; 7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao extended <<= 32; 7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao extended |= data[cur_idx++]; 7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.size = extended + 12; 7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.data_off = 16; 7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else { 7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.size = length + 4; 7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.data_off = 8; 7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // ID Field 8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t ID = data[cur_idx++]; 8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x0 == ID) 8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.kind = CIE; 8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.kind = FDE; 8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return result; 8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaotemplate<> 9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::read<32, true>(Input& pInput, EhFrame& pEhFrame) 9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Alphabet: 9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // {CIE, FDE, CIEt} 9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // 9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Regular Expression: 9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // (CIE FDE*)+ CIEt 9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // 9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Autometa: 10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // S = {Q0, Q1, Q2}, Start = Q0, Accept = Q2 10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // 10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FDE 10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // +---+ 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // CIE \ / CIEt 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Q0 -------> Q1 -------> Q2 10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // | / \ ^ 10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // | +---+ | 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // | CIE | 10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // +-----------------------+ 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // CIEt 11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const State autometa[NumOfStates][NumOfTokenKinds] = { 11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // CIE FDE Term Unknown 11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao { Q1, Reject, Accept, Reject }, // Q0 11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao { Q1, Q1, Accept, Reject }, // Q1 11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao }; 11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const Action transition[NumOfStates][NumOfTokenKinds] = { 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao /* CIE FDE Term Unknown */ 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao { addCIE, reject, addTerm, reject}, // Q0 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao { addCIE, addFDE, addTerm, reject}, // Q1 12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao }; 12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& section = pEhFrame.getSection(); 124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (section.size() == 0x0) { 125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines NullFragment* frag = new NullFragment(); 126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pEhFrame.addFragment(*frag); 127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 128f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 129f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 130f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get file offset and address 13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t file_off = pInput.fileOffset() + section.offset(); 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion* sect_reg = 13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pInput.memArea()->request(file_off, section.size()); 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ConstAddress handler = (ConstAddress)sect_reg->start(); 13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao State cur_state = Q0; 13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao while (Reject != cur_state && Accept != cur_state) { 13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Token token = scan<true>(handler, file_off, *sect_reg); 14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion* entry = pInput.memArea()->request(token.file_off, token.size); 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!transition[cur_state][token.kind](pEhFrame, *entry, token)) { 14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // fail to scan 14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao debug(diag::debug_cannot_scan_eh) << pInput.name(); 14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 14822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao file_off += token.size; 14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao handler += token.size; 15022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 15122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (handler == sect_reg->end()) 15222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cur_state = Accept; 15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else if (handler > sect_reg->end()) { 15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cur_state = Reject; 15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 15622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cur_state = autometa[cur_state][token.kind]; 15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } // end of while 15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (Reject == cur_state) { 16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // fail to parse 16222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao debug(diag::debug_cannot_parse_eh) << pInput.name(); 16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 16422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 16522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 16622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 16722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 16822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::addCIE(EhFrame& pEhFrame, 16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion& pRegion, 17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const EhFrameReader::Token& pToken) 17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip Length, Extended Length and CIE ID. 17322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ConstAddress handler = pRegion.start() + pToken.data_off; 17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ConstAddress cie_end = pRegion.end(); 17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // the version should be 1 or 3 17722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint8_t version = *handler++; 17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (1 != version && 3 != version) { 17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 18122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Set up the Augumentation String 18322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ConstAddress aug_str_front = handler; 18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ConstAddress aug_str_back = static_cast<ConstAddress>( 18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao memchr(aug_str_front, '\0', cie_end - aug_str_front)); 18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == aug_str_back) { 18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Augumentation String field 19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao handler = aug_str_back + 1; 19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Code Alignment Factor 19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!skip_LEB128(&handler, cie_end)) { 19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Data Alignment Factor 19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!skip_LEB128(&handler, cie_end)) { 19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 20122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Return Address Register 20222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (cie_end - handler < 1) { 20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 20522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++handler; 20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines llvm::StringRef augment((const char*)aug_str_front); 208f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // we discard this CIE if the augumentation string is '\0' 210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (0 == augment.size()) { 211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines EhFrame::CIE* cie = new EhFrame::CIE(pRegion); 212f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines cie->setFDEEncode(llvm::dwarf::DW_EH_PE_absptr); 213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pEhFrame.addCIE(*cie); 214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 216f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 21722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // the Augmentation String start with 'eh' is a CIE from gcc before 3.0, 21822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // in LSB Core Spec 3.0RC1. We do not support it. 219f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (augment.size() > 1 && augment[0] == 'e' && augment[1] == 'h') { 22022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 22122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 22222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 22322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // parse the Augmentation String to get the FDE encodeing if 'z' existed 22422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr; 22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if ('z' == augment[0]) { 22622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 22722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Augumentation Data Length 22822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!skip_LEB128(&handler, cie_end)) { 22922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 23022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 23122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 23222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // parse the Augmentation String 23322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (size_t i = 1; i < augment.size(); ++i) { 23422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao switch (augment[i]) { 23522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // LDSA encoding (1 byte) 23622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case 'L': { 23722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (cie_end - handler < 1) { 23822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 23922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 24022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++handler; 24122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 24222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 24322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Two arguments, the first one represents the encoding of the second 24422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // argument (1 byte). The second one is the address of personality 24522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // routine. 24622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case 'P': { 24722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // the first argument 24822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (cie_end - handler < 1) { 24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 25022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 25122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint8_t per_encode = *handler; 25222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++handler; 25322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // get the length of the second argument 25422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t per_length = 0; 25522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (0x60 == (per_encode & 0x60)) { 25622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 25722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao switch (per_encode & 7) { 25922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao default: 26022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 26122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata2: 26222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao per_length = 2; 26322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata4: 26522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao per_length = 4; 26622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 26722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata8: 26822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao per_length = 8; 26922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 27022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_absptr: 27122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao per_length = 4; // pPkg.bitclass / 8; 27222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 27322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 27422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the alignment 27522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (llvm::dwarf::DW_EH_PE_aligned == (per_encode & 0xf0)) { 27622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t per_align = handler - cie_end; 27722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao per_align += per_length - 1; 27822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao per_align &= ~(per_length -1); 27922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (static_cast<uint32_t>(cie_end - handler) < per_align) { 28022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 28122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 28222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao handler += per_align; 28322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 28422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the second argument 28522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (static_cast<uint32_t>(cie_end - handler) < per_length) { 28622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 28722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 28822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao handler += per_length; 28922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 29022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } // end of case 'P' 29122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 29222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FDE encoding (1 byte) 29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case 'R': { 29422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (cie_end - handler < 1) { 29522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 29622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 29722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fde_encoding = *handler; 29822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao switch (fde_encoding & 7) { 29922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata2: 30022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata4: 30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata8: 30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_absptr: 30322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 30422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao default: 30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 30622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 30722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++handler; 30822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 30922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 31022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao default: 31122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 31222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } // end switch 31322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } // the rest chars. 31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } // first char is 'z' 31522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 31622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // create and push back the CIE entry 31722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao EhFrame::CIE* cie = new EhFrame::CIE(pRegion); 31822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cie->setFDEEncode(fde_encoding); 31922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pEhFrame.addCIE(*cie); 32022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 32122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 32222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 32322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::addFDE(EhFrame& pEhFrame, 32422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion& pRegion, 32522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const EhFrameReader::Token& pToken) 32622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 32722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (pToken.data_off == pRegion.size()) 32822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 33022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // create and push back the FDE entry 33122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao EhFrame::FDE* fde = new EhFrame::FDE(pRegion, 33222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pEhFrame.cie_back(), 33322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pToken.data_off); 33422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pEhFrame.addFDE(*fde); 33522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 33622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 33722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 33822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::addTerm(EhFrame& pEhFrame, 33922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion& pRegion, 34022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const EhFrameReader::Token& pToken) 34122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 34222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao RegionFragment* frag = new RegionFragment(pRegion); 34322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pEhFrame.addFragment(*frag); 34422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 34522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 34622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 34722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::reject(EhFrame& pEhFrame, 34822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao MemoryRegion& pRegion, 34922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const EhFrameReader::Token& pToken) 35022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 35122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 35222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 35322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 354