this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Exception handling: CFI register number rewriting for i386

+404 -10
+2
src/dyld/CMakeLists.txt
··· 7 7 endif(COMMAND cmake_policy) 8 8 9 9 set(dyld_SRCS 10 + eh/BufReWriter.cpp 11 + eh/CFIWalker.cpp 10 12 eh/DwarfPointer.cpp 11 13 eh/BufWriter.cpp 12 14 eh/BufReader.cpp
+13
src/dyld/MachOLoader.cpp
··· 665 665 EHSection ehSection; 666 666 void *reworked_eh_data, *original_eh_data; 667 667 668 + // On Darwin/i386, esp and ebp register numbers are swapped 669 + #ifdef __i386__ 670 + static const std::map<int, int> regSwap = { 671 + std::make_pair<int, int>(4, 5), 672 + std::make_pair<int, int>(5, 4) 673 + }; 674 + #endif 675 + 668 676 original_eh_data = (void*) (eh_frame.first + b.slide); 669 677 LOG << "Reworking __eh_frame at " << original_eh_data << std::endl; 670 678 671 679 ehSection.load(original_eh_data, eh_frame.second); 680 + 681 + #ifdef __i386__ 682 + ehSection.swapRegisterNumbers(regSwap); 683 + #endif 684 + 672 685 ehSection.store(&reworked_eh_data, nullptr); 673 686 674 687 LOG << "Registering reworked __eh_frame at " << reworked_eh_data << std::endl;
+48
src/dyld/eh/BufReWriter.cpp
··· 1 + #include "BufReWriter.h" 2 + #include <cassert> 3 + #include <stdexcept> 4 + 5 + BufReWriter::BufReWriter(void* mem, uintptr_t length) 6 + : BufReader(mem, length), m_pLastULEB128(nullptr), m_pLast8(nullptr) 7 + { 8 + } 9 + 10 + uint64_t BufReWriter::readULEB128() 11 + { 12 + m_pLastULEB128 = (uint8_t*) m_pPos; 13 + return BufReader::readULEB128(); 14 + } 15 + 16 + uint8_t BufReWriter::read() 17 + { 18 + m_pLast8 = (uint8_t*) m_pPos; 19 + return BufReader::read(); 20 + } 21 + 22 + void BufReWriter::updateLastULEB128(uint64_t v) 23 + { 24 + assert(m_pLastULEB128 != nullptr); 25 + 26 + uint8_t* pos = m_pLastULEB128; 27 + 28 + do 29 + { 30 + uint8_t byte = v & 0x7f; 31 + v >>= 7; 32 + if (v != 0) 33 + byte |= 0x80; 34 + 35 + if (!(*pos & 0x80) && v != 0) 36 + std::runtime_error("New ULEB128 value didn't fit into the space of the previous value"); 37 + 38 + *pos = byte; 39 + pos++; 40 + } 41 + while (v != 0); 42 + } 43 + 44 + void BufReWriter::updateLast(uint8_t value) 45 + { 46 + assert(m_pLast8 != nullptr); 47 + *m_pLast8 = value; 48 + }
+19
src/dyld/eh/BufReWriter.h
··· 1 + #ifndef BUFREWRITER_H 2 + #define BUFREWRITER_H 3 + #include "BufReader.h" 4 + 5 + // only designed to rewrite ULEB128 values! 6 + class BufReWriter : public BufReader 7 + { 8 + public: 9 + BufReWriter(void* mem, uintptr_t length); 10 + 11 + uint8_t read(); 12 + uint64_t readULEB128(); 13 + void updateLastULEB128(uint64_t value); 14 + void updateLast(uint8_t value); 15 + private: 16 + uint8_t *m_pLastULEB128, *m_pLast8; 17 + }; 18 + 19 + #endif
+2 -2
src/dyld/eh/BufReader.h
··· 59 59 bool atEnd() const { return m_pPos == m_pEnd; } 60 60 uintptr_t pos() const { return reinterpret_cast<uintptr_t>(m_pPos); } 61 61 void moveTo(uintptr_t pos) { m_pPos = reinterpret_cast<const char*>(pos); } 62 - private: 62 + protected: 63 63 void checkRead(size_t bytes) const; 64 - private: 64 + protected: 65 65 const char *m_pStart, *m_pPos, *m_pEnd; 66 66 }; 67 67
+219
src/dyld/eh/CFIWalker.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2013 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include "CFIWalker.h" 21 + #include <sstream> 22 + #include <stdexcept> 23 + #include "log.h" 24 + 25 + CFIWalker::CFIWalker(uint8_t* instructions, uintptr_t length, uint8_t dwarfPtrEncoding) 26 + : m_buffer(instructions, length), m_dwarfPtrEncoding(dwarfPtrEncoding) 27 + { 28 + } 29 + 30 + void CFIWalker::processNextReg(void* opaque, int (*mapRegisterNumber)(void*, int)) 31 + { 32 + uint64_t reg, newReg; 33 + 34 + reg = m_buffer.readULEB128(); 35 + newReg = mapRegisterNumber(opaque, reg); 36 + 37 + if (newReg != reg) 38 + { 39 + LOG << "Updating register number: " << reg << " -> " << newReg << std::endl; 40 + m_buffer.updateLastULEB128(newReg); 41 + } 42 + } 43 + 44 + uint8_t CFIWalker::processMixedInstr(void* opaque, int (*mapRegisterNumber)(void*, int), uint8_t instr) 45 + { 46 + int origRegNo = int(instr) & 0x3f; 47 + int newRegNo = mapRegisterNumber(opaque, origRegNo); 48 + 49 + if (origRegNo != newRegNo) 50 + return (uint8_t) (instr & 0xC0) | newRegNo; 51 + else 52 + return instr; 53 + } 54 + 55 + void CFIWalker::walk(void* opaque, int (*mapRegisterNumber)(void*,int)) 56 + { 57 + while (!m_buffer.atEnd()) 58 + { 59 + const uint8_t instr = m_buffer.read(); 60 + uint64_t len; 61 + 62 + switch (instr) 63 + { 64 + case DW_CFA_nop: 65 + break; 66 + case DW_CFA_advance_loc1: 67 + m_buffer.read(); 68 + break; 69 + case DW_CFA_advance_loc2: 70 + m_buffer.read16(); 71 + break; 72 + case DW_CFA_advance_loc4: 73 + m_buffer.read32(); 74 + break; 75 + case DW_CFA_set_loc: 76 + // read a DWARF pointer with ptrEncoding 77 + m_buffer.readDwarfPointer(m_dwarfPtrEncoding); 78 + break; 79 + case DW_CFA_offset_extended: 80 + // uleb128 reg 81 + processNextReg(opaque, mapRegisterNumber); 82 + // uleb128 offset (*data align factor) 83 + m_buffer.readULEB128(); 84 + break; 85 + case DW_CFA_restore_extended: 86 + // uleb128 reg 87 + processNextReg(opaque, mapRegisterNumber); 88 + // loads up initial value 89 + break; 90 + case DW_CFA_undefined: 91 + // uleb128 reg 92 + processNextReg(opaque, mapRegisterNumber); 93 + // marks register as unused 94 + break; 95 + case DW_CFA_same_value: 96 + // uleb128 reg 97 + processNextReg(opaque, mapRegisterNumber); 98 + break; 99 + case DW_CFA_register: 100 + // uleb128 reg 101 + processNextReg(opaque, mapRegisterNumber); 102 + // uleb128 reg2 103 + processNextReg(opaque, mapRegisterNumber); 104 + break; 105 + case DW_CFA_remember_state: 106 + break; 107 + case DW_CFA_restore_state: 108 + break; 109 + case DW_CFA_def_cfa: 110 + // uleb128 reg 111 + processNextReg(opaque, mapRegisterNumber); 112 + // uleb128 offset 113 + m_buffer.readULEB128(); 114 + break; 115 + case DW_CFA_def_cfa_register: 116 + // uleb128 reg 117 + processNextReg(opaque, mapRegisterNumber); 118 + break; 119 + case DW_CFA_def_cfa_offset: 120 + // uleb128 - drop 121 + m_buffer.readULEB128(); 122 + break; 123 + case DW_CFA_def_cfa_expression: 124 + // uleb128 length 125 + len = m_buffer.readULEB128(); 126 + // add read value to m_pPos 127 + m_buffer.readBlock(size_t(len)); 128 + break; 129 + case DW_CFA_expression: 130 + // uleb128 reg 131 + processNextReg(opaque, mapRegisterNumber); 132 + // uleb128 length 133 + len = m_buffer.readULEB128(); 134 + // add read value to m_pPos 135 + m_buffer.readBlock(size_t(len)); 136 + break; 137 + case DW_CFA_offset_extended_sf: 138 + // uleb128 reg 139 + processNextReg(opaque, mapRegisterNumber); 140 + // uleb128 offset 141 + m_buffer.readULEB128(); 142 + break; 143 + case DW_CFA_def_cfa_sf: 144 + // uleb128 reg 145 + processNextReg(opaque, mapRegisterNumber); 146 + // uleb128 offset 147 + m_buffer.readULEB128(); 148 + break; 149 + case DW_CFA_def_cfa_offset_sf: 150 + // uleb128 offset 151 + m_buffer.readULEB128(); 152 + break; 153 + case DW_CFA_val_offset: 154 + // uleb128 reg 155 + processNextReg(opaque, mapRegisterNumber); 156 + // uleb128 offset 157 + m_buffer.readULEB128(); 158 + break; 159 + case DW_CFA_val_offset_sf: 160 + // uleb128 reg 161 + processNextReg(opaque, mapRegisterNumber); 162 + // uleb128 offset 163 + m_buffer.readULEB128(); 164 + break; 165 + case DW_CFA_val_expression: 166 + // uleb128 reg 167 + processNextReg(opaque, mapRegisterNumber); 168 + // uleb128 length 169 + len = m_buffer.readULEB128(); 170 + // add read value to m_pPos 171 + m_buffer.readBlock(size_t(len)); 172 + break; 173 + //case DW_CFA_low_user: // not in Apple's libunwind 174 + //case DW_CFA_GNU_window_save: // not in Apple's libunwind 175 + case DW_CFA_GNU_args_size: 176 + // uleb128 offset 177 + m_buffer.readULEB128(); 178 + break; 179 + case DW_CFA_GNU_negative_offset_extended: 180 + // uleb128 reg 181 + processNextReg(opaque, mapRegisterNumber); 182 + // uleb128 offset 183 + m_buffer.readULEB128(); 184 + break; 185 + //case DW_CFA_high_user: // not in Apple's libunwind 186 + default: 187 + { 188 + uint8_t op = instr & 0x3f; 189 + switch (instr & 0xC0) 190 + { 191 + case DW_CFA_offset: 192 + { 193 + // op is reg! 194 + uint8_t newInstr = processMixedInstr(opaque, mapRegisterNumber, instr); 195 + m_buffer.updateLast(newInstr); 196 + // uleb128 offset 197 + m_buffer.readULEB128(); 198 + break; 199 + } 200 + case DW_CFA_advance_loc: 201 + break; 202 + case DW_CFA_restore: 203 + { 204 + // op is reg! 205 + uint8_t newInstr = processMixedInstr(opaque, mapRegisterNumber, instr); 206 + m_buffer.updateLast(newInstr); 207 + break; 208 + } 209 + default: 210 + { 211 + std::stringstream ss; 212 + ss << "Unhandled DWARF instruction " << std::hex << instr << std::dec; 213 + throw std::runtime_error(ss.str()); 214 + } 215 + } 216 + } 217 + } 218 + } 219 + }
+79
src/dyld/eh/CFIWalker.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2013 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef CFIWALKER_H 21 + #define CFIWALKER_H 22 + #include <stdint.h> 23 + #include "BufReWriter.h" 24 + 25 + class CFIWalker 26 + { 27 + public: 28 + CFIWalker(uint8_t* instructions, uintptr_t length, uint8_t dwarfPtrEncoding); 29 + 30 + void walk(void* opaque, int (*mapRegisterNumber)(void*, int)); 31 + private: 32 + void processNextReg(void* opaque, int (*mapRegisterNumber)(void*, int)); 33 + uint8_t processMixedInstr(void* opaque, int (*mapRegisterNumber)(void*, int), uint8_t instr); 34 + private: 35 + BufReWriter m_buffer; 36 + uint8_t m_dwarfPtrEncoding; 37 + }; 38 + 39 + enum : uint8_t 40 + { 41 + DW_CFA_advance_loc = 0x40, 42 + DW_CFA_offset = 0x80, 43 + DW_CFA_restore = 0xc0, 44 + DW_CFA_extended = 0, 45 + 46 + DW_CFA_nop = 0x00, 47 + DW_CFA_set_loc = 0x01, 48 + DW_CFA_advance_loc1 = 0x02, 49 + DW_CFA_advance_loc2 = 0x03, 50 + DW_CFA_advance_loc4 = 0x04, 51 + DW_CFA_offset_extended = 0x05, 52 + DW_CFA_restore_extended = 0x06, 53 + DW_CFA_undefined = 0x07, 54 + DW_CFA_same_value = 0x08, 55 + DW_CFA_register = 0x09, 56 + DW_CFA_remember_state = 0x0a, 57 + DW_CFA_restore_state = 0x0b, 58 + DW_CFA_def_cfa = 0x0c, 59 + DW_CFA_def_cfa_register = 0x0d, 60 + DW_CFA_def_cfa_offset = 0x0e, 61 + DW_CFA_def_cfa_expression = 0x0f, 62 + DW_CFA_expression = 0x10, 63 + DW_CFA_offset_extended_sf = 0x11, 64 + DW_CFA_def_cfa_sf = 0x12, 65 + DW_CFA_def_cfa_offset_sf = 0x13, 66 + DW_CFA_val_offset = 0x14, 67 + DW_CFA_val_offset_sf = 0x15, 68 + DW_CFA_val_expression = 0x16, 69 + 70 + DW_CFA_low_user = 0x1c, 71 + DW_CFA_MIPS_advance_loc8 = 0x1d, 72 + DW_CFA_GNU_window_save = 0x2d, 73 + DW_CFA_GNU_args_size = 0x2e, 74 + DW_CFA_GNU_negative_offset_extended = 0x2f, 75 + DW_CFA_high_user = 0x3f 76 + }; 77 + 78 + 79 + #endif
+20 -6
src/dyld/eh/EHSection.cpp
··· 24 24 #include <limits> 25 25 #include <memory> 26 26 #include <cstring> 27 - #include "../../util/log.h" 27 + #include "log.h" 28 + #include "CFIWalker.h" 28 29 29 30 EHSection::EHSection() 30 31 { ··· 362 363 *totalLength64 = writer.pos() - startPos; 363 364 } 364 365 365 - void EHSection::swapRegisterNumbers(const std::vector<std::pair<int, int>>& swapList) 366 + void EHSection::swapRegisterNumbers(const std::map<int, int>& swapList) 366 367 { 367 368 for (CIE* cie : m_cies) 368 369 { 369 - swapRegisterNumbers(cie->instructions, swapList); 370 + swapRegisterNumbers(cie->instructions, swapList, cie->ptrEncoding); 370 371 371 372 for (FDE* fde : cie->fdes) 372 - swapRegisterNumbers(fde->instructions, swapList); 373 + swapRegisterNumbers(fde->instructions, swapList, cie->ptrEncoding); 373 374 } 374 375 } 375 376 376 - void EHSection::swapRegisterNumbers(std::vector<uint8_t>& where, const std::vector<std::pair<int, int>>& swapList) 377 + void EHSection::swapRegisterNumbers(std::vector<uint8_t>& where, const std::map<int, int>& swapList, uint8_t ptrEncoding) 377 378 { 378 - // TODO: 379 + CFIWalker walker(&where[0], where.size(), ptrEncoding); 380 + 381 + walker.walk((void*) &swapList, 382 + [](void* sl, int regNo) -> int 383 + { 384 + const std::map<int, int>* swapList = static_cast<const std::map<int, int>*>(sl); 385 + auto it = swapList->find(regNo); 386 + 387 + if (it != swapList->end()) 388 + return it->second; 389 + else 390 + return regNo; 391 + } 392 + ); 379 393 }
+2 -2
src/dyld/eh/EHSection.h
··· 41 41 // Frees all the internal structures 42 42 void clear(); 43 43 44 - void swapRegisterNumbers(const std::vector<std::pair<int, int>>& swapList); 44 + void swapRegisterNumbers(const std::map<int, int>& swapList); 45 45 private: 46 46 struct CIE; 47 47 struct FDE; ··· 59 59 void storeCIE(BufWriter& writer, CIE* cie); 60 60 void storeFDE(BufWriter& writer, FDE* fde, CIE* cie, uintptr_t cieStart); 61 61 62 - static void swapRegisterNumbers(std::vector<uint8_t>& where, const std::vector<std::pair<int, int>>& swapList); 62 + static void swapRegisterNumbers(std::vector<uint8_t>& where, const std::map<int, int>& swapList, uint8_t ptrEncoding); 63 63 private: 64 64 // Needed for relative pointer adjustments 65 65 uintptr_t m_originalStart, m_originalEnd;