this repo has no description
1
fork

Configure Feed

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

Initial code for GDB JIT interface (#41)

+511 -1
+4
src/dyld/dyld.cpp
··· 20 20 #include <libdyld/MachOMgr.h> 21 21 #include <libdyld/MachOObject.h> 22 22 #include <libdyld/NativeObject.h> 23 + #include <libdyld/gdbjit.h> 23 24 #include <iostream> 24 25 #include <stdexcept> 25 26 #include <cstdlib> ··· 89 90 __prefix_set(path); 90 91 unprefixed_argv0 = __prefix_untranslate_path(argv[1], strlen(argv[1])); 91 92 } 93 + 94 + if (getenv("DYLD_GDBJIT") != nullptr) 95 + Darling::SetupGDBJIT(); 92 96 93 97 if (isELF(argv[1])) 94 98 {
+1
src/libdyld/CMakeLists.txt
··· 40 40 environ.c 41 41 threads.cpp 42 42 VirtualPrefix.cpp 43 + gdbjit.cpp 43 44 ) 44 45 45 46 #if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
+1 -1
src/libdyld/eh/BufWriter.h
··· 28 28 public: 29 29 BufWriter(void* mem, uintptr_t length); 30 30 31 - template<typename T> void writeType(T t) { writeBlock(&t, sizeof(T)); } 31 + template<typename T> void writeType(const T& t) { writeBlock(&t, sizeof(T)); } 32 32 33 33 void writePtr(uintptr_t v) { return writeType<uintptr_t>(v); } 34 34 void writePtrS(intptr_t v) { return writeType<intptr_t>(v); }
+420
src/libdyld/gdbjit.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2016 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 <stdint.h> 21 + #include "MachOMgr.h" 22 + #include "MachOObject.h" 23 + #include "gdbjit.h" 24 + #include <map> 25 + #include <cstring> 26 + #include <memory> 27 + #include <iostream> 28 + #include "eh/BufWriter.h" 29 + 30 + enum jit_actions_t 31 + { 32 + JIT_NOACTION = 0, 33 + JIT_REGISTER_FN, 34 + JIT_UNREGISTER_FN 35 + }; 36 + 37 + struct jit_code_entry 38 + { 39 + struct jit_code_entry *next_entry; 40 + struct jit_code_entry *prev_entry; 41 + uint8_t *symfile_addr; 42 + uint64_t symfile_size; 43 + }; 44 + 45 + struct jit_descriptor 46 + { 47 + uint32_t version; 48 + /* This type should be jit_actions_t, but we use uint32_t 49 + to be explicit about the bitwidth. */ 50 + uint32_t action_flag; 51 + struct jit_code_entry *relevant_entry; 52 + struct jit_code_entry *first_entry; 53 + }; 54 + 55 + /* GDB puts a breakpoint in this function. */ 56 + extern "C" 57 + void __attribute__((noinline)) __jit_debug_register_code() { }; 58 + 59 + /* Make sure to specify the version statically, because the 60 + debugger may check the version before we can set it. */ 61 + extern "C" 62 + struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; 63 + 64 + // MachO loading operates under a mutex, so the following code needs no further locking 65 + // when registering stuff with GDB and so on. 66 + static std::map<Darling::MachOObject*, jit_code_entry*> g_machoToElf; 67 + static void OnMachOLoaded(const struct ::mach_header* mh, intptr_t vmaddr_slide); 68 + static void OnMachOUnloaded(const struct ::mach_header* mh, intptr_t vmaddr_slide); 69 + 70 + void Darling::SetupGDBJIT() 71 + { 72 + Darling::MachOMgr* mgr = Darling::MachOMgr::instance(); 73 + mgr->registerLoadHook(OnMachOLoaded); 74 + mgr->registerUnloadHook(OnMachOUnloaded); 75 + } 76 + 77 + static int MachO2ElfFlags(vm_prot_t prot) 78 + { 79 + int flags = 0; 80 + if (prot & VM_PROT_READ) 81 + flags |= PF_R; 82 + if (prot & VM_PROT_WRITE) 83 + flags |= PF_W; 84 + if (prot & VM_PROT_EXECUTE) 85 + flags |= PF_X; 86 + return flags; 87 + } 88 + 89 + void OnMachOLoaded(const struct ::mach_header* mh, intptr_t vmaddr_slide) 90 + { 91 + Darling::MachOObject* object = Darling::MachOMgr::instance()->objectByHeader(const_cast<struct ::mach_header*>(mh)); 92 + Darling::ELFProducer producer; 93 + MachO* mo; 94 + 95 + mo = object->getMachOFile(); 96 + const std::vector<MachO::Symbol> symbols = mo->symbols(); 97 + 98 + for (const MachO::Symbol& sym : symbols) 99 + { 100 + producer.addSymbol(sym.name.c_str(), (void*)(sym.addr + vmaddr_slide), true, false); 101 + } 102 + 103 + if (mo->is64()) 104 + { 105 + const std::vector<segment_command_64*>& segs = mo->segments64(); 106 + for (const segment_command_64* seg : segs) 107 + { 108 + producer.addSegment(Darling::ELFProducer::Segment { seg->segname, seg->fileoff, (void*)(seg->vmaddr + vmaddr_slide), 109 + seg->vmsize, seg->filesize, MachO2ElfFlags(seg->initprot) }); 110 + } 111 + } 112 + else 113 + { 114 + const std::vector<segment_command*>& segs = mo->segments(); 115 + for (const segment_command* seg : segs) 116 + { 117 + producer.addSegment(Darling::ELFProducer::Segment { seg->segname, seg->fileoff, (void*)(seg->vmaddr + vmaddr_slide), 118 + seg->vmsize, seg->filesize, MachO2ElfFlags(seg->initprot) }); 119 + } 120 + } 121 + 122 + producer.setEHSection(mo->get_eh_frame().first, mo->get_eh_frame().second); 123 + 124 + std::pair<uint8_t*, size_t> elfData = producer.produceElf(); 125 + jit_code_entry* entry = new jit_code_entry; 126 + 127 + entry->symfile_addr = elfData.first; 128 + entry->symfile_size = elfData.second; 129 + 130 + std::ofstream dump("/tmp/test.elf"); 131 + dump.write((char*)entry->symfile_addr, entry->symfile_size); 132 + dump.close(); 133 + 134 + entry->next_entry = __jit_debug_descriptor.first_entry; 135 + if (entry->next_entry) 136 + entry->next_entry->prev_entry = entry; 137 + entry->prev_entry = nullptr; 138 + 139 + g_machoToElf[object] = entry; 140 + 141 + std::cout << "Registering " << object->name() << std::endl; 142 + 143 + if (!__jit_debug_descriptor.first_entry) 144 + __jit_debug_descriptor.first_entry = entry; 145 + 146 + __jit_debug_descriptor.relevant_entry = entry; 147 + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; 148 + __jit_debug_register_code(); 149 + } 150 + 151 + void OnMachOUnloaded(const struct ::mach_header* mh, intptr_t vmaddr_slide) 152 + { 153 + Darling::MachOObject* object = Darling::MachOMgr::instance()->objectByHeader(const_cast<struct ::mach_header*>(mh)); 154 + jit_code_entry* jitEntry; 155 + 156 + std::map<Darling::MachOObject*, jit_code_entry*>::iterator it = g_machoToElf.find(object); 157 + 158 + if (it == g_machoToElf.end()) 159 + return; 160 + 161 + jitEntry = it->second; 162 + 163 + // Remove entry from linked list 164 + if (jitEntry->prev_entry) 165 + jitEntry->prev_entry->next_entry = jitEntry->next_entry; 166 + if (jitEntry->next_entry) 167 + jitEntry->next_entry->prev_entry = jitEntry->prev_entry; 168 + 169 + if (__jit_debug_descriptor.first_entry == jitEntry) 170 + __jit_debug_descriptor.first_entry = nullptr; 171 + 172 + // Signal removal to GDB 173 + __jit_debug_descriptor.relevant_entry = jitEntry; 174 + __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; 175 + __jit_debug_register_code(); 176 + 177 + g_machoToElf.erase(it); 178 + delete [] jitEntry->symfile_addr; 179 + delete jitEntry; 180 + } 181 + 182 + Darling::ELFProducer::ELFProducer() 183 + { 184 + addString(""); 185 + m_dotSymtab = addString(".symtab"); 186 + m_dotStrtab = addString(".strtab"); 187 + m_dotText = addString(".text"); 188 + // m_dotEhframe = addString(".eh_frame"); 189 + 190 + ElfW(Shdr) shdr; 191 + 192 + memset(&shdr, 0, sizeof(shdr)); 193 + shdr.sh_type = SHT_NULL; 194 + addSection(shdr); 195 + } 196 + 197 + void Darling::ELFProducer::addSymbol(const char* name, void* addr, bool function, bool local) 198 + { 199 + ElfW(Sym) sym; 200 + 201 + sym.st_name = addString(name); 202 + sym.st_value = uintptr_t(addr); 203 + sym.st_info = ELF32_ST_INFO(local ? STB_LOCAL : STB_GLOBAL, function ? STT_FUNC : STT_OBJECT); 204 + sym.st_shndx = SHN_ABS; 205 + sym.st_other = 0; 206 + sym.st_size = 0x100; 207 + 208 + m_symbols.push_back(sym); 209 + } 210 + 211 + void Darling::ELFProducer::addSegment(Segment seg) 212 + { 213 + m_segments.push_back(seg); 214 + } 215 + 216 + void Darling::ELFProducer::setEHSection(uintptr_t addr, uintptr_t size) 217 + { 218 + m_ehAddr = addr; 219 + m_ehSize = size; 220 + } 221 + 222 + uintptr_t Darling::ELFProducer::addString(const char* str) 223 + { 224 + uintptr_t offset = m_stringTable.size(); 225 + m_stringTable.insert(m_stringTable.end(), str, str + strlen(str) + 1); 226 + return offset; 227 + } 228 + 229 + template <typename T> 230 + inline static size_t pushStruct(std::vector<uint8_t>& buf, const T& _struct) 231 + { 232 + size_t off = buf.size(); 233 + buf.insert(buf.end(), reinterpret_cast<const uint8_t*>(&_struct), reinterpret_cast<const uint8_t*>((&_struct) + 1)); 234 + return off; 235 + } 236 + 237 + std::pair<uint8_t*,size_t> Darling::ELFProducer::produceElf() 238 + { 239 + std::unique_ptr<BufWriter> bufWriter; 240 + size_t memSize; 241 + uint8_t* mem; 242 + 243 + memSize = sizeof(ElfW(Ehdr)); 244 + memSize += m_stringTable.size(); 245 + memSize += 5*sizeof(ElfW(Shdr)); 246 + memSize += sizeof(ElfW(Sym)) * (2+m_symbols.size()); 247 + 248 + mem = new uint8_t[memSize]; 249 + bufWriter.reset(new BufWriter(mem, memSize)); 250 + 251 + ElfW(Ehdr) elfHeader, *elfHeaderPtr; 252 + 253 + elfHeader.e_ident[EI_MAG0] = ELFMAG0; 254 + elfHeader.e_ident[EI_MAG1] = ELFMAG1; 255 + elfHeader.e_ident[EI_MAG2] = ELFMAG2; 256 + elfHeader.e_ident[EI_MAG3] = ELFMAG3; 257 + #ifdef __x86_64__ 258 + elfHeader.e_ident[EI_CLASS] = ELFCLASS64; 259 + #else 260 + elfHeader.e_ident[EI_CLASS] = ELFCLASS32; 261 + #endif 262 + 263 + elfHeader.e_ident[EI_DATA] = ELFDATA2LSB; 264 + elfHeader.e_ident[EI_VERSION] = EV_CURRENT; 265 + elfHeader.e_ident[EI_OSABI] = ELFOSABI_GNU; 266 + elfHeader.e_ident[EI_ABIVERSION] = 0; 267 + 268 + #if defined(__x86_64__) 269 + elfHeader.e_machine = EM_X86_64; 270 + #elif defined(__i386__) 271 + elfHeader.e_machine = EM_386; 272 + #elif defined(__arm__) 273 + elfHeader.e_machine = EM_ARM; 274 + #else 275 + # warning Add support for your arch here 276 + elfHeader.e_machine = 0; 277 + #endif 278 + 279 + elfHeader.e_type = ET_DYN; 280 + elfHeader.e_entry = 0; 281 + elfHeader.e_flags = 0; 282 + elfHeader.e_phoff = 0; //sizeof(elfHeader); 283 + elfHeader.e_phnum = 0; //m_segments.size() /*+ (m_ehSize ? 1 : 0)*/; 284 + elfHeader.e_phentsize = sizeof(ElfW(Phdr)); 285 + elfHeader.e_shentsize = sizeof(ElfW(Shdr)); 286 + elfHeader.e_shstrndx = 2; // string section 287 + elfHeader.e_shnum = 4 /*+ (m_ehSize ? 1 : 0)*/; // string table + symbol table 288 + elfHeader.e_ehsize = sizeof(elfHeader); 289 + 290 + bufWriter->writeType(elfHeader); 291 + 292 + const Segment* textSegment = nullptr; 293 + for (const Segment& seg : m_segments) 294 + { 295 + if (strcmp(seg.name, "__TEXT") == 0) 296 + textSegment = &seg; 297 + } 298 + 299 + elfHeaderPtr = (ElfW(Ehdr)*) mem; 300 + elfHeaderPtr->e_shoff = bufWriter->relativePos(); 301 + 302 + ElfW(Shdr)* symtab; 303 + 304 + { 305 + ElfW(Shdr) shdr; 306 + 307 + memset(&shdr, 0, sizeof(shdr)); 308 + shdr.sh_type = SHT_NULL; 309 + bufWriter->writeType(shdr); 310 + 311 + shdr.sh_name = m_dotSymtab; 312 + shdr.sh_type = SHT_SYMTAB; 313 + shdr.sh_entsize = sizeof(ElfW(Sym)); 314 + shdr.sh_size = shdr.sh_entsize * (m_symbols.size() + 2); 315 + shdr.sh_addr = 0; 316 + shdr.sh_offset = bufWriter->relativePos() + 3*sizeof(shdr) + m_stringTable.size(); // after this shdr and the string table 317 + shdr.sh_flags = SHF_ALLOC; 318 + shdr.sh_addralign = 0; 319 + shdr.sh_link = 2; // which string table section 320 + shdr.sh_info = 0; 321 + 322 + symtab = (ElfW(Shdr)*) bufWriter->posPtr(); 323 + bufWriter->writeType(shdr); 324 + } 325 + 326 + { 327 + ElfW(Shdr) shdr; 328 + 329 + shdr.sh_name = m_dotStrtab; 330 + shdr.sh_type = SHT_STRTAB; 331 + shdr.sh_size = m_stringTable.size(); 332 + shdr.sh_addr = 0; 333 + shdr.sh_offset = bufWriter->relativePos() + 2*sizeof(shdr); // after this and next shdr 334 + shdr.sh_entsize = 0; 335 + shdr.sh_flags = 0; 336 + shdr.sh_link = 0; 337 + shdr.sh_addralign = 0; 338 + shdr.sh_link = 0; 339 + shdr.sh_info = 0; 340 + 341 + bufWriter->writeType(shdr); 342 + } 343 + 344 + if (textSegment != nullptr) 345 + { 346 + ElfW(Shdr) shdr; 347 + 348 + shdr.sh_name = m_dotText; 349 + shdr.sh_type = SHT_PROGBITS; 350 + shdr.sh_size = textSegment->memSize; 351 + shdr.sh_addr = uintptr_t(textSegment->vaddr); 352 + shdr.sh_offset = 0; 353 + shdr.sh_entsize = 0; 354 + shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; 355 + shdr.sh_link = 0; 356 + shdr.sh_addralign = 1; 357 + shdr.sh_link = 0; 358 + shdr.sh_info = 0; 359 + 360 + bufWriter->writeType(shdr); 361 + } 362 + 363 + /* 364 + if (m_ehSize) 365 + { 366 + ElfW(Shdr) shdr; 367 + 368 + shdr.sh_name = m_dotEhframe; 369 + shdr.sh_type = SHT_PROGBITS; 370 + shdr.sh_size = m_ehSize; 371 + shdr.sh_addr = uintptr_t(m_ehAddr); 372 + shdr.sh_offset = 0; 373 + shdr.sh_entsize = 0; 374 + shdr.sh_flags = SHF_ALLOC; 375 + shdr.sh_link = 0; 376 + shdr.sh_addralign = 1; 377 + shdr.sh_link = 0; 378 + shdr.sh_info = 0; 379 + 380 + bufWriter->writeType(shdr); 381 + } 382 + */ 383 + 384 + bufWriter->writeBlock(&m_stringTable[0], m_stringTable.size()); 385 + symtab->sh_addr = (uintptr_t) bufWriter->posPtr(); 386 + 387 + ElfW(Sym) sym; 388 + 389 + sym.st_name = 0; 390 + sym.st_value = 0; 391 + sym.st_info = ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE); 392 + sym.st_shndx = 0; 393 + sym.st_other = 0; 394 + sym.st_size = 0; 395 + 396 + bufWriter->writeType(sym); 397 + 398 + sym.st_name = 0; 399 + sym.st_value = 0; 400 + sym.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION); 401 + sym.st_shndx = 3; 402 + sym.st_other = 0; 403 + 404 + bufWriter->writeType(sym); 405 + 406 + for (ElfW(Sym) sym : m_symbols) 407 + { 408 + sym.st_shndx = 3; // .text section 409 + // sym.st_value -= uintptr_t(textSegment->vaddr); 410 + bufWriter->writeType(sym); 411 + } 412 + 413 + return std::make_pair(mem, memSize); 414 + } 415 + 416 + void Darling::ELFProducer::addSection(const ElfW(Shdr)& section, const std::vector<uint8_t>& data) 417 + { 418 + Section sect { section, data }; 419 + m_sections.push_back(sect); 420 + }
+85
src/libdyld/gdbjit.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2016 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 + #ifndef GDBJIT_H 20 + #define GDBJIT_H 21 + #include <vector> 22 + #include <stdint.h> 23 + #include <elf.h> 24 + 25 + #ifndef ElfW 26 + #ifdef __x86_64__ 27 + # define ElfW(name) Elf64_##name 28 + #else 29 + # define ElfW(name) Elf32_##name 30 + #endif 31 + #endif 32 + 33 + namespace Darling 34 + { 35 + // Prepare for supplying information to GDB through its JIT interface 36 + // (although we're surely no JIT compiler) 37 + void SetupGDBJIT(); 38 + 39 + class ELFProducer 40 + { 41 + public: 42 + struct Segment 43 + { 44 + const char* name; 45 + uintptr_t offsetInFile; 46 + void* vaddr; 47 + uintptr_t memSize; 48 + uintptr_t fileSize; 49 + int flags; 50 + }; 51 + 52 + ELFProducer(); 53 + void addSymbol(const char* name, void* addr, bool function, bool local); 54 + void addSegment(Segment seg); 55 + void setEHSection(uintptr_t addr, uintptr_t size); 56 + std::pair<uint8_t*,size_t> produceElf(); 57 + private: 58 + uintptr_t addString(const char* str); 59 + void addSection(const ElfW(Shdr)& section, const std::vector<uint8_t>& data = std::vector<uint8_t>()); 60 + private: 61 + std::vector<char> m_stringTable; 62 + 63 + struct Symbol 64 + { 65 + uintptr_t name; 66 + void* addr; 67 + bool function, local; 68 + }; 69 + std::vector<ElfW(Sym)> m_symbols; 70 + std::vector<Segment> m_segments; 71 + 72 + struct Section 73 + { 74 + ElfW(Shdr) hdr; 75 + std::vector<uint8_t> data; 76 + }; 77 + std::vector<Section> m_sections; 78 + 79 + uintptr_t m_ehAddr = 0, m_ehSize = 0; 80 + uintptr_t m_dotSymtab, m_dotStrtab, m_dotText, m_dotEhframe; 81 + }; 82 + } 83 + 84 + #endif /* GDBJIT_H */ 85 +