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