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