Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4972 → Rev 4973

/programs/develop/libraries/menuetlibc/src/libmcoff/relocate.c
0,0 → 1,91
#include"mcoff.h"
#include<stdlib.h>
#include"string.h"
 
static int do_coff_relocation(coffobj_t * obj,unsigned long relno,
SCNHDR * sect,symlookupfn_t lookup_fn)
{
int r_delta,t_delta=0;
unsigned long sym_val,sym_sect;
unsigned long * where;
int err;
RELOC * rel;
r_delta=obj->co_loadaddr+sect->s_scnptr-sect->s_vaddr;
rel=((RELOC *)(obj->co_loadaddr+sect->s_relptr))+relno;
where=(unsigned long *)(r_delta+rel->r_vaddr);
err=lookup_fn(obj,&sym_val,&sym_sect,rel->r_symndx);
if(err!=0)
{
printf("Unable to find symbol relno=%u\n",relno);
return err;
}
if(sym_sect!=0)
{
sect=&obj->co_sections[sym_sect-1];
t_delta=obj->co_loadaddr+sect->s_scnptr-sect->s_vaddr;
}
switch(rel->r_type)
{
case RELOC_ADDR32:
if(!sym_sect)
*where=sym_val;
else
*where+=t_delta;
break;
case RELOC_REL32:
if(!sym_sect)
*where+=sym_val-r_delta;
else
*where+=t_delta-r_delta;
break;
default:
printf("Invalid relocation type\n");
return -1;
}
return 0;
}
 
int relocate_coff_file(coffobj_t * obj,symlookupfn_t lookupfn)
{
int s,r;
for(s=0;s<obj->co_filehdr->f_nscns;s++)
{
for(r=0;r<obj->co_sections[s].s_nreloc;r++)
{
if(do_coff_relocation(
obj,
r,
&obj->co_sections[s],
lookupfn)!=0) return -1;
}
}
return 0;
}
 
int mcoff_std_symlookupfn(coffobj_t * obj,unsigned long * sym_val,
unsigned long * sym_sect,int index)
{
SYMENT * symtab,* lookup;
char xname[9];
char * symnamep;
symtab=obj->co_symtab+index;
*sym_sect=(unsigned long)symtab->e_scnum;
if(symtab->e_scnum>0)
{
*sym_val=symtab->e_value;
return 0;
}
if(symtab->e.e.e_zeroes==0)
{
symnamep=(char *)(((long)obj->co_strtab)+symtab->e.e.e_offset);
} else {
symnamep=(char *)symtab->e.e_name;
memset(xname,0,9);
memcpy(xname,symnamep,8);
symnamep=xname;
}
lookup=find_coff_symbol(obj,symnamep);
if(!lookup) return -1;
*sym_val=lookup->e_value+obj->co_sections[lookup->e_scnum-1].s_scnptr+obj->co_loadaddr;
return 0;
}