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