Subversion Repositories Kolibri OS

Rev

Rev 9545 | Rev 9558 | 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.          DLLReference **dllref = me->s1->loaded_dlls;
  47.          CString *str_arr, *len_arr, *sym_arr;
  48.          char dll_len;
  49.          int dll_loaded = me->s1->nb_loaded_dlls;
  50.          int nlib = 0;
  51.          int i;
  52.  
  53.          if (me->header.version != 2)
  54.                  return;
  55.  
  56.          str_arr = tcc_malloc(sizeof(CString) * dll_loaded);
  57.  
  58.          len_arr = tcc_malloc(sizeof(CString)* dll_loaded);
  59.          
  60.          sym_arr = tcc_malloc(sizeof(CString)* dll_loaded);
  61.  
  62.          for (sym_index = 1; sym_index < sym_end; ++sym_index) {
  63.                  sym = (ElfW(Sym) *)symtab_section->data + sym_index;
  64.                  if (sym->st_shndx == SHN_UNDEF) {
  65.                          const char *name = symtab_section->link->data + sym->st_name;
  66.                          int dynsym_index = find_elf_sym(me->s1->dynsymtab_section, name);
  67.  
  68.                          if (dynsym_index == 0) {
  69.                                  //if (strcmp(name, __kx_import_table_sym) != 0) {
  70.                                          tcc_error/*_noabort*/("undefined symbol '%s'", name);
  71.                          }
  72.  
  73.                          // KOS support 32 bit only
  74.                          Elf32_Sym* dyn_sym = &((ElfW(Sym) *)me->s1->dynsymtab_section->data)[dynsym_index];
  75.                          char* dll_name;
  76.                          // TCC store dll index in dyn_sym->st_size field
  77.                          i = dyn_sym->st_size - 1;
  78.                          if (dllref[i]->level != -1) {
  79.                                  dll_name = dllref[i]->name;
  80.                                  dll_len = strlen(dll_name) + 1;
  81.  
  82.                                  nlib++;
  83.  
  84.                                  cstr_new(&str_arr[i]);
  85.                                  cstr_new(&len_arr[i]);
  86.                                  cstr_new(&sym_arr[i]);
  87.  
  88.                                  cstr_ccat(&len_arr[i], dll_len);
  89.                                  cstr_cat(&str_arr[i], dll_name, dll_len);
  90.                                  //Mark dll as already used
  91.                                  dllref[i]->level = -1;
  92.                          }
  93.                          
  94.                          cstr_wccat(&sym_arr[i], (int)name);
  95.  
  96.                          // Export defined with prefix?
  97.                          if (dyn_sym->st_value == -1){
  98.                                  name += (dll_len - 4); // skip prefix_
  99.                          }
  100.  
  101.                          char name_len = strlen(name) + 1;
  102.                          cstr_ccat(&len_arr[i], name_len);
  103.                          cstr_cat(&str_arr[i], name, name_len);
  104.  
  105.                  }
  106.          }
  107.  
  108.          /*if (len_arr[0].size == 0)
  109.          {
  110.  
  111.                  //tcc_error("");
  112.                  return;
  113.          }*/
  114.    
  115.          // Fixed BUG#15 (possible access to uninitialized due unused library)
  116.          // Exclude unused librarys
  117.          if (nlib < dll_loaded) {
  118.                  i = 0; int j, n = 0;
  119.                  do {
  120.  
  121.                          // Find unused library
  122.                          if (dllref[i]->level == 0) {
  123.                                  j = i + 1;
  124.                                  
  125.                                  while (j < dll_loaded) {
  126.                                          // Find first used library
  127.                                          if (dllref[j]->level == -1) {
  128.                                                  // Found, copy i from j
  129.                                                  str_arr[i] = str_arr[j];
  130.                                                  len_arr[i] = len_arr[j];
  131.                                                  sym_arr[i] = sym_arr[j];
  132.                                                  // Mark j as unused
  133.                                                  dllref[j]->level = 0;
  134.  
  135.                                                  if (++n == nlib)
  136.                                                          goto __done;
  137.  
  138.                                                  break;
  139.                                          }
  140.  
  141.                                          j++;
  142.  
  143.                                  }
  144.  
  145.                          }
  146.  
  147.                          i++;
  148.  
  149.                  } while (i < dll_loaded);
  150.  
  151.          }
  152.  
  153.  __done:
  154.  
  155.          // Zero terminate of ptr (was BUG#3)
  156.          i = 0;
  157.          do {
  158.  
  159.                  cstr_ccat(&len_arr[i], 0);
  160.  
  161.                  i++;
  162.  
  163.          } while (i < nlib);
  164.  
  165.          kx_import_table* imp_sect;
  166.  
  167.          imp_sect = tcc_mallocz(sizeof(kx_import_table));
  168.          imp_sect->data = tcc_mallocz(4096); // FIXME!!! I increased it to 4Kb, but steel need dynamicaly size
  169.          imp_sect->data_size = 0;
  170.          //imp_sect->sh_addr = me->header.image_size;// +1;
  171.          
  172.          long imp_data = (long)imp_sect->data; //FIXED changed to long for gcc compatible
  173.  
  174.          // Strings
  175.          i = 0;
  176.          do {
  177.                  memcpy((void*)imp_data, str_arr[i].data, str_arr[i].size);
  178.                  imp_data += str_arr[i].size;
  179.                  imp_sect->data_size += str_arr[i].size;
  180.  
  181.                  i++;
  182.  
  183.          } while (i < nlib);
  184.  
  185.          // Align pad (check algorithm!)
  186.          int align = 4 - (me->header.image_size + imp_sect->data_size) % 4;
  187.          align = align < 4 ? align : 0;
  188.          imp_data += align;
  189.          imp_sect->data_size += align;
  190.  
  191.          /*add_elf_sym(
  192.                  me->s1->dynsymtab_section,
  193.                  me->header.image_size + imp_sect->data_size,
  194.                  0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
  195.                  0, SHN_ABS, __kx_import_table_sym);*/
  196.          __kx_header.i_ptr = me->header.image_size + imp_sect->data_size;
  197.  
  198.          LibraryEntry lib;
  199.          lib.ImportEntry = me->header.image_size + imp_sect->data_size + (nlib * 8) + 4;
  200.          lib.LibraryName = me->header.image_size + 0;
  201.  
  202.          // LibraryEntry
  203.          memcpy((void*)imp_data, &lib, sizeof(LibraryEntry));
  204.  
  205.          if (nlib > 1) {
  206.                  int prev_sum = 0;
  207.                  int prev = 0;
  208.                  i = 1;
  209.                  do {
  210.                          lib.ImportEntry += (len_arr[prev].size - 2) * 4 + 4; //TODO: check that +4 is correct
  211.                          prev_sum += str_arr[prev].size;
  212.                          lib.LibraryName = me->header.image_size + prev_sum; // FIXED (was BUG#10)
  213.                          imp_data += sizeof(LibraryEntry);
  214.                          imp_sect->data_size += sizeof(LibraryEntry);
  215.                          memcpy((void*)imp_data, &lib, sizeof(LibraryEntry));
  216.  
  217.                          prev++;
  218.                          i++;
  219.  
  220.                  } while (i < nlib);
  221.          }
  222.  
  223.          // End of LibraryEntry
  224.          imp_data += sizeof(LibraryEntry) + 4;
  225.          imp_sect->data_size += sizeof(LibraryEntry) + 4;
  226.  
  227.          const char *sym_name;
  228.          char name_len;
  229.          long len_sum;
  230.  
  231.          len_sum = me->header.image_size;
  232.          i = 0;
  233.          do {
  234.                  char* len_data = len_arr[i].data;
  235.                  long* sym_data = sym_arr[i].data;
  236.  
  237.                  name_len = *len_data++; // Skip library name
  238.  
  239.                  do {
  240.                                                  
  241.                          memcpy(&sym_name, sym_data++, 4);
  242.                          
  243.                          add_elf_sym(
  244.                                  me->s1->dynsymtab_section,
  245.                                  me->header.image_size + imp_sect->data_size,
  246.                                  0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
  247.                                  0, SHN_ABS, sym_name);
  248.  
  249.                          len_sum += name_len;
  250.                          memcpy((void*)imp_data, &len_sum, 4);
  251.  
  252.                          imp_data += 4;
  253.                          imp_sect->data_size += 4;
  254.                          name_len = */*++*/len_data/*++*/;              //(was BUG#3)
  255.  
  256.                  } while (/*name_len*/*(++len_data) > 0);
  257.  
  258.                  imp_data += 4;
  259.                  imp_sect->data_size += 4;
  260.  
  261.                  len_sum += name_len;
  262.                  i++;
  263.  
  264.          } while (i < nlib);
  265.  
  266.          me->header.image_size += imp_sect->data_size;
  267.          me->imp_table = imp_sect;
  268.  
  269.          tcc_free(str_arr);
  270.          tcc_free(len_arr);
  271.          tcc_free(sym_arr);
  272.  }
  273.  
  274.  void kx_init(me_info* me) {
  275.          ElfW(Sym) *sym;
  276.          int sym_index = 1, sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
  277.          // Check that we have at last one import...
  278.          for (; sym_index < sym_end; ++sym_index) {
  279.                  sym = (ElfW(Sym) *)symtab_section->data + sym_index;
  280.                  if (sym->st_shndx == SHN_UNDEF)
  281.                          break;
  282.          }
  283.          if ((sym_index < sym_end) &&
  284.                  // ... and user attached at least one *.def
  285.                  (me->s1->nb_loaded_dlls))
  286.                         me->header.version = 2;
  287.  }
  288.  
  289.  long kx_get_header_length(me_info* me) {
  290.          if (me->header.version == 2)
  291.                  return sizeof(kx_header);
  292.  
  293.          return 0;
  294.  }
  295.  
  296.  void kx_write_header(me_info* me, FILE* f) {
  297.          if (me->header.version == 2)
  298.                  fwrite(&__kx_header, 1, sizeof(kx_header), f);
  299.  }
  300.  
  301.  void kx_write_imports(me_info* me, FILE* f) {
  302.          if (me->imp_table)
  303.                  fwrite(me->imp_table->data, 1, me->imp_table->data_size, f);
  304.                  
  305.  }
  306.  
  307.  void kx_free(me_info* me) {
  308.          kx_import_table* imp = me->imp_table;
  309.          if (imp){
  310.                  tcc_free(imp->data);
  311.                  tcc_free(imp);
  312.         }
  313.  }
  314.  
  315. #if /*!*/defined(_DEBUG)// && !defined(_WIN32)
  316.  #define        kx_debug_output         printf
  317. #else
  318.  #define kx_debug_output(s,p)   ((void)0)
  319. #endif
  320.  
  321. /*
  322.         Calling once from tcc_set_lib_path_xxx
  323.         This function correct tcc_root if tcc_root/kx is a run directory,
  324.         otherwise do trim filename
  325. */
  326. #if 0
  327.  void kx_fix_root_directory(char *buf, size_t size) {
  328.          
  329.          int defult = 1;
  330.          char* tcc_conf = tcc_malloc(strlen(buf)+5);
  331.          strcpy(tcc_conf, buf);
  332.          char* base = tcc_basename(tcc_conf);
  333.          *base = 0;
  334.          base = tcc_basename(buf);
  335.          strcat(tcc_conf, "tcc.conf");
  336.          FILE* f = fopen(tcc_conf,"r");
  337.          if (f) {
  338.                  char line[100];
  339.                  while (fgets(line, sizeof line, f)){
  340.                          switch (*line)
  341.                                 case '#':
  342.                                 case '\n':
  343.                                         continue;
  344.                                         if ((strspn(line, "tcc_root") == 8) && line[8] == ' ') {
  345.  
  346.                                                 if (strcmp(line + 9, "kx") == 0) {
  347.                                                         strcpy(base, line + 9);
  348.                                                         defult = 0;
  349.                                                 }
  350.                                                 else
  351.                                                 {
  352.                                                         // Disallow change tcc_root with arbitrary path
  353.                                                         continue;
  354.                                                 }
  355.  
  356.                                         }
  357.                  }
  358.  
  359.                  fclose(f);
  360.          }
  361.          if (defult) {
  362.  
  363.                  *--base = 0;
  364.          }
  365.  
  366.          tcc_free(tcc_conf);
  367.          kx_debug_output("tcc root = %s\n", buf);
  368.  }
  369. #endif
  370.