Bug 3079 - deref macro cannot read 64-bit values on 32-bit x86
Summary: deref macro cannot read 64-bit values on 32-bit x86
Status: RESOLVED FIXED
Alias: None
Product: systemtap
Classification: Unclassified
Component: runtime (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Josh Stone
URL:
Keywords:
: 3879 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-08-16 23:19 UTC by Josh Stone
Modified: 2007-01-22 23:46 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Josh Stone 2006-08-16 23:19:26 UTC
On 32-bit x86, this fails:

function deref64:long() %{
    int64_t a = 42;
    THIS->__retvalue = deref(sizeof(a), &a);
    if (0) {
deref_fault:
        CONTEXT->last_error = "bad stuff happened";
    }
%}
probe begin {
    printf("%d\n", deref64())
    exit()
}

Error messages:
...
{standard input}: Assembler messages:
{standard input}:8811: Error: suffix or operands invalid for `movq'
{standard input}:8815: Error: suffix or operands invalid for `xor'
...

This results from improper use of __get_user_asm().  In 32-bit mode, 'mov' and
'xor' cannot deal with 64-bit quantities.

Probably the fix will need to make two 32-bit calls to __get_user_asm to get the
whole 64-bit quantity (nothing says this needs to be atomic anyway).  There's
still a problem with the "return-value" of deref, an intptr_t, as it can't hold
a 64-bit value.  And we can't change the return type to int64_t, because that
won't cleanly typecast to pointers.

I imagine the semantics of deref will need to change a bit, perhaps to something
like this:

#define deref(var)  deref_ex(typeof(var), sizeof(var), &(var))
#define deref_ex(type, size, addr)  ... /* return type is (type) */

I will probably tackle this bug myself, but I wanted to solicit ideas/feedback
from others before I try it...
Comment 1 Roland McGrath 2006-08-16 23:24:36 UTC
Don't use deref for that.
The loc2c-runtime.h macros are for the loc2c-generated code.
They are not intended as general purpose facilities.
loc2c never generates accesses wider than word size.
On 32-bit platforms, 64-bit quantities are sometimes located in two separate
words not contiguous in memory, and the DWARF information and loc2c know how to
handle this.
Comment 2 Josh Stone 2006-08-16 23:38:26 UTC
(In reply to comment #1)
> Don't use deref for that.
> The loc2c-runtime.h macros are for the loc2c-generated code.
> They are not intended as general purpose facilities.

Then we need a separate 'deref' for use outside of loc2c-generated code.  A lot
of tapset code needs to have a safe way to dereference pointers, so that any
faults caused by bad pointers can be caught and reported as errors.

This may be related to bug #1303, but that's talking about broadly catching
faults, while here I want explicit fault handling.

We can redirect the solution to using something besides 'deref' if you like, but
please don't close the bug until we've actually solved the issue at hand.
Comment 3 Frank Ch. Eigler 2007-01-17 18:02:01 UTC
*** Bug 3879 has been marked as a duplicate of this bug. ***
Comment 4 Josh Stone 2007-01-20 03:12:04 UTC
I created two new macros, kread and kwrite, which act as wrappers for deref and
store_deref.  As a special case on i386, these split 64-bit accesses into two
32-bit accesses, whereas other platforms map directly to deref.

For the convenience of tapset writers, these new macros don't require a size
parameter; instead they infer the size from the pointer type.  The return value
from kread is also cast appropriately.
Comment 5 Frank Ch. Eigler 2007-01-22 22:43:21 UTC
Josh, do you intend to change at least the problematic tapsets
to call this new facility? (See bug #3879).
Comment 6 Josh Stone 2007-01-22 23:46:53 UTC
(In reply to comment #5)
> Josh, do you intend to change at least the problematic tapsets
> to call this new facility? (See bug #3879).

Yes, I will address this.  I actually just discovered a problem with using kread
to get 32-bit pointers, but once I figure that out I will go through the
tapsets.  I would like to fully migrate the tapsets to these new calls, but I'll
start with the problematic ones first.