|
|
1.1 root 1: #include <stdio.h>
2: #include <errno.h>
3: #include <coff.h>
4: #include <fcntl.h>
5: #include <sys/types.h>
6: #include "patch.h"
7:
8: extern char *symbols; /* String of symbol names. */
9: extern int peek; /* Are we just looking? */
10:
11: /*
12: * Modify the contents of the file namep to match the array of patch
13: * structures pl[]. The argument, n, is the number of entries in pl[]
14: * that should be processed.
15: */
16: void
17: setfile(namep, n, pl)
18: char *namep;
19: int n;
20: struct plist pl[];
21: {
22: int i;
23: int fd;
24: fsize_t seek; /* Final seek address for each pl[] entry. */
25: SYMENT *sym; /* Holder SYMENTs while looping. */
26: static FILEHDR mainhdr; /* Main COFF file header. */
27: static AOUTHDR opthdr; /* COFF Optional header (for executables). */
28: static SCNHDR sh; /* Section header. */
29:
30: long text_size; /* Size of text section in bytes. */
31: vaddr_t text_addr; /* Virtual memory base address for text. */
32: short text_scnum; /* Section number of text section. */
33: fsize_t text_base; /* File offset of start of text section. */
34:
35: long data_size; /* Size of data section in bytes. */
36: vaddr_t data_addr; /* Virtual memory base address for data. */
37: short data_scnum; /* Section number of data section. */
38: fsize_t data_base; /* File offset of start of data section. */
39:
40: char *symname; /* Name of the currently patched LHS. */
41:
42: /* Open the file to be patched. */
43: if (peek) {
44: if ((fd=open(namep, O_RDONLY)) < 0) {
45: fprintf(stderr, "Cannot open %s for reading.\n", namep);
46: exit(1);
47: }
48: } else {
49: if ((fd=open(namep, O_RDWR)) < 0) {
50: fprintf(stderr, "Cannot open %s.\n", namep);
51: exit(1);
52: }
53: }
54:
55: lseek(fd, 0L, 0);
56:
57: /* Read filehdr. */
58: if (-1 == read(fd, &mainhdr, sizeof(FILEHDR))) {
59: perror(namep);
60: fprintf(stderr, "Cannot read executable header.\n");
61: exit(1);
62: }
63:
64: /* Check for valid magic and length of optional header. */
65: if (!ISCOFF(mainhdr.f_magic) || (mainhdr.f_opthdr < sizeof(opthdr))) {
66: fprintf(stderr, "Bad magic in %s.\n", namep);
67: exit(1);
68: }
69:
70: /* Read the optional header. */
71: if (-1 == read(fd, &opthdr, sizeof(AOUTHDR))) {
72: perror(namep);
73: fprintf(stderr, "Cannot read optional header.\n");
74: exit(1);
75: }
76:
77:
78: /* Fill in the parameters we can get from the opthdr. */
79: text_size = opthdr.tsize;
80: text_addr = opthdr.text_start;
81:
82: data_size = opthdr.dsize;
83: data_addr = opthdr.data_start;
84:
85: /* Read section headers for offsets. */
86: text_scnum = -1; /* Mark as not found. */
87: data_scnum = -1; /* Mark as not found. */
88: for (i = 1; i <= mainhdr.f_nscns; ++i) {
89: if (-1 == read(fd, &sh, sizeof(SCNHDR))) {
90: perror(namep);
91: fprintf(stderr, "Cannot read section header.\n");
92: exit(1);
93: }
94:
95: if (STYP_TEXT == sh.s_flags) {
96: text_scnum = i;
97: text_base = sh.s_scnptr;
98: } else if (STYP_DATA == sh.s_flags) {
99: data_scnum = i;
100: data_base = sh.s_scnptr;
101: } /* else ignore this section header. */
102: }
103:
104: /* Did we find both sections? */
105: if (-1 == text_scnum) {
106: fprintf(stderr, "No text section in %s.\n", namep);
107: }
108:
109: if (-1 == data_scnum) {
110: fprintf(stderr, "No data section in %s.\n", namep);
111: }
112:
113: /* Range check all the patch addresses. */
114: for (i = 0; i < n; i += 1) {
115: sym = pl[i].p_lvnp;
116: if (sym->n_scnum == text_scnum) {
117: if ((sym->n_value < text_addr) ||
118: (sym->n_value > text_addr + text_size) ) {
119:
120: fprintf(stderr, "Symbol out of range for text section.\n");
121: fprintf(stderr, "%s: %x\n",
122: &(symbols[sym->n_offset - sizeof(long)]),
123: sym->n_value);
124: exit(1);
125: }
126: } else if (sym->n_scnum == data_scnum) {
127: if ((sym->n_value < data_addr) ||
128: (sym->n_value > data_addr + data_size) ) {
129:
130: fprintf(stderr, "Symbol out of range for data section.\n");
131: fprintf(stderr, "%s: %x\n",
132: &(symbols[sym->n_offset - sizeof(long)]),
133: sym->n_value);
134: exit(1);
135: }
136: } else {
137: fprintf(stderr,
138: "Illegal section number %d for symbol %s.\n",
139: sym->n_scnum,
140: &(symbols[(sym->n_offset) - sizeof(long)]));
141: fprintf(stderr, "Was there really a mem fault?\n");
142: exit(1);
143: }
144:
145: }
146:
147: /* Walk through pl[] seeking and patching. */
148: for (i = 0; i < n; i += 1) {
149: seek = pl[i].p_lval;
150: sym = pl[i].p_lvnp;
151: /*
152: * Adjust the file offset for the symbol based on which
153: * segement it resides in.
154: */
155: if (sym->n_scnum == text_scnum) {
156: seek = (seek - text_addr) + text_base;
157: } else if (sym->n_scnum == data_scnum) {
158: seek = (seek - data_addr) + data_base;
159: } else {
160: fprintf(stderr, "Unreachable code is setfile().\n");
161: exit(1);
162: }
163:
164: lseek(fd, seek, 0);
165:
166: symname = &(symbols[pl[i].p_lvnp->n_offset - sizeof(long)]);
167: if (patch(fd, &pl[i], namep, symname) < 0) {
168: fprintf(stderr, "Write error in %s\n", namep);
169: }
170: }
171:
172: close(fd);
173: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.