Subversion Repositories Kolibri OS

Rev

Rev 9085 | Rev 9220 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9085 Boppan 1
#include 
8579 Boppan 2
#include 
3
#include 
4
#include 
5
#include 
6
#include 
7
 
8
#define EPEP_INST
9
#include "epep/epep.h"
10
 
8948 Boppan 11
const char *epep_errors[] = {
12
	"EPEP_ERR_SUCCESS",
13
	"EPEP_ERR_DATA_DIRECTORY_INDEX_IS_INVALID",
14
	"EPEP_ERR_SECTION_HEADER_INDEX_IS_INVALID",
15
	"EPEP_ERR_SYMBOL_INDEX_IS_INVALID",
16
	"EPEP_ERR_NOT_AN_OBJECT",
17
	"EPEP_ERR_ADDRESS_IS_OUT_OF_SECTION_RAW_DATA",
18
	"EPEP_ERR_OUTPUT_CAPACITY_IS_ZERO",
19
	"EPEP_ERR_OUTPUT_IS_NULL",
20
	"EPEP_ERR_ADDRESS_IS_OUT_OF_ANY_SECTION",
21
	"EPEP_ERR_EXPORT_ADDRESS_TABLE_ENTRY_NAME_NOT_FOUND",
22
	"EPEP_ERR_NO_BASE_RELOCATION_TABLE",
23
	"EPEP_ERR_BASE_RELOCATION_IS_ALREADY_END",
24
	"EPEP_ERR_INVALID_DATA_DIRECTORY_OFFSET",
25
	"EPEP_ERR_INVALID_SECTION_HEADER_OFFSET",
26
	"EPEP_ERR_INVALID_SECTION_DATA_OFFSET",
27
	"EPEP_ERR_INVALID_STRING_TABLE_SIZE_OFFSET",
28
	"EPEP_ERR_INVALID_SYMBOL_OFFSET",
29
	"EPEP_ERR_INVALID_IMPORT_DIRECTORY_OFFSET",
30
	"EPEP_ERR_INVALID_IMPORT_DIRECTORY_NAME_OFFSET",
31
	"EPEP_ERR_INVALID_LOOKUP_OFFSET",
32
	"EPEP_ERR_INVALID_LOOKUP_NAME_OFFSET",
33
	"EPEP_ERR_INVALID_EXPORT_TABLE_OFFSET",
34
	"EPEP_ERR_INVALID_DLL_NAME_OFFSET",
35
	"EPEP_ERR_INVALID_EXPORT_NAME_POINTER_OFFSET",
36
	"EPEP_ERR_INVALID_ORDINAL_TABLE_OFFSET",
37
	"EPEP_ERR_INVALID_EXPORT_NAME_OFFSET",
38
	"EPEP_ERR_INVALID_EXPORT_ADDRESS_OFFSET",
39
	"EPEP_ERR_INVALID_FORWARDER_OFFSET",
40
	"EPEP_ERR_INVALID_BASE_RELOCATION_BLOCK_OFFSET",
41
	"EPEP_ERR_INVALID_NEXT_BASE_RELOCATION_BLOCK_OFFSET",
42
	"EPEP_ERR_INVALID_BASE_RELOCATION_BLOCK_BASE_RELOCATION_OFFSET",
43
	"EPEP_ERR_INVALID_SECTION_RELOCATION_OFFSET",
44
	"EPEP_ERR_INVALID_LINENUMBER_OFFSET",
45
};
46
 
8579 Boppan 47
typedef char *pchar;
48
 
49
typedef struct {
50
	Epep epep;
51
	char *name;
52
	size_t *section_offsets;
53
} CoffObject;
54
 
55
typedef struct {
56
	size_t obj_id;
57
	size_t sec_id;
58
} ObjIdSecId;
59
 
60
typedef struct {
61
	ObjIdSecId *source;
62
	uint32_t characteristics;
63
	size_t size;
64
	size_t number_of_relocations;
65
} SectionInfo;
66
 
67
typedef struct {
68
	EpepCoffSymbol sym;
69
	EpepCoffSymbol *auxes;
70
	char *name;
71
	size_t object_index;
72
	size_t index;
73
} Symbol;
74
 
75
#define CDICT_VAL_T SectionInfo
76
#define CDICT_INST
77
#include "cdict/cdict.h"
78
 
79
#define CDICT_VAL_T Symbol
80
#define CDICT_INST
81
#include "cdict/cdict.h"
82
 
83
typedef struct {
84
	CoffObject *objects;
85
	char **section_names_set;
86
	CDict_CStr_SectionInfo info_per_section;
87
	CDict_CStr_Symbol symtab;
88
	char **sym_name_set;
89
	size_t number_of_symbols;
90
} ObjectIr;
91
 
92
#define CVEC_INST
93
#define CVEC_TYPE CoffObject
94
#include "cvec/cvec.h"
95
 
96
#define CVEC_INST
97
#define CVEC_TYPE size_t
98
#include "cvec/cvec.h"
99
 
100
#define CVEC_INST
101
#define CVEC_TYPE pchar
102
#include "cvec/cvec.h"
103
 
104
#define CVEC_INST
105
#define CVEC_TYPE char
106
#include "cvec/cvec.h"
107
 
108
#define CVEC_INST
109
#define CVEC_TYPE ObjIdSecId
110
#include "cvec/cvec.h"
111
 
112
#define CVEC_INST
113
#define CVEC_TYPE EpepCoffSymbol
114
#include "cvec/cvec.h"
115
 
8948 Boppan 116
#define ERROR_EPEP(epep) printf("Error: epep returned %u (%s) at "__FILE__":%u", \
117
                                (epep)->error_code, epep_errors[(epep)->error_code], __LINE__); exit(-1)
8579 Boppan 118
 
119
#define ERROR_CDICT(cdict) printf("Error: cdict returned %u at "__FILE__":%u", \
120
                                  (cdict)->error_code, __LINE__); exit(-1);
121
 
9084 Boppan 122
static int emit_logs;
123
 
9085 Boppan 124
static void log_info(const char *fmt, ...) {
9084 Boppan 125
	if (emit_logs) {
126
		va_list ap;
127
		va_start(ap, fmt);
128
		vprintf(fmt, ap);
129
		va_end(ap);
130
	}
131
}
132
 
8579 Boppan 133
static void fwrite8(FILE *f, uint8_t b) {
134
	fputc(b, f);
135
}
136
 
137
static void fwrite16(FILE *f, uint16_t w) {
138
	fputc((w & 0x00ff) >> 0, f);
139
	fputc((w & 0xff00) >> 8, f);
140
}
141
 
142
static void fwrite32(FILE *f, uint32_t d) {
143
	fputc((d & 0x000000ff) >> 0, f);
144
	fputc((d & 0x0000ff00) >> 8, f);
145
	fputc((d & 0x00ff0000) >> 16, f);
146
	fputc((d & 0xff000000) >> 24, f);
147
}
148
 
149
static size_t strtab_add(char **strtab, char *str) {
150
	size_t res = cvec_char_size(strtab);
151
 
152
	for (char *p = str; *p; p++) {
153
		cvec_char_push_back(strtab, *p);
154
	}
155
	cvec_char_push_back(strtab, '\0');
156
	return res + 4;
157
}
158
 
159
static size_t get_section_number(char ***section_names_set, char *sec_name) {
160
	for (size_t i = 0; i < cvec_pchar_size(section_names_set); i++) {
161
		char *it = cvec_pchar_at(section_names_set, i);
162
		if (!strcmp(it, sec_name)) {
163
			return i + 1;
164
		}
165
	}
166
	return 0;
167
}
168
 
169
static void add_name_to_set(char *sym_name, char ***set) {
170
	for (size_t i = 0; i < cvec_pchar_size(set); i++) {
171
		char *it = cvec_pchar_at(set, i);
172
		if (!strcmp(it, sym_name)) {
173
			return;
174
		}
175
	}
176
	cvec_pchar_push_back(set, sym_name);
177
}
178
 
9080 Boppan 179
static void build(ObjectIr *ir, const char *outname) {
180
	FILE *out = fopen(outname, "wb");
8579 Boppan 181
	char *strtab = cvec_char_new(1024);
182
	size_t size_of_sections = 0;
183
	size_t number_of_relocations = 0;
184
 
9084 Boppan 185
	log_info("Calculating all sections size and relocations count... ");
8579 Boppan 186
	for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
187
		char *name = ir->section_names_set[sec_i];
188
 
189
		SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
190
		size_of_sections += si.size;
191
		number_of_relocations += si.number_of_relocations;
192
	}
9084 Boppan 193
	log_info("Done: %u & %u\n", size_of_sections, number_of_relocations);
8579 Boppan 194
 
195
	size_t fisrt_section_offset = 20 + 40 * cvec_pchar_size(&ir->section_names_set);
196
	size_t offset_to_first_relocation = fisrt_section_offset + size_of_sections;
197
	size_t offset_to_next_relocation = offset_to_first_relocation;
198
	size_t next_section_offset = fisrt_section_offset;
199
 
200
	size_t PointerToSymbolTable = fisrt_section_offset + size_of_sections + number_of_relocations * 10;
201
 
202
	// COFF Header
9084 Boppan 203
	log_info("Writing COFF header... ");
8579 Boppan 204
	fwrite16(out, 0x14c);                                   // Machine
205
	fwrite16(out, cvec_pchar_size(&ir->section_names_set)); // NumberOfSections
206
	fwrite32(out, 0);                                       // TimeDataStamp
207
	fwrite32(out, PointerToSymbolTable);                    // PointerToSymbolTable
208
	fwrite32(out, ir->number_of_symbols);                   // NumberOfSymbols
209
	fwrite16(out, 0);                                       // SizeOfOptionalHeader
210
	fwrite16(out, 0);                                       // Characteristics
9084 Boppan 211
	log_info("Done.\n");
8579 Boppan 212
 
213
	// Section Headers
9084 Boppan 214
	log_info("Writing section headers {\n");
8579 Boppan 215
	for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
216
		char *name = ir->section_names_set[sec_i];
217
		SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
218
 
219
		// Name
9084 Boppan 220
		log_info(" Writing %s Section Header... ", name);
8579 Boppan 221
		if (strlen(name) <= 8) {
222
			for (size_t i = 0; i < 8; i++) {
223
				size_t sl = strlen(name);
224
				fwrite8(out, i < sl ? name[i] : '\0');
225
			}
226
		} else {
227
			fwrite8(out, '/');
228
 
229
			size_t strtab_index = strtab_add(&strtab, name);
230
			char numstr[8] = { 0 };
231
			sprintf(numstr, "%u", strtab_index);
232
			fwrite(numstr, 1, 7, out);
233
		}
234
		fwrite32(out, 0);                         // VirtualSize
235
		fwrite32(out, 0);                         // VirtualAddress
236
		fwrite32(out, si.size);                   // SizeOfRawData
237
		fwrite32(out, next_section_offset);       // PointerToRawData
238
		next_section_offset += si.size;
239
		fwrite32(out, offset_to_next_relocation); // PointerToRelocations
240
		offset_to_next_relocation += si.number_of_relocations * 10;
241
		fwrite32(out, 0);                         // PointerToLinenumbers
242
		fwrite16(out, si.number_of_relocations);  // NumberOfRelocations
243
		fwrite16(out, 0);                         // NumberOfLinenumbers
244
		fwrite32(out, si.characteristics);        // Characteristics
9084 Boppan 245
		log_info("Done.\n");
8579 Boppan 246
	}
9084 Boppan 247
	log_info("}\n");
8579 Boppan 248
 
249
	// Section data
9084 Boppan 250
	log_info("Writing sections {\n");
8579 Boppan 251
	for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
252
		char *name = ir->section_names_set[sec_i];
253
		SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
254
 
9084 Boppan 255
		log_info(" Writing %s... ", name);
8579 Boppan 256
		for (size_t i = 0; i < cvec_ObjIdSecId_size(&si.source); i++) {
257
			ObjIdSecId id = cvec_ObjIdSecId_at(&si.source, i);
258
			CoffObject *object = &ir->objects[id.obj_id];
259
			Epep *epep = &object->epep;
260
 
261
			EpepSectionHeader sh = { 0 };
262
			if (!epep_get_section_header_by_index(epep, &sh, id.sec_id)) {
263
				ERROR_EPEP(epep);
264
			}
8618 Boppan 265
 
266
			// If the section contains uninitialized data (BSS)
267
			// it should be filled by zeroes
268
			// Yes, current implementation emits BSS sections too
269
			// cause KOS has no idea they should be allocated automatically
270
			// cause FASM has no idea they should be generated without contents
271
			// cause Tomasz Grysztar didn't care
272
			char *buf = calloc(sh.SizeOfRawData, 1);
273
 
274
			// Othervice it should be filled by its contents from source object
275
			if (!(sh.Characteristics & 0x00000080)) {
276
				if (!epep_get_section_contents(epep, &sh, buf)) {
277
					ERROR_EPEP(epep);
278
				}
8579 Boppan 279
			}
8618 Boppan 280
 
8579 Boppan 281
			fwrite(buf, 1, sh.SizeOfRawData, out);
282
		}
9084 Boppan 283
		log_info("Done.\n");
8579 Boppan 284
	}
9084 Boppan 285
	log_info("}\n");
8579 Boppan 286
 
287
	// COFF Relocations
8959 Boppan 288
	char **undefined_symbols = cvec_pchar_new(8);
289
 
9084 Boppan 290
	log_info("Writing COFF Relocations {\n");
8579 Boppan 291
	for (size_t sec_i = 0; sec_i < cvec_pchar_size(&ir->section_names_set); sec_i++) {
292
		char *name = ir->section_names_set[sec_i];
293
		SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name);
294
 
9084 Boppan 295
		log_info(" Writing relocations of %s {\n", name);
8579 Boppan 296
		for (size_t i = 0; i < cvec_ObjIdSecId_size(&si.source); i++) {
297
			ObjIdSecId id = cvec_ObjIdSecId_at(&si.source, i);
298
			CoffObject *object = &ir->objects[id.obj_id];
299
			Epep *epep = &object->epep;
300
 
301
			size_t strtab_size = 0;
302
			if (!epep_get_string_table_size(epep, &strtab_size)) {
303
				ERROR_EPEP(epep);
304
			}
305
 
306
			char *obj_strtab = malloc(strtab_size);
307
			if (!epep_get_string_table(epep, obj_strtab)) {
308
				ERROR_EPEP(epep);
309
			}
310
 
311
			EpepSectionHeader sh = { 0 };
312
			if (!epep_get_section_header_by_index(epep, &sh, id.sec_id)) {
313
				ERROR_EPEP(epep);
314
			}
315
			for (size_t rel_i = 0; rel_i < sh.NumberOfRelocations; rel_i++) {
316
				EpepCoffRelocation rel = { 0 };
317
 
318
				if (!epep_get_section_relocation_by_index(epep, &sh, &rel, rel_i)) {
319
					ERROR_EPEP(epep);
320
				}
9084 Boppan 321
				log_info("  { %02x, %02x, %02x }", rel.VirtualAddress, rel.SymbolTableIndex, rel.Type);
8579 Boppan 322
				rel.VirtualAddress += object->section_offsets[sec_i];
323
				{
324
					size_t index = rel.SymbolTableIndex;
325
					EpepCoffSymbol sym = { 0 };
326
 
327
					if (!epep_get_symbol_by_index(epep, &sym, index)) {
328
						ERROR_EPEP(epep);
329
					}
330
 
331
					size_t name_max = 1024;
332
					char name[name_max];
333
 
334
					if (sym.symbol.Zeroes == 0) {
335
						strcpy(name, &obj_strtab[sym.symbol.Offset]);
336
					} else {
337
						memcpy(name, sym.symbol.ShortName, 8);
338
						name[8] = '\0';
339
					}
340
 
341
					if (!strcmp(name, "_EXPORTS")) {
342
						strcpy(name, "EXPORTS");
343
					}
344
 
345
					if (sym.symbol.StorageClass != 2) {
346
						sprintf(name, "%s@%s", name, object->name);
347
					}
348
 
349
					Symbol old_sym = cdict_CStr_Symbol_get_v(&ir->symtab, name);
350
 
351
					if (old_sym.name == NULL) {
8959 Boppan 352
						add_name_to_set(strdup(name), &undefined_symbols);
8579 Boppan 353
					}
354
 
355
					rel.SymbolTableIndex = old_sym.index;
9084 Boppan 356
					log_info(" -> { %02x, %02x, %02x }: ", rel.VirtualAddress, rel.SymbolTableIndex, rel.Type);
357
					log_info("New relocation of %s in %s\n", name, sh.Name);
8579 Boppan 358
				}
359
				fwrite(&rel, 1, 10, out);
360
			}
361
		}
9084 Boppan 362
		log_info(" }\n");
8579 Boppan 363
	}
9084 Boppan 364
	log_info("}\n");
8579 Boppan 365
 
8959 Boppan 366
	if (cvec_pchar_size(&undefined_symbols) > 0) {
367
		printf("Undefined symbols found, aborting\nUndefined:\n");
368
		for (int i = 0; i < cvec_pchar_size(&undefined_symbols); i++) {
369
			printf("%s\n", undefined_symbols[i]);
370
		}
371
		exit(-1);
372
	}
373
 
8579 Boppan 374
	// Symbols Table
9084 Boppan 375
	log_info("Writing symbols {\n");
8579 Boppan 376
	for (size_t sym_i = 0; sym_i < cvec_pchar_size(&ir->sym_name_set); sym_i++) {
377
		char *name = ir->sym_name_set[sym_i];
378
 
379
		Symbol sym = cdict_CStr_Symbol_get_v(&ir->symtab, name);
380
 
381
		if (sym.sym.symbol.SectionNumber == 0xffff ||
382
			sym.sym.symbol.SectionNumber == 0xfffe ||
9075 Boppan 383
			(sym.sym.symbol.StorageClass != 2 &&  // Not an external symbol
384
			 sym.sym.symbol.StorageClass != 3 &&  // Not a static symbol
385
			 sym.sym.symbol.StorageClass != 6)) { // Not a label
8579 Boppan 386
			fwrite(&sym.sym.symbol, 1, 18, out);
387
		} else {
388
			size_t sec_name_max = 1024;
389
			char sec_name[sec_name_max];
390
 
391
			size_t object_index = sym.object_index;
392
			CoffObject *object = &ir->objects[object_index];
393
			Epep *epep = &object->epep;
394
			size_t section_offset = object->section_offsets[sym.sym.symbol.SectionNumber - 1];
395
 
396
			size_t strtab_size = 0;
397
			if (!epep_get_string_table_size(epep, &strtab_size)) {
398
				ERROR_EPEP(epep);
399
			}
400
 
401
			char *obj_strtab = malloc(strtab_size);
402
			if (!epep_get_string_table(epep, obj_strtab)) {
403
				ERROR_EPEP(epep);
404
			}
405
 
406
			EpepSectionHeader sh = { 0 };
407
			if (!epep_get_section_header_by_index(epep, &sh, sym.sym.symbol.SectionNumber - 1)) {
408
				ERROR_EPEP(epep);
409
			}
410
 
411
			if (sh.Name[0] == '/') {
412
				strcpy(sec_name, &obj_strtab[atoi(&sh.Name[1])]);
413
			} else {
414
				memcpy(sec_name, sh.Name, 8);
415
				sec_name[8] = '\0';
416
			}
417
 
9084 Boppan 418
			log_info("%s:\n", sym.name);
419
			log_info(" Section:      %s\n", sec_name);
420
			log_info(" StorageClass: %u\n", sym.sym.symbol.StorageClass);
8579 Boppan 421
 
422
			sym.sym.symbol.SectionNumber = get_section_number(&ir->section_names_set, sec_name);
423
 
424
			if (sym.sym.symbol.SectionNumber == 0) {
9085 Boppan 425
				printf("Internal error: %s section is not found in output file", sec_name);
8579 Boppan 426
				exit(-1);
427
			}
428
 
429
			sym.sym.symbol.Value += section_offset;
430
 
431
			if (strlen(sym.name) <= 8) {
9075 Boppan 432
				memcpy(sym.sym.symbol.ShortName, sym.name, 8);
8579 Boppan 433
			} else {
434
				sym.sym.symbol.Zeroes = 0;
435
				sym.sym.symbol.Offset = strtab_add(&strtab, name);
436
			}
437
 
438
			fwrite(&sym.sym.symbol, 1, 18, out);
439
		}
440
		for (size_t aux_i = 0; aux_i < sym.sym.symbol.NumberOfAuxSymbols; aux_i++) {
441
			fwrite(&sym.auxes[aux_i].symbol, 1, 18, out);
442
		}
443
	}
9084 Boppan 444
	log_info("}\n");
8579 Boppan 445
 
446
	// COFF String Table
9084 Boppan 447
	log_info("Writing COFF String Table... ");
9085 Boppan 448
	fwrite32(out, cvec_char_size(&strtab) + 4);
449
	fwrite(strtab, 1, cvec_char_size(&strtab), out);
9084 Boppan 450
	log_info("Done.\n");
8579 Boppan 451
}
452
 
453
static ObjectIr parse_objects(int argc, char **argv) {
454
	CoffObject *objects = cvec_CoffObject_new(128);
455
	char **section_names_set = cvec_pchar_new(4);
456
	char **sym_name_set = cvec_pchar_new(128);
457
	size_t number_of_symbols = 0;
458
 
459
	for (int i = 1; i < argc; i++) {
9084 Boppan 460
		// If one arg is NULL, that means it was a parameter and was cleared
461
		// It's not a input file name
462
		if (argv[i] == NULL) {
463
			continue;
464
		}
8579 Boppan 465
 
9084 Boppan 466
		log_info("Primary parsing of %s... ", argv[i]);
467
 
8579 Boppan 468
		CoffObject object = { 0 };
469
		object.name = argv[i];
470
		object.section_offsets = cvec_size_t_new(128);
471
 
472
		{
473
			FILE *fp = fopen(object.name, "rb");
474
			if (!fp) {
475
				printf("Error: Can't open \"%s\"", object.name);
476
				exit(-1);
477
			}
478
 
479
			if (!epep_init(&object.epep, fp)) {
480
				ERROR_EPEP(&object.epep);
481
			}
482
		}
483
 
484
		cvec_CoffObject_push_back(&objects, object);
485
 
9084 Boppan 486
		log_info("Done.\n");
8579 Boppan 487
	}
488
 
489
	CDict_CStr_Symbol symtab;
490
 
491
	if (!cdict_CStr_Symbol_init(&symtab)) {
492
		ERROR_CDICT(&symtab);
493
	}
494
 
495
	CDict_CStr_SectionInfo info_per_section;
496
 
497
	if (!cdict_CStr_SectionInfo_init(&info_per_section)) {
498
		ERROR_CDICT(&info_per_section);
499
	}
500
 
501
	for (size_t i = 0; i < cvec_CoffObject_size(&objects); i++) {
9084 Boppan 502
		log_info("Secondary parsing of %s {\n", objects[i].name);
8579 Boppan 503
 
504
		Epep *epep = &(objects[i].epep);
505
 
506
		size_t strtab_size = 0;
507
		if (!epep_get_string_table_size(epep, &strtab_size)) {
508
			ERROR_EPEP(epep);
509
		}
510
 
511
		char *strtab = malloc(strtab_size);
512
		if (!epep_get_string_table(epep, strtab)) {
513
			ERROR_EPEP(epep);
514
		}
515
 
516
		// Fill symbols table
9084 Boppan 517
		log_info(" Symbols {\n");
8579 Boppan 518
		for (size_t sym_i = 0; sym_i < epep->coffFileHeader.NumberOfSymbols; sym_i++) {
519
			EpepCoffSymbol sym = { 0 };
520
 
521
			if (!epep_get_symbol_by_index(epep, &sym, sym_i)) {
522
				ERROR_EPEP(epep);
523
			}
524
 
525
			size_t name_max = 1024;
526
			char name[name_max];
527
 
528
			if (sym.symbol.Zeroes == 0) {
529
				strcpy(name, &strtab[sym.symbol.Offset]);
530
			} else {
531
				memcpy(name, sym.symbol.ShortName, 8);
532
				name[8] = '\0';
533
			}
534
 
535
			if (!strcmp(name, "_EXPORTS")) {
536
				strcpy(name, "EXPORTS");
537
			}
538
 
539
			if (sym.symbol.StorageClass != 2) {
540
				sprintf(name, "%s@%s", name, objects[i].name);
541
			}
542
 
543
			if (sym.symbol.StorageClass != 2 || sym.symbol.SectionNumber) {
544
				if (memcmp(cdict_CStr_Symbol_get_v(&symtab, name).sym.symbol.ShortName, "\0\0\0\0\0\0\0\0", 8)) {
545
					printf("Error: Redefinition of \"%s\"", name);
546
					exit(-1);
547
				}
548
 
549
				EpepCoffSymbol *auxes = cvec_EpepCoffSymbol_new(1);
550
				size_t index = number_of_symbols;
551
 
552
				for (size_t aux_i = 0; aux_i < sym.symbol.NumberOfAuxSymbols; aux_i++) {
553
					EpepCoffSymbol aux = { 0 };
554
 
555
					if (!epep_get_symbol_by_index(epep, &aux, sym_i + aux_i)) {
556
						ERROR_EPEP(epep);
557
					}
558
					cvec_EpepCoffSymbol_push_back(&auxes, aux);
559
					number_of_symbols++;
560
				}
561
 
562
				Symbol new_sym = { sym, auxes, strdup(name), i, index };
563
				if (!cdict_CStr_Symbol_add_vv(&symtab, strdup(name), new_sym, CDICT_NO_CHECK)) {
564
					ERROR_CDICT(&symtab);
565
				}
566
				number_of_symbols++;
567
 
9084 Boppan 568
				log_info("  Symbol #%u: %s (%u auxes, #%u)\n", sym_i, name, cvec_EpepCoffSymbol_size(&auxes), number_of_symbols - 1);
8579 Boppan 569
 
570
				add_name_to_set(strdup(name), &sym_name_set);
571
			}
572
 
573
			sym_i += sym.symbol.NumberOfAuxSymbols;
574
		}
9084 Boppan 575
		log_info(" }\n");
8579 Boppan 576
 
577
		// Set section offsets and fill unique section name set
9084 Boppan 578
		log_info(" Sections {\n");
8579 Boppan 579
		for (size_t sec_i = 0; sec_i < epep->coffFileHeader.NumberOfSections; sec_i++) {
580
			EpepSectionHeader sh = { 0 };
581
 
582
			if (!epep_get_section_header_by_index(epep, &sh, sec_i)) {
583
				ERROR_EPEP(epep);
584
			}
585
 
586
			size_t name_max = 1024;
587
			char name[name_max];
588
 
589
			if (sh.Name[0] == '/') {
590
				strcpy(name, &strtab[atoi(&sh.Name[1])]);
591
			} else {
592
				memcpy(name, sh.Name, 8);
593
				name[8] = '\0';
594
			}
595
 
596
			add_name_to_set(strdup(name), §ion_names_set);
597
 
598
			SectionInfo si = cdict_CStr_SectionInfo_get_v(&info_per_section, name);
599
			if (si.source == NULL) {
600
				si.source = cvec_ObjIdSecId_new(32);
601
			}
602
 
603
			size_t sec_offset = si.size;
604
			cvec_size_t_push_back(&objects[i].section_offsets, sec_offset);
605
 
606
			si.size += sh.SizeOfRawData;
607
			si.characteristics |= sh.Characteristics;
608
			si.number_of_relocations += sh.NumberOfRelocations;
609
			cvec_ObjIdSecId_push_back(&si.source, (ObjIdSecId){ i, sec_i });
610
			cdict_CStr_SectionInfo_add_vv(&info_per_section, strdup(name), si, CDICT_REPLACE_EXIST);
611
 
9084 Boppan 612
			log_info("  Section #%llu {\n", sec_i);
613
			log_info("   Name:                      %s\n", name);
614
			log_info("   Virtual Address:           %u\n", sh.VirtualAddress);
615
			log_info("   Characteristics:           %08x\n", sh.Characteristics);
616
			log_info("   Offset in the big section: %u\n", objects[i].section_offsets[sec_i]);
617
			log_info("  }\n");
9075 Boppan 618
 
619
			if (sh.VirtualAddress != 0) {
9084 Boppan 620
				printf("Warning: Handling of section with Virtual Address another that 0 is not implemented");
9075 Boppan 621
			}
8579 Boppan 622
		}
9084 Boppan 623
		log_info(" }\n");
624
		log_info("}\n");
8579 Boppan 625
	}
626
 
627
	ObjectIr ir;
628
	ir.objects = objects;
629
	ir.section_names_set = section_names_set;
630
	ir.info_per_section = info_per_section;
631
	ir.symtab = symtab;
632
	ir.sym_name_set = sym_name_set;
633
	ir.number_of_symbols = number_of_symbols;
634
	return ir;
635
}
636
 
9084 Boppan 637
int arg_got_flag(int argc, char **argv, ...) {
638
	char *arg_names[8];
639
	int arg_name_c = 0;
640
 
641
	va_list ap;
642
	va_start(ap, argv);
643
	for (char *arg_name = va_arg(ap, char *); arg_name; arg_name = va_arg(ap, char *)) {
644
		if (arg_name_c >= 8) {
645
			printf("Internal error: Too many parameter aliases passed to %s", __func__);
646
			exit(-1);
647
		}
648
		arg_names[arg_name_c++] = arg_name;
649
	}
650
	va_end(ap);
651
 
652
	for (int i = 1; i < argc; i++) {
9088 Boppan 653
		// If an argumetns was handled already then it's NULL here
654
		if (argv[i] == NULL) {
655
			continue;
656
		}
9084 Boppan 657
		for (int arg_name_i = 0; arg_name_i < arg_name_c; arg_name_i++) {
658
			char *arg_name = arg_names[arg_name_i];
659
			if (!strcmp(argv[i], arg_name)) {
660
				argv[i] = NULL; // Do not handle this argument as a input name
9088 Boppan 661
				return i;
9084 Boppan 662
			}
663
		}
664
	}
665
	return 0;
666
}
667
 
9088 Boppan 668
char *arg_got_param(int argc, char **argv, char *arg) {
669
	int i = arg_got_flag(argc, argv, arg, 0);
670
	if (i == 0) {
671
		return NULL;
672
	}
673
 
674
	if (i + 1 >= argc) {
675
		printf("Warning: %s parameter expects a value (like %s )", arg, arg);
676
		return NULL;
677
	}
678
	char *result = argv[i + 1];
679
	argv[i + 1] = NULL;
680
	return result;
681
}
682
 
683
int usage(char *name, char *remark) {
684
	if (remark) {
685
		printf("Error: %s\n\n", remark);
686
	}
687
	printf("Usage: %s [option]... [object file name]...\n", name);
688
	printf("  Link multiple COFF files into one\n");
689
	printf("\n");
690
	printf("Options:\n");
691
	printf("  -o   Output into \n");
692
	printf("  -v, --verbose Emit information logs\n");
693
	printf("  -h, --help    Output this help and exit\n");
694
	return 0;
695
}
696
 
8579 Boppan 697
int main(int argc, char **argv) {
9088 Boppan 698
	if (arg_got_flag(argc, argv, "-h", "-help", "--help", 0)) {
699
		return usage(argv[0], NULL);
700
	}
9080 Boppan 701
 
9088 Boppan 702
	const char *outname = arg_got_param(argc, argv, "-o");
703
	if (outname == NULL) {
704
		outname = "a.out.obj";
9080 Boppan 705
	}
706
 
9084 Boppan 707
	emit_logs = arg_got_flag(argc, argv, "-v", "-verbose", "--verbose", 0);
708
 
9088 Boppan 709
	// After handling arguments there only leaven unhandled ones
710
	// They should be names if inputs. But if there's no input - exit
711
	int input_file_count = 0;
712
	for (int i = 1; i < argc; i++) {
713
		if (argv[i] != NULL) {
714
			input_file_count++;
715
		}
716
	}
717
	if (input_file_count == 0) {
718
		return usage(argv[0], "No input file names supplied");
719
	}
720
 
8579 Boppan 721
	ObjectIr ir = parse_objects(argc, argv);
9080 Boppan 722
	build(&ir, outname);
8620 Boppan 723
	return 0;
8579 Boppan 724
}