http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55940



             Bug #: 55940

           Summary: Incorrect code for accessing parameters with 32-bit

                    Intel hosts

    Classification: Unclassified

           Product: gcc

           Version: 4.7.2

            Status: UNCONFIRMED

          Severity: normal

          Priority: P3

         Component: target

        AssignedTo: unassig...@gcc.gnu.org

        ReportedBy: f...@os.inf.tu-dresden.de





There are some reports about incorrect compiled Linux kernel modules for

VirtualBox. I've debugged one report (see here:

https://www.virtualbox.org/ticket/11035) and saw that the compiler generated

invalid code for accessing parameters inside a function. When it should read

the parameter from the stack it reads the parameter from a register.



I don't know exactly under which circumstance this happens but this seems to be

related to 32-bit x86 targets. The function VBoxHost_RTR0MemObjGetPagePhysAddr

is marked as __attribute__((cdelc, regparm(0))). The pre-processed

memobj-r0drv.i file is attached to that ticket. The generated code is part of

the vboxdrv.ko file which is also attached to the ticket.



The following code is generated to access the first function parameter (keep

cdecl in mind!):



VBoxHost_RTR0MemObjGetPagePhysAddr():

/usr/src/virtualbox-bin-4.2.4_81684/vboxhost/vboxdrv/r0drv/memobj-r0drv.c:268

    955e:       8b 0f                   mov    (%edi),%ecx

    9560:       8b 47 04                mov    0x4(%edi),%eax

/usr/src/virtualbox-bin-4.2.4_81684/vboxhost/vboxdrv/r0drv/memobj-r0drv.c:272

    9563:       8d 91 00 10 00 00       lea    0x1000(%ecx),%edx



So the function is using the EDI register to access the parameter while it

should read the parameter from the stack.



The C code of this function looks (see memobj-r0drv.i) is:



RTHCPHYS __attribute__((cdecl,regparm(0)))

VBoxHost_RTR0MemObjGetPagePhysAddr(RTR0MEMOBJ MemObj, size_t iPage)

{



    PRTR0MEMOBJINTERNAL pMem;

    size_t cPages;

    do { if (__builtin_expect(!!(!(( (uintptr_t)(MemObj) + 0x1000U >= 0x2000U

))), 0)) return ((~(RTHCPHYS)0)); } while (0);

    ...



(Explanation of the code: This is actually a sanity check if the pointer is

valid; the value must be either less than 0xFFFFF000U or greater than

0x00000FFFU).



Unfortunately I cannot reproduce this problem myself (gcc 4.7.2 on my Linux

distribution creates correct code). The gcc compiler the user is using is



gcc version 4.7.2 (Exherbo gcc-4.7.2-r2)



(see comment 18 in the above ticket).

Reply via email to