/* $Id: exedump.c,v 1.1 1993/06/09 03:28:10 root Exp root $ */ /* * Copyright Robert J. Amstadt, 1993 */ #include #include #include #include #include #include #include #include #include #include #include #include "neexe.h" #include "segmem.h" #include "prototypes.h" #include "dlls.h" extern int CallTo16(unsigned long csip, unsigned long sssp, unsigned short ds); extern void CallTo32(); unsigned short WIN_StackSize; char **Argv; int Argc; /********************************************************************** * DebugPrintString */ int DebugPrintString(char *str) { fprintf(stderr, "%s", str); return 0; } /********************************************************************** * myerror */ void myerror(const char *s) { char buffer[200]; sprintf(buffer, "%s", Argv[0]); if (s == NULL) perror(buffer); else fprintf(stderr, "%s: %s\n", buffer, s); exit(1); } /********************************************************************** * main */ main(int argc, char **argv) { struct stat finfo; struct mz_header_s *mz_header; struct ne_header_s *ne_header; struct ne_segment_table_entry_s *seg_table; unsigned int status; unsigned int read_size; struct segment_descriptor_s *selector_table; int fd; int segment; int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg; int rv; Argc = argc; Argv = argv; if (argc < 2) { fprintf(stderr, "usage: %s FILENAME\n", argv[0]); exit(1); } /* * Open file for reading. */ fd = open(argv[1], O_RDONLY); if (fd < 0) { myerror(NULL); } /* * Allocate memory to hold entire executable. */ if (fstat(fd, &finfo) < 0) myerror(NULL); /* * Establish header pointers. */ mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));; status = lseek(fd, 0, SEEK_SET); if (read(fd, mz_header, sizeof(struct mz_header_s)) != sizeof(struct mz_header_s)) { myerror("Unable to read MZ header from file"); } if (mz_header->must_be_0x40 != 0x40) myerror("This is not a Windows program"); ne_header = (struct ne_header_s *) malloc(sizeof(struct ne_header_s)); status = lseek(fd, mz_header->ne_offset, SEEK_SET); if (read(fd, ne_header, sizeof(struct ne_header_s)) != sizeof(struct ne_header_s)) { myerror("Unable to read NE header from file"); } if (ne_header->header_type[0] != 'N' || ne_header->header_type[1] != 'E') myerror("This is not a Windows program"); WIN_StackSize = ne_header->stack_length; /* * Create segment selectors. */ status = lseek(fd, mz_header->ne_offset + ne_header->segment_tab_offset, SEEK_SET); read_size = ne_header->n_segment_tab * sizeof(struct ne_segment_table_entry_s); seg_table = (struct ne_segment_table_entry_s *) malloc(read_size); if (read(fd, seg_table, read_size) != read_size) myerror("Unable to read segment table header from file"); selector_table = CreateSelectors(fd, seg_table, ne_header); /* * Fixup references. */ for (segment = 0; segment < ne_header->n_segment_tab; segment++) { if (FixupSegment(fd, mz_header, ne_header, seg_table, selector_table, segment) < 0) { myerror("fixup failed."); } } close(fd); /* * Fixup stack and jump to start. */ ds_reg = selector_table[ne_header->auto_data_seg-1].selector; cs_reg = selector_table[ne_header->cs-1].selector; ip_reg = ne_header->ip; ss_reg = selector_table[ne_header->ss-1].selector; sp_reg = ne_header->sp; rv = CallTo16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg); printf ("rv = %x\n", rv); } /********************************************************************** * GetImportedName */ char * GetImportedName(int fd, struct mz_header_s *mz_header, struct ne_header_s *ne_header, int name_offset, char *buffer) { char *p; int length; int status; int i; status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset + name_offset, SEEK_SET); length = 0; read(fd, &length, 1); /* Get the length byte */ read(fd, buffer, length); buffer[length] = 0; return buffer; } /********************************************************************** * GetModuleName */ char * GetModuleName(int fd, struct mz_header_s *mz_header, struct ne_header_s *ne_header, int index, char *buffer) { char *p; int length; int name_offset, status; int i; status = lseek(fd, mz_header->ne_offset + ne_header->moduleref_tab_offset + 2*(index - 1), SEEK_SET); name_offset = 0; read(fd, &name_offset, 2); status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset + name_offset, SEEK_SET); length = 0; read(fd, &length, 1); /* Get the length byte */ read(fd, buffer, length); buffer[length] = 0; return buffer; } /********************************************************************** * FixupSegment */ int FixupSegment(int fd, struct mz_header_s * mz_header, struct ne_header_s *ne_header, struct ne_segment_table_entry_s *seg_table, struct segment_descriptor_s *selector_table, int segment_num) { struct relocation_entry_s *rep, *rep1; struct ne_segment_table_entry_s *seg; struct segment_descriptor_s *sel; struct dll_table_entry_s *dll_table; unsigned short *sp; unsigned int selector, address; unsigned int next_addr; int ordinal; int status; char dll_name[257]; char func_name[257]; int i, n_entries; seg = &seg_table[segment_num]; sel = &selector_table[segment_num]; if (seg->seg_data_offset == 0) return 0; /* * Go through the relocation table on entry at a time. */ i = seg->seg_data_length; if (i == 0) i = 0x10000; status = lseek(fd, seg->seg_data_offset * 512 + i, SEEK_SET); n_entries = 0; read(fd, &n_entries, sizeof(short int)); rep = (struct relocation_entry_s *) malloc(n_entries * sizeof(struct relocation_entry_s)); if (read(fd,rep, n_entries * sizeof(struct relocation_entry_s)) != n_entries * sizeof(struct relocation_entry_s)) { myerror("Unable to read relocation information"); } rep1 = rep; for (i = 0; i < n_entries; i++, rep++) { /* * Get the target address corresponding to this entry. */ switch (rep->relocation_type) { case NE_RELTYPE_ORDINAL: if (GetModuleName(fd, mz_header, ne_header, rep->target1, dll_name) == NULL) { return -1; } dll_table = FindDLLTable(dll_name); ordinal = rep->target2; selector = dll_table[ordinal].selector; address = (unsigned int) dll_table[ordinal].address; #ifdef DEBUG_FIXUP printf("%d: %s.%d: %04.4x:%04.4x\n", i + 1, dll_name, ordinal, selector, address); #endif break; case NE_RELTYPE_NAME: if (GetModuleName(fd, mz_header, ne_header, rep->target1, dll_name) == NULL) { return -1; } dll_table = FindDLLTable(dll_name); if (GetImportedName(fd, mz_header, ne_header, rep->target2, func_name) == NULL) { return -1; } ordinal = FindOrdinalFromName(dll_table, func_name); selector = dll_table[ordinal].selector; address = (unsigned int) dll_table[ordinal].address; #ifdef DEBUG_FIXUP printf("%d: %s %s.%d: %04.4x:%04.4x\n", i + 1, func_name, dll_name, ordinal, selector, address); #endif break; case NE_RELTYPE_INTERNAL: default: free(rep1); return -1; } /* * Stuff the right size result in. */ sp = (unsigned short *) ((char *) sel->base_addr + rep->offset); switch (rep->address_type) { case NE_RADDR_OFFSET16: do { next_addr = *sp; *sp = (unsigned short) address; sp = (unsigned short *) ((char *) sel->base_addr + next_addr); } while (next_addr != 0xffff); break; case NE_RADDR_POINTER32: do { next_addr = *sp; *sp = (unsigned short) address; *(sp+1) = (unsigned short) selector; sp = (unsigned short *) ((char *) sel->base_addr + next_addr); } while (next_addr != 0xffff); break; default: free(rep1); return -1; } } free(rep1); return 0; }