From mboxrd@z Thu Jan 1 00:00:00 1970 From: mhiramat@kernel.org (Masami Hiramatsu) Date: Wed, 14 Nov 2018 00:37:30 -0800 Subject: [RFC/RFT 2/2] RISC-V: kprobes/kretprobe support In-Reply-To: <20181113195804.22825-3-me@packi.ch> References: <20181113195804.22825-1-me@packi.ch> <20181113195804.22825-3-me@packi.ch> Message-ID: <20181114003730.06f810517a270070734df4ce@kernel.org> To: linux-riscv@lists.infradead.org List-Id: linux-riscv.lists.infradead.org Hi Patrick, Thank you very much for implementing kprobes on RISC-V :) On Tue, 13 Nov 2018 20:58:04 +0100 Patrick St?hlin wrote: > First implementation, adapted from arm64. The C.ADDISP16 instruction > gets simulated and the kprobes-handler called by inserting a C.EBREAK > instruction. > > C.ADDISP16 was chosen as it sets-up the stack frame for functions. > Some work has been done to support probes on non-compressed > instructions but there is no support yet for decoding those. Does this only support C.ADDISP16? No other insns are supported? Supporting 1 insn is too few I think. Can RISC-V do single stepping? If not, we need to prepare emulator as match as possible, or for ALU instructions, we can run it on buffer and hook it. > The way forward should be to uncompress the instructions for simulation > to reduce the number of instructions used to decode the immediate > values on probe hit. I have some comments on the patch, please review. > > Signed-off-by: Patrick St?hlin > --- > arch/riscv/Kconfig | 5 +- > arch/riscv/include/asm/kprobes.h | 30 ++ > arch/riscv/include/asm/probes.h | 26 ++ > arch/riscv/kernel/Makefile | 1 + > arch/riscv/kernel/probes/Makefile | 3 + > arch/riscv/kernel/probes/decode-insn.c | 38 ++ > arch/riscv/kernel/probes/decode-insn.h | 23 + > arch/riscv/kernel/probes/kprobes.c | 401 ++++++++++++++++++ > arch/riscv/kernel/probes/kprobes_trampoline.S | 91 ++++ > arch/riscv/kernel/probes/simulate-insn.c | 33 ++ > arch/riscv/kernel/probes/simulate-insn.h | 8 + > arch/riscv/kernel/traps.c | 13 +- > arch/riscv/mm/fault.c | 28 +- > 13 files changed, 694 insertions(+), 6 deletions(-) > create mode 100644 arch/riscv/include/asm/probes.h > create mode 100644 arch/riscv/kernel/probes/Makefile > create mode 100644 arch/riscv/kernel/probes/decode-insn.c > create mode 100644 arch/riscv/kernel/probes/decode-insn.h > create mode 100644 arch/riscv/kernel/probes/kprobes.c > create mode 100644 arch/riscv/kernel/probes/kprobes_trampoline.S > create mode 100644 arch/riscv/kernel/probes/simulate-insn.c > create mode 100644 arch/riscv/kernel/probes/simulate-insn.h > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index b157ac82d486..11ef4030e8f2 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -44,6 +44,8 @@ config RISCV > select GENERIC_IRQ_MULTI_HANDLER > select ARCH_HAS_PTE_SPECIAL > select HAVE_REGS_AND_STACK_ACCESS_API > + select HAVE_KPROBES > + select HAVE_KRETPROBES > > config MMU > def_bool y > @@ -89,9 +91,6 @@ config PGTABLE_LEVELS > default 3 if 64BIT > default 2 > > -config HAVE_KPROBES > - def_bool n > - > menu "Platform type" > > choice > diff --git a/arch/riscv/include/asm/kprobes.h b/arch/riscv/include/asm/kprobes.h > index c7eb010d1528..657adcd35a3d 100644 > --- a/arch/riscv/include/asm/kprobes.h > +++ b/arch/riscv/include/asm/kprobes.h > @@ -19,4 +19,34 @@ > > #include > > +#ifdef CONFIG_KPROBES > +#include > +#include > +#include > + > +#define flush_insn_slot(p) do { } while (0) > +#define kretprobe_blacklist_size 0 > + > +#include > + > +struct prev_kprobe { > + struct kprobe *kp; > + unsigned int status; > +}; > + > +/* per-cpu kprobe control block */ > +struct kprobe_ctlblk { > + unsigned int kprobe_status; > + struct prev_kprobe prev_kprobe; > +}; > + > +void arch_remove_kprobe(struct kprobe *p); > +int kprobe_fault_handler(struct pt_regs *regs, unsigned int cause); > +int kprobe_exceptions_notify(struct notifier_block *self, > + unsigned long val, void *data); > +int kprobe_breakpoint_handler(struct pt_regs *regs); > +void kretprobe_trampoline(void); > +void __kprobes *trampoline_probe_handler(struct pt_regs *regs); > + > +#endif /* CONFIG_KPROBES */ > #endif /* _RISCV_KPROBES_H */ > diff --git a/arch/riscv/include/asm/probes.h b/arch/riscv/include/asm/probes.h > new file mode 100644 > index 000000000000..64cf12567539 > --- /dev/null > +++ b/arch/riscv/include/asm/probes.h > @@ -0,0 +1,26 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Based on arch/arm64/include/asm/probes.h > + * > + * Copyright (C) 2013 Linaro Limited > + */ > +#ifndef _RISCV_PROBES_H > +#define _RISCV_PROBES_H > + > +typedef u32 probe_opcode_t; > +typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *); > + > +/* architecture specific copy of original instruction */ > +struct arch_probe_insn { > + probes_handler_t *handler; > + /* restore address after simulation */ > + unsigned long restore; > +}; > +#ifdef CONFIG_KPROBES > +typedef u32 kprobe_opcode_t; > +struct arch_specific_insn { > + struct arch_probe_insn api; > +}; > +#endif Are there any reason of putting this kprobes dedicated data structure here? > + > +#endif /* _RISCV_PROBES_H */ > diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile > index f13f7f276639..5360a445b9d3 100644 > --- a/arch/riscv/kernel/Makefile > +++ b/arch/riscv/kernel/Makefile > @@ -28,6 +28,7 @@ obj-y += stacktrace.o > obj-y += vdso.o > obj-y += cacheinfo.o > obj-y += vdso/ > +obj-y += probes/ > > CFLAGS_setup.o := -mcmodel=medany > > diff --git a/arch/riscv/kernel/probes/Makefile b/arch/riscv/kernel/probes/Makefile > new file mode 100644 > index 000000000000..144d1c1743fb > --- /dev/null > +++ b/arch/riscv/kernel/probes/Makefile > @@ -0,0 +1,3 @@ > +# SPDX-License-Identifier: GPL-2.0 > +obj-$(CONFIG_KPROBES) += kprobes.o kprobes_trampoline.o \ > + decode-insn.o simulate-insn.o > diff --git a/arch/riscv/kernel/probes/decode-insn.c b/arch/riscv/kernel/probes/decode-insn.c > new file mode 100644 > index 000000000000..2d8f46f4c2e7 > --- /dev/null > +++ b/arch/riscv/kernel/probes/decode-insn.c > @@ -0,0 +1,38 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "decode-insn.h" > +#include "simulate-insn.h" > + > +#define C_ADDISP16_MASK 0x6F83 > +#define C_ADDISP16_VAL 0x6101 > + > +/* Return: > + * INSN_REJECTED If instruction is one not allowed to kprobe, > + * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. > + */ > +enum probe_insn __kprobes > +riscv_probe_decode_insn(kprobe_opcode_t *addr, struct arch_probe_insn *api) Please don't use __kprobes anymore. That is old stlye, instead, please use NOKPROBE_SYMBOL() or nokprobe_inline for static-inline function. (NOKPROBE_SYMBOL() will make the symbol non-inline always) > +{ > + probe_opcode_t insn = le32_to_cpu(*addr); > + > + if (!is_compressed_insn(insn)) { > + pr_warn("Can't handle non-compressed instruction %x\n", insn); > + return INSN_REJECTED; > + } > + > + /* c.addisp16 imm */ > + if ((insn & C_ADDISP16_MASK) == C_ADDISP16_VAL) { > + api->handler = simulate_caddisp16; > + } else { > + pr_warn("Rejected unknown instruction %x\n", insn); > + return INSN_REJECTED; > + } > + > + return INSN_GOOD_NO_SLOT; > +} > diff --git a/arch/riscv/kernel/probes/decode-insn.h b/arch/riscv/kernel/probes/decode-insn.h > new file mode 100644 > index 000000000000..0053ed6a308a > --- /dev/null > +++ b/arch/riscv/kernel/probes/decode-insn.h > @@ -0,0 +1,23 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +#ifndef _RISCV_KERNEL_KPROBES_DECODE_INSN_H > +#define _RISCV_KERNEL_KPROBES_DECODE_INSN_H > + > +#include > +#include > + > +enum probe_insn { > + INSN_REJECTED, > + INSN_GOOD_NO_SLOT, > +}; > + > +/* > + * Compressed instruction format: > + * xxxxxxxxxxxxxxaa where aa != 11 > + */ > +#define is_compressed_insn(insn) ((insn & 0x3) != 0x3) > + > +#ifdef CONFIG_KPROBES > +enum probe_insn __kprobes > +riscv_probe_decode_insn(kprobe_opcode_t *addr, struct arch_probe_insn *asi); > +#endif > +#endif /* _RISCV_KERNEL_KPROBES_DECODE_INSN_H */ > diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c > new file mode 100644 > index 000000000000..3c7b5cf72ee1 > --- /dev/null > +++ b/arch/riscv/kernel/probes/kprobes.c > @@ -0,0 +1,401 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +/* > + * Kprobes support for RISC-V > + * > + * Author: Patrick St?hlin > + */ > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "decode-insn.h" > + > +DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; > +DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); > + > +static void __kprobes > +post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *); > + > +static int __kprobes patch_text(kprobe_opcode_t *addr, u32 opcode) > +{ > + if (is_compressed_insn(opcode)) > + *(u16 *)addr = cpu_to_le16(opcode); > + else > + *addr = cpu_to_le32(opcode); > + > + return 0; > +} > + > +static void __kprobes arch_prepare_simulate(struct kprobe *p) > +{ > + unsigned long offset = is_compressed_insn(p->opcode) ? 2 : 4; > + > + p->ainsn.api.restore = (unsigned long)p->addr + offset; > +} > + > +static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) > +{ > + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); > + > + if (p->ainsn.api.handler) > + p->ainsn.api.handler((u32)p->opcode, (long)p->addr, regs); it seems api.handler must be here, > + > + /* single instruction simulated, now go for post processing */ > + post_kprobe_handler(kcb, regs); > +} > + > +int __kprobes arch_prepare_kprobe(struct kprobe *p) > +{ > + unsigned long probe_addr = (unsigned long)p->addr; > + extern char __start_rodata[]; > + extern char __end_rodata[]; > + > + if (probe_addr & 0x1) { > + pr_warn("Address not aligned.\n"); > + return -EINVAL; > + } > + > + /* copy instruction */ > + p->opcode = le32_to_cpu(*p->addr); > + > + if (probe_addr >= (unsigned long) __start_rodata && > + probe_addr <= (unsigned long) __end_rodata) { > + return -EINVAL; > + } > + > + /* decode instruction */ > + switch (riscv_probe_decode_insn(p->addr, &p->ainsn.api)) { > + case INSN_REJECTED: /* insn not supported */ > + return -EINVAL; > + > + case INSN_GOOD_NO_SLOT: /* insn needs simulation */ > + break; > + } > + > + arch_prepare_simulate(p); > + > + return 0; > +} > + > +#define C_EBREAK_OPCODE 0x9002 > + > +/* arm kprobe: install breakpoint in text */ > +void __kprobes arch_arm_kprobe(struct kprobe *p) > +{ > + patch_text(p->addr, C_EBREAK_OPCODE); > +} > + > +/* disarm kprobe: remove breakpoint from text */ > +void __kprobes arch_disarm_kprobe(struct kprobe *p) > +{ > + patch_text(p->addr, p->opcode); > +} > + > +void __kprobes arch_remove_kprobe(struct kprobe *p) > +{ > +} > + > +static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) > +{ > + kcb->prev_kprobe.kp = kprobe_running(); > + kcb->prev_kprobe.status = kcb->kprobe_status; > +} > + > +static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) > +{ > + __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); > + kcb->kprobe_status = kcb->prev_kprobe.status; > +} > + > +static void __kprobes set_current_kprobe(struct kprobe *p) > +{ > + __this_cpu_write(current_kprobe, p); > +} > + > +static void __kprobes simulate(struct kprobe *p, > + struct pt_regs *regs, > + struct kprobe_ctlblk *kcb, int reenter) > +{ > + if (reenter) { > + save_previous_kprobe(kcb); > + set_current_kprobe(p); > + kcb->kprobe_status = KPROBE_REENTER; > + } else { > + kcb->kprobe_status = KPROBE_HIT_SS; > + } > + > + arch_simulate_insn(p, regs); > +} > + > +static int __kprobes reenter_kprobe(struct kprobe *p, > + struct pt_regs *regs, > + struct kprobe_ctlblk *kcb) > +{ > + switch (kcb->kprobe_status) { > + case KPROBE_HIT_SSDONE: > + case KPROBE_HIT_ACTIVE: > + kprobes_inc_nmissed_count(p); > + simulate(p, regs, kcb, 1); > + break; > + case KPROBE_HIT_SS: > + case KPROBE_REENTER: > + pr_warn("Unrecoverable kprobe detected.\n"); > + dump_kprobe(p); > + BUG(); > + break; > + default: > + WARN_ON(1); > + return 0; > + } > + > + return 1; If this always return 1, we can make it void return. > +} > + > +static void __kprobes > +post_kprobe_handler(struct kprobe_ctlblk *kcb, struct pt_regs *regs) > +{ > + struct kprobe *cur = kprobe_running(); > + > + if (!cur) > + return; > + > + /* return addr restore if non-branching insn */ > + if (cur->ainsn.api.restore != 0) > + instruction_pointer_set(regs, cur->ainsn.api.restore); > + > + /* restore back original saved kprobe variables and continue */ > + if (kcb->kprobe_status == KPROBE_REENTER) { > + restore_previous_kprobe(kcb); > + return; > + } > + /* call post handler */ > + kcb->kprobe_status = KPROBE_HIT_SSDONE; > + if (cur->post_handler) { > + /* post_handler can hit breakpoint and single step > + * again, so we enable D-flag for recursive exception. > + */ > + cur->post_handler(cur, regs, 0); > + } > + > + reset_current_kprobe(); > +} > + > +int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int cause) > +{ > + struct kprobe *cur = kprobe_running(); > + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); > + > + switch (kcb->kprobe_status) { > + case KPROBE_HIT_SS: > + case KPROBE_REENTER: > + /* > + * We are here because the instruction being single > + * stepped caused a page fault. We reset the current > + * kprobe and the ip points back to the probe address > + * and allow the page fault handler to continue as a > + * normal page fault. > + */ > + instruction_pointer_set(regs, (unsigned long) cur->addr); > + if (!instruction_pointer(regs)) > + BUG(); Use BUG_ON(). > + > + if (kcb->kprobe_status == KPROBE_REENTER) > + restore_previous_kprobe(kcb); > + else > + reset_current_kprobe(); > + > + break; > + case KPROBE_HIT_ACTIVE: > + case KPROBE_HIT_SSDONE: > + /* > + * We increment the nmissed count for accounting, > + * we can also use npre/npostfault count for accounting > + * these specific fault cases. > + */ > + kprobes_inc_nmissed_count(cur); > + > + /* > + * We come here because instructions in the pre/post > + * handler caused the page_fault, this could happen > + * if handler tries to access user space by > + * copy_from_user(), get_user() etc. Let the > + * user-specified handler try to fix it first. > + */ > + if (cur->fault_handler && cur->fault_handler(cur, regs, cause)) > + return 1; > + > + /* > + * In case the user-specified fault handler returned > + * zero, try to fix up. > + */ > + if (fixup_exception(regs)) > + return 1; > + } > + return 0; > +} > + > +static void __kprobes kprobe_handler(struct pt_regs *regs) > +{ Does this handler run under local IRQ disabled? (for making sure) > + struct kprobe *p, *cur_kprobe; > + struct kprobe_ctlblk *kcb; > + unsigned long addr = instruction_pointer(regs); > + > + kcb = get_kprobe_ctlblk(); > + cur_kprobe = kprobe_running(); > + > + p = get_kprobe((kprobe_opcode_t *) addr); > + > + if (p) { > + if (cur_kprobe) { > + if (reenter_kprobe(p, regs, kcb)) > + return; > + } else { > + /* Probe hit */ > + set_current_kprobe(p); > + kcb->kprobe_status = KPROBE_HIT_ACTIVE; > + > + /* > + * If we have no pre-handler or it returned 0, we > + * continue with normal processing. If we have a > + * pre-handler and it returned non-zero, it will > + * modify the execution path and no need to single > + * stepping. Let's just reset current kprobe and exit. > + * > + * pre_handler can hit a breakpoint and can step thru > + * before return, keep PSTATE D-flag enabled until > + * pre_handler return back. Is this true on RISC-V too? > + */ > + if (!p->pre_handler || !p->pre_handler(p, regs)) > + simulate(p, regs, kcb, 0); > + else > + reset_current_kprobe(); > + } > + } > + /* > + * The breakpoint instruction was removed right > + * after we hit it. Another cpu has removed > + * either a probepoint or a debugger breakpoint > + * at this address. In either case, no further > + * handling of this interrupt is appropriate. > + * Return back to original instruction, and continue. > + */ This should return 0 if it doesn't handle anything, but if it handles c.break should return 1. > +} > + > +int __kprobes > +kprobe_breakpoint_handler(struct pt_regs *regs) > +{ > + kprobe_handler(regs); > + return 1; Why don't you call kprobe_handler directly? > +} > + > +bool arch_within_kprobe_blacklist(unsigned long addr) > +{ > + if ((addr >= (unsigned long)__kprobes_text_start && > + addr < (unsigned long)__kprobes_text_end) || > + (addr >= (unsigned long)__entry_text_start && > + addr < (unsigned long)__entry_text_end) || > + !!search_exception_tables(addr)) > + return true; > + > + return false; > +} > + > +void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs) > +{ > + struct kretprobe_instance *ri = NULL; > + struct hlist_head *head, empty_rp; > + struct hlist_node *tmp; > + unsigned long flags, orig_ret_address = 0; > + unsigned long trampoline_address = > + (unsigned long)&kretprobe_trampoline; > + kprobe_opcode_t *correct_ret_addr = NULL; > + It seems you don't setup instruction_pointer. > + INIT_HLIST_HEAD(&empty_rp); > + kretprobe_hash_lock(current, &head, &flags); > + > + /* > + * It is possible to have multiple instances associated with a given > + * task either because multiple functions in the call path have > + * return probes installed on them, and/or more than one > + * return probe was registered for a target function. > + * > + * We can handle this because: > + * - instances are always pushed into the head of the list > + * - when multiple return probes are registered for the same > + * function, the (chronologically) first instance's ret_addr > + * will be the real return address, and all the rest will > + * point to kretprobe_trampoline. > + */ > + hlist_for_each_entry_safe(ri, tmp, head, hlist) { > + if (ri->task != current) > + /* another task is sharing our hash bucket */ > + continue; > + > + orig_ret_address = (unsigned long)ri->ret_addr; > + > + if (orig_ret_address != trampoline_address) > + /* > + * This is the real return address. Any other > + * instances associated with this task are for > + * other calls deeper on the call stack > + */ > + break; > + } > + > + kretprobe_assert(ri, orig_ret_address, trampoline_address); > + > + correct_ret_addr = ri->ret_addr; > + hlist_for_each_entry_safe(ri, tmp, head, hlist) { > + if (ri->task != current) > + /* another task is sharing our hash bucket */ > + continue; > + > + orig_ret_address = (unsigned long)ri->ret_addr; > + if (ri->rp && ri->rp->handler) { > + __this_cpu_write(current_kprobe, &ri->rp->kp); > + get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; > + ri->ret_addr = correct_ret_addr; > + ri->rp->handler(ri, regs); > + __this_cpu_write(current_kprobe, NULL); > + } > + > + recycle_rp_inst(ri, &empty_rp); > + > + if (orig_ret_address != trampoline_address) > + /* > + * This is the real return address. Any other > + * instances associated with this task are for > + * other calls deeper on the call stack > + */ > + break; > + } > + > + kretprobe_hash_unlock(current, &flags); > + > + hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { > + hlist_del(&ri->hlist); > + kfree(ri); > + } > + return (void *)orig_ret_address; > +} > + > +void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, > + struct pt_regs *regs) > +{ > + ri->ret_addr = (kprobe_opcode_t *)regs->ra; > + regs->ra = (long)&kretprobe_trampoline; > +} > + > +int __kprobes arch_trampoline_kprobe(struct kprobe *p) > +{ > + return 0; > +} > + > +int __init arch_init_kprobes(void) > +{ > + return 0; > +} > diff --git a/arch/riscv/kernel/probes/kprobes_trampoline.S b/arch/riscv/kernel/probes/kprobes_trampoline.S > new file mode 100644 > index 000000000000..c7ceda9556a3 > --- /dev/null > +++ b/arch/riscv/kernel/probes/kprobes_trampoline.S > @@ -0,0 +1,91 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > + > +#include > + > +#include > +#include > + > + .text > + .altmacro > + > + .macro save_all_base_regs > + REG_S x1, PT_RA(sp) > + REG_S x3, PT_GP(sp) > + REG_S x4, PT_TP(sp) > + REG_S x5, PT_T0(sp) > + REG_S x6, PT_T1(sp) > + REG_S x7, PT_T2(sp) > + REG_S x8, PT_S0(sp) > + REG_S x9, PT_S1(sp) > + REG_S x10, PT_A0(sp) > + REG_S x11, PT_A1(sp) > + REG_S x12, PT_A2(sp) > + REG_S x13, PT_A3(sp) > + REG_S x14, PT_A4(sp) > + REG_S x15, PT_A5(sp) > + REG_S x16, PT_A6(sp) > + REG_S x17, PT_A7(sp) > + REG_S x18, PT_S2(sp) > + REG_S x19, PT_S3(sp) > + REG_S x20, PT_S4(sp) > + REG_S x21, PT_S5(sp) > + REG_S x22, PT_S6(sp) > + REG_S x23, PT_S7(sp) > + REG_S x24, PT_S8(sp) > + REG_S x25, PT_S9(sp) > + REG_S x26, PT_S10(sp) > + REG_S x27, PT_S11(sp) > + REG_S x28, PT_T3(sp) > + REG_S x29, PT_T4(sp) > + REG_S x30, PT_T5(sp) > + REG_S x31, PT_T6(sp) > + .endm > + > + .macro restore_all_base_regs > + REG_L x3, PT_GP(sp) > + REG_L x4, PT_TP(sp) > + REG_L x5, PT_T0(sp) > + REG_L x6, PT_T1(sp) > + REG_L x7, PT_T2(sp) > + REG_L x8, PT_S0(sp) > + REG_L x9, PT_S1(sp) > + REG_L x10, PT_A0(sp) > + REG_L x11, PT_A1(sp) > + REG_L x12, PT_A2(sp) > + REG_L x13, PT_A3(sp) > + REG_L x14, PT_A4(sp) > + REG_L x15, PT_A5(sp) > + REG_L x16, PT_A6(sp) > + REG_L x17, PT_A7(sp) > + REG_L x18, PT_S2(sp) > + REG_L x19, PT_S3(sp) > + REG_L x20, PT_S4(sp) > + REG_L x21, PT_S5(sp) > + REG_L x22, PT_S6(sp) > + REG_L x23, PT_S7(sp) > + REG_L x24, PT_S8(sp) > + REG_L x25, PT_S9(sp) > + REG_L x26, PT_S10(sp) > + REG_L x27, PT_S11(sp) > + REG_L x28, PT_T3(sp) > + REG_L x29, PT_T4(sp) > + REG_L x30, PT_T5(sp) > + REG_L x31, PT_T6(sp) > + .endm > + > +ENTRY(kretprobe_trampoline) > + addi sp, sp, -(PT_SIZE_ON_STACK) > + save_all_base_regs > + > + move a0, sp /* pt_regs */ > + > + call trampoline_probe_handler > + > + /* use the result as the return-address */ > + move ra, a0 > + > + restore_all_base_regs > + addi sp, sp, PT_SIZE_ON_STACK > + > + ret > +ENDPROC(kretprobe_trampoline) > diff --git a/arch/riscv/kernel/probes/simulate-insn.c b/arch/riscv/kernel/probes/simulate-insn.c > new file mode 100644 > index 000000000000..5734d9bae22f > --- /dev/null > +++ b/arch/riscv/kernel/probes/simulate-insn.c > @@ -0,0 +1,33 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +#include > +#include > +#include > + > +#include "simulate-insn.h" > + > +#define bit_at(value, bit) ((value) & (1 << (bit))) > +#define move_bit_at(value, bit, to) ((bit_at(value, bit) >> bit) << to) > + > +void __kprobes > +simulate_caddisp16(u32 opcode, long addr, struct pt_regs *regs) > +{ > + s16 imm; > + > + /* > + * Immediate value layout in c.addisp16: > + * xxx9 xxxx x468 75xx > + * 1 1 8 4 0 > + * 5 2 > + */ > + imm = sign_extend32( > + move_bit_at(opcode, 12, 9) | > + move_bit_at(opcode, 6, 4) | > + move_bit_at(opcode, 5, 6) | > + move_bit_at(opcode, 4, 8) | > + move_bit_at(opcode, 3, 7) | > + move_bit_at(opcode, 2, 5), > + 9); > + > + regs->sp += imm; What about updating regs->sepc? > +} > diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h > new file mode 100644 > index 000000000000..dc2c06c30167 > --- /dev/null > +++ b/arch/riscv/kernel/probes/simulate-insn.h > @@ -0,0 +1,8 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > + > +#ifndef _RISCV_KERNEL_KPROBES_SIMULATE_INSN_H > +#define _RISCV_KERNEL_KPROBES_SIMULATE_INSN_H > + > +void simulate_caddisp16(u32 opcode, long addr, struct pt_regs *regs); > + > +#endif /* _RISCV_KERNEL_KPROBES_SIMULATE_INSN_H */ > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c > index 24a9333dda2c..d7113178d401 100644 > --- a/arch/riscv/kernel/traps.c > +++ b/arch/riscv/kernel/traps.c > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -120,8 +121,14 @@ DO_ERROR_INFO(do_trap_ecall_m, > > asmlinkage void do_trap_break(struct pt_regs *regs) > { > + bool handler_found = false; > + > +#ifdef CONFIG_KPROBES > + if (kprobe_breakpoint_handler(regs)) > + handler_found = 1; Why don't you just return from here? > +#endif > #ifdef CONFIG_GENERIC_BUG > - if (!user_mode(regs)) { > + if (!handler_found && !user_mode(regs)) { > enum bug_trap_type type; > > type = report_bug(regs->sepc, regs); > @@ -137,7 +144,9 @@ asmlinkage void do_trap_break(struct pt_regs *regs) > } > #endif /* CONFIG_GENERIC_BUG */ > > - force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)(regs->sepc), current); > + if (!handler_found) > + force_sig_fault(SIGTRAP, TRAP_BRKPT, > + (void __user *)(regs->sepc), current); > } > > #ifdef CONFIG_GENERIC_BUG > diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c > index 88401d5125bc..eff816e33479 100644 > --- a/arch/riscv/mm/fault.c > +++ b/arch/riscv/mm/fault.c > @@ -22,6 +22,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -30,11 +31,33 @@ > #include > #include > > +#ifdef CONFIG_KPROBES > +static inline int notify_page_fault(struct pt_regs *regs, unsigned int cause) please use nokprobe_inline. > +{ > + int ret = 0; > + > + /* kprobe_running() needs smp_processor_id() */ > + if (!user_mode(regs)) { > + preempt_disable(); > + if (kprobe_running() && kprobe_fault_handler(regs, cause)) > + ret = 1; > + preempt_enable(); > + } > + > + return ret; > +} > +#else > +static inline int notify_page_fault(struct pt_regs *regs, unsigned int cause) > +{ > + return 0; > +} > +#endif > + > /* > * This routine handles page faults. It determines the address and the > * problem, and then passes it off to one of the appropriate routines. > */ > -asmlinkage void do_page_fault(struct pt_regs *regs) > +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs) > { > struct task_struct *tsk; > struct vm_area_struct *vma; > @@ -47,6 +70,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs) > cause = regs->scause; > addr = regs->sbadaddr; > > + if (notify_page_fault(regs, cause)) > + return; > + > tsk = current; > mm = tsk->mm; > > -- > 2.17.1 > Thank you, -- Masami Hiramatsu From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.5 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 803B7C43441 for ; Wed, 14 Nov 2018 08:38:11 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4EE4521582 for ; Wed, 14 Nov 2018 08:38:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="iixJKayk"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="awfJFokl"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="W3snnbKN" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4EE4521582 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-riscv-bounces+infradead-linux-riscv=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Mime-Version:References:In-Reply-To: Message-Id:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=LmYywQdVVVj91l+wmf/WvS+2Hpp1HUyX9tmpvUOuces=; b=iixJKayk8n3jha C3lLd1/jpTtN1Frs5xLpoacSgT3eNq4c233BXFQOK4JKmUcYQ5kaZclFaS85yxBc51SgmCwaiY7g0 F1OuWqEem8ml7v+mAGCUAvHPQlbp+TMaMj5DCDBBYHxzwtxDW5LSJeczRI5idvXNnQC1HV1Ht4Zeu 0wSLIoZZHd4a6tol6kSLEuZfpaWVRjBvZzXk98VBy4X2XuG3j6zfwuOZtIL43TfvjW9BbpElS2Iqw 8Hwq9dhvcKtBI5jgDGg1zDeiPtD1rUk4qZI+DleH1gBNrNm+mgecaH5frwo+Hgz37dU/OM5+bpvRF K0j9CFToNhxNH2arE5vw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gMqgI-0002Cw-J3; Wed, 14 Nov 2018 08:37:50 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gMqgF-0002Co-NQ for linux-riscv@bombadil.infradead.org; Wed, 14 Nov 2018 08:37:48 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Content-Transfer-Encoding:Content-Type: Mime-Version:References:In-Reply-To:Message-Id:Subject:Cc:To:From:Date:Sender :Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=X3faR3PfhxC14nY1sOjEtpxvftWRn47cpJ8qanVVDyY=; b=awfJFoklpIUTgM5CiT32NwUUAr y0RoZvTgw+uffOtmN1HXmXpFpRKnQR53KVvBHQd6nKvFYGCRzH5/CeVpTEW2YlYUXr89VpLtmST35 tqnKguFWl/xadPPoxI6R5Xdkf50uV6s6owF8KOIJuoPQAcxBjgCnZ0EXc8FU94Cl2H1ZMgPPrH8Y5 YjyGWytS1kYeWp3Og44QhzdRNd4Vvxy0zLHDpkXuc+pSt2RpWQU938byn8Hm0jFuh/EruT+OfUa5I B1ayWGc5vvPuevuBSozP1eipzm5Ir2Wqdo2+ahc9v+Y8NimjMakW7QT/IMqaJrwO6Sq3kk5pxxOLf OMxk0g2g==; Received: from mail.kernel.org ([198.145.29.99]) by merlin.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gMqgB-0003V1-L0 for linux-riscv@lists.infradead.org; Wed, 14 Nov 2018 08:37:45 +0000 Received: from devnote (unknown [64.114.255.114]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id BAAAD21582; Wed, 14 Nov 2018 08:37:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1542184651; bh=xpgvujKl6MsiOcDRJYvT+oTRDgORjQdH0lMp9QldhrU=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=W3snnbKNbkJstpNgnV7lParB+InGYUbHTpzvCDUkBhj33A3MybaslDBQzEYqeK5+B G8GZ6PZSZoAESpQgTSUP6UYrq1Y+5vblEHIGrYe/k8Z1EEIJhzP4UeMcUFb+bR8HL4 f3Lj6qJDz4DCOpadxMTO7coIWVHEXH8s7FpmmGcE= Date: Wed, 14 Nov 2018 00:37:30 -0800 From: Masami Hiramatsu To: Patrick =?UTF-8?B?U3TDpGhsaW4=?= Subject: Re: [RFC/RFT 2/2] RISC-V: kprobes/kretprobe support Message-Id: <20181114003730.06f810517a270070734df4ce@kernel.org> In-Reply-To: <20181113195804.22825-3-me@packi.ch> References: <20181113195804.22825-1-me@packi.ch> <20181113195804.22825-3-me@packi.ch> X-Mailer: Sylpheed 3.5.0 (GTK+ 2.24.30; x86_64-pc-linux-gnu) Mime-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181114_033743_821164_383B6FD2 X-CRM114-Status: GOOD ( 37.44 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Albert Ou , Anders Roxell , Andrew Morton , Alan Kao , Catalin Marinas , Palmer Dabbelt , Will Deacon , linux-kernel@vger.kernel.org, Al Viro , Souptick Joarder , Zong Li , Thomas Gleixner , Masami Hiramatsu , linux-riscv@lists.infradead.org, Jim Wilson , zhong jiang , Ingo Molnar , Luc Van Oostenryck , "Eric W. Biederman" Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-riscv" Errors-To: linux-riscv-bounces+infradead-linux-riscv=archiver.kernel.org@lists.infradead.org Message-ID: <20181114083730.IlEA5ppqHuex1G2hkLrV7pMWEsgTuSoQhXrpNHmrdaE@z> SGkgUGF0cmljaywKClRoYW5rIHlvdSB2ZXJ5IG11Y2ggZm9yIGltcGxlbWVudGluZyBrcHJvYmVz IG9uIFJJU0MtViA6KQoKT24gVHVlLCAxMyBOb3YgMjAxOCAyMDo1ODowNCArMDEwMApQYXRyaWNr IFN0w6RobGluIDxtZUBwYWNraS5jaD4gd3JvdGU6Cgo+IEZpcnN0IGltcGxlbWVudGF0aW9uLCBh ZGFwdGVkIGZyb20gYXJtNjQuIFRoZSBDLkFERElTUDE2IGluc3RydWN0aW9uCj4gZ2V0cyBzaW11 bGF0ZWQgYW5kIHRoZSBrcHJvYmVzLWhhbmRsZXIgY2FsbGVkIGJ5IGluc2VydGluZyBhIEMuRUJS RUFLCj4gaW5zdHJ1Y3Rpb24uCj4gCj4gQy5BRERJU1AxNiB3YXMgY2hvc2VuIGFzIGl0IHNldHMt dXAgdGhlIHN0YWNrIGZyYW1lIGZvciBmdW5jdGlvbnMuCj4gU29tZSB3b3JrIGhhcyBiZWVuIGRv bmUgdG8gc3VwcG9ydCBwcm9iZXMgb24gbm9uLWNvbXByZXNzZWQKPiBpbnN0cnVjdGlvbnMgYnV0 IHRoZXJlIGlzIG5vIHN1cHBvcnQgeWV0IGZvciBkZWNvZGluZyB0aG9zZS4KCkRvZXMgdGhpcyBv bmx5IHN1cHBvcnQgQy5BRERJU1AxNj8gTm8gb3RoZXIgaW5zbnMgYXJlIHN1cHBvcnRlZD8KU3Vw cG9ydGluZyAxIGluc24gaXMgdG9vIGZldyBJIHRoaW5rLgoKQ2FuIFJJU0MtViBkbyBzaW5nbGUg c3RlcHBpbmc/IElmIG5vdCwgd2UgbmVlZCB0byBwcmVwYXJlIGVtdWxhdG9yCmFzIG1hdGNoIGFz IHBvc3NpYmxlLCBvciBmb3IgQUxVIGluc3RydWN0aW9ucywgd2UgY2FuIHJ1biBpdCBvbgpidWZm ZXIgYW5kIGhvb2sgaXQuCgo+IFRoZSB3YXkgZm9yd2FyZCBzaG91bGQgYmUgdG8gdW5jb21wcmVz cyB0aGUgaW5zdHJ1Y3Rpb25zIGZvciBzaW11bGF0aW9uCj4gdG8gcmVkdWNlIHRoZSBudW1iZXIg b2YgaW5zdHJ1Y3Rpb25zIHVzZWQgdG8gZGVjb2RlICB0aGUgaW1tZWRpYXRlCj4gdmFsdWVzIG9u IHByb2JlIGhpdC4KCkkgaGF2ZSBzb21lIGNvbW1lbnRzIG9uIHRoZSBwYXRjaCwgcGxlYXNlIHJl dmlldy4KCj4gCj4gU2lnbmVkLW9mZi1ieTogUGF0cmljayBTdMOkaGxpbiA8bWVAcGFja2kuY2g+ Cj4gLS0tCj4gIGFyY2gvcmlzY3YvS2NvbmZpZyAgICAgICAgICAgICAgICAgICAgICAgICAgICB8 ICAgNSArLQo+ICBhcmNoL3Jpc2N2L2luY2x1ZGUvYXNtL2twcm9iZXMuaCAgICAgICAgICAgICAg fCAgMzAgKysKPiAgYXJjaC9yaXNjdi9pbmNsdWRlL2FzbS9wcm9iZXMuaCAgICAgICAgICAgICAg IHwgIDI2ICsrCj4gIGFyY2gvcmlzY3Yva2VybmVsL01ha2VmaWxlICAgICAgICAgICAgICAgICAg ICB8ICAgMSArCj4gIGFyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9NYWtlZmlsZSAgICAgICAgICAg ICB8ICAgMyArCj4gIGFyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9kZWNvZGUtaW5zbi5jICAgICAg ICB8ICAzOCArKwo+ICBhcmNoL3Jpc2N2L2tlcm5lbC9wcm9iZXMvZGVjb2RlLWluc24uaCAgICAg ICAgfCAgMjMgKwo+ICBhcmNoL3Jpc2N2L2tlcm5lbC9wcm9iZXMva3Byb2Jlcy5jICAgICAgICAg ICAgfCA0MDEgKysrKysrKysrKysrKysrKysrCj4gIGFyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9r cHJvYmVzX3RyYW1wb2xpbmUuUyB8ICA5MSArKysrCj4gIGFyY2gvcmlzY3Yva2VybmVsL3Byb2Jl cy9zaW11bGF0ZS1pbnNuLmMgICAgICB8ICAzMyArKwo+ICBhcmNoL3Jpc2N2L2tlcm5lbC9wcm9i ZXMvc2ltdWxhdGUtaW5zbi5oICAgICAgfCAgIDggKwo+ICBhcmNoL3Jpc2N2L2tlcm5lbC90cmFw cy5jICAgICAgICAgICAgICAgICAgICAgfCAgMTMgKy0KPiAgYXJjaC9yaXNjdi9tbS9mYXVsdC5j ICAgICAgICAgICAgICAgICAgICAgICAgIHwgIDI4ICstCj4gIDEzIGZpbGVzIGNoYW5nZWQsIDY5 NCBpbnNlcnRpb25zKCspLCA2IGRlbGV0aW9ucygtKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgYXJj aC9yaXNjdi9pbmNsdWRlL2FzbS9wcm9iZXMuaAo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgYXJjaC9y aXNjdi9rZXJuZWwvcHJvYmVzL01ha2VmaWxlCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBhcmNoL3Jp c2N2L2tlcm5lbC9wcm9iZXMvZGVjb2RlLWluc24uYwo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgYXJj aC9yaXNjdi9rZXJuZWwvcHJvYmVzL2RlY29kZS1pbnNuLmgKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0 IGFyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9rcHJvYmVzLmMKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0 IGFyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9rcHJvYmVzX3RyYW1wb2xpbmUuUwo+ICBjcmVhdGUg bW9kZSAxMDA2NDQgYXJjaC9yaXNjdi9rZXJuZWwvcHJvYmVzL3NpbXVsYXRlLWluc24uYwo+ICBj cmVhdGUgbW9kZSAxMDA2NDQgYXJjaC9yaXNjdi9rZXJuZWwvcHJvYmVzL3NpbXVsYXRlLWluc24u aAo+IAo+IGRpZmYgLS1naXQgYS9hcmNoL3Jpc2N2L0tjb25maWcgYi9hcmNoL3Jpc2N2L0tjb25m aWcKPiBpbmRleCBiMTU3YWM4MmQ0ODYuLjExZWY0MDMwZThmMiAxMDA2NDQKPiAtLS0gYS9hcmNo L3Jpc2N2L0tjb25maWcKPiArKysgYi9hcmNoL3Jpc2N2L0tjb25maWcKPiBAQCAtNDQsNiArNDQs OCBAQCBjb25maWcgUklTQ1YKPiAgCXNlbGVjdCBHRU5FUklDX0lSUV9NVUxUSV9IQU5ETEVSCj4g IAlzZWxlY3QgQVJDSF9IQVNfUFRFX1NQRUNJQUwKPiAgCXNlbGVjdCBIQVZFX1JFR1NfQU5EX1NU QUNLX0FDQ0VTU19BUEkKPiArCXNlbGVjdCBIQVZFX0tQUk9CRVMKPiArCXNlbGVjdCBIQVZFX0tS RVRQUk9CRVMKPiAgCj4gIGNvbmZpZyBNTVUKPiAgCWRlZl9ib29sIHkKPiBAQCAtODksOSArOTEs NiBAQCBjb25maWcgUEdUQUJMRV9MRVZFTFMKPiAgCWRlZmF1bHQgMyBpZiA2NEJJVAo+ICAJZGVm YXVsdCAyCj4gIAo+IC1jb25maWcgSEFWRV9LUFJPQkVTCj4gLQlkZWZfYm9vbCBuCj4gLQo+ICBt ZW51ICJQbGF0Zm9ybSB0eXBlIgo+ICAKPiAgY2hvaWNlCj4gZGlmZiAtLWdpdCBhL2FyY2gvcmlz Y3YvaW5jbHVkZS9hc20va3Byb2Jlcy5oIGIvYXJjaC9yaXNjdi9pbmNsdWRlL2FzbS9rcHJvYmVz LmgKPiBpbmRleCBjN2ViMDEwZDE1MjguLjY1N2FkY2QzNWEzZCAxMDA2NDQKPiAtLS0gYS9hcmNo L3Jpc2N2L2luY2x1ZGUvYXNtL2twcm9iZXMuaAo+ICsrKyBiL2FyY2gvcmlzY3YvaW5jbHVkZS9h c20va3Byb2Jlcy5oCj4gQEAgLTE5LDQgKzE5LDM0IEBACj4gIAo+ICAjaW5jbHVkZSA8YXNtLWdl bmVyaWMva3Byb2Jlcy5oPgo+ICAKPiArI2lmZGVmIENPTkZJR19LUFJPQkVTCj4gKyNpbmNsdWRl IDxsaW51eC90eXBlcy5oPgo+ICsjaW5jbHVkZSA8bGludXgvcHRyYWNlLmg+Cj4gKyNpbmNsdWRl IDxsaW51eC9wZXJjcHUuaD4KPiArCj4gKyNkZWZpbmUgZmx1c2hfaW5zbl9zbG90KHApCQlkbyB7 IH0gd2hpbGUgKDApCj4gKyNkZWZpbmUga3JldHByb2JlX2JsYWNrbGlzdF9zaXplCTAKPiArCj4g KyNpbmNsdWRlIDxhc20vcHJvYmVzLmg+Cj4gKwo+ICtzdHJ1Y3QgcHJldl9rcHJvYmUgewo+ICsJ c3RydWN0IGtwcm9iZSAqa3A7Cj4gKwl1bnNpZ25lZCBpbnQgc3RhdHVzOwo+ICt9Owo+ICsKPiAr LyogcGVyLWNwdSBrcHJvYmUgY29udHJvbCBibG9jayAqLwo+ICtzdHJ1Y3Qga3Byb2JlX2N0bGJs ayB7Cj4gKwl1bnNpZ25lZCBpbnQga3Byb2JlX3N0YXR1czsKPiArCXN0cnVjdCBwcmV2X2twcm9i ZSBwcmV2X2twcm9iZTsKPiArfTsKPiArCj4gK3ZvaWQgYXJjaF9yZW1vdmVfa3Byb2JlKHN0cnVj dCBrcHJvYmUgKnApOwo+ICtpbnQga3Byb2JlX2ZhdWx0X2hhbmRsZXIoc3RydWN0IHB0X3JlZ3Mg KnJlZ3MsIHVuc2lnbmVkIGludCBjYXVzZSk7Cj4gK2ludCBrcHJvYmVfZXhjZXB0aW9uc19ub3Rp Znkoc3RydWN0IG5vdGlmaWVyX2Jsb2NrICpzZWxmLAo+ICsJCQkgICAgIHVuc2lnbmVkIGxvbmcg dmFsLCB2b2lkICpkYXRhKTsKPiAraW50IGtwcm9iZV9icmVha3BvaW50X2hhbmRsZXIoc3RydWN0 IHB0X3JlZ3MgKnJlZ3MpOwo+ICt2b2lkIGtyZXRwcm9iZV90cmFtcG9saW5lKHZvaWQpOwo+ICt2 b2lkIF9fa3Byb2JlcyAqdHJhbXBvbGluZV9wcm9iZV9oYW5kbGVyKHN0cnVjdCBwdF9yZWdzICpy ZWdzKTsKPiArCj4gKyNlbmRpZiAvKiBDT05GSUdfS1BST0JFUyAqLwo+ICAjZW5kaWYgLyogX1JJ U0NWX0tQUk9CRVNfSCAqLwo+IGRpZmYgLS1naXQgYS9hcmNoL3Jpc2N2L2luY2x1ZGUvYXNtL3By b2Jlcy5oIGIvYXJjaC9yaXNjdi9pbmNsdWRlL2FzbS9wcm9iZXMuaAo+IG5ldyBmaWxlIG1vZGUg MTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi42NGNmMTI1Njc1MzkKPiAtLS0gL2Rldi9udWxs Cj4gKysrIGIvYXJjaC9yaXNjdi9pbmNsdWRlL2FzbS9wcm9iZXMuaAo+IEBAIC0wLDAgKzEsMjYg QEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgKi8KPiArLyoKPiArICog QmFzZWQgb24gYXJjaC9hcm02NC9pbmNsdWRlL2FzbS9wcm9iZXMuaAo+ICsgKgo+ICsgKiBDb3B5 cmlnaHQgKEMpIDIwMTMgTGluYXJvIExpbWl0ZWQKPiArICovCj4gKyNpZm5kZWYgX1JJU0NWX1BS T0JFU19ICj4gKyNkZWZpbmUgX1JJU0NWX1BST0JFU19ICj4gKwo+ICt0eXBlZGVmIHUzMiBwcm9i ZV9vcGNvZGVfdDsKPiArdHlwZWRlZiB2b2lkIChwcm9iZXNfaGFuZGxlcl90KSAodTMyIG9wY29k ZSwgbG9uZyBhZGRyLCBzdHJ1Y3QgcHRfcmVncyAqKTsKPiArCj4gKy8qIGFyY2hpdGVjdHVyZSBz cGVjaWZpYyBjb3B5IG9mIG9yaWdpbmFsIGluc3RydWN0aW9uICovCj4gK3N0cnVjdCBhcmNoX3By b2JlX2luc24gewo+ICsJcHJvYmVzX2hhbmRsZXJfdCAqaGFuZGxlcjsKPiArCS8qIHJlc3RvcmUg YWRkcmVzcyBhZnRlciBzaW11bGF0aW9uICovCj4gKwl1bnNpZ25lZCBsb25nIHJlc3RvcmU7Cj4g K307Cj4gKyNpZmRlZiBDT05GSUdfS1BST0JFUwo+ICt0eXBlZGVmIHUzMiBrcHJvYmVfb3Bjb2Rl X3Q7Cj4gK3N0cnVjdCBhcmNoX3NwZWNpZmljX2luc24gewo+ICsJc3RydWN0IGFyY2hfcHJvYmVf aW5zbiBhcGk7Cj4gK307Cj4gKyNlbmRpZgoKQXJlIHRoZXJlIGFueSByZWFzb24gb2YgcHV0dGlu ZyB0aGlzIGtwcm9iZXMgZGVkaWNhdGVkIGRhdGEgc3RydWN0dXJlIGhlcmU/Cgo+ICsKPiArI2Vu ZGlmIC8qIF9SSVNDVl9QUk9CRVNfSCAqLwo+IGRpZmYgLS1naXQgYS9hcmNoL3Jpc2N2L2tlcm5l bC9NYWtlZmlsZSBiL2FyY2gvcmlzY3Yva2VybmVsL01ha2VmaWxlCj4gaW5kZXggZjEzZjdmMjc2 NjM5Li41MzYwYTQ0NWI5ZDMgMTAwNjQ0Cj4gLS0tIGEvYXJjaC9yaXNjdi9rZXJuZWwvTWFrZWZp bGUKPiArKysgYi9hcmNoL3Jpc2N2L2tlcm5lbC9NYWtlZmlsZQo+IEBAIC0yOCw2ICsyOCw3IEBA IG9iai15CSs9IHN0YWNrdHJhY2Uubwo+ICBvYmoteQkrPSB2ZHNvLm8KPiAgb2JqLXkJKz0gY2Fj aGVpbmZvLm8KPiAgb2JqLXkJKz0gdmRzby8KPiArb2JqLXkJKz0gcHJvYmVzLwo+ICAKPiAgQ0ZM QUdTX3NldHVwLm8gOj0gLW1jbW9kZWw9bWVkYW55Cj4gIAo+IGRpZmYgLS1naXQgYS9hcmNoL3Jp c2N2L2tlcm5lbC9wcm9iZXMvTWFrZWZpbGUgYi9hcmNoL3Jpc2N2L2tlcm5lbC9wcm9iZXMvTWFr ZWZpbGUKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uMTQ0ZDFj MTc0M2ZiCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2FyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9N YWtlZmlsZQo+IEBAIC0wLDAgKzEsMyBAQAo+ICsjIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBH UEwtMi4wCj4gK29iai0kKENPTkZJR19LUFJPQkVTKQkJKz0ga3Byb2Jlcy5vIGtwcm9iZXNfdHJh bXBvbGluZS5vIFwKPiArCQkJCSAgIGRlY29kZS1pbnNuLm8gc2ltdWxhdGUtaW5zbi5vCj4gZGlm ZiAtLWdpdCBhL2FyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9kZWNvZGUtaW5zbi5jIGIvYXJjaC9y aXNjdi9rZXJuZWwvcHJvYmVzL2RlY29kZS1pbnNuLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+ IGluZGV4IDAwMDAwMDAwMDAwMC4uMmQ4ZjQ2ZjRjMmU3Cj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBi L2FyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9kZWNvZGUtaW5zbi5jCj4gQEAgLTAsMCArMSwzOCBA QAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCsKPiArCj4gKyNpbmNsdWRl IDxsaW51eC9rZXJuZWwuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2twcm9iZXMuaD4KPiArI2luY2x1 ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgva2FsbHN5bXMuaD4KPiArI2lu Y2x1ZGUgPGFzbS9zZWN0aW9ucy5oPgo+ICsKPiArI2luY2x1ZGUgImRlY29kZS1pbnNuLmgiCj4g KyNpbmNsdWRlICJzaW11bGF0ZS1pbnNuLmgiCj4gKwo+ICsjZGVmaW5lIENfQURESVNQMTZfTUFT SyAweDZGODMKPiArI2RlZmluZSBDX0FERElTUDE2X1ZBTCAgMHg2MTAxCj4gKwo+ICsvKiBSZXR1 cm46Cj4gKyAqICAgSU5TTl9SRUpFQ1RFRCAgICAgSWYgaW5zdHJ1Y3Rpb24gaXMgb25lIG5vdCBh bGxvd2VkIHRvIGtwcm9iZSwKPiArICogICBJTlNOX0dPT0RfTk9fU0xPVCBJZiBpbnN0cnVjdGlv biBpcyBzdXBwb3J0ZWQgYnV0IGRvZXNuJ3QgdXNlIGl0cyBzbG90Lgo+ICsgKi8KPiArZW51bSBw cm9iZV9pbnNuIF9fa3Byb2Jlcwo+ICtyaXNjdl9wcm9iZV9kZWNvZGVfaW5zbihrcHJvYmVfb3Bj b2RlX3QgKmFkZHIsIHN0cnVjdCBhcmNoX3Byb2JlX2luc24gKmFwaSkKClBsZWFzZSBkb24ndCB1 c2UgX19rcHJvYmVzIGFueW1vcmUuIFRoYXQgaXMgb2xkIHN0bHllLCBpbnN0ZWFkLCBwbGVhc2UK dXNlIE5PS1BST0JFX1NZTUJPTCgpIG9yIG5va3Byb2JlX2lubGluZSBmb3Igc3RhdGljLWlubGlu ZSBmdW5jdGlvbi4KKE5PS1BST0JFX1NZTUJPTCgpIHdpbGwgbWFrZSB0aGUgc3ltYm9sIG5vbi1p bmxpbmUgYWx3YXlzKQoKPiArewo+ICsJcHJvYmVfb3Bjb2RlX3QgaW5zbiA9IGxlMzJfdG9fY3B1 KCphZGRyKTsKPiArCj4gKwlpZiAoIWlzX2NvbXByZXNzZWRfaW5zbihpbnNuKSkgewo+ICsJCXBy X3dhcm4oIkNhbid0IGhhbmRsZSBub24tY29tcHJlc3NlZCBpbnN0cnVjdGlvbiAleFxuIiwgaW5z bik7Cj4gKwkJcmV0dXJuIElOU05fUkVKRUNURUQ7Cj4gKwl9Cj4gKwo+ICsJLyogYy5hZGRpc3Ax NiBpbW0gKi8KPiArCWlmICgoaW5zbiAmIENfQURESVNQMTZfTUFTSykgPT0gQ19BRERJU1AxNl9W QUwpIHsKPiArCQlhcGktPmhhbmRsZXIgPSBzaW11bGF0ZV9jYWRkaXNwMTY7Cj4gKwl9IGVsc2Ug ewo+ICsJCXByX3dhcm4oIlJlamVjdGVkIHVua25vd24gaW5zdHJ1Y3Rpb24gJXhcbiIsIGluc24p Owo+ICsJCXJldHVybiBJTlNOX1JFSkVDVEVEOwo+ICsJfQo+ICsKPiArCXJldHVybiBJTlNOX0dP T0RfTk9fU0xPVDsKPiArfQo+IGRpZmYgLS1naXQgYS9hcmNoL3Jpc2N2L2tlcm5lbC9wcm9iZXMv ZGVjb2RlLWluc24uaCBiL2FyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9kZWNvZGUtaW5zbi5oCj4g bmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLjAwNTNlZDZhMzA4YQo+ IC0tLSAvZGV2L251bGwKPiArKysgYi9hcmNoL3Jpc2N2L2tlcm5lbC9wcm9iZXMvZGVjb2RlLWlu c24uaAo+IEBAIC0wLDAgKzEsMjMgQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQ TC0yLjArICovCj4gKyNpZm5kZWYgX1JJU0NWX0tFUk5FTF9LUFJPQkVTX0RFQ09ERV9JTlNOX0gK PiArI2RlZmluZSBfUklTQ1ZfS0VSTkVMX0tQUk9CRVNfREVDT0RFX0lOU05fSAo+ICsKPiArI2lu Y2x1ZGUgPGFzbS9zZWN0aW9ucy5oPgo+ICsjaW5jbHVkZSA8YXNtL2twcm9iZXMuaD4KPiArCj4g K2VudW0gcHJvYmVfaW5zbiB7Cj4gKwlJTlNOX1JFSkVDVEVELAo+ICsJSU5TTl9HT09EX05PX1NM T1QsCj4gK307Cj4gKwo+ICsvKgo+ICsgKiBDb21wcmVzc2VkIGluc3RydWN0aW9uIGZvcm1hdDoK PiArICogeHh4eHh4eHh4eHh4eHhhYSB3aGVyZSBhYSAhPSAxMQo+ICsgKi8KPiArI2RlZmluZSBp c19jb21wcmVzc2VkX2luc24oaW5zbikgKChpbnNuICYgMHgzKSAhPSAweDMpCj4gKwo+ICsjaWZk ZWYgQ09ORklHX0tQUk9CRVMKPiArZW51bSBwcm9iZV9pbnNuIF9fa3Byb2Jlcwo+ICtyaXNjdl9w cm9iZV9kZWNvZGVfaW5zbihrcHJvYmVfb3Bjb2RlX3QgKmFkZHIsIHN0cnVjdCBhcmNoX3Byb2Jl X2luc24gKmFzaSk7Cj4gKyNlbmRpZgo+ICsjZW5kaWYgLyogX1JJU0NWX0tFUk5FTF9LUFJPQkVT X0RFQ09ERV9JTlNOX0ggKi8KPiBkaWZmIC0tZ2l0IGEvYXJjaC9yaXNjdi9rZXJuZWwvcHJvYmVz L2twcm9iZXMuYyBiL2FyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9rcHJvYmVzLmMKPiBuZXcgZmls ZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uM2M3YjVjZjcyZWUxCj4gLS0tIC9k ZXYvbnVsbAo+ICsrKyBiL2FyY2gvcmlzY3Yva2VybmVsL3Byb2Jlcy9rcHJvYmVzLmMKPiBAQCAt MCwwICsxLDQwMSBAQAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCsKPiAr Cj4gKy8qCj4gKyAqIEtwcm9iZXMgc3VwcG9ydCBmb3IgUklTQy1WCj4gKyAqCj4gKyAqIEF1dGhv cjogUGF0cmljayBTdMOkaGxpbiA8bWVAcGFja2kuY2g+Cj4gKyAqLwo+ICsjaW5jbHVkZSA8bGlu dXgva3Byb2Jlcy5oPgo+ICsjaW5jbHVkZSA8bGludXgvZXh0YWJsZS5oPgo+ICsjaW5jbHVkZSA8 bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8YXNtL3B0cmFjZS5oPgo+ICsjaW5jbHVkZSA8bGlu dXgvdWFjY2Vzcy5oPgo+ICsjaW5jbHVkZSA8YXNtL3NlY3Rpb25zLmg+Cj4gKwo+ICsjaW5jbHVk ZSAiZGVjb2RlLWluc24uaCIKPiArCj4gK0RFRklORV9QRVJfQ1BVKHN0cnVjdCBrcHJvYmUgKiwg Y3VycmVudF9rcHJvYmUpID0gTlVMTDsKPiArREVGSU5FX1BFUl9DUFUoc3RydWN0IGtwcm9iZV9j dGxibGssIGtwcm9iZV9jdGxibGspOwo+ICsKPiArc3RhdGljIHZvaWQgX19rcHJvYmVzCj4gK3Bv c3Rfa3Byb2JlX2hhbmRsZXIoc3RydWN0IGtwcm9iZV9jdGxibGsgKiwgc3RydWN0IHB0X3JlZ3Mg Kik7Cj4gKwo+ICtzdGF0aWMgaW50IF9fa3Byb2JlcyBwYXRjaF90ZXh0KGtwcm9iZV9vcGNvZGVf dCAqYWRkciwgdTMyIG9wY29kZSkKPiArewo+ICsJaWYgKGlzX2NvbXByZXNzZWRfaW5zbihvcGNv ZGUpKQo+ICsJCSoodTE2ICopYWRkciA9IGNwdV90b19sZTE2KG9wY29kZSk7Cj4gKwllbHNlCj4g KwkJKmFkZHIgPSBjcHVfdG9fbGUzMihvcGNvZGUpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgdm9pZCBfX2twcm9iZXMgYXJjaF9wcmVwYXJlX3NpbXVsYXRlKHN0cnVjdCBr cHJvYmUgKnApCj4gK3sKPiArCXVuc2lnbmVkIGxvbmcgb2Zmc2V0ID0gaXNfY29tcHJlc3NlZF9p bnNuKHAtPm9wY29kZSkgPyAyIDogNDsKPiArCj4gKwlwLT5haW5zbi5hcGkucmVzdG9yZSA9ICh1 bnNpZ25lZCBsb25nKXAtPmFkZHIgKyBvZmZzZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIF9f a3Byb2JlcyBhcmNoX3NpbXVsYXRlX2luc24oc3RydWN0IGtwcm9iZSAqcCwgc3RydWN0IHB0X3Jl Z3MgKnJlZ3MpCj4gK3sKPiArCXN0cnVjdCBrcHJvYmVfY3RsYmxrICprY2IgPSBnZXRfa3Byb2Jl X2N0bGJsaygpOwo+ICsKPiArCWlmIChwLT5haW5zbi5hcGkuaGFuZGxlcikKPiArCQlwLT5haW5z bi5hcGkuaGFuZGxlcigodTMyKXAtPm9wY29kZSwgKGxvbmcpcC0+YWRkciwgcmVncyk7CgppdCBz ZWVtcyBhcGkuaGFuZGxlciBtdXN0IGJlIGhlcmUsIAoKPiArCj4gKwkvKiBzaW5nbGUgaW5zdHJ1 Y3Rpb24gc2ltdWxhdGVkLCBub3cgZ28gZm9yIHBvc3QgcHJvY2Vzc2luZyAqLwo+ICsJcG9zdF9r cHJvYmVfaGFuZGxlcihrY2IsIHJlZ3MpOwo+ICt9Cj4gKwo+ICtpbnQgX19rcHJvYmVzIGFyY2hf cHJlcGFyZV9rcHJvYmUoc3RydWN0IGtwcm9iZSAqcCkKPiArewo+ICsJdW5zaWduZWQgbG9uZyBw cm9iZV9hZGRyID0gKHVuc2lnbmVkIGxvbmcpcC0+YWRkcjsKPiArCWV4dGVybiBjaGFyIF9fc3Rh cnRfcm9kYXRhW107Cj4gKwlleHRlcm4gY2hhciBfX2VuZF9yb2RhdGFbXTsKPiArCj4gKwlpZiAo cHJvYmVfYWRkciAmIDB4MSkgewo+ICsJCXByX3dhcm4oIkFkZHJlc3Mgbm90IGFsaWduZWQuXG4i KTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwkvKiBjb3B5IGluc3RydWN0aW9u ICovCj4gKwlwLT5vcGNvZGUgPSBsZTMyX3RvX2NwdSgqcC0+YWRkcik7Cj4gKwo+ICsJaWYgKHBy b2JlX2FkZHIgPj0gKHVuc2lnbmVkIGxvbmcpIF9fc3RhcnRfcm9kYXRhICYmCj4gKwkgICAgcHJv YmVfYWRkciA8PSAodW5zaWduZWQgbG9uZykgX19lbmRfcm9kYXRhKSB7Cj4gKwkJcmV0dXJuIC1F SU5WQUw7Cj4gKwl9Cj4gKwo+ICsJLyogZGVjb2RlIGluc3RydWN0aW9uICovCj4gKwlzd2l0Y2gg KHJpc2N2X3Byb2JlX2RlY29kZV9pbnNuKHAtPmFkZHIsICZwLT5haW5zbi5hcGkpKSB7Cj4gKwlj YXNlIElOU05fUkVKRUNURUQ6CS8qIGluc24gbm90IHN1cHBvcnRlZCAqLwo+ICsJCXJldHVybiAt RUlOVkFMOwo+ICsKPiArCWNhc2UgSU5TTl9HT09EX05PX1NMT1Q6CS8qIGluc24gbmVlZHMgc2lt dWxhdGlvbiAqLwo+ICsJCWJyZWFrOwo+ICsJfQo+ICsKPiArCWFyY2hfcHJlcGFyZV9zaW11bGF0 ZShwKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArI2RlZmluZSBDX0VCUkVBS19PUENP REUgMHg5MDAyCj4gKwo+ICsvKiBhcm0ga3Byb2JlOiBpbnN0YWxsIGJyZWFrcG9pbnQgaW4gdGV4 dCAqLwo+ICt2b2lkIF9fa3Byb2JlcyBhcmNoX2FybV9rcHJvYmUoc3RydWN0IGtwcm9iZSAqcCkK PiArewo+ICsJcGF0Y2hfdGV4dChwLT5hZGRyLCBDX0VCUkVBS19PUENPREUpOwo+ICt9Cj4gKwo+ ICsvKiBkaXNhcm0ga3Byb2JlOiByZW1vdmUgYnJlYWtwb2ludCBmcm9tIHRleHQgKi8KPiArdm9p ZCBfX2twcm9iZXMgYXJjaF9kaXNhcm1fa3Byb2JlKHN0cnVjdCBrcHJvYmUgKnApCj4gK3sKPiAr CXBhdGNoX3RleHQocC0+YWRkciwgcC0+b3Bjb2RlKTsKPiArfQo+ICsKPiArdm9pZCBfX2twcm9i ZXMgYXJjaF9yZW1vdmVfa3Byb2JlKHN0cnVjdCBrcHJvYmUgKnApCj4gK3sKPiArfQo+ICsKPiAr c3RhdGljIHZvaWQgX19rcHJvYmVzIHNhdmVfcHJldmlvdXNfa3Byb2JlKHN0cnVjdCBrcHJvYmVf Y3RsYmxrICprY2IpCj4gK3sKPiArCWtjYi0+cHJldl9rcHJvYmUua3AgPSBrcHJvYmVfcnVubmlu ZygpOwo+ICsJa2NiLT5wcmV2X2twcm9iZS5zdGF0dXMgPSBrY2ItPmtwcm9iZV9zdGF0dXM7Cj4g K30KPiArCj4gK3N0YXRpYyB2b2lkIF9fa3Byb2JlcyByZXN0b3JlX3ByZXZpb3VzX2twcm9iZShz dHJ1Y3Qga3Byb2JlX2N0bGJsayAqa2NiKQo+ICt7Cj4gKwlfX3RoaXNfY3B1X3dyaXRlKGN1cnJl bnRfa3Byb2JlLCBrY2ItPnByZXZfa3Byb2JlLmtwKTsKPiArCWtjYi0+a3Byb2JlX3N0YXR1cyA9 IGtjYi0+cHJldl9rcHJvYmUuc3RhdHVzOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBfX2twcm9i ZXMgc2V0X2N1cnJlbnRfa3Byb2JlKHN0cnVjdCBrcHJvYmUgKnApCj4gK3sKPiArCV9fdGhpc19j cHVfd3JpdGUoY3VycmVudF9rcHJvYmUsIHApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBfX2tw cm9iZXMgc2ltdWxhdGUoc3RydWN0IGtwcm9iZSAqcCwKPiArCQkJICAgICAgIHN0cnVjdCBwdF9y ZWdzICpyZWdzLAo+ICsJCQkgICAgICAgc3RydWN0IGtwcm9iZV9jdGxibGsgKmtjYiwgaW50IHJl ZW50ZXIpCj4gK3sKPiArCWlmIChyZWVudGVyKSB7Cj4gKwkJc2F2ZV9wcmV2aW91c19rcHJvYmUo a2NiKTsKPiArCQlzZXRfY3VycmVudF9rcHJvYmUocCk7Cj4gKwkJa2NiLT5rcHJvYmVfc3RhdHVz ID0gS1BST0JFX1JFRU5URVI7Cj4gKwl9IGVsc2Ugewo+ICsJCWtjYi0+a3Byb2JlX3N0YXR1cyA9 IEtQUk9CRV9ISVRfU1M7Cj4gKwl9Cj4gKwo+ICsJYXJjaF9zaW11bGF0ZV9pbnNuKHAsIHJlZ3Mp Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IF9fa3Byb2JlcyByZWVudGVyX2twcm9iZShzdHJ1Y3Qg a3Byb2JlICpwLAo+ICsJCQkJICAgIHN0cnVjdCBwdF9yZWdzICpyZWdzLAo+ICsJCQkJICAgIHN0 cnVjdCBrcHJvYmVfY3RsYmxrICprY2IpCj4gK3sKPiArCXN3aXRjaCAoa2NiLT5rcHJvYmVfc3Rh dHVzKSB7Cj4gKwljYXNlIEtQUk9CRV9ISVRfU1NET05FOgo+ICsJY2FzZSBLUFJPQkVfSElUX0FD VElWRToKPiArCQlrcHJvYmVzX2luY19ubWlzc2VkX2NvdW50KHApOwo+ICsJCXNpbXVsYXRlKHAs IHJlZ3MsIGtjYiwgMSk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIEtQUk9CRV9ISVRfU1M6Cj4gKwlj YXNlIEtQUk9CRV9SRUVOVEVSOgo+ICsJCXByX3dhcm4oIlVucmVjb3ZlcmFibGUga3Byb2JlIGRl dGVjdGVkLlxuIik7Cj4gKwkJZHVtcF9rcHJvYmUocCk7Cj4gKwkJQlVHKCk7Cj4gKwkJYnJlYWs7 Cj4gKwlkZWZhdWx0Ogo+ICsJCVdBUk5fT04oMSk7Cj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ ICsJcmV0dXJuIDE7CgpJZiB0aGlzIGFsd2F5cyByZXR1cm4gMSwgd2UgY2FuIG1ha2UgaXQgdm9p ZCByZXR1cm4uCgo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBfX2twcm9iZXMKPiArcG9zdF9rcHJv YmVfaGFuZGxlcihzdHJ1Y3Qga3Byb2JlX2N0bGJsayAqa2NiLCBzdHJ1Y3QgcHRfcmVncyAqcmVn cykKPiArewo+ICsJc3RydWN0IGtwcm9iZSAqY3VyID0ga3Byb2JlX3J1bm5pbmcoKTsKPiArCj4g KwlpZiAoIWN1cikKPiArCQlyZXR1cm47Cj4gKwo+ICsJLyogcmV0dXJuIGFkZHIgcmVzdG9yZSBp ZiBub24tYnJhbmNoaW5nIGluc24gKi8KPiArCWlmIChjdXItPmFpbnNuLmFwaS5yZXN0b3JlICE9 IDApCj4gKwkJaW5zdHJ1Y3Rpb25fcG9pbnRlcl9zZXQocmVncywgY3VyLT5haW5zbi5hcGkucmVz dG9yZSk7Cj4gKwo+ICsJLyogcmVzdG9yZSBiYWNrIG9yaWdpbmFsIHNhdmVkIGtwcm9iZSB2YXJp YWJsZXMgYW5kIGNvbnRpbnVlICovCj4gKwlpZiAoa2NiLT5rcHJvYmVfc3RhdHVzID09IEtQUk9C RV9SRUVOVEVSKSB7Cj4gKwkJcmVzdG9yZV9wcmV2aW91c19rcHJvYmUoa2NiKTsKPiArCQlyZXR1 cm47Cj4gKwl9Cj4gKwkvKiBjYWxsIHBvc3QgaGFuZGxlciAqLwo+ICsJa2NiLT5rcHJvYmVfc3Rh dHVzID0gS1BST0JFX0hJVF9TU0RPTkU7Cj4gKwlpZiAoY3VyLT5wb3N0X2hhbmRsZXIpCXsKPiAr CQkvKiBwb3N0X2hhbmRsZXIgY2FuIGhpdCBicmVha3BvaW50IGFuZCBzaW5nbGUgc3RlcAo+ICsJ CSAqIGFnYWluLCBzbyB3ZSBlbmFibGUgRC1mbGFnIGZvciByZWN1cnNpdmUgZXhjZXB0aW9uLgo+ ICsJCSAqLwo+ICsJCWN1ci0+cG9zdF9oYW5kbGVyKGN1ciwgcmVncywgMCk7Cj4gKwl9Cj4gKwo+ ICsJcmVzZXRfY3VycmVudF9rcHJvYmUoKTsKPiArfQo+ICsKPiAraW50IF9fa3Byb2JlcyBrcHJv YmVfZmF1bHRfaGFuZGxlcihzdHJ1Y3QgcHRfcmVncyAqcmVncywgdW5zaWduZWQgaW50IGNhdXNl KQo+ICt7Cj4gKwlzdHJ1Y3Qga3Byb2JlICpjdXIgPSBrcHJvYmVfcnVubmluZygpOwo+ICsJc3Ry dWN0IGtwcm9iZV9jdGxibGsgKmtjYiA9IGdldF9rcHJvYmVfY3RsYmxrKCk7Cj4gKwo+ICsJc3dp dGNoIChrY2ItPmtwcm9iZV9zdGF0dXMpIHsKPiArCWNhc2UgS1BST0JFX0hJVF9TUzoKPiArCWNh c2UgS1BST0JFX1JFRU5URVI6Cj4gKwkJLyoKPiArCQkgKiBXZSBhcmUgaGVyZSBiZWNhdXNlIHRo ZSBpbnN0cnVjdGlvbiBiZWluZyBzaW5nbGUKPiArCQkgKiBzdGVwcGVkIGNhdXNlZCBhIHBhZ2Ug ZmF1bHQuIFdlIHJlc2V0IHRoZSBjdXJyZW50Cj4gKwkJICoga3Byb2JlIGFuZCB0aGUgaXAgcG9p bnRzIGJhY2sgdG8gdGhlIHByb2JlIGFkZHJlc3MKPiArCQkgKiBhbmQgYWxsb3cgdGhlIHBhZ2Ug ZmF1bHQgaGFuZGxlciB0byBjb250aW51ZSBhcyBhCj4gKwkJICogbm9ybWFsIHBhZ2UgZmF1bHQu Cj4gKwkJICovCj4gKwkJaW5zdHJ1Y3Rpb25fcG9pbnRlcl9zZXQocmVncywgKHVuc2lnbmVkIGxv bmcpIGN1ci0+YWRkcik7Cj4gKwkJaWYgKCFpbnN0cnVjdGlvbl9wb2ludGVyKHJlZ3MpKQo+ICsJ CQlCVUcoKTsKClVzZSBCVUdfT04oKS4KCj4gKwo+ICsJCWlmIChrY2ItPmtwcm9iZV9zdGF0dXMg PT0gS1BST0JFX1JFRU5URVIpCj4gKwkJCXJlc3RvcmVfcHJldmlvdXNfa3Byb2JlKGtjYik7Cj4g KwkJZWxzZQo+ICsJCQlyZXNldF9jdXJyZW50X2twcm9iZSgpOwo+ICsKPiArCQlicmVhazsKPiAr CWNhc2UgS1BST0JFX0hJVF9BQ1RJVkU6Cj4gKwljYXNlIEtQUk9CRV9ISVRfU1NET05FOgo+ICsJ CS8qCj4gKwkJICogV2UgaW5jcmVtZW50IHRoZSBubWlzc2VkIGNvdW50IGZvciBhY2NvdW50aW5n LAo+ICsJCSAqIHdlIGNhbiBhbHNvIHVzZSBucHJlL25wb3N0ZmF1bHQgY291bnQgZm9yIGFjY291 bnRpbmcKPiArCQkgKiB0aGVzZSBzcGVjaWZpYyBmYXVsdCBjYXNlcy4KPiArCQkgKi8KPiArCQlr cHJvYmVzX2luY19ubWlzc2VkX2NvdW50KGN1cik7Cj4gKwo+ICsJCS8qCj4gKwkJICogV2UgY29t ZSBoZXJlIGJlY2F1c2UgaW5zdHJ1Y3Rpb25zIGluIHRoZSBwcmUvcG9zdAo+ICsJCSAqIGhhbmRs ZXIgY2F1c2VkIHRoZSBwYWdlX2ZhdWx0LCB0aGlzIGNvdWxkIGhhcHBlbgo+ICsJCSAqIGlmIGhh bmRsZXIgdHJpZXMgdG8gYWNjZXNzIHVzZXIgc3BhY2UgYnkKPiArCQkgKiBjb3B5X2Zyb21fdXNl cigpLCBnZXRfdXNlcigpIGV0Yy4gTGV0IHRoZQo+ICsJCSAqIHVzZXItc3BlY2lmaWVkIGhhbmRs ZXIgdHJ5IHRvIGZpeCBpdCBmaXJzdC4KPiArCQkgKi8KPiArCQlpZiAoY3VyLT5mYXVsdF9oYW5k bGVyICYmIGN1ci0+ZmF1bHRfaGFuZGxlcihjdXIsIHJlZ3MsIGNhdXNlKSkKPiArCQkJcmV0dXJu IDE7Cj4gKwo+ICsJCS8qCj4gKwkJICogSW4gY2FzZSB0aGUgdXNlci1zcGVjaWZpZWQgZmF1bHQg aGFuZGxlciByZXR1cm5lZAo+ICsJCSAqIHplcm8sIHRyeSB0byBmaXggdXAuCj4gKwkJICovCj4g KwkJaWYgKGZpeHVwX2V4Y2VwdGlvbihyZWdzKSkKPiArCQkJcmV0dXJuIDE7Cj4gKwl9Cj4gKwly ZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgX19rcHJvYmVzIGtwcm9iZV9oYW5kbGVy KHN0cnVjdCBwdF9yZWdzICpyZWdzKQo+ICt7CgpEb2VzIHRoaXMgaGFuZGxlciBydW4gdW5kZXIg bG9jYWwgSVJRIGRpc2FibGVkPyAoZm9yIG1ha2luZyBzdXJlKQoKPiArCXN0cnVjdCBrcHJvYmUg KnAsICpjdXJfa3Byb2JlOwo+ICsJc3RydWN0IGtwcm9iZV9jdGxibGsgKmtjYjsKPiArCXVuc2ln bmVkIGxvbmcgYWRkciA9IGluc3RydWN0aW9uX3BvaW50ZXIocmVncyk7Cj4gKwo+ICsJa2NiID0g Z2V0X2twcm9iZV9jdGxibGsoKTsKPiArCWN1cl9rcHJvYmUgPSBrcHJvYmVfcnVubmluZygpOwo+ ICsKPiArCXAgPSBnZXRfa3Byb2JlKChrcHJvYmVfb3Bjb2RlX3QgKikgYWRkcik7Cj4gKwo+ICsJ aWYgKHApIHsKPiArCQlpZiAoY3VyX2twcm9iZSkgewo+ICsJCQlpZiAocmVlbnRlcl9rcHJvYmUo cCwgcmVncywga2NiKSkKPiArCQkJCXJldHVybjsKPiArCQl9IGVsc2Ugewo+ICsJCQkvKiBQcm9i ZSBoaXQgKi8KPiArCQkJc2V0X2N1cnJlbnRfa3Byb2JlKHApOwo+ICsJCQlrY2ItPmtwcm9iZV9z dGF0dXMgPSBLUFJPQkVfSElUX0FDVElWRTsKPiArCj4gKwkJCS8qCj4gKwkJCSAqIElmIHdlIGhh dmUgbm8gcHJlLWhhbmRsZXIgb3IgaXQgcmV0dXJuZWQgMCwgd2UKPiArCQkJICogY29udGludWUg d2l0aCBub3JtYWwgcHJvY2Vzc2luZy4gIElmIHdlIGhhdmUgYQo+ICsJCQkgKiBwcmUtaGFuZGxl ciBhbmQgaXQgcmV0dXJuZWQgbm9uLXplcm8sIGl0IHdpbGwKPiArCQkJICogbW9kaWZ5IHRoZSBl eGVjdXRpb24gcGF0aCBhbmQgbm8gbmVlZCB0byBzaW5nbGUKPiArCQkJICogc3RlcHBpbmcuIExl dCdzIGp1c3QgcmVzZXQgY3VycmVudCBrcHJvYmUgYW5kIGV4aXQuCj4gKwkJCSAqCj4gKwkJCSAq IHByZV9oYW5kbGVyIGNhbiBoaXQgYSBicmVha3BvaW50IGFuZCBjYW4gc3RlcCB0aHJ1Cj4gKwkJ CSAqIGJlZm9yZSByZXR1cm4sIGtlZXAgUFNUQVRFIEQtZmxhZyBlbmFibGVkIHVudGlsCj4gKwkJ CSAqIHByZV9oYW5kbGVyIHJldHVybiBiYWNrLgoKSXMgdGhpcyB0cnVlIG9uIFJJU0MtViB0b28/ Cgo+ICsJCQkgKi8KPiArCQkJaWYgKCFwLT5wcmVfaGFuZGxlciB8fCAhcC0+cHJlX2hhbmRsZXIo cCwgcmVncykpCj4gKwkJCQlzaW11bGF0ZShwLCByZWdzLCBrY2IsIDApOwo+ICsJCQllbHNlCj4g KwkJCQlyZXNldF9jdXJyZW50X2twcm9iZSgpOwo+ICsJCX0KPiArCX0KPiArCS8qCj4gKwkgKiBU aGUgYnJlYWtwb2ludCBpbnN0cnVjdGlvbiB3YXMgcmVtb3ZlZCByaWdodAo+ICsJICogYWZ0ZXIg d2UgaGl0IGl0LiAgQW5vdGhlciBjcHUgaGFzIHJlbW92ZWQKPiArCSAqIGVpdGhlciBhIHByb2Jl cG9pbnQgb3IgYSBkZWJ1Z2dlciBicmVha3BvaW50Cj4gKwkgKiBhdCB0aGlzIGFkZHJlc3MuICBJ biBlaXRoZXIgY2FzZSwgbm8gZnVydGhlcgo+ICsJICogaGFuZGxpbmcgb2YgdGhpcyBpbnRlcnJ1 cHQgaXMgYXBwcm9wcmlhdGUuCj4gKwkgKiBSZXR1cm4gYmFjayB0byBvcmlnaW5hbCBpbnN0cnVj dGlvbiwgYW5kIGNvbnRpbnVlLgo+ICsJICovCgpUaGlzIHNob3VsZCByZXR1cm4gMCBpZiBpdCBk b2Vzbid0IGhhbmRsZSBhbnl0aGluZywgYnV0IGlmIGl0IGhhbmRsZXMgYy5icmVhawpzaG91bGQg cmV0dXJuIDEuCgo+ICt9Cj4gKwo+ICtpbnQgX19rcHJvYmVzCj4gK2twcm9iZV9icmVha3BvaW50 X2hhbmRsZXIoc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCj4gK3sKPiArCWtwcm9iZV9oYW5kbGVyKHJl Z3MpOwo+ICsJcmV0dXJuIDE7CgpXaHkgZG9uJ3QgeW91IGNhbGwga3Byb2JlX2hhbmRsZXIgZGly ZWN0bHk/Cgo+ICt9Cj4gKwo+ICtib29sIGFyY2hfd2l0aGluX2twcm9iZV9ibGFja2xpc3QodW5z aWduZWQgbG9uZyBhZGRyKQo+ICt7Cj4gKwlpZiAoKGFkZHIgPj0gKHVuc2lnbmVkIGxvbmcpX19r cHJvYmVzX3RleHRfc3RhcnQgJiYKPiArCSAgICBhZGRyIDwgKHVuc2lnbmVkIGxvbmcpX19rcHJv YmVzX3RleHRfZW5kKSB8fAo+ICsJICAgIChhZGRyID49ICh1bnNpZ25lZCBsb25nKV9fZW50cnlf dGV4dF9zdGFydCAmJgo+ICsJICAgIGFkZHIgPCAodW5zaWduZWQgbG9uZylfX2VudHJ5X3RleHRf ZW5kKSB8fAo+ICsJICAgICEhc2VhcmNoX2V4Y2VwdGlvbl90YWJsZXMoYWRkcikpCj4gKwkJcmV0 dXJuIHRydWU7Cj4gKwo+ICsJcmV0dXJuIGZhbHNlOwo+ICt9Cj4gKwo+ICt2b2lkIF9fa3Byb2Jl cyBfX3VzZWQgKnRyYW1wb2xpbmVfcHJvYmVfaGFuZGxlcihzdHJ1Y3QgcHRfcmVncyAqcmVncykK PiArewo+ICsJc3RydWN0IGtyZXRwcm9iZV9pbnN0YW5jZSAqcmkgPSBOVUxMOwo+ICsJc3RydWN0 IGhsaXN0X2hlYWQgKmhlYWQsIGVtcHR5X3JwOwo+ICsJc3RydWN0IGhsaXN0X25vZGUgKnRtcDsK PiArCXVuc2lnbmVkIGxvbmcgZmxhZ3MsIG9yaWdfcmV0X2FkZHJlc3MgPSAwOwo+ICsJdW5zaWdu ZWQgbG9uZyB0cmFtcG9saW5lX2FkZHJlc3MgPQo+ICsJCSh1bnNpZ25lZCBsb25nKSZrcmV0cHJv YmVfdHJhbXBvbGluZTsKPiArCWtwcm9iZV9vcGNvZGVfdCAqY29ycmVjdF9yZXRfYWRkciA9IE5V TEw7Cj4gKwoKCUl0IHNlZW1zIHlvdSBkb24ndCBzZXR1cCBpbnN0cnVjdGlvbl9wb2ludGVyLgoK PiArCUlOSVRfSExJU1RfSEVBRCgmZW1wdHlfcnApOwo+ICsJa3JldHByb2JlX2hhc2hfbG9jayhj dXJyZW50LCAmaGVhZCwgJmZsYWdzKTsKPiArCj4gKwkvKgo+ICsJICogSXQgaXMgcG9zc2libGUg dG8gaGF2ZSBtdWx0aXBsZSBpbnN0YW5jZXMgYXNzb2NpYXRlZCB3aXRoIGEgZ2l2ZW4KPiArCSAq IHRhc2sgZWl0aGVyIGJlY2F1c2UgbXVsdGlwbGUgZnVuY3Rpb25zIGluIHRoZSBjYWxsIHBhdGgg aGF2ZQo+ICsJICogcmV0dXJuIHByb2JlcyBpbnN0YWxsZWQgb24gdGhlbSwgYW5kL29yIG1vcmUg dGhhbiBvbmUKPiArCSAqIHJldHVybiBwcm9iZSB3YXMgcmVnaXN0ZXJlZCBmb3IgYSB0YXJnZXQg ZnVuY3Rpb24uCj4gKwkgKgo+ICsJICogV2UgY2FuIGhhbmRsZSB0aGlzIGJlY2F1c2U6Cj4gKwkg KiAgICAgLSBpbnN0YW5jZXMgYXJlIGFsd2F5cyBwdXNoZWQgaW50byB0aGUgaGVhZCBvZiB0aGUg bGlzdAo+ICsJICogICAgIC0gd2hlbiBtdWx0aXBsZSByZXR1cm4gcHJvYmVzIGFyZSByZWdpc3Rl cmVkIGZvciB0aGUgc2FtZQo+ICsJICoJIGZ1bmN0aW9uLCB0aGUgKGNocm9ub2xvZ2ljYWxseSkg Zmlyc3QgaW5zdGFuY2UncyByZXRfYWRkcgo+ICsJICoJIHdpbGwgYmUgdGhlIHJlYWwgcmV0dXJu IGFkZHJlc3MsIGFuZCBhbGwgdGhlIHJlc3Qgd2lsbAo+ICsJICoJIHBvaW50IHRvIGtyZXRwcm9i ZV90cmFtcG9saW5lLgo+ICsJICovCj4gKwlobGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKHJpLCB0 bXAsIGhlYWQsIGhsaXN0KSB7Cj4gKwkJaWYgKHJpLT50YXNrICE9IGN1cnJlbnQpCj4gKwkJCS8q IGFub3RoZXIgdGFzayBpcyBzaGFyaW5nIG91ciBoYXNoIGJ1Y2tldCAqLwo+ICsJCQljb250aW51 ZTsKPiArCj4gKwkJb3JpZ19yZXRfYWRkcmVzcyA9ICh1bnNpZ25lZCBsb25nKXJpLT5yZXRfYWRk cjsKPiArCj4gKwkJaWYgKG9yaWdfcmV0X2FkZHJlc3MgIT0gdHJhbXBvbGluZV9hZGRyZXNzKQo+ ICsJCQkvKgo+ICsJCQkgKiBUaGlzIGlzIHRoZSByZWFsIHJldHVybiBhZGRyZXNzLiBBbnkgb3Ro ZXIKPiArCQkJICogaW5zdGFuY2VzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRhc2sgYXJlIGZvcgo+ ICsJCQkgKiBvdGhlciBjYWxscyBkZWVwZXIgb24gdGhlIGNhbGwgc3RhY2sKPiArCQkJICovCj4g KwkJCWJyZWFrOwo+ICsJfQo+ICsKPiArCWtyZXRwcm9iZV9hc3NlcnQocmksIG9yaWdfcmV0X2Fk ZHJlc3MsIHRyYW1wb2xpbmVfYWRkcmVzcyk7Cj4gKwo+ICsJY29ycmVjdF9yZXRfYWRkciA9IHJp LT5yZXRfYWRkcjsKPiArCWhsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUocmksIHRtcCwgaGVhZCwg aGxpc3QpIHsKPiArCQlpZiAocmktPnRhc2sgIT0gY3VycmVudCkKPiArCQkJLyogYW5vdGhlciB0 YXNrIGlzIHNoYXJpbmcgb3VyIGhhc2ggYnVja2V0ICovCj4gKwkJCWNvbnRpbnVlOwo+ICsKPiAr CQlvcmlnX3JldF9hZGRyZXNzID0gKHVuc2lnbmVkIGxvbmcpcmktPnJldF9hZGRyOwo+ICsJCWlm IChyaS0+cnAgJiYgcmktPnJwLT5oYW5kbGVyKSB7Cj4gKwkJCV9fdGhpc19jcHVfd3JpdGUoY3Vy cmVudF9rcHJvYmUsICZyaS0+cnAtPmtwKTsKPiArCQkJZ2V0X2twcm9iZV9jdGxibGsoKS0+a3By b2JlX3N0YXR1cyA9IEtQUk9CRV9ISVRfQUNUSVZFOwo+ICsJCQlyaS0+cmV0X2FkZHIgPSBjb3Jy ZWN0X3JldF9hZGRyOwo+ICsJCQlyaS0+cnAtPmhhbmRsZXIocmksIHJlZ3MpOwo+ICsJCQlfX3Ro aXNfY3B1X3dyaXRlKGN1cnJlbnRfa3Byb2JlLCBOVUxMKTsKPiArCQl9Cj4gKwo+ICsJCXJlY3lj bGVfcnBfaW5zdChyaSwgJmVtcHR5X3JwKTsKPiArCj4gKwkJaWYgKG9yaWdfcmV0X2FkZHJlc3Mg IT0gdHJhbXBvbGluZV9hZGRyZXNzKQo+ICsJCQkvKgo+ICsJCQkgKiBUaGlzIGlzIHRoZSByZWFs IHJldHVybiBhZGRyZXNzLiBBbnkgb3RoZXIKPiArCQkJICogaW5zdGFuY2VzIGFzc29jaWF0ZWQg d2l0aCB0aGlzIHRhc2sgYXJlIGZvcgo+ICsJCQkgKiBvdGhlciBjYWxscyBkZWVwZXIgb24gdGhl IGNhbGwgc3RhY2sKPiArCQkJICovCj4gKwkJCWJyZWFrOwo+ICsJfQo+ICsKPiArCWtyZXRwcm9i ZV9oYXNoX3VubG9jayhjdXJyZW50LCAmZmxhZ3MpOwo+ICsKPiArCWhsaXN0X2Zvcl9lYWNoX2Vu dHJ5X3NhZmUocmksIHRtcCwgJmVtcHR5X3JwLCBobGlzdCkgewo+ICsJCWhsaXN0X2RlbCgmcmkt PmhsaXN0KTsKPiArCQlrZnJlZShyaSk7Cj4gKwl9Cj4gKwlyZXR1cm4gKHZvaWQgKilvcmlnX3Jl dF9hZGRyZXNzOwo+ICt9Cj4gKwo+ICt2b2lkIF9fa3Byb2JlcyBhcmNoX3ByZXBhcmVfa3JldHBy b2JlKHN0cnVjdCBrcmV0cHJvYmVfaW5zdGFuY2UgKnJpLAo+ICsJCQkJICAgICAgc3RydWN0IHB0 X3JlZ3MgKnJlZ3MpCj4gK3sKPiArCXJpLT5yZXRfYWRkciA9IChrcHJvYmVfb3Bjb2RlX3QgKily ZWdzLT5yYTsKPiArCXJlZ3MtPnJhID0gKGxvbmcpJmtyZXRwcm9iZV90cmFtcG9saW5lOwo+ICt9 Cj4gKwo+ICtpbnQgX19rcHJvYmVzIGFyY2hfdHJhbXBvbGluZV9rcHJvYmUoc3RydWN0IGtwcm9i ZSAqcCkKPiArewo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK2ludCBfX2luaXQgYXJjaF9pbml0 X2twcm9iZXModm9pZCkKPiArewo+ICsJcmV0dXJuIDA7Cj4gK30KPiBkaWZmIC0tZ2l0IGEvYXJj aC9yaXNjdi9rZXJuZWwvcHJvYmVzL2twcm9iZXNfdHJhbXBvbGluZS5TIGIvYXJjaC9yaXNjdi9r ZXJuZWwvcHJvYmVzL2twcm9iZXNfdHJhbXBvbGluZS5TCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQK PiBpbmRleCAwMDAwMDAwMDAwMDAuLmM3Y2VkYTk1NTZhMwo+IC0tLSAvZGV2L251bGwKPiArKysg Yi9hcmNoL3Jpc2N2L2tlcm5lbC9wcm9iZXMva3Byb2Jlc190cmFtcG9saW5lLlMKPiBAQCAtMCww ICsxLDkxIEBACj4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wKyAqLwo+ICsK PiArI2luY2x1ZGUgPGxpbnV4L2xpbmthZ2UuaD4KPiArCj4gKyNpbmNsdWRlIDxhc20vYXNtLmg+ Cj4gKyNpbmNsdWRlIDxhc20vYXNtLW9mZnNldHMuaD4KPiArCj4gKwkudGV4dAo+ICsJLmFsdG1h Y3JvCj4gKwo+ICsJLm1hY3JvIHNhdmVfYWxsX2Jhc2VfcmVncwo+ICsJUkVHX1MgeDEsICBQVF9S QShzcCkKPiArCVJFR19TIHgzLCAgUFRfR1Aoc3ApCj4gKwlSRUdfUyB4NCwgIFBUX1RQKHNwKQo+ ICsJUkVHX1MgeDUsICBQVF9UMChzcCkKPiArCVJFR19TIHg2LCAgUFRfVDEoc3ApCj4gKwlSRUdf UyB4NywgIFBUX1QyKHNwKQo+ICsJUkVHX1MgeDgsICBQVF9TMChzcCkKPiArCVJFR19TIHg5LCAg UFRfUzEoc3ApCj4gKwlSRUdfUyB4MTAsIFBUX0EwKHNwKQo+ICsJUkVHX1MgeDExLCBQVF9BMShz cCkKPiArCVJFR19TIHgxMiwgUFRfQTIoc3ApCj4gKwlSRUdfUyB4MTMsIFBUX0EzKHNwKQo+ICsJ UkVHX1MgeDE0LCBQVF9BNChzcCkKPiArCVJFR19TIHgxNSwgUFRfQTUoc3ApCj4gKwlSRUdfUyB4 MTYsIFBUX0E2KHNwKQo+ICsJUkVHX1MgeDE3LCBQVF9BNyhzcCkKPiArCVJFR19TIHgxOCwgUFRf UzIoc3ApCj4gKwlSRUdfUyB4MTksIFBUX1MzKHNwKQo+ICsJUkVHX1MgeDIwLCBQVF9TNChzcCkK PiArCVJFR19TIHgyMSwgUFRfUzUoc3ApCj4gKwlSRUdfUyB4MjIsIFBUX1M2KHNwKQo+ICsJUkVH X1MgeDIzLCBQVF9TNyhzcCkKPiArCVJFR19TIHgyNCwgUFRfUzgoc3ApCj4gKwlSRUdfUyB4MjUs IFBUX1M5KHNwKQo+ICsJUkVHX1MgeDI2LCBQVF9TMTAoc3ApCj4gKwlSRUdfUyB4MjcsIFBUX1Mx MShzcCkKPiArCVJFR19TIHgyOCwgUFRfVDMoc3ApCj4gKwlSRUdfUyB4MjksIFBUX1Q0KHNwKQo+ ICsJUkVHX1MgeDMwLCBQVF9UNShzcCkKPiArCVJFR19TIHgzMSwgUFRfVDYoc3ApCj4gKwkuZW5k bQo+ICsKPiArCS5tYWNybyByZXN0b3JlX2FsbF9iYXNlX3JlZ3MKPiArCVJFR19MIHgzLCAgUFRf R1Aoc3ApCj4gKwlSRUdfTCB4NCwgIFBUX1RQKHNwKQo+ICsJUkVHX0wgeDUsICBQVF9UMChzcCkK PiArCVJFR19MIHg2LCAgUFRfVDEoc3ApCj4gKwlSRUdfTCB4NywgIFBUX1QyKHNwKQo+ICsJUkVH X0wgeDgsICBQVF9TMChzcCkKPiArCVJFR19MIHg5LCAgUFRfUzEoc3ApCj4gKwlSRUdfTCB4MTAs IFBUX0EwKHNwKQo+ICsJUkVHX0wgeDExLCBQVF9BMShzcCkKPiArCVJFR19MIHgxMiwgUFRfQTIo c3ApCj4gKwlSRUdfTCB4MTMsIFBUX0EzKHNwKQo+ICsJUkVHX0wgeDE0LCBQVF9BNChzcCkKPiAr CVJFR19MIHgxNSwgUFRfQTUoc3ApCj4gKwlSRUdfTCB4MTYsIFBUX0E2KHNwKQo+ICsJUkVHX0wg eDE3LCBQVF9BNyhzcCkKPiArCVJFR19MIHgxOCwgUFRfUzIoc3ApCj4gKwlSRUdfTCB4MTksIFBU X1MzKHNwKQo+ICsJUkVHX0wgeDIwLCBQVF9TNChzcCkKPiArCVJFR19MIHgyMSwgUFRfUzUoc3Ap Cj4gKwlSRUdfTCB4MjIsIFBUX1M2KHNwKQo+ICsJUkVHX0wgeDIzLCBQVF9TNyhzcCkKPiArCVJF R19MIHgyNCwgUFRfUzgoc3ApCj4gKwlSRUdfTCB4MjUsIFBUX1M5KHNwKQo+ICsJUkVHX0wgeDI2 LCBQVF9TMTAoc3ApCj4gKwlSRUdfTCB4MjcsIFBUX1MxMShzcCkKPiArCVJFR19MIHgyOCwgUFRf VDMoc3ApCj4gKwlSRUdfTCB4MjksIFBUX1Q0KHNwKQo+ICsJUkVHX0wgeDMwLCBQVF9UNShzcCkK PiArCVJFR19MIHgzMSwgUFRfVDYoc3ApCj4gKwkuZW5kbQo+ICsKPiArRU5UUlkoa3JldHByb2Jl X3RyYW1wb2xpbmUpCj4gKwlhZGRpIHNwLCBzcCwgLShQVF9TSVpFX09OX1NUQUNLKQo+ICsJc2F2 ZV9hbGxfYmFzZV9yZWdzCj4gKwo+ICsJbW92ZSBhMCwgc3AgLyogcHRfcmVncyAqLwo+ICsKPiAr CWNhbGwgdHJhbXBvbGluZV9wcm9iZV9oYW5kbGVyCj4gKwo+ICsJLyogdXNlIHRoZSByZXN1bHQg YXMgdGhlIHJldHVybi1hZGRyZXNzICovCj4gKwltb3ZlIHJhLCBhMAo+ICsKPiArCXJlc3RvcmVf YWxsX2Jhc2VfcmVncwo+ICsJYWRkaSBzcCwgc3AsIFBUX1NJWkVfT05fU1RBQ0sKPiArCj4gKwly ZXQKPiArRU5EUFJPQyhrcmV0cHJvYmVfdHJhbXBvbGluZSkKPiBkaWZmIC0tZ2l0IGEvYXJjaC9y aXNjdi9rZXJuZWwvcHJvYmVzL3NpbXVsYXRlLWluc24uYyBiL2FyY2gvcmlzY3Yva2VybmVsL3By b2Jlcy9zaW11bGF0ZS1pbnNuLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAw MDAwMDAwMC4uNTczNGQ5YmFlMjJmCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2FyY2gvcmlzY3Yv a2VybmVsL3Byb2Jlcy9zaW11bGF0ZS1pbnNuLmMKPiBAQCAtMCwwICsxLDMzIEBACj4gKy8vIFNQ RFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wKwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2Jp dG9wcy5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9r cHJvYmVzLmg+Cj4gKwo+ICsjaW5jbHVkZSAic2ltdWxhdGUtaW5zbi5oIgo+ICsKPiArI2RlZmlu ZSBiaXRfYXQodmFsdWUsIGJpdCkJCSgodmFsdWUpICYgKDEgPDwgKGJpdCkpKQo+ICsjZGVmaW5l IG1vdmVfYml0X2F0KHZhbHVlLCBiaXQsIHRvKQkoKGJpdF9hdCh2YWx1ZSwgYml0KSA+PiBiaXQp IDw8IHRvKQo+ICsKPiArdm9pZCBfX2twcm9iZXMKPiArc2ltdWxhdGVfY2FkZGlzcDE2KHUzMiBv cGNvZGUsIGxvbmcgYWRkciwgc3RydWN0IHB0X3JlZ3MgKnJlZ3MpCj4gK3sKPiArCXMxNiBpbW07 Cj4gKwo+ICsJLyoKPiArCSAqIEltbWVkaWF0ZSB2YWx1ZSBsYXlvdXQgaW4gYy5hZGRpc3AxNjoK PiArCSAqIHh4eDkgeHh4eCB4NDY4IDc1eHgKPiArCSAqIDEgIDEgICAgOCAgICA0ICAgIDAKPiAr CSAqIDUgIDIKPiArCSAqLwo+ICsJaW1tID0gc2lnbl9leHRlbmQzMigKPiArCQltb3ZlX2JpdF9h dChvcGNvZGUsIDEyLCA5KSB8Cj4gKwkJbW92ZV9iaXRfYXQob3Bjb2RlLCA2LCA0KSB8Cj4gKwkJ bW92ZV9iaXRfYXQob3Bjb2RlLCA1LCA2KSB8Cj4gKwkJbW92ZV9iaXRfYXQob3Bjb2RlLCA0LCA4 KSB8Cj4gKwkJbW92ZV9iaXRfYXQob3Bjb2RlLCAzLCA3KSB8Cj4gKwkJbW92ZV9iaXRfYXQob3Bj b2RlLCAyLCA1KSwKPiArCQk5KTsKPiArCj4gKwlyZWdzLT5zcCArPSBpbW07CgpXaGF0IGFib3V0 IHVwZGF0aW5nIHJlZ3MtPnNlcGM/Cgo+ICt9Cj4gZGlmZiAtLWdpdCBhL2FyY2gvcmlzY3Yva2Vy bmVsL3Byb2Jlcy9zaW11bGF0ZS1pbnNuLmggYi9hcmNoL3Jpc2N2L2tlcm5lbC9wcm9iZXMvc2lt dWxhdGUtaW5zbi5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAu LmRjMmMwNmMzMDE2Nwo+IC0tLSAvZGV2L251bGwKPiArKysgYi9hcmNoL3Jpc2N2L2tlcm5lbC9w cm9iZXMvc2ltdWxhdGUtaW5zbi5oCj4gQEAgLTAsMCArMSw4IEBACj4gKy8qIFNQRFgtTGljZW5z ZS1JZGVudGlmaWVyOiBHUEwtMi4wKyAqLwo+ICsKPiArI2lmbmRlZiBfUklTQ1ZfS0VSTkVMX0tQ Uk9CRVNfU0lNVUxBVEVfSU5TTl9ICj4gKyNkZWZpbmUgX1JJU0NWX0tFUk5FTF9LUFJPQkVTX1NJ TVVMQVRFX0lOU05fSAo+ICsKPiArdm9pZCBzaW11bGF0ZV9jYWRkaXNwMTYodTMyIG9wY29kZSwg bG9uZyBhZGRyLCBzdHJ1Y3QgcHRfcmVncyAqcmVncyk7Cj4gKwo+ICsjZW5kaWYgLyogX1JJU0NW X0tFUk5FTF9LUFJPQkVTX1NJTVVMQVRFX0lOU05fSCAqLwo+IGRpZmYgLS1naXQgYS9hcmNoL3Jp c2N2L2tlcm5lbC90cmFwcy5jIGIvYXJjaC9yaXNjdi9rZXJuZWwvdHJhcHMuYwo+IGluZGV4IDI0 YTkzMzNkZGEyYy4uZDcxMTMxNzhkNDAxIDEwMDY0NAo+IC0tLSBhL2FyY2gvcmlzY3Yva2VybmVs L3RyYXBzLmMKPiArKysgYi9hcmNoL3Jpc2N2L2tlcm5lbC90cmFwcy5jCj4gQEAgLTE4LDYgKzE4 LDcgQEAKPiAgI2luY2x1ZGUgPGxpbnV4L3NjaGVkL3NpZ25hbC5oPgo+ICAjaW5jbHVkZSA8bGlu dXgvc2lnbmFsLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9rZGVidWcuaD4KPiArI2luY2x1ZGUgPGxp bnV4L2twcm9iZXMuaD4KPiAgI2luY2x1ZGUgPGxpbnV4L3VhY2Nlc3MuaD4KPiAgI2luY2x1ZGUg PGxpbnV4L21tLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPiBAQCAtMTIwLDggKzEy MSwxNCBAQCBET19FUlJPUl9JTkZPKGRvX3RyYXBfZWNhbGxfbSwKPiAgCj4gIGFzbWxpbmthZ2Ug dm9pZCBkb190cmFwX2JyZWFrKHN0cnVjdCBwdF9yZWdzICpyZWdzKQo+ICB7Cj4gKwlib29sIGhh bmRsZXJfZm91bmQgPSBmYWxzZTsKPiArCj4gKyNpZmRlZiBDT05GSUdfS1BST0JFUwo+ICsJaWYg KGtwcm9iZV9icmVha3BvaW50X2hhbmRsZXIocmVncykpCj4gKwkJaGFuZGxlcl9mb3VuZCA9IDE7 CgpXaHkgZG9uJ3QgeW91IGp1c3QgcmV0dXJuIGZyb20gaGVyZT8KCj4gKyNlbmRpZgo+ICAjaWZk ZWYgQ09ORklHX0dFTkVSSUNfQlVHCj4gLQlpZiAoIXVzZXJfbW9kZShyZWdzKSkgewo+ICsJaWYg KCFoYW5kbGVyX2ZvdW5kICYmICF1c2VyX21vZGUocmVncykpIHsKPiAgCQllbnVtIGJ1Z190cmFw X3R5cGUgdHlwZTsKPiAgCj4gIAkJdHlwZSA9IHJlcG9ydF9idWcocmVncy0+c2VwYywgcmVncyk7 Cj4gQEAgLTEzNyw3ICsxNDQsOSBAQCBhc21saW5rYWdlIHZvaWQgZG9fdHJhcF9icmVhayhzdHJ1 Y3QgcHRfcmVncyAqcmVncykKPiAgCX0KPiAgI2VuZGlmIC8qIENPTkZJR19HRU5FUklDX0JVRyAq Lwo+ICAKPiAtCWZvcmNlX3NpZ19mYXVsdChTSUdUUkFQLCBUUkFQX0JSS1BULCAodm9pZCBfX3Vz ZXIgKikocmVncy0+c2VwYyksIGN1cnJlbnQpOwo+ICsJaWYgKCFoYW5kbGVyX2ZvdW5kKQo+ICsJ CWZvcmNlX3NpZ19mYXVsdChTSUdUUkFQLCBUUkFQX0JSS1BULAo+ICsJCQkodm9pZCBfX3VzZXIg KikocmVncy0+c2VwYyksIGN1cnJlbnQpOwo+ICB9Cj4gIAo+ICAjaWZkZWYgQ09ORklHX0dFTkVS SUNfQlVHCj4gZGlmZiAtLWdpdCBhL2FyY2gvcmlzY3YvbW0vZmF1bHQuYyBiL2FyY2gvcmlzY3Yv bW0vZmF1bHQuYwo+IGluZGV4IDg4NDAxZDUxMjViYy4uZWZmODE2ZTMzNDc5IDEwMDY0NAo+IC0t LSBhL2FyY2gvcmlzY3YvbW0vZmF1bHQuYwo+ICsrKyBiL2FyY2gvcmlzY3YvbW0vZmF1bHQuYwo+ IEBAIC0yMiw2ICsyMiw3IEBACj4gIAo+ICAjaW5jbHVkZSA8bGludXgvbW0uaD4KPiAgI2luY2x1 ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgva3Byb2Jlcy5oPgo+ICAjaW5j bHVkZSA8bGludXgvaW50ZXJydXB0Lmg+Cj4gICNpbmNsdWRlIDxsaW51eC9wZXJmX2V2ZW50Lmg+ Cj4gICNpbmNsdWRlIDxsaW51eC9zaWduYWwuaD4KPiBAQCAtMzAsMTEgKzMxLDMzIEBACj4gICNp bmNsdWRlIDxhc20vcGdhbGxvYy5oPgo+ICAjaW5jbHVkZSA8YXNtL3B0cmFjZS5oPgo+ICAKPiAr I2lmZGVmIENPTkZJR19LUFJPQkVTCj4gK3N0YXRpYyBpbmxpbmUgaW50IG5vdGlmeV9wYWdlX2Zh dWx0KHN0cnVjdCBwdF9yZWdzICpyZWdzLCB1bnNpZ25lZCBpbnQgY2F1c2UpCgpwbGVhc2UgdXNl IG5va3Byb2JlX2lubGluZS4KCj4gK3sKPiArCWludCByZXQgPSAwOwo+ICsKPiArCS8qIGtwcm9i ZV9ydW5uaW5nKCkgbmVlZHMgc21wX3Byb2Nlc3Nvcl9pZCgpICovCj4gKwlpZiAoIXVzZXJfbW9k ZShyZWdzKSkgewo+ICsJCXByZWVtcHRfZGlzYWJsZSgpOwo+ICsJCWlmIChrcHJvYmVfcnVubmlu ZygpICYmIGtwcm9iZV9mYXVsdF9oYW5kbGVyKHJlZ3MsIGNhdXNlKSkKPiArCQkJcmV0ID0gMTsK PiArCQlwcmVlbXB0X2VuYWJsZSgpOwo+ICsJfQo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiAr I2Vsc2UKPiArc3RhdGljIGlubGluZSBpbnQgbm90aWZ5X3BhZ2VfZmF1bHQoc3RydWN0IHB0X3Jl Z3MgKnJlZ3MsIHVuc2lnbmVkIGludCBjYXVzZSkKPiArewo+ICsJcmV0dXJuIDA7Cj4gK30KPiAr I2VuZGlmCj4gKwo+ICAvKgo+ICAgKiBUaGlzIHJvdXRpbmUgaGFuZGxlcyBwYWdlIGZhdWx0cy4g IEl0IGRldGVybWluZXMgdGhlIGFkZHJlc3MgYW5kIHRoZQo+ICAgKiBwcm9ibGVtLCBhbmQgdGhl biBwYXNzZXMgaXQgb2ZmIHRvIG9uZSBvZiB0aGUgYXBwcm9wcmlhdGUgcm91dGluZXMuCj4gICAq Lwo+IC1hc21saW5rYWdlIHZvaWQgZG9fcGFnZV9mYXVsdChzdHJ1Y3QgcHRfcmVncyAqcmVncykK PiArYXNtbGlua2FnZSB2b2lkIF9fa3Byb2JlcyBkb19wYWdlX2ZhdWx0KHN0cnVjdCBwdF9yZWdz ICpyZWdzKQo+ICB7Cj4gIAlzdHJ1Y3QgdGFza19zdHJ1Y3QgKnRzazsKPiAgCXN0cnVjdCB2bV9h cmVhX3N0cnVjdCAqdm1hOwo+IEBAIC00Nyw2ICs3MCw5IEBAIGFzbWxpbmthZ2Ugdm9pZCBkb19w YWdlX2ZhdWx0KHN0cnVjdCBwdF9yZWdzICpyZWdzKQo+ICAJY2F1c2UgPSByZWdzLT5zY2F1c2U7 Cj4gIAlhZGRyID0gcmVncy0+c2JhZGFkZHI7Cj4gIAo+ICsJaWYgKG5vdGlmeV9wYWdlX2ZhdWx0 KHJlZ3MsIGNhdXNlKSkKPiArCQlyZXR1cm47Cj4gKwo+ICAJdHNrID0gY3VycmVudDsKPiAgCW1t ID0gdHNrLT5tbTsKPiAgCj4gLS0gCj4gMi4xNy4xCj4gCgpUaGFuayB5b3UsCgotLSAKTWFzYW1p IEhpcmFtYXRzdSA8bWhpcmFtYXRAa2VybmVsLm9yZz4KCl9fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LXJpc2N2IG1haWxpbmcgbGlzdApsaW51eC1y aXNjdkBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxt YW4vbGlzdGluZm8vbGludXgtcmlzY3YK