binpatch.c revision 1.3 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