Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 37877
b: refs/heads/master
c: 12dce62
h: refs/heads/master
i:
  37875: 43c71c7
v: v3
  • Loading branch information
Linus Torvalds committed Oct 2, 2006
1 parent 09584f2 commit 2e9ed37
Show file tree
Hide file tree
Showing 297 changed files with 5,332 additions and 3,724 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 04b314b2c3732bb5aa752fdbb3076de16decdab6
refs/heads/master: 12dce6263d43daeb4e16fa4eb964c1c99fa4fa2e
89 changes: 56 additions & 33 deletions trunk/Documentation/kprobes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ So that you can load and unload Kprobes-based instrumentation modules,
make sure "Loadable module support" (CONFIG_MODULES) and "Module
unloading" (CONFIG_MODULE_UNLOAD) are set to "y".

You may also want to ensure that CONFIG_KALLSYMS and perhaps even
CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name()
is a handy, version-independent way to find a function's address.
Also make sure that CONFIG_KALLSYMS and perhaps even CONFIG_KALLSYMS_ALL
are set to "y", since kallsyms_lookup_name() is used by the in-kernel
kprobe address resolution code.

If you need to insert a probe in the middle of a function, you may find
it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO),
Expand All @@ -179,6 +179,27 @@ occurs during execution of kp->pre_handler or kp->post_handler,
or during single-stepping of the probed instruction, Kprobes calls
kp->fault_handler. Any or all handlers can be NULL.

NOTE:
1. With the introduction of the "symbol_name" field to struct kprobe,
the probepoint address resolution will now be taken care of by the kernel.
The following will now work:

kp.symbol_name = "symbol_name";

(64-bit powerpc intricacies such as function descriptors are handled
transparently)

2. Use the "offset" field of struct kprobe if the offset into the symbol
to install a probepoint is known. This field is used to calculate the
probepoint.

3. Specify either the kprobe "symbol_name" OR the "addr". If both are
specified, kprobe registration will fail with -EINVAL.

4. With CISC architectures (such as i386 and x86_64), the kprobes code
does not validate if the kprobe.addr is at an instruction boundary.
Use "offset" with caution.

register_kprobe() returns 0 on success, or a negative errno otherwise.

User's pre-handler (kp->pre_handler):
Expand Down Expand Up @@ -225,6 +246,12 @@ control to Kprobes.) If the probed function is declared asmlinkage,
fastcall, or anything else that affects how args are passed, the
handler's declaration must match.

NOTE: A macro JPROBE_ENTRY is provided to handle architecture-specific
aliasing of jp->entry. In the interest of portability, it is advised
to use:

jp->entry = JPROBE_ENTRY(handler);

register_jprobe() returns 0 on success, or a negative errno otherwise.

4.3 register_kretprobe
Expand All @@ -251,6 +278,11 @@ of interest:
- ret_addr: the return address
- rp: points to the corresponding kretprobe object
- task: points to the corresponding task struct

The regs_return_value(regs) macro provides a simple abstraction to
extract the return value from the appropriate register as defined by
the architecture's ABI.

The handler's return value is currently ignored.

4.4 unregister_*probe
Expand Down Expand Up @@ -369,7 +401,6 @@ stack trace and selected i386 registers when do_fork() is called.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/sched.h>

/*For each probe you need to allocate a kprobe structure*/
Expand Down Expand Up @@ -403,18 +434,14 @@ int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
return 0;
}

int init_module(void)
static int __init kprobe_init(void)
{
int ret;
kp.pre_handler = handler_pre;
kp.post_handler = handler_post;
kp.fault_handler = handler_fault;
kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name("do_fork");
/* register the kprobe now */
if (!kp.addr) {
printk("Couldn't find %s to plant kprobe\n", "do_fork");
return -1;
}
kp.symbol_name = "do_fork";

if ((ret = register_kprobe(&kp) < 0)) {
printk("register_kprobe failed, returned %d\n", ret);
return -1;
Expand All @@ -423,12 +450,14 @@ int init_module(void)
return 0;
}

void cleanup_module(void)
static void __exit kprobe_exit(void)
{
unregister_kprobe(&kp);
printk("kprobe unregistered\n");
}

module_init(kprobe_init)
module_exit(kprobe_exit)
MODULE_LICENSE("GPL");
----- cut here -----

Expand Down Expand Up @@ -463,7 +492,6 @@ the arguments of do_fork().
#include <linux/fs.h>
#include <linux/uio.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>

/*
* Jumper probe for do_fork.
Expand All @@ -485,17 +513,13 @@ long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
}

static struct jprobe my_jprobe = {
.entry = (kprobe_opcode_t *) jdo_fork
.entry = JPROBE_ENTRY(jdo_fork)
};

int init_module(void)
static int __init jprobe_init(void)
{
int ret;
my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
if (!my_jprobe.kp.addr) {
printk("Couldn't find %s to plant jprobe\n", "do_fork");
return -1;
}
my_jprobe.kp.symbol_name = "do_fork";

if ((ret = register_jprobe(&my_jprobe)) <0) {
printk("register_jprobe failed, returned %d\n", ret);
Expand All @@ -506,12 +530,14 @@ int init_module(void)
return 0;
}

void cleanup_module(void)
static void __exit jprobe_exit(void)
{
unregister_jprobe(&my_jprobe);
printk("jprobe unregistered\n");
}

module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL");
----- cut here -----

Expand All @@ -530,16 +556,13 @@ report failed calls to sys_open().
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>

static const char *probed_func = "sys_open";

/* Return-probe handler: If the probed function fails, log the return value. */
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
// Substitute the appropriate register name for your architecture --
// e.g., regs->rax for x86_64, regs->gpr[3] for ppc64.
int retval = (int) regs->eax;
int retval = regs_return_value(regs);
if (retval < 0) {
printk("%s returns %d\n", probed_func, retval);
}
Expand All @@ -552,15 +575,11 @@ static struct kretprobe my_kretprobe = {
.maxactive = 20
};

int init_module(void)
static int __init kretprobe_init(void)
{
int ret;
my_kretprobe.kp.addr =
(kprobe_opcode_t *) kallsyms_lookup_name(probed_func);
if (!my_kretprobe.kp.addr) {
printk("Couldn't find %s to plant return probe\n", probed_func);
return -1;
}
my_kretprobe.kp.symbol_name = (char *)probed_func;

if ((ret = register_kretprobe(&my_kretprobe)) < 0) {
printk("register_kretprobe failed, returned %d\n", ret);
return -1;
Expand All @@ -569,7 +588,7 @@ int init_module(void)
return 0;
}

void cleanup_module(void)
static void __exit kretprobe_exit(void)
{
unregister_kretprobe(&my_kretprobe);
printk("kretprobe unregistered\n");
Expand All @@ -578,6 +597,8 @@ void cleanup_module(void)
my_kretprobe.nmissed, probed_func);
}

module_init(kretprobe_init)
module_exit(kretprobe_exit)
MODULE_LICENSE("GPL");
----- cut here -----

Expand All @@ -590,3 +611,5 @@ messages.)
For additional information on Kprobes, refer to the following URLs:
http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe
http://www.redhat.com/magazine/005mar05/features/kprobes/
http://www-users.cs.umn.edu/~boutcher/kprobes/
http://www.linuxsymposium.org/2006/linuxsymposium_procv2.pdf (pages 101-115)
3 changes: 1 addition & 2 deletions trunk/arch/alpha/kernel/alpha_ksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include <asm/cacheflush.h>
#include <asm/vga.h>

#define __KERNEL_SYSCALLS__
#include <asm/unistd.h>

extern struct hwrpb_struct *hwrpb;
Expand Down Expand Up @@ -116,7 +115,7 @@ EXPORT_SYMBOL(sys_dup);
EXPORT_SYMBOL(sys_exit);
EXPORT_SYMBOL(sys_write);
EXPORT_SYMBOL(sys_lseek);
EXPORT_SYMBOL(execve);
EXPORT_SYMBOL(kernel_execve);
EXPORT_SYMBOL(sys_setsid);
EXPORT_SYMBOL(sys_wait4);

Expand Down
10 changes: 5 additions & 5 deletions trunk/arch/alpha/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -655,12 +655,12 @@ kernel_thread:
.end kernel_thread

/*
* execve(path, argv, envp)
* kernel_execve(path, argv, envp)
*/
.align 4
.globl execve
.ent execve
execve:
.globl kernel_execve
.ent kernel_execve
kernel_execve:
/* We can be called from a module. */
ldgp $gp, 0($27)
lda $sp, -(32+SIZEOF_PT_REGS+8)($sp)
Expand Down Expand Up @@ -704,7 +704,7 @@ execve:

1: lda $sp, 32+SIZEOF_PT_REGS+8($sp)
ret
.end execve
.end kernel_execve


/*
Expand Down
26 changes: 13 additions & 13 deletions trunk/arch/alpha/kernel/osf_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,15 @@ osf_utsname(char __user *name)

down_read(&uts_sem);
error = -EFAULT;
if (copy_to_user(name + 0, system_utsname.sysname, 32))
if (copy_to_user(name + 0, utsname()->sysname, 32))
goto out;
if (copy_to_user(name + 32, system_utsname.nodename, 32))
if (copy_to_user(name + 32, utsname()->nodename, 32))
goto out;
if (copy_to_user(name + 64, system_utsname.release, 32))
if (copy_to_user(name + 64, utsname()->release, 32))
goto out;
if (copy_to_user(name + 96, system_utsname.version, 32))
if (copy_to_user(name + 96, utsname()->version, 32))
goto out;
if (copy_to_user(name + 128, system_utsname.machine, 32))
if (copy_to_user(name + 128, utsname()->machine, 32))
goto out;

error = 0;
Expand Down Expand Up @@ -449,8 +449,8 @@ osf_getdomainname(char __user *name, int namelen)

down_read(&uts_sem);
for (i = 0; i < len; ++i) {
__put_user(system_utsname.domainname[i], name + i);
if (system_utsname.domainname[i] == '\0')
__put_user(utsname()->domainname[i], name + i);
if (utsname()->domainname[i] == '\0')
break;
}
up_read(&uts_sem);
Expand Down Expand Up @@ -607,12 +607,12 @@ osf_sigstack(struct sigstack __user *uss, struct sigstack __user *uoss)
asmlinkage long
osf_sysinfo(int command, char __user *buf, long count)
{
static char * sysinfo_table[] = {
system_utsname.sysname,
system_utsname.nodename,
system_utsname.release,
system_utsname.version,
system_utsname.machine,
char *sysinfo_table[] = {
utsname()->sysname,
utsname()->nodename,
utsname()->release,
utsname()->version,
utsname()->machine,
"alpha", /* instruction set architecture */
"dummy", /* hardware serial number */
"dummy", /* hardware manufacturer */
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/alpha/kernel/srmcons.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ srmcons_close(struct tty_struct *tty, struct file *filp)

static struct tty_driver *srmcons_driver;

static struct tty_operations srmcons_ops = {
static const struct tty_operations srmcons_ops = {
.open = srmcons_open,
.close = srmcons_close,
.write = srmcons_write,
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/arm/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ static void __init setup_processor(void)
cpu_name, processor_id, (int)processor_id & 15,
proc_arch[cpu_architecture()], cr_alignment);

sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
elf_hwcap = list->elf_hwcap;
#ifndef CONFIG_ARM_THUMB
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
* The online bitmask indicates that the CPU is up and running.
*/
cpumask_t cpu_possible_map;
EXPORT_SYMBOL(cpu_possible_map);
cpumask_t cpu_online_map;
EXPORT_SYMBOL(cpu_online_map);

/*
* as from 2.5, kernels no longer have an init_tasks structure
Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/arm/kernel/sys_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ asmlinkage int sys_execve(char __user *filenamei, char __user * __user *argv,
return error;
}

long execve(const char *filename, char **argv, char **envp)
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
{
struct pt_regs regs;
int ret;
Expand Down Expand Up @@ -317,7 +317,7 @@ long execve(const char *filename, char **argv, char **envp)
out:
return ret;
}
EXPORT_SYMBOL(execve);
EXPORT_SYMBOL(kernel_execve);

/*
* Since loff_t is a 64 bit type we avoid a lot of ABI hastle
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/arm26/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ static void __init setup_processor(void)

dump_cpu_info();

sprintf(system_utsname.machine, "%s", list->arch_name);
sprintf(init_utsname()->machine, "%s", list->arch_name);
sprintf(elf_platform, "%s", list->elf_name);
elf_hwcap = list->elf_hwcap;

Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/arm26/kernel/sys_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ asmlinkage int sys_execve(char *filenamei, char **argv, char **envp, struct pt_r
}

/* FIXME - see if this is correct for arm26 */
long execve(const char *filename, char **argv, char **envp)
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
{
struct pt_regs regs;
int ret;
Expand Down Expand Up @@ -320,4 +320,4 @@ long execve(const char *filename, char **argv, char **envp)
return ret;
}

EXPORT_SYMBOL(execve);
EXPORT_SYMBOL(kernel_execve);
Loading

0 comments on commit 2e9ed37

Please sign in to comment.