Bug 616040
| Summary: | system tap does not work properly for i386 objects over x86_64 | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Red Hat Enterprise Linux 5 | Reporter: | Menny Hamburger <mennyh> | ||||
| Component: | systemtap | Assignee: | Frank Ch. Eigler <fche> | ||||
| Status: | CLOSED DUPLICATE | QA Contact: | qe-baseos-tools-bugs | ||||
| Severity: | high | Docs Contact: | |||||
| Priority: | low | ||||||
| Version: | 5.5 | CC: | mjw | ||||
| Target Milestone: | rc | ||||||
| Target Release: | --- | ||||||
| Hardware: | All | ||||||
| OS: | Linux | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | Doc Type: | Bug Fix | |||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | Environment: | ||||||
| Last Closed: | 2010-11-29 16:57:15 UTC | Type: | --- | ||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Embargoed: | |||||||
| Attachments: |
|
||||||
Could you provide the test binary for inspection? Created attachment 433386 [details]
A 32 bit Samba vfs object
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; \
})
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;
}
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) \
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.
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 *** |
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; }