Subversion Repositories Kolibri OS

Rev

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