void EHSection::loadFDE(BufReader& reader, uint64_t endPos, CIE* cie) { FDE* fde = new FDE; fde->startAddress = reader.readDwarfPointer(cie->ptrEncoding); fde->length = reader.readDwarfPointer(cie->ptrEncoding); // if ptrEncoding is relative, then in context of length, it is still just a plain number if (*cie->augmentationString == 'z') fde->augmentationDataLength = reader.readLEB128(); else fde->augmentationDataLength = 0; if (strchr(cie->augmentationString, 'L') && cie->lsdaEncoding != 0xff) // DW_EH_PE_omit fde->lsdaPointer = reader.readDwarfPointer(cie->lsdaEncoding); uint64_t instructionsLength = endPos - reader.pos(); const uint8_t* data = reinterpret_cast<const uint8_t*>(reader.readBlock(instructionsLength)); fde->instructions.assign(data, data+instructionsLength); cie->fdes.push_back(fde); }
void EHSection::loadCIE(BufReader& reader, uint64_t endPos, uintptr_t location) { CIE* cie = new CIE; cie->start = reader.pos(); cie->version = reader.read(); cie->augmentationString = reader.readString(); cie->codeAlign = reader.readLEB128(); cie->dataAlign = reader.readLEB128(); if (cie->codeAlign != 1) { std::stringstream ss; ss << "Invalid code alignment: " << int(cie->codeAlign) << std::endl; delete cie; throw std::runtime_error(ss.str()); } if (cie->version == 1) cie->returnRegister = reader.read(); else if (cie->version == 3) cie->returnRegister = reader.readLEB128(); else { std::stringstream ss; ss << "Invalid CIE version: " << int(cie->version) << std::endl; delete cie; throw std::runtime_error(ss.str()); } cie->augmentationDataPresent = false; uint64_t augmentationDataLength, augmentationDataEnd; cie->lsdaEncoding = cie->ptrEncoding = 0xff; for (const char* augP = cie->augmentationString; *augP; augP++) { switch (*augP) { case 'z': cie->augmentationDataPresent = true; augmentationDataLength = reader.readULEB128(); augmentationDataEnd = reader.pos() + augmentationDataLength; break; case 'L': cie->lsdaEncoding = reader.read(); break; case 'R': cie->ptrEncoding = reader.read(); break; case 'P': { uint8_t persEncoding = reader.read(); cie->personality = reader.readDwarfPointer(persEncoding); break; } case 'S': break; default: { std::stringstream ss; ss << "Unsupported character in CIE augmentation string: " << *augP; delete cie; throw std::runtime_error(ss.str()); } } } reader.moveTo(augmentationDataEnd); uint64_t instructionsLength = endPos - reader.pos(); const uint8_t* data = reinterpret_cast<const uint8_t*>(reader.readBlock(instructionsLength)); cie->instructions.assign(data, data+instructionsLength); m_cies.push_back(cie); m_ciePositions[location] = cie; LOG << "Loaded a CIE at " << std::hex << location << std::dec << std::endl; }