Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
145 halyavin 1
/*
2
 *  TCCMEOS.C - KolibriOS/MenuetOS file output for the TinyC Compiler
6441 siemargl 3
 *
145 halyavin 4
 *  Copyright (c) 2006 Andrey Khalyavin
9284 Coldy 5
 *  Copyright (c) 2021 Coldy (KX extension)
145 halyavin 6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
609 andrew_pro 20
 */
21
 
9284 Coldy 22
#ifndef TCC_TARGET_KX
8786 turbocat 23
int undef_sym_flag=0;
9284 Coldy 24
#endif
8786 turbocat 25
 
609 andrew_pro 26
typedef struct {
27
	char magic[8];
28
	int version;
29
	int entry_point;
30
	int image_size;
31
	int memory_size;
32
	int stack;
33
	int params;
34
	int argv;
35
} IMAGE_MEOS_FILE_HEADER,*PIMAGE_MEOS_FILE_HEADER;
36
typedef struct _meos_section_info{
37
	int sh_addr;
38
	void* data;
39
	int data_size;
40
	int sec_num;
41
	struct _meos_section_info* next;
42
} meos_section_info;
9284 Coldy 43
#ifdef TCC_TARGET_KX
609 andrew_pro 44
typedef struct {
9284 Coldy 45
	void* data;
46
	int	  data_size;
47
} kx_import_table;
48
#endif
49
typedef struct {
609 andrew_pro 50
	TCCState* s1;
51
	IMAGE_MEOS_FILE_HEADER header;
52
	meos_section_info* code_sections;
53
	meos_section_info* data_sections;
9284 Coldy 54
#ifdef TCC_TARGET_KX
55
	kx_import_table* imp_table;
56
#endif
609 andrew_pro 57
	meos_section_info* bss_sections;
58
} me_info;
59
 
9284 Coldy 60
#ifdef TCC_TARGET_KX
61
	void kx_init(me_info* me);
62
	void kx_build_imports(me_info* me);
63
	long kx_get_header_length(me_info* me);
64
	void kx_write_header(me_info* me, FILE* f);
65
	void kx_write_imports(me_info* me, FILE* f);
66
	void kx_free(me_info* me);
67
#endif
68
 
6441 siemargl 69
int tcc_output_dbgme(const char *filename, me_info* me);
70
 
71
 
609 andrew_pro 72
meos_section_info* findsection(me_info* me,int num)
73
{
74
	meos_section_info* si;
75
	for(si=me->code_sections;si;si=si->next)
76
	{
77
		if (si->sec_num==num)
78
			return si;
79
	}
80
	for (si=me->data_sections;si;si=si->next)
81
	{
82
		if (si->sec_num==num)
83
			return si;
84
	}
85
	for (si=me->bss_sections;si;si=si->next)
86
	{
87
		if (si->sec_num==num)
88
			return si;
89
	}
90
	return (meos_section_info*)0;
91
}
92
 
93
void build_reloc(me_info* me)
94
{
95
	int flag;
6441 siemargl 96
	Elf32_Rel *rel = 0, *rel_ = 0, *rel_end = 0;
609 andrew_pro 97
	Section *sr;
98
	meos_section_info* s;
99
	meos_section_info* ss;
100
	s=me->code_sections;
101
	rel=0;
102
	rel_end=0;
103
	flag=0;
104
	for(;;)
105
	{
106
		sr=me->s1->sections[s->sec_num]->reloc;
107
		if (sr)
108
		{
145 halyavin 109
			rel = (Elf32_Rel *) sr->data;
609 andrew_pro 110
			rel_end = (Elf32_Rel *) (sr->data + sr->data_offset);
111
		}
112
		rel_=rel;
113
		while (rel_
114
			rel=rel_;
115
			int type = ELF32_R_TYPE(rel->r_info);
116
			rel_=rel+1;
145 halyavin 117
			if (type != R_386_PC32 && type != R_386_32)
609 andrew_pro 118
				continue;
119
			int sym = ELF32_R_SYM(rel->r_info);
120
			if (sym>symtab_section->data_offset/sizeof(Elf32_Sym))
121
				continue;
122
			Elf32_Sym* esym = ((Elf32_Sym *)symtab_section->data)+sym;
123
			int sect=esym->st_shndx;
9284 Coldy 124
      int sh_addr;
609 andrew_pro 125
			ss=findsection(me,sect);
6441 siemargl 126
			if (ss==0)
6429 siemargl 127
			{
9284 Coldy 128
        const char *sym_name = strtab_section->data + esym->st_name;
129
#ifdef TCC_TARGET_KX
130
				int sym_index = find_elf_sym(me->s1->dynsymtab_section, sym_name);
131
				Elf32_Sym* dyn_sym;
132
				if (sym_index == 0) {
133
#else
8786 turbocat 134
    			undef_sym_flag=1;
9284 Coldy 135
#endif
136
          tcc_error_noabort("undefined symbol '%s'", sym_name);
6429 siemargl 137
				continue;
9284 Coldy 138
#ifdef TCC_TARGET_KX
6429 siemargl 139
			}
9284 Coldy 140
				dyn_sym = &((ElfW(Sym) *)me->s1->dynsymtab_section->data)[sym_index];
141
				sh_addr = dyn_sym->st_value;
142
				if (sh_addr == 0) {
143
					tcc_error_noabort("symbol '%s' has zero value", sym_name);
144
					continue;
145
				}
146
#endif
147
			}
148
			else
149
				sh_addr = ss->sh_addr;
609 andrew_pro 150
			if (rel->r_offset>s->data_size)
151
				continue;
152
			if (type==R_386_PC32)
9284 Coldy 153
				*(int*)(rel->r_offset+s->data)+=/*ss->*/sh_addr+esym->st_value-rel->r_offset-s->sh_addr;
609 andrew_pro 154
			else if (type==R_386_32)
9284 Coldy 155
				*(int*)(rel->r_offset+s->data)+=/*ss->*/sh_addr+esym->st_value;
609 andrew_pro 156
		}
157
        rel=rel_;
158
		s=s->next;
6441 siemargl 159
		if (s==0) // what about multiple BSS sections ?
609 andrew_pro 160
		{
161
			if (flag) break;
162
			s=me->data_sections;
163
			if (s==0) break;
164
			flag=1;
165
			continue;
166
		}
167
	}
168
}
169
 
170
void assign_addresses(me_info* me)
171
{
172
	int i;
173
	meos_section_info* si;
174
	for (i=1;is1->nb_sections;i++)
175
	{
176
		Section* s=me->s1->sections[i];
177
		if (strcmp(".text",s->name)==0)
178
		{
179
			si=tcc_malloc(sizeof(meos_section_info));
180
			si->data=s->data;
181
			si->data_size=s->data_offset;
182
			si->next=me->code_sections;
183
			si->sec_num=i;
184
			me->code_sections=si;
185
			continue;
186
		}
187
		if (strcmp(".data",s->name)==0)
188
		{
189
			si=tcc_malloc(sizeof(meos_section_info));
190
			si->data=s->data;
191
			si->data_size=s->data_offset;
192
			si->next=me->data_sections;
193
			si->sec_num=i;
194
			me->data_sections=si;
195
			continue;
196
		}
197
		if (strcmp(".bss",s->name)==0)
198
		{
199
			si=tcc_malloc(sizeof(meos_section_info));
6441 siemargl 200
			si->data=s->data;
609 andrew_pro 201
			si->data_size=s->data_offset;
202
			si->next=me->bss_sections;
203
			si->sec_num=i;
204
			me->bss_sections=si;
205
			continue;
206
		}
207
	}
208
	int addr;
209
	addr=sizeof(IMAGE_MEOS_FILE_HEADER);
9284 Coldy 210
#ifdef TCC_TARGET_KX
211
	addr += kx_get_header_length(me);
212
#endif
609 andrew_pro 213
	for (si=me->code_sections;si;si=si->next)
214
	{
215
		si->sh_addr=addr;
216
		addr+=si->data_size;
217
	}
218
	for (si=me->data_sections;si;si=si->next)
219
	{
220
		si->sh_addr=addr;
221
		addr+=si->data_size;
222
	}
223
	me->header.image_size=addr;
9284 Coldy 224
#ifdef TCC_TARGET_KX
225
	kx_build_imports(me);
226
	addr = me->header.image_size;
227
#endif
609 andrew_pro 228
	for (si=me->bss_sections;si;si=si->next)
229
	{
230
		si->sh_addr=addr;
231
		addr+=si->data_size;
8157 Boppan 232
	}
6441 siemargl 233
	if (me->s1->pe_stack_size < 4096)
8157 Boppan 234
        addr+=4096;
6441 siemargl 235
    else
8157 Boppan 236
        addr += me->s1->pe_stack_size;
609 andrew_pro 237
	addr=(addr+4)&(~3);
238
	me->header.stack=addr;
239
	me->header.memory_size=addr;
240
	build_reloc(me);
241
}
6429 siemargl 242
 
243
 
6441 siemargl 244
const char *tcc_get_symbol_name(int st_name)
6429 siemargl 245
// return string by index from stringtable section
246
{
247
	const char *sym_name = strtab_section->data + st_name;
248
	return sym_name;
249
}
250
 
609 andrew_pro 251
int tcc_find_symbol_me(me_info* me, const char *sym_name)
252
{
253
	int i;
254
	int symtab;
255
	int strtab;
256
	symtab=0;
257
	strtab=0;
258
	for (i=1;is1->nb_sections;i++)
259
	{
260
		Section* s;
261
		s=me->s1->sections[i];
262
		if (strcmp(s->name,".symtab")==0)
263
		{
264
			symtab=i;
265
		}
266
		if (strcmp(s->name,".strtab")==0)
267
		{
268
			strtab=i;
269
		}
270
	}
271
	if (symtab==0 || strtab==0)
6429 siemargl 272
	{
273
        tcc_error_noabort("undefined sections .symtab or .strtab on linking '%s'", sym_name);
609 andrew_pro 274
		return 0;
6429 siemargl 275
	}
609 andrew_pro 276
	Elf32_Sym* s,*se;
277
	char* name;
278
	s=(Elf32_Sym*)me->s1->sections[symtab]->data;
279
	se=(Elf32_Sym*)(((void*)s)+me->s1->sections[symtab]->data_offset);
280
	name=(char*)me->s1->sections[strtab]->data;
281
	while (s
282
	{
283
		if (strcmp(name+s->st_name,sym_name)==0)
284
		{
285
			return s->st_value+findsection(me,s->st_shndx)->sh_addr;
286
		}
287
		s++;
288
	}
6429 siemargl 289
    tcc_error_noabort("undefined symbol '%s'", sym_name);
609 andrew_pro 290
	return 0;
291
}
6429 siemargl 292
 
609 andrew_pro 293
const char* me_magic="MENUET01";
294
int tcc_output_me(TCCState* s1,const char *filename)
295
{
296
	me_info me;
297
    int i;
298
    FILE* f;
299
    //printf("%d\n",s1->nb_sections);
300
	memset(&me,0,sizeof(me));
301
	me.s1=s1;
9284 Coldy 302
#ifdef TCC_TARGET_KX
303
	kx_init(&me);
304
#endif
609 andrew_pro 305
	relocate_common_syms();
306
	assign_addresses(&me);
9284 Coldy 307
#ifndef TCC_TARGET_KX
8786 turbocat 308
    if(undef_sym_flag){
309
       tcc_error("Linker error!");
310
    }
9284 Coldy 311
#endif
8786 turbocat 312
 
6441 siemargl 313
	if (s1->do_debug)
314
		tcc_output_dbgme(filename, &me);
315
 
609 andrew_pro 316
	me.header.entry_point=tcc_find_symbol_me(&me,"start");
317
	me.header.params= tcc_find_symbol_me(&me,"__argv"); // <--
318
	me.header.argv= tcc_find_symbol_me(&me,"__path"); // <--
6441 siemargl 319
 
8716 turbocat 320
	if((f=fopen(filename,"wb"))==NULL){
321
		tcc_error("could not create '%s': %s", filename, strerror(errno));
322
	}
323
 
609 andrew_pro 324
    for (i=0;i<8;i++)
325
        me.header.magic[i]=me_magic[i];
326
	fwrite(&me.header,1,sizeof(IMAGE_MEOS_FILE_HEADER),f);
9284 Coldy 327
#ifdef TCC_TARGET_KX
328
	kx_write_header(&me, f);
329
#endif
609 andrew_pro 330
	meos_section_info* si;
331
	for(si=me.code_sections;si;si=si->next)
332
		fwrite(si->data,1,si->data_size,f);
333
	for (si=me.data_sections;si;si=si->next)
8157 Boppan 334
		fwrite(si->data,1,si->data_size,f);
9284 Coldy 335
#ifdef TCC_TARGET_KX
336
	kx_write_imports(&me, f);
337
	kx_free(&me);
338
#else
8157 Boppan 339
	if (!s1->nobss)
6858 siemargl 340
	{
8157 Boppan 341
		for (si=me.bss_sections;si;si=si->next)
6858 siemargl 342
		{
8157 Boppan 343
	    	if (si->data == NULL)
344
			{
345
	//         	printf("\nError! BSS data is NULL! size:%i",(int)si->data_size);
346
	         	si->data = calloc(si->data_size, 1);
347
	      	}
348
			fwrite(si->data, 1, si->data_size, f);
349
		}
350
	}
351
/*
352
    if (me.bss_sections) // Siemargl testin, what we lose
353
    {
6441 siemargl 354
        tcc_error_noabort("We lose .BSS section when linking KOS32 executable");
8157 Boppan 355
    }
6441 siemargl 356
*/
9284 Coldy 357
#endif
609 andrew_pro 358
	fclose(f);
359
	return 0;
360
}
6429 siemargl 361
 
8677 turbocat 362
#if !defined(_WIN32) && !defined(TCC_TARGET_MEOS_LINUX)
6429 siemargl 363
 
364
static inline int get_current_folder(char* buf, int bufsize){
365
    register int val;
366
    asm volatile ("int $0x40":"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize));
367
    return val;
368
}
369
 
8678 turbocat 370
 
6429 siemargl 371
char *getcwd(char *buf, size_t size)
372
{
373
	int rc = get_current_folder(buf, size);
374
	if (rc > size)
375
	{
376
		errno = ERANGE;
377
		return 0;
378
	}
379
	else
380
		return buf;
381
}
382
 
383
#endif
8157 Boppan 384
 
385
 
386
static FILE *src_file;
387
static int next_src_line;
388
 
389
void close_source_file()
390
{
391
    if (src_file)
392
        fclose(src_file);
393
    src_file = NULL;
394
}
395
 
396
void load_source_file(char *fname)
397
{
398
    close_source_file();
6441 siemargl 399
    src_file = fopen(fname,"rt");
8157 Boppan 400
	if (!src_file) return;
401
	next_src_line = 1;
402
}
6441 siemargl 403
 
8157 Boppan 404
int get_src_lines(char *buf, int sz, int start, int end)
405
// 1 if read
406
{
407
    char line[255], *ch;
408
    strcpy(buf, "");
409
	if (!src_file) return 0;
410
    while (next_src_line < start) // skip
411
    {
412
        ch = fgets(line, sizeof line, src_file);
413
        if (!ch) return 0;
414
        next_src_line++;
415
    }
416
    while (next_src_line <= end)
417
    {
418
        ch = fgets(line, sizeof line, src_file);
419
        if (!ch) return 0;
420
        next_src_line++;
421
        strncat(buf, line, sz - strlen(buf) - 1);
422
    }
423
    // remove newlines
424
    for (ch = buf; *ch; ch++)
425
        if (strchr("\t\n\r", *ch)) *ch = ' ';
426
 
427
    return 1;
428
}
429
 
6441 siemargl 430
int tcc_output_dbgme(const char *filename, me_info* me)
431
// by Siemargl. Writes filename.dbg file for source code level debuggin with MTDBG
432
// return 1 on error
433
{
434
	FILE 	*fdbg;
8157 Boppan 435
	char	fname[400],
436
            buf[80]; // no more fits in mtdbg string
6441 siemargl 437
 
438
	strcpy(fname, filename);
439
	strcat(fname, ".dbg");
440
	fdbg = fopen(fname,"wt");
441
	if (!fdbg) return 1;
442
 
8157 Boppan 443
	meos_section_info *si, *ss;
444
    fputs(".text\n", fdbg); // just for mtbg
445
 
446
    // print symbol table with resolved addresses
447
    Elf32_Sym* esym;
448
    for (esym = (Elf32_Sym*)symtab_section->data; esym <= (Elf32_Sym*)(symtab_section->data + symtab_section->data_offset); esym++)
449
    {
450
        if (esym->st_info == 0 || esym->st_info == 4) continue;
6441 siemargl 451
        int sect = esym->st_shndx;
452
        ss = findsection(me, sect);
453
        const char *sym_name = strtab_section->data + esym->st_name;
454
        if (ss == 0)
455
        {
456
            fprintf(fdbg, "undefined symbol '%s' type(%d)\n", sym_name, esym->st_info);
457
            continue;
458
        }
459
        fprintf(fdbg, "0x%X %s\n", ss->sh_addr + esym->st_value, sym_name); // removed type(%d)   esym->st_info
8157 Boppan 460
    }
461
 
462
    fputs(".text source code links\n", fdbg); // just for mtbg
463
    // print symbol table with resolved addresses
464
    Stab_Sym *stab;
465
    char    *str = "", *cur_file = "???", cur_fun[255];
466
    int cur_line = 0, cur_fun_addr = 0, fun_flag = 0;
467
    strcpy(cur_fun, "fn???");
468
    for (stab = (Stab_Sym*)stab_section->data; stab <= (Stab_Sym*)(stab_section->data + stab_section->data_offset); stab++)
469
    {
470
        str = "";
471
        switch(stab->n_type)
472
        {
473
        case 100:   // source file, or path
474
            if (stab->n_strx)
475
            {
476
                cur_file = stabstr_section->data + stab->n_strx;
477
                load_source_file(cur_file);
478
            }
479
            else
480
                cur_file = "???";
481
            strcpy(cur_fun, "fn???");
482
            cur_line = 0;
483
            cur_fun_addr = 0;
484
            fun_flag = 0;
485
            break;
486
        case 36:    // func
487
            cur_fun_addr = 0;
488
            if (stab->n_strx)
489
            {
490
                strcpy(cur_fun, stabstr_section->data + stab->n_strx);
491
                str = strchr(cur_fun, ':');
492
                if (str) *str = '\0';
493
                cur_fun_addr = tcc_find_symbol_me(me, cur_fun);
494
                cur_line = stab->n_desc;
495
                fun_flag = 1;
496
                //fprintf(fdbg, "0x%X %s() line(%d)\n", cur_fun_addr, cur_fun, cur_line); // commented as conflicted with direct address
497
            }
498
            else
499
                strcpy(cur_fun, "fn???");
500
            break;
501
        case 68:    // N_SLINE
502
            if (stab->n_value == 0 ) continue;  // skip zero offset line
503
            if (fun_flag) // skip string {, as duplicates address
504
            {
505
                fun_flag = 0;
506
                continue;
507
            }
508
 
509
            int line;
510
            if (stab->n_desc > cur_line)
511
                line = cur_line + 1;
512
            else
513
                line = cur_line;
514
            //fprintf(fdbg, "0x%X LINES %d-%d \n", cur_fun_addr + stab->n_value, line,  stab->n_desc);
515
            if (get_src_lines(buf, sizeof buf, line, stab->n_desc))
516
                fprintf(fdbg, "0x%X %s\n", cur_fun_addr + stab->n_value, buf);
517
 
518
            cur_line = stab->n_desc;
519
            break;
520
        default:
521
            continue;
522
        }
523
/*
524
        if (stab->n_strx)
525
            str = stabstr_section->data + stab->n_strx;
526
        fprintf(fdbg, "0x%X type(%d) str(%s) desc(%d)\n", stab->n_value, stab->n_type, str, stab->n_desc);
527
*/
528
    }
529
 
530
/*        for(; si; si = si->next)
531
        {
532
            Section *sr;
6441 siemargl 533
            Elf32_Rel *rel, *rel_end;
534
            for(sr = me->s1->sections[si->sec_num]->reloc; sr; )
8157 Boppan 535
            {
6441 siemargl 536
                for (rel = (Elf32_Rel *) sr->data, rel_end = (Elf32_Rel *) (sr->data + sr->data_offset); rel < rel_end; rel++)
537
                {
538
                    int type = ELF32_R_TYPE(rel->r_info);
539
                    if (type != R_386_PC32 && type != R_386_32)
540
                        continue;
541
                    int sym = ELF32_R_SYM(rel->r_info);
542
                    if (sym > symtab_section->data_offset / sizeof(Elf32_Sym))
543
                        continue;
544
                    Elf32_Sym* esym = ((Elf32_Sym*)symtab_section->data) + sym;
545
                    int sect = esym->st_shndx;
546
                    ss = findsection(me, sect);
547
                    const char *sym_name = strtab_section->data + esym->st_name;
548
                    if (ss == 0)
549
                    {
550
                        fprintf(fdbg, "undefined symbol '%s'\n", sym_name);
551
                        continue;
552
                    }
553
                    if (rel->r_offset > si->data_size) continue;
554
                    fprintf(fdbg, "\t0x%X %s\n", ss->sh_addr + esym->st_value, sym_name);
555
                }
556
            }
8157 Boppan 557
        }
558
*/
6441 siemargl 559
    close_source_file();
560
	fclose(fdbg);
561
	return 0;
562
}