Attend XDA's Second Annual Developer Conference, XDA:DevCon 2014!
5,813,079 Members 54,239 Now Online
XDA Developers Android and Mobile Development Forum

[Beta] Win86emu: Running x86 apps on WinRT devices

Tip us?
 
clrokr
Old
#11  
Member
Thanks Meter 53
Posts: 69
Join Date: Aug 2009
Would you mind giving a technical explanation?
 
no2chem
Old
#12  
Senior Member
Thanks Meter 101
Posts: 275
Join Date: Jul 2007
Quote:
Originally Posted by mamaich View Post
I'm presenting a prototype of a tool that allows running Windows programs compiled for a desktop PC (x86) on an unlocked Windows RT (arm) tablet. The tool emulates x86 instructions and passes Windows API calls to WinRT kernel with necessary modifications.

This build is an early alpha version. It can run only very simple apps that use rather small subset of Win32 API that I've already implemented. Archive contains clock.exe from NT4 distribution as an example of such app. As I'll continue work on the project - the list of supported applications would grow up.

This tool would support only 32-bit windows native applications. It would not allow running drivers or .NET apps that were written for old .NET versions nor Win16 or DOS apps. And current version supports emulation only of EXE files that contain relocations section (this would be fixed later).

Instructions:
1. Unlock your device with this tool: http://forum.xda-developers.com/show....php?t=2092158
2. Unzip the archive to any directory
3. Run _start_clock.cmd
This would execute the clock.exe from NT4 in the emulation mode.

This post would be updated as I'll make more progress.

Note: This is an early alpha version, and do not expect that it would run anything except the provided file. Do not ask me what programs would be supported and when the next builds would appear - I don't know, as I work on this project only on spare time. I would not publish the complete sources of the tool, but it would be extensible by users, and some plugins (at least bochs/dosbox emulation engines and some of the API wrappers) would be opensource.
"Yact" in the file names stands for "yet another code translator", it was the original name of the project.

Edited 13.01.2012:
- added a few ARM WinAPI workarounds, added calc.exe as a second example (run _start_calc.cmd).
heh, is this a port of the app you showed off back in the CE days? -awesome getting that ported over
 
chansthename
Old
#13  
Senior Member
Thanks Meter 5
Posts: 223
Join Date: May 2007
This is great, really opens up a lot more things and means that we don't need to recompile everything either.
 
mamaich
Old
(Last edited by mamaich; 13th January 2013 at 03:54 AM.)
#14  
Recognized Developer - OP
Thanks Meter 214
Posts: 1,150
Join Date: Apr 2004

 
DONATE TO ME
Quote:
heh, is this a port of the app you showed off back in the CE days? -awesome getting that ported over
Not exactly a port, it is a clean remake based on the old ideas.
Quote:
Originally Posted by clrokr View Post
Would you mind giving a technical explanation?
The idea is very simple:
- a PE file loader (load files, process relocs, run TLS callbacks in an emulation mode). Support import loops (DLL A imports B while B imports A), ordinals, etc.
- a set of wrapper x86 DLLs (kernel32_stub.dll and so on) that "look like" the corresponding Win API functions for an emulated program:
Code:
#define DEFINE_FUNC1(name)      \
static const ModuleDef str_##name={DLL_NAME,#name};     \
EXTERN_C DW STUB_EXPORT stub_##name(DW p1)              \
{       \
        DW *p=&p1;      \
        __asm { mov eax,p }     \
        __asm { jmp f1 }        \
        __asm { mov eax,offset str_##name }     \
f1:     __asm { in eax,0xe5 }   \
        __asm { mov p,eax }     \
        return (DW)p;   \
}
.....
#define DEFINE_FUNC3(name)      \
static const ModuleDef str_##name={DLL_NAME,#name};     \
EXTERN_C DW STUB_EXPORT stub_##name(DW p1,DW p2,DW p3)          \
{       \
        DW *p=&p1;      \
        __asm { mov eax,p }     \
        __asm { jmp f1 }        \
        __asm { mov eax,offset str_##name }     \
f1:     __asm { in eax,0xe5 }   \
        __asm { mov p,eax }     \
        return (DW)p;   \
}
....
DEFINE_FUNC1(AddAtomA)
DEFINE_FUNC1(AddAtomW)
DEFINE_FUNC7(CreateFileA) -- number in macro == number of parameters to a __stdcall WinAPI function. 
Compiler automatically generates "ret N*4" at the end of such function. 
I've decided to use such c+asm approach instead of making a tiny assebler stub, 
as I can easily implement some of such functions in C directly in a stub DLL plus it 
simplifies debugging. And the functions have a usual C prologue/epilogue, so that 
the emulated program may even patch them in runtime, for example for hooks.
...
- a 32-bit x86 emulation engine (currently 2 engines: from bochs and from dosbox, planning on adding my own) that intercepts the command "in eax,0xe5", determines which API is needed by a program and passes it to a handler.
- native (arm) API handler DLLs (kernel32_yact.dll and so on). They are mostly autogenerated too:
Code:
#define DEFINE_FUNC1(name) 	\
EXTERN_C DW STUB_IMPORT name(DW);	\                     -- this behaves like a function prototype to compiler
EXTERN_C DW STUB_EXPORT yact_##name(DW *R)		\     -- R - pointer to the x86 stack 
{	\
  DW r=name(p1);	\         // call the func passing it paramers from the emulated stack, p1==R[0], p2==R[1] and so on
  LEAVE(1);		\         // empty macro, as the stack is unwinded in x86 stub DLL now
  return r;		\
}
...
#define DEFINE_FUNC3(name) 	\
EXTERN_C DW STUB_IMPORT name(DW,DW,DW);	\
EXTERN_C DW STUB_EXPORT yact_##name(DW *R)		\
{	\
  DW r=name(p1,p2,p3);	\
  LEAVE(3);		\
  return r;		\
}
...
DEFINE_FUNC1(AddAtomA)
DEFINE_FUNC1(AddAtomW)
DEFINE_FUNC7(CreateFileA)  // as you see - implementation part is identical to an x86 stub, so I can use the same stub-generator tool
Some of the functions require complex emulation due to their absence in ARM or due to the callbacks to x86 code:
Code:
static DWORD WINAPI ThreadProc(
  LPVOID lpParameter	// [0] == orig func, [1] == orig param
)
{
	__EXCEPTION_REGISTRATION_RECORD R;
	DWORD *Parm=(DWORD*)lpParameter;
	DWORD *TEB=(DWORD*)PeLdrGetCurrentTeb();
	R.Next=(__EXCEPTION_REGISTRATION_RECORD*)-1;
	R.Handler=(void*)CbReturnToHost();
	TEB[0]=(DWORD)&R;	// in case of unhandled exception - just return 
	PeLdrNotifyNewThread(NULL,DLL_THREAD_ATTACH);

	DWORD Ret=EmuExecute(Parm[0],1,Parm[1]); // 1 == number of parameters to the emulated function
	delete Parm;
	return Ret;
}

EXTERN_C DW STUB_EXPORT yact_CreateThread(DW *R)
{	
	DWORD* Parm=new DWORD[2];
	Parm[0]=p3;                               // TODO: no out-of-memory checking for now
	Parm[1]=p4;
	DWORD StackSize=p2;
	if(StackSize)
		StackSize+=1024*1024;      // I reserve some space for my own needs (debugging)
	else
		StackSize=2*1024*1024;     // TODO: I don't support autogrow stacks, so reserve 2 Mb

	DWORD t=(DWORD)CreateThread((LPSECURITY_ATTRIBUTES)p1,StackSize,ThreadProc,Parm,p5,(LPDWORD)p6);
	LEAVE(6);		
	return t;
}
Some of the COM interfaces are already implemented, for example DirectDraw and DirectSound, though not heavily debugged. On a desktop emulator build I can already run "Heroes of might and magic 3" and old WinRAR, but there are several RT-specific OS limitations I need to bypass before making them run on ARM. Current work in progress is: overcoming the RT limitations, manually implementing the API functions that callback to a program code (like CreateThread, RegisterClassA and so on), adding stubs for other system DLLs/COM objects.
Manually thrown SEH exceptions are fully supported, but access violation, int3 and similar OS-generated exceptions would cause program to crash. Some of the TEB fields (TLS and the fields required by the Borland compilers) are implemented too.

I don't make pointer translation in an emulated code nor make parameter checks passed to API. As a side-effect - the emulated program may trash the emulator in memory, but this greatly increases speed.
Most of the x86 EXE files don't contain relocations section and need to be loaded on the specific addresses (typically 0x400000). This is not a problem on a desktop, as I can rebase my emulator's EXE to any address I need, and free the corresponding RAM addrs for emulated program, but on ARM - this is a main problem. So currently only EXEs with relocs are supported for emulation, but there are ways to overcome this problem. And some EXEs produced by old Borland compilers contain "broken" relocs, this is a small problem too.
...
The Following 3 Users Say Thank You to mamaich For This Useful Post: [ Click to Expand ]
 
rheza02
Old
#15  
Senior Member
Thanks Meter 10
Posts: 459
Join Date: May 2006
HI mamaich, sorry for disturbing you, may i know how do you compile visual studio project for arm ?, i already change windowsarmdesktop to true. But i can't find arm options in build settings. Any suggestion ?
oh, hello...
 
netham45
Old
#16  
Recognized Developer
Thanks Meter 540
Posts: 863
Join Date: Jun 2009
Location: Denver

 
DONATE TO ME
Quote:
Originally Posted by rheza02 View Post
HI mamaich, sorry for disturbing you, may i know how do you compile visual studio project for arm ?, i already change windowsarmdesktop to true. But i can't find arm options in build settings. Any suggestion ?
This is completely unrelated to the topic and has been covered in at least 3 threads, multiple times in each, in the past couple days. Use the search function.
Don't PM me for help, post on the forums. I won't respond to basic questions.

I wrote and maintain the jailbreak scripts for Windows RT.

Tablet: Microsoft Surface RT 32GB, Type Keyboard
Phone: Samsung Galaxy Note III

Helpful Windows RT Links:
Windows RT Jailbreak Tool
List of ported apps
Disabling Windows Update
 
mamaich
Old
#17  
Recognized Developer - OP
Thanks Meter 214
Posts: 1,150
Join Date: Apr 2004

 
DONATE TO ME
Quote:
Originally Posted by netham45 View Post
This is completely unrelated to the topic and has been covered in at least 3 threads, multiple times in each, in the past couple days. Use the search function.
Yes, and I've answered it here: http://forum.xda-developers.com/show...&postcount=131
...
 
GoodDayToDie
Old
#18  
Recognized Developer
Thanks Meter 2,699
Posts: 5,682
Join Date: Jan 2011
Location: Seattle
Wow, this is awesome work! While recompiling (for native speed, lower memory footprint, launch time, lower battery usage, script transparency, etc.) is still obviously preferred, this finally offers a way to run closed-source or otherwise un-recompilable legacy apps. Well done; I'll be watching this closely.

A thought for making it easier to run the apps (including the aforementioned script transparency): Windows (at least on x86 and x64, and I'm pretty sure on ARM too) supports specifying executable names that, when they would be executed, are instead passed as a parameter to another executable. This is usually used for testing or debugging purposes (for example, always load a given app under a debugger or have Application Verifier hook into it at launch) but it can be used for other purposes too. One, which would be fantastic here, is to always run a program through a compatibility layer... I've never before seen it used for a full instruction set translation compatibility layer, but why not?

Create the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<IMAGE FILE NAME>
i.e. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\starcraft.exe
Then create a REG_SZ (String) value under that key called "Debugger" and set the value to the full path of the program you want to host the executable.
i.e. C:\Program Files\x86_peldr\peldr.exe

Source: http://support.microsoft.com/kb/824344

I can't promise that this will work for executable images that wouldn't be loadable normally, but it's probably worth a shot. Another, slightly less seamless option: change the extension of the executables (for example, starcraft.ex86) and register your app as the handler for that file type.
Win8/Windows RT projects:
List of desktop apps for hacked RT devices

WP8 projects:
Native Access WebServer and Libraries
WP8 Interop Unlocks
Storage Cleanup tool

WP7 projects:
XapHandler, Root Webserver, OEM Marketplace XAPs, Bookmarklets collection (Find On Page), Interop-unlock hacks.


Do not private message me with questions that should have been posted on the forum! Not only are you wasting your time - I'm not going to bother writing an answer to such a question for only one person - but I will probably block you from PMing me in the future as well.
 
netham45
Old
#19  
Recognized Developer
Thanks Meter 540
Posts: 863
Join Date: Jun 2009
Location: Denver

 
DONATE TO ME
Quote:
Originally Posted by GoodDayToDie View Post
Wow, this is awesome work! While recompiling (for native speed, lower memory footprint, launch time, lower battery usage, script transparency, etc.) is still obviously preferred, this finally offers a way to run closed-source or otherwise un-recompilable legacy apps. Well done; I'll be watching this closely.

A thought for making it easier to run the apps (including the aforementioned script transparency): Windows (at least on x86 and x64, and I'm pretty sure on ARM too) supports specifying executable names that, when they would be executed, are instead passed as a parameter to another executable. This is usually used for testing or debugging purposes (for example, always load a given app under a debugger or have Application Verifier hook into it at launch) but it can be used for other purposes too. One, which would be fantastic here, is to always run a program through a compatibility layer... I've never before seen it used for a full instruction set translation compatibility layer, but why not?

Create the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<IMAGE FILE NAME>
i.e. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\starcraft.exe
Then create a REG_SZ (String) value under that key called "Debugger" and set the value to the full path of the program you want to host the executable.
i.e. C:\Program Files\x86_peldr\peldr.exe

Source: http://support.microsoft.com/kb/824344

I can't promise that this will work for executable images that wouldn't be loadable normally, but it's probably worth a shot. Another, slightly less seamless option: change the extension of the executables (for example, starcraft.ex86) and register your app as the handler for that file type.
What I was thinking of for doing that was hooking the 'This doesn't run on this PC' error that explorer gives and making it call this instead of the error.
Don't PM me for help, post on the forums. I won't respond to basic questions.

I wrote and maintain the jailbreak scripts for Windows RT.

Tablet: Microsoft Surface RT 32GB, Type Keyboard
Phone: Samsung Galaxy Note III

Helpful Windows RT Links:
Windows RT Jailbreak Tool
List of ported apps
Disabling Windows Update
 
GoodDayToDie
Old
#20  
Recognized Developer
Thanks Meter 2,699
Posts: 5,682
Join Date: Jan 2011
Location: Seattle
Nice... but that doesn't cover things like launching a program from the command line (script or manually), or one program launching another, or launching Windows services (although I'm not sure you'd want to emulate those anyhow... the battery hit would suck), or so on. Still an interesting goal.

One other thought for the "it'd-be-awesome" list (not even really a wish-list): support doing this for DLLs loaded into other processes (i.e. somehow get between LoadLibrary and the x86 binary, and interpose your translator). Why, you ask? Plugins. Browser plugins, media codecs (which are DLLs, whatever their extension), Control Panel files, COM objects in general, etc.
Win8/Windows RT projects:
List of desktop apps for hacked RT devices

WP8 projects:
Native Access WebServer and Libraries
WP8 Interop Unlocks
Storage Cleanup tool

WP7 projects:
XapHandler, Root Webserver, OEM Marketplace XAPs, Bookmarklets collection (Find On Page), Interop-unlock hacks.


Do not private message me with questions that should have been posted on the forum! Not only are you wasting your time - I'm not going to bother writing an answer to such a question for only one person - but I will probably block you from PMing me in the future as well.

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes