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