qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] RFC: x86_64 Best way to fix 'cast to pointer from integer o


From: TJ
Subject: [Qemu-devel] RFC: x86_64 Best way to fix 'cast to pointer from integer of different size' problems?
Date: Sat, 03 Nov 2007 17:26:50 +0000

I'm building on x86_64 GNU/Linux. There are *lots* of (1053) compiler
warnings of the class:

warning: cast to pointer from integer of different size

caused by the various conversions to/from host-to-target pointer and int
types.

On x86 the warnings mostly don't occur. An easy way to get an idea of
the scale of the build problems is to review the Ubuntu build logs for
x86, x86_64, powerpc, and solaris (It's a 0.9.0 build and the solaris
build fails, but the x86_64 build log is clear although the line numbers
don't match CVS).

Fixing it looks to require a variety of fixes, from simple explicit
casts in-line, to some complicated review of multiple levels of macros
to decide where best to apply a fix.

I am aiming to work through all 1053 errors to classify the reasons for
them, and then work up a solution for each class.

If you could review the details here and provide useful feedback and
ides I'd be grateful. I don't want to redo work others are already doing
or go against some implicit techniques hidden in the macro nesting in
particular.

This should be considered alongside Thayne Harbaugh's post "[RFC]
linux-user (mostly syscall.c)".

Thanks

TJ.

--- specimen details ---

The first warning is also one of the most complex to unravel. It occurs
in  linux-user/syscall.c in functions

target_to_host_cmsg()
host_to_target_cmsg()

It is caused by use of the macro TARGET_CMSG_FIRSTHDR (which is a
reworking of the linux macro CMSG_FIRSTHDR defined in
<sys/bits/socket.h>):

static inline void target_to_host_cmsg(struct msghdr *msgh,
                                       struct target_msghdr *target_msgh) 
{
   struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);

The macro is defined thus:

linux-user/syscall_defs.h

    #define TARGET_CMSG_FIRSTHDR(mhdr) \
     ((size_t) tswapl((mhdr)->msg_controllen) >= sizeof (struct  
target_cmsghdr) \
     ? (struct target_cmsghdr *) tswapl((mhdr)->msg_control) : (struct 
target_cmsghdr *) NULL)

and the pre-processor generates:

 struct target_cmsghdr *target_cmsg = ((size_t) 
tswap32((target_msgh)->msg_controllen) >= sizeof (struct target_cmsghdr) ? 
(struct target_cmsghdr *) tswap32((target_msgh)->msg_control) : (struct 
target_cmsghdr *) ((void *)0));

The issue is in the 'true' action:

 (struct target_cmsghdr *) tswap32((target_msgh)->msg_control)

and the fact that the macro wasn't designed to handle different pointer
sizes. In this case assigning a 32-bit unsigned int to a 64-bit pointer.

The variables are defined as:

linux-user/syscall_defs.h
    struct target_msghdr { ...
     abi_long     msg_control;

linux-user/qemu.h
    #ifdef TARGET_ABI32
     typedef uint32_t abi_ulong;
     typedef int32_t abi_long;
     #define TARGET_ABI_BITS 32

and the 'tswap' function as:

cpu-all.h

static inline uint32_t tswap32(uint32_t s)
{
    return s;
}

So the compiler assigns the 32-bit value returned by tswap32() to the 64-bit 
pointer 'target_cmsg'.

For this case it appears the 'pure' solution would be to use additional
macros along the lines of:

struct target_cmsghdr *target_cmsg = TARGET_TO_HOST_PTR( 
TARGET_CMSG_FIRSTHDR(target_msgh));

and define new macros along the lines of

TARGET_TO_HOST_PTR
HOST_TO_TARGET_PTR

The practical solution is to promote the 32-bit unsigned integer to a
64-bit unsigned integer (using a cast) and then let the compiler do
implicit conversion to a 64-bit pointer.







reply via email to

[Prev in Thread] Current Thread [Next in Thread]