1 #include "debug_jit.hpp"
2 #include <dlfcn.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string>
6 
7 using namespace std;
8 
9 namespace JIT
10 {
11 
12 struct DebugBlock::Impl
13 {
14 	Impl() = default;
15 	Impl(Impl &&) = delete;
16 	void operator=(Impl &&) = delete;
17 	~Impl();
18 
19 	void *dylib = nullptr;
20 	Func block = nullptr;
21 	string name, soname;
22 
23 	bool compile(uint64_t hash, const std::string &source);
24 };
25 
DebugBlock(const unordered_map<string,uint64_t> &)26 DebugBlock::DebugBlock(const unordered_map<string, uint64_t> &)
27 {
28 }
29 
~DebugBlock()30 DebugBlock::~DebugBlock()
31 {
32 }
33 
~Impl()34 DebugBlock::Impl::~Impl()
35 {
36 	if (dylib)
37 		dlclose(dylib);
38 
39 	remove(soname.c_str());
40 	remove(name.c_str());
41 }
42 
compile(uint64_t hash,const std::string & source)43 bool DebugBlock::compile(uint64_t hash, const std::string &source)
44 {
45 	impl = unique_ptr<Impl>(new Impl);
46 	bool ret = impl->compile(hash, source);
47 	if (ret)
48 		block = impl->block;
49 	return ret;
50 }
51 
compile(uint64_t hash,const std::string & source)52 bool DebugBlock::Impl::compile(uint64_t hash, const std::string &source)
53 {
54 	name = "/tmp/";
55 	name += to_string(hash);
56 	soname = name;
57 	name += ".c";
58 	soname += ".so";
59 
60 	FILE *file = fopen(name.c_str(), "w");
61 	if (!file)
62 		return false;
63 
64 	fputs(source.c_str(), file);
65 	fclose(file);
66 
67 	char command[256];
68 	if (sizeof(size_t) == 8)
69 	{
70 		sprintf(command, "gcc -o %s %s -shared -fpic -O0 -g -std=c99 -Wl,--unresolved-symbols=ignore-all",
71 		        soname.c_str(),
72 		        name.c_str());
73 	}
74 	else if (sizeof(size_t) == 4)
75 	{
76 		sprintf(command, "gcc -m32 -o %s %s -shared -fpic -O0 -g -std=c99 -Wl,--unresolved-symbols=ignore-all",
77 		        soname.c_str(),
78 		        name.c_str());
79 	}
80 	int ret = system(command);
81 	if (ret != 0)
82 		return false;
83 
84 	dylib = dlopen(soname.c_str(), RTLD_LOCAL | RTLD_LAZY);
85 	if (!dylib)
86 		return false;
87 
88 	block = reinterpret_cast<Func>(dlsym(dylib, "block_entry"));
89 	if (!dylib)
90 		return false;
91 	return true;
92 }
93 
94 } // namespace JIT
95