Rev 647 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
145 | halyavin | 1 | /* |
2 | * COFF file handling for TCC |
||
3 | * |
||
4 | * Copyright (c) 2003, 2004 TK |
||
5 | * Copyright (c) 2004 Fabrice Bellard |
||
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 |
||
20 | */ |
||
21 | |||
6429 | siemargl | 22 | #include "tcc.h" |
23 | |||
145 | halyavin | 24 | #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */ |
25 | #define MAX_STR_TABLE 1000000 |
||
26 | AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */ |
||
27 | |||
28 | SCNHDR section_header[MAXNSCNS]; |
||
29 | |||
30 | #define MAX_FUNCS 1000 |
||
31 | #define MAX_FUNC_NAME_LENGTH 128 |
||
32 | |||
33 | int nFuncs; |
||
34 | char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; |
||
35 | char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH]; |
||
36 | int LineNoFilePtr[MAX_FUNCS]; |
||
37 | int EndAddress[MAX_FUNCS]; |
||
38 | int LastLineNo[MAX_FUNCS]; |
||
39 | int FuncEntries[MAX_FUNCS]; |
||
40 | |||
6429 | siemargl | 41 | int OutputTheSection(Section * sect); |
145 | halyavin | 42 | short int GetCoffFlags(const char *s); |
43 | void SortSymbolTable(void); |
||
44 | Section *FindSection(TCCState * s1, const char *sname); |
||
45 | |||
46 | int C67_main_entry_point; |
||
47 | |||
48 | int FindCoffSymbolIndex(const char *func_name); |
||
49 | int nb_syms; |
||
50 | |||
51 | typedef struct { |
||
52 | long tag; |
||
53 | long size; |
||
54 | long fileptr; |
||
55 | long nextsym; |
||
56 | short int dummy; |
||
57 | } AUXFUNC; |
||
58 | |||
59 | typedef struct { |
||
60 | long regmask; |
||
61 | unsigned short lineno; |
||
62 | unsigned short nentries; |
||
63 | int localframe; |
||
64 | int nextentry; |
||
65 | short int dummy; |
||
66 | } AUXBF; |
||
67 | |||
68 | typedef struct { |
||
69 | long dummy; |
||
70 | unsigned short lineno; |
||
71 | unsigned short dummy1; |
||
72 | int dummy2; |
||
73 | int dummy3; |
||
74 | unsigned short dummy4; |
||
75 | } AUXEF; |
||
76 | |||
6429 | siemargl | 77 | ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f) |
145 | halyavin | 78 | { |
79 | Section *tcc_sect; |
||
80 | SCNHDR *coff_sec; |
||
81 | int file_pointer; |
||
82 | char *Coff_str_table, *pCoff_str_table; |
||
83 | int CoffTextSectionNo, coff_nb_syms; |
||
84 | FILHDR file_hdr; /* FILE HEADER STRUCTURE */ |
||
85 | Section *stext, *sdata, *sbss; |
||
86 | int i, NSectionsToOutput = 0; |
||
87 | |||
6429 | siemargl | 88 | Coff_str_table = pCoff_str_table = NULL; |
89 | |||
145 | halyavin | 90 | stext = FindSection(s1, ".text"); |
91 | sdata = FindSection(s1, ".data"); |
||
92 | sbss = FindSection(s1, ".bss"); |
||
93 | |||
94 | nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); |
||
95 | coff_nb_syms = FindCoffSymbolIndex("XXXXXXXXXX1"); |
||
96 | |||
97 | file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */ |
||
98 | file_hdr.f_timdat = 0; /* time & date stamp */ |
||
99 | file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */ |
||
100 | file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */ |
||
101 | file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */ |
||
102 | |||
103 | o_filehdr.magic = 0x0108; /* see magic.h */ |
||
104 | o_filehdr.vstamp = 0x0190; /* version stamp */ |
||
105 | o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */ |
||
106 | o_filehdr.dsize = sdata->data_offset; /* initialized data " " */ |
||
107 | o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */ |
||
108 | o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */ |
||
109 | o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */ |
||
110 | o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */ |
||
111 | |||
112 | |||
113 | // create all the section headers |
||
114 | |||
115 | file_pointer = FILHSZ + sizeof(AOUTHDR); |
||
116 | |||
117 | CoffTextSectionNo = -1; |
||
118 | |||
119 | for (i = 1; i < s1->nb_sections; i++) { |
||
120 | coff_sec = §ion_header[i]; |
||
121 | tcc_sect = s1->sections[i]; |
||
122 | |||
123 | if (OutputTheSection(tcc_sect)) { |
||
124 | NSectionsToOutput++; |
||
125 | |||
126 | if (CoffTextSectionNo == -1 && tcc_sect == stext) |
||
127 | CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is |
||
128 | |||
129 | strcpy(coff_sec->s_name, tcc_sect->name); /* section name */ |
||
130 | |||
131 | coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */ |
||
132 | coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */ |
||
133 | coff_sec->s_size = tcc_sect->data_offset; /* section size */ |
||
134 | coff_sec->s_scnptr = 0; /* file ptr to raw data for section */ |
||
135 | coff_sec->s_relptr = 0; /* file ptr to relocation */ |
||
136 | coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */ |
||
137 | coff_sec->s_nreloc = 0; /* number of relocation entries */ |
||
138 | coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */ |
||
139 | coff_sec->s_reserved = 0; /* reserved byte */ |
||
140 | coff_sec->s_page = 0; /* memory page id */ |
||
141 | |||
142 | file_pointer += sizeof(SCNHDR); |
||
143 | } |
||
144 | } |
||
145 | |||
146 | file_hdr.f_nscns = NSectionsToOutput; /* number of sections */ |
||
147 | |||
148 | // now loop through and determine file pointer locations |
||
149 | // for the raw data |
||
150 | |||
151 | |||
152 | for (i = 1; i < s1->nb_sections; i++) { |
||
153 | coff_sec = §ion_header[i]; |
||
154 | tcc_sect = s1->sections[i]; |
||
155 | |||
156 | if (OutputTheSection(tcc_sect)) { |
||
157 | // put raw data |
||
158 | coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */ |
||
159 | file_pointer += coff_sec->s_size; |
||
160 | } |
||
161 | } |
||
162 | |||
163 | // now loop through and determine file pointer locations |
||
164 | // for the relocation data |
||
165 | |||
166 | for (i = 1; i < s1->nb_sections; i++) { |
||
167 | coff_sec = §ion_header[i]; |
||
168 | tcc_sect = s1->sections[i]; |
||
169 | |||
170 | if (OutputTheSection(tcc_sect)) { |
||
171 | // put relocations data |
||
172 | if (coff_sec->s_nreloc > 0) { |
||
173 | coff_sec->s_relptr = file_pointer; /* file ptr to relocation */ |
||
174 | file_pointer += coff_sec->s_nreloc * sizeof(struct reloc); |
||
175 | } |
||
176 | } |
||
177 | } |
||
178 | |||
179 | // now loop through and determine file pointer locations |
||
180 | // for the line number data |
||
181 | |||
182 | for (i = 1; i < s1->nb_sections; i++) { |
||
183 | coff_sec = §ion_header[i]; |
||
184 | tcc_sect = s1->sections[i]; |
||
185 | |||
186 | coff_sec->s_nlnno = 0; |
||
187 | coff_sec->s_lnnoptr = 0; |
||
188 | |||
6429 | siemargl | 189 | if (s1->do_debug && tcc_sect == stext) { |
145 | halyavin | 190 | // count how many line nos data |
191 | |||
192 | // also find association between source file name and function |
||
193 | // so we can sort the symbol table |
||
194 | |||
195 | |||
196 | Stab_Sym *sym, *sym_end; |
||
197 | char func_name[MAX_FUNC_NAME_LENGTH], |
||
198 | last_func_name[MAX_FUNC_NAME_LENGTH]; |
||
199 | unsigned long func_addr, last_pc, pc; |
||
200 | const char *incl_files[INCLUDE_STACK_SIZE]; |
||
201 | int incl_index, len, last_line_num; |
||
202 | const char *str, *p; |
||
203 | |||
204 | coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */ |
||
205 | |||
206 | |||
207 | func_name[0] = '\0'; |
||
208 | func_addr = 0; |
||
209 | incl_index = 0; |
||
210 | last_func_name[0] = '\0'; |
||
211 | last_pc = 0xffffffff; |
||
212 | last_line_num = 1; |
||
213 | sym = (Stab_Sym *) stab_section->data + 1; |
||
214 | sym_end = |
||
215 | (Stab_Sym *) (stab_section->data + |
||
216 | stab_section->data_offset); |
||
217 | |||
218 | nFuncs = 0; |
||
219 | while (sym < sym_end) { |
||
220 | switch (sym->n_type) { |
||
221 | /* function start or end */ |
||
222 | case N_FUN: |
||
223 | if (sym->n_strx == 0) { |
||
224 | // end of function |
||
225 | |||
226 | coff_sec->s_nlnno++; |
||
227 | file_pointer += LINESZ; |
||
228 | |||
229 | pc = sym->n_value + func_addr; |
||
230 | func_name[0] = '\0'; |
||
231 | func_addr = 0; |
||
232 | EndAddress[nFuncs] = pc; |
||
233 | FuncEntries[nFuncs] = |
||
234 | (file_pointer - |
||
235 | LineNoFilePtr[nFuncs]) / LINESZ - 1; |
||
236 | LastLineNo[nFuncs++] = last_line_num + 1; |
||
237 | } else { |
||
238 | // beginning of function |
||
239 | |||
240 | LineNoFilePtr[nFuncs] = file_pointer; |
||
241 | coff_sec->s_nlnno++; |
||
242 | file_pointer += LINESZ; |
||
243 | |||
244 | str = |
||
245 | (const char *) stabstr_section->data + |
||
246 | sym->n_strx; |
||
247 | |||
248 | p = strchr(str, ':'); |
||
249 | if (!p) { |
||
250 | pstrcpy(func_name, sizeof(func_name), str); |
||
251 | pstrcpy(Func[nFuncs], sizeof(func_name), str); |
||
252 | } else { |
||
253 | len = p - str; |
||
254 | if (len > sizeof(func_name) - 1) |
||
255 | len = sizeof(func_name) - 1; |
||
256 | memcpy(func_name, str, len); |
||
257 | memcpy(Func[nFuncs], str, len); |
||
258 | func_name[len] = '\0'; |
||
259 | } |
||
260 | |||
261 | // save the file that it came in so we can sort later |
||
262 | pstrcpy(AssociatedFile[nFuncs], sizeof(func_name), |
||
263 | incl_files[incl_index - 1]); |
||
264 | |||
265 | func_addr = sym->n_value; |
||
266 | } |
||
267 | break; |
||
268 | |||
269 | /* line number info */ |
||
270 | case N_SLINE: |
||
271 | pc = sym->n_value + func_addr; |
||
272 | |||
273 | last_pc = pc; |
||
274 | last_line_num = sym->n_desc; |
||
275 | |||
276 | /* XXX: slow! */ |
||
277 | strcpy(last_func_name, func_name); |
||
278 | |||
279 | coff_sec->s_nlnno++; |
||
280 | file_pointer += LINESZ; |
||
281 | break; |
||
282 | /* include files */ |
||
283 | case N_BINCL: |
||
284 | str = |
||
285 | (const char *) stabstr_section->data + sym->n_strx; |
||
286 | add_incl: |
||
287 | if (incl_index < INCLUDE_STACK_SIZE) { |
||
288 | incl_files[incl_index++] = str; |
||
289 | } |
||
290 | break; |
||
291 | case N_EINCL: |
||
292 | if (incl_index > 1) |
||
293 | incl_index--; |
||
294 | break; |
||
295 | case N_SO: |
||
296 | if (sym->n_strx == 0) { |
||
297 | incl_index = 0; /* end of translation unit */ |
||
298 | } else { |
||
299 | str = |
||
300 | (const char *) stabstr_section->data + |
||
301 | sym->n_strx; |
||
302 | /* do not add path */ |
||
303 | len = strlen(str); |
||
304 | if (len > 0 && str[len - 1] != '/') |
||
305 | goto add_incl; |
||
306 | } |
||
307 | break; |
||
308 | } |
||
309 | sym++; |
||
310 | } |
||
311 | } |
||
312 | |||
313 | } |
||
314 | |||
315 | file_hdr.f_symptr = file_pointer; /* file pointer to symtab */ |
||
316 | |||
6429 | siemargl | 317 | if (s1->do_debug) |
145 | halyavin | 318 | file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */ |
319 | else |
||
320 | file_hdr.f_nsyms = 0; |
||
321 | |||
322 | file_pointer += file_hdr.f_nsyms * SYMNMLEN; |
||
323 | |||
324 | // OK now we are all set to write the file |
||
325 | |||
326 | |||
327 | fwrite(&file_hdr, FILHSZ, 1, f); |
||
328 | fwrite(&o_filehdr, sizeof(o_filehdr), 1, f); |
||
329 | |||
330 | // write section headers |
||
331 | for (i = 1; i < s1->nb_sections; i++) { |
||
332 | coff_sec = §ion_header[i]; |
||
333 | tcc_sect = s1->sections[i]; |
||
334 | |||
335 | if (OutputTheSection(tcc_sect)) { |
||
336 | fwrite(coff_sec, sizeof(SCNHDR), 1, f); |
||
337 | } |
||
338 | } |
||
339 | |||
340 | // write raw data |
||
341 | for (i = 1; i < s1->nb_sections; i++) { |
||
342 | coff_sec = §ion_header[i]; |
||
343 | tcc_sect = s1->sections[i]; |
||
344 | |||
345 | if (OutputTheSection(tcc_sect)) { |
||
346 | fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f); |
||
347 | } |
||
348 | } |
||
349 | |||
350 | // write relocation data |
||
351 | for (i = 1; i < s1->nb_sections; i++) { |
||
352 | coff_sec = §ion_header[i]; |
||
353 | tcc_sect = s1->sections[i]; |
||
354 | |||
355 | if (OutputTheSection(tcc_sect)) { |
||
356 | // put relocations data |
||
357 | if (coff_sec->s_nreloc > 0) { |
||
358 | fwrite(tcc_sect->reloc, |
||
359 | coff_sec->s_nreloc * sizeof(struct reloc), 1, f); |
||
360 | } |
||
361 | } |
||
362 | } |
||
363 | |||
364 | |||
365 | // group the symbols in order of filename, func1, func2, etc |
||
366 | // finally global symbols |
||
367 | |||
6429 | siemargl | 368 | if (s1->do_debug) |
145 | halyavin | 369 | SortSymbolTable(); |
370 | |||
371 | // write line no data |
||
372 | |||
373 | for (i = 1; i < s1->nb_sections; i++) { |
||
374 | coff_sec = §ion_header[i]; |
||
375 | tcc_sect = s1->sections[i]; |
||
376 | |||
6429 | siemargl | 377 | if (s1->do_debug && tcc_sect == stext) { |
145 | halyavin | 378 | // count how many line nos data |
379 | |||
380 | |||
381 | Stab_Sym *sym, *sym_end; |
||
382 | char func_name[128], last_func_name[128]; |
||
383 | unsigned long func_addr, last_pc, pc; |
||
384 | const char *incl_files[INCLUDE_STACK_SIZE]; |
||
385 | int incl_index, len, last_line_num; |
||
386 | const char *str, *p; |
||
387 | |||
388 | LINENO CoffLineNo; |
||
389 | |||
390 | func_name[0] = '\0'; |
||
391 | func_addr = 0; |
||
392 | incl_index = 0; |
||
393 | last_func_name[0] = '\0'; |
||
394 | last_pc = 0; |
||
395 | last_line_num = 1; |
||
396 | sym = (Stab_Sym *) stab_section->data + 1; |
||
397 | sym_end = |
||
398 | (Stab_Sym *) (stab_section->data + |
||
399 | stab_section->data_offset); |
||
400 | |||
401 | while (sym < sym_end) { |
||
402 | switch (sym->n_type) { |
||
403 | /* function start or end */ |
||
404 | case N_FUN: |
||
405 | if (sym->n_strx == 0) { |
||
406 | // end of function |
||
407 | |||
408 | CoffLineNo.l_addr.l_paddr = last_pc; |
||
409 | CoffLineNo.l_lnno = last_line_num + 1; |
||
410 | fwrite(&CoffLineNo, 6, 1, f); |
||
411 | |||
412 | pc = sym->n_value + func_addr; |
||
413 | func_name[0] = '\0'; |
||
414 | func_addr = 0; |
||
415 | } else { |
||
416 | // beginning of function |
||
417 | |||
418 | str = |
||
419 | (const char *) stabstr_section->data + |
||
420 | sym->n_strx; |
||
421 | |||
422 | |||
423 | p = strchr(str, ':'); |
||
424 | if (!p) { |
||
425 | pstrcpy(func_name, sizeof(func_name), str); |
||
426 | } else { |
||
427 | len = p - str; |
||
428 | if (len > sizeof(func_name) - 1) |
||
429 | len = sizeof(func_name) - 1; |
||
430 | memcpy(func_name, str, len); |
||
431 | func_name[len] = '\0'; |
||
432 | } |
||
433 | func_addr = sym->n_value; |
||
434 | last_pc = func_addr; |
||
435 | last_line_num = -1; |
||
436 | |||
437 | // output a function begin |
||
438 | |||
439 | CoffLineNo.l_addr.l_symndx = |
||
440 | FindCoffSymbolIndex(func_name); |
||
441 | CoffLineNo.l_lnno = 0; |
||
442 | |||
443 | fwrite(&CoffLineNo, 6, 1, f); |
||
444 | } |
||
445 | break; |
||
446 | |||
447 | /* line number info */ |
||
448 | case N_SLINE: |
||
449 | pc = sym->n_value + func_addr; |
||
450 | |||
451 | |||
452 | /* XXX: slow! */ |
||
453 | strcpy(last_func_name, func_name); |
||
454 | |||
455 | // output a line reference |
||
456 | |||
457 | CoffLineNo.l_addr.l_paddr = last_pc; |
||
458 | |||
459 | if (last_line_num == -1) { |
||
460 | CoffLineNo.l_lnno = sym->n_desc; |
||
461 | } else { |
||
462 | CoffLineNo.l_lnno = last_line_num + 1; |
||
463 | } |
||
464 | |||
465 | fwrite(&CoffLineNo, 6, 1, f); |
||
466 | |||
467 | last_pc = pc; |
||
468 | last_line_num = sym->n_desc; |
||
469 | |||
470 | break; |
||
471 | |||
472 | /* include files */ |
||
473 | case N_BINCL: |
||
474 | str = |
||
475 | (const char *) stabstr_section->data + sym->n_strx; |
||
476 | add_incl2: |
||
477 | if (incl_index < INCLUDE_STACK_SIZE) { |
||
478 | incl_files[incl_index++] = str; |
||
479 | } |
||
480 | break; |
||
481 | case N_EINCL: |
||
482 | if (incl_index > 1) |
||
483 | incl_index--; |
||
484 | break; |
||
485 | case N_SO: |
||
486 | if (sym->n_strx == 0) { |
||
487 | incl_index = 0; /* end of translation unit */ |
||
488 | } else { |
||
489 | str = |
||
490 | (const char *) stabstr_section->data + |
||
491 | sym->n_strx; |
||
492 | /* do not add path */ |
||
493 | len = strlen(str); |
||
494 | if (len > 0 && str[len - 1] != '/') |
||
495 | goto add_incl2; |
||
496 | } |
||
497 | break; |
||
498 | } |
||
499 | sym++; |
||
500 | } |
||
501 | } |
||
502 | } |
||
503 | |||
504 | // write symbol table |
||
6429 | siemargl | 505 | if (s1->do_debug) { |
145 | halyavin | 506 | int k; |
507 | struct syment csym; |
||
508 | AUXFUNC auxfunc; |
||
509 | AUXBF auxbf; |
||
510 | AUXEF auxef; |
||
511 | int i; |
||
512 | Elf32_Sym *p; |
||
513 | const char *name; |
||
514 | int nstr; |
||
515 | int n = 0; |
||
516 | |||
517 | Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE); |
||
518 | pCoff_str_table = Coff_str_table; |
||
519 | nstr = 0; |
||
520 | |||
521 | p = (Elf32_Sym *) symtab_section->data; |
||
522 | |||
523 | |||
524 | for (i = 0; i < nb_syms; i++) { |
||
525 | |||
526 | name = symtab_section->link->data + p->st_name; |
||
527 | |||
528 | for (k = 0; k < 8; k++) |
||
529 | csym._n._n_name[k] = 0; |
||
530 | |||
531 | if (strlen(name) <= 8) { |
||
532 | strcpy(csym._n._n_name, name); |
||
533 | } else { |
||
534 | if (pCoff_str_table - Coff_str_table + strlen(name) > |
||
535 | MAX_STR_TABLE - 1) |
||
6429 | siemargl | 536 | tcc_error("String table too large"); |
145 | halyavin | 537 | |
538 | csym._n._n_n._n_zeroes = 0; |
||
539 | csym._n._n_n._n_offset = |
||
540 | pCoff_str_table - Coff_str_table + 4; |
||
541 | |||
542 | strcpy(pCoff_str_table, name); |
||
543 | pCoff_str_table += strlen(name) + 1; // skip over null |
||
544 | nstr++; |
||
545 | } |
||
546 | |||
547 | if (p->st_info == 4) { |
||
548 | // put a filename symbol |
||
549 | csym.n_value = 33; // ????? |
||
550 | csym.n_scnum = N_DEBUG; |
||
551 | csym.n_type = 0; |
||
552 | csym.n_sclass = C_FILE; |
||
553 | csym.n_numaux = 0; |
||
554 | fwrite(&csym, 18, 1, f); |
||
555 | n++; |
||
556 | |||
557 | } else if (p->st_info == 0x12) { |
||
558 | // find the function data |
||
559 | |||
560 | for (k = 0; k < nFuncs; k++) { |
||
561 | if (strcmp(name, Func[k]) == 0) |
||
562 | break; |
||
563 | } |
||
564 | |||
565 | if (k >= nFuncs) { |
||
6429 | siemargl | 566 | tcc_error("debug info can't find function: %s", name); |
145 | halyavin | 567 | } |
568 | // put a Function Name |
||
569 | |||
570 | csym.n_value = p->st_value; // physical address |
||
571 | csym.n_scnum = CoffTextSectionNo; |
||
572 | csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0); |
||
573 | csym.n_sclass = C_EXT; |
||
574 | csym.n_numaux = 1; |
||
575 | fwrite(&csym, 18, 1, f); |
||
576 | |||
577 | // now put aux info |
||
578 | |||
579 | auxfunc.tag = 0; |
||
580 | auxfunc.size = EndAddress[k] - p->st_value; |
||
581 | auxfunc.fileptr = LineNoFilePtr[k]; |
||
582 | auxfunc.nextsym = n + 6; // tktk |
||
583 | auxfunc.dummy = 0; |
||
584 | fwrite(&auxfunc, 18, 1, f); |
||
585 | |||
586 | // put a .bf |
||
587 | |||
588 | strcpy(csym._n._n_name, ".bf"); |
||
589 | csym.n_value = p->st_value; // physical address |
||
590 | csym.n_scnum = CoffTextSectionNo; |
||
591 | csym.n_type = 0; |
||
592 | csym.n_sclass = C_FCN; |
||
593 | csym.n_numaux = 1; |
||
594 | fwrite(&csym, 18, 1, f); |
||
595 | |||
596 | // now put aux info |
||
597 | |||
598 | auxbf.regmask = 0; |
||
599 | auxbf.lineno = 0; |
||
600 | auxbf.nentries = FuncEntries[k]; |
||
601 | auxbf.localframe = 0; |
||
602 | auxbf.nextentry = n + 6; |
||
603 | auxbf.dummy = 0; |
||
604 | fwrite(&auxbf, 18, 1, f); |
||
605 | |||
606 | // put a .ef |
||
607 | |||
608 | strcpy(csym._n._n_name, ".ef"); |
||
609 | csym.n_value = EndAddress[k]; // physical address |
||
610 | csym.n_scnum = CoffTextSectionNo; |
||
611 | csym.n_type = 0; |
||
612 | csym.n_sclass = C_FCN; |
||
613 | csym.n_numaux = 1; |
||
614 | fwrite(&csym, 18, 1, f); |
||
615 | |||
616 | // now put aux info |
||
617 | |||
618 | auxef.dummy = 0; |
||
619 | auxef.lineno = LastLineNo[k]; |
||
620 | auxef.dummy1 = 0; |
||
621 | auxef.dummy2 = 0; |
||
622 | auxef.dummy3 = 0; |
||
623 | auxef.dummy4 = 0; |
||
624 | fwrite(&auxef, 18, 1, f); |
||
625 | |||
626 | n += 6; |
||
627 | |||
628 | } else { |
||
629 | // try an put some type info |
||
630 | |||
631 | if ((p->st_other & VT_BTYPE) == VT_DOUBLE) { |
||
632 | csym.n_type = T_DOUBLE; // int |
||
633 | csym.n_sclass = C_EXT; |
||
634 | } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) { |
||
635 | csym.n_type = T_FLOAT; |
||
636 | csym.n_sclass = C_EXT; |
||
637 | } else if ((p->st_other & VT_BTYPE) == VT_INT) { |
||
638 | csym.n_type = T_INT; // int |
||
639 | csym.n_sclass = C_EXT; |
||
640 | } else if ((p->st_other & VT_BTYPE) == VT_SHORT) { |
||
641 | csym.n_type = T_SHORT; |
||
642 | csym.n_sclass = C_EXT; |
||
643 | } else if ((p->st_other & VT_BTYPE) == VT_BYTE) { |
||
644 | csym.n_type = T_CHAR; |
||
645 | csym.n_sclass = C_EXT; |
||
646 | } else { |
||
647 | csym.n_type = T_INT; // just mark as a label |
||
648 | csym.n_sclass = C_LABEL; |
||
649 | } |
||
650 | |||
651 | |||
652 | csym.n_value = p->st_value; |
||
653 | csym.n_scnum = 2; |
||
654 | csym.n_numaux = 1; |
||
655 | fwrite(&csym, 18, 1, f); |
||
656 | |||
657 | auxfunc.tag = 0; |
||
658 | auxfunc.size = 0x20; |
||
659 | auxfunc.fileptr = 0; |
||
660 | auxfunc.nextsym = 0; |
||
661 | auxfunc.dummy = 0; |
||
662 | fwrite(&auxfunc, 18, 1, f); |
||
663 | n++; |
||
664 | n++; |
||
665 | |||
666 | } |
||
667 | |||
668 | p++; |
||
669 | } |
||
670 | } |
||
671 | |||
6429 | siemargl | 672 | if (s1->do_debug) { |
145 | halyavin | 673 | // write string table |
674 | |||
675 | // first write the size |
||
676 | i = pCoff_str_table - Coff_str_table; |
||
677 | fwrite(&i, 4, 1, f); |
||
678 | |||
679 | // then write the strings |
||
680 | fwrite(Coff_str_table, i, 1, f); |
||
681 | |||
682 | tcc_free(Coff_str_table); |
||
683 | } |
||
684 | |||
685 | return 0; |
||
686 | } |
||
687 | |||
688 | |||
689 | |||
690 | // group the symbols in order of filename, func1, func2, etc |
||
691 | // finally global symbols |
||
692 | |||
693 | void SortSymbolTable(void) |
||
694 | { |
||
695 | int i, j, k, n = 0; |
||
696 | Elf32_Sym *p, *p2, *NewTable; |
||
697 | char *name, *name2; |
||
698 | |||
699 | NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym)); |
||
700 | |||
701 | p = (Elf32_Sym *) symtab_section->data; |
||
702 | |||
703 | |||
704 | // find a file symbol, copy it over |
||
705 | // then scan the whole symbol list and copy any function |
||
706 | // symbols that match the file association |
||
707 | |||
708 | for (i = 0; i < nb_syms; i++) { |
||
709 | if (p->st_info == 4) { |
||
710 | name = (char *) symtab_section->link->data + p->st_name; |
||
711 | |||
712 | // this is a file symbol, copy it over |
||
713 | |||
714 | NewTable[n++] = *p; |
||
715 | |||
716 | p2 = (Elf32_Sym *) symtab_section->data; |
||
717 | |||
718 | for (j = 0; j < nb_syms; j++) { |
||
719 | if (p2->st_info == 0x12) { |
||
720 | // this is a func symbol |
||
721 | |||
722 | name2 = |
||
723 | (char *) symtab_section->link->data + p2->st_name; |
||
724 | |||
725 | // find the function data index |
||
726 | |||
727 | for (k = 0; k < nFuncs; k++) { |
||
728 | if (strcmp(name2, Func[k]) == 0) |
||
729 | break; |
||
730 | } |
||
731 | |||
732 | if (k >= nFuncs) { |
||
6429 | siemargl | 733 | tcc_error("debug (sort) info can't find function: %s", name2); |
145 | halyavin | 734 | } |
735 | |||
736 | if (strcmp(AssociatedFile[k], name) == 0) { |
||
737 | // yes they match copy it over |
||
738 | |||
739 | NewTable[n++] = *p2; |
||
740 | } |
||
741 | } |
||
742 | p2++; |
||
743 | } |
||
744 | } |
||
745 | p++; |
||
746 | } |
||
747 | |||
748 | // now all the filename and func symbols should have been copied over |
||
749 | // copy all the rest over (all except file and funcs) |
||
750 | |||
751 | p = (Elf32_Sym *) symtab_section->data; |
||
752 | for (i = 0; i < nb_syms; i++) { |
||
753 | if (p->st_info != 4 && p->st_info != 0x12) { |
||
754 | NewTable[n++] = *p; |
||
755 | } |
||
756 | p++; |
||
757 | } |
||
758 | |||
759 | if (n != nb_syms) |
||
6429 | siemargl | 760 | tcc_error("Internal Compiler error, debug info"); |
145 | halyavin | 761 | |
762 | // copy it all back |
||
763 | |||
764 | p = (Elf32_Sym *) symtab_section->data; |
||
765 | for (i = 0; i < nb_syms; i++) { |
||
766 | *p++ = NewTable[i]; |
||
767 | } |
||
768 | |||
769 | tcc_free(NewTable); |
||
770 | } |
||
771 | |||
772 | |||
773 | int FindCoffSymbolIndex(const char *func_name) |
||
774 | { |
||
775 | int i, n = 0; |
||
776 | Elf32_Sym *p; |
||
777 | char *name; |
||
778 | |||
779 | p = (Elf32_Sym *) symtab_section->data; |
||
780 | |||
781 | for (i = 0; i < nb_syms; i++) { |
||
782 | |||
783 | name = (char *) symtab_section->link->data + p->st_name; |
||
784 | |||
785 | if (p->st_info == 4) { |
||
786 | // put a filename symbol |
||
787 | n++; |
||
788 | } else if (p->st_info == 0x12) { |
||
789 | |||
790 | if (strcmp(func_name, name) == 0) |
||
791 | return n; |
||
792 | |||
793 | n += 6; |
||
794 | |||
795 | // put a Function Name |
||
796 | |||
797 | // now put aux info |
||
798 | |||
799 | // put a .bf |
||
800 | |||
801 | // now put aux info |
||
802 | |||
803 | // put a .ef |
||
804 | |||
805 | // now put aux info |
||
806 | |||
807 | } else { |
||
808 | n += 2; |
||
809 | } |
||
810 | |||
811 | p++; |
||
812 | } |
||
813 | |||
814 | return n; // total number of symbols |
||
815 | } |
||
816 | |||
6429 | siemargl | 817 | int OutputTheSection(Section * sect) |
145 | halyavin | 818 | { |
819 | const char *s = sect->name; |
||
820 | |||
821 | if (!strcmp(s, ".text")) |
||
6429 | siemargl | 822 | return 1; |
145 | halyavin | 823 | else if (!strcmp(s, ".data")) |
6429 | siemargl | 824 | return 1; |
145 | halyavin | 825 | else |
826 | return 0; |
||
827 | } |
||
828 | |||
829 | short int GetCoffFlags(const char *s) |
||
830 | { |
||
831 | if (!strcmp(s, ".text")) |
||
832 | return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400; |
||
833 | else if (!strcmp(s, ".data")) |
||
834 | return STYP_DATA; |
||
835 | else if (!strcmp(s, ".bss")) |
||
836 | return STYP_BSS; |
||
837 | else if (!strcmp(s, ".stack")) |
||
838 | return STYP_BSS | STYP_ALIGN | 0x200; |
||
839 | else if (!strcmp(s, ".cinit")) |
||
840 | return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200; |
||
841 | else |
||
842 | return 0; |
||
843 | } |
||
844 | |||
845 | Section *FindSection(TCCState * s1, const char *sname) |
||
846 | { |
||
847 | Section *s; |
||
848 | int i; |
||
849 | |||
850 | for (i = 1; i < s1->nb_sections; i++) { |
||
851 | s = s1->sections[i]; |
||
852 | |||
853 | if (!strcmp(sname, s->name)) |
||
854 | return s; |
||
855 | } |
||
856 | |||
6429 | siemargl | 857 | tcc_error("could not find section %s", sname); |
145 | halyavin | 858 | return 0; |
859 | } |
||
860 | |||
6429 | siemargl | 861 | ST_FUNC int tcc_load_coff(TCCState * s1, int fd) |
145 | halyavin | 862 | { |
863 | // tktk TokenSym *ts; |
||
864 | |||
865 | FILE *f; |
||
866 | unsigned int str_size; |
||
867 | char *Coff_str_table, *name; |
||
868 | int i, k; |
||
869 | struct syment csym; |
||
870 | char name2[9]; |
||
871 | FILHDR file_hdr; /* FILE HEADER STRUCTURE */ |
||
872 | |||
873 | f = fdopen(fd, "rb"); |
||
874 | if (!f) { |
||
6429 | siemargl | 875 | tcc_error("Unable to open .out file for input"); |
145 | halyavin | 876 | } |
877 | |||
878 | if (fread(&file_hdr, FILHSZ, 1, f) != 1) |
||
6429 | siemargl | 879 | tcc_error("error reading .out file for input"); |
145 | halyavin | 880 | |
881 | if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1) |
||
6429 | siemargl | 882 | tcc_error("error reading .out file for input"); |
145 | halyavin | 883 | |
884 | // first read the string table |
||
885 | |||
886 | if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET)) |
||
6429 | siemargl | 887 | tcc_error("error reading .out file for input"); |
145 | halyavin | 888 | |
889 | if (fread(&str_size, sizeof(int), 1, f) != 1) |
||
6429 | siemargl | 890 | tcc_error("error reading .out file for input"); |
145 | halyavin | 891 | |
892 | |||
893 | Coff_str_table = (char *) tcc_malloc(str_size); |
||
894 | |||
895 | if (fread(Coff_str_table, str_size - 4, 1, f) != 1) |
||
6429 | siemargl | 896 | tcc_error("error reading .out file for input"); |
145 | halyavin | 897 | |
898 | // read/process all the symbols |
||
899 | |||
900 | // seek back to symbols |
||
901 | |||
902 | if (fseek(f, file_hdr.f_symptr, SEEK_SET)) |
||
6429 | siemargl | 903 | tcc_error("error reading .out file for input"); |
145 | halyavin | 904 | |
905 | for (i = 0; i < file_hdr.f_nsyms; i++) { |
||
906 | if (fread(&csym, SYMESZ, 1, f) != 1) |
||
6429 | siemargl | 907 | tcc_error("error reading .out file for input"); |
145 | halyavin | 908 | |
909 | if (csym._n._n_n._n_zeroes == 0) { |
||
910 | name = Coff_str_table + csym._n._n_n._n_offset - 4; |
||
911 | } else { |
||
912 | name = csym._n._n_name; |
||
913 | |||
914 | if (name[7] != 0) { |
||
915 | for (k = 0; k < 8; k++) |
||
916 | name2[k] = name[k]; |
||
917 | |||
918 | name2[8] = 0; |
||
919 | |||
920 | name = name2; |
||
921 | } |
||
922 | } |
||
923 | // if (strcmp("_DAC_Buffer",name)==0) // tktk |
||
924 | // name[0]=0; |
||
925 | |||
926 | if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures |
||
927 | (csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure |
||
928 | (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles |
||
929 | (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats |
||
930 | { |
||
931 | // strip off any leading underscore (except for other main routine) |
||
932 | |||
933 | if (name[0] == '_' && strcmp(name, "_main") != 0) |
||
934 | name++; |
||
935 | |||
6429 | siemargl | 936 | tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value); |
145 | halyavin | 937 | } |
938 | // skip any aux records |
||
939 | |||
940 | if (csym.n_numaux == 1) { |
||
941 | if (fread(&csym, SYMESZ, 1, f) != 1) |
||
6429 | siemargl | 942 | tcc_error("error reading .out file for input"); |
145 | halyavin | 943 | i++; |
944 | } |
||
945 | } |
||
946 | |||
947 | return 0; |
||
948 | }>>>>>>>>>>=>>>>>>>>>>>>>>> |