Subversion Repositories Kolibri OS

Rev

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