|
|
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.