From nobody Thu Jan 18 22:26:00 2024 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4TGHQJ6Ghqz578dp; Thu, 18 Jan 2024 22:26:00 +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 4TGHQJ4B3Jz411q; Thu, 18 Jan 2024 22:26:00 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1705616760; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Z9D/cfIAbhJ0gzWtB3Qb0f9xbYBUYQD5C9FiO4VCq/g=; b=lQllUIDDFasuyoJOnEXX953P9Mn8rqtDXJfKQbLcJ092zl0TMHbSw0PijEoYftThfqEF7u RbJDUiZoyMoNk1PkolUDaX0jAaJaDib7NNnFVuASohnrj4r0hOlQcevG8EVHFtTfgcFgwY kcmmu8vkPLnVDX7V1hqzMIzAvVkqsezaUdEv+6M0fjMhnLtOHjdgadpHuRhQ1sVtAeh0p2 qGzkWiYppKH9Ng6Q4/UJ/35izZBVCrDtDSgJoN7bqG/fkQvXMzOrcLRz9+QEZn0b/xqOqV k28/MXBScASn1M30bWZ3XHIu1JLIq3U+ilpUWYxa9Am2PuBUpIX+Za85Jq3Lzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1705616760; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Z9D/cfIAbhJ0gzWtB3Qb0f9xbYBUYQD5C9FiO4VCq/g=; b=ujypcWdXvYCPj3th0ZgibTz+2z7jpPrIadSMkgwd+e0ZUTNzSfh4lDVmf3yhdqXmtfxpIa 6GJow4sVIbyr7vTne3CfWpPKA91RgRJvUpW1NmVhgLFlSX6QXDdCIzsjcHXb8BkH81CstC TXEb9Na8X4Vu7O6Bq7HLx1GZiLHGIoT45BqwVowVB6FsDSo4th+7p8PkcTDYGFXn5qW3T4 KVpQCZ36EAIT7uJryLXmc+BA5rTCBCj/ud/ZJgVHiUHLla5e2aoZk0cJC8bG1rqQxUFcjU b/BGyq/2bhILUdGZA5n92M/S03nPg9+Vf4v864HcLvI9tUPL3jHjOtqgOqNlBg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1705616760; a=rsa-sha256; cv=none; b=y0O2+UOnNf05tywlXzbi5sF5IbtZv4uQBlpVW2Lm9CtePB6oFq6xdW3nguD2NJoWeyaqMO 7g+Xq/QJZOUBuBq/2fODH9qlmyjkXV1IlmbA0vDWy98czh/2casI4s8KHRIhxmcDe9ujfk lZckiWYf+o7Wiwm60Ezl0//d+JoeL4k5qfcF+ilJbdJRgx5RwVtWo3l+j5xluJ2RGqpkIr tDehb0gcD+MOgAn9Ap8QTfeIo6kSnlF7s/krtb9GxWRGeh2u8BOIxdykGgvKz1QYdgrCkC X/WYgnrpIEjrN0imvJZVBLKppF2Ymm2Yy56pcA4t93jy70Zsc3a4URhGNzk5qw== 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 4TGHQJ3GBrzQ4W; Thu, 18 Jan 2024 22:26:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 40IMQ0G3089484; Thu, 18 Jan 2024 22:26:00 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 40IMQ0jG089481; Thu, 18 Jan 2024 22:26:00 GMT (envelope-from git) Date: Thu, 18 Jan 2024 22:26:00 GMT Message-Id: <202401182226.40IMQ0jG089481@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: John Baldwin Subject: git: 214c8da28028 - stable/14 - kldxref: Simplify handling of ELF object files List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 214c8da28028760b5a3c0c1c264c4d4aa42128f7 Auto-Submitted: auto-generated The branch stable/14 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=214c8da28028760b5a3c0c1c264c4d4aa42128f7 commit 214c8da28028760b5a3c0c1c264c4d4aa42128f7 Author: John Baldwin AuthorDate: 2023-12-22 15:49:18 +0000 Commit: John Baldwin CommitDate: 2024-01-18 21:31:29 +0000 kldxref: Simplify handling of ELF object files Unlike the backend for ELF DSOs, the object file backend allocated an aligned chunk of memory and read all of the in-memory sections from the file into this memory even though most of the file contents were never used. Instead, just track a set of virtual addresses (based at 0) that each loaded section would be loaded at and only read the necessary bits from the backing file when needed. Reviewed by: imp Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D43126 (cherry picked from commit 0d557cdf6f0e94e909acea065f3de2a28437ae74) --- usr.sbin/kldxref/ef_obj.c | 146 +++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 81 deletions(-) diff --git a/usr.sbin/kldxref/ef_obj.c b/usr.sbin/kldxref/ef_obj.c index 36c0dce432b6..1274a14c10af 100644 --- a/usr.sbin/kldxref/ef_obj.c +++ b/usr.sbin/kldxref/ef_obj.c @@ -46,7 +46,8 @@ #include "ef.h" typedef struct { - char *addr; + GElf_Addr addr; + GElf_Off offset; GElf_Off size; int flags; int sec; /* Original section */ @@ -69,9 +70,6 @@ struct ef_file { char *ef_name; struct elf_file *ef_efile; - char *address; - GElf_Off size; - Elf_progent *progtab; int nprogtab; @@ -113,6 +111,22 @@ static struct elf_file_ops ef_obj_file_ops = { .lookup_set = ef_obj_lookup_set, }; +static GElf_Off +ef_obj_get_offset(elf_file_t ef, GElf_Addr addr) +{ + Elf_progent *pt; + int i; + + for (i = 0; i < ef->nprogtab; i++) { + pt = &ef->progtab[i]; + if (pt->offset == (GElf_Off)-1) + continue; + if (addr >= pt->addr && addr < pt->addr + pt->size) + return (pt->offset + (addr - pt->addr)); + } + return (0); +} + static int ef_obj_lookup_symbol(elf_file_t ef, const char *name, GElf_Sym **sym) { @@ -139,9 +153,8 @@ ef_obj_lookup_set(elf_file_t ef, const char *name, GElf_Addr *startp, for (i = 0; i < ef->nprogtab; i++) { if ((strncmp(ef->progtab[i].name, "set_", 4) == 0) && strcmp(ef->progtab[i].name + 4, name) == 0) { - *startp = ef->progtab[i].addr - ef->address; - *stopp = ef->progtab[i].addr + ef->progtab[i].size - - ef->address; + *startp = ef->progtab[i].addr; + *stopp = ef->progtab[i].addr + ef->progtab[i].size; *countp = (*stopp - *startp) / elf_pointer_size(ef->ef_efile); return (0); @@ -160,46 +173,50 @@ ef_obj_symaddr(elf_file_t ef, GElf_Size symidx) sym = ef->ddbsymtab + symidx; if (sym->st_shndx != SHN_UNDEF) - return (sym->st_value - (GElf_Addr)ef->address); + return (sym->st_value); return (0); } static int ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, void *dest) { - char *memaddr; + GElf_Off secofs; GElf_Rel *r; GElf_Rela *a; GElf_Addr secbase, dataoff; int error, i, sec; - if (address + len > ef->size) { - if (ef->ef_verbose) - warnx("ef_obj_seg_read_rel(%s): bad offset/len (%lx:%ld)", - ef->ef_name, (long)address, (long)len); - return (EFAULT); - } - bcopy(ef->address + address, dest, len); - /* Find out which section contains the data. */ - memaddr = ef->address + address; sec = -1; - secbase = dataoff = 0; for (i = 0; i < ef->nprogtab; i++) { - if (ef->progtab[i].addr == NULL) + if (address < ef->progtab[i].addr) continue; - if (memaddr < (char *)ef->progtab[i].addr || memaddr + len > - (char *)ef->progtab[i].addr + ef->progtab[i].size) + + dataoff = address - ef->progtab[i].addr; + if (dataoff + len > ef->progtab[i].size) continue; + sec = ef->progtab[i].sec; - /* We relocate to address 0. */ - secbase = (char *)ef->progtab[i].addr - ef->address; - dataoff = memaddr - ef->address; + secbase = ef->progtab[i].addr; + secofs = ef->progtab[i].offset; break; } - if (sec == -1) + if (sec == -1) { + if (ef->ef_verbose) + warnx("ef_obj_seg_read_rel(%s): bad address (%jx)", + ef->ef_name, (uintmax_t)address); return (EFAULT); + } + + if (secofs == (GElf_Off)-1) { + memset(dest, 0, len); + } else { + error = elf_read_raw_data(ef->ef_efile, secofs + dataoff, dest, + len); + if (error != 0) + return (error); + } /* Now do the relocations. */ for (i = 0; i < ef->nrel; i++) { @@ -208,7 +225,7 @@ ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, void *dest) for (r = ef->reltab[i].rel; r < &ef->reltab[i].rel[ef->reltab[i].nrel]; r++) { error = elf_reloc(ef->ef_efile, r, ELF_T_REL, secbase, - dataoff, len, dest); + address, len, dest); if (error != 0) return (error); } @@ -219,7 +236,7 @@ ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, void *dest) for (a = ef->relatab[i].rela; a < &ef->relatab[i].rela[ef->relatab[i].nrela]; a++) { error = elf_reloc(ef->ef_efile, a, ELF_T_RELA, secbase, - dataoff, len, dest); + address, len, dest); if (error != 0) return (error); } @@ -230,21 +247,23 @@ ef_obj_seg_read_rel(elf_file_t ef, GElf_Addr address, size_t len, void *dest) static int ef_obj_seg_read_string(elf_file_t ef, GElf_Addr address, size_t len, char *dest) { + GElf_Off ofs; + int error; - if (address >= ef->size) { + ofs = ef_obj_get_offset(ef, address); + if (ofs == 0) { if (ef->ef_verbose) - warnx("ef_obj_seg_read_string(%s): bad address (%lx)", - ef->ef_name, (long)address); + warnx("ef_obj_seg_read_string(%s): bad address (%jx)", + ef->ef_name, (uintmax_t)address); return (EFAULT); } - if (ef->size - address < len) - len = ef->size - address; - - if (strnlen(ef->address + address, len) == len) + error = elf_read_raw_data(ef->ef_efile, ofs, dest, len); + if (error != 0) + return (error); + if (strnlen(dest, len) == len) return (EFAULT); - memcpy(dest, ef->address + address, len); return (0); } @@ -255,8 +274,8 @@ ef_obj_open(struct elf_file *efile, int verbose) GElf_Ehdr *hdr; GElf_Shdr *shdr; GElf_Sym *es; - char *mapbase; - size_t i, mapsize, alignmask, max_addralign, nshdr; + GElf_Addr mapbase; + size_t i, nshdr; int error, pb, ra, rl; int j, nsym, symstrindex, symtabindex; @@ -359,59 +378,26 @@ ef_obj_open(struct elf_file *efile, int verbose) } } - /* Size up code/data(progbits) and bss(nobits). */ - alignmask = 0; - max_addralign = 0; - mapsize = 0; - for (i = 0; i < nshdr; i++) { - switch (shdr[i].sh_type) { - case SHT_PROGBITS: - case SHT_NOBITS: - alignmask = shdr[i].sh_addralign - 1; - if (shdr[i].sh_addralign > max_addralign) - max_addralign = shdr[i].sh_addralign; - mapsize += alignmask; - mapsize &= ~alignmask; - mapsize += shdr[i].sh_size; - break; - } - } - - /* We know how much space we need for the text/data/bss/etc. */ - ef->size = mapsize; - if (posix_memalign((void **)&ef->address, max_addralign, mapsize)) { - printf("posix_memalign failed\n"); - goto out; - } - mapbase = ef->address; - /* - * Now load code/data(progbits), zero bss(nobits), allocate - * space for and load relocs + * Now allocate address space for code/data(progbits) and + * bss(nobits) and allocate space for and load relocs. */ pb = 0; rl = 0; ra = 0; - alignmask = 0; + mapbase = 0; for (i = 0; i < nshdr; i++) { switch (shdr[i].sh_type) { case SHT_PROGBITS: case SHT_NOBITS: - alignmask = shdr[i].sh_addralign - 1; - mapbase += alignmask; - mapbase = (char *)((uintptr_t)mapbase & ~alignmask); - ef->progtab[pb].addr = (void *)(uintptr_t)mapbase; + mapbase = roundup2(mapbase, shdr[i].sh_addralign); + ef->progtab[pb].addr = mapbase; if (shdr[i].sh_type == SHT_PROGBITS) { ef->progtab[pb].name = "<>"; - if (elf_read_raw_data(efile, - shdr[i].sh_offset, ef->progtab[pb].addr, - shdr[i].sh_size) != 0) { - printf("failed to read progbits\n"); - goto out; - } + ef->progtab[pb].offset = shdr[i].sh_offset; } else { ef->progtab[pb].name = "<>"; - bzero(ef->progtab[pb].addr, shdr[i].sh_size); + ef->progtab[pb].offset = (GElf_Off)-1; } ef->progtab[pb].size = shdr[i].sh_size; ef->progtab[pb].sec = i; @@ -424,7 +410,7 @@ ef_obj_open(struct elf_file *efile, int verbose) es = &ef->ddbsymtab[j]; if (es->st_shndx != i) continue; - es->st_value += (GElf_Addr)ef->progtab[pb].addr; + es->st_value += ef->progtab[pb].addr; } mapbase += shdr[i].sh_size; pb++; @@ -464,8 +450,6 @@ ef_obj_close(elf_file_t ef) if (ef->ef_name) free(ef->ef_name); - if (ef->size != 0) - free(ef->address); if (ef->nprogtab != 0) free(ef->progtab); if (ef->nrel != 0) {