linux/arch/alpha/boot/tools/objstrip.c
<<
>>
Prefs
   1/*
   2 * arch/alpha/boot/tools/objstrip.c
   3 *
   4 * Strip the object file headers/trailers from an executable (ELF or ECOFF).
   5 *
   6 * Copyright (C) 1996 David Mosberger-Tang.
   7 */
   8/*
   9 * Converts an ECOFF or ELF object file into a bootable file.  The
  10 * object file must be a OMAGIC file (i.e., data and bss follow immediately
  11 * behind the text).  See DEC "Assembly Language Programmer's Guide"
  12 * documentation for details.  The SRM boot process is documented in
  13 * the Alpha AXP Architecture Reference Manual, Second Edition by
  14 * Richard L. Sites and Richard T. Witek.
  15 */
  16#include <stdio.h>
  17#include <string.h>
  18#include <stdlib.h>
  19#include <unistd.h>
  20
  21#include <sys/fcntl.h>
  22#include <sys/stat.h>
  23#include <sys/types.h>
  24
  25#include <linux/a.out.h>
  26#include <linux/coff.h>
  27#include <linux/param.h>
  28#ifdef __ELF__
  29# include <linux/elf.h>
  30#endif
  31
  32/* bootfile size must be multiple of BLOCK_SIZE: */
  33#define BLOCK_SIZE      512
  34
  35const char * prog_name;
  36
  37
  38static void
  39usage (void)
  40{
  41    fprintf(stderr,
  42            "usage: %s [-v] -p file primary\n"
  43            "       %s [-vb] file [secondary]\n", prog_name, prog_name);
  44    exit(1);
  45}
  46
  47
  48int
  49main (int argc, char *argv[])
  50{
  51    size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0;
  52    int fd, ofd, i, j, verbose = 0, primary = 0;
  53    char buf[8192], *inname;
  54    struct exec * aout;         /* includes file & aout header */
  55    long offset;
  56#ifdef __ELF__
  57    struct elfhdr *elf;
  58    struct elf_phdr *elf_phdr;  /* program header */
  59    unsigned long long e_entry;
  60#endif
  61
  62    prog_name = argv[0];
  63
  64    for (i = 1; i < argc && argv[i][0] == '-'; ++i) {
  65        for (j = 1; argv[i][j]; ++j) {
  66            switch (argv[i][j]) {
  67              case 'v':
  68                  verbose = ~verbose;
  69                  break;
  70
  71              case 'b':
  72                  pad = BLOCK_SIZE;
  73                  break;
  74
  75              case 'p':
  76                  primary = 1;          /* make primary bootblock */
  77                  break;
  78            }
  79        }
  80    }
  81
  82    if (i >= argc) {
  83        usage();
  84    }
  85    inname = argv[i++];
  86
  87    fd = open(inname, O_RDONLY);
  88    if (fd == -1) {
  89        perror("open");
  90        exit(1);
  91    }
  92
  93    ofd = 1;
  94    if (i < argc) {
  95        ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666);
  96        if (ofd == -1) {
  97            perror("open");
  98            exit(1);
  99        }
 100    }
 101
 102    if (primary) {
 103        /* generate bootblock for primary loader */
 104        
 105        unsigned long bb[64], sum = 0;
 106        struct stat st;
 107        off_t size;
 108        int i;
 109
 110        if (ofd == 1) {
 111            usage();
 112        }
 113
 114        if (fstat(fd, &st) == -1) {
 115            perror("fstat");
 116            exit(1);
 117        }
 118
 119        size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
 120        memset(bb, 0, sizeof(bb));
 121        strcpy((char *) bb, "Linux SRM bootblock");
 122        bb[60] = size / BLOCK_SIZE;     /* count */
 123        bb[61] = 1;                     /* starting sector # */
 124        bb[62] = 0;                     /* flags---must be 0 */
 125        for (i = 0; i < 63; ++i) {
 126            sum += bb[i];
 127        }
 128        bb[63] = sum;
 129        if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) {
 130            perror("boot-block write");
 131            exit(1);
 132        }
 133        printf("%lu\n", size);
 134        return 0;
 135    }
 136
 137    /* read and inspect exec header: */
 138
 139    if (read(fd, buf, sizeof(buf)) < 0) {
 140        perror("read");
 141        exit(1);
 142    }
 143
 144#ifdef __ELF__
 145    elf = (struct elfhdr *) buf;
 146
 147    if (elf->e_ident[0] == 0x7f && strncmp((char *)elf->e_ident + 1, "ELF", 3) == 0) {
 148        if (elf->e_type != ET_EXEC) {
 149            fprintf(stderr, "%s: %s is not an ELF executable\n",
 150                    prog_name, inname);
 151            exit(1);
 152        }
 153        if (!elf_check_arch(elf)) {
 154            fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n",
 155                    prog_name, elf->e_machine);
 156            exit(1);
 157        }
 158        if (elf->e_phnum != 1) {
 159            fprintf(stderr,
 160                    "%s: %d program headers (forgot to link with -N?)\n",
 161                    prog_name, elf->e_phnum);
 162        }
 163
 164        e_entry = elf->e_entry;
 165
 166        lseek(fd, elf->e_phoff, SEEK_SET);
 167        if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) {
 168            perror("read");
 169            exit(1);
 170        }
 171
 172        elf_phdr = (struct elf_phdr *) buf;
 173        offset   = elf_phdr->p_offset;
 174        mem_size = elf_phdr->p_memsz;
 175        fil_size = elf_phdr->p_filesz;
 176
 177        /* work around ELF bug: */
 178        if (elf_phdr->p_vaddr < e_entry) {
 179            unsigned long delta = e_entry - elf_phdr->p_vaddr;
 180            offset   += delta;
 181            mem_size -= delta;
 182            fil_size -= delta;
 183            elf_phdr->p_vaddr += delta;
 184        }
 185
 186        if (verbose) {
 187            fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
 188                    prog_name, (long) elf_phdr->p_vaddr,
 189                    elf_phdr->p_vaddr + fil_size, offset);
 190        }
 191    } else
 192#endif
 193    {
 194        aout = (struct exec *) buf;
 195
 196        if (!(aout->fh.f_flags & COFF_F_EXEC)) {
 197            fprintf(stderr, "%s: %s is not in executable format\n",
 198                    prog_name, inname);
 199            exit(1);
 200        }
 201
 202        if (aout->fh.f_opthdr != sizeof(aout->ah)) {
 203            fprintf(stderr, "%s: %s has unexpected optional header size\n",
 204                    prog_name, inname);
 205            exit(1);
 206        }
 207
 208        if (N_MAGIC(*aout) != OMAGIC) {
 209            fprintf(stderr, "%s: %s is not an OMAGIC file\n",
 210                    prog_name, inname);
 211            exit(1);
 212        }
 213        offset = N_TXTOFF(*aout);
 214        fil_size = aout->ah.tsize + aout->ah.dsize;
 215        mem_size = fil_size + aout->ah.bsize;
 216
 217        if (verbose) {
 218            fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
 219                    prog_name, aout->ah.text_start,
 220                    aout->ah.text_start + fil_size, offset);
 221        }
 222    }
 223
 224    if (lseek(fd, offset, SEEK_SET) != offset) {
 225        perror("lseek");
 226        exit(1);
 227    }
 228
 229    if (verbose) {
 230        fprintf(stderr, "%s: copying %lu byte from %s\n",
 231                prog_name, (unsigned long) fil_size, inname);
 232    }
 233
 234    tocopy = fil_size;
 235    while (tocopy > 0) {
 236        n = tocopy;
 237        if (n > sizeof(buf)) {
 238            n = sizeof(buf);
 239        }
 240        tocopy -= n;
 241        if ((size_t) read(fd, buf, n) != n) {
 242            perror("read");
 243            exit(1);
 244        }
 245        do {
 246            nwritten = write(ofd, buf, n);
 247            if ((ssize_t) nwritten == -1) {
 248                perror("write");
 249                exit(1);
 250            }
 251            n -= nwritten;
 252        } while (n > 0);
 253    }
 254
 255    if (pad) {
 256        mem_size = ((mem_size + pad - 1) / pad) * pad;
 257    }
 258
 259    tocopy = mem_size - fil_size;
 260    if (tocopy > 0) {
 261        fprintf(stderr,
 262                "%s: zero-filling bss and aligning to %lu with %lu bytes\n",
 263                prog_name, pad, (unsigned long) tocopy);
 264
 265        memset(buf, 0x00, sizeof(buf));
 266        do {
 267            n = tocopy;
 268            if (n > sizeof(buf)) {
 269                n = sizeof(buf);
 270            }
 271            nwritten = write(ofd, buf, n);
 272            if ((ssize_t) nwritten == -1) {
 273                perror("write");
 274                exit(1);
 275            }
 276            tocopy -= nwritten;
 277        } while (tocopy > 0);
 278    }
 279    return 0;
 280}
 281