From 6192271ea890b04b00419368a6ab9950972749d0 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 20 Jan 2004 21:32:47 +0000 Subject: [PATCH] Resident executable support stage 4/4: remove prebinding support. Resident executables are a whole lot more efficient so prebinding support is no longer necessary. See 'resident' command. --- libexec/rtld-elf/Makefile | 7 +- libexec/rtld-elf/i386/rtld_machdep.h | 27 +- libexec/rtld-elf/prebind.c | 949 --------------------------- libexec/rtld-elf/rtld.c | 79 +-- libexec/rtld-elf/rtld.h | 7 +- usr.sbin/Makefile | 3 +- usr.sbin/prebind/Makefile | 8 - usr.sbin/prebind/prebind.8 | 18 - usr.sbin/prebind/prebind.c | 196 ------ usr.sbin/resident/resident.c | 4 +- 10 files changed, 14 insertions(+), 1284 deletions(-) delete mode 100644 libexec/rtld-elf/prebind.c delete mode 100644 usr.sbin/prebind/Makefile delete mode 100644 usr.sbin/prebind/prebind.8 delete mode 100644 usr.sbin/prebind/prebind.c diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile index 1fc9cb79e7..cd77059a89 100644 --- a/libexec/rtld-elf/Makefile +++ b/libexec/rtld-elf/Makefile @@ -1,18 +1,15 @@ # $FreeBSD: src/libexec/rtld-elf/Makefile,v 1.10.2.6 2002/06/22 17:03:13 jdp Exp $ -# $DragonFly: src/libexec/rtld-elf/Makefile,v 1.3 2003/09/18 21:22:56 dillon Exp $ +# $DragonFly: src/libexec/rtld-elf/Makefile,v 1.4 2004/01/20 21:32:46 dillon Exp $ PROG= ld-elf.so.1 SRCS= rtld_start.S rtld.c lockdflt.c map_object.c malloc.c \ - xmalloc.c debug.c reloc.c prebind.c + xmalloc.c debug.c reloc.c MAN= rtld.1 CFLAGS+= -Wall -DFREEBSD_ELF -I${.CURDIR}/${MACHINE_ARCH} -I${.CURDIR} LDFLAGS+= -nostdlib -e .rtld_start INSTALLFLAGS= -fschg -C -b MLINKS= rtld.1 ld-elf.so.1.1 -RTLD_TS!= /bin/date +%s -CFLAGS+= -DRTLD_TS=${RTLD_TS} - .if exists(${.CURDIR}/${MACHINE_ARCH}/Makefile.inc) .include "${.CURDIR}/${MACHINE_ARCH}/Makefile.inc" .endif diff --git a/libexec/rtld-elf/i386/rtld_machdep.h b/libexec/rtld-elf/i386/rtld_machdep.h index 724dc14033..43e755b78d 100644 --- a/libexec/rtld-elf/i386/rtld_machdep.h +++ b/libexec/rtld-elf/i386/rtld_machdep.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/libexec/rtld-elf/i386/rtld_machdep.h,v 1.3.2.2 2002/07/02 04:10:51 jdp Exp $ - * $DragonFly: src/libexec/rtld-elf/i386/rtld_machdep.h,v 1.4 2003/10/05 23:06:45 dillon Exp $ + * $DragonFly: src/libexec/rtld-elf/i386/rtld_machdep.h,v 1.5 2004/01/20 21:32:47 dillon Exp $ */ #ifndef RTLD_MACHDEP_H @@ -63,29 +63,4 @@ atomic_add_int(volatile int *p, int val) : "cc"); } -/* - * Optimized version of the calculation y = ky + m (mod p) - * See elf_uniqid() for details - */ -static inline u_int32_t -uniqid_hash_block(u_int32_t hash, u_int32_t key, u_int32_t block) -{ - int ret; - - __asm __const ( "mull %2\n\t" - "lea (%%edx,%%edx,4),%%edx\n\t" - "addl %%edx,%%eax\n\t" - "lea 0x5(%%eax),%%edx\n\t" - "jnc 1f\n\t" - "movl %%edx,%%eax\n\t" - "1:; addl %3,%%eax\n\t" - "lea 0x5(%%eax),%%edx\n\t" - "jnc 1f\n\t" - "movl %%edx,%%eax\n\t" - "1:;\n\t" - : "=a"(ret) : "a"(hash), "rm"(key), "g"(block) : "cc", "dx"); - - return ret; -} - #endif diff --git a/libexec/rtld-elf/prebind.c b/libexec/rtld-elf/prebind.c deleted file mode 100644 index b277b47a46..0000000000 --- a/libexec/rtld-elf/prebind.c +++ /dev/null @@ -1,949 +0,0 @@ -/*- - * Copyright (c) 2003 Matthew N. Dodd - * All rights reserved. - * - * Redistribution and use in soupe and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of soupe code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $DragonFly: src/libexec/rtld-elf/Attic/prebind.c,v 1.1 2003/09/18 21:22:56 dillon Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "rtld.h" - -typedef struct { - Elf_Word r_info; /* Relocation type and symbol index. */ - Elf_Addr r_offset; /* Offset from object Relocation constant */ - int index; /* Definition Object index */ - Elf_Addr st_value; /* Definition Symbol value. */ - Elf_Size st_size; /* Copy relocation size */ -} Prebind_Entry; - -typedef struct { - int index; /* Object index */ - int type; /* Type of Prebind_Entry objects */ - int count; /* Number of Prebind_Entry objects */ -} Prebind_Object_Index; -#define TYPE_NONE 0 /* None */ -#define TYPE_NON_PLT 1 /* Non-PLT relocation. */ -#define TYPE_PLT 2 /* PLT relocation. */ -#define TYPE_COPY 3 /* Non-PLT COPY relocation */ - -typedef struct { - char name[MAXPATHLEN];/* (obj->path) */ - u_int32_t uniqid; /* Unique executable ID */ -} Prebind_Object; - -typedef struct { - int version; /* Version number */ - char name[MAXPATHLEN];/* basename */ - u_int32_t uniqid; /* Unique executable ID */ - int nobjects; /* number of Prebind_Object elements */ -} Prebind_Header; - -#define PREBIND_PATH "/var/db/prebind" -#define PREBIND_VERSION 2003052500 -#define PREBIND_MINSIZE (sizeof(Prebind_Header) + \ - sizeof(Prebind_Object)) - -static char name[MAXPATHLEN]; -static int valid_args (Obj_Entry *, Obj_Entry *); -static int set_filename (Obj_Entry *); -static int check_object (Obj_Entry *, Prebind_Object *); - -/* Non-PLT relocations */ -static int count_non_plt (Obj_Entry *); -static int write_non_plt (int, Obj_Entry *, Obj_Entry **); -static int read_non_plt (Obj_Entry *, Obj_Entry **, - Prebind_Object_Index *, - caddr_t, off_t *, off_t); -/* PLT relocations */ -static int count_plt (Obj_Entry *); -static int write_plt (int, Obj_Entry *, Obj_Entry **); -static int read_plt (Obj_Entry *, Obj_Entry **, - Prebind_Object_Index *, - caddr_t, off_t *, off_t); -/* Non-PLT COPY relocations */ -static int count_copy (Obj_Entry *); -static int write_copy (int, Obj_Entry *, Obj_Entry **); -static int read_copy (Obj_Entry *, Obj_Entry **, - Prebind_Object_Index *, - caddr_t, off_t *, off_t); - -#if 0 -static void dump_Elf_Rel (Obj_Entry *, const Elf_Rel *, u_long); -#endif -static int obj2index (Obj_Entry **, const Obj_Entry *); - -static inline int -prebind_cklen(off_t off, off_t size, off_t len) -{ - if (off + len > size) { - warnx("Prebind file appears truncated."); - return -1; - } - - return 0; -} - -int -prebind_load (Obj_Entry *obj_rtld, Obj_Entry *obj0) -{ - struct stat sb; - Obj_Entry **obj_list; - Obj_Entry *obj; - Prebind_Header *ph; - Prebind_Object *po; - Prebind_Object_Index *poi; - caddr_t cache; - off_t off, size; - int fd; - int nobj; - int i; - int error; - int retval; - - obj_list = NULL; - retval = -1; - - if ((nobj = valid_args(obj_rtld, obj0)) == -1) - return (1); - if (set_filename(obj0)) - return (1); - - off = 0; - fd = open(name, O_RDONLY, 0644); - if (fd == -1) - return (1); - - error = fstat(fd, &sb); - if (error == -1) { - warn("stat(\"%s\", ...)", name); - goto out; - } - size = sb.st_size; - - if ((sb.st_uid != 0) || (sb.st_gid != 0) || - ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0)) { - warnx("Prebind file has invalid permissions/ownership."); - goto out; - } - - dbg("Prebind: Reading from \"%s\"\n", name); - - cache = mmap(0, sb.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); - if (cache == MAP_FAILED) - goto out; - - if (prebind_cklen(off, size, sizeof(Prebind_Header))) - goto error; - - ph = (Prebind_Header *)cache; - off += sizeof(Prebind_Header); - dbg("\tversion %d, name \"%s\", nobjects %d\n", - ph->version, ph->name, ph->nobjects); - - if (ph->version != PREBIND_VERSION) { - warnx("Prebind file header version number invalid!"); - goto error; - } - - if (nobj != ph->nobjects) { - warnx("Number of objects (%d) different from expected (%d).", - nobj, ph->nobjects); - goto error; - } - - if (ph->uniqid != obj0->uniqid) { - warnx("Executable UNIQID does not match cache file header."); - goto error; - } - - /* Init our object list */ - obj_list = xmalloc((nobj + 2) * sizeof(obj_list[0])); - obj_list[nobj+1] = NULL; /* NULL terminate the list */ - - /* Check ld-elf.so and add it to the list. */ - if (prebind_cklen(off, size, sizeof(Prebind_Object))) - goto error; - - po = (Prebind_Object *)(cache + off); - off += sizeof(Prebind_Object); - dbg(" object \"%s\", uniqid %d, relocbase %p\n", - obj_rtld->path, obj_rtld->uniqid, obj_rtld->relocbase); - if (check_object(obj_rtld, po)) - goto error; - obj_list[0] = obj_rtld; - - /* Check each object and add it to the list */ - for (i = 1, obj = obj0; obj != NULL; i++, obj = obj->next) { - if (prebind_cklen(off, size, sizeof(Prebind_Object))) - goto error; - - po = (Prebind_Object *)(cache + off); - off += sizeof(Prebind_Object); - - dbg(" object \"%s\", uniqid %d, relocbase %p\n", - obj->path, obj->uniqid, obj->relocbase); - - if (check_object(obj, po)) - goto error; - - obj_list[i] = obj; - } - - while ((off + sizeof(Prebind_Object_Index)) <= sb.st_size) { - if (prebind_cklen(off, size, sizeof(Prebind_Object_Index))) - goto error; - - poi = (Prebind_Object_Index *)(cache + off); - off += sizeof(Prebind_Object_Index); - obj = obj_list[poi->index]; - - dbg("index %d, type %d, count %d\n", - poi->index, poi->type, poi->count); - - switch (poi->type) { - case TYPE_NON_PLT: - if (read_non_plt(obj, obj_list, poi, cache, &off, size) != 0) - goto error; - break; - case TYPE_PLT: - if (read_plt(obj, obj_list, poi, cache, &off, size) != 0) - goto error; - break; - case TYPE_COPY: - if (read_copy(obj, obj_list, poi, cache, &off, size) != 0) - goto error; - break; - default: - break; - } - } - - /* Finish up. */ - for (obj = obj0; obj != NULL; obj = obj->next) { - /* - * Set up the magic number and version in the Obj_Entry. These - * were checked in the crt1.o from the original ElfKit, so we - * set them for backward compatibility. - */ - obj->magic = RTLD_MAGIC; - obj->version = RTLD_VERSION; - - /* Set the special PLT or GOT entries. */ - init_pltgot(obj); - } - - retval = 0; -error: - munmap(cache, sb.st_size); -out: - close(fd); - if (obj_list) - free(obj_list); - if (retval == -1) - warnx("Prebind failed."); - else - dbg("Prebind ok.\n"); - return (retval); -} - -int -prebind_save (Obj_Entry *obj_rtld, Obj_Entry *obj0) -{ - Obj_Entry **obj_list; - Obj_Entry *obj; - Prebind_Header ph; - Prebind_Object po; - Prebind_Object_Index poi; - int nobj; - int i; - int fd; - ssize_t len; - - obj_list = NULL; - i = 0; - - if ((nobj = valid_args(obj_rtld, obj0)) == -1) - return (1); - if (set_filename(obj0)) - return (1); - - fd = open(name, O_CREAT | O_TRUNC | O_WRONLY, 0644); - if (fd == -1) { - warn("open(\"%s\", ...)", name); - return (1); - } - - /* Prebinding Cache Header */ - bzero(&ph, sizeof(Prebind_Header)); - ph.version = PREBIND_VERSION; - strcpy(ph.name, basename(obj0->path)); - ph.uniqid = obj0->uniqid; - ph.nobjects = nobj; - len = write(fd, &ph, sizeof(Prebind_Header)); - if (len == -1) { - warn("write(Prebind_Header)"); - goto error; - } - if (len != sizeof(Prebind_Header)) { - warnx("short write."); - goto error; - } - - /* Setup object list for index lookups. */ - obj_list = xmalloc((nobj + 2) * sizeof(obj_list[0])); - obj_list[nobj+1] = NULL; - - dbg(" object %-30s uniqid %d\n", obj_rtld->path, obj_rtld->uniqid); - - /* ld-elf.so Prebinding Cache Object */ - bzero(&po, sizeof(Prebind_Object)); - strcpy(po.name, obj_rtld->path); - po.uniqid = obj_rtld->uniqid; - len = write(fd, &po, sizeof(Prebind_Object)); - if (len == -1) { - warn("write(Prebind_Object)"); - goto error; - } - if (len != sizeof(Prebind_Object)) { - warnx("short write."); - goto error; - } - obj_list[0] = obj_rtld; - - /* Add entries for each object */ - for (i = 1, obj = obj0; obj != NULL; i++, obj = obj->next) { - printf(" object %-30s uniqid %d\n", obj->path, obj->uniqid); - if (obj->textrel) - dbg("\timpure text\n"); - - /* Prebinding Cache Object */ - bzero(&po, sizeof(Prebind_Object)); - strcpy(po.name, obj->mainprog ? basename(obj->path) : obj->path); - po.uniqid = obj->uniqid; - - len = write(fd, &po, sizeof(Prebind_Object)); - if (len == -1) { - warn("write(Prebind_Object)"); - goto error; - } - if (len != sizeof(Prebind_Object)) { - warnx("short write."); - goto error; - } - obj_list[i] = obj; - } - - printf("Non-PLT Prebindings:\n"); - for (i = 1, obj = obj0; obj != NULL; i++, obj = obj->next) { - poi.index = i; - poi.type = TYPE_NON_PLT; - poi.count = count_non_plt(obj); - - if (poi.count == 0) - continue; - printf(" object %-30s count %d\n", obj->path, poi.count); - - len = write(fd, &poi, sizeof(Prebind_Object_Index)); - if (len == -1) { - warn("write(Prebind_Object_Index)"); - goto error; - } - if (len != sizeof(Prebind_Object_Index)) { - warnx("short write."); - goto error; - } - - len = write_non_plt(fd, obj, obj_list); - if (len == -1) - goto error; - } - - printf("PLT Prebindings:\n"); - for (i = 1, obj = obj0; obj != NULL; i++, obj = obj->next) { - poi.index = i; - poi.type = TYPE_PLT; - poi.count = count_plt(obj); - - if (poi.count == 0) - continue; - printf(" object %-30s count %d\n", obj->path, poi.count); - - len = write(fd, &poi, sizeof(Prebind_Object_Index)); - if (len == -1) { - warn("write(Prebind_Object_Index)"); - goto error; - } - if (len != sizeof(Prebind_Object_Index)) { - warnx("short write."); - goto error; - } - - len = write_plt(fd, obj, obj_list); - if (len == -1) - goto error; - } - - printf("Non-PLT COPY Prebindings:\n"); - for (i = 1, obj = obj0; obj != NULL; i++, obj = obj->next) { - poi.index = i; - poi.type = TYPE_COPY; - poi.count = count_copy(obj); - - if (poi.count == 0) - continue; - printf(" object %-30s count %d\n", obj->path, poi.count); - - len = write(fd, &poi, sizeof(Prebind_Object_Index)); - if (len == -1) { - warn("write(Prebind_Object_Index)"); - goto error; - } - if (len != sizeof(Prebind_Object_Index)) { - warnx("short write."); - goto error; - } - - len = write_copy(fd, obj, obj_list); - if (len == -1) - goto error; - } - -error: - if (obj_list) - free(obj_list); - close(fd); - return (0); -} - -static int -valid_args (Obj_Entry *obj_rtld, Obj_Entry *obj0) -{ - Obj_Entry *obj; - int nobj; - - if (obj_rtld->rtld == 0 || obj0->mainprog == 0) - return (-1); - - for (nobj = 0, obj = obj0; obj != NULL; ++nobj, obj = obj->next) - ; /* loop */ - - return (nobj); -} - -static int -set_filename (Obj_Entry *obj0) -{ - - bzero(name, MAXPATHLEN); - snprintf(name, MAXPATHLEN, "%s/%08x.%s", - PREBIND_PATH, obj0->uniqid, basename(obj0->path)); - if (strlen(name) < (strlen(PREBIND_PATH) + 10)) { - warnx("Invalid or truncated Prebind file name \"%s\".", name); - return (1); - } - return (0); -} - -static int -check_object (Obj_Entry *obj, Prebind_Object *po) -{ - if (po->uniqid != obj->uniqid) { - warnx("Object UNIQID does not match cache file entry."); - warnx("\"%s\".", obj->path); - return (1); - } - - if (strcmp(po->name, obj->mainprog ? - basename(obj->path) : obj->path) != 0) { - warnx("Object name does not match cache file entry."); - return (1); - } - - return (0); -} - -static int -count_non_plt (Obj_Entry *obj) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - int count; - - count = 0; - rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize); - for (rel = obj->rel; rel < rellim; rel++) { - switch (ELF_R_TYPE(rel->r_info)) { - case R_386_32: - case R_386_PC32: - case R_386_GLOB_DAT: - count++; - break; - default: - break; - } - } - - return (count); -} - -static int -write_non_plt (int fd, Obj_Entry *obj, Obj_Entry **obj_list) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - SymCache *cache; - Prebind_Entry pe; - ssize_t len; - int bytes; - int error; - - bytes = obj->nchains * sizeof(SymCache); - error = -1; - - /* - * The dynamic loader may be called from a thread, we have - * limited amounts of stack available so we cannot use alloca(). - */ - cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); - if (cache == MAP_FAILED) - cache = NULL; - - rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize); - for (rel = obj->rel; rel < rellim; rel++) { - pe.r_info = rel->r_info; - pe.r_offset = rel->r_offset; - pe.index = -1; - pe.st_value = 0; - pe.st_size = 0; - - switch (ELF_R_TYPE(rel->r_info)) { - case R_386_NONE: - case R_386_RELATIVE: - continue; - break; - case R_386_32: - case R_386_PC32: - case R_386_GLOB_DAT: { - const Elf_Sym *defsym; - const Obj_Entry *defobj; - - defsym = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, false, - cache); - if (defsym == NULL) - goto error; - - pe.index = obj2index(obj_list, defobj); - pe.st_value = defsym->st_value; - break; - } - case R_386_COPY: - if (!obj->mainprog) { - warnx("%s: Unexpected R_386_COPY relocation in shared library", - obj->path); - goto error; - } - continue; - break; - default: - warnx("%s: Unsupported relocation type %d.", - obj->path, ELF_R_TYPE(rel->r_info)); - goto error; - break; - } - - len = write(fd, &pe, sizeof(Prebind_Entry)); - if (len == -1) { - warn("write(Prebind_Entry)"); - goto error; - } - if (len != sizeof(Prebind_Entry)) { - warnx("short write"); - goto error; - } - -#if 0 - printf(" \"%s\" r_info %04x, r_offset %#x, idx %d, st_value %#x, st_size %d\n", - obj->strtab + - ((const Elf_Sym *)(obj->symtab + ELF_R_SYM(rel->r_info)))->st_name, - pe.r_info, pe.r_offset, pe.index, pe.st_value, pe.st_size); -#endif - } - - error = 0; -error: - if (cache) - munmap(cache, bytes); - return (error); -} - -static int -read_non_plt (Obj_Entry *obj, Obj_Entry **obj_list, Prebind_Object_Index *poi, - caddr_t addr, off_t *poff, off_t size) -{ - Prebind_Entry *pe; - const Elf_Rel *rel; - const Elf_Rel *rellim; - Elf_Addr *where, target; - int i; - int retval; - off_t off; - - retval = -1; - off = *poff; - - if (obj->textrel) { - /* There are relocations to the write-protected text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - warn("%s: Cannot write-enable text segment", obj->path); - goto error; - } - } - - for (i = 0; i < poi->count; i++) { - if (prebind_cklen(off, size, sizeof(Prebind_Entry))) - goto error; - - pe = (Prebind_Entry *)(addr + off); - off += sizeof(Prebind_Entry); - - where = (Elf_Addr *) (obj->relocbase + pe->r_offset); - target = (Elf_Addr) (obj_list[pe->index]->relocbase + pe->st_value); - - switch (ELF_R_TYPE(pe->r_info)) { - case R_386_32: - *where += target; - break; - case R_386_PC32: - *where += target - (Elf_Addr) where; - break; - case R_386_GLOB_DAT: - *where = target; - break; - default: - warnx("%s: Enexpected relocation type %d", obj->path, - ELF_R_TYPE(pe->r_info)); - goto error; - break; - } - } - - /* While we're here, take care of all RELATIVE relocations. */ - rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize); - for (rel = obj->rel; rel < rellim; rel++) { - if (ELF_R_TYPE(rel->r_info) != R_386_RELATIVE) - continue; - where = (Elf_Addr *) (obj->relocbase + rel->r_offset); - *where += (Elf_Addr) obj->relocbase; - } - - if (obj->textrel) { /* Re-protected the text segment. */ - if (mprotect(obj->mapbase, obj->textsize, PROT_READ|PROT_EXEC) == -1) { - warn("%s: Cannot write-protect text segment", obj->path); - goto error; - } - } - - retval = 0; -error: - *poff = off; - return (retval); -} - -static int -count_plt (Obj_Entry *obj) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - int count; - - count = 0; - rellim = (const Elf_Rel *)((caddr_t)obj->pltrel + obj->pltrelsize); - for (rel = obj->pltrel; rel < rellim; rel++) - if (ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT) - count++; - - return (count); -} - -static int -write_plt (int fd, Obj_Entry *obj, Obj_Entry **obj_list) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - SymCache *cache; - Prebind_Entry pe; - ssize_t len; - int bytes; - int error; - - bytes = obj->nchains * sizeof(SymCache); - error = -1; - - /* - * The dynamic loader may be called from a thread, we have - * limited amounts of stack available so we cannot use alloca(). - */ - cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); - if (cache == MAP_FAILED) - cache = NULL; - - rellim = (const Elf_Rel *)((caddr_t)obj->pltrel + obj->pltrelsize); - for (rel = obj->pltrel; rel < rellim; rel++) { - const Elf_Sym *defsym; - const Obj_Entry *defobj; - - assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT); - - pe.r_info = rel->r_info; - pe.r_offset = rel->r_offset; - pe.index = -1; - pe.st_value = 0; - pe.st_size = 0; - - defsym = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, cache); - if (defsym == NULL) - goto error; - - pe.index = obj2index(obj_list, defobj); - pe.st_value = defsym->st_value; - - len = write(fd, &pe, sizeof(Prebind_Entry)); - if (len == -1) { - warn("write(Prebind_Entry)"); - goto error; - } - if (len != sizeof(Prebind_Entry)) { - warnx("short write"); - goto error; - } -#if 0 - printf(" \"%s\" r_info %04x, r_offset %#x, idx %d, st_value %#x, st_size %d\n", - obj->strtab + - ((const Elf_Sym *)(obj->symtab + ELF_R_SYM(rel->r_info)))->st_name, - pe.r_info, pe.r_offset, pe.index, pe.st_value, pe.st_size); -#endif - } - - error = 0; -error: - if (cache) - munmap(cache, bytes); - return (error); -} - -static int -read_plt (Obj_Entry *obj, Obj_Entry **obj_list, Prebind_Object_Index *poi, - caddr_t addr, off_t *poff, off_t size) -{ - Prebind_Entry *pe; - Elf_Addr *where, target; - int i; - int retval; - off_t off; - - retval = -1; - off = *poff; - - for (i = 0; i < poi->count; i++) { - if (prebind_cklen(off, size, sizeof(Prebind_Entry))) - goto error; - - pe = (Prebind_Entry *)(addr + off); - off += sizeof(Prebind_Entry); - - where = (Elf_Addr *) (obj->relocbase + pe->r_offset); - target = (Elf_Addr) (obj_list[pe->index]->relocbase + pe->st_value); - *where += (Elf_Addr) obj->relocbase; - reloc_jmpslot(where, target); - } - - retval = 0; -error: - *poff = off; - return (retval); -} - -static int -count_copy (Obj_Entry *obj) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - int count; - - count = 0; - rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize); - for (rel = obj->rel; rel < rellim; rel++) - if (ELF_R_TYPE(rel->r_info) == R_386_COPY) - count++; - - return (count); -} - -static int -write_copy (int fd, Obj_Entry *obj, Obj_Entry **obj_list) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - Prebind_Entry pe; - ssize_t len; - int error; - - error = -1; - - rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize); - for (rel = obj->rel; rel < rellim; rel++) { - const Elf_Sym *sym; - const Elf_Sym *defsym; - const Obj_Entry *defobj; - const char *name; - unsigned long hash; - - if (ELF_R_TYPE(rel->r_info) != R_386_COPY) - continue; - - pe.r_info = rel->r_info; - pe.r_offset = rel->r_offset; - pe.index = -1; - - sym = obj->symtab + ELF_R_SYM(rel->r_info); - hash = elf_hash(obj->strtab + sym->st_name); - name = obj->strtab + sym->st_name; - - for (defobj = obj->next; defobj != NULL; defobj = defobj->next) - if ((defsym = symlook_obj(name, hash, defobj, false)) != NULL) - break; - - if (defobj == NULL) { - printf("Undefined symbol \"%s\" referenced from COPY" - " relocation in %s", name, obj->path); - goto error; - } - - pe.index = obj2index(obj_list, defobj); - pe.st_value = defsym->st_value; - pe.st_size = sym->st_size; - - len = write(fd, &pe, sizeof(Prebind_Entry)); - if (len == -1) { - warn("write(Prebind_Entry)"); - goto error; - } - if (len != sizeof(Prebind_Entry)) { - warnx("short write"); - goto error; - } -#if 0 - printf(" \"%s\" r_info %04x, r_offset %#x, idx %d, st_value %#x, st_size %d\n", - obj->strtab + - ((const Elf_Sym *)(obj->symtab + ELF_R_SYM(rel->r_info)))->st_name, - pe.r_info, pe.r_offset, pe.index, pe.st_value, pe.st_size); -#endif - } - - error = 0; -error: - return (error); -} - -static int -read_copy (Obj_Entry *obj, Obj_Entry **obj_list, Prebind_Object_Index *poi, - caddr_t addr, off_t *poff, off_t size) -{ - Prebind_Entry *pe; - Elf_Addr *where, target; - int i; - int retval; - off_t off; - - retval = -1; - off = *poff; - - for (i = 0; i < poi->count; i++) { - if (prebind_cklen(off, size, sizeof(Prebind_Entry))) - goto error; - - pe = (Prebind_Entry *)(addr + off); - off += sizeof(Prebind_Entry); - - if (ELF_R_TYPE(pe->r_info) != R_386_COPY) { - warnx("Unexpected relocation type %d; expected R_386_COPY.", - ELF_R_TYPE(pe->r_info)); - goto error; - } - - where = (Elf_Addr *) (obj->relocbase + pe->r_offset); - target = (Elf_Addr) (obj_list[pe->index]->relocbase + pe->st_value); - memcpy(where, (void *)target, pe->st_size); - } - - retval = 0; -error: - *poff = off; - return (retval); -} - -#if 0 -static void -dump_Elf_Rel (Obj_Entry *obj, const Elf_Rel *rel0, u_long relsize) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - const Elf_Sym *sym; - Elf_Addr *dstaddr; - - rellim = (const Elf_Rel *)((char *)rel0 + relsize); - for (rel = rel0; rel < rellim; rel++) { - dstaddr = (Elf_Addr *)(obj->relocbase + rel->r_offset); - sym = obj->symtab + ELF_R_SYM(rel->r_info); - printf("\t\"%s\" offset %p, info %04x, addr %#x, size %d\n", - obj->strtab + sym->st_name, - dstaddr, rel->r_info, *dstaddr, sym->st_size); - } - return; -} -#endif - -static int -obj2index (Obj_Entry **obj_list, const Obj_Entry *obj) -{ - int i; - - for (i = 0; obj_list[i] != NULL; i++) - if (obj == obj_list[i]) - return (i); - - return (-1); -} diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 77d69d971d..54f15c648c 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -24,7 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/libexec/rtld-elf/rtld.c,v 1.43.2.15 2003/02/20 20:42:46 kan Exp $ - * $DragonFly: src/libexec/rtld-elf/rtld.c,v 1.6 2004/01/20 21:13:57 dillon Exp $ + * $DragonFly: src/libexec/rtld-elf/rtld.c,v 1.7 2004/01/20 21:32:46 dillon Exp $ */ /* @@ -83,7 +83,6 @@ static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); static Obj_Entry *dlcheck(void *); static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); static bool donelist_check(DoneList *, const Obj_Entry *); -static u_int32_t elf_uniqid(u_int32_t, const void *, size_t); static void errmsg_restore(char *); static char *errmsg_save(void); static void *fill_search_info(const char *, size_t, void *); @@ -142,7 +141,6 @@ static const char *ld_library_path; /* Environment variable for search path */ static char *ld_preload; /* Environment variable for libraries to load first */ static const char *ld_tracing; /* Called from ldd(1) to print libs */ -static const char *ld_prebind; /* Called from prebind(1) to prebind libs */ static Obj_Entry *obj_list; /* Head of linked list of shared objects */ static Obj_Entry **obj_tail; /* Link field of last object in list */ static Obj_Entry **preload_tail; @@ -263,7 +261,6 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) const char *argv0; Obj_Entry *obj; Objlist initlist; - int prebind_disable = 0; ld_index = 0; /* don't use old env cache in case we are resident */ @@ -308,8 +305,6 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) trust = (geteuid() == getuid()) && (getegid() == getgid()); - prebind_disable = _getenv_ld("LD_PREBIND_DISABLE") != NULL; - ld_bind_now = _getenv_ld("LD_BIND_NOW"); if (trust) { ld_debug = _getenv_ld("LD_DEBUG"); @@ -318,14 +313,6 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) } ld_tracing = _getenv_ld("LD_TRACE_LOADED_OBJECTS"); - if (trust) { - ld_prebind = _getenv_ld("LD_PREBIND"); - if (ld_prebind != NULL && *ld_prebind != '\0') { - ld_bind_now = ld_prebind; - prebind_disable = 1; - } - } - if (ld_debug != NULL && *ld_debug != '\0') debug = 1; dbg("%s is initialized, base address = %p", __progname, @@ -426,21 +413,16 @@ resident_skip1: if (ld_resident) /* XXX clean this up! */ goto resident_skip2; - if (prebind_disable || prebind_load(&obj_rtld, obj_main)) { - if (relocate_objects(obj_main, - ld_bind_now != NULL && *ld_bind_now != '\0') == -1) - die(); + if (relocate_objects(obj_main, + ld_bind_now != NULL && *ld_bind_now != '\0') == -1) + die(); - dbg("doing copy relocations"); - if (do_copy_relocations(obj_main) == -1) - die(); - } + dbg("doing copy relocations"); + if (do_copy_relocations(obj_main) == -1) + die(); resident_skip2: - if (ld_prebind != NULL && *ld_prebind != '\0') - exit (prebind_save(&obj_rtld, obj_main)); - if (_getenv_ld("LD_RESIDENT_UNREGISTER_NOW")) { if (exec_sys_unregister(-1) < 0) { dbg("exec_sys_unregister failed %d\n", errno); @@ -717,12 +699,6 @@ digest_dynamic(Obj_Entry *obj) } obj->traced = false; - obj->uniqid = 1; - - if (obj->pltrelsize) - obj->uniqid = elf_uniqid(obj->uniqid, obj->pltrel, obj->pltrelsize); - if (obj->symtab) - obj->uniqid = elf_uniqid(obj->uniqid, obj->symtab, obj->nchains * sizeof(*obj->symtab)); if (plttype == DT_RELA) { obj->pltrela = (const Elf_Rela *) obj->pltrel; @@ -853,45 +829,6 @@ elf_hash(const char *name) return h; } -/* - * Hash function to get an unique ID from an ELF object file - * needs to be fast and small - * - * This one is after Krovetz, Rogaway: The PolyR construction, - * http://www.cs.ucdavis.edu/~rogaway/papers/poly.htm - * - * If called for the first time on a block, pass hash = 1 - */ -static u_int32_t -elf_uniqid(u_int32_t hash, const void *data, size_t len) -{ - const u_int32_t p = 0xfffffffb; /* The largest prime smaller than 2^32 */ - const u_int32_t offset = 5; /* Constant for translating out-of-range words */ - const u_int32_t marker = 0xfffffffa; /* Constant for indicating out-of-range words */ - const u_int32_t key = RTLD_TS; /* Hash key XXX */ - u_int32_t n = len / 4; /* 32 bit blocks */ - u_int32_t remainder = 0; - const u_int32_t *block; - - for (block = data; n; --n, ++block) -uniqid_hash: - if (*block >= p - 1) { /* If word is not in range, then */ - hash = uniqid_hash_block(hash, key, marker); /* Maker indicates out-of-range */ - hash = uniqid_hash_block(hash, key, *block - offset); /* Offset m back into range */ - } else - hash = uniqid_hash_block(hash, key, *block); - - if (len % 4) { /* we got some remainder */ - memcpy(&remainder, block, len % 4); /* copy remaining bytes into 0-padded block */ - block = &remainder; /* set up pointer */ - n = 1; /* one block to process */ - len = 0; /* we've done the remainder */ - goto uniqid_hash; /* run once again */ - } - - return hash; -} - /* * Find the library with the given name, and return its full pathname. * The returned string is dynamically allocated. Generates an error @@ -1096,8 +1033,6 @@ init_rtld(caddr_t mapbase) /* Replace the path with a dynamically allocated copy. */ obj_rtld.path = xstrdup(obj_rtld.path); - obj_rtld.uniqid = RTLD_TS; - r_debug.r_brk = r_debug_state; r_debug.r_state = RT_CONSISTENT; } diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index f75964b3b2..4a9b56d7a0 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -23,7 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/libexec/rtld-elf/rtld.h,v 1.15.2.6 2003/02/20 20:42:46 kan Exp $ - * $DragonFly: src/libexec/rtld-elf/rtld.h,v 1.3 2003/09/18 21:22:56 dillon Exp $ + * $DragonFly: src/libexec/rtld-elf/rtld.h,v 1.4 2004/01/20 21:32:46 dillon Exp $ */ #ifndef RTLD_H /* { */ @@ -161,8 +161,6 @@ typedef struct Struct_Obj_Entry { Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ Objlist dagmembers; /* DAG has these members (%) */ dev_t dev; /* Object's filesystem's device */ - - u_int32_t uniqid; /* Unique ID (hash) of the object */ ino_t ino; /* Object's inode number */ } Obj_Entry; @@ -186,9 +184,6 @@ extern void *xrealloc(void *, size_t); extern char *xstrdup(const char *); extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; -extern int prebind_load (Obj_Entry *, Obj_Entry *); -extern int prebind_save (Obj_Entry *, Obj_Entry *); - /* * Function declarations. */ diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 14c564e51e..de04bfb752 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,6 +1,6 @@ # From: @(#)Makefile 5.20 (Berkeley) 6/12/93 # $FreeBSD: src/usr.sbin/Makefile,v 1.183.2.14 2003/04/16 11:01:51 ru Exp $ -# $DragonFly: src/usr.sbin/Makefile,v 1.5 2004/01/20 18:46:19 dillon Exp $ +# $DragonFly: src/usr.sbin/Makefile,v 1.6 2004/01/20 21:32:34 dillon Exp $ # XXX MISSING: mkproto SUBDIR= IPXrouted \ @@ -66,7 +66,6 @@ SUBDIR= IPXrouted \ pppctl \ pppd \ pppstats \ - prebind \ prefix \ procctl \ pstat \ diff --git a/usr.sbin/prebind/Makefile b/usr.sbin/prebind/Makefile deleted file mode 100644 index e510ff00eb..0000000000 --- a/usr.sbin/prebind/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $DragonFly: src/usr.sbin/prebind/Attic/Makefile,v 1.1 2003/09/18 21:23:06 dillon Exp $ - -PROG= prebind -SRCS= prebind.c -WARNS?= 5 -MAN= prebind.8 - -.include diff --git a/usr.sbin/prebind/prebind.8 b/usr.sbin/prebind/prebind.8 deleted file mode 100644 index fb08b1f82e..0000000000 --- a/usr.sbin/prebind/prebind.8 +++ /dev/null @@ -1,18 +0,0 @@ -.\" $DragonFly: src/usr.sbin/prebind/Attic/prebind.8,v 1.1 2003/09/18 21:23:06 dillon Exp $ -.\" -.Dd May 21, 2003 -.Dt PREBIND 1 -.Os -.Sh NAME -.Nm prebind -.Nd create Relocation Cache prebinding file. -.Sh SYNOPSIS -.Nm -.Ar program ... -.Sh DESCRIPTION -.Sh SEE ALSO -.Xr ld 1 , -.Xr ldd 1 , -.Xr nm 1 , -.Xr rtld 1 -.Sh HISTORY diff --git a/usr.sbin/prebind/prebind.c b/usr.sbin/prebind/prebind.c deleted file mode 100644 index 79c36dd812..0000000000 --- a/usr.sbin/prebind/prebind.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 1993 Paul Kranenburg - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Paul Kranenburg. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $DragonFly: src/usr.sbin/prebind/Attic/prebind.c,v 1.1 2003/09/18 21:23:06 dillon Exp $ - */ - -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -static void -usage(void) -{ - fprintf(stderr, "usage: prebind program ...\n"); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - int rval; - int c; - - while ((c = getopt(argc, argv, "")) != -1) { - switch (c) { - default: - usage(); - /*NOTREACHED*/ - } - } - argc -= optind; - argv += optind; - - if (argc <= 0) { - usage(); - /*NOTREACHED*/ - } - - /* ld-elf.so magic */ - setenv("LD_PREBIND", "yes", 1); - - rval = 0; - for ( ; argc > 0; argc--, argv++) { - int fd; - union { - struct exec aout; - Elf_Ehdr elf; - } hdr; - int n; - int status; - int file_ok; - int is_shlib; - - if ((fd = open(*argv, O_RDONLY, 0)) < 0) { - warn("%s", *argv); - rval |= 1; - continue; - } - if ((n = read(fd, &hdr, sizeof hdr)) == -1) { - warn("%s: can't read program header", *argv); - (void)close(fd); - rval |= 1; - continue; - } - - file_ok = 1; - is_shlib = 0; - if ((size_t)n >= sizeof hdr.aout && !N_BADMAG(hdr.aout)) { - /* a.out file */ - if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC -#if 1 /* Compatibility */ - || hdr.aout.a_entry < __LDPGSZ -#endif - ) { - warnx("%s: not a dynamic executable", *argv); - file_ok = 0; - } - } else if ((size_t)n >= sizeof hdr.elf && IS_ELF(hdr.elf)) { - Elf_Ehdr ehdr; - Elf_Phdr phdr; - int dynamic = 0, i; - - if (lseek(fd, 0, SEEK_SET) == -1 || - read(fd, &ehdr, sizeof ehdr) != sizeof ehdr || - lseek(fd, ehdr.e_phoff, SEEK_SET) == -1 - ) { - warnx("%s: can't read program header", *argv); - file_ok = 0; - } else { - for (i = 0; i < ehdr.e_phnum; i++) { - if (read(fd, &phdr, ehdr.e_phentsize) - != sizeof phdr) { - warnx("%s: can't read program header", - *argv); - file_ok = 0; - break; - } - if (phdr.p_type == PT_DYNAMIC) - dynamic = 1; - } - } - if (!dynamic) { - warnx("%s: not a dynamic executable", *argv); - file_ok = 0; - } else if (hdr.elf.e_type == ET_DYN) { - if (hdr.elf.e_ident[EI_OSABI] & ELFOSABI_FREEBSD) { - is_shlib = 1; - } else { - warnx("%s: not a FreeBSD ELF shared " - "object", *argv); - file_ok = 0; - } - } - } else { - warnx("%s: not a dynamic executable", *argv); - file_ok = 0; - } - (void)close(fd); - if (!file_ok) { - rval |= 1; - continue; - } - - if (is_shlib) { - rval |= 1; - warnx("%s: prebinding not supported on shared libraries.", *argv); - continue; - } - - fflush(stdout); - - switch (fork()) { - case -1: - err(1, "fork"); - break; - default: - if (wait(&status) <= 0) { - warn("wait"); - rval |= 1; - } else if (WIFSIGNALED(status)) { - fprintf(stderr, "%s: signal %d\n", - *argv, WTERMSIG(status)); - rval |= 1; - } else if (WIFEXITED(status) && WEXITSTATUS(status)) { - fprintf(stderr, "%s: exit status %d\n", - *argv, WEXITSTATUS(status)); - rval |= 1; - } else { - } - break; - case 0: - execl(*argv, *argv, (char *)NULL); - warn("%s", *argv); - _exit(1); - } - } - - return rval; -} diff --git a/usr.sbin/resident/resident.c b/usr.sbin/resident/resident.c index a170ea27ea..162d07f83e 100644 --- a/usr.sbin/resident/resident.c +++ b/usr.sbin/resident/resident.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/usr.sbin/resident/resident.c,v 1.2 2004/01/20 21:14:00 dillon Exp $ + * $DragonFly: src/usr.sbin/resident/resident.c,v 1.3 2004/01/20 21:32:43 dillon Exp $ */ #include @@ -183,7 +183,7 @@ main(int argc, char *argv[]) if (is_shlib) { rval |= 1; - warnx("%s: prebinding not supported on shared libraries.", *argv); + warnx("%s: resident not supported on shared libraries.", *argv); continue; } -- 2.41.0