Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * arch/alpha/boot/tools/objstrip.c
0004  *
0005  * Strip the object file headers/trailers from an executable (ELF or ECOFF).
0006  *
0007  * Copyright (C) 1996 David Mosberger-Tang.
0008  */
0009 /*
0010  * Converts an ECOFF or ELF object file into a bootable file.  The
0011  * object file must be a OMAGIC file (i.e., data and bss follow immediately
0012  * behind the text).  See DEC "Assembly Language Programmer's Guide"
0013  * documentation for details.  The SRM boot process is documented in
0014  * the Alpha AXP Architecture Reference Manual, Second Edition by
0015  * Richard L. Sites and Richard T. Witek.
0016  */
0017 #include <stdio.h>
0018 #include <string.h>
0019 #include <stdlib.h>
0020 #include <unistd.h>
0021 
0022 #include <sys/fcntl.h>
0023 #include <sys/stat.h>
0024 #include <sys/types.h>
0025 
0026 #include <linux/a.out.h>
0027 #include <linux/coff.h>
0028 #include <linux/param.h>
0029 #ifdef __ELF__
0030 # include <linux/elf.h>
0031 # define elfhdr elf64_hdr
0032 # define elf_phdr elf64_phdr
0033 # define elf_check_arch(x) ((x)->e_machine == EM_ALPHA)
0034 #endif
0035 
0036 /* bootfile size must be multiple of BLOCK_SIZE: */
0037 #define BLOCK_SIZE  512
0038 
0039 const char * prog_name;
0040 
0041 
0042 static void
0043 usage (void)
0044 {
0045     fprintf(stderr,
0046         "usage: %s [-v] -p file primary\n"
0047         "       %s [-vb] file [secondary]\n", prog_name, prog_name);
0048     exit(1);
0049 }
0050 
0051 
0052 int
0053 main (int argc, char *argv[])
0054 {
0055     size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0;
0056     int fd, ofd, i, j, verbose = 0, primary = 0;
0057     char buf[8192], *inname;
0058     struct exec * aout;     /* includes file & aout header */
0059     long offset;
0060 #ifdef __ELF__
0061     struct elfhdr *elf;
0062     struct elf_phdr *elf_phdr;  /* program header */
0063     unsigned long long e_entry;
0064 #endif
0065 
0066     prog_name = argv[0];
0067 
0068     for (i = 1; i < argc && argv[i][0] == '-'; ++i) {
0069     for (j = 1; argv[i][j]; ++j) {
0070         switch (argv[i][j]) {
0071           case 'v':
0072           verbose = ~verbose;
0073           break;
0074 
0075           case 'b':
0076           pad = BLOCK_SIZE;
0077           break;
0078 
0079           case 'p':
0080           primary = 1;      /* make primary bootblock */
0081           break;
0082         }
0083     }
0084     }
0085 
0086     if (i >= argc) {
0087     usage();
0088     }
0089     inname = argv[i++];
0090 
0091     fd = open(inname, O_RDONLY);
0092     if (fd == -1) {
0093     perror("open");
0094     exit(1);
0095     }
0096 
0097     ofd = 1;
0098     if (i < argc) {
0099     ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666);
0100     if (ofd == -1) {
0101         perror("open");
0102         exit(1);
0103     }
0104     }
0105 
0106     if (primary) {
0107     /* generate bootblock for primary loader */
0108     
0109     unsigned long bb[64], sum = 0;
0110     struct stat st;
0111     off_t size;
0112     int i;
0113 
0114     if (ofd == 1) {
0115         usage();
0116     }
0117 
0118     if (fstat(fd, &st) == -1) {
0119         perror("fstat");
0120         exit(1);
0121     }
0122 
0123     size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
0124     memset(bb, 0, sizeof(bb));
0125     strcpy((char *) bb, "Linux SRM bootblock");
0126     bb[60] = size / BLOCK_SIZE; /* count */
0127     bb[61] = 1;         /* starting sector # */
0128     bb[62] = 0;         /* flags---must be 0 */
0129     for (i = 0; i < 63; ++i) {
0130         sum += bb[i];
0131     }
0132     bb[63] = sum;
0133     if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) {
0134         perror("boot-block write");
0135         exit(1);
0136     }
0137     printf("%lu\n", size);
0138     return 0;
0139     }
0140 
0141     /* read and inspect exec header: */
0142 
0143     if (read(fd, buf, sizeof(buf)) < 0) {
0144     perror("read");
0145     exit(1);
0146     }
0147 
0148 #ifdef __ELF__
0149     elf = (struct elfhdr *) buf;
0150 
0151     if (elf->e_ident[0] == 0x7f && str_has_prefix((char *)elf->e_ident + 1, "ELF")) {
0152     if (elf->e_type != ET_EXEC) {
0153         fprintf(stderr, "%s: %s is not an ELF executable\n",
0154             prog_name, inname);
0155         exit(1);
0156     }
0157     if (!elf_check_arch(elf)) {
0158         fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n",
0159             prog_name, elf->e_machine);
0160         exit(1);
0161     }
0162     if (elf->e_phnum != 1) {
0163         fprintf(stderr,
0164             "%s: %d program headers (forgot to link with -N?)\n",
0165             prog_name, elf->e_phnum);
0166     }
0167 
0168     e_entry = elf->e_entry;
0169 
0170     lseek(fd, elf->e_phoff, SEEK_SET);
0171     if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) {
0172         perror("read");
0173         exit(1);
0174     }
0175 
0176     elf_phdr = (struct elf_phdr *) buf;
0177     offset   = elf_phdr->p_offset;
0178     mem_size = elf_phdr->p_memsz;
0179     fil_size = elf_phdr->p_filesz;
0180 
0181     /* work around ELF bug: */
0182     if (elf_phdr->p_vaddr < e_entry) {
0183         unsigned long delta = e_entry - elf_phdr->p_vaddr;
0184         offset   += delta;
0185         mem_size -= delta;
0186         fil_size -= delta;
0187         elf_phdr->p_vaddr += delta;
0188     }
0189 
0190     if (verbose) {
0191         fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
0192             prog_name, (long) elf_phdr->p_vaddr,
0193             elf_phdr->p_vaddr + fil_size, offset);
0194     }
0195     } else
0196 #endif
0197     {
0198     aout = (struct exec *) buf;
0199 
0200     if (!(aout->fh.f_flags & COFF_F_EXEC)) {
0201         fprintf(stderr, "%s: %s is not in executable format\n",
0202             prog_name, inname);
0203         exit(1);
0204     }
0205 
0206     if (aout->fh.f_opthdr != sizeof(aout->ah)) {
0207         fprintf(stderr, "%s: %s has unexpected optional header size\n",
0208             prog_name, inname);
0209         exit(1);
0210     }
0211 
0212     if (N_MAGIC(*aout) != OMAGIC) {
0213         fprintf(stderr, "%s: %s is not an OMAGIC file\n",
0214             prog_name, inname);
0215         exit(1);
0216     }
0217     offset = N_TXTOFF(*aout);
0218     fil_size = aout->ah.tsize + aout->ah.dsize;
0219     mem_size = fil_size + aout->ah.bsize;
0220 
0221     if (verbose) {
0222         fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
0223             prog_name, aout->ah.text_start,
0224             aout->ah.text_start + fil_size, offset);
0225     }
0226     }
0227 
0228     if (lseek(fd, offset, SEEK_SET) != offset) {
0229     perror("lseek");
0230     exit(1);
0231     }
0232 
0233     if (verbose) {
0234     fprintf(stderr, "%s: copying %lu byte from %s\n",
0235         prog_name, (unsigned long) fil_size, inname);
0236     }
0237 
0238     tocopy = fil_size;
0239     while (tocopy > 0) {
0240     n = tocopy;
0241     if (n > sizeof(buf)) {
0242         n = sizeof(buf);
0243     }
0244     tocopy -= n;
0245     if ((size_t) read(fd, buf, n) != n) {
0246         perror("read");
0247         exit(1);
0248     }
0249     do {
0250         nwritten = write(ofd, buf, n);
0251         if ((ssize_t) nwritten == -1) {
0252         perror("write");
0253         exit(1);
0254         }
0255         n -= nwritten;
0256     } while (n > 0);
0257     }
0258 
0259     if (pad) {
0260     mem_size = ((mem_size + pad - 1) / pad) * pad;
0261     }
0262 
0263     tocopy = mem_size - fil_size;
0264     if (tocopy > 0) {
0265     fprintf(stderr,
0266         "%s: zero-filling bss and aligning to %lu with %lu bytes\n",
0267         prog_name, pad, (unsigned long) tocopy);
0268 
0269     memset(buf, 0x00, sizeof(buf));
0270     do {
0271         n = tocopy;
0272         if (n > sizeof(buf)) {
0273         n = sizeof(buf);
0274         }
0275         nwritten = write(ofd, buf, n);
0276         if ((ssize_t) nwritten == -1) {
0277         perror("write");
0278         exit(1);
0279         }
0280         tocopy -= nwritten;
0281     } while (tocopy > 0);
0282     }
0283     return 0;
0284 }