)]}'
{
  "commit": "73649dab0fd524cb8545a8cb83c6eaf77b107105",
  "tree": "70f43b37ba915de148c28008e275dacec200e33f",
  "parents": [
    "b94cce926b2b902b79380ccba370d6f9f2980de0"
  ],
  "author": {
    "name": "Rusty Lynch",
    "email": "rusty.lynch@intel.com",
    "time": "Thu Jun 23 00:09:23 2005 -0700"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@ppc970.osdl.org",
    "time": "Thu Jun 23 09:45:21 2005 -0700"
  },
  "message": "[PATCH] x86_64 specific function return probes\n\nThe following patch adds the x86_64 architecture specific implementation\nfor function return probes.\n\nFunction return probes is a mechanism built on top of kprobes that allows\na caller to register a handler to be called when a given function exits.\nFor example, to instrument the return path of sys_mkdir:\n\nstatic int sys_mkdir_exit(struct kretprobe_instance *i, struct pt_regs *regs)\n{\n\tprintk(\"sys_mkdir exited\\n\");\n\treturn 0;\n}\nstatic struct kretprobe return_probe \u003d {\n\t.handler \u003d sys_mkdir_exit,\n};\n\n\u003cinside setup function\u003e\n\nreturn_probe.kp.addr \u003d (kprobe_opcode_t *) kallsyms_lookup_name(\"sys_mkdir\");\nif (register_kretprobe(\u0026return_probe)) {\n\tprintk(KERN_DEBUG \"Unable to register return probe!\\n\");\n\t/* do error path */\n}\n\n\u003cinside cleanup function\u003e\nunregister_kretprobe(\u0026return_probe);\n\nThe way this works is that:\n\n* At system initialization time, kernel/kprobes.c installs a kprobe\n  on a function called kretprobe_trampoline() that is implemented in\n  the arch/x86_64/kernel/kprobes.c  (More on this later)\n\n* When a return probe is registered using register_kretprobe(),\n  kernel/kprobes.c will install a kprobe on the first instruction of the\n  targeted function with the pre handler set to arch_prepare_kretprobe()\n  which is implemented in arch/x86_64/kernel/kprobes.c.\n\n* arch_prepare_kretprobe() will prepare a kretprobe instance that stores:\n  - nodes for hanging this instance in an empty or free list\n  - a pointer to the return probe\n  - the original return address\n  - a pointer to the stack address\n\n  With all this stowed away, arch_prepare_kretprobe() then sets the return\n  address for the targeted function to a special trampoline function called\n  kretprobe_trampoline() implemented in arch/x86_64/kernel/kprobes.c\n\n* The kprobe completes as normal, with control passing back to the target\n  function that executes as normal, and eventually returns to our trampoline\n  function.\n\n* Since a kprobe was installed on kretprobe_trampoline() during system\n  initialization, control passes back to kprobes via the architecture\n  specific function trampoline_probe_handler() which will lookup the\n  instance in an hlist maintained by kernel/kprobes.c, and then call\n  the handler function.\n\n* When trampoline_probe_handler() is done, the kprobes infrastructure\n  single steps the original instruction (in this case just a top), and\n  then calls trampoline_post_handler().  trampoline_post_handler() then\n  looks up the instance again, puts the instance back on the free list,\n  and then makes a long jump back to the original return instruction.\n\nSo to recap, to instrument the exit path of a function this implementation\nwill cause four interruptions:\n\n  - A breakpoint at the very beginning of the function allowing us to\n    switch out the return address\n  - A single step interruption to execute the original instruction that\n    we replaced with the break instruction (normal kprobe flow)\n  - A breakpoint in the trampoline function where our instrumented function\n    returned to\n  - A single step interruption to execute the original instruction that\n    we replaced with the break instruction (normal kprobe flow)\n\nSigned-off-by: Andrew Morton \u003cakpm@osdl.org\u003e\nSigned-off-by: Linus Torvalds \u003ctorvalds@osdl.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "f77f8a0ff1873bdc1717d473f74eb4116874eae7",
      "old_mode": 33188,
      "old_path": "arch/x86_64/kernel/kprobes.c",
      "new_id": "203672ca7401cbf988397e5ef7d5a44d36d243ff",
      "new_mode": 33188,
      "new_path": "arch/x86_64/kernel/kprobes.c"
    },
    {
      "type": "modify",
      "old_id": "dce8bab4306cdc3c73abd6ef91529040487360fb",
      "old_mode": 33188,
      "old_path": "arch/x86_64/kernel/process.c",
      "new_id": "e59d1f9d616396172129d91524196d4551324f1f",
      "new_mode": 33188,
      "new_path": "arch/x86_64/kernel/process.c"
    },
    {
      "type": "modify",
      "old_id": "bfea52d516f8eb0d0d2076827b8f32d74e50a7d5",
      "old_mode": 33188,
      "old_path": "include/asm-x86_64/kprobes.h",
      "new_id": "6d6d883fdf6d0f2862d3a41771f15ba09ed04c5a",
      "new_mode": 33188,
      "new_path": "include/asm-x86_64/kprobes.h"
    }
  ]
}
