From owner-dev-commits-src-branches@freebsd.org Sat Jan 23 16:01:59 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 782484F6B9F; Sat, 23 Jan 2021 16:01:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DNLVH32bxz4dhL; Sat, 23 Jan 2021 16:01:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 5B04D141AA; Sat, 23 Jan 2021 16:01:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 10NG1xX3053760; Sat, 23 Jan 2021 16:01:59 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 10NG1xET053759; Sat, 23 Jan 2021 16:01:59 GMT (envelope-from git) Date: Sat, 23 Jan 2021 16:01:59 GMT Message-Id: <202101231601.10NG1xET053759@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: 80a5b8512a2c - stable/12 - kldxref(8): Sort MDT_MODULE info first in linker.hints output MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: 80a5b8512a2c6193df36bd2dd885fc772633a971 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 Jan 2021 16:01:59 -0000 The branch stable/12 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=80a5b8512a2c6193df36bd2dd885fc772633a971 commit 80a5b8512a2c6193df36bd2dd885fc772633a971 Author: Conrad Meyer AuthorDate: 2019-05-27 17:33:20 +0000 Commit: Mark Johnston 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);