diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-06 12:30:52 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-06 12:30:52 -0400 |
| commit | 4aed2fd8e3181fea7c09ba79cf64e7e3f4413bf9 (patch) | |
| tree | 1f69733e5daab4915a76a41de0e4d1dc61e12cfb /arch/x86/kernel/kprobes.c | |
| parent | 3a3527b6461b1298cc53ce72f336346739297ac8 (diff) | |
| parent | fc9ea5a1e53ee54f681e226d735008e2a6f8f470 (diff) | |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (162 commits)
tracing/kprobes: unregister_trace_probe needs to be called under mutex
perf: expose event__process function
perf events: Fix mmap offset determination
perf, powerpc: fsl_emb: Restore setting perf_sample_data.period
perf, powerpc: Convert the FSL driver to use local64_t
perf tools: Don't keep unreferenced maps when unmaps are detected
perf session: Invalidate last_match when removing threads from rb_tree
perf session: Free the ref_reloc_sym memory at the right place
x86,mmiotrace: Add support for tracing STOS instruction
perf, sched migration: Librarize task states and event headers helpers
perf, sched migration: Librarize the GUI class
perf, sched migration: Make the GUI class client agnostic
perf, sched migration: Make it vertically scrollable
perf, sched migration: Parameterize cpu height and spacing
perf, sched migration: Fix key bindings
perf, sched migration: Ignore unhandled task states
perf, sched migration: Handle ignored migrate out events
perf: New migration tool overview
tracing: Drop cpparg() macro
perf: Use tracepoint_synchronize_unregister() to flush any pending tracepoint call
...
Fix up trivial conflicts in Makefile and drivers/cpufreq/cpufreq.c
Diffstat (limited to 'arch/x86/kernel/kprobes.c')
| -rw-r--r-- | arch/x86/kernel/kprobes.c | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 675879b65ce6..1bfb6cf4dd55 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c | |||
| @@ -126,16 +126,22 @@ static void __kprobes synthesize_reljump(void *from, void *to) | |||
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | /* | 128 | /* |
| 129 | * Check for the REX prefix which can only exist on X86_64 | 129 | * Skip the prefixes of the instruction. |
| 130 | * X86_32 always returns 0 | ||
| 131 | */ | 130 | */ |
| 132 | static int __kprobes is_REX_prefix(kprobe_opcode_t *insn) | 131 | static kprobe_opcode_t *__kprobes skip_prefixes(kprobe_opcode_t *insn) |
| 133 | { | 132 | { |
| 133 | insn_attr_t attr; | ||
| 134 | |||
| 135 | attr = inat_get_opcode_attribute((insn_byte_t)*insn); | ||
| 136 | while (inat_is_legacy_prefix(attr)) { | ||
| 137 | insn++; | ||
| 138 | attr = inat_get_opcode_attribute((insn_byte_t)*insn); | ||
| 139 | } | ||
| 134 | #ifdef CONFIG_X86_64 | 140 | #ifdef CONFIG_X86_64 |
| 135 | if ((*insn & 0xf0) == 0x40) | 141 | if (inat_is_rex_prefix(attr)) |
| 136 | return 1; | 142 | insn++; |
| 137 | #endif | 143 | #endif |
| 138 | return 0; | 144 | return insn; |
| 139 | } | 145 | } |
| 140 | 146 | ||
| 141 | /* | 147 | /* |
| @@ -272,6 +278,9 @@ static int __kprobes can_probe(unsigned long paddr) | |||
| 272 | */ | 278 | */ |
| 273 | static int __kprobes is_IF_modifier(kprobe_opcode_t *insn) | 279 | static int __kprobes is_IF_modifier(kprobe_opcode_t *insn) |
| 274 | { | 280 | { |
| 281 | /* Skip prefixes */ | ||
| 282 | insn = skip_prefixes(insn); | ||
| 283 | |||
| 275 | switch (*insn) { | 284 | switch (*insn) { |
| 276 | case 0xfa: /* cli */ | 285 | case 0xfa: /* cli */ |
| 277 | case 0xfb: /* sti */ | 286 | case 0xfb: /* sti */ |
| @@ -280,13 +289,6 @@ static int __kprobes is_IF_modifier(kprobe_opcode_t *insn) | |||
| 280 | return 1; | 289 | return 1; |
| 281 | } | 290 | } |
| 282 | 291 | ||
| 283 | /* | ||
| 284 | * on X86_64, 0x40-0x4f are REX prefixes so we need to look | ||
| 285 | * at the next byte instead.. but of course not recurse infinitely | ||
| 286 | */ | ||
| 287 | if (is_REX_prefix(insn)) | ||
| 288 | return is_IF_modifier(++insn); | ||
| 289 | |||
| 290 | return 0; | 292 | return 0; |
| 291 | } | 293 | } |
| 292 | 294 | ||
| @@ -803,9 +805,8 @@ static void __kprobes resume_execution(struct kprobe *p, | |||
| 803 | unsigned long orig_ip = (unsigned long)p->addr; | 805 | unsigned long orig_ip = (unsigned long)p->addr; |
| 804 | kprobe_opcode_t *insn = p->ainsn.insn; | 806 | kprobe_opcode_t *insn = p->ainsn.insn; |
| 805 | 807 | ||
| 806 | /*skip the REX prefix*/ | 808 | /* Skip prefixes */ |
| 807 | if (is_REX_prefix(insn)) | 809 | insn = skip_prefixes(insn); |
| 808 | insn++; | ||
| 809 | 810 | ||
| 810 | regs->flags &= ~X86_EFLAGS_TF; | 811 | regs->flags &= ~X86_EFLAGS_TF; |
| 811 | switch (*insn) { | 812 | switch (*insn) { |
