Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4973 right-hear 1
#include"mcoff.h"
2
#include
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;sco_filehdr->f_nscns;s++)
52
 {
53
  for(r=0;rco_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
}