Subversion Repositories Kolibri OS

Rev

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 reserved1;
  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) continue;
  100.                         if (rel->r_offset>s->data_size)
  101.                                 continue;
  102.                         if (type==R_386_PC32)
  103.                                 *(int*)(rel->r_offset+s->data)+=ss->sh_addr+esym->st_value-rel->r_offset-s->sh_addr;
  104.                         else if (type==R_386_32)
  105.                                 *(int*)(rel->r_offset+s->data)+=ss->sh_addr+esym->st_value;
  106.                 }
  107.         rel=rel_;
  108.                 s=s->next;
  109.                 if (s==0)
  110.                 {
  111.                         if (flag) break;
  112.                         s=me->data_sections;
  113.                         if (s==0) break;
  114.                         flag=1;
  115.                         continue;
  116.                 }
  117.         }
  118. }
  119.  
  120. void assign_addresses(me_info* me)
  121. {
  122.         int i;
  123.         meos_section_info* si;
  124.         for (i=1;i<me->s1->nb_sections;i++)
  125.         {
  126.                 Section* s=me->s1->sections[i];
  127.                 if (strcmp(".text",s->name)==0)
  128.                 {
  129.                         si=tcc_malloc(sizeof(meos_section_info));
  130.                         si->data=s->data;
  131.                         si->data_size=s->data_offset;
  132.                         si->next=me->code_sections;
  133.                         si->sec_num=i;
  134.                         me->code_sections=si;
  135.                         continue;
  136.                 }
  137.                 if (strcmp(".data",s->name)==0)
  138.                 {
  139.                         si=tcc_malloc(sizeof(meos_section_info));
  140.                         si->data=s->data;
  141.                         si->data_size=s->data_offset;
  142.                         si->next=me->data_sections;
  143.                         si->sec_num=i;
  144.                         me->data_sections=si;
  145.                         continue;
  146.                 }
  147.                 if (strcmp(".bss",s->name)==0)
  148.                 {
  149.                         si=tcc_malloc(sizeof(meos_section_info));
  150.                         si->data_size=s->data_offset;
  151.                         si->next=me->bss_sections;
  152.                         si->sec_num=i;
  153.                         me->bss_sections=si;
  154.                         continue;
  155.                 }
  156.         }
  157.         int addr;
  158.         addr=sizeof(IMAGE_MEOS_FILE_HEADER);
  159.         for (si=me->code_sections;si;si=si->next)
  160.         {
  161.                 si->sh_addr=addr;
  162.                 addr+=si->data_size;
  163.         }
  164.         for (si=me->data_sections;si;si=si->next)
  165.         {
  166.                 si->sh_addr=addr;
  167.                 addr+=si->data_size;
  168.         }
  169.         me->header.image_size=addr;
  170.         for (si=me->bss_sections;si;si=si->next)
  171.         {
  172.                 si->sh_addr=addr;
  173.                 addr+=si->data_size;
  174.         }
  175.         addr+=4096;
  176.         addr=(addr+4)&(~3);
  177.         me->header.stack=addr;
  178.         me->header.memory_size=addr;
  179.         build_reloc(me);
  180. }
  181. int tcc_find_symbol_me(me_info* me, const char *sym_name)
  182. {
  183.         int i;
  184.         int symtab;
  185.         int strtab;
  186.         symtab=0;
  187.         strtab=0;
  188.         for (i=1;i<me->s1->nb_sections;i++)
  189.         {
  190.                 Section* s;
  191.                 s=me->s1->sections[i];
  192.                 if (strcmp(s->name,".symtab")==0)
  193.                 {
  194.                         symtab=i;
  195.                 }
  196.                 if (strcmp(s->name,".strtab")==0)
  197.                 {
  198.                         strtab=i;
  199.                 }
  200.         }
  201.         if (symtab==0 || strtab==0)
  202.                 return 0;
  203.         Elf32_Sym* s,*se;
  204.         char* name;
  205.         s=(Elf32_Sym*)me->s1->sections[symtab]->data;
  206.         se=(Elf32_Sym*)(((void*)s)+me->s1->sections[symtab]->data_offset);
  207.         name=(char*)me->s1->sections[strtab]->data;
  208.         while (s<se)
  209.         {
  210.                 if (strcmp(name+s->st_name,sym_name)==0)
  211.                 {
  212.                         return s->st_value+findsection(me,s->st_shndx)->sh_addr;
  213.                 }
  214.                 s++;
  215.         }
  216.         return 0;
  217. }
  218. const char* me_magic="MENUET01";
  219. int tcc_output_me(TCCState* s1,const char *filename)
  220. {
  221.         me_info me;
  222.     int i;
  223.     FILE* f;
  224.     //printf("%d\n",s1->nb_sections);
  225.         memset(&me,0,sizeof(me));
  226.         me.s1=s1;
  227.         relocate_common_syms();
  228.         assign_addresses(&me);
  229.         me.header.entry_point=tcc_find_symbol_me(&me,"start");
  230.        
  231.         f=fopen(filename,"wb");
  232.     for (i=0;i<8;i++)
  233.         me.header.magic[i]=me_magic[i];
  234.         /*me.header.magic[0]='M';me.header.magic[1]='E';
  235.         me.header.magic[2]='N';me.header.magic[3]='U';
  236.         me.header.magic[4]='E';me.header.magic[5]='T';
  237.         me.header.magic[6]='0';me.header.magic[7]='1';*/
  238.         fwrite(&me.header,1,sizeof(IMAGE_MEOS_FILE_HEADER),f);
  239.         meos_section_info* si;
  240.         for(si=me.code_sections;si;si=si->next)
  241.                 fwrite(si->data,1,si->data_size,f);
  242.         for (si=me.data_sections;si;si=si->next)
  243.                 fwrite(si->data,1,si->data_size,f);
  244.         fclose(f);
  245.         return 0;
  246. }
  247.