mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-29 07:51:01 +00:00
Fix thread support (#640)
This PR fixes several things related to threads emulation:
1. Support `SameTebFlags.InitialThread`
This flag is needed to support emulation of .net executables (not yet
fully supported) that don't have an entry point set in `PE` header. This
applies to both `PE32` and `PE64` executables. If `InitialThread` is set
the loader substitutes an entry point of the .net executable with
`mscoree.dll!_CorExeMain`.
2. Fix static thread local storage for `WOW64`
This fix resolves `shell32.dll` initialization on `WOW64`. This fix also
uses correct structure and field names that are obtained from the
corresponding `.pdb` files.
3. Fix dynamic thread local storage for `WOW64`
4. Fix setting argument of a `WOW64` thread start proc
5. Fix creating suspended thread and parse create_flags
Currently creating suspended thread doesn't work because
`NtCreateThreadEx` handler uses invalid flag `CREATE_SUSPENDED`. This PR
fixes that, and moreover it carefully parses create_flags of the
`NtCreateThreadEx` call.
6. Fix `FS` and `GS` handling
This PR fixes several problems with `GS` and `FS` segments:
* Wrong GDT descriptor for selector 0x53
* Update GDT descriptor for selector 0x53 for a `WOW64` process every
context switch like Windows does
* Set `GS` base when `GS` segment register is updated in 64-bit code
(code selector is `0x33`). When `GS` segment register is loaded with
correct selector (`0x2b`) `GS` base is set to 0. So, when the code
accesses something like `gs:[0]`, a page fault occurs. `KiPageFault`
handles this situation and sets correct `GS` base.
Also, take into account that `teb64.ExceptionList` initially contains
`teb32` address for `WOW64` process. This is used to setup `FS` base
when `wrfsbase` instruction is available. We can enable this instruction
using `kusd.ProcessorFeatures.arr[PF_RDWRFSGSBASE_AVAILABLE] = 1;` and
this work perfectly with `unicorn` backend. Unfortunately `icicle`
backend does not support `wrfsbase`, so I don't enable this instruction
by default.
This commit is contained in:
@@ -49,7 +49,7 @@ class emulator_thread : public ref_counted_object
|
||||
}
|
||||
|
||||
emulator_thread(memory_manager& memory, const process_context& context, uint64_t start_address, uint64_t argument, uint64_t stack_size,
|
||||
bool suspended, uint32_t id);
|
||||
uint32_t create_flags, uint32_t id, bool initial_thread);
|
||||
|
||||
emulator_thread(const emulator_thread&) = delete;
|
||||
emulator_thread& operator=(const emulator_thread&) = delete;
|
||||
@@ -86,6 +86,7 @@ class emulator_thread : public ref_counted_object
|
||||
bool await_any{false};
|
||||
bool waiting_for_alert{false};
|
||||
bool alerted{false};
|
||||
uint32_t create_flags{0};
|
||||
uint32_t suspended{0};
|
||||
std::optional<std::chrono::steady_clock::time_point> await_time{};
|
||||
|
||||
@@ -123,6 +124,7 @@ class emulator_thread : public ref_counted_object
|
||||
void restore(x86_64_emulator& emu) const
|
||||
{
|
||||
emu.restore_registers(this->last_registers);
|
||||
this->refresh_execution_context(emu);
|
||||
}
|
||||
|
||||
void setup_if_necessary(x86_64_emulator& emu, const process_context& context)
|
||||
@@ -166,6 +168,7 @@ class emulator_thread : public ref_counted_object
|
||||
buffer.write(this->waiting_for_alert);
|
||||
buffer.write(this->alerted);
|
||||
|
||||
buffer.write(this->create_flags);
|
||||
buffer.write(this->suspended);
|
||||
buffer.write_optional(this->await_time);
|
||||
|
||||
@@ -213,6 +216,7 @@ class emulator_thread : public ref_counted_object
|
||||
buffer.read(this->waiting_for_alert);
|
||||
buffer.read(this->alerted);
|
||||
|
||||
buffer.read(this->create_flags);
|
||||
buffer.read(this->suspended);
|
||||
buffer.read_optional(this->await_time);
|
||||
|
||||
@@ -245,6 +249,7 @@ class emulator_thread : public ref_counted_object
|
||||
|
||||
private:
|
||||
void setup_registers(x86_64_emulator& emu, const process_context& context) const;
|
||||
void refresh_execution_context(x86_64_emulator& emu) const;
|
||||
|
||||
void release()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user