Subversion Repositories Kolibri OS

Rev

Rev 158 | Go to most recent revision | Blame | 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. typedef struct {
  22.         char magic[8];
  23.         int version;
  24.         int entry_point;
  25.         int image_size;
  26.         int memory_size;
  27.         int stack;
  28.         int params;
  29.         int argv;
  30. } IMAGE_MEOS_FILE_HEADER,*PIMAGE_MEOS_FILE_HEADER;
  31. typedef struct _meos_section_info{
  32.         int sh_addr;
  33.         void* data;
  34.         int data_size;
  35.         int sec_num;
  36.         struct _meos_section_info* next;
  37. } meos_section_info;
  38. typedef struct {
  39.         TCCState* s1;
  40.         IMAGE_MEOS_FILE_HEADER header;
  41.         meos_section_info* code_sections;
  42.         meos_section_info* data_sections;
  43.         meos_section_info* bss_sections;
  44. } me_info;
  45.  
  46. meos_section_info* findsection(me_info* me,int num)
  47. {
  48.         meos_section_info* si;
  49.         for(si=me->code_sections;si;si=si->next)
  50.         {
  51.                 if (si->sec_num==num)
  52.                         return si;
  53.         }
  54.         for (si=me->data_sections;si;si=si->next)
  55.         {
  56.                 if (si->sec_num==num)
  57.                         return si;
  58.         }
  59.         for (si=me->bss_sections;si;si=si->next)
  60.         {
  61.                 if (si->sec_num==num)
  62.                         return si;
  63.         }
  64.         return (meos_section_info*)0;
  65. }
  66.  
  67. void build_reloc(me_info* me)
  68. {
  69.         int flag;
  70.         Elf32_Rel *rel, *rel_, *rel_end;
  71.         Section *sr;
  72.         meos_section_info* s;
  73.         meos_section_info* ss;
  74.         s=me->code_sections;
  75.         rel=0;
  76.         rel_end=0;
  77.         flag=0;
  78.         for(;;)
  79.         {
  80.                 sr=me->s1->sections[s->sec_num]->reloc;
  81.                 if (sr)
  82.                 {
  83.                         rel = (Elf32_Rel *) sr->data;
  84.                         rel_end = (Elf32_Rel *) (sr->data + sr->data_offset);
  85.                 }
  86.                 rel_=rel;
  87.                 while (rel_<rel_end){
  88.                         rel=rel_;
  89.                         int type = ELF32_R_TYPE(rel->r_info);
  90.                         rel_=rel+1;
  91.                         if (type != R_386_PC32 && type != R_386_32)
  92.                                 continue;
  93.                         int sym = ELF32_R_SYM(rel->r_info);
  94.                         if (sym>symtab_section->data_offset/sizeof(Elf32_Sym))
  95.                                 continue;
  96.                         Elf32_Sym* esym = ((Elf32_Sym *)symtab_section->data)+sym;
  97.                         int sect=esym->st_shndx;
  98.                         ss=findsection(me,sect);
  99.                         if (ss==0)
  100.                                 ss=me->bss_sections;
  101.                         if (rel->r_offset>s->data_size)
  102.                                 continue;
  103.                         if (type==R_386_PC32)
  104.                                 *(int*)(rel->r_offset+s->data)=ss->sh_addr+esym->st_value-rel->r_offset-s->sh_addr-4;
  105.                         else if (type==R_386_32)
  106.                                 *(int*)(rel->r_offset+s->data)+=ss->sh_addr+esym->st_value;
  107.                 }
  108.         rel=rel_;
  109.                 s=s->next;
  110.                 if (s==0)
  111.                 {
  112.                         if (flag) break;
  113.                         s=me->data_sections;
  114.                         if (s==0) break;
  115.                         flag=1;
  116.                         continue;
  117.                 }
  118.         }
  119. }
  120.  
  121. void assign_addresses(me_info* me)
  122. {
  123.         int i;
  124.         meos_section_info* si;
  125.         for (i=1;i<me->s1->nb_sections;i++)
  126.         {
  127.                 Section* s=me->s1->sections[i];
  128.                 if (strcmp(".text",s->name)==0)
  129.                 {
  130.                         si=tcc_malloc(sizeof(meos_section_info));
  131.                         si->data=s->data;
  132.                         si->data_size=s->data_offset;
  133.                         si->next=me->code_sections;
  134.                         si->sec_num=i;
  135.                         me->code_sections=si;
  136.                         continue;
  137.                 }
  138.                 if (strcmp(".data",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->data_sections;
  144.                         si->sec_num=i;
  145.                         me->data_sections=si;
  146.                         continue;
  147.                 }
  148.                 if (strcmp(".bss",s->name)==0)
  149.                 {
  150.                         si=tcc_malloc(sizeof(meos_section_info));
  151.                         si->data_size=s->data_offset;
  152.                         si->next=me->bss_sections;
  153.                         si->sec_num=i;
  154.                         me->bss_sections=si;
  155.                         continue;
  156.                 }
  157.         }
  158.         int addr;
  159.         addr=sizeof(IMAGE_MEOS_FILE_HEADER);
  160.         for (si=me->code_sections;si;si=si->next)
  161.         {
  162.                 si->sh_addr=addr;
  163.                 addr+=si->data_size;
  164.         }
  165.         for (si=me->data_sections;si;si=si->next)
  166.         {
  167.                 si->sh_addr=addr;
  168.                 addr+=si->data_size;
  169.         }
  170.         me->header.image_size=addr;
  171.         for (si=me->bss_sections;si;si=si->next)
  172.         {
  173.                 si->sh_addr=addr;
  174.                 addr+=si->data_size;
  175.         }
  176.         addr+=4096;
  177.         addr=(addr+4)&(~3);
  178.         me->header.stack=addr;
  179.         me->header.memory_size=addr;
  180.         build_reloc(me);
  181. }
  182. int tcc_find_symbol_me(me_info* me, const char *sym_name)
  183. {
  184.         int i;
  185.         int symtab;
  186.         int strtab;
  187.         symtab=0;
  188.         strtab=0;
  189.         for (i=1;i<me->s1->nb_sections;i++)
  190.         {
  191.                 Section* s;
  192.                 s=me->s1->sections[i];
  193.                 if (strcmp(s->name,".symtab")==0)
  194.                 {
  195.                         symtab=i;
  196.                 }
  197.                 if (strcmp(s->name,".strtab")==0)
  198.                 {
  199.                         strtab=i;
  200.                 }
  201.         }
  202.         if (symtab==0 || strtab==0)
  203.                 return 0;
  204.         Elf32_Sym* s,*se;
  205.         char* name;
  206.         s=(Elf32_Sym*)me->s1->sections[symtab]->data;
  207.         se=(Elf32_Sym*)(((void*)s)+me->s1->sections[symtab]->data_offset);
  208.         name=(char*)me->s1->sections[strtab]->data;
  209.         while (s<se)
  210.         {
  211.                 if (strcmp(name+s->st_name,sym_name)==0)
  212.                 {
  213.                         return s->st_value+findsection(me,s->st_shndx)->sh_addr;
  214.                 }
  215.                 s++;
  216.         }
  217.         return 0;
  218. }
  219. const char* me_magic="MENUET01";
  220. int tcc_output_me(TCCState* s1,const char *filename)
  221. {
  222.         me_info me;
  223.     int i;
  224.     FILE* f;
  225.     //printf("%d\n",s1->nb_sections);
  226.         memset(&me,0,sizeof(me));
  227.         me.s1=s1;
  228.         relocate_common_syms();
  229.         assign_addresses(&me);
  230.         me.header.version=1;
  231.         me.header.entry_point=tcc_find_symbol_me(&me,"start");
  232.         me.header.params= tcc_find_symbol_me(&me,"__argv"); // <--
  233.         me.header.argv= tcc_find_symbol_me(&me,"__path"); // <--
  234.        
  235.         f=fopen(filename,"wb");
  236.     for (i=0;i<8;i++)
  237.         me.header.magic[i]=me_magic[i];
  238.         /*me.header.magic[0]='M';me.header.magic[1]='E';
  239.         me.header.magic[2]='N';me.header.magic[3]='U';
  240.         me.header.magic[4]='E';me.header.magic[5]='T';
  241.         me.header.magic[6]='0';me.header.magic[7]='1';*/
  242.         fwrite(&me.header,1,sizeof(IMAGE_MEOS_FILE_HEADER),f);
  243.         meos_section_info* si;
  244.         for(si=me.code_sections;si;si=si->next)
  245.                 fwrite(si->data,1,si->data_size,f);
  246.         for (si=me.data_sections;si;si=si->next)
  247.                 fwrite(si->data,1,si->data_size,f);
  248.         fclose(f);
  249.         return 0;
  250. }
  251.