···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2016 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include <stdint.h>
2121+#include "MachOMgr.h"
2222+#include "MachOObject.h"
2323+#include "gdbjit.h"
2424+#include <map>
2525+#include <cstring>
2626+#include <memory>
2727+#include <iostream>
2828+#include "eh/BufWriter.h"
2929+3030+enum jit_actions_t
3131+{
3232+ JIT_NOACTION = 0,
3333+ JIT_REGISTER_FN,
3434+ JIT_UNREGISTER_FN
3535+};
3636+3737+struct jit_code_entry
3838+{
3939+ struct jit_code_entry *next_entry;
4040+ struct jit_code_entry *prev_entry;
4141+ uint8_t *symfile_addr;
4242+ uint64_t symfile_size;
4343+};
4444+4545+struct jit_descriptor
4646+{
4747+ uint32_t version;
4848+ /* This type should be jit_actions_t, but we use uint32_t
4949+ to be explicit about the bitwidth. */
5050+ uint32_t action_flag;
5151+ struct jit_code_entry *relevant_entry;
5252+ struct jit_code_entry *first_entry;
5353+};
5454+5555+/* GDB puts a breakpoint in this function. */
5656+extern "C"
5757+void __attribute__((noinline)) __jit_debug_register_code() { };
5858+5959+/* Make sure to specify the version statically, because the
6060+ debugger may check the version before we can set it. */
6161+extern "C"
6262+struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
6363+6464+// MachO loading operates under a mutex, so the following code needs no further locking
6565+// when registering stuff with GDB and so on.
6666+static std::map<Darling::MachOObject*, jit_code_entry*> g_machoToElf;
6767+static void OnMachOLoaded(const struct ::mach_header* mh, intptr_t vmaddr_slide);
6868+static void OnMachOUnloaded(const struct ::mach_header* mh, intptr_t vmaddr_slide);
6969+7070+void Darling::SetupGDBJIT()
7171+{
7272+ Darling::MachOMgr* mgr = Darling::MachOMgr::instance();
7373+ mgr->registerLoadHook(OnMachOLoaded);
7474+ mgr->registerUnloadHook(OnMachOUnloaded);
7575+}
7676+7777+static int MachO2ElfFlags(vm_prot_t prot)
7878+{
7979+ int flags = 0;
8080+ if (prot & VM_PROT_READ)
8181+ flags |= PF_R;
8282+ if (prot & VM_PROT_WRITE)
8383+ flags |= PF_W;
8484+ if (prot & VM_PROT_EXECUTE)
8585+ flags |= PF_X;
8686+ return flags;
8787+}
8888+8989+void OnMachOLoaded(const struct ::mach_header* mh, intptr_t vmaddr_slide)
9090+{
9191+ Darling::MachOObject* object = Darling::MachOMgr::instance()->objectByHeader(const_cast<struct ::mach_header*>(mh));
9292+ Darling::ELFProducer producer;
9393+ MachO* mo;
9494+9595+ mo = object->getMachOFile();
9696+ const std::vector<MachO::Symbol> symbols = mo->symbols();
9797+9898+ for (const MachO::Symbol& sym : symbols)
9999+ {
100100+ producer.addSymbol(sym.name.c_str(), (void*)(sym.addr + vmaddr_slide), true, false);
101101+ }
102102+103103+ if (mo->is64())
104104+ {
105105+ const std::vector<segment_command_64*>& segs = mo->segments64();
106106+ for (const segment_command_64* seg : segs)
107107+ {
108108+ producer.addSegment(Darling::ELFProducer::Segment { seg->segname, seg->fileoff, (void*)(seg->vmaddr + vmaddr_slide),
109109+ seg->vmsize, seg->filesize, MachO2ElfFlags(seg->initprot) });
110110+ }
111111+ }
112112+ else
113113+ {
114114+ const std::vector<segment_command*>& segs = mo->segments();
115115+ for (const segment_command* seg : segs)
116116+ {
117117+ producer.addSegment(Darling::ELFProducer::Segment { seg->segname, seg->fileoff, (void*)(seg->vmaddr + vmaddr_slide),
118118+ seg->vmsize, seg->filesize, MachO2ElfFlags(seg->initprot) });
119119+ }
120120+ }
121121+122122+ producer.setEHSection(mo->get_eh_frame().first, mo->get_eh_frame().second);
123123+124124+ std::pair<uint8_t*, size_t> elfData = producer.produceElf();
125125+ jit_code_entry* entry = new jit_code_entry;
126126+127127+ entry->symfile_addr = elfData.first;
128128+ entry->symfile_size = elfData.second;
129129+130130+ std::ofstream dump("/tmp/test.elf");
131131+ dump.write((char*)entry->symfile_addr, entry->symfile_size);
132132+ dump.close();
133133+134134+ entry->next_entry = __jit_debug_descriptor.first_entry;
135135+ if (entry->next_entry)
136136+ entry->next_entry->prev_entry = entry;
137137+ entry->prev_entry = nullptr;
138138+139139+ g_machoToElf[object] = entry;
140140+141141+ std::cout << "Registering " << object->name() << std::endl;
142142+143143+ if (!__jit_debug_descriptor.first_entry)
144144+ __jit_debug_descriptor.first_entry = entry;
145145+146146+ __jit_debug_descriptor.relevant_entry = entry;
147147+ __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
148148+ __jit_debug_register_code();
149149+}
150150+151151+void OnMachOUnloaded(const struct ::mach_header* mh, intptr_t vmaddr_slide)
152152+{
153153+ Darling::MachOObject* object = Darling::MachOMgr::instance()->objectByHeader(const_cast<struct ::mach_header*>(mh));
154154+ jit_code_entry* jitEntry;
155155+156156+ std::map<Darling::MachOObject*, jit_code_entry*>::iterator it = g_machoToElf.find(object);
157157+158158+ if (it == g_machoToElf.end())
159159+ return;
160160+161161+ jitEntry = it->second;
162162+163163+ // Remove entry from linked list
164164+ if (jitEntry->prev_entry)
165165+ jitEntry->prev_entry->next_entry = jitEntry->next_entry;
166166+ if (jitEntry->next_entry)
167167+ jitEntry->next_entry->prev_entry = jitEntry->prev_entry;
168168+169169+ if (__jit_debug_descriptor.first_entry == jitEntry)
170170+ __jit_debug_descriptor.first_entry = nullptr;
171171+172172+ // Signal removal to GDB
173173+ __jit_debug_descriptor.relevant_entry = jitEntry;
174174+ __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
175175+ __jit_debug_register_code();
176176+177177+ g_machoToElf.erase(it);
178178+ delete [] jitEntry->symfile_addr;
179179+ delete jitEntry;
180180+}
181181+182182+Darling::ELFProducer::ELFProducer()
183183+{
184184+ addString("");
185185+ m_dotSymtab = addString(".symtab");
186186+ m_dotStrtab = addString(".strtab");
187187+ m_dotText = addString(".text");
188188+ // m_dotEhframe = addString(".eh_frame");
189189+190190+ ElfW(Shdr) shdr;
191191+192192+ memset(&shdr, 0, sizeof(shdr));
193193+ shdr.sh_type = SHT_NULL;
194194+ addSection(shdr);
195195+}
196196+197197+void Darling::ELFProducer::addSymbol(const char* name, void* addr, bool function, bool local)
198198+{
199199+ ElfW(Sym) sym;
200200+201201+ sym.st_name = addString(name);
202202+ sym.st_value = uintptr_t(addr);
203203+ sym.st_info = ELF32_ST_INFO(local ? STB_LOCAL : STB_GLOBAL, function ? STT_FUNC : STT_OBJECT);
204204+ sym.st_shndx = SHN_ABS;
205205+ sym.st_other = 0;
206206+ sym.st_size = 0x100;
207207+208208+ m_symbols.push_back(sym);
209209+}
210210+211211+void Darling::ELFProducer::addSegment(Segment seg)
212212+{
213213+ m_segments.push_back(seg);
214214+}
215215+216216+void Darling::ELFProducer::setEHSection(uintptr_t addr, uintptr_t size)
217217+{
218218+ m_ehAddr = addr;
219219+ m_ehSize = size;
220220+}
221221+222222+uintptr_t Darling::ELFProducer::addString(const char* str)
223223+{
224224+ uintptr_t offset = m_stringTable.size();
225225+ m_stringTable.insert(m_stringTable.end(), str, str + strlen(str) + 1);
226226+ return offset;
227227+}
228228+229229+template <typename T>
230230+inline static size_t pushStruct(std::vector<uint8_t>& buf, const T& _struct)
231231+{
232232+ size_t off = buf.size();
233233+ buf.insert(buf.end(), reinterpret_cast<const uint8_t*>(&_struct), reinterpret_cast<const uint8_t*>((&_struct) + 1));
234234+ return off;
235235+}
236236+237237+std::pair<uint8_t*,size_t> Darling::ELFProducer::produceElf()
238238+{
239239+ std::unique_ptr<BufWriter> bufWriter;
240240+ size_t memSize;
241241+ uint8_t* mem;
242242+243243+ memSize = sizeof(ElfW(Ehdr));
244244+ memSize += m_stringTable.size();
245245+ memSize += 5*sizeof(ElfW(Shdr));
246246+ memSize += sizeof(ElfW(Sym)) * (2+m_symbols.size());
247247+248248+ mem = new uint8_t[memSize];
249249+ bufWriter.reset(new BufWriter(mem, memSize));
250250+251251+ ElfW(Ehdr) elfHeader, *elfHeaderPtr;
252252+253253+ elfHeader.e_ident[EI_MAG0] = ELFMAG0;
254254+ elfHeader.e_ident[EI_MAG1] = ELFMAG1;
255255+ elfHeader.e_ident[EI_MAG2] = ELFMAG2;
256256+ elfHeader.e_ident[EI_MAG3] = ELFMAG3;
257257+#ifdef __x86_64__
258258+ elfHeader.e_ident[EI_CLASS] = ELFCLASS64;
259259+#else
260260+ elfHeader.e_ident[EI_CLASS] = ELFCLASS32;
261261+#endif
262262+263263+ elfHeader.e_ident[EI_DATA] = ELFDATA2LSB;
264264+ elfHeader.e_ident[EI_VERSION] = EV_CURRENT;
265265+ elfHeader.e_ident[EI_OSABI] = ELFOSABI_GNU;
266266+ elfHeader.e_ident[EI_ABIVERSION] = 0;
267267+268268+#if defined(__x86_64__)
269269+ elfHeader.e_machine = EM_X86_64;
270270+#elif defined(__i386__)
271271+ elfHeader.e_machine = EM_386;
272272+#elif defined(__arm__)
273273+ elfHeader.e_machine = EM_ARM;
274274+#else
275275+# warning Add support for your arch here
276276+ elfHeader.e_machine = 0;
277277+#endif
278278+279279+ elfHeader.e_type = ET_DYN;
280280+ elfHeader.e_entry = 0;
281281+ elfHeader.e_flags = 0;
282282+ elfHeader.e_phoff = 0; //sizeof(elfHeader);
283283+ elfHeader.e_phnum = 0; //m_segments.size() /*+ (m_ehSize ? 1 : 0)*/;
284284+ elfHeader.e_phentsize = sizeof(ElfW(Phdr));
285285+ elfHeader.e_shentsize = sizeof(ElfW(Shdr));
286286+ elfHeader.e_shstrndx = 2; // string section
287287+ elfHeader.e_shnum = 4 /*+ (m_ehSize ? 1 : 0)*/; // string table + symbol table
288288+ elfHeader.e_ehsize = sizeof(elfHeader);
289289+290290+ bufWriter->writeType(elfHeader);
291291+292292+ const Segment* textSegment = nullptr;
293293+ for (const Segment& seg : m_segments)
294294+ {
295295+ if (strcmp(seg.name, "__TEXT") == 0)
296296+ textSegment = &seg;
297297+ }
298298+299299+ elfHeaderPtr = (ElfW(Ehdr)*) mem;
300300+ elfHeaderPtr->e_shoff = bufWriter->relativePos();
301301+302302+ ElfW(Shdr)* symtab;
303303+304304+ {
305305+ ElfW(Shdr) shdr;
306306+307307+ memset(&shdr, 0, sizeof(shdr));
308308+ shdr.sh_type = SHT_NULL;
309309+ bufWriter->writeType(shdr);
310310+311311+ shdr.sh_name = m_dotSymtab;
312312+ shdr.sh_type = SHT_SYMTAB;
313313+ shdr.sh_entsize = sizeof(ElfW(Sym));
314314+ shdr.sh_size = shdr.sh_entsize * (m_symbols.size() + 2);
315315+ shdr.sh_addr = 0;
316316+ shdr.sh_offset = bufWriter->relativePos() + 3*sizeof(shdr) + m_stringTable.size(); // after this shdr and the string table
317317+ shdr.sh_flags = SHF_ALLOC;
318318+ shdr.sh_addralign = 0;
319319+ shdr.sh_link = 2; // which string table section
320320+ shdr.sh_info = 0;
321321+322322+ symtab = (ElfW(Shdr)*) bufWriter->posPtr();
323323+ bufWriter->writeType(shdr);
324324+ }
325325+326326+ {
327327+ ElfW(Shdr) shdr;
328328+329329+ shdr.sh_name = m_dotStrtab;
330330+ shdr.sh_type = SHT_STRTAB;
331331+ shdr.sh_size = m_stringTable.size();
332332+ shdr.sh_addr = 0;
333333+ shdr.sh_offset = bufWriter->relativePos() + 2*sizeof(shdr); // after this and next shdr
334334+ shdr.sh_entsize = 0;
335335+ shdr.sh_flags = 0;
336336+ shdr.sh_link = 0;
337337+ shdr.sh_addralign = 0;
338338+ shdr.sh_link = 0;
339339+ shdr.sh_info = 0;
340340+341341+ bufWriter->writeType(shdr);
342342+ }
343343+344344+ if (textSegment != nullptr)
345345+ {
346346+ ElfW(Shdr) shdr;
347347+348348+ shdr.sh_name = m_dotText;
349349+ shdr.sh_type = SHT_PROGBITS;
350350+ shdr.sh_size = textSegment->memSize;
351351+ shdr.sh_addr = uintptr_t(textSegment->vaddr);
352352+ shdr.sh_offset = 0;
353353+ shdr.sh_entsize = 0;
354354+ shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
355355+ shdr.sh_link = 0;
356356+ shdr.sh_addralign = 1;
357357+ shdr.sh_link = 0;
358358+ shdr.sh_info = 0;
359359+360360+ bufWriter->writeType(shdr);
361361+ }
362362+363363+ /*
364364+ if (m_ehSize)
365365+ {
366366+ ElfW(Shdr) shdr;
367367+368368+ shdr.sh_name = m_dotEhframe;
369369+ shdr.sh_type = SHT_PROGBITS;
370370+ shdr.sh_size = m_ehSize;
371371+ shdr.sh_addr = uintptr_t(m_ehAddr);
372372+ shdr.sh_offset = 0;
373373+ shdr.sh_entsize = 0;
374374+ shdr.sh_flags = SHF_ALLOC;
375375+ shdr.sh_link = 0;
376376+ shdr.sh_addralign = 1;
377377+ shdr.sh_link = 0;
378378+ shdr.sh_info = 0;
379379+380380+ bufWriter->writeType(shdr);
381381+ }
382382+ */
383383+384384+ bufWriter->writeBlock(&m_stringTable[0], m_stringTable.size());
385385+ symtab->sh_addr = (uintptr_t) bufWriter->posPtr();
386386+387387+ ElfW(Sym) sym;
388388+389389+ sym.st_name = 0;
390390+ sym.st_value = 0;
391391+ sym.st_info = ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE);
392392+ sym.st_shndx = 0;
393393+ sym.st_other = 0;
394394+ sym.st_size = 0;
395395+396396+ bufWriter->writeType(sym);
397397+398398+ sym.st_name = 0;
399399+ sym.st_value = 0;
400400+ sym.st_info = ELF32_ST_INFO(STB_LOCAL, STT_SECTION);
401401+ sym.st_shndx = 3;
402402+ sym.st_other = 0;
403403+404404+ bufWriter->writeType(sym);
405405+406406+ for (ElfW(Sym) sym : m_symbols)
407407+ {
408408+ sym.st_shndx = 3; // .text section
409409+ // sym.st_value -= uintptr_t(textSegment->vaddr);
410410+ bufWriter->writeType(sym);
411411+ }
412412+413413+ return std::make_pair(mem, memSize);
414414+}
415415+416416+void Darling::ELFProducer::addSection(const ElfW(Shdr)& section, const std::vector<uint8_t>& data)
417417+{
418418+ Section sect { section, data };
419419+ m_sections.push_back(sect);
420420+}
+85
src/libdyld/gdbjit.h
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2016 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+#ifndef GDBJIT_H
2020+#define GDBJIT_H
2121+#include <vector>
2222+#include <stdint.h>
2323+#include <elf.h>
2424+2525+#ifndef ElfW
2626+#ifdef __x86_64__
2727+# define ElfW(name) Elf64_##name
2828+#else
2929+# define ElfW(name) Elf32_##name
3030+#endif
3131+#endif
3232+3333+namespace Darling
3434+{
3535+ // Prepare for supplying information to GDB through its JIT interface
3636+ // (although we're surely no JIT compiler)
3737+ void SetupGDBJIT();
3838+3939+ class ELFProducer
4040+ {
4141+ public:
4242+ struct Segment
4343+ {
4444+ const char* name;
4545+ uintptr_t offsetInFile;
4646+ void* vaddr;
4747+ uintptr_t memSize;
4848+ uintptr_t fileSize;
4949+ int flags;
5050+ };
5151+5252+ ELFProducer();
5353+ void addSymbol(const char* name, void* addr, bool function, bool local);
5454+ void addSegment(Segment seg);
5555+ void setEHSection(uintptr_t addr, uintptr_t size);
5656+ std::pair<uint8_t*,size_t> produceElf();
5757+ private:
5858+ uintptr_t addString(const char* str);
5959+ void addSection(const ElfW(Shdr)& section, const std::vector<uint8_t>& data = std::vector<uint8_t>());
6060+ private:
6161+ std::vector<char> m_stringTable;
6262+6363+ struct Symbol
6464+ {
6565+ uintptr_t name;
6666+ void* addr;
6767+ bool function, local;
6868+ };
6969+ std::vector<ElfW(Sym)> m_symbols;
7070+ std::vector<Segment> m_segments;
7171+7272+ struct Section
7373+ {
7474+ ElfW(Shdr) hdr;
7575+ std::vector<uint8_t> data;
7676+ };
7777+ std::vector<Section> m_sections;
7878+7979+ uintptr_t m_ehAddr = 0, m_ehSize = 0;
8080+ uintptr_t m_dotSymtab, m_dotStrtab, m_dotText, m_dotEhframe;
8181+ };
8282+}
8383+8484+#endif /* GDBJIT_H */
8585+