* Question about how to retrieve ip value of a syscall
@ 2014-08-20 23:15 tarek slaymia
0 siblings, 0 replies; 2+ messages in thread
From: tarek slaymia @ 2014-08-20 23:15 UTC (permalink / raw)
To: lttng-dev-request, lttng-dev
[-- Attachment #1.1: Type: text/plain, Size: 502 bytes --]
Hi all ,
i tried to implement an event in statedump in order to compare the runtime
syscall address and the syscall symbol address ( the same address displayed
in ip field when i use lttng kprobe ).
did you know how can i retrieve the syscall symbol value using my function
in lttng-statedump-impl.c file ?
i have an other issue when i tried to list all kernel event , the new event
that i add in lttng-module isn't displayed . did i miss something ?
you find in attachment the additional code .
BR
[-- Attachment #1.2: Type: text/html, Size: 637 bytes --]
[-- Attachment #2: lttng-statedump.h --]
[-- Type: text/x-chdr, Size: 5308 bytes --]
#undef TRACE_SYSTEM
#define TRACE_SYSTEM lttng_statedump
#if !defined(_TRACE_LTTNG_STATEDUMP_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_LTTNG_STATEDUMP_H
#include <linux/tracepoint.h>
#include <linux/nsproxy.h>
#include <linux/pid_namespace.h>
#include <linux/types.h>
TRACE_EVENT(lttng_statedump_start,
TP_PROTO(struct lttng_session *session),
TP_ARGS(session),
TP_STRUCT__entry(
),
TP_fast_assign(
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_end,
TP_PROTO(struct lttng_session *session),
TP_ARGS(session),
TP_STRUCT__entry(
),
TP_fast_assign(
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_process_state,
TP_PROTO(struct lttng_session *session,
struct task_struct *p,
int type, int mode, int submode, int status,
struct pid_namespace *pid_ns),
TP_ARGS(session, p, type, mode, submode, status, pid_ns),
TP_STRUCT__entry(
__field(pid_t, tid)
__field(pid_t, vtid)
__field(pid_t, pid)
__field(pid_t, vpid)
__field(pid_t, ppid)
__field(pid_t, vppid)
__array_text(char, name, TASK_COMM_LEN)
__field(int, type)
__field(int, mode)
__field(int, submode)
__field(int, status)
__field(int, ns_level)
),
TP_fast_assign(
tp_assign(tid, p->pid)
tp_assign(vtid, pid_ns ? task_pid_nr_ns(p, pid_ns) : 0)
tp_assign(pid, p->tgid)
tp_assign(vpid, pid_ns ? task_tgid_nr_ns(p, pid_ns) : 0)
tp_assign(ppid,
({
pid_t ret;
rcu_read_lock();
ret = task_tgid_nr(p->real_parent);
rcu_read_unlock();
ret;
}))
tp_assign(vppid,
({
struct task_struct *parent;
pid_t ret = 0;
if (pid_ns) {
rcu_read_lock();
parent = rcu_dereference(p->real_parent);
ret = task_tgid_nr_ns(parent, pid_ns);
rcu_read_unlock();
}
ret;
}))
tp_memcpy(name, p->comm, TASK_COMM_LEN)
tp_assign(type, type)
tp_assign(mode, mode)
tp_assign(submode, submode)
tp_assign(status, status)
tp_assign(ns_level, pid_ns ? pid_ns->level : 0)
),
TP_printk("")
)
//--- Added by Tarek------------------------------------------------------------------------------//
TRACE_EVENT(lttng_statedump_syscall_address_list,
TP_PROTO(struct lttng_session *session,const char *syscall_name,
unsigned int runtime_syscall_address,
unsigned int symbol_syscall_address),
TP_ARGS(session, syscall_name, runtime_syscall_address, symbol_syscall_address),
TP_STRUCT__entry(
__string(syscall_name, syscall_name)
__field(unsigned int, runtime_syscall_address)
__field(unsigned int, symbol_syscall_address)
),
TP_fast_assign(
tp_assign(runtime_syscall_address, runtime_syscall_address)
tp_assign(symbol_syscall_address, symbol_syscall_address)
tp_strcpy(syscall_name, syscall_name)
),
TP_printk("")
)
//--------------------------------------------------------------------------------------------//
TRACE_EVENT(lttng_statedump_file_descriptor,
TP_PROTO(struct lttng_session *session,
struct task_struct *p, int fd, const char *filename,
unsigned int flags, fmode_t fmode),
TP_ARGS(session, p, fd, filename, flags, fmode),
TP_STRUCT__entry(
__field(pid_t, pid)
__field(int, fd)
__field_oct(unsigned int, flags)
__field_hex(fmode_t, fmode)
__string(filename, filename)
),
TP_fast_assign(
tp_assign(pid, p->tgid)
tp_assign(fd, fd)
tp_assign(flags, flags)
tp_assign(fmode, fmode)
tp_strcpy(filename, filename)
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_vm_map,
TP_PROTO(struct lttng_session *session,
struct task_struct *p, struct vm_area_struct *map,
unsigned long inode),
TP_ARGS(session, p, map, inode),
TP_STRUCT__entry(
__field(pid_t, pid)
__field_hex(unsigned long, start)
__field_hex(unsigned long, end)
__field_hex(unsigned long, flags)
__field(unsigned long, inode)
__field(unsigned long, pgoff)
),
TP_fast_assign(
tp_assign(pid, p->tgid)
tp_assign(start, map->vm_start)
tp_assign(end, map->vm_end)
tp_assign(flags, map->vm_flags)
tp_assign(inode, inode)
tp_assign(pgoff, map->vm_pgoff << PAGE_SHIFT)
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_network_interface,
TP_PROTO(struct lttng_session *session,
struct net_device *dev, struct in_ifaddr *ifa),
TP_ARGS(session, dev, ifa),
TP_STRUCT__entry(
__string(name, dev->name)
__field_network_hex(uint32_t, address_ipv4)
),
TP_fast_assign(
tp_strcpy(name, dev->name)
tp_assign(address_ipv4, ifa ? ifa->ifa_address : 0U)
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_block_device,
TP_PROTO(struct lttng_session *session,
dev_t dev, const char *diskname),
TP_ARGS(session, dev, diskname),
TP_STRUCT__entry(
__field(dev_t, dev)
__string(diskname, diskname)
),
TP_fast_assign(
tp_assign(dev, dev)
tp_strcpy(diskname, diskname)
),
TP_printk("")
)
/* Called with desc->lock held */
TRACE_EVENT(lttng_statedump_interrupt,
TP_PROTO(struct lttng_session *session,
unsigned int irq, const char *chip_name,
struct irqaction *action),
TP_ARGS(session, irq, chip_name, action),
TP_STRUCT__entry(
__field(unsigned int, irq)
__string(name, chip_name)
__string(action, action->name ? : "")
),
TP_fast_assign(
tp_assign(irq, irq)
tp_strcpy(name, chip_name)
tp_strcpy(action, action->name ? : "")
),
TP_printk("")
)
#endif /* _TRACE_LTTNG_STATEDUMP_H */
/* This part must be outside protection */
#include "../../../probes/define_trace.h"
[-- Attachment #3: lttng-statedump-impl.c --]
[-- Type: text/x-csrc, Size: 16883 bytes --]
/*
* lttng-statedump.c
*
* Linux Trace Toolkit Next Generation Kernel State Dump
*
* Copyright 2005 Jean-Hugues Deschenes <jean-hugues.deschenes@polymtl.ca>
* Copyright 2006-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; only
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Changes:
* Eric Clement: Add listing of network IP interface
* 2006, 2007 Mathieu Desnoyers Fix kernel threads
* Various updates
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/kthread.h>
#include <linux/proc_fs.h>
#include <linux/file.h>
#include <linux/interrupt.h>
#include <linux/irqnr.h>
#include <linux/cpu.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/fdtable.h>
#include <linux/swap.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/device.h>
//add tarek syscall
#include <linux/kallsyms.h>
#include <trace/syscall.h>
#include <asm/syscall.h>
//end
#include "lttng-events.h"
#include "lttng-tracer.h"
#include "wrapper/irqdesc.h"
#include "wrapper/spinlock.h"
#include "wrapper/fdtable.h"
#include "wrapper/nsproxy.h"
#include "wrapper/irq.h"
#include "wrapper/tracepoint.h"
#include "wrapper/genhd.h"
#ifdef CONFIG_LTTNG_HAS_LIST_IRQ
#include <linux/irq.h>
#endif
//add tarek syscall
#ifndef CONFIG_FTRACE_SYSCALLS
#error "You need to set CONFIG_FTRACE_SYSCALLS=y"
#endif
#ifndef CONFIG_KALLSYMS_ALL
#error "You need to set CONFIG_KALLSYMS_ALL=y"
#endif
static struct syscall_metadata **__start_syscalls_metadata;
static struct syscall_metadata **__stop_syscalls_metadata;
//end
/* Define the tracepoints, but do not build the probes */
#define CREATE_TRACE_POINTS
#define TRACE_INCLUDE_PATH ../instrumentation/events/lttng-module
#define TRACE_INCLUDE_FILE lttng-statedump
#include "instrumentation/events/lttng-module/lttng-statedump.h"
DEFINE_TRACE(lttng_statedump_block_device);
DEFINE_TRACE(lttng_statedump_end);
DEFINE_TRACE(lttng_statedump_interrupt);
DEFINE_TRACE(lttng_statedump_file_descriptor);
DEFINE_TRACE(lttng_statedump_start);
DEFINE_TRACE(lttng_statedump_process_state);
//Add Tarek
DEFINE_TRACE(lttng_statedump_syscall_address_list);
//end
DEFINE_TRACE(lttng_statedump_network_interface);
struct lttng_fd_ctx {
char *page;
struct lttng_session *session;
struct task_struct *p;
struct files_struct *files;
};
/*
* Protected by the trace lock.
*/
static struct delayed_work cpu_work[NR_CPUS];
static DECLARE_WAIT_QUEUE_HEAD(statedump_wq);
static atomic_t kernel_threads_to_run;
enum lttng_thread_type {
LTTNG_USER_THREAD = 0,
LTTNG_KERNEL_THREAD = 1,
};
enum lttng_execution_mode {
LTTNG_USER_MODE = 0,
LTTNG_SYSCALL = 1,
LTTNG_TRAP = 2,
LTTNG_IRQ = 3,
LTTNG_SOFTIRQ = 4,
LTTNG_MODE_UNKNOWN = 5,
};
enum lttng_execution_submode {
LTTNG_NONE = 0,
LTTNG_UNKNOWN = 1,
};
enum lttng_process_status {
LTTNG_UNNAMED = 0,
LTTNG_WAIT_FORK = 1,
LTTNG_WAIT_CPU = 2,
LTTNG_EXIT = 3,
LTTNG_ZOMBIE = 4,
LTTNG_WAIT = 5,
LTTNG_RUN = 6,
LTTNG_DEAD = 7,
};
static
int lttng_enumerate_block_devices(struct lttng_session *session)
{
struct class *ptr_block_class;
struct device_type *ptr_disk_type;
struct class_dev_iter iter;
struct device *dev;
ptr_block_class = wrapper_get_block_class();
if (!ptr_block_class)
return -ENOSYS;
ptr_disk_type = wrapper_get_disk_type();
if (!ptr_disk_type) {
return -ENOSYS;
}
class_dev_iter_init(&iter, ptr_block_class, NULL, ptr_disk_type);
while ((dev = class_dev_iter_next(&iter))) {
struct disk_part_iter piter;
struct gendisk *disk = dev_to_disk(dev);
struct hd_struct *part;
/*
* Don't show empty devices or things that have been
* suppressed
*/
if (get_capacity(disk) == 0 ||
(disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
continue;
disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
while ((part = disk_part_iter_next(&piter))) {
char name_buf[BDEVNAME_SIZE];
char *p;
p = wrapper_disk_name(disk, part->partno, name_buf);
if (!p) {
disk_part_iter_exit(&piter);
class_dev_iter_exit(&iter);
return -ENOSYS;
}
trace_lttng_statedump_block_device(session,
part_devt(part), name_buf);
}
disk_part_iter_exit(&piter);
}
class_dev_iter_exit(&iter);
return 0;
}
#ifdef CONFIG_INET
static
void lttng_enumerate_device(struct lttng_session *session,
struct net_device *dev)
{
struct in_device *in_dev;
struct in_ifaddr *ifa;
if (dev->flags & IFF_UP) {
in_dev = in_dev_get(dev);
if (in_dev) {
for (ifa = in_dev->ifa_list; ifa != NULL;
ifa = ifa->ifa_next) {
trace_lttng_statedump_network_interface(
session, dev, ifa);
}
in_dev_put(in_dev);
}
} else {
trace_lttng_statedump_network_interface(
session, dev, NULL);
}
}
static
int lttng_enumerate_network_ip_interface(struct lttng_session *session)
{
struct net_device *dev;
read_lock(&dev_base_lock);
for_each_netdev(&init_net, dev)
lttng_enumerate_device(session, dev);
read_unlock(&dev_base_lock);
return 0;
}
#else /* CONFIG_INET */
static inline
int lttng_enumerate_network_ip_interface(struct lttng_session *session)
{
return 0;
}
#endif /* CONFIG_INET */
static
int lttng_dump_one_fd(const void *p, struct file *file, unsigned int fd)
{
const struct lttng_fd_ctx *ctx = p;
const char *s = d_path(&file->f_path, ctx->page, PAGE_SIZE);
unsigned int flags = file->f_flags;
struct fdtable *fdt;
/*
* We don't expose kernel internal flags, only userspace-visible
* flags.
*/
flags &= ~FMODE_NONOTIFY;
fdt = files_fdtable(ctx->files);
/*
* We need to check here again whether fd is within the fdt
* max_fds range, because we might be seeing a different
* files_fdtable() than iterate_fd(), assuming only RCU is
* protecting the read. In reality, iterate_fd() holds
* file_lock, which should ensure the fdt does not change while
* the lock is taken, but we are not aware whether this is
* guaranteed or not, so play safe.
*/
if (fd < fdt->max_fds && test_bit(fd, fdt->close_on_exec))
flags |= O_CLOEXEC;
if (IS_ERR(s)) {
struct dentry *dentry = file->f_path.dentry;
/* Make sure we give at least some info */
spin_lock(&dentry->d_lock);
trace_lttng_statedump_file_descriptor(ctx->session, ctx->p, fd,
dentry->d_name.name, flags, file->f_mode);
spin_unlock(&dentry->d_lock);
goto end;
}
trace_lttng_statedump_file_descriptor(ctx->session, ctx->p, fd, s,
flags, file->f_mode);
end:
return 0;
}
static
void lttng_enumerate_task_fd(struct lttng_session *session,
struct task_struct *p, char *tmp)
{
struct lttng_fd_ctx ctx = { .page = tmp, .session = session, .p = p };
struct files_struct *files;
task_lock(p);
files = p->files;
if (!files)
goto end;
ctx.files = files;
lttng_iterate_fd(files, 0, lttng_dump_one_fd, &ctx);
end:
task_unlock(p);
}
static
int lttng_enumerate_file_descriptors(struct lttng_session *session)
{
struct task_struct *p;
char *tmp;
tmp = (char *) __get_free_page(GFP_KERNEL);
if (!tmp)
return -ENOMEM;
/* Enumerate active file descriptors */
rcu_read_lock();
for_each_process(p)
lttng_enumerate_task_fd(session, p, tmp);
rcu_read_unlock();
free_page((unsigned long) tmp);
return 0;
}
#if 0
/*
* FIXME: we cannot take a mmap_sem while in a RCU read-side critical section
* (scheduling in atomic). Normally, the tasklist lock protects this kind of
* iteration, but it is not exported to modules.
*/
static
void lttng_enumerate_task_vm_maps(struct lttng_session *session,
struct task_struct *p)
{
struct mm_struct *mm;
struct vm_area_struct *map;
unsigned long ino;
/* get_task_mm does a task_lock... */
mm = get_task_mm(p);
if (!mm)
return;
map = mm->mmap;
if (map) {
down_read(&mm->mmap_sem);
while (map) {
if (map->vm_file)
ino = map->vm_file->f_dentry->d_inode->i_ino;
else
ino = 0;
trace_lttng_statedump_vm_map(session, p, map, ino);
map = map->vm_next;
}
up_read(&mm->mmap_sem);
}
mmput(mm);
}
static
int lttng_enumerate_vm_maps(struct lttng_session *session)
{
struct task_struct *p;
rcu_read_lock();
for_each_process(p)
lttng_enumerate_task_vm_maps(session, p);
rcu_read_unlock();
return 0;
}
#endif
#ifdef CONFIG_LTTNG_HAS_LIST_IRQ
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
#define irq_desc_get_chip(desc) get_irq_desc_chip(desc)
#endif
static
int lttng_list_interrupts(struct lttng_session *session)
{
unsigned int irq;
unsigned long flags = 0;
struct irq_desc *desc;
#define irq_to_desc wrapper_irq_to_desc
/* needs irq_desc */
for_each_irq_desc(irq, desc) {
struct irqaction *action;
const char *irq_chip_name =
irq_desc_get_chip(desc)->name ? : "unnamed_irq_chip";
local_irq_save(flags);
wrapper_desc_spin_lock(&desc->lock);
for (action = desc->action; action; action = action->next) {
trace_lttng_statedump_interrupt(session,
irq, irq_chip_name, action);
}
wrapper_desc_spin_unlock(&desc->lock);
local_irq_restore(flags);
}
return 0;
#undef irq_to_desc
}
#else
static inline
int lttng_list_interrupts(struct lttng_session *session)
{
return 0;
}
#endif
static
void lttng_statedump_process_ns(struct lttng_session *session,
struct task_struct *p,
enum lttng_thread_type type,
enum lttng_execution_mode mode,
enum lttng_execution_submode submode,
enum lttng_process_status status)
{
struct nsproxy *proxy;
struct pid_namespace *pid_ns;
rcu_read_lock();
proxy = task_nsproxy(p);
if (proxy) {
pid_ns = lttng_get_proxy_pid_ns(proxy);
do {
trace_lttng_statedump_process_state(session,
p, type, mode, submode, status, pid_ns);
pid_ns = pid_ns->parent;
} while (pid_ns);
} else {
trace_lttng_statedump_process_state(session,
p, type, mode, submode, status, NULL);
}
rcu_read_unlock();
}
static
int lttng_enumerate_process_states(struct lttng_session *session)
{
struct task_struct *g, *p;
rcu_read_lock();
for_each_process(g) {
p = g;
do {
enum lttng_execution_mode mode =
LTTNG_MODE_UNKNOWN;
enum lttng_execution_submode submode =
LTTNG_UNKNOWN;
enum lttng_process_status status;
enum lttng_thread_type type;
task_lock(p);
if (p->exit_state == EXIT_ZOMBIE)
status = LTTNG_ZOMBIE;
else if (p->exit_state == EXIT_DEAD)
status = LTTNG_DEAD;
else if (p->state == TASK_RUNNING) {
/* Is this a forked child that has not run yet? */
if (list_empty(&p->rt.run_list))
status = LTTNG_WAIT_FORK;
else
/*
* All tasks are considered as wait_cpu;
* the viewer will sort out if the task
* was really running at this time.
*/
status = LTTNG_WAIT_CPU;
} else if (p->state &
(TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)) {
/* Task is waiting for something to complete */
status = LTTNG_WAIT;
} else
status = LTTNG_UNNAMED;
submode = LTTNG_NONE;
/*
* Verification of t->mm is to filter out kernel
* threads; Viewer will further filter out if a
* user-space thread was in syscall mode or not.
*/
if (p->mm)
type = LTTNG_USER_THREAD;
else
type = LTTNG_KERNEL_THREAD;
lttng_statedump_process_ns(session,
p, type, mode, submode, status);
task_unlock(p);
} while_each_thread(g, p);
}
rcu_read_unlock();
return 0;
}
//BEGIN : Added by Tarek ----------------------------------------------------//
static
int lttng_dump_one_sycall_address(struct lttng_session *session, const char *syscall_name, unsigned int runtime_syscall_address, unsigned int symbol_syscall_address)
{
if (!syscall_name ||
!runtime_syscall_address ||
!symbol_syscall_address ) {
return -1;
}
trace_lttng_statedump_syscall_address_list (session,
syscall_name,
runtime_syscall_address,
symbol_syscall_address);
return 0;
}
static __init
struct syscall_metadata *find_syscall_meta(unsigned long syscall)
{
struct syscall_metadata **iter;
for (iter = __start_syscalls_metadata;
iter < __stop_syscalls_metadata; iter++) {
if ((*iter)->syscall_nr == syscall)
return (*iter);
}
return NULL;
}
static
int lttng_enumerate_syscall_address_list(struct lttng_session *session)
{
// get syscall table address
// hash table that contains all system_call names and numbers
// iterate for every system call and get its address in the system call table
struct syscall_metadata *meta;
int i;
unsigned long *sys_call_table = NULL;
__start_syscalls_metadata = (void *) kallsyms_lookup_name("__start_syscalls_metadata");
__stop_syscalls_metadata = (void *) kallsyms_lookup_name("__stop_syscalls_metadata");
sys_call_table = (unsigned long *) kallsyms_lookup_name("sys_call_table");
for (i = 0; i < NR_syscalls; i++) {
int j;
meta = find_syscall_meta(i);
if (!meta || !sys_call_table)
continue;
printk("syscall %s ; nr %d ; nbargs %d ; address in sys call table : %p ",
meta->name, meta->syscall_nr, meta->nb_args, (void *) sys_call_table[meta->syscall_nr]);
// TODO : retierve the symbol address of a syscall in order to inject it in the third argument of lttng_dump_one_sycall_address function
lttng_dump_one_sycall_address(session,meta->name,sys_call_table[meta->syscall_nr], (unsigned int) NULL /* address of syscall symbol*/);
}
printk("SUCCESS\n");
return -1;
}
//END----------------------------------------------------//
static
void lttng_statedump_work_func(struct work_struct *work)
{
if (atomic_dec_and_test(&kernel_threads_to_run))
/* If we are the last thread, wake up do_lttng_statedump */
wake_up(&statedump_wq);
}
static
int do_lttng_statedump(struct lttng_session *session)
{
int cpu, ret;
trace_lttng_statedump_start(session);
ret = lttng_enumerate_process_states(session);
if (ret)
return ret;
//Added by Tarek
ret = lttng_enumerate_syscall_address_list(session);
if (ret)
return ret;
//
ret = lttng_enumerate_file_descriptors(session);
if (ret)
return ret;
/*
* FIXME
* ret = lttng_enumerate_vm_maps(session);
* if (ret)
* return ret;
*/
ret = lttng_list_interrupts(session);
if (ret)
return ret;
ret = lttng_enumerate_network_ip_interface(session);
if (ret)
return ret;
ret = lttng_enumerate_block_devices(session);
switch (ret) {
case -ENOSYS:
printk(KERN_WARNING "LTTng: block device enumeration is not supported by kernel\n");
break;
default:
return ret;
}
/* TODO lttng_dump_idt_table(session); */
/* TODO lttng_dump_softirq_vec(session); */
/* TODO lttng_list_modules(session); */
/* TODO lttng_dump_swap_files(session); */
/*
* Fire off a work queue on each CPU. Their sole purpose in life
* is to guarantee that each CPU has been in a state where is was in
* syscall mode (i.e. not in a trap, an IRQ or a soft IRQ).
*/
get_online_cpus();
atomic_set(&kernel_threads_to_run, num_online_cpus());
for_each_online_cpu(cpu) {
INIT_DELAYED_WORK(&cpu_work[cpu], lttng_statedump_work_func);
schedule_delayed_work_on(cpu, &cpu_work[cpu], 0);
}
/* Wait for all threads to run */
__wait_event(statedump_wq, (atomic_read(&kernel_threads_to_run) == 0));
put_online_cpus();
/* Our work is done */
trace_lttng_statedump_end(session);
return 0;
}
/*
* Called with session mutex held.
*/
int lttng_statedump_start(struct lttng_session *session)
{
return do_lttng_statedump(session);
}
EXPORT_SYMBOL_GPL(lttng_statedump_start);
static
int __init lttng_statedump_init(void)
{
/*
* Allow module to load even if the fixup cannot be done. This
* will allow seemless transition when the underlying issue fix
* is merged into the Linux kernel, and when tracepoint.c
* "tracepoint_module_notify" is turned into a static function.
*/
(void) wrapper_lttng_fixup_sig(THIS_MODULE);
return 0;
}
module_init(lttng_statedump_init);
static
void __exit lttng_statedump_exit(void)
{
}
module_exit(lttng_statedump_exit);
MODULE_LICENSE("GPL and additional rights");
MODULE_AUTHOR("Jean-Hugues Deschenes");
MODULE_DESCRIPTION("Linux Trace Toolkit Next Generation Statedump");
MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
__stringify(LTTNG_MODULES_MINOR_VERSION) "."
__stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
LTTNG_MODULES_EXTRAVERSION);
[-- Attachment #4: Type: text/plain, Size: 155 bytes --]
_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Question about how to retrieve ip value of a syscall
[not found] <CAP7TvLdAAszF8YM9buAy-umJ1pYY+Mu-1vPPYE2=mMHoH72Rsg@mail.gmail.com>
@ 2014-09-10 15:12 ` Mathieu Desnoyers
0 siblings, 0 replies; 2+ messages in thread
From: Mathieu Desnoyers @ 2014-09-10 15:12 UTC (permalink / raw)
To: tarek slaymia; +Cc: lttng-dev, lttng-dev-request
[-- Attachment #1.1: Type: text/plain, Size: 1329 bytes --]
----- Original Message -----
> From: "tarek slaymia" <tarek.slaymia@gmail.com>
> To: lttng-dev-request@lists.lttng.org, lttng-dev@lists.lttng.org
> Sent: Wednesday, August 20, 2014 7:15:21 PM
> Subject: [lttng-dev] Question about how to retrieve ip value of a syscall
> Hi all ,
> i tried to implement an event in statedump in order to compare the runtime
> syscall address and the syscall symbol address ( the same address displayed
> in ip field when i use lttng kprobe ).
> did you know how can i retrieve the syscall symbol value using my function in
> lttng-statedump-impl.c file ?
> i have an other issue when i tried to list all kernel event , the new event
> that i add in lttng-module isn't displayed . did i miss something ?
> you find in attachment the additional code .
Does the printk within lttng_enumerate_syscall_address_list()
print anything on the console when you start tracing ?
Try adding printk in your code to see what is happening. It's not executed often,
so it should be easy to understand what is going wrong by adding printk statements.
Thanks,
Mathieu
> BR
> _______________________________________________
> lttng-dev mailing list
> lttng-dev@lists.lttng.org
> http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
[-- Attachment #1.2: Type: text/html, Size: 2319 bytes --]
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: lttng-statedump.h --]
[-- Type: text/x-chdr; name=lttng-statedump.h, Size: 5308 bytes --]
#undef TRACE_SYSTEM
#define TRACE_SYSTEM lttng_statedump
#if !defined(_TRACE_LTTNG_STATEDUMP_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_LTTNG_STATEDUMP_H
#include <linux/tracepoint.h>
#include <linux/nsproxy.h>
#include <linux/pid_namespace.h>
#include <linux/types.h>
TRACE_EVENT(lttng_statedump_start,
TP_PROTO(struct lttng_session *session),
TP_ARGS(session),
TP_STRUCT__entry(
),
TP_fast_assign(
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_end,
TP_PROTO(struct lttng_session *session),
TP_ARGS(session),
TP_STRUCT__entry(
),
TP_fast_assign(
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_process_state,
TP_PROTO(struct lttng_session *session,
struct task_struct *p,
int type, int mode, int submode, int status,
struct pid_namespace *pid_ns),
TP_ARGS(session, p, type, mode, submode, status, pid_ns),
TP_STRUCT__entry(
__field(pid_t, tid)
__field(pid_t, vtid)
__field(pid_t, pid)
__field(pid_t, vpid)
__field(pid_t, ppid)
__field(pid_t, vppid)
__array_text(char, name, TASK_COMM_LEN)
__field(int, type)
__field(int, mode)
__field(int, submode)
__field(int, status)
__field(int, ns_level)
),
TP_fast_assign(
tp_assign(tid, p->pid)
tp_assign(vtid, pid_ns ? task_pid_nr_ns(p, pid_ns) : 0)
tp_assign(pid, p->tgid)
tp_assign(vpid, pid_ns ? task_tgid_nr_ns(p, pid_ns) : 0)
tp_assign(ppid,
({
pid_t ret;
rcu_read_lock();
ret = task_tgid_nr(p->real_parent);
rcu_read_unlock();
ret;
}))
tp_assign(vppid,
({
struct task_struct *parent;
pid_t ret = 0;
if (pid_ns) {
rcu_read_lock();
parent = rcu_dereference(p->real_parent);
ret = task_tgid_nr_ns(parent, pid_ns);
rcu_read_unlock();
}
ret;
}))
tp_memcpy(name, p->comm, TASK_COMM_LEN)
tp_assign(type, type)
tp_assign(mode, mode)
tp_assign(submode, submode)
tp_assign(status, status)
tp_assign(ns_level, pid_ns ? pid_ns->level : 0)
),
TP_printk("")
)
//--- Added by Tarek------------------------------------------------------------------------------//
TRACE_EVENT(lttng_statedump_syscall_address_list,
TP_PROTO(struct lttng_session *session,const char *syscall_name,
unsigned int runtime_syscall_address,
unsigned int symbol_syscall_address),
TP_ARGS(session, syscall_name, runtime_syscall_address, symbol_syscall_address),
TP_STRUCT__entry(
__string(syscall_name, syscall_name)
__field(unsigned int, runtime_syscall_address)
__field(unsigned int, symbol_syscall_address)
),
TP_fast_assign(
tp_assign(runtime_syscall_address, runtime_syscall_address)
tp_assign(symbol_syscall_address, symbol_syscall_address)
tp_strcpy(syscall_name, syscall_name)
),
TP_printk("")
)
//--------------------------------------------------------------------------------------------//
TRACE_EVENT(lttng_statedump_file_descriptor,
TP_PROTO(struct lttng_session *session,
struct task_struct *p, int fd, const char *filename,
unsigned int flags, fmode_t fmode),
TP_ARGS(session, p, fd, filename, flags, fmode),
TP_STRUCT__entry(
__field(pid_t, pid)
__field(int, fd)
__field_oct(unsigned int, flags)
__field_hex(fmode_t, fmode)
__string(filename, filename)
),
TP_fast_assign(
tp_assign(pid, p->tgid)
tp_assign(fd, fd)
tp_assign(flags, flags)
tp_assign(fmode, fmode)
tp_strcpy(filename, filename)
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_vm_map,
TP_PROTO(struct lttng_session *session,
struct task_struct *p, struct vm_area_struct *map,
unsigned long inode),
TP_ARGS(session, p, map, inode),
TP_STRUCT__entry(
__field(pid_t, pid)
__field_hex(unsigned long, start)
__field_hex(unsigned long, end)
__field_hex(unsigned long, flags)
__field(unsigned long, inode)
__field(unsigned long, pgoff)
),
TP_fast_assign(
tp_assign(pid, p->tgid)
tp_assign(start, map->vm_start)
tp_assign(end, map->vm_end)
tp_assign(flags, map->vm_flags)
tp_assign(inode, inode)
tp_assign(pgoff, map->vm_pgoff << PAGE_SHIFT)
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_network_interface,
TP_PROTO(struct lttng_session *session,
struct net_device *dev, struct in_ifaddr *ifa),
TP_ARGS(session, dev, ifa),
TP_STRUCT__entry(
__string(name, dev->name)
__field_network_hex(uint32_t, address_ipv4)
),
TP_fast_assign(
tp_strcpy(name, dev->name)
tp_assign(address_ipv4, ifa ? ifa->ifa_address : 0U)
),
TP_printk("")
)
TRACE_EVENT(lttng_statedump_block_device,
TP_PROTO(struct lttng_session *session,
dev_t dev, const char *diskname),
TP_ARGS(session, dev, diskname),
TP_STRUCT__entry(
__field(dev_t, dev)
__string(diskname, diskname)
),
TP_fast_assign(
tp_assign(dev, dev)
tp_strcpy(diskname, diskname)
),
TP_printk("")
)
/* Called with desc->lock held */
TRACE_EVENT(lttng_statedump_interrupt,
TP_PROTO(struct lttng_session *session,
unsigned int irq, const char *chip_name,
struct irqaction *action),
TP_ARGS(session, irq, chip_name, action),
TP_STRUCT__entry(
__field(unsigned int, irq)
__string(name, chip_name)
__string(action, action->name ? : "")
),
TP_fast_assign(
tp_assign(irq, irq)
tp_strcpy(name, chip_name)
tp_strcpy(action, action->name ? : "")
),
TP_printk("")
)
#endif /* _TRACE_LTTNG_STATEDUMP_H */
/* This part must be outside protection */
#include "../../../probes/define_trace.h"
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: lttng-statedump-impl.c --]
[-- Type: text/x-c++src; name=lttng-statedump-impl.c, Size: 16883 bytes --]
/*
* lttng-statedump.c
*
* Linux Trace Toolkit Next Generation Kernel State Dump
*
* Copyright 2005 Jean-Hugues Deschenes <jean-hugues.deschenes@polymtl.ca>
* Copyright 2006-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; only
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Changes:
* Eric Clement: Add listing of network IP interface
* 2006, 2007 Mathieu Desnoyers Fix kernel threads
* Various updates
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/kthread.h>
#include <linux/proc_fs.h>
#include <linux/file.h>
#include <linux/interrupt.h>
#include <linux/irqnr.h>
#include <linux/cpu.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/fdtable.h>
#include <linux/swap.h>
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/device.h>
//add tarek syscall
#include <linux/kallsyms.h>
#include <trace/syscall.h>
#include <asm/syscall.h>
//end
#include "lttng-events.h"
#include "lttng-tracer.h"
#include "wrapper/irqdesc.h"
#include "wrapper/spinlock.h"
#include "wrapper/fdtable.h"
#include "wrapper/nsproxy.h"
#include "wrapper/irq.h"
#include "wrapper/tracepoint.h"
#include "wrapper/genhd.h"
#ifdef CONFIG_LTTNG_HAS_LIST_IRQ
#include <linux/irq.h>
#endif
//add tarek syscall
#ifndef CONFIG_FTRACE_SYSCALLS
#error "You need to set CONFIG_FTRACE_SYSCALLS=y"
#endif
#ifndef CONFIG_KALLSYMS_ALL
#error "You need to set CONFIG_KALLSYMS_ALL=y"
#endif
static struct syscall_metadata **__start_syscalls_metadata;
static struct syscall_metadata **__stop_syscalls_metadata;
//end
/* Define the tracepoints, but do not build the probes */
#define CREATE_TRACE_POINTS
#define TRACE_INCLUDE_PATH ../instrumentation/events/lttng-module
#define TRACE_INCLUDE_FILE lttng-statedump
#include "instrumentation/events/lttng-module/lttng-statedump.h"
DEFINE_TRACE(lttng_statedump_block_device);
DEFINE_TRACE(lttng_statedump_end);
DEFINE_TRACE(lttng_statedump_interrupt);
DEFINE_TRACE(lttng_statedump_file_descriptor);
DEFINE_TRACE(lttng_statedump_start);
DEFINE_TRACE(lttng_statedump_process_state);
//Add Tarek
DEFINE_TRACE(lttng_statedump_syscall_address_list);
//end
DEFINE_TRACE(lttng_statedump_network_interface);
struct lttng_fd_ctx {
char *page;
struct lttng_session *session;
struct task_struct *p;
struct files_struct *files;
};
/*
* Protected by the trace lock.
*/
static struct delayed_work cpu_work[NR_CPUS];
static DECLARE_WAIT_QUEUE_HEAD(statedump_wq);
static atomic_t kernel_threads_to_run;
enum lttng_thread_type {
LTTNG_USER_THREAD = 0,
LTTNG_KERNEL_THREAD = 1,
};
enum lttng_execution_mode {
LTTNG_USER_MODE = 0,
LTTNG_SYSCALL = 1,
LTTNG_TRAP = 2,
LTTNG_IRQ = 3,
LTTNG_SOFTIRQ = 4,
LTTNG_MODE_UNKNOWN = 5,
};
enum lttng_execution_submode {
LTTNG_NONE = 0,
LTTNG_UNKNOWN = 1,
};
enum lttng_process_status {
LTTNG_UNNAMED = 0,
LTTNG_WAIT_FORK = 1,
LTTNG_WAIT_CPU = 2,
LTTNG_EXIT = 3,
LTTNG_ZOMBIE = 4,
LTTNG_WAIT = 5,
LTTNG_RUN = 6,
LTTNG_DEAD = 7,
};
static
int lttng_enumerate_block_devices(struct lttng_session *session)
{
struct class *ptr_block_class;
struct device_type *ptr_disk_type;
struct class_dev_iter iter;
struct device *dev;
ptr_block_class = wrapper_get_block_class();
if (!ptr_block_class)
return -ENOSYS;
ptr_disk_type = wrapper_get_disk_type();
if (!ptr_disk_type) {
return -ENOSYS;
}
class_dev_iter_init(&iter, ptr_block_class, NULL, ptr_disk_type);
while ((dev = class_dev_iter_next(&iter))) {
struct disk_part_iter piter;
struct gendisk *disk = dev_to_disk(dev);
struct hd_struct *part;
/*
* Don't show empty devices or things that have been
* suppressed
*/
if (get_capacity(disk) == 0 ||
(disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
continue;
disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
while ((part = disk_part_iter_next(&piter))) {
char name_buf[BDEVNAME_SIZE];
char *p;
p = wrapper_disk_name(disk, part->partno, name_buf);
if (!p) {
disk_part_iter_exit(&piter);
class_dev_iter_exit(&iter);
return -ENOSYS;
}
trace_lttng_statedump_block_device(session,
part_devt(part), name_buf);
}
disk_part_iter_exit(&piter);
}
class_dev_iter_exit(&iter);
return 0;
}
#ifdef CONFIG_INET
static
void lttng_enumerate_device(struct lttng_session *session,
struct net_device *dev)
{
struct in_device *in_dev;
struct in_ifaddr *ifa;
if (dev->flags & IFF_UP) {
in_dev = in_dev_get(dev);
if (in_dev) {
for (ifa = in_dev->ifa_list; ifa != NULL;
ifa = ifa->ifa_next) {
trace_lttng_statedump_network_interface(
session, dev, ifa);
}
in_dev_put(in_dev);
}
} else {
trace_lttng_statedump_network_interface(
session, dev, NULL);
}
}
static
int lttng_enumerate_network_ip_interface(struct lttng_session *session)
{
struct net_device *dev;
read_lock(&dev_base_lock);
for_each_netdev(&init_net, dev)
lttng_enumerate_device(session, dev);
read_unlock(&dev_base_lock);
return 0;
}
#else /* CONFIG_INET */
static inline
int lttng_enumerate_network_ip_interface(struct lttng_session *session)
{
return 0;
}
#endif /* CONFIG_INET */
static
int lttng_dump_one_fd(const void *p, struct file *file, unsigned int fd)
{
const struct lttng_fd_ctx *ctx = p;
const char *s = d_path(&file->f_path, ctx->page, PAGE_SIZE);
unsigned int flags = file->f_flags;
struct fdtable *fdt;
/*
* We don't expose kernel internal flags, only userspace-visible
* flags.
*/
flags &= ~FMODE_NONOTIFY;
fdt = files_fdtable(ctx->files);
/*
* We need to check here again whether fd is within the fdt
* max_fds range, because we might be seeing a different
* files_fdtable() than iterate_fd(), assuming only RCU is
* protecting the read. In reality, iterate_fd() holds
* file_lock, which should ensure the fdt does not change while
* the lock is taken, but we are not aware whether this is
* guaranteed or not, so play safe.
*/
if (fd < fdt->max_fds && test_bit(fd, fdt->close_on_exec))
flags |= O_CLOEXEC;
if (IS_ERR(s)) {
struct dentry *dentry = file->f_path.dentry;
/* Make sure we give at least some info */
spin_lock(&dentry->d_lock);
trace_lttng_statedump_file_descriptor(ctx->session, ctx->p, fd,
dentry->d_name.name, flags, file->f_mode);
spin_unlock(&dentry->d_lock);
goto end;
}
trace_lttng_statedump_file_descriptor(ctx->session, ctx->p, fd, s,
flags, file->f_mode);
end:
return 0;
}
static
void lttng_enumerate_task_fd(struct lttng_session *session,
struct task_struct *p, char *tmp)
{
struct lttng_fd_ctx ctx = { .page = tmp, .session = session, .p = p };
struct files_struct *files;
task_lock(p);
files = p->files;
if (!files)
goto end;
ctx.files = files;
lttng_iterate_fd(files, 0, lttng_dump_one_fd, &ctx);
end:
task_unlock(p);
}
static
int lttng_enumerate_file_descriptors(struct lttng_session *session)
{
struct task_struct *p;
char *tmp;
tmp = (char *) __get_free_page(GFP_KERNEL);
if (!tmp)
return -ENOMEM;
/* Enumerate active file descriptors */
rcu_read_lock();
for_each_process(p)
lttng_enumerate_task_fd(session, p, tmp);
rcu_read_unlock();
free_page((unsigned long) tmp);
return 0;
}
#if 0
/*
* FIXME: we cannot take a mmap_sem while in a RCU read-side critical section
* (scheduling in atomic). Normally, the tasklist lock protects this kind of
* iteration, but it is not exported to modules.
*/
static
void lttng_enumerate_task_vm_maps(struct lttng_session *session,
struct task_struct *p)
{
struct mm_struct *mm;
struct vm_area_struct *map;
unsigned long ino;
/* get_task_mm does a task_lock... */
mm = get_task_mm(p);
if (!mm)
return;
map = mm->mmap;
if (map) {
down_read(&mm->mmap_sem);
while (map) {
if (map->vm_file)
ino = map->vm_file->f_dentry->d_inode->i_ino;
else
ino = 0;
trace_lttng_statedump_vm_map(session, p, map, ino);
map = map->vm_next;
}
up_read(&mm->mmap_sem);
}
mmput(mm);
}
static
int lttng_enumerate_vm_maps(struct lttng_session *session)
{
struct task_struct *p;
rcu_read_lock();
for_each_process(p)
lttng_enumerate_task_vm_maps(session, p);
rcu_read_unlock();
return 0;
}
#endif
#ifdef CONFIG_LTTNG_HAS_LIST_IRQ
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
#define irq_desc_get_chip(desc) get_irq_desc_chip(desc)
#endif
static
int lttng_list_interrupts(struct lttng_session *session)
{
unsigned int irq;
unsigned long flags = 0;
struct irq_desc *desc;
#define irq_to_desc wrapper_irq_to_desc
/* needs irq_desc */
for_each_irq_desc(irq, desc) {
struct irqaction *action;
const char *irq_chip_name =
irq_desc_get_chip(desc)->name ? : "unnamed_irq_chip";
local_irq_save(flags);
wrapper_desc_spin_lock(&desc->lock);
for (action = desc->action; action; action = action->next) {
trace_lttng_statedump_interrupt(session,
irq, irq_chip_name, action);
}
wrapper_desc_spin_unlock(&desc->lock);
local_irq_restore(flags);
}
return 0;
#undef irq_to_desc
}
#else
static inline
int lttng_list_interrupts(struct lttng_session *session)
{
return 0;
}
#endif
static
void lttng_statedump_process_ns(struct lttng_session *session,
struct task_struct *p,
enum lttng_thread_type type,
enum lttng_execution_mode mode,
enum lttng_execution_submode submode,
enum lttng_process_status status)
{
struct nsproxy *proxy;
struct pid_namespace *pid_ns;
rcu_read_lock();
proxy = task_nsproxy(p);
if (proxy) {
pid_ns = lttng_get_proxy_pid_ns(proxy);
do {
trace_lttng_statedump_process_state(session,
p, type, mode, submode, status, pid_ns);
pid_ns = pid_ns->parent;
} while (pid_ns);
} else {
trace_lttng_statedump_process_state(session,
p, type, mode, submode, status, NULL);
}
rcu_read_unlock();
}
static
int lttng_enumerate_process_states(struct lttng_session *session)
{
struct task_struct *g, *p;
rcu_read_lock();
for_each_process(g) {
p = g;
do {
enum lttng_execution_mode mode =
LTTNG_MODE_UNKNOWN;
enum lttng_execution_submode submode =
LTTNG_UNKNOWN;
enum lttng_process_status status;
enum lttng_thread_type type;
task_lock(p);
if (p->exit_state == EXIT_ZOMBIE)
status = LTTNG_ZOMBIE;
else if (p->exit_state == EXIT_DEAD)
status = LTTNG_DEAD;
else if (p->state == TASK_RUNNING) {
/* Is this a forked child that has not run yet? */
if (list_empty(&p->rt.run_list))
status = LTTNG_WAIT_FORK;
else
/*
* All tasks are considered as wait_cpu;
* the viewer will sort out if the task
* was really running at this time.
*/
status = LTTNG_WAIT_CPU;
} else if (p->state &
(TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)) {
/* Task is waiting for something to complete */
status = LTTNG_WAIT;
} else
status = LTTNG_UNNAMED;
submode = LTTNG_NONE;
/*
* Verification of t->mm is to filter out kernel
* threads; Viewer will further filter out if a
* user-space thread was in syscall mode or not.
*/
if (p->mm)
type = LTTNG_USER_THREAD;
else
type = LTTNG_KERNEL_THREAD;
lttng_statedump_process_ns(session,
p, type, mode, submode, status);
task_unlock(p);
} while_each_thread(g, p);
}
rcu_read_unlock();
return 0;
}
//BEGIN : Added by Tarek ----------------------------------------------------//
static
int lttng_dump_one_sycall_address(struct lttng_session *session, const char *syscall_name, unsigned int runtime_syscall_address, unsigned int symbol_syscall_address)
{
if (!syscall_name ||
!runtime_syscall_address ||
!symbol_syscall_address ) {
return -1;
}
trace_lttng_statedump_syscall_address_list (session,
syscall_name,
runtime_syscall_address,
symbol_syscall_address);
return 0;
}
static __init
struct syscall_metadata *find_syscall_meta(unsigned long syscall)
{
struct syscall_metadata **iter;
for (iter = __start_syscalls_metadata;
iter < __stop_syscalls_metadata; iter++) {
if ((*iter)->syscall_nr == syscall)
return (*iter);
}
return NULL;
}
static
int lttng_enumerate_syscall_address_list(struct lttng_session *session)
{
// get syscall table address
// hash table that contains all system_call names and numbers
// iterate for every system call and get its address in the system call table
struct syscall_metadata *meta;
int i;
unsigned long *sys_call_table = NULL;
__start_syscalls_metadata = (void *) kallsyms_lookup_name("__start_syscalls_metadata");
__stop_syscalls_metadata = (void *) kallsyms_lookup_name("__stop_syscalls_metadata");
sys_call_table = (unsigned long *) kallsyms_lookup_name("sys_call_table");
for (i = 0; i < NR_syscalls; i++) {
int j;
meta = find_syscall_meta(i);
if (!meta || !sys_call_table)
continue;
printk("syscall %s ; nr %d ; nbargs %d ; address in sys call table : %p ",
meta->name, meta->syscall_nr, meta->nb_args, (void *) sys_call_table[meta->syscall_nr]);
// TODO : retierve the symbol address of a syscall in order to inject it in the third argument of lttng_dump_one_sycall_address function
lttng_dump_one_sycall_address(session,meta->name,sys_call_table[meta->syscall_nr], (unsigned int) NULL /* address of syscall symbol*/);
}
printk("SUCCESS\n");
return -1;
}
//END----------------------------------------------------//
static
void lttng_statedump_work_func(struct work_struct *work)
{
if (atomic_dec_and_test(&kernel_threads_to_run))
/* If we are the last thread, wake up do_lttng_statedump */
wake_up(&statedump_wq);
}
static
int do_lttng_statedump(struct lttng_session *session)
{
int cpu, ret;
trace_lttng_statedump_start(session);
ret = lttng_enumerate_process_states(session);
if (ret)
return ret;
//Added by Tarek
ret = lttng_enumerate_syscall_address_list(session);
if (ret)
return ret;
//
ret = lttng_enumerate_file_descriptors(session);
if (ret)
return ret;
/*
* FIXME
* ret = lttng_enumerate_vm_maps(session);
* if (ret)
* return ret;
*/
ret = lttng_list_interrupts(session);
if (ret)
return ret;
ret = lttng_enumerate_network_ip_interface(session);
if (ret)
return ret;
ret = lttng_enumerate_block_devices(session);
switch (ret) {
case -ENOSYS:
printk(KERN_WARNING "LTTng: block device enumeration is not supported by kernel\n");
break;
default:
return ret;
}
/* TODO lttng_dump_idt_table(session); */
/* TODO lttng_dump_softirq_vec(session); */
/* TODO lttng_list_modules(session); */
/* TODO lttng_dump_swap_files(session); */
/*
* Fire off a work queue on each CPU. Their sole purpose in life
* is to guarantee that each CPU has been in a state where is was in
* syscall mode (i.e. not in a trap, an IRQ or a soft IRQ).
*/
get_online_cpus();
atomic_set(&kernel_threads_to_run, num_online_cpus());
for_each_online_cpu(cpu) {
INIT_DELAYED_WORK(&cpu_work[cpu], lttng_statedump_work_func);
schedule_delayed_work_on(cpu, &cpu_work[cpu], 0);
}
/* Wait for all threads to run */
__wait_event(statedump_wq, (atomic_read(&kernel_threads_to_run) == 0));
put_online_cpus();
/* Our work is done */
trace_lttng_statedump_end(session);
return 0;
}
/*
* Called with session mutex held.
*/
int lttng_statedump_start(struct lttng_session *session)
{
return do_lttng_statedump(session);
}
EXPORT_SYMBOL_GPL(lttng_statedump_start);
static
int __init lttng_statedump_init(void)
{
/*
* Allow module to load even if the fixup cannot be done. This
* will allow seemless transition when the underlying issue fix
* is merged into the Linux kernel, and when tracepoint.c
* "tracepoint_module_notify" is turned into a static function.
*/
(void) wrapper_lttng_fixup_sig(THIS_MODULE);
return 0;
}
module_init(lttng_statedump_init);
static
void __exit lttng_statedump_exit(void)
{
}
module_exit(lttng_statedump_exit);
MODULE_LICENSE("GPL and additional rights");
MODULE_AUTHOR("Jean-Hugues Deschenes");
MODULE_DESCRIPTION("Linux Trace Toolkit Next Generation Statedump");
MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
__stringify(LTTNG_MODULES_MINOR_VERSION) "."
__stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
LTTNG_MODULES_EXTRAVERSION);
[-- Attachment #4: Type: text/plain, Size: 155 bytes --]
_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-09-10 15:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CAP7TvLdAAszF8YM9buAy-umJ1pYY+Mu-1vPPYE2=mMHoH72Rsg@mail.gmail.com>
2014-09-10 15:12 ` Question about how to retrieve ip value of a syscall Mathieu Desnoyers
2014-08-20 23:15 tarek slaymia
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).