Cy Schubert writes:
> In message <202507021341.562dfueh023...@gitrepo.freebsd.org>, Mark Johnston 
> wri
> tes:
> > The branch main has been updated by markj:
> >
> > URL: https://cgit.FreeBSD.org/src/commit/?id=aefae931820fe1e93a318552968510
> 29
> > 8c7941a0
> >
> > commit aefae931820fe1e93a318552968510298c7941a0
> > Author:     Mark Johnston <ma...@freebsd.org>
> > AuthorDate: 2025-07-02 13:34:47 +0000
> > Commit:     Mark Johnston <ma...@freebsd.org>
> > CommitDate: 2025-07-02 13:34:47 +0000
> >
> >     linker: Improve handling of ifuncs when fetching symbol metadata
> >     
> >     When looking up symbol values, we map ifunc symbols to the value
> >     returned by the resolver.  However, the returned symbol size is still
> >     that of the resolver.  Be consistent and provide the size of the
> >     implementation symbol as well.
> >     
> >     This fixes an inconsistency in dtrace's FBT provider, which enumerates
> >     all function symbols and disassembles their values, using the symbol
> >     size as the bound for the disassembly loop.  In particular, for ifuncs,
> >     we were not creating return probes.
> >     
> >     Reviewed by:    kib
> >     MFC after:      2 weeks
> >     Sponsored by:   Innovate UK
> >     Differential Revision:  https://reviews.freebsd.org/D50683
> > ---
> >  sys/kern/link_elf.c     | 38 ++++++++++++++++++++++++++++++++++----
> >  sys/kern/link_elf_obj.c | 31 +++++++++++++++++++++++++++++--
> >  2 files changed, 63 insertions(+), 6 deletions(-)
> >
> > diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
> > index 53af1e164980..bbebadc4c395 100644
> > --- a/sys/kern/link_elf.c
> > +++ b/sys/kern/link_elf.c
> > @@ -1628,6 +1628,30 @@ link_elf_lookup_debug_symbol_ctf(linker_file_t lf, c
> on
> > st char *name,
> >     return (i < ef->ddbsymcnt ? link_elf_ctf_get_ddb(lf, lc) : ENOENT);
> >  }
> >  
> > +static void
> > +link_elf_ifunc_symbol_value(linker_file_t lf, caddr_t *valp, size_t *sizep
> )
> > +{
> > +   c_linker_sym_t sym;
> > +   elf_file_t ef;
> > +   const Elf_Sym *es;
> > +   caddr_t val;
> > +   long off;
> > +
> > +   val = *valp;
> > +   ef = (elf_file_t)lf;
> > +
> > +   /* Provide the value and size of the target symbol, if available. */
> > +   val = ((caddr_t (*)(void))val)();
> > +   if (link_elf_search_symbol(lf, val, &sym, &off) == 0 && off == 0) {
> > +           es = (const Elf_Sym *)sym;
> > +           *valp = (caddr_t)ef->address + es->st_value;
> > +           *sizep = es->st_size;
> > +   } else {
> > +           *valp = val;
> > +           *sizep = 0;
> > +   }
> > +}
> > +
> >  static int
> >  link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
> >      linker_symval_t *symval, bool see_local)
> > @@ -1635,6 +1659,7 @@ link_elf_symbol_values1(linker_file_t lf, c_linker_sy
> m_
> > t sym,
> >     elf_file_t ef;
> >     const Elf_Sym *es;
> >     caddr_t val;
> > +   size_t size;
> >  
> >     ef = (elf_file_t)lf;
> >     es = (const Elf_Sym *)sym;
> > @@ -1644,9 +1669,11 @@ link_elf_symbol_values1(linker_file_t lf, c_linker_s
> ym
> > _t sym,
> >             symval->name = ef->strtab + es->st_name;
> >             val = (caddr_t)ef->address + es->st_value;
> >             if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
> > -                   val = ((caddr_t (*)(void))val)();
> > +                   link_elf_ifunc_symbol_value(lf, &val, &size);
> > +           else
> > +                   size = es->st_size;
> >             symval->value = val;
> > -           symval->size = es->st_size;
> > +           symval->size = size;
> >             return (0);
> >     }
> >     return (ENOENT);
> > @@ -1668,6 +1695,7 @@ link_elf_debug_symbol_values(linker_file_t lf, c_link
> er
> > _sym_t sym,
> >     elf_file_t ef = (elf_file_t)lf;
> >     const Elf_Sym *es = (const Elf_Sym *)sym;
> >     caddr_t val;
> > +   size_t size;
> >  
> >     if (link_elf_symbol_values1(lf, sym, symval, true) == 0)
> >             return (0);
> > @@ -1678,9 +1706,11 @@ link_elf_debug_symbol_values(linker_file_t lf, c_lin
> ke
> > r_sym_t sym,
> >             symval->name = ef->ddbstrtab + es->st_name;
> >             val = (caddr_t)ef->address + es->st_value;
> >             if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
> > -                   val = ((caddr_t (*)(void))val)();
> > +                   link_elf_ifunc_symbol_value(lf, &val, &size);
> > +           else
> > +                   size = es->st_size;
> >             symval->value = val;
> > -           symval->size = es->st_size;
> > +           symval->size = size;
> >             return (0);
> >     }
> >     return (ENOENT);
> > diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
> > index 02fd4caffcd9..3d18aed2b1c0 100644
> > --- a/sys/kern/link_elf_obj.c
> > +++ b/sys/kern/link_elf_obj.c
> > @@ -1510,6 +1510,30 @@ link_elf_lookup_debug_symbol_ctf(linker_file_t lf, c
> on
> > st char *name,
> >     return (link_elf_ctf_get_ddb(lf, lc));
> >  }
> >  
> > +static void
> > +link_elf_ifunc_symbol_value(linker_file_t lf, caddr_t *valp, size_t *sizep
> )
> > +{
> > +   c_linker_sym_t sym;
> > +   elf_file_t ef;
> > +   const Elf_Sym *es;
> > +   caddr_t val;
> > +   long off;
> > +
> > +   val = *valp;
> > +   ef = (elf_file_t)lf;
> > +
> > +   /* Provide the value and size of the target symbol, if available. */
> > +   val = ((caddr_t (*)(void))val)();
> > +   if (link_elf_search_symbol(lf, val, &sym, &off) == 0 && off == 0) {
> > +           es = (const Elf_Sym *)sym;
> > +           *valp = (caddr_t)ef->address + es->st_value;
> > +           *sizep = es->st_size;
> > +   } else {
> > +           *valp = val;
> > +           *sizep = 0;
> > +   }
> > +}
> > +
> >  static int
> >  link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym,
> >      linker_symval_t *symval, bool see_local)
> > @@ -1517,6 +1541,7 @@ link_elf_symbol_values1(linker_file_t lf, c_linker_sy
> m_
> > t sym,
> >     elf_file_t ef;
> >     const Elf_Sym *es;
> >     caddr_t val;
> > +   size_t size;
> >  
> >     ef = (elf_file_t) lf;
> >     es = (const Elf_Sym*) sym;
> > @@ -1527,9 +1552,11 @@ link_elf_symbol_values1(linker_file_t lf, c_linker_s
> ym
> > _t sym,
> >             symval->name = ef->ddbstrtab + es->st_name;
> >             val = (caddr_t)es->st_value;
> >             if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC)
> > -                   val = ((caddr_t (*)(void))val)();
> > +                   link_elf_ifunc_symbol_value(lf, &val, &size);
> > +           else
> > +                   size = es->st_size;
> >             symval->value = val;
> > -           symval->size = es->st_size;
> > +           symval->size = size;
> >             return (0);
> >     }
> >     return (ENOENT);
> >
>
> This commit may have caused a panic loading linux.ko.
>
> #0  __curthread () at /opt/src/git-src/sys/amd64/include/pcpu_aux.h:57
> #1  doadump (textdump=textdump@entry=1)
>     at /opt/src/git-src/sys/kern/kern_shutdown.c:399
> #2  0xffffffff806fad1e in kern_reboot (howto=260)
>     at /opt/src/git-src/sys/kern/kern_shutdown.c:519
> #3  0xffffffff806fb247 in vpanic (fmt=0xffffffff80b2e000 "%s", 
>     ap=ap@entry=0xfffffe008c8e2450)
>     at /opt/src/git-src/sys/kern/kern_shutdown.c:974
> #4  0xffffffff806fb073 in panic (fmt=<unavailable>)
>     at /opt/src/git-src/sys/kern/kern_shutdown.c:887
> #5  0xffffffff80aa8e7a in trap_fatal (frame=<optimized out>, 
>     eva=<optimized out>) at /opt/src/git-src/sys/amd64/amd64/trap.c:974
> #6  0xffffffff80aa8e7a in trap_pfault (frame=0xfffffe008c8e24d0, 
>     usermode=false, signo=<optimized out>, ucode=<optimized out>)
> #7  <signal handler called>
> #8  fbt_provide_module_function (lf=lf@entry=0xfffff80126035900, 
>     symindx=symindx@entry=753, symval=symval@entry=0xfffffe008c8e25f0, 
>     opaque=opaque@entry=0xfffffe008c8e2640)
>     at /opt/src/git-src/sys/cddl/dev/fbt/x86/fbt_isa.c:205
> #9  0xffffffff80ac870d in link_elf_each_function_nameval (
>     file=0xfffff80126035900, 
>     callback=0xffffffff81d916a0 <fbt_provide_module_function>, 
>     opaque=0xfffffe008c8e2640) at /opt/src/git-src/sys/kern/link_elf_obj.c:1
> 685
> --Type <RET> for more, q to quit, c to continue without paging--c
> #10 0xffffffff81d9035f in fbt_provide_module (arg=<optimized out>, 
>     lf=0xfffff80126035900) at /opt/src/git-src/sys/cddl/dev/fbt/fbt.c:221
> #11 0xffffffff81cc87fb in dtrace_module_loaded (ctl=0xfffff80126035900)
>     at /opt/src/git-src/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrac
> e.c:16709
> #12 dtrace_kld_load (arg=<optimized out>, lf=0xfffff80126035900)
>     at /opt/src/git-src/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrac
> e.c:16894
> #13 0xffffffff806c4ecb in linker_load_file (
>     filename=0xfffff80054e6d500 "/boot/kernel/linux.ko", 
>     result=<optimized out>) at /opt/src/git-src/sys/kern/kern_linker.c:518
> #14 linker_load_module (kldname=kldname@entry=0x0, 
>     modname=0xfffff8005437c800 "linux", parent=parent@entry=0x0, 
>     verinfo=verinfo@entry=0x0, lfpp=lfpp@entry=0xfffffe008c8e2da0)
>     at /opt/src/git-src/sys/kern/kern_linker.c:2292
> #15 0xffffffff806c69f5 in kern_kldload (td=td@entry=0xfffff8005ce3c780, 
>     file=file@entry=0xfffff8005437c800 "linux", 
>     fileid=fileid@entry=0xfffffe008c8e2de4)
>     at /opt/src/git-src/sys/kern/kern_linker.c:1236
> #16 0xffffffff806c6b09 in sys_kldload (td=0xfffff8005ce3c780, 
>     uap=0xfffff8005ce3cba8) at /opt/src/git-src/sys/kern/kern_linker.c:1259
> #17 0xffffffff80aa97d6 in syscallenter (td=0xfffff8005ce3c780)
>     at /opt/src/git-src/sys/amd64/amd64/../../kern/subr_syscall.c:193
> #18 amd64_syscall (td=0xfffff8005ce3c780, traced=0)
>     at /opt/src/git-src/sys/amd64/amd64/trap.c:1215
> #19 <signal handler called>
> #20 0x00000ce63ecf8c3a in ?? ()

Confirmed. kldload linux causes the panic.


-- 
Cheers,
Cy Schubert <cy.schub...@cschubert.com>
FreeBSD UNIX:  <c...@freebsd.org>   Web:  https://FreeBSD.org
NTP:           <c...@nwtime.org>    Web:  https://nwtime.org

                        e**(i*pi)+1=0



Reply via email to