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