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//===----------------------------------------------------------------------===// 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/EhFrameReader.h" 1022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/NullFragment.h" 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Input.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h" 16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 17f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/ADT/StringRef.h> 18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/Dwarf.h> 19f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/Support/LEB128.h> 2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 2137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 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. 2937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic bool skip_LEB128(EhFrameReader::ConstAddress* pp, 3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines EhFrameReader::ConstAddress pend) { 3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao for (EhFrameReader::ConstAddress p = *pp; p < pend; ++p) { 3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((*p & 0x80) == 0x0) { 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *pp = p + 1; 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// EhFrameReader 4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 4337b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <> 4437b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrameReader::Token EhFrameReader::scan<true>(ConstAddress pHandler, 4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines uint64_t pOffset, 4637b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::StringRef pData) const { 4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Token result; 4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.file_off = pOffset; 4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const uint32_t* data = (const uint32_t*)pHandler; 5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao size_t cur_idx = 0; 5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Length Field 5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t length = data[cur_idx++]; 5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (length == 0x0) { 5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // terminator 5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.kind = Terminator; 5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.data_off = 4; 5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.size = 4; 6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return result; 6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Extended Field 6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t extended = 0x0; 6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (length == 0xFFFFFFFF) { 6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao extended = data[cur_idx++]; 6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao extended <<= 32; 6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao extended |= data[cur_idx++]; 6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.size = extended + 12; 7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.data_off = 16; 71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines // 64-bit obj file still uses 32-bit eh_frame. 7237b74a387bb3993387029859c2d9d051c41c724eStephen Hines assert(false && "We don't support 64-bit eh_frame."); 7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.size = length + 4; 7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.data_off = 8; 7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // ID Field 7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint32_t ID = data[cur_idx++]; 8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (ID == 0x0) 8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.kind = CIE; 8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao result.kind = FDE; 8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return result; 8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8837b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <> 8937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool EhFrameReader::read<32, true>(Input& pInput, EhFrame& pEhFrame) { 9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Alphabet: 9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // {CIE, FDE, CIEt} 9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // 9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Regular Expression: 9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // (CIE FDE*)+ CIEt 9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // 9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Autometa: 9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // S = {Q0, Q1, Q2}, Start = Q0, Accept = Q2 9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // 9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FDE 10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // +---+ 10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // CIE \ / CIEt 10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Q0 -------> Q1 -------> Q2 10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // | / \ ^ 10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // | +---+ | 10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // | CIE | 10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // +-----------------------+ 10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // CIEt 10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const State autometa[NumOfStates][NumOfTokenKinds] = { 10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines // CIE FDE Term Unknown 11037b74a387bb3993387029859c2d9d051c41c724eStephen Hines {Q1, Reject, Accept, Reject}, // Q0 11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines {Q1, Q1, Accept, Reject}, // Q1 11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao }; 11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const Action transition[NumOfStates][NumOfTokenKinds] = { 11537b74a387bb3993387029859c2d9d051c41c724eStephen Hines /* CIE FDE Term Unknown */ 11637b74a387bb3993387029859c2d9d051c41c724eStephen Hines {addCIE, reject, addTerm, reject}, // Q0 11737b74a387bb3993387029859c2d9d051c41c724eStephen Hines {addCIE, addFDE, addTerm, reject}, // Q1 11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao }; 11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& section = pEhFrame.getSection(); 121f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (section.size() == 0x0) { 122f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines NullFragment* frag = new NullFragment(); 123f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pEhFrame.addFragment(*frag); 124f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 125f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 126f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 127f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // get file offset and address 12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t file_off = pInput.fileOffset() + section.offset(); 129f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef sect_reg = 130f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines pInput.memArea()->request(file_off, section.size()); 131f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines ConstAddress handler = (ConstAddress)sect_reg.begin(); 13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao State cur_state = Q0; 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao while (Reject != cur_state && Accept != cur_state) { 135f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines Token token = scan<true>(handler, file_off, sect_reg); 13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::StringRef entry = 13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines pInput.memArea()->request(token.file_off, token.size); 13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 139f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines if (!transition[cur_state][token.kind](pEhFrame, entry, token)) { 14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // fail to scan 14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao debug(diag::debug_cannot_scan_eh) << pInput.name(); 14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao file_off += token.size; 14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao handler += token.size; 14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (handler == sect_reg.end()) { 14922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cur_state = Accept; 15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else if (handler > sect_reg.end()) { 15122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cur_state = Reject; 15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines } else { 15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cur_state = autometa[cur_state][token.kind]; 15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } 15537b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end of while 15622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (Reject == cur_state) { 15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // fail to parse 15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao debug(diag::debug_cannot_parse_eh) << pInput.name(); 16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 16222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 16422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 16522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::addCIE(EhFrame& pEhFrame, 166f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef pRegion, 16737b74a387bb3993387029859c2d9d051c41c724eStephen Hines const EhFrameReader::Token& pToken) { 16822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip Length, Extended Length and CIE ID. 169f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines ConstAddress handler = pRegion.begin() + pToken.data_off; 17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ConstAddress cie_end = pRegion.end(); 171f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines ConstAddress handler_start = handler; 172f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines uint64_t pr_ptr_data_offset = pToken.data_off; 17322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // the version should be 1 or 3 17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint8_t version = *handler++; 17637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (version != 1 && version != 3) { 17722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Set up the Augumentation String 18122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ConstAddress aug_str_front = handler; 18237b74a387bb3993387029859c2d9d051c41c724eStephen Hines ConstAddress aug_str_back = static_cast<ConstAddress>( 18337b74a387bb3993387029859c2d9d051c41c724eStephen Hines memchr(aug_str_front, '\0', cie_end - aug_str_front)); 18437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (aug_str_back == NULL) { 18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Augumentation String field 18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao handler = aug_str_back + 1; 19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Code Alignment Factor 19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!skip_LEB128(&handler, cie_end)) { 19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Data Alignment Factor 19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (!skip_LEB128(&handler, cie_end)) { 19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // skip the Return Address Register 20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (cie_end - handler < 1) { 20122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 20222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++handler; 20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines llvm::StringRef augment((const char*)aug_str_front); 206f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 207f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines // we discard this CIE if the augumentation string is '\0' 20837b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (augment.size() == 0) { 209f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines EhFrame::CIE* cie = new EhFrame::CIE(pRegion); 210f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines cie->setFDEEncode(llvm::dwarf::DW_EH_PE_absptr); 211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines pEhFrame.addCIE(*cie); 212f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines pEhFrame.getCIEMap().insert(std::make_pair(pToken.file_off, cie)); 213f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 214f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 215f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 21622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // the Augmentation String start with 'eh' is a CIE from gcc before 3.0, 21722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // in LSB Core Spec 3.0RC1. We do not support it. 218f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (augment.size() > 1 && augment[0] == 'e' && augment[1] == 'h') { 21922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 22022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 22122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 22222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // parse the Augmentation String to get the FDE encodeing if 'z' existed 22322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr; 224f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines std::string augdata; 225f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines std::string pr_ptr_data; 22637b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (augment[0] == 'z') { 227f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines unsigned offset; 228f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines size_t augdata_size = llvm::decodeULEB128((const uint8_t*)handler, &offset); 229f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines handler += offset; 230f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines augdata = std::string((const char*)handler, augdata_size); 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; 25537b74a387bb3993387029859c2d9d051c41c724eStephen Hines if ((per_encode & 0x60) == 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: 27137b74a387bb3993387029859c2d9d051c41c724eStephen Hines 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; 27837b74a387bb3993387029859c2d9d051c41c724eStephen Hines 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 } 288f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines pr_ptr_data_offset += handler - handler_start; 289f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines pr_ptr_data = std::string((const char*)handler, per_length); 29022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao handler += per_length; 29122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 29237b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end of case 'P' 29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 29422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FDE encoding (1 byte) 29522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case 'R': { 29622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (cie_end - handler < 1) { 29722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 29822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 29922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao fde_encoding = *handler; 30022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao switch (fde_encoding & 7) { 30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata2: 30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata4: 30322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_udata8: 30422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::dwarf::DW_EH_PE_absptr: 30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 30622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao default: 30722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 30822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 30922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ++handler; 31022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao break; 31122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 31222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao default: 31322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 31437b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // end switch 31537b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // the rest chars. 31637b74a387bb3993387029859c2d9d051c41c724eStephen Hines } // first char is 'z' 31722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 31822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // create and push back the CIE entry 31922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao EhFrame::CIE* cie = new EhFrame::CIE(pRegion); 32022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao cie->setFDEEncode(fde_encoding); 321f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines cie->setPersonalityOffset(pr_ptr_data_offset); 322f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines cie->setPersonalityName(pr_ptr_data); 323f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines cie->setAugmentationData(augdata); 32422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pEhFrame.addCIE(*cie); 325f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines pEhFrame.getCIEMap().insert(std::make_pair(pToken.file_off, cie)); 32622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 32722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 32822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::addFDE(EhFrame& pEhFrame, 330f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef pRegion, 33137b74a387bb3993387029859c2d9d051c41c724eStephen Hines const EhFrameReader::Token& pToken) { 33222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (pToken.data_off == pRegion.size()) 33322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return false; 33422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 33537b74a387bb3993387029859c2d9d051c41c724eStephen Hines const int32_t offset = 33637b74a387bb3993387029859c2d9d051c41c724eStephen Hines *(const int32_t*)(pRegion.begin() + pToken.data_off - 4); 33737b74a387bb3993387029859c2d9d051c41c724eStephen Hines size_t cie_offset = 33837b74a387bb3993387029859c2d9d051c41c724eStephen Hines (size_t)((int64_t)(pToken.file_off + 4) - (int32_t)offset); 339f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 340f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines EhFrame::CIEMap::iterator iter = pEhFrame.getCIEMap().find(cie_offset); 341f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines if (iter == pEhFrame.getCIEMap().end()) 342f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines return false; 343f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines 34422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // create and push back the FDE entry 345f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines EhFrame::FDE* fde = new EhFrame::FDE(pRegion, *iter->second); 34622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao pEhFrame.addFDE(*fde); 34722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 34822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 34922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 35022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::addTerm(EhFrame& pEhFrame, 351f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef pRegion, 35237b74a387bb3993387029859c2d9d051c41c724eStephen Hines const EhFrameReader::Token& pToken) { 35322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 35422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 35522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 35622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool EhFrameReader::reject(EhFrame& pEhFrame, 357f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef pRegion, 35837b74a387bb3993387029859c2d9d051c41c724eStephen Hines const EhFrameReader::Token& pToken) { 35922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return true; 36022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 36137b74a387bb3993387029859c2d9d051c41c724eStephen Hines 36237b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 363