1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===- EhFrame.cpp --------------------------------------------------------===//
2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//                     The MCLinker Project
4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This file is distributed under the University of Illinois Open Source
6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// License. See LICENSE.TXT for details.
7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
9cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/LD/EhFrame.h>
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Dwarf.h>
13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Host.h>
14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/MC/MCLinker.h>
16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/Target/TargetLDBackend.h>
17cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/Support/MsgHandling.h>
18cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
19affc150dc44fab1911775a49636d0ce85333b634Zonr Changusing namespace mcld;
20affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
21affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//==========================
22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// EhFrame
23affc150dc44fab1911775a49636d0ce85333b634Zonr ChangEhFrame::EhFrame()
24affc150dc44fab1911775a49636d0ce85333b634Zonr Chang : m_fCanRecognizeAll(true) {
25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
26affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
27affc150dc44fab1911775a49636d0ce85333b634Zonr ChangEhFrame::~EhFrame()
28affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
29affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
30affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
31affc150dc44fab1911775a49636d0ce85333b634Zonr Changuint64_t EhFrame::readEhFrame(Layout& pLayout,
32affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                              const TargetLDBackend& pBackend,
33cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                              SectionData& pSD,
3467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                              const Input& pInput,
35affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                              LDSection& pSection,
36affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                              MemoryArea& pArea)
37affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
3867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao  MemoryRegion* region = pArea.request(
3967e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                     pInput.fileOffset() + pSection.offset(), pSection.size());
40affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // an empty .eh_frame
41affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (NULL == region) {
42affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return 0;
43affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
44affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
45affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress eh_start = region->start();
46affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress eh_end = region->end();
47affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress p = eh_start;
48affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
49affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // read the Length filed
50affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint32_t len = readVal(p, pBackend.isLittleEndian());
51affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
52affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // This CIE is a terminator if the Length field is 0, return 0 to handled it
53affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // as an ordinary input.
54affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0 == len) {
55affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pArea.release(region);
56affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return 0;
57affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
58affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
59affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (0xffffffff == len) {
60cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    debug(diag::debug_eh_unsupport) << pInput.name();
61affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pArea.release(region);
62affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    m_fCanRecognizeAll = false;
63affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return 0;
64affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
65affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
66affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // record the order of the CIE and FDE fragments
67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  FragListType frag_list;
68affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
69affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  while (p < eh_end) {
70affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
71affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (eh_end - p < 4) {
72cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      debug(diag::debug_eh_unsupport) << pInput.name();
73affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      m_fCanRecognizeAll = false;
74affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      break;
75affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
76affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // read the Length field
77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    len = readVal(p, pBackend.isLittleEndian());
78affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    p += 4;
79affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
80affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // the zero length entry should be the end of the section
81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (0 == len) {
82affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (p < eh_end) {
83cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        debug(diag::debug_eh_unsupport) << pInput.name();
84affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_fCanRecognizeAll = false;
85affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      break;
87affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (0xffffffff == len) {
89cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      debug(diag::debug_eh_unsupport) << pInput.name();
90affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      m_fCanRecognizeAll = false;
91affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      break;
92affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
93affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
94affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (eh_end - p < 4) {
95cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      debug(diag::debug_eh_unsupport) << pInput.name();
96affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      m_fCanRecognizeAll = false;
97affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      break;
98affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
99affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // compute the section offset of this entry
101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    uint32_t ent_offset = static_cast<uint32_t>(p - eh_start - 4);
102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
103affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // get the MemoryRegion for this entry
10467e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao    MemoryRegion* ent_region = pArea.request(
10567e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao                pInput.fileOffset() + pSection.offset() + ent_offset, len + 4);
106affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
107affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // create and add a CIE or FDE entry
108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    uint32_t id = readVal(p, pBackend.isLittleEndian());
109affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // CIE
110affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (0 == id) {
111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (!addCIE(*ent_region, pBackend, frag_list)) {
112affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_fCanRecognizeAll = false;
113affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        pArea.release(ent_region);
114affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        break;
115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
118affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // FDE
119affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    else {
120affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (!addFDE(*ent_region, pBackend, frag_list)) {
121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        m_fCanRecognizeAll = false;
122affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        pArea.release(ent_region);
123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        break;
124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
125affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
126affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    p += len;
127affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
128affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
129affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!m_fCanRecognizeAll) {
130cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    debug(diag::debug_eh_unsupport) << pInput.name();
131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pArea.release(region);
132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    deleteFragments(frag_list, pArea);
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return 0;
134affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
136affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // append all CIE and FDE fragments to Layout after we successfully read
137affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // this eh_frame
138affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  size_t section_size = 0;
139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  for (FragListType::iterator it = frag_list.begin();
140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang         it != frag_list.end(); ++it)
141affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    section_size += pLayout.appendFragment(**it, pSD, pSection.align());
142affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
143affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pArea.release(region);
144affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return section_size;
145affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
147affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool EhFrame::addCIE(MemoryRegion& pRegion,
148affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                     const TargetLDBackend& pBackend,
149affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                     FragListType& pFragList)
150affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress cie_start = pRegion.start();
152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress cie_end = pRegion.end();
153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress p = cie_start;
154affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // skip the Length (4 byte) and CIE ID (4 byte) fields
156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  p += 8;
157affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
158affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // the version should be 1
159affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (1 != *p) {
160affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
161affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
162affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ++p;
163affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
164affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // get the Augumentation String
165affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress aug_str = p;
166affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress aug_str_end = static_cast<ConstAddress>(
167affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                               memchr(p, '\0', cie_end - p));
168affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
169affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // skip the Augumentation String field
170affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  p = aug_str_end + 1;
171affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
172affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // skip the Code Alignment Factor
173affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!skipLEB128(&p, cie_end)) {
174affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
175affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
176affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // skip the Data Alignment Factor
177affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!skipLEB128(&p, cie_end)) {
178affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
179affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
180affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // skip the Return Address Register
181affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (cie_end - p < 1) {
182affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
183affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
184affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ++p;
185affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
186affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // the Augmentation String start with 'eh' is a CIE from gcc before 3.0,
187affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // in LSB Core Spec 3.0RC1. We do not support it.
188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (aug_str[0] == 'e' && aug_str[1] == 'h') {
189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // parse the Augmentation String to get the FDE encodeing if 'z' existed
193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  std::string aug_str_data;
194affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr;
195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (*aug_str == 'z') {
196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
197affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    aug_str_data += *aug_str;
198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    ++aug_str;
199affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // skip the Augumentation Data Length
201affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (!skipLEB128(&p, cie_end)) {
202affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      return false;
203affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
204affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
205affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    while (aug_str != aug_str_end) {
206affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      switch (*aug_str) {
207affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        default:
208affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          return false;
209affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
210affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // LDSA encoding (1 byte)
211affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        case 'L':
212affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          if (cie_end - p < 1) {
213affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            return false;
214affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
215affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          ++p;
216affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          break;
217affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
218affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // Two arguments, the first one represents the encoding of the second
219affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // argument (1 byte). The second one is the address of personality
220affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // routine.
221affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        case 'P': {
222affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          // the first argument
223affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          if (cie_end - p < 1) {
224affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            return false;
225affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          uint8_t per_encode = *p;
227affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          ++p;
228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          // get the length of the second argument
229affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          uint32_t per_length = 0;
230affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          if (0x60 == (per_encode & 0x60)) {
231affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            return false;
232affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
233affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          switch (per_encode & 7) {
234affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            default:
235affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              return false;
236affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_udata2:
237affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              per_length = 2;
238affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              break;
239affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_udata4:
240affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              per_length = 4;
241affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              break;
242affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_udata8:
243affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              per_length = 8;
244affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              break;
245affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_absptr:
246affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              per_length = pBackend.bitclass() / 8;
247affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              break;
248affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
249affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          // skip the alignment
250affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          if (llvm::dwarf::DW_EH_PE_aligned == (per_encode & 0xf0)) {
251affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            uint32_t per_align = p - cie_end;
252affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            per_align += per_length - 1;
253affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            per_align &= ~(per_length -1);
254affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            if (static_cast<uint32_t>(cie_end - p) < per_align) {
255affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              return false;
256affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            }
257affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            p += per_align;
258affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          // skip the second argument
260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          if (static_cast<uint32_t>(cie_end - p) < per_length) {
261affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            return false;
262affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
263affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          p += per_length;
264affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        }
265affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        break;
266affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
267affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // FDE encoding (1 byte)
268affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        case 'R':
269affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          if (cie_end - p < 1) {
270affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            return false;
271affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
272affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          fde_encoding = *p;
273affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          switch (fde_encoding & 7) {
274affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_udata2:
275affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_udata4:
276affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_udata8:
277affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            case llvm::dwarf::DW_EH_PE_absptr:
278affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              break;
279affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            default:
280affc150dc44fab1911775a49636d0ce85333b634Zonr Chang              return false;
281affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          }
282affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          ++p;
283affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          break;
284affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      } // end switch
285affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      aug_str_data += *aug_str;
286affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      ++aug_str;
287affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    } // end while
288affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
290affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  note(diag::note_eh_cie) << pRegion.size()
291affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                          << aug_str_data
292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                          << (fde_encoding & 7);
293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
294affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // create and push back the CIE entry
295affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  CIE* entry = new CIE(pRegion, fde_encoding);
296affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_CIEs.push_back(entry);
297cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pFragList.push_back(static_cast<Fragment*>(entry));
298affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
299affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
300affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
301affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool EhFrame::addFDE(MemoryRegion& pRegion,
302affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                     const TargetLDBackend& pBackend,
303affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                     FragListType& pFragList)
304affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
305affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress fde_start = pRegion.start();
306affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress fde_end = pRegion.end();
307affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  ConstAddress p = fde_start;
308affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
309affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // skip the Length (4 byte) and CIE Pointer (4 byte) fields
310affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  p += 8;
311affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
312affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // get the entry offset of the PC Begin
313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (fde_end - p < 1) {
314affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  FDE::Offset pc_offset = static_cast<FDE::Offset>(p - fde_start);
317affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
318affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  note(diag::note_eh_fde) << pRegion.size() << pc_offset;
319affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // create and push back the FDE entry
320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  FDE* entry = new FDE(pRegion, **(m_CIEs.end() -1), pc_offset);
321affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  m_FDEs.push_back(entry);
322cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  pFragList.push_back(static_cast<Fragment*>(entry));
323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
324affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
326affc150dc44fab1911775a49636d0ce85333b634Zonr Changuint32_t EhFrame::readVal(ConstAddress pAddr, bool pIsTargetLittleEndian)
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const uint32_t* p = reinterpret_cast<const uint32_t*>(pAddr);
329affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  uint32_t val = *p;
330affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
331affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // byte swapping if the host and target have different endian
332affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (llvm::sys::isLittleEndianHost() != pIsTargetLittleEndian)
333affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    val = bswap32(val);
334affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return val;
335affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
336affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
337affc150dc44fab1911775a49636d0ce85333b634Zonr Changbool EhFrame::skipLEB128(ConstAddress* pp, ConstAddress pend)
338affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
339affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  for (ConstAddress p = *pp; p < pend; ++p) {
340affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (0 == (*p & 0x80)) {
341affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      *pp = p + 1;
342affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      return true;
343affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
344affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
345affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return false;
346affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
347affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
348affc150dc44fab1911775a49636d0ce85333b634Zonr Changvoid EhFrame::deleteFragments(FragListType& pList, MemoryArea& pArea)
349affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
350cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  RegionFragment* frag = NULL;
351affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  for (FragListType::iterator it = pList.begin(); it != pList.end(); ++it) {
352cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    frag = static_cast<RegionFragment*>(*it);
353affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    pArea.release(&(frag->getRegion()));
354affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    delete *it;
355affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
356affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  pList.clear();
357affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
358affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
359