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