Subversion Repositories Kolibri OS

Rev

Rev 9305 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9284 Coldy 1
/*
2
 *  TCCKX.C - KolibriOS/KX file output for the TinyC Compiler
3
 *
4
 *  Copyright (c) 2021 Coldy
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
19
 */
20
 
21
typedef struct {
22
	char magic[4];
23
	long flags;
24
	long i_ptr;
25
} kx_header;
26
 
27
static kx_header __kx_header = { 'K','X',0, 0, 0x40, 0 };
28
 
29
  typedef struct LibraryEntry {
30
	 uint32_t ImportEntry;
31
	 uint32_t LibraryName;
32
 };
33
 
34
 /*union ImportEntry {
35
 uint32_t ImportStr;
36
 uint32_t ImportPrt;
37
 };*/
38
 
39
 //static char __kx_import_table_sym[] = "__i_ptr__";
40
 
41
 void kx_build_imports(me_info* me) {
42
 
43
	 ElfW(Sym) *sym;
44
	 int sym_index, sym_end;
45
	 sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
46
	 CString *str_arr, *len_arr;
47
	 int nlib = 0;
48
	 int i;
49
 
50
	 if (me->header.version != 2)
51
		 return;
52
 
53
	 str_arr = tcc_malloc(sizeof(CString) * me->s1->nb_loaded_dlls);
54
	 if (str_arr == 0) {
55
		 return;
56
	 }
57
 
58
	 len_arr = tcc_malloc(sizeof(CString)* me->s1->nb_loaded_dlls);
59
	 if (len_arr == 0) {
60
		 tcc_free(str_arr);
61
		 return;
62
	 }
63
 
64
	 for (sym_index = 1; sym_index < sym_end; ++sym_index) {
65
		 sym = (ElfW(Sym) *)symtab_section->data + sym_index;
66
		 if (sym->st_shndx == SHN_UNDEF) {
67
			 const char *name = symtab_section->link->data + sym->st_name;
68
			 int dynsym_index = find_elf_sym(me->s1->dynsymtab_section, name);
69
 
70
			 if (dynsym_index == 0) {
71
				 //if (strcmp(name, __kx_import_table_sym) != 0) {
72
					 tcc_error/*_noabort*/("undefined symbol '%s'", name);
73
					 //continue; // FIXME: stop compile!
74
				 //}
75
 
76
				 //continue;
77
			 }
78
 
79
			 // KOS support 32 bit only
80
			 Elf32_Sym* dyn_sym = &((ElfW(Sym) *)me->s1->dynsymtab_section->data)[dynsym_index];
81
			 DLLReference **dllref = me->s1->loaded_dlls;
82
			 i = dyn_sym->st_size - 1;
83
			 // TCC store dll index in dyn_sym->st_size field
84
			 if (dllref[i]->level != -1) {
85
				 char* dll_name = dllref[i]->name;
86
				 char dll_len = strlen(dll_name) + 1;
87
 
88
				 nlib++;
89
 
90
				 cstr_new(&str_arr[i]);
91
				 cstr_new(&len_arr[i]);
92
 
93
				 cstr_ccat(&len_arr[i], dll_len);
94
				 cstr_cat(&str_arr[i], dll_name, dll_len);
95
				 //Mark dll as already used
96
				 dllref[i]->level = -1;
97
			 }
98
 
99
			 char name_len = strlen(name) + 1;
100
			 cstr_ccat(&len_arr[i], name_len);
101
			 cstr_cat(&str_arr[i], name, name_len);
102
 
103
		 }
104
	 }
105
 
106
	 /*if (len_arr[0].size == 0)
107
	 {
108
 
109
		 //tcc_error("");
110
		 return;
111
	 }*/
112
 
113
	 // Zero terminate of ptr (was BUG#3)
114
	 i = 0;
115
	 do {
116
 
117
		 cstr_ccat(&len_arr[i], 0);
118
 
119
		 i++;
120
 
121
	 } while (i < nlib);
122
 
123
	 kx_import_table* imp_sect;
124
 
125
	 imp_sect = tcc_mallocz(sizeof(kx_import_table));
126
	 imp_sect->data = tcc_mallocz(1024); // FIXME!!!
127
	 imp_sect->data_size = 0;
128
	 //imp_sect->sh_addr = me->header.image_size;// +1;
129
 
130
	long imp_data = imp_sect->data; //FIXME change to long for gcc compatible?
131
 
132
	 // Strings
133
	 i = 0;
134
	 do {
135
		 memcpy(imp_data, str_arr[i].data, str_arr[i].size);
136
		 imp_data += str_arr[i].size;
137
		 imp_sect->data_size += str_arr[i].size;
138
 
139
		 i++;
140
 
141
	 } while (i < nlib);
142
 
143
	 // Align pad (check algorithm!)
144
	 int align = 4 - (me->header.image_size + imp_sect->data_size) % 4;
145
	 imp_data += align;
146
	 imp_sect->data_size += align;
147
 
148
	 /*add_elf_sym(
149
		 me->s1->dynsymtab_section,
150
		 me->header.image_size + imp_sect->data_size,
151
		 0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
152
		 0, SHN_ABS, __kx_import_table_sym);*/
153
	 __kx_header.i_ptr = me->header.image_size + imp_sect->data_size;
154
 
155
	 struct LibraryEntry lib;
156
	 lib.ImportEntry = me->header.image_size + imp_sect->data_size + (nlib * 8) + 4;
157
	 lib.LibraryName = me->header.image_size + 0;
158
 
159
	 // LibraryEntry
160
	 memcpy(imp_data, &lib, sizeof(struct LibraryEntry));
161
 
162
	 if (nlib > 1) {
163
		 int prev = 0;
164
		 i = 1;
165
		 do {
166
			 lib.ImportEntry += (len_arr[prev].size - 2) * 4 + 4; //TODO: check that +4 is correct
167
			 lib.LibraryName = me->header.image_size + str_arr[prev].size;
168
			 imp_data += sizeof(struct LibraryEntry);
169
			 imp_sect->data_size += sizeof(struct LibraryEntry);
170
			 memcpy(imp_data, &lib, sizeof(struct LibraryEntry));
171
 
172
			 prev++;
173
			 i++;
174
 
175
		 } while (i < nlib);
176
	 }
177
 
178
	 // End of LibraryEntry
179
	 imp_data += sizeof(struct LibraryEntry) + 4;
180
	 imp_sect->data_size += sizeof(struct LibraryEntry) + 4;
181
 
182
	 char name_len;
183
	 long l, nl;
184
 
185
	 l = me->header.image_size;
186
	 i = 0;
187
	 do {
188
		 char* len_data = len_arr[i].data;
189
 
190
		 name_len = *len_data++; // Skip library name
191
		 nl = name_len;
192
 
193
		 do {
194
			 const char *name = (const char *)str_arr[i].data + nl;
195
 
196
			 add_elf_sym(
197
				 me->s1->dynsymtab_section,
198
				 me->header.image_size + imp_sect->data_size,
199
				 0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
200
				 0, SHN_ABS, name);
201
 
202
			 l += name_len;
203
			 memcpy(imp_data, &l, 4);
204
 
205
			 imp_data += 4;
206
			 imp_sect->data_size += 4;
207
			 name_len = */*++*/len_data/*++*/;		//(was BUG#3)
208
 
209
			 nl = nl + name_len;
210
 
211
		 } while (/*name_len*/*(++len_data) > 0);
212
 
213
		 imp_data += 4;
214
		 imp_sect->data_size += 4;
215
 
216
		 l += name_len;
217
		 i++;
218
 
219
	 } while (i < nlib);
220
 
221
	 me->header.image_size += imp_sect->data_size;
222
	 me->imp_table = imp_sect;
223
 
224
	 tcc_free(str_arr);
225
	 tcc_free(len_arr);
226
 
227
 }
228
 
229
 
230
 
231
 void kx_init(me_info* me) {
232
	 ElfW(Sym) *sym;
233
	 int sym_index = 1, sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
234
	 // Check that we have at last one import...
235
	 for (; sym_index < sym_end; ++sym_index) {
236
		 sym = (ElfW(Sym) *)symtab_section->data + sym_index;
237
		 if (sym->st_shndx == SHN_UNDEF)
238
			 break;
239
	 }
240
	 if ((sym_index < sym_end) &&
241
		 // ... and user attached at last one *.def
242
		 (me->s1->nb_loaded_dlls))
243
			me->header.version = 2;
244
 
245
	 //tcc_add_crt(me->s1, "start1.o");
246
 }
247
 
248
 long kx_get_header_length(me_info* me) {
249
	 if (me->header.version = 2)
250
		 return sizeof(kx_header);
251
 
252
	 return 0;
253
 }
254
 
255
 void kx_write_header(me_info* me, FILE* f) {
256
	 if (me->header.version = 2)
257
		 fwrite(&__kx_header, 1, sizeof(kx_header), f);
258
 }
259
 
260
 void kx_write_imports(me_info* me, FILE* f) {
261
	 if (me->imp_table)
262
		 fwrite(me->imp_table->data, 1, me->imp_table->data_size, f);
263
 
264
 }
265
 
266
 void kx_free(me_info* me) {
267
	 kx_import_table* imp = me->imp_table;
268
	 if (imp){
269
		 tcc_free(imp->data);
270
		 tcc_free(imp);
271
	}
272
 }