Re: [PATCH v3 09/19] unwind: Introduce sframe user space unwinding
Steven Rostedt <[email protected]>
| Newsgroups | org.kernel.vger.linux-toolchains,org.kernel.vger.linux-kernel,org.kernel.vger.linux-perf-users |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 13 Nov 2024 13:15:35 -0800 Josh Poimboeuf <[email protected]> wrote: > On Wed, Nov 13, 2024 at 03:50:40PM -0500, Steven Rostedt wrote: > > On Thu, 7 Nov 2024 17:59:08 +0100 > > Jens Remus <[email protected]> wrote: > > > > > On 28.10.2024 22:47, Josh Poimboeuf wrote: > > > ... > > > > diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c > > > ... > > > > +static int find_fde(struct sframe_section *sec, unsigned long ip, > > > > + struct sframe_fde *fde) > > > > +{ > > > > + struct sframe_fde __user *first, *last, *found = NULL; > > > > + u32 ip_off, func_off_low = 0, func_off_high = -1; > > > > + > > > > + ip_off = ip - sec->sframe_addr; > > > > + > > > > + first = (void __user *)sec->fdes_addr; > > > > + last = first + sec->fdes_nr; > > > > > > Could it be that this needs to be: > > > > > > last = first + sec->fdes_nr - 1; > > > > Yep, I discovered the same issue. > > Indeed, thanks. > BTW, the following changes were needed to make it work for me: -- Steve diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 434c548f0837..64cc3c1188ca 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -842,7 +842,8 @@ static int load_elf_binary(struct linux_binprm *bprm) int first_pt_load = 1; unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; - struct elf_phdr *elf_property_phdata = NULL, *sframe_phdr = NULL; + struct elf_phdr *elf_property_phdata = NULL; + unsigned long sframe_vaddr = 0; unsigned long elf_brk; int retval, i; unsigned long elf_entry; @@ -951,7 +952,7 @@ static int load_elf_binary(struct linux_binprm *bprm) break; case PT_GNU_SFRAME: - sframe_phdr = elf_ppnt; + sframe_vaddr = elf_ppnt->p_vaddr; break; case PT_LOPROC ... PT_HIPROC: @@ -1344,8 +1345,8 @@ static int load_elf_binary(struct linux_binprm *bprm) task_pid_nr(current), retval); } - if (sframe_phdr) - sframe_add_section(load_bias + sframe_phdr->p_vaddr, + if (sframe_vaddr) + sframe_add_section(load_bias + sframe_vaddr, start_code, end_code); regs = current_pt_regs(); diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c index 933e47696e29..ca4ef0b72772 100644 --- a/kernel/unwind/sframe.c +++ b/kernel/unwind/sframe.c @@ -73,15 +73,15 @@ static int find_fde(struct sframe_section *sec, unsigned long ip, struct sframe_fde *fde) { struct sframe_fde __user *first, *last, *found = NULL; - u32 ip_off, func_off_low = 0, func_off_high = -1; + s32 ip_off, func_off_low = INT_MIN, func_off_high = INT_MAX; ip_off = ip - sec->sframe_addr; first = (void __user *)sec->fdes_addr; - last = first + sec->fdes_nr; + last = first + sec->fdes_nr - 1; while (first <= last) { struct sframe_fde __user *mid; - u32 func_off; + s32 func_off; mid = first + ((last - first) / 2); diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 11aadfade005..d9cd820150c5 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -97,7 +97,7 @@ int unwind_user_start(struct unwind_user_state *state) if (current_has_sframe()) state->type = UNWIND_USER_TYPE_SFRAME; - else if (IS_ENABLED(CONFIG_UNWIND_USER_FP)) + else if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) state->type = UNWIND_USER_TYPE_FP; else state->type = UNWIND_USER_TYPE_NONE; @@ -138,7 +138,7 @@ int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries) static u64 ctx_to_cookie(u64 cpu, u64 ctx) { BUILD_BUG_ON(NR_CPUS > 65535); - return (ctx & ((1UL << 48) - 1)) | cpu; + return (ctx & ((1UL << 48) - 1)) | (cpu << 48); } /*