1 /* 2 * $Id: binpatch.c,v 1.3 1994/02/11 07:02:53 chopps Exp $ 3 */ 4 5 #include <sys/types.h> 6 #include <a.out.h> 7 #include <stdio.h> 8 9 extern char *optarg; 10 extern int optind; 11 12 volatile void error (); 13 14 int test = 1; 15 int testbss; 16 char foo = 23; 17 18 19 int 20 main(argc, argv) 21 int argc; 22 char *argv[]; 23 { 24 struct exec e; 25 int c; 26 u_long addr = 0, offset = 0; 27 u_long replace = 0, do_replace = 0; 28 char *symbol = 0; 29 char size = 4; /* default to long */ 30 char *fname; 31 int fd; 32 int type, off; 33 u_long lval; 34 u_short sval; 35 u_char cval; 36 37 38 while ((c = getopt (argc, argv, "a:bwlr:s:o:")) != EOF) 39 switch (c) 40 { 41 case 'a': 42 if (addr || symbol) 43 error ("only one address/symbol allowed"); 44 if (! strncmp (optarg, "0x", 2)) 45 sscanf (optarg, "%x", &addr); 46 else 47 addr = atoi (optarg); 48 if (! addr) 49 error ("invalid address"); 50 break; 51 52 case 'b': 53 size = 1; 54 break; 55 56 case 'w': 57 size = 2; 58 break; 59 60 case 'l': 61 size = 4; 62 break; 63 64 case 'r': 65 do_replace = 1; 66 if (! strncmp (optarg, "0x", 2)) 67 sscanf (optarg, "%x", &replace); 68 else 69 replace = atoi (optarg); 70 break; 71 72 case 's': 73 if (addr || symbol) 74 error ("only one address/symbol allowed"); 75 symbol = optarg; 76 break; 77 78 case 'o': 79 if (offset) 80 error ("only one offset allowed"); 81 if (! strncmp (optarg, "0x", 2)) 82 sscanf (optarg, "%x", &offset); 83 else 84 offset = atoi (optarg); 85 break; 86 } 87 88 argv += optind; 89 argc -= optind; 90 91 92 if (argc < 1) 93 error ("No file to patch."); 94 95 fname = argv[0]; 96 if ((fd = open (fname, 0)) < 0) 97 error ("Can't open file"); 98 99 if (read (fd, &e, sizeof (e)) != sizeof (e) 100 || N_BADMAG (e)) 101 error ("Not a valid executable."); 102 103 /* fake mid, so the N_ macros work on the amiga.. */ 104 e.a_midmag |= 127 << 16; 105 106 if (symbol) 107 { 108 struct nlist nl[2]; 109 nl[0].n_un.n_name = symbol; 110 nl[1].n_un.n_name = 0; 111 if (nlist (fname, nl) != 0) 112 error ("Symbol not found."); 113 addr = nl[0].n_value; 114 type = nl[0].n_type & N_TYPE; 115 } 116 else 117 { 118 type = N_UNDF; 119 if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e)) 120 type = N_TEXT; 121 else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data) 122 type = N_DATA; 123 } 124 addr += offset; 125 126 /* if replace-mode, have to reopen the file for writing. 127 Can't do that from the beginning, or nlist() will not 128 work (at least not under AmigaDOS) */ 129 if (do_replace) 130 { 131 close (fd); 132 if ((fd = open (fname, 2)) == -1) 133 error ("Can't reopen file for writing."); 134 } 135 136 if (type != N_TEXT && type != N_DATA) 137 error ("address/symbol is not in text or data section."); 138 139 if (type == N_TEXT) 140 off = addr - N_TXTADDR(e) + N_TXTOFF(e); 141 else 142 off = addr - N_DATADDR(e) + N_DATOFF(e); 143 144 if (lseek (fd, off, 0) == -1) 145 error ("lseek"); 146 147 /* not beautiful, but works on big and little endian machines */ 148 switch (size) 149 { 150 case 1: 151 if (read (fd, &cval, 1) != 1) 152 error ("cread"); 153 lval = cval; 154 break; 155 156 case 2: 157 if (read (fd, &sval, 2) != 2) 158 error ("sread"); 159 lval = sval; 160 break; 161 162 case 4: 163 if (read (fd, &lval, 4) != 4) 164 error ("lread"); 165 break; 166 } 167 168 169 if (symbol) 170 printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval); 171 else 172 printf ("0x%x: %d (0x%x)\n", addr, lval, lval); 173 174 if (do_replace) 175 { 176 if (lseek (fd, off, 0) == -1) 177 error ("write-lseek"); 178 switch (size) 179 { 180 case 1: 181 cval = replace; 182 if (cval != replace) 183 error ("byte-value overflow."); 184 if (write (fd, &cval, 1) != 1) 185 error ("cwrite"); 186 break; 187 188 case 2: 189 sval = replace; 190 if (sval != replace) 191 error ("word-value overflow."); 192 if (write (fd, &sval, 2) != 2) 193 error ("swrite"); 194 break; 195 196 case 4: 197 if (write (fd, &replace, 4) != 4) 198 error ("lwrite"); 199 break; 200 } 201 } 202 203 close (fd); 204 } 205 206 207 208 volatile void error (str) 209 char *str; 210 { 211 fprintf (stderr, "%s\n", str); 212 exit (1); 213 } 214