@@ -54,10 +54,6 @@ static void* const s_memory = []() -> void*
54
54
static u8* s_code_addr;
55
55
static u64 s_code_size;
56
56
57
- // EH frames
58
- static u8* s_unwind_info;
59
- static u64 s_unwind_size;
60
-
61
57
#ifdef _WIN32
62
58
static std::vector<std::vector<RUNTIME_FUNCTION>> s_unwind; // .pdata
63
59
#endif
@@ -193,8 +189,27 @@ struct MemoryManager final : llvm::RTDyldMemoryManager
193
189
194
190
virtual void registerEHFrames (u8* addr, u64 load_addr, std::size_t size) override
195
191
{
196
- s_unwind_info = addr;
197
- s_unwind_size = size;
192
+ #ifdef _WIN32
193
+ // Use s_memory as a BASE, compute the difference
194
+ const u64 code_diff = (u64)s_code_addr - (u64)s_memory;
195
+ const u64 unwind_diff = (u64)addr - (u64)s_memory;
196
+
197
+ // Fix RUNTIME_FUNCTION records (.pdata section)
198
+ auto & pdata = s_unwind.back ();
199
+
200
+ for (auto & rf : pdata)
201
+ {
202
+ rf.BeginAddress += static_cast <DWORD>(code_diff);
203
+ rf.EndAddress += static_cast <DWORD>(code_diff);
204
+ rf.UnwindData += static_cast <DWORD>(unwind_diff);
205
+ }
206
+
207
+ // Register .xdata UNWIND_INFO structs
208
+ if (!RtlAddFunctionTable (pdata.data (), (DWORD)pdata.size (), (u64)s_memory))
209
+ {
210
+ LOG_ERROR (GENERAL, " RtlAddFunctionTable() failed! Error %u" , GetLastError ());
211
+ }
212
+ #endif
198
213
199
214
return RTDyldMemoryManager::registerEHFrames (addr, load_addr, size);
200
215
}
@@ -241,6 +256,36 @@ struct EventListener final : llvm::JITEventListener
241
256
const llvm::StringRef elf = obj.getData ();
242
257
fs::file (path, fs::rewrite).write (elf.data (), elf.size ());
243
258
}
259
+
260
+ #ifdef _WIN32
261
+ for (auto it = obj.section_begin (), end = obj.section_end (); it != end; ++it)
262
+ {
263
+ llvm::StringRef name;
264
+ it->getName (name);
265
+
266
+ if (name == " .pdata" )
267
+ {
268
+ llvm::StringRef data;
269
+ it->getContents (data);
270
+
271
+ std::vector<RUNTIME_FUNCTION> rfs (data.size () / sizeof (RUNTIME_FUNCTION));
272
+
273
+ auto offsets = reinterpret_cast <DWORD*>(rfs.data ());
274
+
275
+ // Initialize .pdata section using relocation info
276
+ for (auto ri = it->relocation_begin (), end = it->relocation_end (); ri != end; ++ri)
277
+ {
278
+ if (ri->getType () == 3 /* R_X86_64_GOT32*/ )
279
+ {
280
+ const u64 value = *reinterpret_cast <const DWORD*>(data.data () + ri->getOffset ());
281
+ offsets[ri->getOffset () / sizeof (DWORD)] = static_cast <DWORD>(value + ri->getSymbol ()->getAddress ().get ());
282
+ }
283
+ }
284
+
285
+ s_unwind.emplace_back (std::move (rfs));
286
+ }
287
+ }
288
+ #endif
244
289
}
245
290
};
246
291
@@ -250,8 +295,6 @@ jit_compiler::jit_compiler(std::unordered_map<std::string, std::uintptr_t> init_
250
295
: m_link(std::move(init_linkage_info))
251
296
, m_cpu(std::move(_cpu))
252
297
{
253
- verify (HERE), s_memory;
254
-
255
298
// Initialization
256
299
llvm::InitializeNativeTarget ();
257
300
llvm::InitializeNativeTargetAsmPrinter ();
@@ -282,7 +325,6 @@ jit_compiler::jit_compiler(std::unordered_map<std::string, std::uintptr_t> init_
282
325
fmt::throw_exception (" LLVM: Failed to create ExecutionEngine: %s" , result);
283
326
}
284
327
285
- m_engine->setProcessAllSections (true ); // ???
286
328
m_engine->RegisterJITEventListener (&s_listener);
287
329
}
288
330
@@ -308,8 +350,6 @@ void jit_compiler::load(std::unique_ptr<llvm::Module> module, std::unique_ptr<ll
308
350
m_map[name] = m_engine->getFunctionAddress (name);
309
351
}
310
352
}
311
-
312
- init ();
313
353
}
314
354
315
355
void jit_compiler::make (std::unique_ptr<llvm::Module> module, std::string path)
@@ -336,74 +376,6 @@ void jit_compiler::make(std::unique_ptr<llvm::Module> module, std::string path)
336
376
// Delete IR to lower memory consumption
337
377
func.deleteBody ();
338
378
}
339
-
340
- init ();
341
- }
342
-
343
- void jit_compiler::init ()
344
- {
345
- #ifdef _WIN32
346
- // Register .xdata UNWIND_INFO (.pdata section is empty for some reason)
347
- std::set<u64> func_set;
348
-
349
- for (const auto & pair : m_map)
350
- {
351
- func_set.emplace (pair.second );
352
- }
353
-
354
- const u64 base = (u64)s_memory;
355
- const u8* bits = s_unwind_info;
356
-
357
- std::vector<RUNTIME_FUNCTION> unwind;
358
- unwind.reserve (m_map.size ());
359
-
360
- for (const u64 addr : func_set)
361
- {
362
- // Find next function address
363
- const auto _next = func_set.upper_bound (addr);
364
- const u64 next = _next != func_set.end () ? *_next : (u64)s_code_addr + s_code_size;
365
-
366
- // Generate RUNTIME_FUNCTION record
367
- RUNTIME_FUNCTION uw;
368
- uw.BeginAddress = static_cast <u32>(addr - base);
369
- uw.EndAddress = static_cast <u32>(next - base);
370
- uw.UnwindData = static_cast <u32>((u64)bits - base);
371
- unwind.emplace_back (uw);
372
-
373
- // Parse .xdata UNWIND_INFO record
374
- const u8 flags = *bits++; // Version and flags
375
- const u8 prolog = *bits++; // Size of prolog
376
- const u8 count = *bits++; // Count of unwind codes
377
- const u8 frame = *bits++; // Frame Reg + Off
378
- bits += ::align (std::max<u8>(1 , count), 2 ) * sizeof (u16); // UNWIND_CODE array
379
-
380
- if (flags != 1 )
381
- {
382
- // Can't happen for trivial code
383
- LOG_ERROR (GENERAL, " LLVM: unsupported UNWIND_INFO version/flags (0x%02x)" , flags);
384
- break ;
385
- }
386
-
387
- LOG_TRACE (GENERAL, " LLVM: .xdata at 0x%llx: function 0x%x..0x%x: p0x%02x, c0x%02x, f0x%02x" , uw.UnwindData + base, uw.BeginAddress + base, uw.EndAddress + base, prolog, count, frame);
388
- }
389
-
390
- if (s_unwind_info + s_unwind_size != bits)
391
- {
392
- LOG_ERROR (GENERAL, " LLVM: .xdata analysis failed! (%p != %p)" , s_unwind_info + s_unwind_size, bits);
393
- }
394
- else if (!RtlAddFunctionTable (unwind.data (), (DWORD)unwind.size (), base))
395
- {
396
- LOG_ERROR (GENERAL, " RtlAddFunctionTable(%p) failed! Error %u" , s_unwind_info, GetLastError ());
397
- }
398
- else
399
- {
400
- LOG_NOTICE (GENERAL, " LLVM: UNWIND_INFO registered (%p, size=0x%llx)" , s_unwind_info, s_unwind_size);
401
- }
402
-
403
- s_unwind.emplace_back (std::move (unwind));
404
- #else
405
- // TODO: register EH frames if necessary
406
- #endif
407
379
}
408
380
409
381
jit_compiler::~jit_compiler ()
0 commit comments