Date: Mon, 27 May 2019 17:33:20 +0000 (UTC) From: Conrad Meyer <cem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r348309 - head/usr.sbin/kldxref Message-ID: <201905271733.x4RHXKTP005785@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: cem Date: Mon May 27 17:33:20 2019 New Revision: 348309 URL: https://svnweb.freebsd.org/changeset/base/348309 Log: kldxref(8): Sort MDT_MODULE info first in linker.hints output MDT_MODULE info is required to be ordered before any other MDT metadata for a given kld because it serves as an implicit record boundary between distinct klds for linker.hints consumers. kldxref(8) has previously relied on the assumption that MDT_MODULE was ordered relative to other module metadata in kld objects by source code ordering. However, C does not require implementations to emit file scope objects in any particular order, and it seems that GCC 6.4.0 and/or binutils 2.32 ld may reorder emitted objects with respect to source code ordering. So: just take two passes over a given .ko's module metadata, scanning for the MDT_MODULE on the first pass and the other metadata on subsequent passes. It's not super expensive and not exactly a performance-critical piece of code. This ensures MDT_MODULE is always ordered before MDT_PNP_INFO and other MDTs, regardless of compiler/linker movement. As a fringe benefit, it removes the requirement that care be taken to always order MODULE_PNP_INFO after DRIVER_MODULE in source code. Reviewed by: emaste, imp Differential Revision: https://reviews.freebsd.org/D20405 Modified: head/usr.sbin/kldxref/kldxref.c Modified: head/usr.sbin/kldxref/kldxref.c ============================================================================== --- head/usr.sbin/kldxref/kldxref.c Mon May 27 17:14:46 2019 (r348308) +++ head/usr.sbin/kldxref/kldxref.c Mon May 27 17:33:20 2019 (r348309) @@ -549,9 +549,9 @@ read_kld(char *filename, char *kldname) { struct mod_metadata md; struct elf_file ef; - void **p, **orgp; + void **p; int error, eftype; - long start, finish, entries; + long start, finish, entries, i; char cval[MAXMODNAME + 1]; if (verbose || dflag) @@ -575,18 +575,53 @@ read_kld(char *filename, char *kldname) &entries)); check(EF_SEG_READ_ENTRY_REL(&ef, start, sizeof(*p) * entries, (void *)&p)); - orgp = p; - while(entries--) { - check(EF_SEG_READ_REL(&ef, (Elf_Off)*p, sizeof(md), + /* + * Do a first pass to find MDT_MODULE. It is required to be + * ordered first in the output linker.hints stream because it + * serves as an implicit record boundary between distinct klds + * in the stream. Other MDTs only make sense in the context of + * a specific MDT_MODULE. + * + * Some compilers (e.g., GCC 6.4.0 xtoolchain) or binutils + * (e.g., GNU binutils 2.32 objcopy/ld.bfd) can reorder + * MODULE_METADATA set entries relative to the source ordering. + * This is permitted by the C standard; memory layout of + * file-scope objects is left implementation-defined. There is + * no requirement that source code ordering is retained. + * + * Handle that here by taking two passes to ensure MDT_MODULE + * records are emitted to linker.hints before other MDT records + * in the same kld. + */ + for (i = 0; i < entries; i++) { + check(EF_SEG_READ_REL(&ef, (Elf_Off)p[i], sizeof(md), &md)); - p++; check(EF_SEG_READ_STRING(&ef, (Elf_Off)md.md_cval, sizeof(cval), cval)); - parse_entry(&md, cval, &ef, kldname); + if (md.md_type == MDT_MODULE) { + parse_entry(&md, cval, &ef, kldname); + break; + } } + if (error != 0) { + warnc(error, "error while reading %s", filename); + break; + } + + /* + * Second pass for all !MDT_MODULE entries. + */ + for (i = 0; i < entries; i++) { + check(EF_SEG_READ_REL(&ef, (Elf_Off)p[i], sizeof(md), + &md)); + check(EF_SEG_READ_STRING(&ef, (Elf_Off)md.md_cval, + sizeof(cval), cval)); + if (md.md_type != MDT_MODULE) + parse_entry(&md, cval, &ef, kldname); + } if (error != 0) warnc(error, "error while reading %s", filename); - free(orgp); + free(p); } while(0); EF_CLOSE(&ef); return (error);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905271733.x4RHXKTP005785>