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 | }>>>>>>> |