xref: /openbmc/linux/arch/alpha/boot/tools/objstrip.c (revision a4c082f2)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * arch/alpha/boot/tools/objstrip.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Strip the object file headers/trailers from an executable (ELF or ECOFF).
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Copyright (C) 1996 David Mosberger-Tang.
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds /*
101da177e4SLinus Torvalds  * Converts an ECOFF or ELF object file into a bootable file.  The
111da177e4SLinus Torvalds  * object file must be a OMAGIC file (i.e., data and bss follow immediately
121da177e4SLinus Torvalds  * behind the text).  See DEC "Assembly Language Programmer's Guide"
131da177e4SLinus Torvalds  * documentation for details.  The SRM boot process is documented in
141da177e4SLinus Torvalds  * the Alpha AXP Architecture Reference Manual, Second Edition by
151da177e4SLinus Torvalds  * Richard L. Sites and Richard T. Witek.
161da177e4SLinus Torvalds  */
171da177e4SLinus Torvalds #include <stdio.h>
181da177e4SLinus Torvalds #include <string.h>
191da177e4SLinus Torvalds #include <stdlib.h>
201da177e4SLinus Torvalds #include <unistd.h>
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds #include <sys/fcntl.h>
231da177e4SLinus Torvalds #include <sys/stat.h>
241da177e4SLinus Torvalds #include <sys/types.h>
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds #include <linux/a.out.h>
271da177e4SLinus Torvalds #include <linux/coff.h>
281da177e4SLinus Torvalds #include <linux/param.h>
291da177e4SLinus Torvalds #ifdef __ELF__
301da177e4SLinus Torvalds # include <linux/elf.h>
3123430603SHelge Deller # define elfhdr elf64_hdr
3223430603SHelge Deller # define elf_phdr elf64_phdr
3323430603SHelge Deller # define elf_check_arch(x) ((x)->e_machine == EM_ALPHA)
341da177e4SLinus Torvalds #endif
351da177e4SLinus Torvalds 
361da177e4SLinus Torvalds /* bootfile size must be multiple of BLOCK_SIZE: */
371da177e4SLinus Torvalds #define BLOCK_SIZE	512
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds const char * prog_name;
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds 
42ad0cd62aSJosh Triplett static void
usage(void)431da177e4SLinus Torvalds usage (void)
441da177e4SLinus Torvalds {
451da177e4SLinus Torvalds     fprintf(stderr,
461da177e4SLinus Torvalds 	    "usage: %s [-v] -p file primary\n"
471da177e4SLinus Torvalds 	    "       %s [-vb] file [secondary]\n", prog_name, prog_name);
481da177e4SLinus Torvalds     exit(1);
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds int
main(int argc,char * argv[])531da177e4SLinus Torvalds main (int argc, char *argv[])
541da177e4SLinus Torvalds {
551da177e4SLinus Torvalds     size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0;
561da177e4SLinus Torvalds     int fd, ofd, i, j, verbose = 0, primary = 0;
571da177e4SLinus Torvalds     char buf[8192], *inname;
581da177e4SLinus Torvalds     struct exec * aout;		/* includes file & aout header */
591da177e4SLinus Torvalds     long offset;
601da177e4SLinus Torvalds #ifdef __ELF__
611da177e4SLinus Torvalds     struct elfhdr *elf;
621da177e4SLinus Torvalds     struct elf_phdr *elf_phdr;	/* program header */
631da177e4SLinus Torvalds     unsigned long long e_entry;
641da177e4SLinus Torvalds #endif
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds     prog_name = argv[0];
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds     for (i = 1; i < argc && argv[i][0] == '-'; ++i) {
691da177e4SLinus Torvalds 	for (j = 1; argv[i][j]; ++j) {
701da177e4SLinus Torvalds 	    switch (argv[i][j]) {
711da177e4SLinus Torvalds 	      case 'v':
721da177e4SLinus Torvalds 		  verbose = ~verbose;
731da177e4SLinus Torvalds 		  break;
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds 	      case 'b':
761da177e4SLinus Torvalds 		  pad = BLOCK_SIZE;
771da177e4SLinus Torvalds 		  break;
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds 	      case 'p':
801da177e4SLinus Torvalds 		  primary = 1;		/* make primary bootblock */
811da177e4SLinus Torvalds 		  break;
821da177e4SLinus Torvalds 	    }
831da177e4SLinus Torvalds 	}
841da177e4SLinus Torvalds     }
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds     if (i >= argc) {
871da177e4SLinus Torvalds 	usage();
881da177e4SLinus Torvalds     }
891da177e4SLinus Torvalds     inname = argv[i++];
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds     fd = open(inname, O_RDONLY);
921da177e4SLinus Torvalds     if (fd == -1) {
931da177e4SLinus Torvalds 	perror("open");
941da177e4SLinus Torvalds 	exit(1);
951da177e4SLinus Torvalds     }
961da177e4SLinus Torvalds 
971da177e4SLinus Torvalds     ofd = 1;
981da177e4SLinus Torvalds     if (i < argc) {
991da177e4SLinus Torvalds 	ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666);
10027258e44SRoel Kluin 	if (ofd == -1) {
1011da177e4SLinus Torvalds 	    perror("open");
1021da177e4SLinus Torvalds 	    exit(1);
1031da177e4SLinus Torvalds 	}
1041da177e4SLinus Torvalds     }
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds     if (primary) {
1071da177e4SLinus Torvalds 	/* generate bootblock for primary loader */
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 	unsigned long bb[64], sum = 0;
1101da177e4SLinus Torvalds 	struct stat st;
1111da177e4SLinus Torvalds 	off_t size;
1121da177e4SLinus Torvalds 	int i;
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	if (ofd == 1) {
1151da177e4SLinus Torvalds 	    usage();
1161da177e4SLinus Torvalds 	}
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds 	if (fstat(fd, &st) == -1) {
1191da177e4SLinus Torvalds 	    perror("fstat");
1201da177e4SLinus Torvalds 	    exit(1);
1211da177e4SLinus Torvalds 	}
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds 	size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
1241da177e4SLinus Torvalds 	memset(bb, 0, sizeof(bb));
1251da177e4SLinus Torvalds 	strcpy((char *) bb, "Linux SRM bootblock");
1261da177e4SLinus Torvalds 	bb[60] = size / BLOCK_SIZE;	/* count */
1271da177e4SLinus Torvalds 	bb[61] = 1;			/* starting sector # */
1281da177e4SLinus Torvalds 	bb[62] = 0;			/* flags---must be 0 */
1291da177e4SLinus Torvalds 	for (i = 0; i < 63; ++i) {
1301da177e4SLinus Torvalds 	    sum += bb[i];
1311da177e4SLinus Torvalds 	}
1321da177e4SLinus Torvalds 	bb[63] = sum;
1331da177e4SLinus Torvalds 	if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) {
1341da177e4SLinus Torvalds 	    perror("boot-block write");
1351da177e4SLinus Torvalds 	    exit(1);
1361da177e4SLinus Torvalds 	}
1371da177e4SLinus Torvalds 	printf("%lu\n", size);
1381da177e4SLinus Torvalds 	return 0;
1391da177e4SLinus Torvalds     }
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds     /* read and inspect exec header: */
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds     if (read(fd, buf, sizeof(buf)) < 0) {
1441da177e4SLinus Torvalds 	perror("read");
1451da177e4SLinus Torvalds 	exit(1);
1461da177e4SLinus Torvalds     }
1471da177e4SLinus Torvalds 
1481da177e4SLinus Torvalds #ifdef __ELF__
1491da177e4SLinus Torvalds     elf = (struct elfhdr *) buf;
1501da177e4SLinus Torvalds 
151*a4c082f2SAl Viro     if (memcmp(&elf->e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) {
1521da177e4SLinus Torvalds 	if (elf->e_type != ET_EXEC) {
1531da177e4SLinus Torvalds 	    fprintf(stderr, "%s: %s is not an ELF executable\n",
1541da177e4SLinus Torvalds 		    prog_name, inname);
1551da177e4SLinus Torvalds 	    exit(1);
1561da177e4SLinus Torvalds 	}
1571da177e4SLinus Torvalds 	if (!elf_check_arch(elf)) {
1581da177e4SLinus Torvalds 	    fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n",
1591da177e4SLinus Torvalds 		    prog_name, elf->e_machine);
1601da177e4SLinus Torvalds 	    exit(1);
1611da177e4SLinus Torvalds 	}
1621da177e4SLinus Torvalds 	if (elf->e_phnum != 1) {
1631da177e4SLinus Torvalds 	    fprintf(stderr,
1641da177e4SLinus Torvalds 		    "%s: %d program headers (forgot to link with -N?)\n",
1651da177e4SLinus Torvalds 		    prog_name, elf->e_phnum);
1661da177e4SLinus Torvalds 	}
1671da177e4SLinus Torvalds 
1681da177e4SLinus Torvalds 	e_entry = elf->e_entry;
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds 	lseek(fd, elf->e_phoff, SEEK_SET);
1711da177e4SLinus Torvalds 	if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) {
1721da177e4SLinus Torvalds 	    perror("read");
1731da177e4SLinus Torvalds 	    exit(1);
1741da177e4SLinus Torvalds 	}
1751da177e4SLinus Torvalds 
1761da177e4SLinus Torvalds 	elf_phdr = (struct elf_phdr *) buf;
1771da177e4SLinus Torvalds 	offset	 = elf_phdr->p_offset;
1781da177e4SLinus Torvalds 	mem_size = elf_phdr->p_memsz;
1791da177e4SLinus Torvalds 	fil_size = elf_phdr->p_filesz;
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds 	/* work around ELF bug: */
1821da177e4SLinus Torvalds 	if (elf_phdr->p_vaddr < e_entry) {
1831da177e4SLinus Torvalds 	    unsigned long delta = e_entry - elf_phdr->p_vaddr;
1841da177e4SLinus Torvalds 	    offset   += delta;
1851da177e4SLinus Torvalds 	    mem_size -= delta;
1861da177e4SLinus Torvalds 	    fil_size -= delta;
1871da177e4SLinus Torvalds 	    elf_phdr->p_vaddr += delta;
1881da177e4SLinus Torvalds 	}
1891da177e4SLinus Torvalds 
1901da177e4SLinus Torvalds 	if (verbose) {
1911da177e4SLinus Torvalds 	    fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
1921da177e4SLinus Torvalds 		    prog_name, (long) elf_phdr->p_vaddr,
1931da177e4SLinus Torvalds 		    elf_phdr->p_vaddr + fil_size, offset);
1941da177e4SLinus Torvalds 	}
1951da177e4SLinus Torvalds     } else
1961da177e4SLinus Torvalds #endif
1971da177e4SLinus Torvalds     {
1981da177e4SLinus Torvalds 	aout = (struct exec *) buf;
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 	if (!(aout->fh.f_flags & COFF_F_EXEC)) {
2011da177e4SLinus Torvalds 	    fprintf(stderr, "%s: %s is not in executable format\n",
2021da177e4SLinus Torvalds 		    prog_name, inname);
2031da177e4SLinus Torvalds 	    exit(1);
2041da177e4SLinus Torvalds 	}
2051da177e4SLinus Torvalds 
2061da177e4SLinus Torvalds 	if (aout->fh.f_opthdr != sizeof(aout->ah)) {
2071da177e4SLinus Torvalds 	    fprintf(stderr, "%s: %s has unexpected optional header size\n",
2081da177e4SLinus Torvalds 		    prog_name, inname);
2091da177e4SLinus Torvalds 	    exit(1);
2101da177e4SLinus Torvalds 	}
2111da177e4SLinus Torvalds 
2121da177e4SLinus Torvalds 	if (N_MAGIC(*aout) != OMAGIC) {
2131da177e4SLinus Torvalds 	    fprintf(stderr, "%s: %s is not an OMAGIC file\n",
2141da177e4SLinus Torvalds 		    prog_name, inname);
2151da177e4SLinus Torvalds 	    exit(1);
2161da177e4SLinus Torvalds 	}
2171da177e4SLinus Torvalds 	offset = N_TXTOFF(*aout);
2181da177e4SLinus Torvalds 	fil_size = aout->ah.tsize + aout->ah.dsize;
2191da177e4SLinus Torvalds 	mem_size = fil_size + aout->ah.bsize;
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds 	if (verbose) {
2221da177e4SLinus Torvalds 	    fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
2231da177e4SLinus Torvalds 		    prog_name, aout->ah.text_start,
2241da177e4SLinus Torvalds 		    aout->ah.text_start + fil_size, offset);
2251da177e4SLinus Torvalds 	}
2261da177e4SLinus Torvalds     }
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds     if (lseek(fd, offset, SEEK_SET) != offset) {
2291da177e4SLinus Torvalds 	perror("lseek");
2301da177e4SLinus Torvalds 	exit(1);
2311da177e4SLinus Torvalds     }
2321da177e4SLinus Torvalds 
2331da177e4SLinus Torvalds     if (verbose) {
2341da177e4SLinus Torvalds 	fprintf(stderr, "%s: copying %lu byte from %s\n",
2351da177e4SLinus Torvalds 		prog_name, (unsigned long) fil_size, inname);
2361da177e4SLinus Torvalds     }
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds     tocopy = fil_size;
2391da177e4SLinus Torvalds     while (tocopy > 0) {
2401da177e4SLinus Torvalds 	n = tocopy;
2411da177e4SLinus Torvalds 	if (n > sizeof(buf)) {
2421da177e4SLinus Torvalds 	    n = sizeof(buf);
2431da177e4SLinus Torvalds 	}
2441da177e4SLinus Torvalds 	tocopy -= n;
2451da177e4SLinus Torvalds 	if ((size_t) read(fd, buf, n) != n) {
2461da177e4SLinus Torvalds 	    perror("read");
2471da177e4SLinus Torvalds 	    exit(1);
2481da177e4SLinus Torvalds 	}
2491da177e4SLinus Torvalds 	do {
2501da177e4SLinus Torvalds 	    nwritten = write(ofd, buf, n);
2511da177e4SLinus Torvalds 	    if ((ssize_t) nwritten == -1) {
2521da177e4SLinus Torvalds 		perror("write");
2531da177e4SLinus Torvalds 		exit(1);
2541da177e4SLinus Torvalds 	    }
2551da177e4SLinus Torvalds 	    n -= nwritten;
2561da177e4SLinus Torvalds 	} while (n > 0);
2571da177e4SLinus Torvalds     }
2581da177e4SLinus Torvalds 
2591da177e4SLinus Torvalds     if (pad) {
2601da177e4SLinus Torvalds 	mem_size = ((mem_size + pad - 1) / pad) * pad;
2611da177e4SLinus Torvalds     }
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds     tocopy = mem_size - fil_size;
2641da177e4SLinus Torvalds     if (tocopy > 0) {
2651da177e4SLinus Torvalds 	fprintf(stderr,
2661da177e4SLinus Torvalds 		"%s: zero-filling bss and aligning to %lu with %lu bytes\n",
2671da177e4SLinus Torvalds 		prog_name, pad, (unsigned long) tocopy);
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	memset(buf, 0x00, sizeof(buf));
2701da177e4SLinus Torvalds 	do {
2711da177e4SLinus Torvalds 	    n = tocopy;
2721da177e4SLinus Torvalds 	    if (n > sizeof(buf)) {
2731da177e4SLinus Torvalds 		n = sizeof(buf);
2741da177e4SLinus Torvalds 	    }
2751da177e4SLinus Torvalds 	    nwritten = write(ofd, buf, n);
2761da177e4SLinus Torvalds 	    if ((ssize_t) nwritten == -1) {
2771da177e4SLinus Torvalds 		perror("write");
2781da177e4SLinus Torvalds 		exit(1);
2791da177e4SLinus Torvalds 	    }
2801da177e4SLinus Torvalds 	    tocopy -= nwritten;
2811da177e4SLinus Torvalds 	} while (tocopy > 0);
2821da177e4SLinus Torvalds     }
2831da177e4SLinus Torvalds     return 0;
2841da177e4SLinus Torvalds }
285