Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include"mcoff.h"
  2. #include<stdlib.h>
  3. #include"string.h"
  4.  
  5. static int do_coff_relocation(coffobj_t * obj,unsigned long relno,
  6.  SCNHDR * sect,symlookupfn_t lookup_fn)
  7. {
  8.  int r_delta,t_delta=0;
  9.  unsigned long sym_val,sym_sect;
  10.  unsigned long * where;
  11.  int err;
  12.  RELOC * rel;
  13.  r_delta=obj->co_loadaddr+sect->s_scnptr-sect->s_vaddr;
  14.  rel=((RELOC *)(obj->co_loadaddr+sect->s_relptr))+relno;
  15.  where=(unsigned long *)(r_delta+rel->r_vaddr);
  16.  err=lookup_fn(obj,&sym_val,&sym_sect,rel->r_symndx);
  17.  if(err!=0)
  18.  {
  19.   printf("Unable to find symbol relno=%u\n",relno);
  20.   return err;
  21.  }
  22.  if(sym_sect!=0)
  23.  {
  24.   sect=&obj->co_sections[sym_sect-1];
  25.   t_delta=obj->co_loadaddr+sect->s_scnptr-sect->s_vaddr;
  26.  }
  27.  switch(rel->r_type)
  28.  {
  29.   case RELOC_ADDR32:
  30.    if(!sym_sect)
  31.     *where=sym_val;
  32.    else
  33.     *where+=t_delta;
  34.    break;
  35.   case RELOC_REL32:
  36.    if(!sym_sect)
  37.     *where+=sym_val-r_delta;
  38.    else
  39.     *where+=t_delta-r_delta;
  40.    break;
  41.   default:
  42.    printf("Invalid relocation type\n");
  43.    return -1;
  44.  }
  45.  return 0;
  46. }
  47.  
  48. int relocate_coff_file(coffobj_t * obj,symlookupfn_t lookupfn)
  49. {
  50.  int s,r;
  51.  for(s=0;s<obj->co_filehdr->f_nscns;s++)
  52.  {
  53.   for(r=0;r<obj->co_sections[s].s_nreloc;r++)
  54.   {
  55.    if(do_coff_relocation(
  56.     obj,
  57.     r,
  58.     &obj->co_sections[s],
  59.     lookupfn)!=0) return -1;
  60.   }
  61.  }
  62.  return 0;
  63. }
  64.  
  65. int mcoff_std_symlookupfn(coffobj_t * obj,unsigned long * sym_val,
  66.  unsigned long * sym_sect,int index)
  67. {
  68.  SYMENT * symtab,* lookup;
  69.  char xname[9];
  70.  char * symnamep;
  71.  symtab=obj->co_symtab+index;
  72.  *sym_sect=(unsigned long)symtab->e_scnum;
  73.  if(symtab->e_scnum>0)
  74.  {
  75.   *sym_val=symtab->e_value;
  76.   return 0;
  77.  }
  78.  if(symtab->e.e.e_zeroes==0)
  79.  {
  80.   symnamep=(char *)(((long)obj->co_strtab)+symtab->e.e.e_offset);
  81.  } else {
  82.   symnamep=(char *)symtab->e.e_name;
  83.   memset(xname,0,9);
  84.   memcpy(xname,symnamep,8);
  85.   symnamep=xname;
  86.  }
  87.  lookup=find_coff_symbol(obj,symnamep);
  88.  if(!lookup) return -1;
  89.  *sym_val=lookup->e_value+obj->co_sections[lookup->e_scnum-1].s_scnptr+obj->co_loadaddr;
  90.  return 0;
  91. }
  92.