Bug 616040 - system tap does not work properly for i386 objects over x86_64
Summary: system tap does not work properly for i386 objects over x86_64
Keywords:
Status: CLOSED DUPLICATE of bug 606726
Alias: None
Product: Red Hat Enterprise Linux 5
Classification: Red Hat
Component: systemtap
Version: 5.5
Hardware: All
OS: Linux
low
high
Target Milestone: rc
: ---
Assignee: Frank Ch. Eigler
QA Contact: qe-baseos-tools-bugs
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2010-07-19 14:05 UTC by Menny Hamburger
Modified: 2011-05-13 12:45 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-11-29 16:57:15 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
A 32 bit Samba vfs object (186.88 KB, application/octet-stream)
2010-07-21 11:15 UTC, Menny Hamburger
no flags Details

Description Menny Hamburger 2010-07-19 14:05:05 UTC
I am running systemtap over a 32 bit binary running in x86_64.
the script is quite simple:
probe process("/usr/local/bin/test").function("*").call {
        log (probefunc()." ".$$parms)
}

stage 4 fails on many of these warnings (treated as errors):
warning: cast to pointer from integer of different size

When looking in the generated c files I see that the failures in the
function__dwarf_tvar_get_cookie_in_xxx   functions. specifically in the line:
{ uint32_t value = deref (4, addr); u_pieces0.pieces.p4 = value; }

Comment 1 Mark Wielaard 2010-07-19 14:42:57 UTC
Could you provide the test binary for inspection?

Comment 2 Menny Hamburger 2010-07-21 11:15:38 UTC
Created attachment 433386 [details]
A 32 bit Samba vfs object

Comment 3 Mark Wielaard 2010-07-21 12:09:42 UTC
Thanks. Confirmed. Also fails against latest upstream systemtap from git trunk.

stap -k -p4 -e  'probe process("./unixntacl.so").function("*").call {log (probefunc()." ".$$parms)}'
cc1: warnings being treated as errors
/tmp/stapPR4o9H/stap_14100.c: In function ‘function__dwarf_tvar_get_offset_97’:
/tmp/stapPR4o9H/stap_14100.c:2949: error: cast to pointer from integer of different size
/tmp/stapPR4o9H/stap_14100.c:2949: error: cast to pointer from integer of different size
/tmp/stapPR4o9H/stap_14100.c:2949: error: cast to pointer from integer of different size
/tmp/stapPR4o9H/stap_14100.c:2949: error: cast to pointer from integer of different size
make[1]: *** [/tmp/stapPR4o9H/stap_14100.o] Error 1
make: *** [_module_/tmp/stapPR4o9H] Error 2
Pass 4: compilation failed.  Try again with another '--vp 0001' option.
Keeping temporary directory "/tmp/stapPR4o9H"

Where line 2949 is:

    { int32_t value = deref (4, addr); u_pieces0.pieces.p4 = value; }

and deref is defined for __x86_64__ in runtime/loc2c-runtime.h as:

#define deref(size, addr)                                                     \
  ({                                                                          \
    int _bad = 0;                                                             \
    u8 _b; u16 _w; u32 _l; u64 _q;                                            \
    intptr_t _v = 0;                                                          \
    if (lookup_bad_addr((unsigned long)addr, size))                           \
      _bad = 1;                                                               \
    else                                                                      \
      switch (size)                                                           \
        {                                                                     \
        case 1: __get_user_asm(_b,addr,_bad,"b","b","=q",1); _v = _b; break;  \
        case 2: __get_user_asm(_w,addr,_bad,"w","w","=r",1); _v = _w; break;  \
        case 4: __get_user_asm(_l,addr,_bad,"l","","=r",1); _v = _l; break;   \
        case 8: __get_user_asm(_q,addr,_bad,"q","","=r",1); _v = _q; break;   \
        default: _v = __get_user_bad();                                       \
        }                                                                     \
    if (_bad)                                                                 \
      DEREF_FAULT(addr);                                                              \
    _v;                                                                       \
  })

Comment 4 Mark Wielaard 2010-07-21 12:49:50 UTC
The whole context of the generated loc2c part is:

#define fetch_register u_fetch_register
#define store_register u_store_register
{
  {
    union {
      char bytes[8];
      struct {
        uint32_t p0;
        uint32_t p4;
      } pieces __attribute__ ((packed));
      uint64_t whole;
    } u_pieces0;
    uint32_t addr;
    { int32_t value = fetch_register (6); u_pieces0.pieces.p0 = value; }
    { // DWARF expression: 0x75(32)
      {
        uintptr_t s0;
        s0 = fetch_register (5) + 32L;
        addr = s0;
      }
    }
    { int32_t value = deref (4, addr); u_pieces0.pieces.p4 = value; }
    THIS->__retvalue = u_pieces0.whole;
  }
  goto out;
if (0) goto deref_fault;
deref_fault:
  goto out;
}

Comment 5 Mark Wielaard 2010-07-21 12:57:45 UTC
Frank pointed out that the address fetched is 32bit (because from 32bit app), but then used by deref on a 64bit host. So the fix seems to be:

diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index 90c392d..eeb7cdb 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -517,10 +517,10 @@ extern void __store_deref_bad(void);
     else                                                                      \
       switch (size)                                                           \
         {                                                                     \
-        case 1: __get_user_asm(_b,addr,_bad,"b","b","=q",1); _v = _b; break;  \
-        case 2: __get_user_asm(_w,addr,_bad,"w","w","=r",1); _v = _w; break;  \
-        case 4: __get_user_asm(_l,addr,_bad,"l","","=r",1); _v = _l; break;   \
-        case 8: __get_user_asm(_q,addr,_bad,"q","","=r",1); _v = _q; break;   \
+        case 1: __get_user_asm(_b,(unsigned long)addr,_bad,"b","b","=q",1); _v = _b; break;  \
+        case 2: __get_user_asm(_w,(unsigned long)addr,_bad,"w","w","=r",1); _v = _w; break;  \
+        case 4: __get_user_asm(_l,(unsigned long)addr,_bad,"l","","=r",1); _v = _l; break;   \
+        case 8: __get_user_asm(_q,(unsigned long)addr,_bad,"q","","=r",1); _v = _q; break;   \
         default: _v = __get_user_bad();                                       \
         }                                                                     \
     if (_bad)                                                                \

Comment 6 Mark Wielaard 2010-07-21 14:01:40 UTC
Pushed upstream:

commit 31f7f175720b0756bbf022a977a1e3a687bd96da
Author: Mark Wielaard <mjw>
Date:   Wed Jul 21 15:59:27 2010 +0200

    rhbz#616040 loc2c deref on 32bit address fails.
    
    * runtime/loc2c-runtime.h (deref): For __x86_64__ case cast address to
      (unsigned long) everywhere in case we got a 32 bit address of a 32-on-64
      but process.

Comment 7 Frank Ch. Eigler 2010-11-29 16:57:15 UTC
This problem is fixed automatically with the rhel5.6-bound version 1.3 rebase.

*** This bug has been marked as a duplicate of bug 606726 ***


Note You need to log in before you can comment on or make changes to this bug.