From: Hyogeol L. <hyo...@gm...> - 2008-07-29 12:27:11
|
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 Hi, I wrote patch for brandelf(1) to use libelf. Would you review this patch? patch against usr.bin/brandelf in 7-STABLE. You can get this patch also in http://home.megapass.net/~supr07/brandelf.patch Best Regards, Hyogeol Lee diff -urN usr.bin/brandelf.org/Makefile usr.bin/brandelf/Makefile - --- usr.bin/brandelf.org/Makefile 2003-06-15 04:32:51.000000000 +0900 +++ usr.bin/brandelf/Makefile 2008-07-29 19:44:24.000000000 +0900 @@ -1,5 +1,6 @@ ~ # $FreeBSD: src/usr.bin/brandelf/Makefile,v 1.7 2003/06/14 19:32:51 obrien Exp $ ~ PROG= brandelf +LDADD= -lelf ~ .include <bsd.prog.mk> diff -urN usr.bin/brandelf.org/brandelf.c usr.bin/brandelf/brandelf.c - --- usr.bin/brandelf.org/brandelf.c 2005-05-21 18:55:04.000000000 +0900 +++ usr.bin/brandelf/brandelf.c 2008-07-29 21:09:38.000000000 +0900 @@ -1,4 +1,5 @@ ~ /*- + * Copyright (c) 2008 Hyogeol Lee ~ * Copyright (c) 2000, 2001 David O'Brien ~ * Copyright (c) 1996 S�ren Schmidt ~ * All rights reserved. @@ -31,10 +32,12 @@ ~ __FBSDID("$FreeBSD: src/usr.bin/brandelf/brandelf.c,v 1.25 2005/05/21 09:55:04 ru Exp $"); ~ #include <sys/types.h> - -#include <sys/elf_common.h> +#include <sys/stat.h> ~ #include <sys/errno.h> ~ #include <err.h> ~ #include <fcntl.h> +#include <gelf.h> +#include <libelf.h> ~ #include <stdio.h> ~ #include <stdlib.h> ~ #include <string.h> @@ -42,6 +45,8 @@ ~ static int elftype(const char *); ~ static const char *iselftype(int); +static int isfile(const char *); +static Elf *openelf(int, const char *); ~ static void printelftypes(void); ~ static void usage(void); @@ -51,20 +56,26 @@ ~ }; ~ /* XXX - any more types? */ ~ static struct ELFtypes elftypes[] = { - - { "FreeBSD", ELFOSABI_FREEBSD }, + { "NetBSD", ELFOSABI_NETBSD}, ~ { "Linux", ELFOSABI_LINUX }, ~ { "Solaris", ELFOSABI_SOLARIS }, + { "FreeBSD", ELFOSABI_FREEBSD }, + { "OpenBSD", ELFOSABI_OPENBSD }, ~ { "SVR4", ELFOSABI_SYSV } ~ }; ~ int ~ main(int argc, char **argv) ~ { - - + GElf_Ehdr ehdr; + Elf *elf; ~ const char *strtype = "FreeBSD"; ~ int type = ELFOSABI_FREEBSD; ~ int retval = 0; - - int ch, change = 0, verbose = 0, force = 0, listed = 0; + int ch, change = 0, verbose = 0, force = 0, listed = 0, e_err = 0; + + if (elf_version(EV_CURRENT) == EV_NONE) + errx(1, "elf_version error"); ~ while ((ch = getopt(argc, argv, "f:lt:v")) != -1) ~ switch (ch) { @@ -114,29 +125,36 @@ ~ while (argc) { ~ int fd; - - char buffer[EI_NIDENT]; - - if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) { + if (isfile(argv[0]) != 0) { + retval = 1; + goto fail2; + } + if ((fd = open(argv[0], change || force ? + O_RDWR : O_RDONLY, 0)) < 0) { ~ warn("error opening file %s", argv[0]); ~ retval = 1; ~ goto fail; ~ } - - if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) { - - warnx("file '%s' too short", argv[0]); + if ((elf = openelf(fd, argv[0])) == NULL) { ~ retval = 1; ~ goto fail; ~ } - - if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 || - - buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) { - - warnx("file '%s' is not ELF format", argv[0]); + if (gelf_getehdr(elf, &ehdr) == NULL) { + if ((e_err = elf_errno()) != 0) + warnx("gelf_getehdr : %s", + elf_errmsg(e_err)); + else + warnx("gelf_getehdr error"); ~ retval = 1; ~ goto fail; ~ } ~ if (!change && !force) { ~ fprintf(stdout, - - "File '%s' is of brand '%s' (%u).\n", - - argv[0], iselftype(buffer[EI_OSABI]), - - buffer[EI_OSABI]); + "File '%s' is of brand '%s' (%u).\n", + argv[0], iselftype(ehdr.e_ident[EI_OSABI]), + ehdr.e_ident[EI_OSABI]); + ~ if (!iselftype(type)) { ~ warnx("ELF ABI Brand '%u' is unknown", ~ type); @@ -144,21 +162,39 @@ ~ } ~ } ~ else { - - buffer[EI_OSABI] = type; - - lseek(fd, 0, SEEK_SET); - - if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) { - - warn("error writing %s %d", argv[0], fd); + ehdr.e_ident[EI_OSABI] = type; + if (gelf_update_ehdr(elf, &ehdr) == 0) { + if ((e_err = elf_errno()) != 0) + warnx("gelf_update_ehdr error : %s", + elf_errmsg(e_err)); + else + warnx("gelf_update_ehdr error"); + retval = 1; + goto fail; + } + + if (elf_update(elf, ELF_C_WRITE) == -1) { + if ((e_err = elf_errno()) != 0) + warnx("elf_update error : %s", + elf_errmsg(e_err)); + else + warnx("elf_update error"); ~ retval = 1; ~ goto fail; ~ } ~ } ~ fail: - - close(fd); + elf_end(elf); + if (close(fd) == -1) { + warnx("%s: close error", argv[0]); + retval = 1; + } +fail2: ~ argc--; ~ argv++; ~ } - - return retval; + return (retval); ~ } ~ static void @@ -178,8 +214,36 @@ ~ elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); ~ elfwalk++) ~ if (etype == elftypes[elfwalk].value) - - return elftypes[elfwalk].str; - - return 0; + return (elftypes[elfwalk].str); + return (0); +} + +/* Return 0 if path is regular file. */ +static int +isfile(const char *path) +{ + struct stat sb; + + if (path == NULL) + return (1); + + errno = 0; + if (stat(path, &sb) != 0) { + if (errno == ENOENT) + warnx("'%s': No such file", path); + else + warn("'%s'", path); + + return (1); + } + + if (!S_ISLNK(sb.st_mode) && !S_ISREG(sb.st_mode)) { + warnx("Warning: '%s' is not an ordinary file", path); + + return (1); + } + + return (0); ~ } ~ static int @@ -191,8 +255,51 @@ ~ elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); ~ elfwalk++) ~ if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) - - return elftypes[elfwalk].value; - - return -1; + return (elftypes[elfwalk].value); + return (-1); +} + +static Elf * +openelf(int fd, const char *name) +{ + Elf *elf; + Elf_Cmd cmd; + Elf_Kind kind; + int e_err = 0; + + if (fd < 0) + return (NULL); + + /* Archive does not support write mode. So try ar type by read cmd. */ + cmd = ELF_C_READ; +begin: + if ((elf = elf_begin(fd, cmd, (Elf *) NULL)) == NULL) { + if ((e_err = elf_errno()) != 0) + warnx("elf_begin error : %s", + elf_errmsg(e_err)); + else + warnx("elf_begin error"); + + return (NULL); + } + + if ((kind = elf_kind(elf)) != ELF_K_ELF) { + if (kind == ELF_K_AR) + warnx("file '%s' is an archive.", name); + else + warnx("file '%s' is not ELF format", name); + + return (NULL); + } + + if (cmd == ELF_C_RDWR) + return (elf); + + elf_end(elf); + + cmd = ELF_C_RDWR; + + goto begin; ~ } ~ static void -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (FreeBSD) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEAREKAAYFAkiPDJMACgkQ1D7/GiH6QSFdHwCfazW6XekCAaXryWLXuw0Q74qx GuAAn3IKCb31THR2zH80tQbZ1PPVZHqQ =jEJ/ -----END PGP SIGNATURE----- |