Subversion Repositories Kolibri OS

Rev

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