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