├── LICENSE ├── README.md ├── build.sh ├── codelib.cpp ├── codelib.h ├── resfile.h ├── resstdfile.h └── symdump.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dynamic COFF object loader 2 | ========================== 3 | 4 | Tiny lib, can load .obj files into memory, link with other objects and provided functions. 5 | Can be used for in-game scripting. Currently 32-bit only. 6 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | i686-w64-mingw32-gcc -static -O2 codelib.cpp symdump.cpp -o symdump.exe -lstdc++ -limagehlp -------------------------------------------------------------------------------- /codelib.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "codelib.h" 8 | #include "resfile.h" 9 | 10 | #ifndef SAFE_DELETE 11 | #define SAFE_DELETE(p) { if (p) { delete (p); (p) = 0; } } 12 | #endif 13 | 14 | CCodeLib::CCodeLib() 15 | { 16 | alloctype = 0; 17 | image_ready = 0; 18 | image_size = bbs_size = 0; 19 | pimage = 0; 20 | bss_seg = 0; 21 | exports_num = 0; 22 | exports = 0; 23 | imports_num = 0; 24 | resolved_imports_num = 0; 25 | imports = 0; 26 | relocs_num = 0; 27 | relocs = 0; 28 | } 29 | 30 | void CCodeLib::Unload() 31 | { 32 | if (pimage) 33 | if (alloctype) VirtualFree(pimage, 0, MEM_RELEASE); else delete pimage; 34 | SAFE_DELETE(bss_seg); 35 | image_size = bbs_size = 0; 36 | pimage = 0; 37 | alloctype = 0; 38 | image_ready = 0; 39 | 40 | int i; 41 | for(i = 0; i < exports_num; i++) 42 | if (exports[i].name) delete exports[i].name; 43 | for(i = 0; i < imports_num; i++) 44 | if (imports[i].name) delete imports[i].name; 45 | exports_num = 0; 46 | imports_num = 0; 47 | resolved_imports_num = 0; 48 | relocs_num = 0; 49 | SAFE_DELETE(exports); 50 | SAFE_DELETE(imports); 51 | SAFE_DELETE(relocs); 52 | } 53 | 54 | int CCodeLib::LoadObjCode(CResFile *f) 55 | { 56 | Unload(); 57 | 58 | int imagesize = f->GetSize(); 59 | pimage = (BYTE*)VirtualAlloc(0, imagesize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 60 | if (!pimage) 61 | { 62 | printf("error: not enough memory %d", imagesize); 63 | return 0; 64 | } 65 | alloctype = 1; 66 | f->Read(pimage, imagesize); 67 | 68 | // setup pointers 69 | IMAGE_FILE_HEADER *fh = (IMAGE_FILE_HEADER *)pimage; 70 | if (fh->Machine != IMAGE_FILE_MACHINE_I386 || fh->SizeOfOptionalHeader != 0) 71 | { 72 | printf("error: invalid header"); 73 | return 0; 74 | } 75 | 76 | IMAGE_SECTION_HEADER *sections = (IMAGE_SECTION_HEADER *)(pimage + sizeof(IMAGE_FILE_HEADER)); 77 | BYTE **sections_data = new BYTE *[fh->NumberOfSections]; 78 | int i; 79 | // calculate section sizes statistics 80 | bbs_size = 0; 81 | code_size = 0; 82 | data_size = 0; 83 | rdata_size = 0; 84 | for (i = 0; i < fh->NumberOfSections; i++) 85 | { 86 | if (sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) 87 | { 88 | sections_data[i] = 0; 89 | bbs_size += sections[i].SizeOfRawData; 90 | } else 91 | sections_data[i] = pimage + sections[i].PointerToRawData; 92 | if (sections[i].Characteristics & IMAGE_SCN_CNT_CODE) 93 | { 94 | code_size += sections[i].SizeOfRawData; 95 | } else 96 | if (sections[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA && 97 | !(sections[i].Characteristics & IMAGE_SCN_MEM_DISCARDABLE) 98 | ) 99 | { 100 | if (sections[i].Characteristics & IMAGE_SCN_MEM_WRITE) 101 | data_size += sections[i].SizeOfRawData; 102 | else 103 | rdata_size += sections[i].SizeOfRawData; 104 | } 105 | } 106 | // allocate bss section if needed 107 | if (bbs_size) 108 | { 109 | bss_seg = new BYTE[bbs_size]; 110 | ZeroMemory(bss_seg, bbs_size); 111 | BYTE *pbbs = bss_seg; 112 | for (i = 0; i < fh->NumberOfSections; i++) 113 | if (sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) 114 | { 115 | sections_data[i] = pbbs; 116 | pbbs += sections[i].SizeOfRawData; 117 | } 118 | } 119 | IMAGE_SYMBOL *symbols = (IMAGE_SYMBOL *)(pimage + fh->PointerToSymbolTable); 120 | 121 | // process symbols 122 | exports_num = 0; 123 | imports_num = 0; 124 | for (i = 0; i < (int)fh->NumberOfSymbols; i++) 125 | { 126 | if (symbols[i].StorageClass == IMAGE_SYM_CLASS_EXTERNAL || 127 | (symbols[i].StorageClass == IMAGE_SYM_CLASS_STATIC && 128 | symbols[i].SectionNumber > 0 && symbols[i].NumberOfAuxSymbols == 0)) // TODO: remove static members 129 | if (symbols[i].SectionNumber == IMAGE_SYM_UNDEFINED) 130 | imports_num++; else exports_num++; 131 | i += symbols[i].NumberOfAuxSymbols; 132 | } 133 | exports = new symbol[exports_num]; 134 | if (!exports) return 0; 135 | imports = new symbol[imports_num]; 136 | if (!imports) return 0; 137 | 138 | char *string_table = (char*)&symbols[fh->NumberOfSymbols]; 139 | int nexp = 0, nimp = 0; 140 | for (i = 0; i < (int)fh->NumberOfSymbols; i++) 141 | { 142 | if (symbols[i].StorageClass == IMAGE_SYM_CLASS_EXTERNAL || 143 | (symbols[i].StorageClass == IMAGE_SYM_CLASS_STATIC && 144 | symbols[i].SectionNumber > 0 && symbols[i].NumberOfAuxSymbols == 0)) // TODO: remove static members 145 | { 146 | int len = 0; 147 | char *fname; 148 | char buf[256]; 149 | if (symbols[i].N.Name.Short != 0) 150 | { 151 | fname = (char*)&symbols[i].N.ShortName; 152 | sprintf(buf, "%.8s", fname); 153 | fname = buf; 154 | len = strlen(fname); 155 | } else 156 | { 157 | fname = string_table + symbols[i].N.Name.Long; 158 | len = strlen(fname); 159 | } 160 | int undlen = UnDecorateSymbolName(fname, buf, 256, UNDNAME_NAME_ONLY); 161 | char *undec_name = new char[undlen + 1]; 162 | strcpy(undec_name, buf); 163 | 164 | if (symbols[i].SectionNumber == IMAGE_SYM_UNDEFINED) 165 | { 166 | imports[nimp].undec_name = undec_name; 167 | imports[nimp].name = new char[len + 1]; 168 | strcpy(imports[nimp].name, fname); 169 | 170 | imports[nimp].address = 0; 171 | imports[nimp].size = 0; 172 | imports[nimp].type = 0; 173 | symbols[i].Value = nimp; 174 | nimp++; 175 | } else 176 | { 177 | exports[nexp].undec_name = undec_name; 178 | exports[nexp].name = new char[len + 1]; 179 | strcpy(exports[nexp].name, fname); 180 | 181 | int sect = symbols[i].SectionNumber - 1; 182 | exports[nexp].address = sections_data[sect] + symbols[i].Value; 183 | exports[nexp].size = sections[sect].SizeOfRawData - symbols[i].Value; 184 | // correct size if any other symbols present in this section 185 | for (int j = 0; j < (int)fh->NumberOfSymbols; j++) 186 | if (i != j && (symbols[j].SectionNumber - 1) == sect) 187 | { 188 | if (symbols[j].Value > symbols[i].Value) 189 | { 190 | int size = symbols[j].Value - symbols[i].Value; 191 | if (exports[nexp].size > size) 192 | exports[nexp].size = size; 193 | break; 194 | } 195 | } 196 | exports[nexp].type = 0; 197 | if (sections[sect].Characteristics & IMAGE_SCN_CNT_CODE) 198 | exports[nexp].type |= SYMBOL_TYPE_CODE; 199 | if (sections[sect].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) 200 | exports[nexp].type |= SYMBOL_TYPE_INITIALIZED_DATA; 201 | if (sections[sect].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) 202 | exports[nexp].type |= SYMBOL_TYPE_UNINITIALIZED_DATA; 203 | if (sections[sect].Characteristics & IMAGE_SCN_MEM_WRITE) 204 | exports[nexp].type |= SYMBOL_TYPE_WRITE; 205 | nexp++; 206 | } 207 | } 208 | if (symbols[i].NumberOfAuxSymbols) 209 | { 210 | IMAGE_AUX_SYMBOL *aux = (IMAGE_AUX_SYMBOL *)&symbols[i + 1]; 211 | aux = aux; 212 | } 213 | 214 | i += symbols[i].NumberOfAuxSymbols; 215 | } 216 | 217 | // rebase sections 218 | relocs_num = 0; 219 | for (i = 0; i < fh->NumberOfSections; i++) 220 | { 221 | /*if (strncmp((char*)§ions[i].Name[0], ".deb", 4) != 0 && 222 | strncmp((char*)§ions[i].Name[0], ".dre", 4) != 0) 223 | printf("%s %d\n", sections[i].Name, sections[i].SizeOfRawData);*/ 224 | if (sections[i].PointerToRelocations == 0) continue; 225 | if (sections[i].Characteristics & IMAGE_SCN_MEM_DISCARDABLE) continue; 226 | IMAGE_RELOCATION *rel = (IMAGE_RELOCATION *)(pimage + sections[i].PointerToRelocations); 227 | for (int j = 0; j < sections[i].NumberOfRelocations; j++) 228 | if (rel[j].Type == IMAGE_REL_I386_DIR32 || 229 | rel[j].Type == IMAGE_REL_I386_REL32) 230 | { 231 | void **p = (void**)(sections_data[i] + rel[j].VirtualAddress); 232 | int sym = rel[j].SymbolTableIndex; 233 | int sect = symbols[sym].SectionNumber; 234 | switch (sect) 235 | { 236 | case IMAGE_SYM_UNDEFINED: 237 | relocs_num++; 238 | continue; 239 | case IMAGE_SYM_ABSOLUTE: 240 | case IMAGE_SYM_DEBUG: 241 | continue; 242 | } 243 | void *address = sections_data[sect - 1] + symbols[sym].Value; 244 | if (rel[j].Type == IMAGE_REL_I386_REL32) 245 | *(DWORD*)p += (DWORD)((uintptr_t)address - (uintptr_t)p - sizeof(void*)); 246 | else 247 | *(DWORD*)p += (uintptr_t)address; 248 | } else if (rel[j].Type != IMAGE_REL_I386_ABSOLUTE) 249 | { // unsupported relocation 250 | printf("error: unsupported relocation"); 251 | return 0; 252 | } 253 | } 254 | 255 | // build relocations for imports 256 | resolved_imports_num = 0; 257 | relocs = new reloc[relocs_num]; 258 | int nreloc = 0; 259 | for (i = 0; i < fh->NumberOfSections; i++) 260 | { 261 | if (sections[i].PointerToRelocations == 0) continue; 262 | IMAGE_RELOCATION *rel = (IMAGE_RELOCATION *)(pimage + sections[i].PointerToRelocations); 263 | for (int j = 0; j < sections[i].NumberOfRelocations; j++) 264 | if (rel[j].Type == IMAGE_REL_I386_DIR32 || 265 | rel[j].Type == IMAGE_REL_I386_REL32) 266 | { 267 | int sym = rel[j].SymbolTableIndex; 268 | if (symbols[sym].SectionNumber == IMAGE_SYM_UNDEFINED) 269 | { 270 | relocs[nreloc].VirtualAddress = (void**)(sections_data[i] + rel[j].VirtualAddress); 271 | relocs[nreloc].imp_num = symbols[sym].Value; 272 | if (rel[j].Type == IMAGE_REL_I386_REL32) 273 | relocs[nreloc].imp_num |= 0x80000000; 274 | nreloc++; 275 | } 276 | } 277 | } 278 | 279 | delete sections_data; 280 | return 1; 281 | } 282 | 283 | int CCodeLib::LoadProcs(cfunction *funcs) 284 | { 285 | Unload(); 286 | exports_num = 0; 287 | int npointers = 0; 288 | for(;;exports_num++) 289 | { 290 | if (funcs[exports_num].name == 0) break; 291 | if (funcs[exports_num].type & FUNCTION_TYPE_CREATE_POINTER) npointers++; 292 | } 293 | 294 | void **paddr; 295 | if (npointers) 296 | { 297 | pimage = (BYTE*)new DWORD[npointers]; 298 | if (!pimage) return 0; 299 | alloctype = 0; 300 | paddr = (void **)pimage; 301 | } 302 | 303 | exports = new symbol[exports_num]; 304 | if (!exports) return 0; 305 | 306 | int ppointer = 0; 307 | for(int i = 0; i < exports_num; i++) 308 | { 309 | int len = strlen(funcs[i].name); 310 | exports[i].name = new char[len + 1]; 311 | strcpy(exports[i].name, funcs[i].name); 312 | char buf[256]; 313 | int undlen = UnDecorateSymbolName(funcs[i].name, buf, 256, UNDNAME_NAME_ONLY); 314 | exports[i].undec_name = new char[undlen + 1]; 315 | strcpy(exports[i].undec_name, buf); 316 | 317 | if (funcs[i].type & FUNCTION_TYPE_CREATE_POINTER) 318 | { 319 | paddr[ppointer] = funcs[i].address; 320 | exports[i].address = &paddr[ppointer]; 321 | ppointer++; 322 | } else 323 | exports[i].address = funcs[i].address; 324 | exports[i].size = 0; 325 | exports[i].type = SYMBOL_TYPE_CODE; 326 | } 327 | image_ready = 1; 328 | return 1; 329 | } 330 | 331 | int CCodeLib::Link(CCodeLib *lib) 332 | { 333 | int i; 334 | if (!relocs_num || !relocs || !imports_num || !imports) return 1; 335 | if (lib) 336 | { 337 | if (resolved_imports_num >= imports_num) 338 | return 1; 339 | for(i = 0; i < imports_num; i++) 340 | { 341 | if (imports[i].address) continue; 342 | symbol *sym = lib->FindSym(imports[i].name); 343 | if (sym) 344 | { 345 | if (!sym->address) continue; 346 | imports[i].address = sym->address; 347 | imports[i].size = sym->size; 348 | imports[i].type = sym->type; 349 | resolved_imports_num++; 350 | } 351 | } 352 | } 353 | /* for(i = 0; i < imports_num; i++) 354 | { 355 | if (imports[i].address) continue; 356 | MessageBox(0, imports[i].name, "Error", MB_OK | MB_ICONSTOP); 357 | }*/ 358 | if (resolved_imports_num >= imports_num) 359 | { 360 | if (image_ready) return 1; 361 | for(i = 0; i < relocs_num; i++) 362 | { 363 | int imp = relocs[i].imp_num & 0x7fffffff; 364 | if (imports[imp].address) 365 | { 366 | if (relocs[i].imp_num & 0x80000000) // relative ? 367 | *(DWORD*)relocs[i].VirtualAddress += (DWORD)((uintptr_t)imports[imp].address - (uintptr_t)relocs[i].VirtualAddress - 4); 368 | else 369 | *(DWORD*)relocs[i].VirtualAddress += (uintptr_t)imports[imp].address; 370 | } else return 0; 371 | } 372 | image_ready = 1; 373 | return 1; 374 | } 375 | return 0; 376 | } 377 | 378 | int CCodeLib::LinkMany(CCodeLib **lib, int libs) 379 | { 380 | for(int i = 0; i < libs; i++) 381 | { 382 | if (lib[i] == 0) continue; 383 | if (lib[i] == this) continue; 384 | Link(lib[i]); 385 | } 386 | return image_ready; 387 | } 388 | 389 | void *CCodeLib::FindSymAddr(char *sym_name) 390 | { 391 | for(int i = 0; i < exports_num; i++) 392 | if (strcmp(exports[i].name, sym_name) == 0) return exports[i].address; 393 | return 0; 394 | } 395 | 396 | void *CCodeLib::FindSymAddrUndec(char *und_fname) 397 | { 398 | for(int i = 0; i < exports_num; i++) 399 | if (strcmp(exports[i].undec_name, und_fname) == 0) return exports[i].address; 400 | return 0; 401 | } 402 | 403 | CCodeLib::symbol *CCodeLib::FindSym(char *sym_name) 404 | { 405 | for(int i = 0; i < exports_num; i++) 406 | if (strcmp(exports[i].name, sym_name) == 0) return &exports[i]; 407 | return 0; 408 | } 409 | 410 | CCodeLib::symbol *CCodeLib::FindSymUndec(char *und_sym_name) 411 | { 412 | for(int i = 0; i < exports_num; i++) 413 | if (strcmp(exports[i].undec_name, und_sym_name) == 0) return &exports[i]; 414 | return 0; 415 | } 416 | 417 | int CCodeLib::operator ()(char *fn_name) 418 | { 419 | if (!image_ready) return 0; 420 | symbol *sym = FindSymUndec(fn_name); 421 | if (!sym) return 0; 422 | if (!(sym->type & SYMBOL_TYPE_CODE)) return 0; 423 | 424 | void (__cdecl *func)() = (void (__cdecl *)())sym->address; 425 | func(); 426 | return 1; 427 | } 428 | -------------------------------------------------------------------------------- /codelib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define SYMBOL_TYPE_CODE 0x01 4 | #define SYMBOL_TYPE_INITIALIZED_DATA 0x02 5 | #define SYMBOL_TYPE_UNINITIALIZED_DATA 0x04 6 | #define SYMBOL_TYPE_WRITE 0x08 7 | 8 | #define FUNCTION_TYPE_CREATE_POINTER 0x01 9 | 10 | 11 | enum FunctionType 12 | { 13 | ft_cdecl, // Pushes parameters on the stack, in reverse order (right to left) 14 | ft_stdcall, // Pushes parameters on the stack, in reverse order (right to left) 15 | ft_fastcall // Stored in registers, then pushed on stack 16 | //ft_thiscall // Pushed on stack; this pointer stored in ECX 17 | }; 18 | 19 | struct cfunction 20 | { 21 | char *name; 22 | void *address; 23 | int type; 24 | }; 25 | 26 | class CResFile; 27 | 28 | class CCodeLib 29 | { 30 | struct reloc 31 | { 32 | void **VirtualAddress; 33 | int imp_num; 34 | }; 35 | struct symbol 36 | { 37 | char *name; 38 | char *undec_name; 39 | void *address; 40 | int size, type; 41 | }; 42 | int alloctype, image_ready, image_size, bbs_size, code_size, data_size, rdata_size; 43 | BYTE *pimage; 44 | BYTE *bss_seg; 45 | 46 | public: 47 | CCodeLib(); 48 | 49 | int exports_num; 50 | symbol *exports; 51 | int imports_num, resolved_imports_num; 52 | symbol *imports; 53 | int relocs_num; 54 | reloc *relocs; 55 | 56 | int LoadObjCode(CResFile *f); 57 | //int LoadDll(char *dllname,char **funcs); 58 | int LoadProcs(cfunction *funcs); 59 | int Link(CCodeLib *lib); 60 | int LinkMany(CCodeLib **lib, int libs); 61 | void Unload(); 62 | 63 | void *FindSymAddr(char *fname); 64 | void *FindSymAddrUndec(char *und_fname); 65 | 66 | symbol *FindSym(char *sym_name); 67 | symbol *FindSymUndec(char *und_sym_name); 68 | 69 | int operator ()(char *fn_name); 70 | 71 | int GetBSS_Size() { return bbs_size; } 72 | int GetCode_Size() { return code_size; } 73 | int GetData_Size() { return data_size; } 74 | int GetRData_Size() { return rdata_size; } 75 | }; 76 | -------------------------------------------------------------------------------- /resfile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class CResFile 5 | { 6 | public: 7 | virtual ~CResFile() {}; 8 | virtual size_t Read(void *p, size_t size)=0; // return 0 on error 9 | virtual size_t Write(const void *p, size_t size)=0; // return 0 on error 10 | virtual size_t GetSize()=0; // return -1 on error 11 | virtual size_t GetPos()=0; // return -1 on error 12 | virtual int SetPos(size_t pos)=0; // return 0 on error 13 | virtual int IsOpened()=0; // return 0 if object not connected with storage 14 | }; 15 | -------------------------------------------------------------------------------- /resstdfile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "resfile.h" 3 | #include 4 | #include 5 | #include 6 | 7 | // Standart C file implementation 8 | 9 | class CStandartResFile: public CResFile 10 | { 11 | FILE *f; 12 | public: 13 | // constructors 14 | CStandartResFile() 15 | { 16 | f = 0; 17 | } 18 | CStandartResFile(FILE *f) 19 | { 20 | this->f = f; 21 | } 22 | CStandartResFile(const char *filename) 23 | { 24 | f = ::fopen(filename, "rb"); 25 | } 26 | CStandartResFile(const char *filename, const char *mode) 27 | { 28 | f = ::fopen(filename, mode); 29 | } 30 | ~CStandartResFile() 31 | { 32 | if (f) fclose(f); 33 | } 34 | // CResFile 35 | size_t Read(void *p, size_t size) 36 | { 37 | return fread(p, 1, size, f); 38 | } 39 | size_t Write(const void *p, size_t size) 40 | { 41 | return fwrite(p, 1, size, f); 42 | } 43 | size_t GetSize() 44 | { 45 | if (!f) return -1; 46 | #ifdef _WIN32 47 | size_t pos = ftell(f); 48 | if (fseek(f, 0, SEEK_END)) 49 | return 0; 50 | size_t size = ftell(f); 51 | if (fseek(f, pos, SEEK_SET)) 52 | return 0; 53 | return size; 54 | #else //_WIN32 55 | struct stat s; 56 | if (fstat(fileno(f), &s) != 0) return 0; 57 | //if (s.st_size > 0xffffffff) return -1; 58 | return (size_t)s.st_size; 59 | #endif //_WIN32 60 | } 61 | size_t GetPos() 62 | { 63 | if (!f) return -1; 64 | return ftell(f); 65 | } 66 | int SetPos(size_t pos) 67 | { 68 | if (!f) return 0; 69 | return !fseek(f, (long)pos, SEEK_SET); 70 | } 71 | int IsOpened() 72 | { 73 | return f != 0; 74 | } 75 | // CStandartResFile 76 | int Open(const char *filename) 77 | { 78 | Close(); 79 | f = ::fopen(filename, "wb"); 80 | return (f != 0); 81 | } 82 | int Close() 83 | { 84 | if (f) fclose(f); f = 0; 85 | return 1; 86 | } 87 | int SetFile(FILE *f) 88 | { 89 | Close(); 90 | this->f = f; 91 | } 92 | static CResFile *fopen(const char *filename, const char *mode) 93 | { 94 | CResFile *f = new CStandartResFile(filename, mode); 95 | if (!f) return 0; 96 | if (!f->IsOpened()) { delete f; return 0; } 97 | return f; 98 | } 99 | void rewind() 100 | { 101 | ::rewind(f); 102 | } 103 | operator FILE*() 104 | { 105 | return f; 106 | } 107 | }; 108 | -------------------------------------------------------------------------------- /symdump.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "resstdfile.h" 7 | #include "codelib.h" 8 | 9 | class CScriptContainer 10 | { 11 | public: 12 | std::vector CodeLibs; 13 | std::vector Names; 14 | CScriptContainer(); 15 | int AddObject(CResFile *f, const char *name); 16 | int Link(); 17 | }; 18 | 19 | CScriptContainer::CScriptContainer() 20 | { 21 | } 22 | 23 | int CScriptContainer::AddObject(CResFile *f, const char *name) 24 | { 25 | CCodeLib *code = new CCodeLib; 26 | if (!code->LoadObjCode(f)) 27 | { 28 | printf("failed to load: %s\n", name); 29 | delete code; 30 | return 0; 31 | } 32 | CodeLibs.push_back(code); 33 | Names.push_back(name); 34 | return 1; 35 | } 36 | 37 | int CScriptContainer::Link() 38 | { 39 | int libs = CodeLibs.size(); 40 | for(int i = 0; i < libs; i++) 41 | { 42 | if (CodeLibs[i]->LinkMany(&CodeLibs[0], libs)) continue; 43 | } 44 | return 1; 45 | } 46 | 47 | int main(int argc,char* argv[]) 48 | { 49 | if (argc < 2) 50 | { 51 | printf("OBJ loader\n"); 52 | return 0; 53 | } 54 | CScriptContainer cont; 55 | /*CCodeLib lib; 56 | // -------------- Load 57 | cfunction funcs[]= 58 | { 59 | {"??2@YAPAXI@Z",operator new,0}, 60 | {"??3@YAXPAX@Z",operator delete,0}, 61 | {"_printf",printf,0}, 62 | {"_sprintf",sprintf,0}, 63 | {"_fopen",fopen,0}, 64 | {"_fclose",fclose,0}, 65 | {"_fread",fread,0}, 66 | {"_fseek",fseek,0}, 67 | {"_ftell",ftell,0}, 68 | {"__imp__MessageBoxA@16",MessageBoxA,FUNCTION_TYPE_CREATE_POINTER}, 69 | {"__imp__UnDecorateSymbolName@16",UnDecorateSymbolName,FUNCTION_TYPE_CREATE_POINTER}, 70 | {"__imp__VirtualAlloc@16",VirtualAlloc,FUNCTION_TYPE_CREATE_POINTER}, 71 | {"__imp__VirtualFree@12",VirtualFree,FUNCTION_TYPE_CREATE_POINTER}, 72 | {0,0} 73 | }; 74 | lib.LoadProcs(funcs);*/ 75 | 76 | int arg = 1; 77 | while(arg < argc) 78 | { 79 | CResFile *f = new CStandartResFile(argv[arg]); 80 | if (!f) 81 | return 0; 82 | cont.AddObject(f, argv[arg]); 83 | delete f; 84 | arg++; 85 | } 86 | cont.Link(); 87 | 88 | int i, undec = 1; 89 | char buf[1024]; 90 | int bbs_size = 0, code_size = 0, data_size = 0, rdata_size = 0; 91 | for(int l = 0; l < cont.CodeLibs.size(); l++) 92 | { 93 | CCodeLib *obj = cont.CodeLibs[l]; 94 | 95 | bbs_size += obj->GetBSS_Size(); 96 | code_size += obj->GetCode_Size(); 97 | data_size += obj->GetData_Size(); 98 | rdata_size += obj->GetRData_Size(); 99 | printf("\n%s sizes (code %d, rdata %d, data %d, bss %d):\n", cont.Names[l].c_str(), 100 | obj->GetCode_Size(), obj->GetRData_Size(), obj->GetData_Size(), obj->GetBSS_Size()); 101 | 102 | printf("exports:\n"); 103 | for(i = 0; i < obj->exports_num; i++) 104 | { 105 | if (undec) 106 | UnDecorateSymbolName(obj->exports[i].name, buf, 256, 0); 107 | else 108 | strcpy(buf, obj->exports[i].name); 109 | const char *type, *rw; 110 | if (obj->exports[i].type & SYMBOL_TYPE_CODE) type = "- function"; else 111 | if (obj->exports[i].type & SYMBOL_TYPE_INITIALIZED_DATA) type = "- initialized data"; else 112 | if (obj->exports[i].type & SYMBOL_TYPE_UNINITIALIZED_DATA) type = "- uninitialized data"; else 113 | type = "- unknown\n"; 114 | rw = (obj->exports[i].type & SYMBOL_TYPE_WRITE) ? "writable" : "read-only"; 115 | printf("(%i) %s %d %s(%s)\n", i, buf, obj->exports[i].size, type, rw); 116 | } 117 | 118 | printf("\nunresolved imports:\n"); 119 | for(i = 0; i < obj->imports_num;i++) 120 | { 121 | if (obj->imports[i].address) 122 | continue; 123 | if (undec) 124 | UnDecorateSymbolName(obj->imports[i].name, buf, 256, 0); 125 | else 126 | strcpy(buf, obj->imports[i].name); 127 | printf("(%i) %s ", i, buf); 128 | if (obj->imports[i].address) 129 | { 130 | if (obj->imports[i].type & SYMBOL_TYPE_CODE) printf("- function\n"); else 131 | if (obj->imports[i].type & SYMBOL_TYPE_INITIALIZED_DATA) printf("- initialized data\n"); else 132 | if (obj->imports[i].type & SYMBOL_TYPE_UNINITIALIZED_DATA) printf("- uninitialized data\n"); else 133 | printf("- unknown\n"); 134 | } else printf("(unresolved)\n"); 135 | } 136 | } 137 | printf("\ntotals: code %d, rdata %d, data %d, bss %d\n", 138 | code_size, rdata_size, data_size, bbs_size); 139 | 140 | return 0; 141 | } 142 | --------------------------------------------------------------------------------