//							RELOC.CPP

#include <windows.h>

#include "reloc.h"
#include "pefiles.h"
#include "textout.h"
#include "dasm.h"

reloc::reloc()
{ int i;
  for(i=0;i<16;i++)rtable[i]=0;
  //setup head and tail of list.
  //  - simplifies other code a lot
  fixes=new struct fixups;
  fixes->next=new struct fixups;
  fixes->next->next=NULL;
  fixes->addr=0;
  fixes->next->addr=0xffffffff;
  lastfix=fixes;
}

reloc::~reloc()
{ struct fixups *nxt;
  while(fixes!=NULL)
  { nxt=fixes;
	 fixes=fixes->next;
	 delete nxt;
  }
}

void reloc::buildrelocdata(void)
{ struct codedata *rel;
  unsigned char *reldata;
  struct relocheader *rh;
  short int *rdata;
  unsigned long numrelocs,rtype,imagebase;
  rel=pe_exe.getrelocdata();
  imagebase=pe_exe.getimagebase();
  if(rel==NULL)return;
  reldata=rel->dataptr;
  rh=(struct relocheader *)reldata;
  while(rh->rva)
  { rdata=(short int *)(reldata+sizeof(struct relocheader));
	 numrelocs=(rh->len-sizeof(struct relocheader))/2;
	 while((numrelocs)&&(*rdata))
	 { rtype=((*rdata)>>12);
		rtable[rtype]++;
		if(rtype==3)addrelocaddr(((unsigned long)(*rdata)&0x0fff)+rh->rva+imagebase);
		rdata++;
		numrelocs--;
	 }
	 reldata+=rh->len;
	 rh=(struct relocheader *)reldata;
  }
  PrintBuff("Reloc types");
  PrintBuff("===========");
  for(rtype=0;rtype<8;rtype++)
	 PrintBuff("  Reloc Type : %d  Number : %lu",rtype,rtable[rtype]);
  PrintBuff("");
}

void reloc::addrelocaddr(unsigned long addr)
{ struct fixups *addit,*prev;
  if(lastfix->addr<addr)addit=lastfix;
  else addit=fixes;
  while(addit->addr<addr)
  { prev=addit;
	 addit=addit->next;
  }
  prev->next=new struct fixups;
  prev->next->next=addit;
  addit=prev->next;
  addit->addr=addr;
  lastfix=addit;
}

BOOL reloc::isreloc(unsigned long addr)
{ struct fixups *fptr;
  fptr=fixes;
  if(lastfix->addr<=addr)
	 fptr=lastfix;
  while(fptr->addr<addr)
  { fptr=fptr->next;
  }
  if(fptr->addr==addr)
  { lastfix=fptr;
	 return TRUE;
  }
  return FALSE;
}
