From 3c05d0baf322f9f47b0894379509f5e3c67e492b Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Sat, 28 Feb 2015 19:14:17 +0000 Subject: [PATCH] added program to output the elf type of a file --- Makefile | 8 ++- elf/elftype.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 elf/elftype.c diff --git a/Makefile b/Makefile index 8f84c9d..fb3494e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,9 @@ -install: +CFLAGS=-Wall -std=c99 + +elftype: elf/elftype.c + $(CC) $(CFLAGS) -o $@ $+ + +install: elftype install -D zpm $(DESTDIR)/bin/zpm install -D zpm-note $(DESTDIR)/bin/zpm-note install -D zpm-sequence $(DESTDIR)/bin/zpm-sequence @@ -6,4 +11,5 @@ install: install -d -m2770 -o root -g adm $(DESTDIR)/var/lib/admin/notes install -d -m2770 -o root -g adm $(DESTDIR)/var/lib/admin/notes/open install -d -m2770 -o root -g adm $(DESTDIR)/var/lib/admin/notes/ack + install -D elftype $(DESTDIR)/usr/sbin/elftype #SPOOL=$(DESTDIR)/var/lib/admin/notes ./zpm-sequence -c notes diff --git a/elf/elftype.c b/elf/elftype.c new file mode 100644 index 0000000..6dece5a --- /dev/null +++ b/elf/elftype.c @@ -0,0 +1,185 @@ +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include +#include + +#include +#include +#include + +#define RELOCATABLE 0x1 +#define EXECUTABLE 0x2 +#define DYNAMIC 0x4 +#define CORE 0x8 +#define SYMLINKS 0x10 + +int readline(FILE *f, char *fn); +int checkfile(char *fn, unsigned int want, int perr, int quiet); + +int errors = 0; +int zeroterm = 0; + +int main(int ac, char **av) { + int option; + unsigned int want = 0; + int quiet = 0; + int perr = 0; + FILE *list = 0; + char fn[PATH_MAX]; + + while ((option = getopt(ac, av, "redclaqp0f:")) != -1) { + switch (option) { + case 'r': want |= RELOCATABLE; break; + case 'e': want |= EXECUTABLE; break; + case 'd': want |= DYNAMIC; break; + case 'c': want |= CORE; break; + case 'l': want |= SYMLINKS; break; + case 'a': want = (RELOCATABLE|EXECUTABLE|DYNAMIC|CORE); break; + case 'q': quiet++; break; + case 'p': perr++; break; + case '0': zeroterm = 1; break; + case 'f': + if (optarg[0] == '-' && optarg[1] == 0) { + list = stdin; + } else { + list = fopen(optarg, "r"); + } + break; + default: + exit(1); + break; + } + } + if (list) { + quiet = 2; + perr = 0; + while (readline(list, fn)) { + fprintf(stderr, "checking %s\n", fn); + if (checkfile(fn, want,perr,quiet)) { + printf("%s\n", fn); + } + } + } else { + fprintf(stderr, "checking %s\n", av[optind]); + return !checkfile(av[optind], want,perr,quiet); + } + return errors ? 1 : 0; +} + +int readline(FILE *f, char *fn) { + int ch; + int i = 0; + + do { + ch = fgetc(f); + switch (ch) { + case EOF: break; + case 0: + if (i == 0) continue; + break; + case '\n': + if (!zeroterm) { + if (i == 0) continue; + break; + } + default: + fn[i++] = ch; + continue; + } + if (i >= PATH_MAX) { + /* TODO print an error */ + return 0; + } + fn[i] = 0; + return i; + } while (ch != EOF); + return 0; +} + +int checkfile(char *fn, unsigned int want, int perr, int quiet) { + Elf64_Ehdr hdr; + int fd, bytes; + int endian = 0; + struct stat st; + + if (want & SYMLINKS) { + lstat(fn, &st); + } else { + stat(fn, &st); + } + if (!S_ISREG(st.st_mode)) { + return 0; + } + + fd = open(fn, O_RDONLY); + if (fd == -1) { + perror("elfcheck"); + errors++; + return 0; + } + bytes = read(fd, &hdr, sizeof hdr); + if (bytes < sizeof hdr) { + if (perr) fprintf(stderr, "could not read full elf header (wanted %zu got %d bytes)\n", sizeof hdr, bytes); + close(fd); + return 0; + } + if (hdr.e_ident[EI_MAG0] != ELFMAG0 + || hdr.e_ident[EI_MAG1] != ELFMAG1 + || hdr.e_ident[EI_MAG2] != ELFMAG2 + || hdr.e_ident[EI_MAG3] != ELFMAG3 + ) { + if (perr) fprintf(stderr, "elf header magic wrong\n"); + close(fd); + return 0; + } + switch (hdr.e_ident[EI_CLASS]) { + case ELFCLASS64: + case ELFCLASS32: + case ELFCLASSNONE: + break; + default: + if (perr) fprintf(stderr, "elf header unknown class\n"); + close(fd); + return 0; + } + + endian = hdr.e_ident[EI_DATA]; + switch (endian) { + case ELFDATA2LSB: break; + case ELFDATA2MSB: break; + /* TODO swap endian if needed */ + default: + if (perr) fprintf(stderr, "elf header unknown endian\n"); + close(fd); + return 0; + } + + switch (hdr.e_type) { + case ET_REL: + if (!quiet) printf("relocatable\n"); + close(fd); + return want & RELOCATABLE ? 1 : 0; + case ET_EXEC: + if (!quiet) printf("executable\n"); + close(fd); + return want & EXECUTABLE ? 1 : 0; + case ET_DYN: + if (!quiet) printf("dynamic\n"); + close(fd); + return want & DYNAMIC ? 1 : 0; + case ET_CORE: + if (!quiet) printf("core\n"); + close(fd); + return want & CORE ? 1 : 0; + case ET_NONE: + default: + if (perr) fprintf(stderr, "unknown type\n"); + close(fd); + return 0; + } + + close(fd); + return 0; +} -- 2.40.0