• IOPL code with Watcom C

    From Vitus Jensen@2:2474/424.1 to All on Sunday, November 26, 2000 18:55:18
    Hi All!

    I'm trying to create a sample program for Watcom C 10.5 which demonstrates IOPL
    code. Usually I'm doing this with ALP and IBM Visual Age but this time it has to be an all Watcom solution (16 bit C, 32 bit C(++), wlink).

    Well, it doesn't work (obviously, that's why I'm writing this msg :-|). The problem isn't the 16 bit code (that's the same i used with VAC++), it's the thunking which isn't working right. Watcom keeps on calling the IOPL directly from it's 16 bit thunking code instead of using a callgate.

    Perhaps someone can tell me what I'm doing wrong...


    Compilation:
    wcc -zq -ml -zl -zdf -zu -nt=R2CODE -2 -s -i=$(WATCOM)\h\os21x io16.c
    wpp386 -zq -bt=OS2 -3s -s -i=$(WATCOM)\h\os2 test16.cpp
    wcl386 -zq -l=OS2V2 -3s -fm @io16.lnk test16.obj io16.obj

    io16.lnk:
    SEGment R2CODE IOPL
    EXP INB 2, INW 2, IND 2, OUTB 4, OUTW 4, OUTD 6


    I'm using the following prototypes:

    ==================<io16.h>==================================
    #if !defined(APIENTRY16)
    # if defined(__WATCOMC__)
    # if defined(__386__)
    # define APIENTRY16 _Far16 _Pascal
    # else
    # define APIENTRY16 __far __pascal
    # endif
    # elif defined(__IBMC__) || defined(__IBMCPP__)
    # define APIENTRY16 _Far16 _Pascal
    # endif
    #endif

    extern unsigned char APIENTRY16 inb(unsigned short __port);
    ...
    ======================<end>=================================


    The whole thing compiles to the following assembler code:

    =====================<start>================================ `W?command_write$n(i)v`:
    push esp
    push 00000004H
    push 00000024H
    call near ptr __TNK
    push esi
    sub esp,00000018H
    mov dword ptr +10H[esp],000003beH
    mov ecx,00000002H
    lea esi,+10H[esp]
    mov eax,INB ; 0x000E0000
    call near ptr __Far16Func2
    and al,0d0H
    movzx edx,al
    ...
    ======================<end>=================================

    This looks quite good (don't know nothing about __TNK), the address of INB is indeed 000E:0000, selector 000E is ring 2 and '__Far16Func2' sounds like a thunking call.
    But when I run the executable, __Far16Func2 finally ends here:

    =====================<start>================================
    0017:0000 mov cs,ss
    0017:0002 mov ds,cx
    0017:0004 mov es,cx
    0017:0006 call dword ptr [bp+0] ; 0x000E0000 ======================<end>=================================

    The call fails (GPE) and IMHO because 0017 is ring 3 and 000E is ring 2 and you
    can't call ring 2 directly from ring 3.
    Again, where is my fault?

    Bye,
    Vitus

    PS: there is sample code for watcom floating around but it uses either IOPL code or 32->16 bit calls not both combined.
    PPS: complete source code on request.

    ---
    * Origin: COFFEED: Coffee Deamon startup (2:2474/424.1)
  • From Jonathan de Boyne Pollard@2:257/609.3 to Vitus Jensen on Tuesday, November 28, 2000 17:55:00
    mov eax,INB ; 0x000E0000

    If that really *isn't* a call gate (double-check it) then I suspect a linker problem. Dump the executable and look at the fixups for the page containing that particular piece of code.

    » JdeBP «

    --- FleetStreet 1.22 NR
    * Origin: JdeBP's point, using Squish <yuk!> (2:257/609.3)
  • From Vitus Jensen@2:2474/424.1 to Jonathan de Boyne Pollard on Thursday, November 30, 2000 18:08:14
    Moin Jonathan!

    29.11.2000, Jonathan de Boyne Pollard wrote a message to Vitus Jensen:

    mov eax,INB ; 0x000E0000

    JdBP> If that really *isn't* a call gate (double-check it) then I suspect
    JdBP> a linker problem. Dump the executable and look at the fixups for
    JdBP> the page containing that particular piece of code.

    There is only one answer: how? Don't expect that I know all the details about LX excutables.


    Let's see what i have:

    Watcom debugger, expect memory: entering 0x000E:0000 tells me I'm at INB+0 and the hex dump shows all the correct opcodes.

    exehdr mmpdemo.exe: INB resides in page 1, offset 0:

    no. virtual virtual map map flags
    address size index size
    0001 00010000 00000059 00000001 00000001 EXECUTABLE, READABLE, NONSHARED,
    PRELOAD, NONCONFORMING, NONRESOURCE,
    NONDISCARDABLE, VALID-PAGES, SWAPPABLE,

    16:16 ALIAS, 16-bit, IOPL
    map physical page flags
    entry page @ size
    00000001 00000600 0059 VALID
    0002 00020000 0000006e 00000002 00000001 EXECUTABLE, READABLE, PRELOAD,
    16:16 ALIAS
    0003 00030000 00012430 00000003 00000001 READABLE, WRITEABLE, PRELOAD, 32-bit 0004 00050000 00001dfc 00000004 00000002 EXECUTABLE, READABLE, NONSHARED,
    PRELOAD, NONCONFORMING, NONRESOURCE,
    NONDISCARDABLE, VALID-PAGES, SWAPPABLE,

    NO 16:16 ALIAS, 32-bit, NOIOPL
    map physical page flags
    entry page @ size
    00000001 000008a2 1000 VALID
    00000002 000018a2 0dfb VALID


    Exports:
    ord obj offset name
    1 1 00000000 INB exported, 1 parm wds
    ...



    Now I need to check where the calls to INB are located? Inside page 4.
    exehdr mmpdemo.exe /v:

    page 4 type offset target
    obj 4:0000 16:16 PTR 0033 object 1 offset 0000 alias
    16:16 PTR 005a object 1 offset 0028 alias
    16:16 PTR 0075 object 1 offset 0000 alias
    16:16 PTR 0099 object 1 offset 0028 alias

    Physical page starts at file offset 0x08a2, relative offset 0x33 is filled with
    0. The bytes match the expected opcodes.

    000008a0: 0e05 cceb fd90 9090 9000 0000 0000 0000 ................
    000008b0: 0000 546a 0468 2400 0000 e88f 0300 0056 ..Tj.h$........V
    000008c0: 83ec 18c7 4424 10be 0300 00b9 0200 0000 ....D$..........
    000008d0: 8d74 2410 b800 0000 00e8 c003 0000 24d0 .t$...........$.


    Did I include the information you wanted me to check? It looks quite usual to me...

    Bye,
    Vitus

    ---
    * Origin: Never hit a man with glasses. Use your fist! (2:2474/424.1)
  • From Jonathan de Boyne Pollard@2:257/609.3 to Vitus Jensen on Saturday, December 16, 2000 08:32:36
    mov eax,INB ; 0x000E0000

    JdBP>> If that really *isn't* a call gate (double-check it) then I suspect
    JdBP>> a linker problem. Dump the executable and look at the fixups for
    JdBP>> the page containing that particular piece of code.

    There is only one answer: how?

    You picked the right tool, EXEHDR, anyway, so I won't bother answering that question. (-:

    Watcom debugger, expect memory: entering 0x000E:0000 tells me I'm at
    INB+0 and the hex dump shows all the correct opcodes.

    That would indicate that 0x000E is the actual code selector for that segment rather than a call gate. So the next thing to find is the part of the LX file that represents the above MOV instruction.

    Now I need to check where the calls to INB are located? Inside page 4. exehdr mmpdemo.exe /v:

    page 4 type offset target
    obj 4:0000 16:16 PTR 0033 object 1 offset 0000 alias
    16:16 PTR 005a object 1 offset 0028 alias
    16:16 PTR 0075 object 1 offset 0000 alias
    16:16 PTR 0099 object 1 offset 0028 alias

    I'll have to double-check, but that doesn't look like a correct fixup.

    » JdeBP «

    --- FleetStreet 1.22 NR
    * Origin: JdeBP's point, using Squish <yuk!> (2:257/609.3)