WINE. Windows NT Architecture WINE Architecture socket pipe.

31
WINE

Transcript of WINE. Windows NT Architecture WINE Architecture socket pipe.

WINE

Windows NT Architecture

WINE Architecture

socket

pipe

Wine Directory Structure

• server/– wineserver

–Windows abstract object (mailslot, mutex, … etc)

• dlls/–Windows DLL

• loader/–Wine call a preloader to reserve memory space for

Windows application

Wine Overview

Windows App

Windows EXEWindows EXE

Kernel32.DLLKernel32.DLL

NTDLL.DLLNTDLL.DLL

wineserver

socket

pipe

• Client send request to wineserver through the pipe• winserver poll request then call corresponding handler

Load Windows Binary - Part 1

• Example– wine → wine_preloader → wine → notepad.exe

– They are the same process but with different image

• wine check a environment variable too see if preloader already ran before, and when wine_preloader finish its job, it reload wine image and start to load Windows application (i.e., notepad.exe)

Load Windows Binary - Part 1

• wine_preloader– Use customized entry function _start

– _start call wld_start to reserve memory space for Windows PE binary, then jump to dynamic linker return by wld_start

Load Windows Binary - Part 2

• Since preloader already ran, we are ready to start the real and complicate job– wine → wine_preloader → wine → notepad.exe

Load Windows Binary - Part 2

• wine → wine_init– wine_init → __wine_process_init (NTDLL.DLL)

– __wine_process_init → __wine_kernel_init (Kernel32.DLL)

– __wine_kernel_init → start_process

– start_process → notepad.exe

Load Windows Binary - Part 2

• wine_init (libs/wine/loader.c)– Set up DLL path so that wine can load correct

DLL it want

– Load built-in NTDLL.DLL. Built-in DLL contains standard WinAPI and wine internal functions

– Get address of function __wine_process_init from built-in BTDLL.DLL

– Run __wine_process_init

Load Windows Binary - Part 2

• wine_process_init (dlls/ntdll/loader.c)– Call function thread_init to initialize TEB, PEB

and other environment for Windows application. Launch winserver if needed and set up connection to the winserver

– Load built-in Kernel32.DLL

– Get address of function __wine_kernel_init from built-in Kernel32.DLL

Load Windows Binary - Part 2

• wine_kernel_init– Initialize things like register this Windows

application to wineserver, set up current directory and environment parameters

– Load image of Windows application

Load Windows Binary - Part 2

• start_process– LdrInitializeThunk loads remaining DLL needed

by the target Windows application

– Jump to Windows application entry point and kick off

– All WinAPI called by Windows application will be directed to Wine’s version

Implement Win32/NT API

• Three examplesCreateProcessOpenFileWriteFile

• Most of them are implement through POSIX API with emulation

• Some of them call POSIX API at client side, others are at wineserver side

CreateProcess

CreateProcessW (dlls/kernel32/process.c

)

CreateProcessW (dlls/kernel32/process.c

)

create_process_impl (dlls/kernel32/process.c

)

create_process_impl (dlls/kernel32/process.c

)

create_process (dlls/kernel32/process.c

)

create_process (dlls/kernel32/process.c

)

exec_loader (dlls/kernel32/process.c

)

exec_loader (dlls/kernel32/process.c

)

fork →wine_exec_wine_binaryfork →wine_exec_wine_binary

Windows App wineserver

create_process (server/process.c)

create_process (server/process.c)

req_new_process(server/process.c)req_new_process(server/process.c)

OpenFile

OpenFile (dlls/kernel32/file.c)

OpenFile (dlls/kernel32/file.c)

NtCreateFile (dlls/ntdll/file.c)

NtCreateFile (dlls/ntdll/file.c)

FILE_CreateFile (dlls/ntdll/file.c)

FILE_CreateFile (dlls/ntdll/file.c)

Windows App wineserver

req_create_file (server/file.c)req_create_file (server/file.c)

struct fd *open_fd (server/fd.c)

struct fd *open_fd (server/fd.c)

create_file(server/file.c)

create_file(server/file.c)

fd->unix_fd = open( … );

fd->unix_fd = open( … );

reply->handle = alloc_handle ( … );

reply->handle = alloc_handle ( … );

File

• Windows app does not own the file it creates by using WinAPI like OpenFile/CreateFile– OpenFile/CreateFile send request to wineserver

– wineserver uses open to create a UNIX file descriptor, associated it with <windows process, handle> pair

–Windows app only see a fake Windows file handle returned by wineserver

WriteFile

WriteFile (dlls/kernel32/file.c)

WriteFile (dlls/kernel32/file.c)

NtWriteFile (dlls/ntdll/file.c)

NtWriteFile (dlls/ntdll/file.c)

server_get_unix_fd (dlls/ntdll/server.c) server_get_unix_fd (dlls/ntdll/server.c)

write(fd …); write(fd …);

Windows App wineserver

req_get_handle_fd (server/fd.c)

req_get_handle_fd (server/fd.c)

get_handle_fd_obj(server/fd.c)

get_handle_fd_obj(server/fd.c)

receive_fd(dlls/ntdll/server.c)

receive_fd(dlls/ntdll/server.c)

send_client_fd (server/request.c)

send_client_fd (server/request.c)

WriteFile

Windows App wineserver

User space

Kernel space

file

wineserver gives the file descriptor accessright temporarily

Cygwin

Cygwin Overview

C library which provides a POSIX-style API

Cygwin Overview

cygwin1.dllcygwin1.dll

UNIX AppUNIX App

Kernel32.DLLKernel32.DLL

NTDLL.DLLNTDLL.DLL

newlibc(C

runtime)

newlibc(C

runtime)

What Cygwin Is?

• Cygwin includes two parts– Provide tools like gcc, make, … etc, let you

compile UNIX source code into Windows executable

– Provide cygwin1.dll which acts as a Linux API layer on Windows

fork

fork(cygwin/fork.cc)

fork(cygwin/fork.cc)

frok:: parent(cygwin/fork.cc)

frok:: parent(cygwin/fork.cc)

CreateProcessW(Win32 API)

CreateProcessW(Win32 API)

• Win32 API receive more parameters then POSIX API, make up those parameters

open

• UNIX provides uniform interfaces like open/close/read/write to access devices

• Windows provides various interfaces for different devices

• cygwin glue them by using Class fhandler_base

open(cygwin/syscalls.cc)

open(cygwin/syscalls.cc)

build_fh_name(cygwin/dtable.cc)

build_fh_name(cygwin/dtable.cc)

open

• cygwin glue them by providing a abstract layer: class fhandler_base

virtual int ioctl (unsigned int cmd, void *);virtual int fcntl (int cmd, void *);virtual char const *ttyname () { return get_name (); }virtual void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3)));virtual ssize_t __stdcall write (const void *ptr, size_t len);

open

• cygwin glue them by providing a abstract layer: class fhandler_base

virtual int ioctl (unsigned int cmd, void *);virtual int fcntl (int cmd, void *);virtual char const *ttyname () { return get_name (); }virtual void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3)));virtual ssize_t __stdcall write (const void *ptr, size_t len);

open

open(cygwin/syscalls.cc)

open(cygwin/syscalls.cc)

build_fh_name(cygwin/dtable.cc)

build_fh_name(cygwin/dtable.cc)

fhandler_disk_file::open(cygwin/

fhandler_disk_file.cc)

fhandler_disk_file::open(cygwin/

fhandler_disk_file.cc)

fhandler_base::open_fs(cygwin/

fhandler_disk_file.cc)

fhandler_base::open_fs(cygwin/

fhandler_disk_file.cc)

Need to deal with different path conventionbetween UNIX and Windows

fhandler_base::open(cygwin/fhandler.cc)fhandler_base::open(cygwin/fhandler.cc)

NtCreateFileNtCreateFile

Design & Implementation Strategy

• Both WINE and Cygwin are API compatibility layers, WinAPI-to-POSIX or vise versa (with a little different)

• WINE provides binary level compatibilityYou don’t have to compile Windows source code Since you usually can’t get the source code

• Cygwin provides source level compatibilityYou use GCC (Windows port) provided by

Cygwin to compile UNIX source code

Design & Implementation Strategy

• Both implement their own .so or DLL, which do API conversion, or vise versa

• Wine need to implement its own PE loader/dynamic linker, since it achieve binary level compatibility

Goal

• The design and implementation strategy of these systems

• The whole procedure from inputting guest app all the way to generating the host code

• One process management example

• One memory management example (or file system, network, device) to explain the procedure