|
|
1.1 root 1: /*
2: * File: coffpatch.c
3: *
4: * Purpose: write into a coff file
5: *
6: * $Log: coffpatch.c,v $
7: * Revision 1.3 93/05/18 07:32:31 bin
8: * *** empty log message ***
9: *
10: */
11:
12: /*
13: * ----------------------------------------------------------------------
14: * Includes.
15: */
16: #include <stdio.h>
17: #include <errno.h>
18: #include <coff.h>
19: #include <sys/types.h>
20:
21: /*
22: * ----------------------------------------------------------------------
23: * Definitions.
24: * Constants.
25: * Macros with argument lists.
26: * Typedefs.
27: * Enums.
28: */
29:
30: /*
31: * ----------------------------------------------------------------------
32: * Functions.
33: * Import Functions.
34: * Export Functions.
35: * Local Functions.
36: */
37: int coffpatch();
38:
39: /*
40: * ----------------------------------------------------------------------
41: * Global Data.
42: * Import Variables.
43: * Export Variables.
44: * Local Variables.
45: */
46: extern char xflag;
47:
48: /*
49: * ----------------------------------------------------------------------
50: * Code.
51: *
52: * Perform peeks/patches as formatted by coffp0() in asypatch.c
53: *
54: * Return nonzero if success; zero if failure.
55: */
56:
57: int
58: coffpatch(fname, sym, stbl, buf, len, do_read)
59: char *fname;
60: SYMENT *sym;
61: char *stbl, *buf;
62: int len, do_read;
63: {
64: int ret = 0;
65: int fd;
66: int rwct, i;
67: static FILEHDR mainhdr;
68: static AOUTHDR opthdr;
69: static SCNHDR sh;
70: long seek, sought;
71:
72: long text_size; /* Size of text section in bytes. */
73: vaddr_t text_addr; /* Virtual memory base address for text. */
74: short text_scnum; /* Section number of text section. */
75: fsize_t text_base; /* File offset of start of text section. */
76:
77: long data_size; /* Size of data section in bytes. */
78: vaddr_t data_addr; /* Virtual memory base address for data. */
79: short data_scnum; /* Section number of data section. */
80: fsize_t data_base; /* File offset of start of data section. */
81:
82: /*
83: * Open the file to be patched.
84: */
85: if ((fd=open(fname, 2)) < 0) {
86: fprintf(stderr, "Cannot open %s\n", fname);
87: goto no_close_fd;
88: }
89: lseek(fd, 0, 0);
90:
91: /*
92: * Read filehdr.
93: */
94: if (-1 == read(fd, &mainhdr, sizeof(FILEHDR))) {
95: perror(fname);
96: fprintf(stderr, "Cannot read executable header.\n");
97: goto close_fd;
98: }
99:
100: /*
101: * Check for valid magic and length of optional header.
102: */
103: if (mainhdr.f_magic != C_386_MAGIC || (mainhdr.f_opthdr < sizeof(opthdr))) {
104: fprintf(stderr, "Bad magic (not COFF) in %s.\n", fname);
105: goto close_fd;
106: }
107:
108: /*
109: *Read the optional header.
110: */
111: if (-1 == read(fd, &opthdr, sizeof(AOUTHDR))) {
112: perror(fname);
113: fprintf(stderr, "Cannot read optional header.\n");
114: goto close_fd;
115: }
116:
117: /*
118: * Fill in the parameters we can get from the opthdr.
119: */
120: text_size = opthdr.tsize;
121: text_addr = opthdr.text_start;
122:
123: data_size = opthdr.dsize;
124: data_addr = opthdr.data_start;
125:
126: /*
127: * Read section headers for offsets.
128: */
129: text_scnum = -1; /* Mark as not found. */
130: data_scnum = -1; /* Mark as not found. */
131: for (i = 1; i <= mainhdr.f_nscns; ++i) {
132: if (-1 == read(fd, &sh, sizeof(SCNHDR))) {
133: perror(fname);
134: fprintf(stderr, "Cannot read section header.\n");
135: goto close_fd;
136: }
137:
138: if (STYP_TEXT == sh.s_flags) {
139: text_scnum = i;
140: text_base = sh.s_scnptr;
141: } else if (STYP_DATA == sh.s_flags) {
142: data_scnum = i;
143: data_base = sh.s_scnptr;
144: } /* else ignore this section header. */
145: }
146:
147: /*
148: * Did we find both sections?
149: */
150: if (-1 == text_scnum) {
151: fprintf(stderr, "No text section in %s.\n", fname);
152: }
153:
154: if (-1 == data_scnum) {
155: fprintf(stderr, "No data section in %s.\n", fname);
156: }
157:
158: /*
159: * Range check the patch address.
160: */
161: if (sym->n_scnum == text_scnum) {
162: if ((sym->n_value < text_addr) ||
163: (sym->n_value + len > text_addr + text_size) ) {
164:
165: fprintf(stderr, "Symbol out of range for text section.\n");
166: fprintf(stderr, "%s: %x\n",
167: stbl + sym->n_offset - sizeof(long),
168: sym->n_value);
169: goto close_fd;
170: }
171: } else if (sym->n_scnum == data_scnum) {
172: if ((sym->n_value < data_addr) ||
173: (sym->n_value + len > data_addr + data_size) ) {
174:
175: fprintf(stderr, "Symbol out of range for data section.\n");
176: fprintf(stderr, "%s: %x\n",
177: stbl + sym->n_offset - sizeof(long),
178: sym->n_value);
179: goto close_fd;
180: }
181: } else {
182: fprintf(stderr,
183: "Illegal section number %d for symbol %s.\n",
184: sym->n_scnum,
185: stbl + sym->n_offset - sizeof(long));
186: goto close_fd;
187: }
188:
189: /*
190: * Seek and patch.
191: */
192: seek = sym->n_value;
193: /*
194: * Adjust the file offset for the symbol based on which
195: * segment it resides in.
196: */
197: if (sym->n_scnum == text_scnum) {
198: seek = (seek - text_addr) + text_base;
199: } else if (sym->n_scnum == data_scnum) {
200: seek = (seek - data_addr) + data_base;
201: } else {
202: fprintf(stderr, "Bad section number!!.\n");
203: goto close_fd;
204: }
205:
206: sought = lseek(fd, seek, 0);
207: if (sought == -1) {
208: fprintf(stderr, "asypatch: lseek to %x failed\n", seek);
209: }
210:
211: if (xflag)
212: printf("write(%d, [%x]=%x, %d)->%x\n",
213: fd, buf, *(int*)buf, len, sought);
214:
215: if (do_read) {
216: if ((rwct = read(fd, buf, len)) != len) {
217: fprintf(stderr, "asypatch %s: read %d bytes of %d\n",
218: stbl, rwct, len);
219: goto close_fd;
220: }
221: } else {
222: if ((rwct = write(fd, buf, len)) != len) {
223: fprintf(stderr, "asypatch %s: wrote %d bytes of %d\n",
224: stbl, rwct, len);
225: goto close_fd;
226: }
227: }
228: ret = 1;
229:
230: close_fd:
231: close(fd);
232: no_close_fd:
233: return ret;
234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.