/* dos.c * This file is part of Decomp - a disassembler. In this file are * routines for handling various types of DOS/Win32 executable types * i.e. PE, NE, MZ, and COM. * * Copyright (C) 2001 Jonathan duSaint * * Started early Feb 2002. */ /* not implemented yet */ #include #include #include "decomp.h" /* various defines for dos/win files */ #include "dos.h" /* void */ /* com_get_file_info (struct file_info *fi) */ /* { */ /* } */ /* MZ (legacy DOS executable) section */ void mz_get_file_info (struct file_info *fi) { } char * mz_read_strtab (struct file_info *fi) { return NULL; } struct symtab * mz_get_next_symbol (struct file_info *fi, char *strtab) { return NULL; } /* NE (Win16 New Executable) section */ void read_ne_header (struct ne_file_header *nh, FILE *fp) { d_read (nh->Signature, sizeof (char), 2, fp, 1); d_read (&nh->LinkerMajorVersion, sizeof (BYTE), 1, fp, 0); d_read (&nh->LinkerMinorVersion, sizeof (BYTE), 1, fp, 0); d_read (&nh->EntryTableOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->EntryTableSize, sizeof (WORD), 1, fp, 0); d_read (nh->Reserved, sizeof (BYTE), 4, fp, 1); d_read (&nh->Flags, sizeof (WORD), 1, fp, 0); d_read (&nh->AutoDataSegment, sizeof (WORD), 1, fp, 0); d_read (&nh->HeapSize, sizeof (WORD), 1, fp, 0); d_read (&nh->StackSize, sizeof (WORD), 1, fp, 0); d_read (&nh->CS, sizeof (WORD), 1, fp, 0); d_read (&nh->IP, sizeof (WORD), 1, fp, 0); d_read (&nh->SS, sizeof (WORD), 1, fp, 0); d_read (&nh->SP, sizeof (WORD), 1, fp, 0); d_read (&nh->SegmentTableEntries, sizeof (WORD), 1, fp, 0); d_read (&nh->ModuleRefTableEntries, sizeof (WORD), 1, fp, 0); d_read (&nh->NonresidentNameTableSize, sizeof (WORD), 1, fp, 0); d_read (&nh->SegmentTableOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->ResourceTableOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->ResidentNameTableOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->ModuleReferenceTableOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->ImportedNameTableOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->NonresidentNameTableOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->MovableEntryPoints, sizeof (WORD), 1, fp, 0); d_read (&nh->Alignment, sizeof (WORD), 1, fp, 0); d_read (&nh->ResourceSegments, sizeof (WORD), 1, fp, 0); d_read (&nh->OperatingSystem, sizeof (BYTE), 1, fp, 0); d_read (&nh->AdditionalInformation, sizeof (BYTE), 1, fp, 0); d_read (&nh->FastLoadSectorOffset, sizeof (WORD), 1, fp, 0); d_read (&nh->FastLoadSectorSize, sizeof (WORD), 1, fp, 0); d_read (&nh->Reserved1, sizeof (WORD), 1, fp, 0); d_read (&nh->WindowsVersion, sizeof (WORD), 1, fp, 0); } void ne_read_segment_header (struct ne_segment_header *sh, FILE *fp) { d_read (&sh->SegmentDataSectorOffset, sizeof (WORD), 1, fp, 0); d_read (&sh->SegmentLength, sizeof (WORD), 1, fp, 0); d_read (&sh->Flags, sizeof (WORD), 1, fp, 0); d_read (&sh->AllocationSize, sizeof (WORD), 1, fp, 0); } void ne_get_file_info (struct file_info *fi) { int k, n_code = 0, n_data = 0; WORD ne_header_pos, sector_size; DWORD addr; struct ne_file_header nh; fi->bit_size = BS_16; fi->arch = MT_IA32; fi->endian = BO_LITTLE_ENDIAN; /* position at NE header */ fseek (fi->fp, NE_POS_HEADER_OFFSET, SEEK_SET); d_read (&ne_header_pos, sizeof (WORD), 1, fi->fp, 0); fseek (fi->fp, ne_header_pos, SEEK_SET); read_ne_header (&nh, fi->fp); addr = fi->load_address = NE_MAKE_REAL_ADDRESS (nh.CS, nh.IP); sector_size = 1 << nh.Alignment; fi->data_sections = xmalloc ((nh.SegmentTableEntries + 1) * sizeof (struct section_info *)); fi->code_sections = xmalloc ((nh.SegmentTableEntries + 1) * sizeof (struct section_info *)); fseek (fi->fp, ne_header_pos + nh.SegmentTableOffset, SEEK_SET); for (k = 0; k < nh.SegmentTableEntries; k++) { char *section_name; WORD segment_size, loaded_segment_size; char *flags; struct ne_segment_header sh; ne_read_segment_header (&sh, fi->fp); /* NE doesn't have section names, so we create an arbitrary name */ section_name = xmalloc (18); segment_size = sh.SegmentLength ? sh.SegmentLength : 0xffff; loaded_segment_size = sh.AllocationSize ? sh.AllocationSize : 0xffff; flags = ""; if (NE_DATA_SEGMENT (sh.Flags)) { snprintf (section_name, 18, ".dataSection%d", n_data); if (debug) printf ("read data segment, idx %#x, offset %#x, size %#x\n", k, sh.SegmentDataSectorOffset * sector_size, segment_size); fi->data_sections[n_data] = alloc_section_info (section_name, DATA_SECTION, sh.SegmentDataSectorOffset * sector_size, segment_size, 0, k, addr, NULL, flags, nh.Alignment); put_data_limits (addr, addr + loaded_segment_size); n_data++; } else if (NE_CODE_SEGMENT (sh.Flags)) { snprintf (section_name, 18, ".codeSection%d", n_code); if (debug) printf ("read code segment, idx %#x, offset %#x, size %#x\n", k, sh.SegmentDataSectorOffset * sector_size, segment_size); fi->code_sections[n_code] = alloc_section_info (section_name, CODE_SECTION, sh.SegmentDataSectorOffset * sector_size, segment_size, 0, k, addr, NULL, flags, nh.Alignment); n_code++; } /* guess start address of next section */ addr = ((addr >> nh.Alignment) + 1) << nh.Alignment; } /* struct section_info *symtab; */ fi->symtab = NULL; /* struct section_info *strtab; */ fi->strtab = NULL; } char * ne_read_strtab (struct file_info *fi) { return NULL; } struct symtab * ne_get_next_symbol (struct file_info *fi, char *strtab) { return NULL; } /* PE (Win32 Portable Executable) section */ char *pe_flags[] = { "", /* no flags */ ", \"w\"", /* writeable */ ", \"x\"", /* executable */ ", \"xw\"", /* executable and writeable */ }; char * pe_get_flags (DWORD flags) { int index = 0; index |= ((flags & IMAGE_SCN_MEM_WRITE) ? 1 : 0); index |= ((flags & IMAGE_SCN_MEM_EXECUTE) ? 2 : 0); return pe_flags[index]; } int pe_get_align (DWORD flags) { return 1 << (((flags >> 20) & 0xf) - 1); } void read_pe_header (PCOFF_HEADER ch, FILE *fp) { d_read (&ch->PeSignature, sizeof (char), 4, fp, 1); d_read (&ch->Machine, sizeof (WORD), 1, fp, 0); d_read (&ch->NumberOfSections, sizeof (WORD), 1, fp, 0); d_read (&ch->TimeDateStamp, sizeof (DWORD), 1, fp, 0); d_read (&ch->PointerToSymbolTable, sizeof (DWORD), 1, fp, 0); d_read (&ch->NumberOfSymbols, sizeof (DWORD), 1, fp, 0); d_read (&ch->SizeOfOptionalHeader, sizeof (WORD), 1, fp, 0); d_read (&ch->Characteristics, sizeof (WORD), 1, fp, 0); } void read_pe_optional_header (PPE32_OPTIONAL_HEADER oh, FILE *fp, WORD oh_size) { WORD size = 0; d_read (&oh->Magic, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->MajorLinkerVersion, sizeof (BYTE), 1, fp, 0); size += sizeof (BYTE); d_read (&oh->MinorLinkerVersion, sizeof (BYTE), 1, fp, 0); size += sizeof (BYTE); d_read (&oh->SizeOfCode, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->SizeOfInitializedData, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->SizeOfUninitializedData, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->AddressOfEntryPoint, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->BaseOfCode, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); if (oh->Magic == PE32_MAGIC) { d_read (&oh->BaseOfData, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); } else oh->BaseOfData = 0; if (oh->Magic == PE32_MAGIC) { d_read (&oh->ImageBase, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); } else { QWORD temp; d_read (&temp, sizeof (QWORD), 1, fp, 0); size += sizeof (QWORD); oh->ImageBase = (DWORD) temp; } d_read (&oh->SectionAlignment, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->FileAlignment, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->MajorOperatingSystemVersion, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->MinorOperatingSystemVersion, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->MajorImageVersion, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->MinorImageVersion, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->MajorSubsystemVersion, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->MinorSubsystemVersion, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->Reserved, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->SizeOfImage, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->SizeOfHeaders, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->CheckSum, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->Subsystem, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); d_read (&oh->DLLCharacteristics, sizeof (WORD), 1, fp, 0); size += sizeof (WORD); if (oh->Magic == PE32_MAGIC) { d_read (&oh->SizeOfStackReserve, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); } else { QWORD temp; d_read (&temp, sizeof (QWORD), 1, fp, 0); size += sizeof (QWORD); oh->SizeOfStackReserve = (DWORD) temp; } if (oh->Magic == PE32_MAGIC) { d_read (&oh->SizeOfStackCommit, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); } else { QWORD temp; d_read (&temp, sizeof (QWORD), 1, fp, 0); size += sizeof (QWORD); oh->SizeOfStackCommit = (DWORD) temp; } if (oh->Magic == PE32_MAGIC) { d_read (&oh->SizeOfHeapReserve, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); } else { QWORD temp; d_read (&temp, sizeof (QWORD), 1, fp, 0); size += sizeof (QWORD); oh->SizeOfHeapReserve = (DWORD) temp; } if (oh->Magic == PE32_MAGIC) { d_read (&oh->SizeOfHeapCommit, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); } else { QWORD temp; d_read (&temp, sizeof (QWORD), 1, fp, 0); size += sizeof (QWORD); oh->SizeOfHeapCommit = (DWORD) temp; } d_read (&oh->LoaderFlags, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); d_read (&oh->NumberOfRvaAndSizes, sizeof (DWORD), 1, fp, 0); size += sizeof (DWORD); } void read_oh_data_directories (IMAGE_DATA_DIRECTORY idd[N_OHDD], FILE *fp, DWORD n_dd) { int k; for (k = 0; k < n_dd; k++) { d_read (&idd[k].RVA, sizeof (DWORD), 1, fp, 0); d_read (&idd[k].Size, sizeof (DWORD), 1, fp, 0); } } void read_pe_section_header (PSECTION_HEADER sh, FILE *fp) { d_read (sh->Name, sizeof (char), 8, fp, 1); d_read (&sh->VirtualSize, sizeof (DWORD), 1, fp, 0); d_read (&sh->VirtualAddress, sizeof (DWORD), 1, fp, 0); d_read (&sh->SizeOfRawData, sizeof (DWORD), 1, fp, 0); d_read (&sh->PointerToRawData, sizeof (DWORD), 1, fp, 0); d_read (&sh->PointerToRelocations, sizeof (DWORD), 1, fp, 0); d_read (&sh->PointerToLinenumbers, sizeof (DWORD), 1, fp, 0); d_read (&sh->NumberOfRelocations, sizeof (WORD), 1, fp, 0); d_read (&sh->NumberOfLinenumbers, sizeof (WORD), 1, fp, 0); d_read (&sh->Characteristics, sizeof (DWORD), 1, fp, 0); } char * get_pe_name (char *raw_name) { char *name; int count; for (count = 0; count < 8; count++) if (!raw_name[count]) break; name = xmalloc (count + 1); memcpy (name, raw_name, count); return name; } void pe_get_file_info (struct file_info *fi) { int n_code = 0, n_data = 0, k; char *section_name; DWORD pe_header_location; COFF_HEADER ch; PE32_OPTIONAL_HEADER oh; SECTION_HEADER sh; IMAGE_DATA_DIRECTORY idd[N_OHDD]; /* find the PE header */ fseek (fi->fp, PE_HEADER_OFFSET, SEEK_SET); d_read (&pe_header_location, sizeof (DWORD), 1, fi->fp, 0); fseek (fi->fp, pe_header_location, SEEK_SET); read_pe_header (&ch, fi->fp); switch (ch.Machine) { case IMAGE_FILE_MACHINE_ALPHA: fi->arch = MT_ALPHA; break; case IMAGE_FILE_MACHINE_I386: fi->arch = MT_IA32; break; default: fi->arch = MT_UNK; } if (ch.Characteristics & IMAGE_FILE_BYTES_REVERSED_LO) fi->endian = BO_LITTLE_ENDIAN; else if (ch.Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) fi->endian = BO_BIG_ENDIAN; if (ch.Characteristics & IMAGE_FILE_32BIT_MACHINE) fi->bit_size = BS_32; else if (ch.Characteristics & IMAGE_FILE_16BIT_MACHINE) /* won't see this */ fi->bit_size = BS_16; else fi->bit_size = BS_64; /* handle symbol table and string table */ if (ch.PointerToSymbolTable) { long file_pos; uint32_t strtab_size; fi->symtab = alloc_section_info (".symtab", OTHER_SECTION, ch.PointerToSymbolTable, ch.NumberOfSymbols * SIZE_SYMBOL_TABLE, SIZE_SYMBOL_TABLE, 0, 0, NULL, NULL, 0); /* read the size of the string table */ file_pos = ftell (fi->fp); fseek (fi->fp, (ch.PointerToSymbolTable + (ch.NumberOfSymbols * SIZE_SYMBOL_TABLE)), SEEK_SET); d_read (&strtab_size, sizeof (uint32_t), 1, fi->fp, 0); fseek (fi->fp, file_pos, SEEK_SET); strtab_size -= 4; fi->strtab = alloc_section_info (".strtab", STRING_SECTION, (ch.PointerToSymbolTable + (ch.NumberOfSymbols * SIZE_SYMBOL_TABLE)) + 4, strtab_size, 0, 0, 0, NULL, NULL, 0); } oh.NumberOfRvaAndSizes = 0; read_pe_optional_header (&oh, fi->fp, ch.SizeOfOptionalHeader); read_oh_data_directories (idd, fi->fp, oh.NumberOfRvaAndSizes); /* find load address */ fi->load_address = oh.ImageBase + oh.AddressOfEntryPoint; /* should be pointing at the section headers here */ fi->data_sections = xmalloc ((ch.NumberOfSections + 1) * sizeof (struct section_info)); fi->code_sections = xmalloc ((ch.NumberOfSections + 1) * sizeof (struct section_info)); for (k = 1; k < ch.NumberOfSections + 1; k++) { read_pe_section_header (&sh, fi->fp); section_name = get_pe_name (sh.Name); if (debug) printf ("read %s, idx %#x, offset %#x\n", section_name, k, sh.PointerToRawData); if (sh.Characteristics & IMAGE_SCN_CNT_CODE) /* code section */ { fi->code_sections[n_code] = alloc_section_info (section_name, CODE_SECTION, sh.PointerToRawData, sh.SizeOfRawData, 0, k, oh.ImageBase + sh.VirtualAddress, NULL, pe_get_flags (sh.Characteristics), pe_get_align (sh.Characteristics)); n_code++; put_data_limits (oh.ImageBase + sh.VirtualAddress, oh.ImageBase + sh.VirtualAddress + sh.VirtualSize); } else if (sh.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA || sh.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { fi->data_sections[n_data] = alloc_section_info (section_name, DATA_SECTION, sh.PointerToRawData, sh.SizeOfRawData, 0, k, oh.ImageBase + sh.VirtualAddress, NULL, pe_get_flags (sh.Characteristics), pe_get_align (sh.Characteristics)); n_data++; put_data_limits (oh.ImageBase + sh.VirtualAddress, oh.ImageBase + sh.VirtualAddress + sh.VirtualSize); } else /* not sure what this section could be */ { if (debug) printf ("unknown section: %s, flags: %08X\n", section_name, sh.Characteristics); xfree (section_name); } } /* print debug info */ if (debug) { k = -1; printf ("data:\n"); while (fi->data_sections[++k]) { printf (" %s (%#lx), %d, %#lx, %#lx, %#lx\n", fi->data_sections[k]->section_name, fi->data_sections[k]->section_index, fi->data_sections[k]->section_type, fi->data_sections[k]->section_offset, fi->data_sections[k]->section_size, fi->data_sections[k]->load_address); } k = -1; printf ("code:\n"); while (fi->code_sections[++k]) { printf (" %s (%#lx), %d, %#lx, %#lx, %#lx\n", fi->code_sections[k]->section_name, fi->code_sections[k]->section_index, fi->code_sections[k]->section_type, fi->code_sections[k]->section_offset, fi->code_sections[k]->section_size, fi->code_sections[k]->load_address); } if (fi->symtab != NULL) printf ("symtab:\n %s (%#lx), %d, %#lx, %#lx, %#lx\n", fi->symtab->section_name, fi->symtab->section_index, fi->symtab->section_type, fi->symtab->section_offset, fi->symtab->section_size, fi->symtab->load_address); if (fi->strtab != NULL) printf ("strtab:\n %s (%#lx), %d, %#lx, %#lx, %#lx\n", fi->strtab->section_name, fi->strtab->section_index, fi->strtab->section_type, fi->strtab->section_offset, fi->strtab->section_size, fi->strtab->load_address); } } char * pe_read_strtab (struct file_info *fi) { char *strtab; if (fi->strtab == NULL) return NULL; fseek (fi->fp, fi->strtab->section_offset, SEEK_SET); strtab = xmalloc (fi->strtab->section_size); d_read (strtab, sizeof (char), fi->strtab->section_size, fi->fp, 1); return strtab; } /* pe_read_symbol * Read a symbol from the symbol table. */ void pe_read_symbol (PCOFF_SYMBOL_TABLE sym, FILE *fp) { DWORD temp; d_read (&temp, sizeof (DWORD), 1, fp, 0); fseek (fp, -4, SEEK_CUR); if (temp != 0) d_read (sym->Name.ShortName, sizeof (char), 8, fp, 1); else { d_read (&sym->Name.LongName.Zeroes, sizeof (DWORD), 1, fp, 0); d_read (&sym->Name.LongName.Offset, sizeof (DWORD), 1, fp, 0); } d_read (&sym->Value, sizeof (DWORD), 1, fp, 0); d_read (&sym->SectionNumber, sizeof (WORD), 1, fp, 0); d_read (&sym->Type, sizeof (WORD), 1, fp, 0); d_read (&sym->StorageClass, sizeof (BYTE), 1, fp, 0); d_read (&sym->NumberOfAuxSymbols, sizeof (BYTE), 1, fp, 0); } /* pe_read_aux_format_one * Read in function definition information. */ void pe_read_aux_format_one (PAUXILIARY_FORMAT_ONE af, FILE *fp) { d_read (&af->TagIndex, sizeof (DWORD), 1, fp, 0); d_read (&af->TotalSize, sizeof (DWORD), 1, fp, 0); d_read (&af->PointerToLinenumber, sizeof (DWORD), 1, fp, 0); d_read (&af->PointerToNextFunction, sizeof (DWORD), 1, fp, 0); d_read (&af->Unused, sizeof (BYTE), 2, fp, 0); } /* pe_read_aux_format_two * Read in information on the .bf and .ef symbols. */ void pe_read_aux_format_two (PAUXILIARY_FORMAT_TWO af, FILE *fp) { d_read (&af->Unused1, sizeof (BYTE), 4, fp, 0); d_read (&af->Linenumber, sizeof (WORD), 1, fp, 0); d_read (&af->Unused2, sizeof (BYTE), 6, fp, 0); d_read (&af->PointerToNextFunction, sizeof (DWORD), 1, fp, 0); d_read (&af->Unused3, sizeof (BYTE), 2, fp, 0); } /* pe_read_aux_format_three * Read in information on weak external symbols. */ void pe_read_aux_format_three (PAUXILIARY_FORMAT_THREE af, FILE *fp) { d_read (&af->TagIndex, sizeof (DWORD), 1, fp, 0); d_read (&af->Characteristics, sizeof (DWORD), 1, fp, 0); d_read (&af->Unused, sizeof (BYTE), 10, fp, 0); } /* pe_read_aux_format_four * Read in information on a .file symbol. */ void pe_read_aux_format_four (PAUXILIARY_FORMAT_FOUR af, FILE *fp) { d_read (af->FileName, sizeof (char), 18, fp, 1); } /* pe_read_aux_format_five * Read in section definition information. */ void pe_read_aux_format_five (PAUXILIARY_FORMAT_FIVE af, FILE *fp) { d_read (&af->Length, sizeof (DWORD), 1, fp, 0); d_read (&af->NumberOfRelocations, sizeof (WORD), 1, fp, 0); d_read (&af->NumberOfLineNumbers, sizeof (WORD), 1, fp, 0); d_read (&af->CheckSum, sizeof (DWORD), 1, fp, 0); d_read (&af->Number, sizeof (WORD), 1, fp, 0); d_read (&af->Selection, sizeof (BYTE), 1, fp, 0); d_read (&af->Unused, sizeof (BYTE), 3, fp, 0); } enum symbol_type pe_get_symbol_type (WORD type, BYTE class) { if (((type >> 4) & 0xf) == IMAGE_SYM_DTYPE_FUNCTION) /* function */ { if (class == IMAGE_SYM_CLASS_EXTERNAL) return GLOBAL_FUNCTION; else return LOCAL_FUNCTION; } else /* data */ { if (class == IMAGE_SYM_CLASS_EXTERNAL) return GLOBAL_DATA; else return LOCAL_DATA; } return UNKNOWN_SYMBOL; } /* pe_get_next_symbol * Read in the next symbol from the symbol table and return * it as a struct symtab. */ struct symtab * pe_get_next_symbol (struct file_info *fi, char *strtab) { struct symtab *sym; COFF_SYMBOL_TABLE symbol; sym = xmalloc (sizeof (struct symtab)); pe_read_symbol (&symbol, fi->fp); /* get the symbol name */ if (symbol.Name.LongName.Zeroes != 0) sym->name = get_pe_name (symbol.Name.ShortName); else { sym->name = xmalloc (strlen (strtab + symbol.Name.LongName.Offset) + 1); strcpy (sym->name, strtab + symbol.Name.LongName.Offset); } sym->address = symbol.Value; /* most likely */ if (symbol.SectionNumber < 1) { sym->address = 0; sym->idx = 0; } else sym->idx = symbol.SectionNumber; /* if this is an external or static symbol, the load address is the Value added to the load address of the section */ if (symbol.StorageClass == IMAGE_SYM_CLASS_EXTERNAL || symbol.StorageClass == IMAGE_SYM_CLASS_STATIC) { if (symbol.SectionNumber > 0) { /* need to find the section with the matching number */ int k; for (k = 0; fi->code_sections[k] != NULL; k++) if (fi->code_sections[k]->section_index == symbol.SectionNumber) { sym->address = (fi->code_sections[k]->load_address + symbol.Value); goto GOT_SECTION_NUMBER; } for (k = 0; fi->data_sections[k] != NULL; k++) if (fi->data_sections[k]->section_index == symbol.SectionNumber) sym->address = (fi->data_sections[k]->load_address + symbol.Value); GOT_SECTION_NUMBER: ; } } sym->type = pe_get_symbol_type (symbol.Type, symbol.StorageClass); switch (symbol.Type & 0xf) { case IMAGE_SYM_TYPE_CHAR: case IMAGE_SYM_TYPE_BYTE: sym->size = 1; break; case IMAGE_SYM_TYPE_SHORT: sym->size = 2; break; case IMAGE_SYM_TYPE_INT: case IMAGE_SYM_TYPE_LONG: case IMAGE_SYM_TYPE_FLOAT: case IMAGE_SYM_TYPE_UINT: case IMAGE_SYM_TYPE_DWORD: sym->size = 4; break; case IMAGE_SYM_TYPE_DOUBLE: sym->size = 8; break; default: sym->size = 0; } if (sym->size == 0 && ((symbol.Type >> 4) & 0xf) == IMAGE_SYM_DTYPE_POINTER) { if (fi->bit_size == BS_32) sym->size = 4; else if (fi->bit_size == BS_64) sym->size = 8; } /* auxiliary data isn't necessarily used */ fseek (fi->fp, 18 * symbol.NumberOfAuxSymbols, SEEK_CUR); if (debug) printf ("%#lx:%s: size %lx, type %x, class %x, idx %lx\n", sym->address, sym->name, sym->size, symbol.Type, symbol.StorageClass, sym->idx); return sym; }