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