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