Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  *  TCCKX.C - KolibriOS/KX file output for the TinyC Compiler
  3.  *
  4.  *  Copyright (c) 2021 Coldy
  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[4];
  23.         long flags;
  24.         long i_ptr;
  25. } kx_header;
  26.  
  27. static kx_header __kx_header = { 'K','X',0, 0, 0x40, 0 };
  28.  
  29. typedef struct {
  30.          uint32_t ImportEntry;
  31.          uint32_t LibraryName;
  32.  } LibraryEntry;
  33.  
  34.  /*union ImportEntry {
  35.  uint32_t ImportStr;
  36.  uint32_t ImportPrt;
  37.  };*/
  38.  
  39.  //static char __kx_import_table_sym[] = "__i_ptr__";
  40.  
  41.  void kx_build_imports(me_info* me) {
  42.  
  43.          ElfW(Sym) *sym;
  44.          int sym_index, sym_end;
  45.          sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
  46.          CString *str_arr, *len_arr, *sym_arr;
  47.    char dll_len;
  48.          int nlib = 0;
  49.          int i;
  50.  
  51.          if (me->header.version != 2)
  52.                  return;
  53.  
  54.          str_arr = tcc_malloc(sizeof(CString) * me->s1->nb_loaded_dlls);
  55.  
  56.          len_arr = tcc_malloc(sizeof(CString)* me->s1->nb_loaded_dlls);
  57.    
  58.    sym_arr = tcc_malloc(sizeof(CString)* me->s1->nb_loaded_dlls);
  59.  
  60.          for (sym_index = 1; sym_index < sym_end; ++sym_index) {
  61.                  sym = (ElfW(Sym) *)symtab_section->data + sym_index;
  62.                  if (sym->st_shndx == SHN_UNDEF) {
  63.                          const char *name = symtab_section->link->data + sym->st_name;
  64.                          int dynsym_index = find_elf_sym(me->s1->dynsymtab_section, name);
  65.  
  66.                          if (dynsym_index == 0) {
  67.                                  //if (strcmp(name, __kx_import_table_sym) != 0) {
  68.                                          tcc_error/*_noabort*/("undefined symbol '%s'", name);
  69.                                          //continue; // FIXME: stop compile!
  70.                                  //}
  71.  
  72.                                  //continue;
  73.                          }
  74.  
  75.                          // KOS support 32 bit only
  76.                          Elf32_Sym* dyn_sym = &((ElfW(Sym) *)me->s1->dynsymtab_section->data)[dynsym_index];
  77.                          DLLReference **dllref = me->s1->loaded_dlls;
  78.        char* dll_name;
  79.                          i = dyn_sym->st_size - 1;
  80.                          // TCC store dll index in dyn_sym->st_size field
  81.                          if (dllref[i]->level != -1) {
  82.                                  dll_name = dllref[i]->name;
  83.                                  dll_len = strlen(dll_name) + 1;
  84.  
  85.                                  nlib++;
  86.  
  87.                                  cstr_new(&str_arr[i]);
  88.                                  cstr_new(&len_arr[i]);
  89.          cstr_new(&sym_arr[i]);
  90.  
  91.                                  cstr_ccat(&len_arr[i], dll_len);
  92.                                  cstr_cat(&str_arr[i], dll_name, dll_len);
  93.                                  //Mark dll as already used
  94.                                  dllref[i]->level = -1;
  95.                          }
  96.        
  97.        cstr_wccat(&sym_arr[i], (int)name);
  98.  
  99.                          // Export defined with prefix?
  100.                          if (dyn_sym->st_value == -1){
  101.                                  name += (dll_len - 4); // skip prefix_
  102.                          }
  103.  
  104.                          char name_len = strlen(name) + 1;
  105.                          cstr_ccat(&len_arr[i], name_len);
  106.                          cstr_cat(&str_arr[i], name, name_len);
  107.  
  108.                  }
  109.          }
  110.  
  111.          /*if (len_arr[0].size == 0)
  112.          {
  113.  
  114.                  //tcc_error("");
  115.                  return;
  116.          }*/
  117.  
  118.          // Zero terminate of ptr (was BUG#3)
  119.          i = 0;
  120.          do {
  121.  
  122.                  cstr_ccat(&len_arr[i], 0);
  123.  
  124.                  i++;
  125.  
  126.          } while (i < nlib);
  127.  
  128.          kx_import_table* imp_sect;
  129.  
  130.          imp_sect = tcc_mallocz(sizeof(kx_import_table));
  131.          imp_sect->data = tcc_mallocz(1024); // FIXME!!!
  132.          imp_sect->data_size = 0;
  133.          //imp_sect->sh_addr = me->header.image_size;// +1;
  134.  
  135.         long imp_data = (long)imp_sect->data; //FIXED changed to long for gcc compatible
  136.  
  137.          // Strings
  138.          i = 0;
  139.          do {
  140.                  memcpy((void*)imp_data, str_arr[i].data, str_arr[i].size);
  141.                  imp_data += str_arr[i].size;
  142.                  imp_sect->data_size += str_arr[i].size;
  143.  
  144.                  i++;
  145.  
  146.          } while (i < nlib);
  147.  
  148.          // Align pad (check algorithm!)
  149.          int align = 4 - (me->header.image_size + imp_sect->data_size) % 4;
  150.          imp_data += align;
  151.          imp_sect->data_size += align;
  152.  
  153.          /*add_elf_sym(
  154.                  me->s1->dynsymtab_section,
  155.                  me->header.image_size + imp_sect->data_size,
  156.                  0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
  157.                  0, SHN_ABS, __kx_import_table_sym);*/
  158.          __kx_header.i_ptr = me->header.image_size + imp_sect->data_size;
  159.  
  160.          LibraryEntry lib;
  161.          lib.ImportEntry = me->header.image_size + imp_sect->data_size + (nlib * 8) + 4;
  162.          lib.LibraryName = me->header.image_size + 0;
  163.  
  164.          // LibraryEntry
  165.          memcpy((void*)imp_data, &lib, sizeof(LibraryEntry));
  166.  
  167.          if (nlib > 1) {
  168.      int prev_sum = 0;
  169.                  int prev = 0;
  170.                  i = 1;
  171.                  do {
  172.                          lib.ImportEntry += (len_arr[prev].size - 2) * 4 + 4; //TODO: check that +4 is correct
  173.                          prev_sum += str_arr[prev].size;
  174.                          lib.LibraryName = me->header.image_size + prev_sum; // FIXED (was BUG#10)
  175.                          imp_data += sizeof(LibraryEntry);
  176.                          imp_sect->data_size += sizeof(LibraryEntry);
  177.                          memcpy((void*)imp_data, &lib, sizeof(LibraryEntry));
  178.  
  179.                          prev++;
  180.                          i++;
  181.  
  182.                  } while (i < nlib);
  183.          }
  184.  
  185.          // End of LibraryEntry
  186.          imp_data += sizeof(LibraryEntry) + 4;
  187.          imp_sect->data_size += sizeof(LibraryEntry) + 4;
  188.  
  189.          const char *sym_name;
  190.    char name_len;
  191.          long len_sum;
  192.  
  193.          len_sum = me->header.image_size;
  194.          i = 0;
  195.          do {
  196.                  char* len_data = len_arr[i].data;
  197.      long* sym_data = sym_arr[i].data;
  198.  
  199.                  name_len = *len_data++; // Skip library name
  200.  
  201.                  do {
  202.                                                  
  203.                          memcpy(&sym_name, sym_data++, 4);
  204.                          
  205.                          add_elf_sym(
  206.                                  me->s1->dynsymtab_section,
  207.                                  me->header.image_size + imp_sect->data_size,
  208.                                  0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
  209.                                  0, SHN_ABS, sym_name);
  210.  
  211.                          len_sum += name_len;
  212.                          memcpy((void*)imp_data, &len_sum, 4);
  213.  
  214.                          imp_data += 4;
  215.                          imp_sect->data_size += 4;
  216.                          name_len = */*++*/len_data/*++*/;              //(was BUG#3)
  217.  
  218.                  } while (/*name_len*/*(++len_data) > 0);
  219.  
  220.                  imp_data += 4;
  221.                  imp_sect->data_size += 4;
  222.  
  223.                  len_sum += name_len;
  224.                  i++;
  225.  
  226.          } while (i < nlib);
  227.  
  228.          me->header.image_size += imp_sect->data_size;
  229.          me->imp_table = imp_sect;
  230.  
  231.          tcc_free(str_arr);
  232.          tcc_free(len_arr);
  233.    tcc_free(sym_arr);
  234.  
  235.  }
  236.  
  237.  
  238.  
  239.  void kx_init(me_info* me) {
  240.          ElfW(Sym) *sym;
  241.          int sym_index = 1, sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
  242.          // Check that we have at last one import...
  243.          for (; sym_index < sym_end; ++sym_index) {
  244.                  sym = (ElfW(Sym) *)symtab_section->data + sym_index;
  245.                  if (sym->st_shndx == SHN_UNDEF)
  246.                          break;
  247.          }
  248.          if ((sym_index < sym_end) &&
  249.                  // ... and user attached at last one *.def
  250.                  (me->s1->nb_loaded_dlls))
  251.                         me->header.version = 2;
  252.  
  253.          //tcc_add_crt(me->s1, "start1.o");
  254.  }
  255.  
  256.  long kx_get_header_length(me_info* me) {
  257.          if (me->header.version == 2)
  258.                  return sizeof(kx_header);
  259.  
  260.          return 0;
  261.  }
  262.  
  263.  void kx_write_header(me_info* me, FILE* f) {
  264.          if (me->header.version == 2)
  265.                  fwrite(&__kx_header, 1, sizeof(kx_header), f);
  266.  }
  267.  
  268.  void kx_write_imports(me_info* me, FILE* f) {
  269.          if (me->imp_table)
  270.                  fwrite(me->imp_table->data, 1, me->imp_table->data_size, f);
  271.                  
  272.  }
  273.  
  274.  void kx_free(me_info* me) {
  275.          kx_import_table* imp = me->imp_table;
  276.          if (imp){
  277.                  tcc_free(imp->data);
  278.                  tcc_free(imp);
  279.         }
  280.  }