Date: Sat, 23 Jan 2021 16:01:59 GMT From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 80a5b8512a2c - stable/12 - kldxref(8): Sort MDT_MODULE info first in linker.hints output Message-ID: <202101231601.10NG1xET053759@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/12 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=80a5b8512a2c6193df36bd2dd885fc772633a971 commit 80a5b8512a2c6193df36bd2dd885fc772633a971 Author: Conrad Meyer <cem@FreeBSD.org> AuthorDate: 2019-05-27 17:33:20 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2021-01-23 16:01:21 +0000 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 (cherry picked from commit 9c1fa7a429145b298a012cb7b752c82a1e0b1184) --- usr.sbin/kldxref/kldxref.c | 51 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/usr.sbin/kldxref/kldxref.c b/usr.sbin/kldxref/kldxref.c index 4e456a05c25b..c70405962dd8 100644 --- a/usr.sbin/kldxref/kldxref.c +++ b/usr.sbin/kldxref/kldxref.c @@ -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)); + 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); + 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)); - 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); } 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?202101231601.10NG1xET053759>