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