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