binpatch.c revision 1.2 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, offset = 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:o:")) != 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 case 'o':
75 if (offset)
76 error ("only one offset allowed");
77 if (! strncmp (optarg, "0x", 2))
78 sscanf (optarg, "%x", &offset);
79 else
80 offset = atoi (optarg);
81 break;
82 }
83
84 argv += optind;
85 argc -= optind;
86
87
88 if (argc < 1)
89 error ("No file to patch.");
90
91 fname = argv[0];
92 if ((fd = open (fname, 0)) < 0)
93 error ("Can't open file");
94
95 if (read (fd, &e, sizeof (e)) != sizeof (e)
96 || N_BADMAG (e))
97 error ("Not a valid executable.");
98
99 /* fake mid, so the N_ macros work on the amiga.. */
100 e.a_midmag |= 127 << 16;
101
102 if (symbol)
103 {
104 struct nlist nl[2];
105 nl[0].n_un.n_name = symbol;
106 nl[1].n_un.n_name = 0;
107 if (nlist (fname, nl) != 0)
108 error ("Symbol not found.");
109 addr = nl[0].n_value;
110 type = nl[0].n_type & N_TYPE;
111 }
112 else
113 {
114 type = N_UNDF;
115 if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e))
116 type = N_TEXT;
117 else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data)
118 type = N_DATA;
119 }
120 addr += offset;
121
122 /* if replace-mode, have to reopen the file for writing.
123 Can't do that from the beginning, or nlist() will not
124 work (at least not under AmigaDOS) */
125 if (do_replace)
126 {
127 close (fd);
128 if ((fd = open (fname, 2)) == -1)
129 error ("Can't reopen file for writing.");
130 }
131
132 if (type != N_TEXT && type != N_DATA)
133 error ("address/symbol is not in text or data section.");
134
135 if (type == N_TEXT)
136 off = addr - N_TXTADDR(e) + N_TXTOFF(e);
137 else
138 off = addr - N_DATADDR(e) + N_DATOFF(e);
139
140 if (lseek (fd, off, 0) == -1)
141 error ("lseek");
142
143 /* not beautiful, but works on big and little endian machines */
144 switch (size)
145 {
146 case 1:
147 if (read (fd, &cval, 1) != 1)
148 error ("cread");
149 lval = cval;
150 break;
151
152 case 2:
153 if (read (fd, &sval, 2) != 2)
154 error ("sread");
155 lval = sval;
156 break;
157
158 case 4:
159 if (read (fd, &lval, 4) != 4)
160 error ("lread");
161 break;
162 }
163
164
165 if (symbol)
166 printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval);
167 else
168 printf ("0x%x: %d (0x%x)\n", addr, lval, lval);
169
170 if (do_replace)
171 {
172 if (lseek (fd, off, 0) == -1)
173 error ("write-lseek");
174 switch (size)
175 {
176 case 1:
177 cval = replace;
178 if (cval != replace)
179 error ("byte-value overflow.");
180 if (write (fd, &cval, 1) != 1)
181 error ("cwrite");
182 break;
183
184 case 2:
185 sval = replace;
186 if (sval != replace)
187 error ("word-value overflow.");
188 if (write (fd, &sval, 2) != 2)
189 error ("swrite");
190 break;
191
192 case 4:
193 if (write (fd, &replace, 4) != 4)
194 error ("lwrite");
195 break;
196 }
197 }
198
199 close (fd);
200 }
201
202
203
204 volatile void error (str)
205 char *str;
206 {
207 fprintf (stderr, "%s\n", str);
208 exit (1);
209 }
210