1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _scanmscoff.d) 9 */ 10 11 module ddmd.scanmscoff; 12 13 import core.stdc..string, core.stdc.stdlib, core.sys.windows.windows; 14 import ddmd.globals, ddmd.errors; 15 16 enum LOG = false; 17 18 /***************************************** 19 * Reads an object module from base[] and passes the names 20 * of any exported symbols to (*pAddSymbol)(). 21 * Params: 22 * pAddSymbol = function to pass the names to 23 * base = array of contents of object module 24 * module_name = name of the object module (used for error messages) 25 * loc = location to use for error printing 26 */ 27 void scanMSCoffObjModule(void delegate(const(char)[] name, int pickAny) pAddSymbol, 28 const(ubyte)[] base, const(char)* module_name, Loc loc) 29 { 30 static if (LOG) 31 { 32 printf("scanMSCoffObjModule(%s)\n", module_name); 33 } 34 35 void corrupt(int reason) 36 { 37 error(loc, "corrupt MS-Coff object module %s %d", module_name, reason); 38 } 39 40 const buf = base.ptr; 41 const buflen = base.length; 42 /* First do sanity checks on object file 43 */ 44 if (buflen < BIGOBJ_HEADER.sizeof) 45 return corrupt(__LINE__); 46 47 BIGOBJ_HEADER* header = cast(BIGOBJ_HEADER*)buf; 48 char is_old_coff = false; 49 if (header.Sig2 != 0xFFFF && header.Version != 2) 50 { 51 is_old_coff = true; 52 IMAGE_FILE_HEADER* header_old; 53 header_old = cast(IMAGE_FILE_HEADER*)malloc(IMAGE_FILE_HEADER.sizeof); 54 memcpy(header_old, buf, IMAGE_FILE_HEADER.sizeof); 55 header = cast(BIGOBJ_HEADER*)malloc(BIGOBJ_HEADER.sizeof); 56 *header = BIGOBJ_HEADER.init; 57 header.Machine = header_old.Machine; 58 header.NumberOfSections = header_old.NumberOfSections; 59 header.TimeDateStamp = header_old.TimeDateStamp; 60 header.PointerToSymbolTable = header_old.PointerToSymbolTable; 61 header.NumberOfSymbols = header_old.NumberOfSymbols; 62 free(header_old); 63 } 64 switch (header.Machine) 65 { 66 case IMAGE_FILE_MACHINE_UNKNOWN: 67 case IMAGE_FILE_MACHINE_I386: 68 case IMAGE_FILE_MACHINE_AMD64: 69 break; 70 default: 71 if (buf[0] == 0x80) 72 error(loc, "Object module %s is 32 bit OMF, but it should be 64 bit MS-Coff", module_name); 73 else 74 error(loc, "MS-Coff object module %s has magic = %x, should be %x", module_name, header.Machine, IMAGE_FILE_MACHINE_AMD64); 75 return; 76 } 77 // Get string table: string_table[0..string_len] 78 size_t off = header.PointerToSymbolTable; 79 if (off == 0) 80 { 81 error(loc, "MS-Coff object module %s has no string table", module_name); 82 return; 83 } 84 off += header.NumberOfSymbols * (is_old_coff ? SymbolTable.sizeof : SymbolTable32.sizeof); 85 if (off + 4 > buflen) 86 return corrupt(__LINE__); 87 88 uint string_len = *cast(uint*)(buf + off); 89 char* string_table = cast(char*)(buf + off + 4); 90 if (off + string_len > buflen) 91 return corrupt(__LINE__); 92 93 string_len -= 4; 94 for (int i = 0; i < header.NumberOfSymbols; i++) 95 { 96 SymbolTable32* n; 97 char[8 + 1] s; 98 char* p; 99 static if (LOG) 100 { 101 printf("Symbol %d:\n", i); 102 } 103 off = header.PointerToSymbolTable + i * (is_old_coff ? SymbolTable.sizeof : SymbolTable32.sizeof); 104 if (off > buflen) 105 return corrupt(__LINE__); 106 107 n = cast(SymbolTable32*)(buf + off); 108 if (is_old_coff) 109 { 110 SymbolTable* n2; 111 n2 = cast(SymbolTable*)malloc(SymbolTable.sizeof); 112 memcpy(n2, (buf + off), SymbolTable.sizeof); 113 n = cast(SymbolTable32*)malloc(SymbolTable32.sizeof); 114 memcpy(n, n2, (n2.Name).sizeof); 115 n.Value = n2.Value; 116 n.SectionNumber = n2.SectionNumber; 117 n.Type = n2.Type; 118 n.StorageClass = n2.StorageClass; 119 n.NumberOfAuxSymbols = n2.NumberOfAuxSymbols; 120 free(n2); 121 } 122 if (n.Zeros) 123 { 124 strncpy(s.ptr, cast(const(char)*)n.Name, 8); 125 s[SYMNMLEN] = 0; 126 p = s.ptr; 127 } 128 else 129 p = string_table + n.Offset - 4; 130 i += n.NumberOfAuxSymbols; 131 static if (LOG) 132 { 133 printf("n_name = '%s'\n", p); 134 printf("n_value = x%08lx\n", n.Value); 135 printf("n_scnum = %d\n", n.SectionNumber); 136 printf("n_type = x%04x\n", n.Type); 137 printf("n_sclass = %d\n", n.StorageClass); 138 printf("n_numaux = %d\n", n.NumberOfAuxSymbols); 139 } 140 switch (n.SectionNumber) 141 { 142 case IMAGE_SYM_DEBUG: 143 continue; 144 case IMAGE_SYM_ABSOLUTE: 145 if (strcmp(p, "@comp.id") == 0) 146 continue; 147 break; 148 case IMAGE_SYM_UNDEFINED: 149 // A non-zero value indicates a common block 150 if (n.Value) 151 break; 152 continue; 153 default: 154 break; 155 } 156 switch (n.StorageClass) 157 { 158 case IMAGE_SYM_CLASS_EXTERNAL: 159 break; 160 case IMAGE_SYM_CLASS_STATIC: 161 if (n.Value == 0) // if it's a section name 162 continue; 163 continue; 164 case IMAGE_SYM_CLASS_FUNCTION: 165 case IMAGE_SYM_CLASS_FILE: 166 case IMAGE_SYM_CLASS_LABEL: 167 continue; 168 default: 169 continue; 170 } 171 pAddSymbol(p[0 .. strlen(p)], 1); 172 } 173 } 174 175 align(1) 176 struct BIGOBJ_HEADER 177 { 178 WORD Sig1; // IMAGE_FILE_MACHINE_UNKNOWN 179 WORD Sig2; // 0xFFFF 180 WORD Version; // 2 181 WORD Machine; // identifies type of target machine 182 DWORD TimeDateStamp; // creation date, number of seconds since 1970 183 BYTE[16] UUID; // { '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b', 184 // '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8' }; 185 DWORD[4] unused; // { 0, 0, 0, 0 } 186 DWORD NumberOfSections; // number of sections 187 DWORD PointerToSymbolTable; // file offset of symbol table 188 DWORD NumberOfSymbols; // number of entries in the symbol table 189 } 190 191 align(1) 192 struct IMAGE_FILE_HEADER 193 { 194 WORD Machine; 195 WORD NumberOfSections; 196 DWORD TimeDateStamp; 197 DWORD PointerToSymbolTable; 198 DWORD NumberOfSymbols; 199 WORD SizeOfOptionalHeader; 200 WORD Characteristics; 201 } 202 203 enum SYMNMLEN = 8; 204 205 enum IMAGE_FILE_MACHINE_UNKNOWN = 0; // applies to any machine type 206 enum IMAGE_FILE_MACHINE_I386 = 0x14C; // x86 207 enum IMAGE_FILE_MACHINE_AMD64 = 0x8664; // x86_64 208 209 enum IMAGE_SYM_DEBUG = -2; 210 enum IMAGE_SYM_ABSOLUTE = -1; 211 enum IMAGE_SYM_UNDEFINED = 0; 212 213 enum IMAGE_SYM_CLASS_EXTERNAL = 2; 214 enum IMAGE_SYM_CLASS_STATIC = 3; 215 enum IMAGE_SYM_CLASS_LABEL = 6; 216 enum IMAGE_SYM_CLASS_FUNCTION = 101; 217 enum IMAGE_SYM_CLASS_FILE = 103; 218 219 align(1) struct SymbolTable32 220 { 221 union 222 { 223 BYTE[SYMNMLEN] Name; 224 struct 225 { 226 DWORD Zeros; 227 DWORD Offset; 228 } 229 } 230 231 DWORD Value; 232 DWORD SectionNumber; 233 WORD Type; 234 BYTE StorageClass; 235 BYTE NumberOfAuxSymbols; 236 } 237 238 align(1) struct SymbolTable 239 { 240 BYTE[SYMNMLEN] Name; 241 DWORD Value; 242 WORD SectionNumber; 243 WORD Type; 244 BYTE StorageClass; 245 BYTE NumberOfAuxSymbols; 246 }