home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / gcl-1.000 / gcl-1 / gcl-1.0 / c / sfaslelf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-29  |  8.1 KB  |  355 lines

  1.  
  2. #define ELF_TARGET_SPARC 1
  3. /* #include "include.h" */
  4. #include "ext_sym.h"
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/mman.h>
  8. #include <sys/stat.h>
  9.  
  10.  
  11. #include <elf.h>
  12.  
  13.  
  14. #ifdef STAND
  15. char *kcl_self;
  16. main(argc,argv)
  17.      char *argv[];
  18. {char *file ;
  19.  file = argv[1];
  20.  kcl_self = argv[2];
  21.  fasload(file);
  22. }
  23. #endif
  24.  
  25. static Elf32_Ehdr *file_h;
  26. static Elf32_Shdr *section_h;
  27. static caddr_t base;
  28. static char *string_table;
  29. static char *section_names;
  30. static int text_index;
  31. struct sect {int start;
  32.       };
  33. static struct sect *section;
  34.  
  35. static int symsize;
  36.  
  37. char *the_start,*start_address;
  38.  
  39.  
  40. #define SECTION_H(n) \
  41.      (*(Elf32_Shdr *) ((char *) section_h + file_h->e_shentsize * (n)))
  42.  
  43.  
  44. /* align for power of two n */
  45. void *
  46. round_up(address,n)
  47.      unsigned int address,n;
  48. {
  49.  return  (void *)((address + n -1) & ~(n-1)) ;
  50. }
  51. #define ROUND_UP(a,b) round_up(a,b) 
  52.  
  53.  
  54. fasload(faslfile)
  55.      object faslfile;
  56. {  FILE *fp;
  57.    object data;
  58.    char filename[256];
  59.    Elf32_Shdr *shp;
  60.    int file;
  61.    struct stat stat_buf;
  62.    object     * old_vs_base =   vs_base ;
  63.    object     * old_vs_top =   vs_top ;
  64.    int symtab_index,j;
  65.    int nsyms;
  66.    int init_address=0;
  67.    int extra_bss=0;
  68.    object memory;
  69.    int current = 0,max_align = 0;
  70.    struct sect section_org[40];
  71.    Elf32_Sym *symbol_table;
  72.  
  73.    section = section_org;
  74.  
  75. #ifdef STAND
  76.    strcpy(filename,faslfile);
  77.    fp=fopen(filename,RDONLY);
  78. #else
  79.    coerce_to_filename(faslfile, filename);
  80.    faslfile = open_stream(faslfile, smm_input, Cnil, Kerror);
  81.    fp = faslfile->sm.sm_fp;
  82. #endif    
  83.  
  84.        
  85.    file = fileno(fp);
  86.  
  87.    if (fstat (file, &stat_buf) == -1)
  88.      FEerror ("Can't fstat(~a): errno %d\n", 1,faslfile);
  89.  
  90.    base = mmap (0, stat_buf.st_size,PROT_READ|PROT_WRITE, MAP_PRIVATE, file, 0);
  91.  
  92.    if (base == (caddr_t) -1)
  93.      FEerror ("Can't mmap(~a):",1,faslfile);
  94.  
  95.    file_h = (Elf32_Ehdr *) base;
  96.  
  97.    section_h = (Elf32_Shdr *) ((char *) base + file_h->e_shoff);
  98.   
  99.    section_names = (char *) base
  100.      + SECTION_H(file_h->e_shstrndx).sh_offset;
  101.  
  102.    symtab_index = get_section_number(".symtab");
  103.    text_index = get_section_number(".text");
  104.  
  105.    /* calculate how much room is needed to align all the sections
  106.     appropriately, and at what offsets they will be read in, presuming
  107.     that the begin of the memory is aligned on max_align */
  108.    for (j=1 ; j <  file_h->e_shnum ; j++)
  109.       { 
  110.     if ((SECTION_H(j).sh_flags & SHF_ALLOC)
  111.         && (SECTION_H(j).sh_type == SHT_PROGBITS))
  112.  
  113.       { if (SECTION_H(j).sh_addralign > max_align)
  114.           max_align = SECTION_H(j).sh_addralign;
  115.         current = (int) ROUND_UP(current,SECTION_H(j).sh_addralign);
  116.         section[j].start = current;
  117.         current += SECTION_H(j).sh_size;
  118.       }
  119.       }
  120.         
  121.    
  122.    shp = &SECTION_H(symtab_index);
  123.    symbol_table = (void *) base + shp->sh_offset;
  124.    nsyms = shp->sh_size/shp->sh_entsize;
  125.    symsize = shp->sh_entsize;
  126.  
  127.    string_table = base + SECTION_H(get_section_number(".strtab")).sh_offset;
  128.  
  129.    /* seek to end of old file */
  130.    SEEK_TO_END_OFILE(fp);
  131.  
  132.  
  133.    if (!((c_table.ptable) && *(c_table.ptable)))
  134.      build_symbol_table();
  135.  
  136.    extra_bss = 0;
  137.    /*
  138.    extra_bss=get_extra_bss(symbol_table,nsyms,current,
  139.                &init_address,bss_size);
  140.                */
  141.  
  142.  
  143.    memory = alloc_object(t_cfdata);
  144.    memory->cfd.cfd_self = 0;
  145.    memory->cfd.cfd_start = 0;
  146.    memory->cfd.cfd_size = current + (max_align > sizeof(char *) ?
  147.                      max_align :0);
  148.    
  149.  
  150.    the_start=start_address=        
  151.      memory->cfd.cfd_start =    
  152.        alloc_contblock(memory->cfd.cfd_size);
  153.  
  154.     /* make sure the memory is aligned */
  155.    start_address = ROUND_UP(start_address,max_align);
  156.    memory->cfd.cfd_size = memory->cfd.cfd_size - (start_address - the_start);
  157.    memory->cfd.cfd_start = start_address;    
  158.  
  159.  
  160.     for (j=1 ; j <  file_h->e_shnum ; j++)
  161.       { if ((SECTION_H(j).sh_flags & SHF_ALLOC)
  162.         && (SECTION_H(j).sh_type == SHT_PROGBITS))
  163.       { 
  164.         bcopy(base + SECTION_H(j).sh_offset,start_address + section[j].start,
  165.           SECTION_H(j).sh_size);
  166.       }
  167.       }
  168.    
  169.    relocate_symbols(symbol_table,nsyms);
  170.  
  171.    {int j=0;
  172.     for (j=1 ; j <  file_h->e_shnum ; j++)
  173.       { shp = &SECTION_H(j); 
  174.     if (shp->sh_type == SHT_RELA)
  175.       { int index_to_relocate = shp->sh_info;
  176.         if (symtab_index != shp->sh_link)
  177.           FEerror("unexpected symbol table used");
  178.         the_start = start_address + section[index_to_relocate].start;
  179.         }
  180.     else
  181.       if (shp->sh_type == SHT_REL)
  182.         FEerror("unknown rel type");
  183.       else continue;
  184.     {int k=0;
  185.      char *rel = (char *) base +   shp->sh_offset;
  186.      for (k= 0; k< shp->sh_size ; k+= shp->sh_entsize)
  187.        relocate(symbol_table,rel + k);
  188.        }}}
  189.  
  190.    SEEK_TO_END_OFILE(fp);
  191.    if (feof(fp))
  192.      data=0;
  193.    else
  194.      data = read_fasl_vector(faslfile);
  195.  
  196.    munmap(base, stat_buf.st_size);
  197.  
  198.    close_stream(faslfile, 1);
  199.  
  200. #ifdef CLEAR_CACHE
  201.    CLEAR_CACHE;
  202. #endif
  203.  
  204.    init_address = section[text_index].start;
  205.    call_init(init_address,memory,data);
  206.     
  207.    vs_base = old_vs_base;
  208.    vs_top = old_vs_top;
  209.    if(symbol_value(Vload_verbose)!=Cnil)
  210.      printf("start address -T %x ",memory->cfd.cfd_start);
  211.    return(memory->cfd.cfd_size);
  212.  
  213.  }
  214.  
  215.  
  216. get_section_number(name)
  217.      char *name;
  218.      
  219. {int k ;
  220.  for (k = 1; k < file_h->e_shnum;
  221.       k++)
  222.    {
  223.      if (!strcmp (section_names + SECTION_H(k).sh_name,
  224.           name))
  225.        return k;
  226.    }
  227. /* fprintf(stderr,"could not find section %s\n", name); */
  228.  return 0;
  229. }
  230.  
  231. relocate_symbols(sym,nsyms)
  232.  Elf32_Sym *sym;
  233.  int nsyms;
  234. {  int siz = symsize;
  235.   while (--nsyms >= 0)
  236.     { switch(ELF32_ST_BIND(sym->st_info))
  237.     { case STB_LOCAL:
  238.         if (sym->st_shndx == SHN_ABS) break;
  239.         if ((SECTION_H(sym->st_shndx).sh_flags & SHF_ALLOC) == 0)
  240.           {printf("[unknown rel secn %d]",sym->st_shndx);}
  241.         else
  242.           sym->st_value += (int) (start_address + section[sym->st_shndx].start); 
  243.         break;
  244.       case STB_GLOBAL:
  245.      if (sym->st_shndx == SHN_UNDEF
  246.          || sym->st_shndx == SHN_COMMON)
  247.        {  set_symbol_address(sym,string_table + sym->st_name);
  248.         }
  249.         else
  250.           if (sym->st_shndx == text_index &&
  251.           bcmp("init_",string_table + sym->st_name,4) == 0) ;
  252.         else    
  253.           {printf("[unknown global sym %s]",string_table + sym->st_name);}
  254.         break;
  255.       default:
  256.         {printf("[unknown bind type %s]",ELF32_ST_BIND(sym->st_info));}
  257.       }
  258.       sym = (void *)sym + siz;
  259.     }
  260. }
  261.  
  262. relocate(symbol_table,reloc_info)
  263. Elf32_Rela *reloc_info;
  264. Elf32_Sym *symbol_table;
  265. {
  266.   char *where ;
  267.   {
  268.     unsigned int new_value;
  269.     unsigned int a,b,p,s,val;
  270.     a = reloc_info->r_addend;
  271.     b = (unsigned int) the_start;
  272.     s = symbol_table[ELF32_R_SYM(reloc_info->r_info)].st_value;
  273.     where = the_start + reloc_info->r_offset;
  274.     p = (unsigned int) where;
  275.  
  276.  
  277. #define MASK(n) (~(~0 << (n)))
  278. #define STORE_VAL(where, mask, val) \
  279.     *(unsigned int *)where = ((val & mask) | ((*(unsigned int *)where) & ~mask))
  280.     
  281.     switch(ELF32_R_TYPE(reloc_info->r_info)){
  282.     case     R_SPARC_WDISP30:
  283.       /* v-disp30*/
  284.       val=(s+a-p) >> 2;
  285.       STORE_VAL(where,MASK(30),val);
  286.       break;
  287.     
  288.     case R_SPARC_HI22:
  289.       /* t-sim22 */
  290.       val = (s+a)>>10;
  291.       STORE_VAL(where,MASK(22),val);
  292.       break;
  293.  
  294.     case R_SPARC_32:
  295.       /*    */
  296.       val = (s+a) ;
  297.       STORE_VAL(where,~0,val);
  298.       break;
  299.       
  300.     case R_SPARC_LO10:
  301.     /* T-simm13 */
  302.       val = (s+a) & MASK(10);
  303.       *(short *)(where +2) |= val;
  304.       break;
  305.     default:
  306.       printf("(non supported relocation type %d)\n",
  307.          ELF32_R_TYPE(reloc_info->r_info));
  308.     }
  309.   }
  310. }
  311.  
  312.  
  313.  
  314. #include "sfasli.c"
  315.  
  316. set_symbol_address(sym,string)
  317. Elf32_Sym *sym;
  318. char *string;
  319. {struct node *answ;
  320.  if (c_table.ptable)
  321.    {
  322.      answ = find_sym_ptable(string);
  323.      if(answ)
  324.        {
  325.      /* the old value of sym->n_value is the length of the common area
  326.         starting at this address */
  327.      sym->st_value = answ->address;
  328.      
  329.      
  330.        }
  331.      else
  332.        { 
  333.      fprintf(stdout,"symbol %s is not in base image",string);
  334.      fflush(stdout);
  335.        }}
  336.     else{FEerror("symbol table not loaded",0,0);}
  337.    
  338. }
  339.  
  340. #define STRUCT_SYMENT Elf32_Sym
  341.  
  342. /* dont try to add extra bss stuff here.   It is not really
  343. common so other files can't reference it, so we really
  344. should use static.
  345. */
  346.  
  347. get_extra_bss(symbol_table,length,start,ptr,bsssize)
  348. int length,bsssize,start;
  349. STRUCT_SYMENT *symbol_table;
  350. int *ptr;   /* store init address offset here */
  351. { return 0;
  352. }
  353.  
  354.  
  355.