Subversion Repositories Kolibri OS

Rev

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

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