summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-09-09 20:00:13 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-09-09 20:00:13 -0400
commit23b3bb31858e54b8a10ad570a3bc8ad49487d725 (patch)
tree0096ff3573baefdb7cffc55574266587e0e8283b /runtime
parent5ff217f44e1e069fcfbd59c27866afef35a61c9a (diff)
parent256d22cfb336b4cf0ec5b35bab89ca55ff5ce9ee (diff)
downloadsystemtap-steved-23b3bb31858e54b8a10ad570a3bc8ad49487d725.tar.gz
systemtap-steved-23b3bb31858e54b8a10ad570a3bc8ad49487d725.tar.xz
systemtap-steved-23b3bb31858e54b8a10ad570a3bc8ad49487d725.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
* 'master' of ssh://sources.redhat.com/git/systemtap: Added tests for utrace-syscall probe context variables. Add $return context variables on per-process-syscall.return probes Add $argN context variables on per-process-syscall probes Add $name context variable support on marker probes Utrace on ia64 fast fetch-register support Add ia64 utrace support Correct this_section_offset calculation in _stp_kallsyms_lookup. tiny grammar fix in NEWS separated Scripts, edited accordingly PR1288: runtime functions for avoiding certain addresses remove test tag added content for Ch1 and 2, to add more later
Diffstat (limited to 'runtime')
-rw-r--r--runtime/ChangeLog28
-rw-r--r--runtime/addr-map.c181
-rw-r--r--runtime/loc2c-runtime.h230
-rw-r--r--runtime/regs-ia64.c21
-rw-r--r--runtime/runtime.h1
-rw-r--r--runtime/sym.c2
-rw-r--r--runtime/syscall.h42
-rw-r--r--runtime/task_finder.c6
8 files changed, 409 insertions, 102 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog
index 8f20ed11..f7a844d8 100644
--- a/runtime/ChangeLog
+++ b/runtime/ChangeLog
@@ -1,3 +1,31 @@
+2008-09-09 Masami Hiramatsu <mhiramat@redhat.com>
+
+ * regs-ia64.c (__ia64_fetch_register): Return the address of the
+ register.
+ (ia64_fetch_register): Use __ia64_fetch_register.
+ * syscall.h (____stp_user_syscall_arg): Use __ia64_fetch_register.
+ (__stp_user_syscall_arg): Wrapping ____stp_user_syscall_arg to pass the
+ unwind address cache.
+ * task_finder.c (__stp_utrace_task_finder_target_syscall_): Added dummy
+ unwind address cache.
+
+2008-09-09 Masami Hiramatsu <mhiramat@redhat.com>
+
+ * syscall.h: Added ia64 support.
+
+2008-09-09 Mark Wielaard <mwielaard@redhat.com>
+
+ * sym.c (_stp_kallsyms_lookup): Correct this_section_offset
+ calculation.
+
+2008-09-08 Tim Moore <timoore@redhat.com>
+
+ PR 1288
+ * addr-map.c: New file with functions for looking up addresses
+ * loc2c-runtime.h (deref, store_deref): Use lookup_bad_addr to
+ avoid dereferencing known dangerous addresses.
+ * runtime.h: Include addr-map.c.
+
2008-09-06 Frank Ch. Eigler <fche@elastic.org>
PR 6445
diff --git a/runtime/addr-map.c b/runtime/addr-map.c
new file mode 100644
index 00000000..8231b57f
--- /dev/null
+++ b/runtime/addr-map.c
@@ -0,0 +1,181 @@
+/* -*- linux-c -*-
+ * Map of addresses to disallow.
+ * Copyright (C) 2005-2008 Red Hat Inc.
+ *
+ * This file is part of systemtap, and is free software. You can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+#ifndef _ADDR_MAP_C_
+#define _ADDR_MAP_C_ 1
+
+/** @file addr-map
+ * @brief Implements functions used by the deref macro to blacklist
+ * certain addresses.
+ */
+
+struct addr_map_entry
+{
+ unsigned long min;
+ unsigned long max;
+};
+
+struct addr_map
+{
+ size_t size;
+ struct addr_map_entry entries[0];
+};
+
+static DEFINE_SPINLOCK(addr_map_lock);
+
+struct addr_map* blackmap;
+
+/* Find address of entry where we can insert a new one. */
+static size_t
+upper_bound(unsigned long addr, struct addr_map* map)
+{
+ size_t start = 0;
+ size_t end = map->size;
+ struct addr_map_entry *entry = 0;
+
+ if (end == 0)
+ return 0;
+ do
+ {
+ size_t new_idx;
+ if (addr < map->entries[start].min)
+ return start;
+ if (addr >= map->entries[end-1].max)
+ return end;
+ new_idx = (end + start) / 2;
+ entry = &map->entries[new_idx];
+ if (addr < entry->min)
+ end = new_idx;
+ else
+ start = new_idx + 1;
+ } while (end != start);
+ return entry - &map->entries[0];
+}
+
+static struct addr_map_entry*
+lookup_addr_aux(unsigned long addr, struct addr_map* map)
+{
+ size_t start = 0;
+ size_t end;
+ if (!map)
+ return 0;
+ end = map->size;
+ if (map->size == 0)
+ return 0;
+
+ do
+ {
+ int entry_idx;
+ struct addr_map_entry *entry = 0;
+ if (addr < map->entries[start].min || addr >= map->entries[end - 1].max)
+ return 0;
+ entry_idx = (end + start) / 2;
+ entry = &map->entries[entry_idx];
+ if (entry->min <= addr && entry->max > addr)
+ return entry;
+ if (addr < entry->min)
+ end = entry_idx;
+ else
+ start = entry_idx + 1;
+ } while (start < end);
+ return 0;
+}
+
+int
+lookup_bad_addr(unsigned long addr)
+{
+ struct addr_map_entry* result = 0;
+ spin_lock(&addr_map_lock);
+ result = lookup_addr_aux(addr, blackmap);
+ spin_unlock(&addr_map_lock);
+ if (result)
+ return 1;
+ else
+ return 0;
+}
+
+
+int
+add_bad_addr_entry(unsigned long min_addr, unsigned long max_addr,
+ struct addr_map_entry** existing_min,
+ struct addr_map_entry** existing_max)
+{
+ struct addr_map* new_map = 0;
+ struct addr_map* old_map = 0;
+ struct addr_map_entry* min_entry = 0;
+ struct addr_map_entry* max_entry = 0;
+ struct addr_map_entry* new_entry = 0;
+ size_t existing = 0;
+
+ while (1)
+ {
+ size_t old_size;
+ spin_lock(&addr_map_lock);
+ old_map = blackmap;
+ if (!blackmap)
+ {
+ existing = 0;
+ old_size = 0;
+ }
+ else
+ {
+ min_entry = lookup_addr_aux(min_addr, blackmap);
+ max_entry = lookup_addr_aux(max_addr, blackmap);
+ if (min_entry || max_entry)
+ {
+ if (existing_min)
+ *existing_min = min_entry;
+ if (existing_max)
+ *existing_max = max_entry;
+ spin_unlock(&addr_map_lock);
+ return 1;
+ }
+ existing = upper_bound(min_addr, old_map);
+ old_size = old_map->size;
+ }
+ spin_unlock(&addr_map_lock);
+ new_map = kmalloc(sizeof(*new_map)
+ + sizeof(*new_entry) * (old_size + 1),
+ GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+ spin_lock(&addr_map_lock);
+ if (blackmap != old_map)
+ {
+ kfree(new_map);
+ spin_unlock(&addr_map_lock);
+ continue;
+ }
+ new_entry = &new_map->entries[existing];
+ new_entry->min = min_addr;
+ new_entry->max = max_addr;
+ if (old_map)
+ {
+ memcpy(&new_map->entries, old_map->entries,
+ existing * sizeof(*new_entry));
+ if (old_map->size > existing)
+ memcpy(new_entry + 1, &old_map->entries[existing + 1],
+ (old_map->size - existing) * sizeof(*new_entry));
+ }
+ new_map->size = blackmap->size + 1;
+ blackmap = new_map;
+ spin_unlock(&addr_map_lock);
+ if (old_map)
+ kfree(old_map);
+ return 0;
+ }
+}
+
+void
+delete_bad_addr_entry(struct addr_map_entry* entry)
+{
+}
+
+#endif
diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h
index 1247da51..0af19edc 100644
--- a/runtime/loc2c-runtime.h
+++ b/runtime/loc2c-runtime.h
@@ -201,6 +201,8 @@
#define deref(size, addr) ({ \
intptr_t _i; \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ __deref_bad(); \
switch (size) { \
case 1: _i = kread((u8 *)(addr)); break; \
case 2: _i = kread((u16 *)(addr)); break; \
@@ -213,6 +215,8 @@
})
#define store_deref(size, addr, value) ({ \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ __store_deref_bad(); \
switch (size) { \
case 1: kwrite((u8 *)(addr), (value)); break; \
case 2: kwrite((u16 *)(addr), (value)); break; \
@@ -234,30 +238,36 @@ extern void __store_deref_bad(void);
int _bad = 0; \
u8 _b; u16 _w; u32 _l; \
intptr_t _v; \
- 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; \
- default: _v = __get_user_bad(); \
- } \
- if (_bad) \
- DEREF_FAULT(addr); \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _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; \
+ default: _v = __get_user_bad(); \
+ } \
+ if (_bad) \
+ DEREF_FAULT(addr); \
_v; \
})
#define store_deref(size, addr, value) \
({ \
int _bad = 0; \
- switch (size) \
- { \
- case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break; \
- case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break; \
- case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break; \
- default: __put_user_bad(); \
- } \
- if (_bad) \
- STORE_DEREF_FAULT(addr); \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size) \
+ { \
+ case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break;\
+ case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break;\
+ case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break;\
+ default: __put_user_bad(); \
+ } \
+ if (_bad) \
+ STORE_DEREF_FAULT(addr); \
})
@@ -268,14 +278,17 @@ extern void __store_deref_bad(void);
int _bad = 0; \
u8 _b; u16 _w; u32 _l; u64 _q; \
intptr_t _v; \
- 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 (lookup_bad_addr((unsigned long)addr)) \
+ _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; \
@@ -284,14 +297,17 @@ extern void __store_deref_bad(void);
#define store_deref(size, addr, value) \
({ \
int _bad = 0; \
- switch (size) \
- { \
- case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break; \
- case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break; \
- case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break; \
- case 8: __put_user_asm(((u64)(value)),addr,_bad,"q","","Zr",1); break; \
- default: __put_user_bad(); \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size) \
+ { \
+ case 1: __put_user_asm(((u8)(value)),addr,_bad,"b","b","iq",1); break; \
+ case 2: __put_user_asm(((u16)(value)),addr,_bad,"w","w","ir",1); break;\
+ case 4: __put_user_asm(((u32)(value)),addr,_bad,"l","k","ir",1); break;\
+ case 8: __put_user_asm(((u64)(value)),addr,_bad,"q","","Zr",1); break; \
+ default: __put_user_bad(); \
+ } \
if (_bad) \
STORE_DEREF_FAULT(addr); \
})
@@ -301,13 +317,16 @@ extern void __store_deref_bad(void);
({ \
int _bad = 0; \
intptr_t _v=0; \
- switch (size){ \
- case 1: __get_user_size(_v, addr, 1, _bad); break; \
- case 2: __get_user_size(_v, addr, 2, _bad); break; \
- case 4: __get_user_size(_v, addr, 4, _bad); break; \
- case 8: __get_user_size(_v, addr, 8, _bad); break; \
- default: __get_user_unknown(); break; \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size){ \
+ case 1: __get_user_size(_v, addr, 1, _bad); break; \
+ case 2: __get_user_size(_v, addr, 2, _bad); break; \
+ case 4: __get_user_size(_v, addr, 4, _bad); break; \
+ case 8: __get_user_size(_v, addr, 8, _bad); break; \
+ default: __get_user_unknown(); break; \
+ } \
if (_bad) \
DEREF_FAULT(addr); \
_v; \
@@ -316,13 +335,16 @@ extern void __store_deref_bad(void);
#define store_deref(size, addr, value) \
({ \
int _bad=0; \
- switch (size){ \
- case 1: __put_user_size(value, addr, 1, _bad); break; \
- case 2: __put_user_size(value, addr, 2, _bad); break; \
- case 4: __put_user_size(value, addr, 4, _bad); break; \
- case 8: __put_user_size(value, addr, 8, _bad); break; \
- default: __put_user_unknown(); break; \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size){ \
+ case 1: __put_user_size(value, addr, 1, _bad); break; \
+ case 2: __put_user_size(value, addr, 2, _bad); break; \
+ case 4: __put_user_size(value, addr, 4, _bad); break; \
+ case 8: __put_user_size(value, addr, 8, _bad); break; \
+ default: __put_user_unknown(); break; \
+ } \
if (_bad) \
STORE_DEREF_FAULT(addr); \
})
@@ -373,30 +395,36 @@ extern void __store_deref_bad(void);
({ \
int _bad = 0; \
intptr_t _v; \
- switch (size) \
- { \
- case 1: __stp_get_user_asm(_v,addr,_bad,"lbz"); break; \
- case 2: __stp_get_user_asm(_v,addr,_bad,"lhz"); break; \
- case 4: __stp_get_user_asm(_v,addr,_bad,"lwz"); break; \
- case 8: __stp_get_user_asm(_v,addr,_bad,"ld"); break; \
- default: _v = __get_user_bad(); \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size) \
+ { \
+ case 1: __stp_get_user_asm(_v,addr,_bad,"lbz"); break; \
+ case 2: __stp_get_user_asm(_v,addr,_bad,"lhz"); break; \
+ case 4: __stp_get_user_asm(_v,addr,_bad,"lwz"); break; \
+ case 8: __stp_get_user_asm(_v,addr,_bad,"ld"); break; \
+ default: _v = __get_user_bad(); \
+ } \
if (_bad) \
- DEREF_FAULT(addr); \
+ DEREF_FAULT(addr); \
_v; \
})
#define store_deref(size, addr, value) \
({ \
int _bad = 0; \
- switch (size) \
- { \
- case 1: __stp_put_user_asm(((u8)(value)),addr,_bad,"stb"); break; \
- case 2: __stp_put_user_asm(((u16)(value)),addr,_bad,"sth"); break; \
- case 4: __stp_put_user_asm(((u32)(value)),addr,_bad,"stw"); break; \
- case 8: __stp_put_user_asm(((u64)(value)),addr,_bad, "std"); break; \
- default: __put_user_bad(); \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size) \
+ { \
+ case 1: __stp_put_user_asm(((u8)(value)),addr,_bad,"stb"); break; \
+ case 2: __stp_put_user_asm(((u16)(value)),addr,_bad,"sth"); break; \
+ case 4: __stp_put_user_asm(((u32)(value)),addr,_bad,"stw"); break; \
+ case 8: __stp_put_user_asm(((u64)(value)),addr,_bad, "std"); break; \
+ default: __put_user_bad(); \
+ } \
if (_bad) \
STORE_DEREF_FAULT(addr); \
})
@@ -541,12 +569,15 @@ extern void __store_deref_bad(void);
({ \
int _bad = 0; \
intptr_t _v=0; \
- switch (size){ \
- case 1: __stp_get_user_asm_byte(_v, addr, _bad); break; \
- case 2: __stp_get_user_asm_half(_v, addr, _bad); break; \
- case 4: __stp_get_user_asm_word(_v, addr, _bad); break; \
- default: __get_user_bad(); break; \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size){ \
+ case 1: __stp_get_user_asm_byte(_v, addr, _bad); break; \
+ case 2: __stp_get_user_asm_half(_v, addr, _bad); break; \
+ case 4: __stp_get_user_asm_word(_v, addr, _bad); break; \
+ default: __get_user_bad(); break; \
+ } \
if (_bad) \
DEREF_FAULT(addr); \
_v; \
@@ -555,13 +586,16 @@ extern void __store_deref_bad(void);
#define store_deref(size, addr, value) \
({ \
int _bad=0; \
- switch (size){ \
- case 1: __stp_put_user_asm_byte(value, addr, _bad); break; \
- case 2: __stp_put_user_asm_half(value, addr, _bad); break; \
- case 4: __stp_put_user_asm_word(value, addr, _bad); break; \
- case 8: __stp_put_user_asm_dword(value, addr, _bad); break; \
- default: __put_user_bad(); break; \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size){ \
+ case 1: __stp_put_user_asm_byte(value, addr, _bad); break; \
+ case 2: __stp_put_user_asm_half(value, addr, _bad); break; \
+ case 4: __stp_put_user_asm_word(value, addr, _bad); break; \
+ case 8: __stp_put_user_asm_dword(value, addr, _bad); break; \
+ default: __put_user_bad(); break; \
+ } \
if (_bad) \
STORE_DEREF_FAULT(addr); \
})
@@ -624,28 +658,31 @@ extern void __store_deref_bad(void);
u8 _b; u16 _w; u32 _l; u64 _q; \
int _bad = 0; \
intptr_t _v = 0; \
- switch (size) { \
- case 1: { \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ switch (size) { \
+ case 1: { \
__stp_get_asm(_b, addr, _bad, 1); \
_v = _b; \
break; \
- }; \
- case 2: { \
+ }; \
+ case 2: { \
__stp_get_asm(_w, addr, _bad, 2); \
_v = _w; \
break; \
- }; \
- case 4: { \
+ }; \
+ case 4: { \
__stp_get_asm(_l, addr, _bad, 4); \
_v = _l; \
break; \
- }; \
- case 8: { \
+ }; \
+ case 8: { \
__stp_get_asm(_q, addr, _bad, 8); \
_v = _q; \
break; \
- }; \
- default: \
+ }; \
+ default: \
_bad = -EFAULT; \
} \
if (_bad) \
@@ -657,12 +694,17 @@ extern void __store_deref_bad(void);
({ \
int _bad = 0; \
int i; \
- for(i=0;i<size;i++){ \
- __stp_put_asm((u8)(value>>((size-i-1)*8)&0xff), \
- (u64)addr+i,_bad); \
- if (_bad) \
- STORE_DEREF_FAULT(addr); \
- } \
+ if (lookup_bad_addr((unsigned long)addr)) \
+ _bad = 1; \
+ else \
+ for(i=0;i<size;i++){ \
+ __stp_put_asm((u8)(value>>((size-i-1)*8)&0xff), \
+ (u64)addr+i,_bad); \
+ if (_bad) \
+ break; \
+ } \
+ if (_bad) \
+ STORE_DEREF_FAULT(addr); \
})
diff --git a/runtime/regs-ia64.c b/runtime/regs-ia64.c
index fd8d8ca8..8ce3e4c3 100644
--- a/runtime/regs-ia64.c
+++ b/runtime/regs-ia64.c
@@ -61,27 +61,36 @@ static void ia64_stap_get_arbsp(struct unw_frame_info *info, void *arg)
-(__offset + (regs->cr_ifs & 127)));\
}
-static long ia64_fetch_register(int regno, struct pt_regs *pt_regs, unsigned long **cache)
+static long *
+__ia64_fetch_register(int regno, struct pt_regs *pt_regs, unsigned long **cache)
{
struct ia64_stap_get_arbsp_param pa;
if (regno == 12)
- return pt_regs->r12;
+ return &pt_regs->r12;
if (regno >= 8 && regno <= 11)
- return *(unsigned long *)(&pt_regs->r8 + regno - 8);
+ return (long *)(&pt_regs->r8 + regno - 8);
else if (regno < 32 || regno > 127)
- return 0;
+ return NULL;
if (!*cache) {
pa.ip = pt_regs->cr_iip;
unw_init_running(ia64_stap_get_arbsp, &pa);
if (pa.address == 0)
- return 0;
+ return NULL;
*cache = pa.address;
}
- return *ia64_rse_skip_regs(*cache, regno-32);
+ return ia64_rse_skip_regs(*cache, regno-32);
+}
+
+static long
+ia64_fetch_register(int regno, struct pt_regs *pt_regs, unsigned long **cache)
+{
+ long *reg;
+ reg = __ia64_fetch_register(regno, pt_regs, cache);
+ return (reg != NULL)? *reg : 0;
}
static void ia64_store_register(int regno,
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 2711f531..fd0cac9e 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -88,6 +88,7 @@ static struct
#ifdef STP_PERFMON
#include "perf.c"
#endif
+#include "addr-map.c"
/* Support functions for int64_t module parameters. */
int param_set_int64_t(const char *val, struct kernel_param *kp)
diff --git a/runtime/sym.c b/runtime/sym.c
index dcdbaf69..b594d9c2 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -98,7 +98,7 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo
unsigned long this_section_addr = _stp_modules[midx]->sections[secidx].addr;
unsigned long this_section_offset;
if (addr < this_section_addr) continue;
- this_section_offset = this_section_addr - addr;
+ this_section_offset = addr - this_section_addr;
if (this_section_offset < closest_section_offset)
{
closest_section_offset = this_section_offset;
diff --git a/runtime/syscall.h b/runtime/syscall.h
index 24e93463..24fc7b1c 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -66,7 +66,15 @@
#define MUNMAP_SYSCALL_NO(tsk) 91
#define MREMAP_SYSCALL_NO(tsk) 163
#endif
-
+
+#if defined(__ia64__)
+#define MMAP_SYSCALL_NO(tsk) 1151
+#define MMAP2_SYSCALL_NO(tsk) 1172
+#define MPROTECT_SYSCALL_NO(tsk) 1155
+#define MUNMAP_SYSCALL_NO(tsk) 1152
+#define MREMAP_SYSCALL_NO(tsk) 1156
+#endif
+
#if !defined(MMAP_SYSCALL_NO) || !defined(MMAP2_SYSCALL_NO) \
|| !defined(MPROTECT_SYSCALL_NO) || !defined(MUNMAP_SYSCALL_NO) \
|| !defined(MREMAP_SYSCALL_NO)
@@ -95,6 +103,14 @@ __stp_user_syscall_nr(struct pt_regs *regs)
}
#endif
+#if defined(__ia64__)
+static inline unsigned long
+__stp_user_syscall_nr(struct pt_regs *regs)
+{
+ return regs->r15;
+}
+#endif
+
#if defined(__i386__) || defined(__x86_64__)
static inline long *
__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
@@ -129,6 +145,14 @@ __stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
}
#endif
+#if defined(__ia64__)
+static inline long *
+__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+ return &regs->r8;
+}
+#endif
+
#if defined(__i386__) || defined(__x86_64__)
static inline long *
__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
@@ -211,4 +235,20 @@ __stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
}
#endif
+#if defined(__ia64__)
+#define __stp_user_syscall_arg(task, regs, n) \
+ ____stp_user_syscall_arg(task, regs, n, &c->unwaddr)
+
+static inline long *
+____stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs,
+ unsigned int n, unsigned long **cache)
+{
+ if (n > 5) {
+ _stp_error("syscall arg > 5");
+ return NULL;
+ }
+ return __ia64_fetch_register(n + 32, regs, cache);
+}
+#endif
+
#endif /* _SYSCALL_H_ */
diff --git a/runtime/task_finder.c b/runtime/task_finder.c
index 2d4eed15..cbb10d35 100644
--- a/runtime/task_finder.c
+++ b/runtime/task_finder.c
@@ -843,6 +843,9 @@ __stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action,
struct vm_area_struct *vma;
unsigned long *arg0_addr, arg0;
int rc;
+#if defined(__ia64__)
+ struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
+#endif
if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
debug_task_finder_detach();
@@ -950,6 +953,9 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action,
struct mm_struct *mm;
struct vm_area_struct *vma;
struct __stp_tf_vma_entry *entry = NULL;
+#if defined(__ia64__)
+ struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c;
+#endif
if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) {
debug_task_finder_detach();