Bug 79939

Summary: xorg-server : fails to compile for MIPS variants with 32-bit pointers
Product: xorg Reporter: Vicente Olivert Riera <vincent.riera>
Component: Server/GeneralAssignee: Xorg Project Team <xorg-team>
Status: RESOLVED FIXED QA Contact: Xorg Project Team <xorg-team>
Severity: normal    
Priority: medium    
Version: unspecified   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments:
Description Flags
0001-backtrace.c-Fix-word-cast-to-a-pointer.patch none

Description Vicente Olivert Riera 2014-06-12 10:32:43 UTC
It fails to compile for MIPS64 n32 platforms when it detects that libunwind is installed.

The error message is this one:

#####################################################################
Making all in os
make[2]: Entering directory `/home/test/test/1/output/build/xserver_xorg-server-1.15.1/os'
  CC     WaitFor.lo
  CC     access.lo
  CC     auth.lo
  CC     backtrace.lo
backtrace.c: In function 'xorg_backtrace':
backtrace.c:90:20: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
         if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
                    ^
backtrace.c:98:13: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
             (void *)(pip.start_ip + off));
             ^
cc1: some warnings being treated as errors
make[2]: *** [backtrace.lo] Error 1
make[2]: *** Waiting for unfinished jobs....
#####################################################################

Here is the explanation about what is happening:

# XORG code #
os/backtrace.c includes the file libunwind.h

# LIBUNWIND code #
libunwind.h
 |- libunwind-mips.h
     |- typedef uint64_t unw_word_t;
     |- libunwind-common.h -> typedef struct unw_proc_info -> unw_word_t start_ip;

So, the start_ip member of the structure unw_proc_info is actually a 64-bit unsigned integer.

# XORG code #
os/backtrace.c line #49
It does this: "unw_proc_info_t pip;"
So the "pip" variable is a structure which has a start_ip member inside, which is a 64-bit unsigned integer.

os/backtrace.c line #90
Is trying to do this: "(void *)(pip.start_ip + off)"
The problem is that "(pip.start_ip + off)" is 64-bit and "(void *)" is 32-bit, because MIPS64 n32 has 32-bit pointers.

Same problem at line #98
Comment 1 Vicente Olivert Riera 2014-10-09 15:33:34 UTC
ping
Comment 2 Alan Coopersmith 2014-10-09 15:40:51 UTC
I don't believe any Xorg developers have any  MIPS64 n32 platforms, nor will
they be finding a way to test & fix bugs in them.

If someone wants to maintain Xorg for these platforms, they'll need to fix
the bugs they hit and submit patches to the xorg-devel mailing list just as
all other platform maintainers do.  There is no magic solution to make fixes
appear with no one willing to work on them.
Comment 3 cagney 2014-12-03 02:58:11 UTC
Change the casts in backtrace.c to something like:

  (void*)(long)(pip.start_ip + off)
or
  (void*)(off_t)(pip.start_ip + off)

The intent is to first cast the "word" to a pointer-sized integer, and then cast that to a pointer.

On n32, while a sizeof(void*) is 32-bit, it is stored in a register and on the stack as a 64-bit (sign extended) value.

Look for MIPSpro(tm) N32 ABI Handbook using your favourite search engine.
Comment 4 Vicente Olivert Riera 2014-12-03 12:00:45 UTC
Created attachment 110406 [details] [review]
0001-backtrace.c-Fix-word-cast-to-a-pointer.patch

(In reply to cagney from comment #3)
> Change the casts in backtrace.c to something like:
> 
>   (void*)(long)(pip.start_ip + off)
> or
>   (void*)(off_t)(pip.start_ip + off)
> 
> The intent is to first cast the "word" to a pointer-sized integer, and then
> cast that to a pointer.
> 
> On n32, while a sizeof(void*) is 32-bit, it is stored in a register and on
> the stack as a 64-bit (sign extended) value.
> 
> Look for MIPSpro(tm) N32 ABI Handbook using your favourite search engine.

I have tried it with MIPS32, MIPS64 n32 and MIPS64 n64. It compiled fine in all cases. I have attached a patch, so please, review it and apply it if you think is valid.

Thanks.
Comment 5 Vicente Olivert Riera 2014-12-05 10:38:49 UTC
Just for the record, this failure is present also for MIPS32. And the reason is exactly the same. libunwind uses a uint64 variable to store the words, and Xorg tries to cast that variable (64-bit) into a pointer (32-bit).

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.