/* * Copyright (C) 1996-1998 Ilya Ryzhenkov (orangy@inetlab.com) * This file maintains DLM relocation functionality */ #include "helpdefs.h" #include "dlm.h" #include "dlmimage.h" #include "dlm_sym.h" void print_name(unsigned int eip); /* This function is used to resolve one symbol (by index) in the DLM to some target. It loops thru relocs and fixup those referneced to symndx. */ unsigned long cache_hits=0; void _dlm_resolve_exact(TDlm *dlm, unsigned long symndx, void *target) { int i,l,r,d; unsigned long *where; DLMSYM *eh=dlm->Symbols+symndx; DLMREL *rels=dlm->Relocs; /* for (l=0; (lNumRel) && (rels[l].r_symndx!=symndx); l++);*/ //printf("Resolve %s in %s to %p\n",dlm->Strings+dlm->Symbols[symndx].e_name,dlm->filename,target); //print_name((unsigned)target); printf("\n"); /* binary search for start of relocation sequence for specified symbol */ l=0; r=dlm->NumRel-1; if (dlm->cached_idx != symndx) /* cached symbol is not what we are searching for */ { /* at least try to shorten search range */ if (dlm->cached_idx < symndx) l=(lcached_pos)?(cache_hits+=dlm->cached_pos,dlm->cached_pos):l; else if (dlm->cached_idx > symndx) r=(r>dlm->cached_pos)?(cache_hits+=r-dlm->cached_pos,dlm->cached_pos):r; while (l=symndx) r=d; else l=d+1; } if (rels[l].r_symndx!=symndx) return; } else { l=dlm->cached_pos; /* cache hit! */ cache_hits+=r; } // ??? should we roll back to start of symndx ? we might found // middle of the sequence! for (i=l; (i>0) && (rels[i-1].r_symndx==symndx); i--); for (; (iNumRel) && (rels[i].r_symndx==symndx); i++) { where=(unsigned long *)(dlm->Base+rels[i].r_vaddr); *where=dlm->RelVal[i]; switch (rels[i].r_flags&DLMREL_TYPE) { case DLMREL_ABS32 : (*where)-=eh->e_value; (*where)+=(unsigned long)target; break; case DLMREL_REL32 : if (eh->e_flags&(DLMSYM_IMPORT|DLMSYM_COMMON)) { (*where)+=((unsigned long)target)-((unsigned long)dlm->Base); } break; } } dlm->cached_idx=symndx; dlm->cached_pos=i; } void _dlm_resolve_dlm_to_sym(char *name,TDlm *dlm,char *addr) { int i; for (i=0; iNumSym; i++) if (!strcmp(name,dlm->Strings+dlm->Symbols[i].e_name)) { _dlm_resolve_exact(dlm,i,addr); return; } } /* This function is used to resolve all matching imports to specified export symbol. */ void _dlm_resolve_to_sym(char *name) { TImportDlmLst *lst; void *symaddr; symaddr=_sym_find_export(name,0); if (!symaddr) symaddr=(void*)0xffffffff; lst=_sym_find_import(name); //printf("Resolve %s",name); //if (!lst) printf(" not requested."); while (lst) { _dlm_resolve_dlm_to_sym(name,lst->dlm,symaddr); //printf(" [%s]",lst->dlm->filename); lst=lst->next; } //printf("\n"); }