/usr/share/systemtap/runtime/linux
NameSizeModeActions
uprobes/-0755rm
uprobes2/-0755rm
access_process_vm.h43110644editdlrm
addr-map.c97490644editdlrm
alloc.c159000644editdlrm
arith.c167990644editdlrm
autoconf-514-panic.c680644editdlrm
autoconf-access_ok_2args.c900644editdlrm
autoconf-alloc-percpu-align.c1180644editdlrm
autoconf-asm-syscall.c510644editdlrm
autoconf-atomic_fetch_add_unless.c940644editdlrm
autoconf-bio-bi_opf.c8240644editdlrm
autoconf-blk-types.c3590644editdlrm
autoconf-compat-utimbuf.c530644editdlrm
autoconf-compat_sigaction.c4480644editdlrm
autoconf-constant-tsc.c630644editdlrm
autoconf-cpu-clock.c12770644editdlrm
autoconf-dpath-path.c1210644editdlrm
autoconf-files_lookup_fd_raw.c1360644editdlrm
autoconf-from_kuid_munged.c1910644editdlrm
autoconf-fs_supers-hlist.c3540644editdlrm
autoconf-generated-compile.c560644editdlrm
autoconf-genhd.c2010644editdlrm
autoconf-get-kretprobe.c1070644editdlrm
autoconf-get_user_pages-flags.c15490644editdlrm
autoconf-get_user_pages-notask_struct.c13010644editdlrm
autoconf-get_user_pages_remote-flags.c15500644editdlrm
autoconf-get_user_pages_remote-flags_locked.c13310644editdlrm
autoconf-get_user_pages_remote-notask_struct.c14380644editdlrm
autoconf-grsecurity.c2190644editdlrm
autoconf-hlist-4args.c2960644editdlrm
autoconf-hlist_add_tail_rcu.c1120644editdlrm
autoconf-hrtimer-getset-expires.c1260644editdlrm
autoconf-hrtimer-rel.c870644editdlrm
autoconf-hw_breakpoint_context.c3150644editdlrm
autoconf-inode-private.c1730644editdlrm
autoconf-inode-rwsem.c1720644editdlrm
autoconf-inode-uretprobes.c2640644editdlrm
autoconf-kernel_read-new-args.c10300644editdlrm
autoconf-kprobe-symbol-name.c900644editdlrm
autoconf-ktime-get-real.c980644editdlrm
autoconf-linux-sched_headers.c16780644editdlrm
autoconf-local-clock.c12820644editdlrm
autoconf-lockdown-debugfs.c1020644editdlrm
autoconf-lockdown-kernel.c900644editdlrm
autoconf-mm-context-vdso-base.c1170644editdlrm
autoconf-mm-context-vdso.c1140644editdlrm
autoconf-mm-shmempages.c720644editdlrm
autoconf-mmap_lock.c1750644editdlrm
autoconf-module-sect-attrs.c1580644editdlrm
autoconf-module_layout.c520644editdlrm
autoconf-mod_kallsyms.c510644editdlrm
autoconf-nameidata.c960644editdlrm
autoconf-netfilter-4_1.c7690644editdlrm
autoconf-netfilter-4_4.c14600644editdlrm
autoconf-netfilter-313b.c6020644editdlrm
autoconf-netfilter.c4220644editdlrm
autoconf-old-inode-uprobes.c3570644editdlrm
autoconf-oneachcpu-retry.c9570644editdlrm
autoconf-pagefault_disable.c1370644editdlrm
autoconf-pde_data.c2260644editdlrm
autoconf-perf-structpid.c4440644editdlrm
autoconf-procfs-owner.c1580644editdlrm
autoconf-proc_ops.c5660644editdlrm
autoconf-rcu_is_watching.c3850644editdlrm
autoconf-real-parent.c4270644editdlrm
autoconf-regset.c2390644editdlrm
autoconf-relay-umode_t.c7300644editdlrm
autoconf-relay_buf-per_cpu_ptr.c9200644editdlrm
autoconf-ring_buffer-flags.c1120644editdlrm
autoconf-ring_buffer_lost_events.c2960644editdlrm
autoconf-ring_buffer_read_prepare.c1810644editdlrm
autoconf-save-stack-trace-no-bp.c4980644editdlrm
autoconf-save-stack-trace.c5010644editdlrm
autoconf-set_fs.c2210644editdlrm
autoconf-smpcall-4args.c1660644editdlrm
autoconf-smpcall-5args.c1690644editdlrm
autoconf-stack-trace-save-regs.c1760644editdlrm
autoconf-stacktrace_ops-int-address.c4090644editdlrm
autoconf-stacktrace_ops-warning.c1880644editdlrm
autoconf-syscall_get_args_3args.c2390644editdlrm
autoconf-task-state.c5500644editdlrm
autoconf-task-uid.c1520644editdlrm
autoconf-task_work-struct.c2190644editdlrm
autoconf-time32-old.c520644editdlrm
autoconf-time32.c530644editdlrm
autoconf-timerfd.c2320644editdlrm
autoconf-trace-printk.c1510644editdlrm
autoconf-tracepoint-has-data.c4930644editdlrm
autoconf-tracepoint-strings.c2330644editdlrm
autoconf-uaccess.c280644editdlrm
autoconf-uapi-mount.c520644editdlrm
autoconf-udelay_simple.c900644editdlrm
autoconf-uidgid.c500644editdlrm
autoconf-unwind-stack-trace.c3260644editdlrm
autoconf-uprobe-get-pc.c3740644editdlrm
autoconf-utrace-regset.c2730644editdlrm
autoconf-utrace-via-tracepoints.c17120644editdlrm
autoconf-vm-area-pte.c1410644editdlrm
autoconf-walk-stack.c2170644editdlrm
autoconf-x86-fs.c900644editdlrm
autoconf-x86-gs.c900644editdlrm
autoconf-x86-uniregs.c1400644editdlrm
autoconf-x86-xfs.c910644editdlrm
common_session_state.h32490644editdlrm
compat_net.h8580644editdlrm
compat_structs.h44090644editdlrm
compat_unistd.h683840644editdlrm
copy.c27170644editdlrm
debug.h29780644editdlrm
io.c52910644editdlrm
itrace.c148740644editdlrm
kprobes.c251260644editdlrm
loc2c-runtime.h298740644editdlrm
map_list.h12200644editdlrm
map_runtime.h52660644editdlrm
namespaces.h71280644editdlrm
netfilter.c14100644editdlrm
perf.c75960644editdlrm
perf.h12720644editdlrm
perf_event_counter_context.c3360644editdlrm
perf_probe_handler_nmi.c2780644editdlrm
perf_read.h9590644editdlrm
print.c114020644editdlrm
probe_lock.h18070644editdlrm
regs-ia64.c37410644editdlrm
regs.c134900644editdlrm
runtime.h125910644editdlrm
runtime_context.h60890644editdlrm
runtime_defines.h10410644editdlrm
stap_mmap_lock.h3430644editdlrm
stat_runtime.h17740644editdlrm
stp_tls.h11810644editdlrm
stp_tracepoint.c114810644editdlrm
stp_tracepoint.h22700644editdlrm
syscalls-common.h9760644editdlrm
task_finder.c538600644editdlrm
task_finder2.c576400644editdlrm
task_finder_map.c51940644editdlrm
task_finder_stubs.c24420644editdlrm
task_work_compatibility.h12830644editdlrm
timer.c22000644editdlrm
timer.h13830644editdlrm
timer_compatibility.h23170644editdlrm
uprobes-common.c155730644editdlrm
uprobes-common.h16530644editdlrm
uprobes-inc.h4840644editdlrm
uprobes-inode.c340860644editdlrm
Edit: /usr/share/systemtap/runtime/linux/print.c (11402B)
/* -*- linux-c -*- * Print Functions * Copyright (C) 2007-2018 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 _STAPLINUX_PRINT_C_ #define _STAPLINUX_PRINT_C_ #include "stp_string.h" #include "print.h" #include "transport/transport.c" #include "vsprintf.c" /** @file print.c * Printing Functions. */ /** @addtogroup print Print Functions * The print buffer is for collecting output to send to the user daemon. * This is a per-cpu static buffer. The buffer is sent when * _stp_print_flush() is called. * * The reason to do this is to allow multiple small prints to be combined then * timestamped and sent together to staprun. This is more efficient than sending * numerous small packets. * * This function is called automatically when the print buffer is full. * It MUST also be called at the end of every probe that prints something. * @{ */ struct _stp_log { unsigned int len; /* Bytes used in the buffer */ char *buf; /* NB we don't use arrays here to avoid allocating memory on offline CPUs (but still possible ones) */ atomic_t reentrancy_lock; }; #include "print_flush.c" static struct _stp_log *_stp_log_pcpu; /* * An atomic counter is used to synchronize every possible print buffer usage * with the _stp_print_cleanup() function. The cleanup function sets the counter * to INT_MAX after waiting for everything using the print buffer to finish. We * cannot use a lock primitive to implement this because lock_acquire() contains * tracepoints and print statements are used both inside and outside of probes. * If the lock were only used inside probes, the runtime context would protect * us from recursing into the lock_acquire() tracepoints and deadlocking. We * instead use _stp_print_ctr as if it were a read-write lock. */ static atomic_t _stp_print_ctr = ATOMIC_INIT(0); /* * This disables IRQs to make per-CPU print buffer accesses atomic. There is a * reentrancy protection mechanism specifically for NMIs, since they can violate * our atomic guarantee. Reentrancy is otherwise allowed within code sections * that have the runtime context held (via _stp_runtime_entryfn_get_context()). */ static bool _stp_print_trylock_irqsave(unsigned long *flags) { bool context_held = false; struct _stp_log *log; log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id()); /* We have to check log->buf == NULL here since the online * CPUs may change at any time through the CPU hotplug * feature of the kernel. So the current CPU's log->buf could be NULL * if it is a new online CPU. And we cannot allocate new memory from within * this context. */ if (unlikely(log->buf == NULL)) return false; local_irq_save(*flags); if (!atomic_add_unless(&_stp_print_ctr, 1, INT_MAX)) goto irq_restore; /* * Check the per-CPU reentrancy lock for contention, unless the runtime * context is already held, in which case we already have reentrancy * protection. Otherwise, if the reentrancy lock is contented, that * means we're either inside an NMI that fired while the current CPU was * accessing the log buffer, or something is trying to nest calls to * _stp_print_trylock_irqsave(). Our only choice is to reject the log * access attempt in this case because log buffer corruption and panics * could ensue if we're inside an NMI. */ if (_stp_runtime_context_trylock()) { struct context *c = _stp_runtime_get_context(); context_held = c && atomic_read(&c->busy); _stp_runtime_context_unlock(); } /* Fall back onto the reentrancy lock if the context isn't held */ if (!context_held) { if (atomic_cmpxchg(&log->reentrancy_lock, 0, 1)) goto print_unlock; } return true; print_unlock: atomic_dec(&_stp_print_ctr); irq_restore: local_irq_restore(*flags); return false; } static void _stp_print_unlock_irqrestore(unsigned long *flags) { bool context_held = false; struct _stp_log *log; if (_stp_runtime_context_trylock()) { struct context *c = _stp_runtime_get_context(); context_held = c && atomic_read(&c->busy); _stp_runtime_context_unlock(); } if (!context_held) { log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id()); atomic_set(&log->reentrancy_lock, 0); } atomic_dec(&_stp_print_ctr); local_irq_restore(*flags); } /* create percpu print and io buffers */ static int _stp_print_init (void) { unsigned int cpu; /* _stp_alloc_percpu() always zero-fills the allocated percpu memory * since the kernel's __alloc_percpu() always does that. */ _stp_log_pcpu = _stp_alloc_percpu(sizeof(*_stp_log_pcpu)); if (!_stp_log_pcpu) return -ENOMEM; /* We don't use for_aech_possible_cpu() here since the number of possible * CPUs may be very large even though there are many fewere online CPUs. * For example, VMWare guests usually have 128 possible CPUs while only * have a few online CPUs. Once the bufs were allocated for * online CPUs at this point, we will discard any printing operations on * any future online CPUs dynamically added through the kernel's CPU * hotplug feature. Memory allocations of the bufs can only happen right * here. */ for_each_online_cpu(cpu) { struct _stp_log *log = per_cpu_ptr(_stp_log_pcpu, cpu); log->reentrancy_lock = (atomic_t)ATOMIC_INIT(0); log->buf = _stp_vzalloc_node(STP_BUFFER_SIZE, cpu_to_node(cpu)); if (unlikely(log->buf == NULL)) { _stp_error ("print log buf (size %lu per cpu) allocation failed", (unsigned long) STP_BUFFER_SIZE); return -ENOMEM; } } return 0; } static void _stp_print_cleanup (void) { unsigned int cpu; /* Wait for the loggers to finish modifying the print buffers */ while (atomic_cmpxchg(&_stp_print_ctr, 0, INT_MAX)) cpu_relax(); /* NB We cannot use the for_each_online_cpu() here since online * CPUs may get changed on-the-fly through the CPU hotplug feature * of the kernel. We only allocated bufs on original online CPUs * when _stp_print_init() was called. */ for_each_possible_cpu(cpu) { struct _stp_log *log = per_cpu_ptr(_stp_log_pcpu, cpu); /* * Flush anything that could be left in the print buffer. It is * safe to do this without any kind of synchronization mechanism * because nothing is using this print buffer anymore. */ if (likely(log->buf)) { /* We have to check log->buf != NULL here since the * online CPUs may change at any time through the CPU * hotplug feature of the kernel. */ __stp_print_flush(log); _stp_vfree(log->buf); log->buf = NULL; } } _stp_free_percpu(_stp_log_pcpu); } static inline void _stp_print_flush(void) { struct _stp_log *log; unsigned long flags; if (!_stp_print_trylock_irqsave(&flags)) return; log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id()); __stp_print_flush(log); _stp_print_unlock_irqrestore(&flags); } #ifndef STP_MAXBINARYARGS #define STP_MAXBINARYARGS 127 #endif /** Reserves space in the output buffer for direct I/O. Must be called with * _stp_print_trylock_irqsave() held. */ static void * _stp_reserve_bytes (int numbytes) { struct _stp_log *log; char *ret; if (unlikely(numbytes == 0 || numbytes > STP_BUFFER_SIZE)) return NULL; log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id()); /* _stp_print_trylock_irqsave already checks log->buf != NULL */ if (unlikely(numbytes > (STP_BUFFER_SIZE - log->len))) __stp_print_flush(log); ret = &log->buf[log->len]; log->len += numbytes; return ret; } static void _stp_unreserve_bytes (int numbytes) { struct _stp_log *log; log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id()); /* We have to check log->buf == NULL here since the online CPUs may * change at any time through the CPU hotplug feature of the kernel. * So the current CPU's log->buf could be NULL if it is a new online * CPU. */ if (unlikely(log->buf == NULL)) return; if (numbytes <= log->len) log->len -= numbytes; } /** Write 64-bit args directly into the output stream. * This function takes a variable number of 64-bit arguments * and writes them directly into the output stream. Marginally faster * than doing the same in _stp_vsnprintf(). * @sa _stp_vsnprintf() */ static void _stp_print_binary (int num, ...) { unsigned long flags; va_list vargs; int i; int64_t *args; if (unlikely(num > STP_MAXBINARYARGS)) num = STP_MAXBINARYARGS; if (!_stp_print_trylock_irqsave(&flags)) return; args = _stp_reserve_bytes(num * sizeof(int64_t)); if (args) { va_start(vargs, num); for (i = 0; i < num; i++) args[i] = va_arg(vargs, int64_t); va_end(vargs); } _stp_print_unlock_irqrestore(&flags); } /** Print into the print buffer. * Like C printf. * * @sa _stp_print_flush() */ static void _stp_printf (const char *fmt, ...) { va_list args; va_start(args, fmt); _stp_vsnprintf(NULL, 0, fmt, args); va_end(args); } /** Write a string into the print buffer. * @param str A C string (char *) */ static void _stp_print (const char *str) { struct _stp_log *log; unsigned long flags; if (!_stp_print_trylock_irqsave(&flags)) return; log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id()); while (1) { while (log->len < STP_BUFFER_SIZE && *str) log->buf[log->len++] = *str++; if (likely(!*str)) break; __stp_print_flush(log); } _stp_print_unlock_irqrestore(&flags); } static void _stp_print_char (const char c) { struct _stp_log *log; unsigned long flags; if (!_stp_print_trylock_irqsave(&flags)) return; log = per_cpu_ptr(_stp_log_pcpu, raw_smp_processor_id()); if (unlikely(log->len == STP_BUFFER_SIZE)) __stp_print_flush(log); log->buf[log->len++] = c; _stp_print_unlock_irqrestore(&flags); } static void _stp_print_kernel_info(char *sname, char *vstr, int ctx, int num_probes) { printk(KERN_DEBUG "%s (%s): systemtap: %s, base: %lx" ", memory: %ludata/%lutext/%uctx/%lunet/%lualloc kb" ", probes: %d" #if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) ", unpriv-uid: %d" #endif "\n", THIS_MODULE->name, sname, /* name of source file */ vstr, /* stap version */ #ifdef STAPCONF_MODULE_LAYOUT (unsigned long) THIS_MODULE->core_layout.base, (unsigned long) (THIS_MODULE->core_layout.size - THIS_MODULE->core_layout.text_size)/1024, (unsigned long) (THIS_MODULE->core_layout.text_size)/1024, #else #ifndef STAPCONF_GRSECURITY (unsigned long) THIS_MODULE->module_core, (unsigned long) (THIS_MODULE->core_size - THIS_MODULE->core_text_size)/1024, (unsigned long) (THIS_MODULE->core_text_size)/1024, #else (unsigned long) THIS_MODULE->module_core_rx, (unsigned long) (THIS_MODULE->core_size_rw - THIS_MODULE->core_size_rx)/1024, (unsigned long) (THIS_MODULE->core_size_rx)/1024, #endif #endif ctx/1024, _stp_allocated_net_memory/1024, (_stp_allocated_memory - _stp_allocated_net_memory - ctx)/1024, /* (un-double-counting net/ctx because they're also stp_alloc'd) */ num_probes #if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) , _stp_uid #endif ); } /** @} */ #endif /* _STAPLINUX_PRINT_C_ */