Date: Wed, 8 May 2019 23:32:11 -0400 From: Mark Johnston <markj@freebsd.org> To: Larry Rosenman <ler@freebsd.org> Cc: freebsd-current@freebsd.org Subject: Re: Crash loading dtraceall Message-ID: <20190509033211.GE11774@raichu> In-Reply-To: <460d563e2fe48bfd90b489015b4c0f9d@FreeBSD.org> References: <20190508205245.ulbo6fusk3b4py7t@ler-imac.local> <20190508222932.GB11774@raichu> <845dd186ef038d98c1a95a7454e432d2@FreeBSD.org> <20190508225553.GC11774@raichu> <460d563e2fe48bfd90b489015b4c0f9d@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, May 08, 2019 at 05:57:18PM -0500, Larry Rosenman wrote: > On 05/08/2019 5:55 pm, Mark Johnston wrote: > > On Wed, May 08, 2019 at 05:47:08PM -0500, Larry Rosenman wrote: > >> On 05/08/2019 5:29 pm, Mark Johnston wrote: > >> > On Wed, May 08, 2019 at 03:52:45PM -0500, Larry Rosenman wrote: > >> >> Greetings, > >> >> > >> >> Somewhere between r346483 and r347241 loading dtraceall causes a > >> >> crash. I have the cores and kernels. > >> >> > >> >> It's hard for me to bisect more than this, as the box is remote. > >> >> > >> >> What more do you need? (this dump is fropm r347355). > >> > > >> > Please visit frame 8 and print *lf. > >> > > >> #9 fbt_provide_module_function (lf=0xfffff800020ff000, symindx=30763, > >> symval=0xfffffe00d74d7e00, opaque=0xfffffe00d74d7e50) at > >> /usr/src/sys/cddl/dev/fbt/x86/fbt_isa.c:191 > >> 191 if (*instr == FBT_PUSHL_EBP) > >> (kgdb) print *lf > >> $1 = {ops = 0xfffff800020f6000, refs = 202, userrefs = 1, flags = 1, > >> link = {tqe_next = 0xfffff800020fec00, tqe_prev = 0xffffffff80c767d0 > >> <linker_files>}, filename = 0xfffff80002101030 "kernel", > >> pathname = 0xfffff80002104080 "/boot/kernel/kernel", id = 1, > >> address = > >> 0xffffffff80200000 "\177ELF\002\001\001\t", size = 17612816, > >> ctors_addr > >> = 0x0, ctors_size = 0, ndeps = 0, deps = 0x0, common = {stqh_first = > >> 0x0, > >> stqh_last = 0xfffff800020ff070}, modules = {tqh_first = > >> 0xfffff800020e5800, tqh_last = 0xfffff80002116790}, loaded = {tqe_next > >> = > >> 0x0, tqe_prev = 0x0}, loadcnt = 1, nenabled = 0, fbt_nentries = 25062} > >> (kgdb) > > > > And could you show the output of: > > > > $ readelf -s /boot/kernel/kernel | grep "30763:" > > _______________________________________________ > > freebsd-current@freebsd.org mailing list > > https://lists.freebsd.org/mailman/listinfo/freebsd-current > > To unsubscribe, send any mail to > > "freebsd-current-unsubscribe@freebsd.org" > > [root@oldtbh2 /var/crash]# readelf -s /boot/kernel/kernel | grep > "30763:" > 30763: ffffffff80791310 75 IFUNC GLOBAL DEFAULT 8 x86_rng_store > [root@oldtbh2 /var/crash]# The problem is with the kernel linker's handling of ifuncs. When enumerating symbols, it replaces ifunc symbol values with the return value of the resolver but preserves the original symbol size, which is that of the resolver. I believe this patch will address the panic you're seeing: diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 6ceb34d66b74..8bd9a0219a1d 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -1350,17 +1350,23 @@ static int link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t *symval) { + c_linker_sym_t target; elf_file_t ef; const Elf_Sym *es; caddr_t val; + long diff; ef = (elf_file_t)lf; es = (const Elf_Sym *)sym; if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) { 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) + if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) { val = ((caddr_t (*)(void))val)(); + (void)link_elf_search_symbol(lf, val, &target, &diff); + if (diff == 0) + es = (const Elf_Sym *)target; + } symval->value = val; symval->size = es->st_size; return (0); @@ -1370,8 +1376,12 @@ link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { 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) + if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) { val = ((caddr_t (*)(void))val)(); + (void)link_elf_search_symbol(lf, val, &target, &diff); + if (diff == 0) + es = (const Elf_Sym *)target; + } symval->value = val; symval->size = es->st_size; return (0); diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index ac4cc8c085cb..5ce160a05699 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -1240,9 +1240,11 @@ static int link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, linker_symval_t *symval) { + c_linker_sym_t target; elf_file_t ef; const Elf_Sym *es; caddr_t val; + long diff; ef = (elf_file_t) lf; es = (const Elf_Sym*) sym; @@ -1250,8 +1252,12 @@ link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym, if (es >= ef->ddbsymtab && es < (ef->ddbsymtab + ef->ddbsymcnt)) { symval->name = ef->ddbstrtab + es->st_name; val = (caddr_t)es->st_value; - if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) + if (ELF_ST_TYPE(es->st_info) == STT_GNU_IFUNC) { val = ((caddr_t (*)(void))val)(); + (void)link_elf_search_symbol(lf, val, &target, &diff); + if (diff == 0) + es = (const Elf_Sym *)target; + } symval->value = val; symval->size = es->st_size; return 0;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20190509033211.GE11774>