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