2017-11-09 17:25:45

by Yonghong Song

[permalink] [raw]
Subject: Re: [PATCH x86 v2] uprobe: emulate push insns for uprobe on x86



On 11/9/17 3:26 AM, David Laight wrote:
> From: Yonghong Song
>> Sent: 09 November 2017 00:55
>>
>> Uprobe is a tracing mechanism for userspace programs.
>> Typical uprobe will incur overhead of two traps.
>> First trap is caused by replaced trap insn, and
>> the second trap is to execute the original displaced
>> insn in user space.
>>
>> To reduce the overhead, kernel provides hooks
>> for architectures to emulate the original insn
>> and skip the second trap. In x86, emulation
>> is done for certain branch insns.
>>
>> This patch extends the emulation to "push <reg>"
>> insns. These insns are typical in the beginning
>> of the function. For example, bcc
> ...
>> diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
>> index 74f4c2f..f9d2b43 100644
>> --- a/arch/x86/include/asm/uprobes.h
>> +++ b/arch/x86/include/asm/uprobes.h
>> @@ -33,6 +33,11 @@ typedef u8 uprobe_opcode_t;
> ...
>> @@ -53,6 +59,10 @@ struct arch_uprobe {
>> u8 fixups;
>> u8 ilen;
>> } defparam;
>> + struct {
>> + u8 rex_prefix;
>
> Just call this 'reg_high' and set to 0 or 1.

Will do.

>
>> + u8 opc1;
>> + } push;
>> };
>> };
>>
>> diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
>> index a3755d2..5ace65c 100644
>> --- a/arch/x86/kernel/uprobes.c
>> +++ b/arch/x86/kernel/uprobes.c
>> @@ -640,11 +640,71 @@ static bool check_jmp_cond(struct arch_uprobe *auprobe, struct pt_regs *regs)
>> #undef COND
>> #undef CASE_COND
>>
>> -static bool branch_emulate_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
>> +static unsigned long *get_push_reg_ptr(struct arch_uprobe *auprobe,
>> + struct pt_regs *regs)
>> {
>> - unsigned long new_ip = regs->ip += auprobe->branch.ilen;
>> - unsigned long offs = (long)auprobe->branch.offs;
>> +#if defined(CONFIG_X86_64)
>> + switch (auprobe->push.opc1) {
>> + case 0x50:
>> + return auprobe->push.rex_prefix ? &regs->r8 : &regs->ax;
>> + case 0x51:
>> + return auprobe->push.rex_prefix ? &regs->r9 : &regs->cx;
>> + case 0x52:
>> + return auprobe->push.rex_prefix ? &regs->r10 : &regs->dx;
>> + case 0x53:
>> + return auprobe->push.rex_prefix ? &regs->r11 : &regs->bx;
>> + case 0x54:
>> + return auprobe->push.rex_prefix ? &regs->r12 : &regs->sp;
>> + case 0x55:
>> + return auprobe->push.rex_prefix ? &regs->r13 : &regs->bp;
>> + case 0x56:
>> + return auprobe->push.rex_prefix ? &regs->r14 : &regs->si;
>> + }
>> +
>> + /* opc1 0x57 */
>> + return auprobe->push.rex_prefix ? &regs->r15 : &regs->di;
>
> The bottom of that switch statement is horrid....
> Actually why can't you sort out this address in the code that
> sets up 'reg_prefix' (etc);

Good suggestion. Will do.

>
> David
>

From 1583587584516368142@xxx Thu Nov 09 11:26:47 +0000 2017
X-GM-THRID: 1583547898123441695
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread