Subversion Repositories Kolibri OS

Rev

Rev 9284 | Rev 9557 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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