Home | History | Annotate | Line # | Download | only in binpatch
binpatch.c revision 1.4.76.1
      1  1.4.76.1     jym /*	$NetBSD: binpatch.c,v 1.4.76.1 2009/05/13 17:16:31 jym Exp $	*/
      2       1.1     leo 
      3       1.1     leo /*
      4       1.1     leo  * Copyright (c) 1994 Christian E. Hopps
      5       1.1     leo  * All rights reserved.
      6       1.1     leo  *
      7       1.1     leo  * Redistribution and use in source and binary forms, with or without
      8       1.1     leo  * modification, are permitted provided that the following conditions
      9       1.1     leo  * are met:
     10       1.1     leo  * 1. Redistributions of source code must retain the above copyright
     11       1.1     leo  *    notice, this list of conditions and the following disclaimer.
     12       1.1     leo  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1     leo  *    notice, this list of conditions and the following disclaimer in the
     14       1.1     leo  *    documentation and/or other materials provided with the distribution.
     15       1.1     leo  * 3. All advertising materials mentioning features or use of this software
     16       1.1     leo  *    must display the following acknowledgement:
     17       1.1     leo  *      This product includes software developed by Christian E. Hopps.
     18       1.3      pk  * 4. The name of the author may not be used to endorse or promote products
     19       1.1     leo  *    derived from this software without specific prior written permission
     20       1.1     leo  *
     21       1.1     leo  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22       1.1     leo  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23       1.1     leo  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24       1.1     leo  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25       1.1     leo  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26       1.1     leo  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27       1.1     leo  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28       1.1     leo  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29       1.1     leo  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30       1.1     leo  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31       1.1     leo  */
     32       1.1     leo 
     33       1.1     leo #include <sys/types.h>
     34       1.1     leo #include <a.out.h>
     35       1.1     leo #include <stdio.h>
     36       1.4  mhitch #include <stdlib.h>
     37       1.1     leo 
     38       1.1     leo extern char *optarg;
     39       1.1     leo extern int optind;
     40       1.1     leo 
     41       1.4  mhitch void error (char *) __attribute__((__noreturn__));
     42       1.1     leo 
     43       1.1     leo int test = 1;
     44       1.1     leo int testbss;
     45       1.1     leo char foo = 23;
     46       1.1     leo 
     47       1.1     leo 
     48       1.1     leo int
     49  1.4.76.1     jym main(int argc, char *argv[])
     50       1.1     leo {
     51       1.1     leo   struct exec e;
     52       1.1     leo   int c;
     53       1.1     leo   u_long addr = 0, offset = 0;
     54       1.1     leo   u_long replace = 0, do_replace = 0;
     55       1.1     leo   char *symbol = 0;
     56       1.1     leo   char size = 4;  /* default to long */
     57       1.1     leo   char *fname;
     58       1.1     leo   int fd;
     59       1.1     leo   int type, off;
     60       1.1     leo   u_long  lval;
     61       1.1     leo   u_short sval;
     62       1.1     leo   u_char  cval;
     63       1.1     leo 
     64       1.1     leo 
     65       1.2   lukem   while ((c = getopt (argc, argv, "a:bwlr:s:o:")) != -1)
     66       1.1     leo     switch (c)
     67       1.1     leo       {
     68       1.1     leo       case 'a':
     69       1.1     leo 	if (addr || symbol)
     70       1.1     leo 	  error ("only one address/symbol allowed");
     71       1.1     leo 	if (! strncmp (optarg, "0x", 2))
     72       1.1     leo 	  sscanf (optarg, "%x", &addr);
     73       1.1     leo 	else
     74       1.1     leo 	  addr = atoi (optarg);
     75       1.1     leo 	if (! addr)
     76       1.1     leo 	  error ("invalid address");
     77       1.1     leo 	break;
     78       1.1     leo 
     79       1.1     leo       case 'b':
     80       1.1     leo 	size = 1;
     81       1.1     leo 	break;
     82       1.1     leo 
     83       1.1     leo       case 'w':
     84       1.1     leo 	size = 2;
     85       1.1     leo 	break;
     86       1.1     leo 
     87       1.1     leo       case 'l':
     88       1.1     leo 	size = 4;
     89       1.1     leo 	break;
     90       1.1     leo 
     91       1.1     leo       case 'r':
     92       1.1     leo 	do_replace = 1;
     93       1.1     leo 	if (! strncmp (optarg, "0x", 2))
     94       1.1     leo 	  sscanf (optarg, "%x", &replace);
     95       1.1     leo 	else
     96       1.1     leo 	  replace = atoi (optarg);
     97       1.1     leo 	break;
     98       1.1     leo 
     99       1.1     leo       case 's':
    100       1.1     leo 	if (addr || symbol)
    101       1.1     leo 	  error ("only one address/symbol allowed");
    102       1.1     leo 	symbol = optarg;
    103       1.1     leo 	break;
    104       1.1     leo 
    105       1.1     leo       case 'o':
    106       1.1     leo 	if (offset)
    107       1.1     leo 	  error ("only one offset allowed");
    108       1.1     leo 	if (! strncmp (optarg, "0x", 2))
    109       1.1     leo 	  sscanf (optarg, "%x", &offset);
    110       1.1     leo 	else
    111       1.1     leo           offset = atoi (optarg);
    112       1.1     leo         break;
    113       1.1     leo       }
    114       1.1     leo 
    115       1.1     leo   argv += optind;
    116       1.1     leo   argc -= optind;
    117       1.1     leo 
    118       1.1     leo 
    119       1.1     leo   if (argc < 1)
    120       1.1     leo     error ("No file to patch.");
    121       1.1     leo 
    122       1.1     leo   fname = argv[0];
    123       1.1     leo   if ((fd = open (fname, 0)) < 0)
    124       1.1     leo     error ("Can't open file");
    125       1.1     leo 
    126       1.1     leo   if (read (fd, &e, sizeof (e)) != sizeof (e)
    127       1.1     leo       || N_BADMAG (e))
    128       1.1     leo     error ("Not a valid executable.");
    129       1.1     leo 
    130       1.1     leo   /* fake mid, so the N_ macros work on the amiga.. */
    131       1.1     leo   e.a_midmag |= 127 << 16;
    132       1.1     leo 
    133       1.1     leo   if (symbol)
    134       1.1     leo     {
    135       1.1     leo       struct nlist nl[2];
    136       1.1     leo       nl[0].n_un.n_name = symbol;
    137       1.1     leo       nl[1].n_un.n_name = 0;
    138       1.1     leo       if (nlist (fname, nl) != 0)
    139       1.1     leo 	error ("Symbol not found.");
    140       1.1     leo       addr = nl[0].n_value;
    141       1.1     leo       type = nl[0].n_type & N_TYPE;
    142       1.1     leo     }
    143       1.1     leo   else
    144       1.1     leo     {
    145       1.1     leo       type = N_UNDF;
    146       1.1     leo       if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e))
    147       1.1     leo 	type = N_TEXT;
    148       1.1     leo       else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data)
    149       1.1     leo 	type = N_DATA;
    150       1.1     leo     }
    151       1.1     leo   addr += offset;
    152       1.1     leo 
    153       1.1     leo   /* if replace-mode, have to reopen the file for writing.
    154       1.1     leo      Can't do that from the beginning, or nlist() will not
    155       1.1     leo      work (at least not under AmigaDOS) */
    156       1.1     leo   if (do_replace)
    157       1.1     leo     {
    158       1.1     leo       close (fd);
    159       1.1     leo       if ((fd = open (fname, 2)) == -1)
    160       1.1     leo 	error ("Can't reopen file for writing.");
    161       1.1     leo     }
    162       1.1     leo 
    163       1.1     leo   if (type != N_TEXT && type != N_DATA)
    164       1.1     leo     error ("address/symbol is not in text or data section.");
    165       1.1     leo 
    166       1.1     leo   if (type == N_TEXT)
    167       1.1     leo     off = addr - N_TXTADDR(e) + N_TXTOFF(e);
    168       1.1     leo   else
    169       1.1     leo     off = addr - N_DATADDR(e) + N_DATOFF(e);
    170       1.1     leo 
    171       1.1     leo   if (lseek (fd, off, 0) == -1)
    172       1.1     leo     error ("lseek");
    173       1.1     leo 
    174       1.1     leo   /* not beautiful, but works on big and little endian machines */
    175       1.1     leo   switch (size)
    176       1.1     leo     {
    177       1.1     leo     case 1:
    178       1.1     leo       if (read (fd, &cval, 1) != 1)
    179       1.1     leo 	error ("cread");
    180       1.1     leo       lval = cval;
    181       1.1     leo       break;
    182       1.1     leo 
    183       1.1     leo     case 2:
    184       1.1     leo       if (read (fd, &sval, 2) != 2)
    185       1.1     leo 	error ("sread");
    186       1.1     leo       lval = sval;
    187       1.1     leo       break;
    188       1.1     leo 
    189       1.1     leo     case 4:
    190       1.1     leo       if (read (fd, &lval, 4) != 4)
    191       1.1     leo 	error ("lread");
    192       1.1     leo       break;
    193       1.1     leo     }
    194       1.1     leo 
    195       1.1     leo 
    196       1.1     leo   if (symbol)
    197       1.1     leo     printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval);
    198       1.1     leo   else
    199       1.1     leo     printf ("0x%x: %d (0x%x)\n", addr, lval, lval);
    200       1.1     leo 
    201       1.1     leo   if (do_replace)
    202       1.1     leo     {
    203       1.1     leo       if (lseek (fd, off, 0) == -1)
    204       1.1     leo 	error ("write-lseek");
    205       1.1     leo       switch (size)
    206       1.1     leo 	{
    207       1.1     leo 	case 1:
    208       1.1     leo 	  cval = replace;
    209       1.1     leo 	  if (cval != replace)
    210       1.1     leo 	    error ("byte-value overflow.");
    211       1.1     leo 	  if (write (fd, &cval, 1) != 1)
    212       1.1     leo 	    error ("cwrite");
    213       1.1     leo 	  break;
    214       1.1     leo 
    215       1.1     leo 	case 2:
    216       1.1     leo 	  sval = replace;
    217       1.1     leo 	  if (sval != replace)
    218       1.1     leo 	    error ("word-value overflow.");
    219       1.1     leo 	  if (write (fd, &sval, 2) != 2)
    220       1.1     leo 	    error ("swrite");
    221       1.1     leo 	  break;
    222       1.1     leo 
    223       1.1     leo 	case 4:
    224       1.1     leo 	  if (write (fd, &replace, 4) != 4)
    225       1.1     leo 	    error ("lwrite");
    226       1.1     leo 	  break;
    227       1.1     leo 	}
    228       1.1     leo     }
    229       1.1     leo 
    230       1.1     leo   close (fd);
    231       1.1     leo }
    232       1.1     leo 
    233       1.1     leo 
    234       1.1     leo 
    235       1.4  mhitch void error (str)
    236       1.1     leo      char *str;
    237       1.1     leo {
    238       1.1     leo   fprintf (stderr, "%s\n", str);
    239       1.1     leo   exit (1);
    240       1.1     leo }
    241