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