Subversion Repositories Kolibri OS

Rev

Rev 647 | Rev 6441 | 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. 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.                         {
  101.                 const char *sym_name = strtab_section->data + esym->st_name;
  102.                         tcc_error_noabort("undefined symbol '%s'", sym_name);
  103.                                 continue;
  104.                         }
  105.                         if (rel->r_offset>s->data_size)
  106.                                 continue;
  107.                         if (type==R_386_PC32)
  108.                                 *(int*)(rel->r_offset+s->data)+=ss->sh_addr+esym->st_value-rel->r_offset-s->sh_addr;
  109.                         else if (type==R_386_32)
  110.                                 *(int*)(rel->r_offset+s->data)+=ss->sh_addr+esym->st_value;
  111.                 }
  112.         rel=rel_;
  113.                 s=s->next;
  114.                 if (s==0)
  115.                 {
  116.                         if (flag) break;
  117.                         s=me->data_sections;
  118.                         if (s==0) break;
  119.                         flag=1;
  120.                         continue;
  121.                 }
  122.         }
  123. }
  124.  
  125. void assign_addresses(me_info* me)
  126. {
  127.         int i;
  128.         meos_section_info* si;
  129.         for (i=1;i<me->s1->nb_sections;i++)
  130.         {
  131.                 Section* s=me->s1->sections[i];
  132.                 if (strcmp(".text",s->name)==0)
  133.                 {
  134.                         si=tcc_malloc(sizeof(meos_section_info));
  135.                         si->data=s->data;
  136.                         si->data_size=s->data_offset;
  137.                         si->next=me->code_sections;
  138.                         si->sec_num=i;
  139.                         me->code_sections=si;
  140.                         continue;
  141.                 }
  142.                 if (strcmp(".data",s->name)==0)
  143.                 {
  144.                         si=tcc_malloc(sizeof(meos_section_info));
  145.                         si->data=s->data;
  146.                         si->data_size=s->data_offset;
  147.                         si->next=me->data_sections;
  148.                         si->sec_num=i;
  149.                         me->data_sections=si;
  150.                         continue;
  151.                 }
  152.                 if (strcmp(".bss",s->name)==0)
  153.                 {
  154.                         si=tcc_malloc(sizeof(meos_section_info));
  155.                         si->data_size=s->data_offset;
  156.                         si->next=me->bss_sections;
  157.                         si->sec_num=i;
  158.                         me->bss_sections=si;
  159.                         continue;
  160.                 }
  161.         }
  162.         int addr;
  163.         addr=sizeof(IMAGE_MEOS_FILE_HEADER);
  164.         for (si=me->code_sections;si;si=si->next)
  165.         {
  166.                 si->sh_addr=addr;
  167.                 addr+=si->data_size;
  168.         }
  169.         for (si=me->data_sections;si;si=si->next)
  170.         {
  171.                 si->sh_addr=addr;
  172.                 addr+=si->data_size;
  173.         }
  174.         me->header.image_size=addr;
  175.         for (si=me->bss_sections;si;si=si->next)
  176.         {
  177.                 si->sh_addr=addr;
  178.                 addr+=si->data_size;
  179.         }
  180.         addr+=4096;
  181.         addr=(addr+4)&(~3);
  182.         me->header.stack=addr;
  183.         me->header.memory_size=addr;
  184.         build_reloc(me);
  185. }
  186.  
  187.  
  188. const char *tcc_get_symbol_name(int st_name)
  189. // return string by index from stringtable section
  190. {
  191.         const char *sym_name = strtab_section->data + st_name;
  192.         return sym_name;
  193. }
  194.  
  195. int tcc_find_symbol_me(me_info* me, const char *sym_name)
  196. {
  197.         int i;
  198.         int symtab;
  199.         int strtab;
  200.         symtab=0;
  201.         strtab=0;
  202.         for (i=1;i<me->s1->nb_sections;i++)
  203.         {
  204.                 Section* s;
  205.                 s=me->s1->sections[i];
  206.                 if (strcmp(s->name,".symtab")==0)
  207.                 {
  208.                         symtab=i;
  209.                 }
  210.                 if (strcmp(s->name,".strtab")==0)
  211.                 {
  212.                         strtab=i;
  213.                 }
  214.         }
  215.         if (symtab==0 || strtab==0)
  216.         {
  217.         tcc_error_noabort("undefined sections .symtab or .strtab on linking '%s'", sym_name);
  218.                 return 0;
  219.         }
  220.         Elf32_Sym* s,*se;
  221.         char* name;
  222.         s=(Elf32_Sym*)me->s1->sections[symtab]->data;
  223.         se=(Elf32_Sym*)(((void*)s)+me->s1->sections[symtab]->data_offset);
  224.         name=(char*)me->s1->sections[strtab]->data;
  225.         while (s<se)
  226.         {
  227.                 if (strcmp(name+s->st_name,sym_name)==0)
  228.                 {
  229.                         return s->st_value+findsection(me,s->st_shndx)->sh_addr;
  230.                 }
  231.                 s++;
  232.         }
  233.     tcc_error_noabort("undefined symbol '%s'", sym_name);
  234.         return 0;
  235. }
  236.  
  237. const char* me_magic="MENUET01";
  238. int tcc_output_me(TCCState* s1,const char *filename)
  239. {
  240.         me_info me;
  241.     int i;
  242.     FILE* f;
  243.     //printf("%d\n",s1->nb_sections);
  244.         memset(&me,0,sizeof(me));
  245.         me.s1=s1;
  246.         relocate_common_syms();
  247.         assign_addresses(&me);
  248.         me.header.entry_point=tcc_find_symbol_me(&me,"start");
  249.         me.header.params= tcc_find_symbol_me(&me,"__argv"); // <--
  250.         me.header.argv= tcc_find_symbol_me(&me,"__path"); // <--
  251.        
  252.         f=fopen(filename,"wb");
  253.     for (i=0;i<8;i++)
  254.         me.header.magic[i]=me_magic[i];
  255.         /*me.header.magic[0]='M';me.header.magic[1]='E';
  256.         me.header.magic[2]='N';me.header.magic[3]='U';
  257.         me.header.magic[4]='E';me.header.magic[5]='T';
  258.         me.header.magic[6]='0';me.header.magic[7]='1';*/
  259.         fwrite(&me.header,1,sizeof(IMAGE_MEOS_FILE_HEADER),f);
  260.         meos_section_info* si;
  261.         for(si=me.code_sections;si;si=si->next)
  262.                 fwrite(si->data,1,si->data_size,f);
  263.         for (si=me.data_sections;si;si=si->next)
  264.                 fwrite(si->data,1,si->data_size,f);
  265.         fclose(f);
  266.         return 0;
  267. }
  268.  
  269. #ifndef _WIN32
  270.  
  271. static inline int get_current_folder(char* buf, int bufsize){
  272.     register int val;
  273.     asm volatile ("int $0x40":"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize));
  274.     return val;
  275. }
  276.  
  277.  
  278. char *getcwd(char *buf, size_t size)
  279. {
  280.         int rc = get_current_folder(buf, size);
  281.         if (rc > size)
  282.         {
  283.                 errno = ERANGE;
  284.                 return 0;
  285.         }
  286.         else
  287.                 return buf;
  288. }
  289.  
  290. #endif
  291.