Subversion Repositories Kolibri OS

Rev

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