xref: /netbsd-src/sys/arch/amiga/stand/binpatch/binpatch.c (revision ae1bfcddc410612bc8c58b807e1830becb69a24c)
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