├── 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 |
--------------------------------------------------------------------------------