binpatch.c revision 1.1 1 /* $NetBSD: binpatch.c,v 1.1 1995/03/26 07:12:04 leo Exp $ */
2
3 /*
4 * Copyright (c) 1994 Christian E. Hopps
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Christian E. Hopps.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/types.h>
34 #include <a.out.h>
35 #include <stdio.h>
36
37 extern char *optarg;
38 extern int optind;
39
40 volatile void error ();
41
42 int test = 1;
43 int testbss;
44 char foo = 23;
45
46
47 int
48 main(argc, argv)
49 int argc;
50 char *argv[];
51 {
52 struct exec e;
53 int c;
54 u_long addr = 0, offset = 0;
55 u_long replace = 0, do_replace = 0;
56 char *symbol = 0;
57 char size = 4; /* default to long */
58 char *fname;
59 int fd;
60 int type, off;
61 u_long lval;
62 u_short sval;
63 u_char cval;
64
65
66 while ((c = getopt (argc, argv, "a:bwlr:s:o:")) != EOF)
67 switch (c)
68 {
69 case 'a':
70 if (addr || symbol)
71 error ("only one address/symbol allowed");
72 if (! strncmp (optarg, "0x", 2))
73 sscanf (optarg, "%x", &addr);
74 else
75 addr = atoi (optarg);
76 if (! addr)
77 error ("invalid address");
78 break;
79
80 case 'b':
81 size = 1;
82 break;
83
84 case 'w':
85 size = 2;
86 break;
87
88 case 'l':
89 size = 4;
90 break;
91
92 case 'r':
93 do_replace = 1;
94 if (! strncmp (optarg, "0x", 2))
95 sscanf (optarg, "%x", &replace);
96 else
97 replace = atoi (optarg);
98 break;
99
100 case 's':
101 if (addr || symbol)
102 error ("only one address/symbol allowed");
103 symbol = optarg;
104 break;
105
106 case 'o':
107 if (offset)
108 error ("only one offset allowed");
109 if (! strncmp (optarg, "0x", 2))
110 sscanf (optarg, "%x", &offset);
111 else
112 offset = atoi (optarg);
113 break;
114 }
115
116 argv += optind;
117 argc -= optind;
118
119
120 if (argc < 1)
121 error ("No file to patch.");
122
123 fname = argv[0];
124 if ((fd = open (fname, 0)) < 0)
125 error ("Can't open file");
126
127 if (read (fd, &e, sizeof (e)) != sizeof (e)
128 || N_BADMAG (e))
129 error ("Not a valid executable.");
130
131 /* fake mid, so the N_ macros work on the amiga.. */
132 e.a_midmag |= 127 << 16;
133
134 if (symbol)
135 {
136 struct nlist nl[2];
137 nl[0].n_un.n_name = symbol;
138 nl[1].n_un.n_name = 0;
139 if (nlist (fname, nl) != 0)
140 error ("Symbol not found.");
141 addr = nl[0].n_value;
142 type = nl[0].n_type & N_TYPE;
143 }
144 else
145 {
146 type = N_UNDF;
147 if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e))
148 type = N_TEXT;
149 else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data)
150 type = N_DATA;
151 }
152 addr += offset;
153
154 /* if replace-mode, have to reopen the file for writing.
155 Can't do that from the beginning, or nlist() will not
156 work (at least not under AmigaDOS) */
157 if (do_replace)
158 {
159 close (fd);
160 if ((fd = open (fname, 2)) == -1)
161 error ("Can't reopen file for writing.");
162 }
163
164 if (type != N_TEXT && type != N_DATA)
165 error ("address/symbol is not in text or data section.");
166
167 if (type == N_TEXT)
168 off = addr - N_TXTADDR(e) + N_TXTOFF(e);
169 else
170 off = addr - N_DATADDR(e) + N_DATOFF(e);
171
172 if (lseek (fd, off, 0) == -1)
173 error ("lseek");
174
175 /* not beautiful, but works on big and little endian machines */
176 switch (size)
177 {
178 case 1:
179 if (read (fd, &cval, 1) != 1)
180 error ("cread");
181 lval = cval;
182 break;
183
184 case 2:
185 if (read (fd, &sval, 2) != 2)
186 error ("sread");
187 lval = sval;
188 break;
189
190 case 4:
191 if (read (fd, &lval, 4) != 4)
192 error ("lread");
193 break;
194 }
195
196
197 if (symbol)
198 printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval);
199 else
200 printf ("0x%x: %d (0x%x)\n", addr, lval, lval);
201
202 if (do_replace)
203 {
204 if (lseek (fd, off, 0) == -1)
205 error ("write-lseek");
206 switch (size)
207 {
208 case 1:
209 cval = replace;
210 if (cval != replace)
211 error ("byte-value overflow.");
212 if (write (fd, &cval, 1) != 1)
213 error ("cwrite");
214 break;
215
216 case 2:
217 sval = replace;
218 if (sval != replace)
219 error ("word-value overflow.");
220 if (write (fd, &sval, 2) != 2)
221 error ("swrite");
222 break;
223
224 case 4:
225 if (write (fd, &replace, 4) != 4)
226 error ("lwrite");
227 break;
228 }
229 }
230
231 close (fd);
232 }
233
234
235
236 volatile void error (str)
237 char *str;
238 {
239 fprintf (stderr, "%s\n", str);
240 exit (1);
241 }
242