Notes about Wine

Last Update : 07/11/2004

On-the-fly byte swapping: Defining a memory region as Little Endian

Defining a memory region as Little Endian in order to provide a way to deal with byte swapping (endian conversion).
Here is the idea: mprotect a memory region with lock access for reading/writing. As soon as there is a memory access to this region, a signal will be raised. We handle the signal, and do the byte swapping at this moment.

Pros :

  • Simple to implement.
  • Don't have to know about the data/no conversion accross calls.

Cons :

  • Heavily depends on how the program exepects the data.
    For example a Big Endian program access to a Little Endian memory zone which is in fact a string:

    char *buffer = {'a','b','c','\0'};
    define_le_zone(buffer, 4); // mprotect a memory region using our technics.

    Accessing it byte per byte will give a correct output:

    for( i = 0; i < 4; i++ )
      printf("buffer[%d] is %c\n",buffer[i]);


    buffer[0] is a
    buffer[1] is b
    buffer[2] is c
    buffer[3] is \0

    But accessing to this buffer int by int assuming that we are on a BE system won't be good:

    uint32_t a_int32 = *((uint32_t *)buffer); // This instruction causes the trouble
    char *buffer2 = {'\0','\0','\0','\0'}; // this buffer is not declared as little endian zone
    memcpy(buffer2, &a_int32, 4);
    for( i = 0; i < 4; i++ )
      printf("buffer2[%d] is %c\n",buffer2[i]);


    buffer2[0] is \0
    buffer2[1] is c
    buffer2[2] is b
    buffer2[3] is a

    Whereas it should give the same output as before.

On-the-fly byte swapping in Wine

  • wine/dlls/kernel/module.c (diff)

    This is the first point where Wine check to see if the exe/dll looks good

  • wine/server/mapping.c (diff)

    Here we can't use our technics since we are in the server. So swap everything.

  • tools/winedump/pe.c (diff)

    Bunch of swapping to do for this tool.

  • dlls/ntdll/signal_powerpc.c (diff)

    Has to be updated to forward signals to our signal handler.

  • dlls/ntdll/virtual.c (diff)

    VIRTUAL_SetProt needs to call our memory region manager in order to update the memory region (lock them again).

    map_image which maps an executable (PE format) image into memory has to be updated in order to be able to declare the mmaped memory region to be LE.

    Also in map_image the address asked is sometimes not available, and in some exe there is no relocation records so we have to skip the error.

  • wine/dlls/ntdll/loader.c

    Here we have to define emu_strlen/emu_strcmp, because the two functions behaves exactly like we fear previously. They access the char using int.

    In LdrInitializeThunk() we have to call SIGNAL_Init before loading the exe, because we wan't to catch the signal before. So we call it in __wine_process_init(). Note that we can also directly register an handler for the emu.

    In LdrInitializeThunk() we have to lock the vm allocated.

Current issues with Mac OS X/Wine
  • Initialisation sequence not working. (diff)

    An effect is the inability to load any dll. In fact it is due to Mac OS X's handling of weak symbols.

    Fix avalaible for dlls/tools/winebuild/spec32.c.

  • Delay import not working. (diff)

    An effect is the inability to load shell32.dll.

    To fix this issue we must investigate dlls/tools/winebuild/import.c.

    ../../tools/winegcc/winegcc -B../../tools/winebuild -shared ./shell32.spec shell.spec.o shell.o authors.o autocomplete.o brsfolder.o changenotify.o classes.o clipboard.o control.o cpanelfolder.o dataobject.o debughlp.o dialogs.o dragdrophelper.o enumidlist.o folders.o iconcache.o memorystream.o pidl.o regsvr.o shell32_main.o shelllink.o shellole.o shellord.o shellpath.o shellreg.o shellstring.o shfldr_desktop.o shfldr_fs.o shfldr_mycomp.o shlexec.o shlfileop.o shlfolder.o shlfsbind.o shlmenu.o shlview.o shpolicy.o shv_bg_cmenu.o shv_item_cmenu.o systray.o shell32.dll.dbg.o shres.res version.res -o -L../../dlls -Wb,-dole32 -lshlwapi -lcomctl32 -luser32 -lgdi32 -ladvapi32 -lkernel32 -L../../libs/wine -lwine -luuid -L../../libs/unicode -lwine_unicode -L../../libs/port -lwine_port -L../../libs/emu -lwine_emu -lresolv -lpoll

  • Delay Import still not working. (diff)

    An effect is the inability to run regedit.

    #15 0x005f10f8 in RtlRaiseException (rec=0x110f8b0) at exception.c:312
    #16 0x000b015c in __wine_delay_load ()
    #17 0x000b01b4 in __wine_spec_delayed_import_loaders ()
    #18 0x000b3fe4 in WinMain (hInstance=0xa0000, hPrevInstance=0x110eab0, lpCmdLine=0x8 <Address 0x8 out of bounds>, nCmdShow=1) at main.c:165
    #19 0x000b0858 in __wine_exe_main ()
    #20 0x020590bc in start_process (arg=0xe) at process.c:982

    fixme:seh:EXC_RtlRaiseException call to unimplemented function shlwapi.dll.GetSubMenu

  • Threading not working.

    An effect is the inability to run with the Desktop Window.

Useful tips
  • -save-temps option for winegcc.
  • -Wl,-read_only_relocs -Wl,suppress option for winegcc when compiling dlls which include libqemu.a

Contact : Pierre d'Herbemont