Subversion Repositories Kolibri OS

Rev

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