#include <stdio.h>
#include <stdlib.h>
#include "ld.h"
ldLibrary *ldAddLibrary(char *lib) {
int i = 0x0;
int x = 0x0;
int rel = 0x0;
uInt32 *reMap = 0x0;
char *newLoc = 0x0;
FILE *linkerFd = 0x0;
ldLibrary *tmpLib = 0x0;
tmpLib = (ldLibrary *)malloc(sizeof(ldLibrary));
if (tmpLib->output == 0x0) {
linkerFd = fopen(lib,"rb");
if (linkerFd == 0x0) {
printf("Cant Open Library: %s\n",lib);
exit(-1);
}
tmpLib->output = (char *)malloc((linkerFd->size+0x4000));
sprintf(tmpLib->name,lib);
}
if (tmpLib->linkerHeader == 0x0) {
fseek(linkerFd,0x0,0x0);
tmpLib->linkerHeader = (elfHeader *)malloc(sizeof(elfHeader));
fread(tmpLib->linkerHeader,sizeof(elfHeader),1,linkerFd);
}
if (tmpLib->linkerProgramHeader == 0x0) {
tmpLib->linkerProgramHeader = (elfProgramHeader *)malloc(sizeof(elfProgramHeader)*tmpLib->linkerHeader->ePhnum);
fseek(linkerFd,tmpLib->linkerHeader->ePhoff,0);
fread(tmpLib->linkerProgramHeader,sizeof(elfProgramHeader),tmpLib->linkerHeader->ePhnum,linkerFd);
for (i=0;i<tmpLib->linkerHeader->ePhnum;i++) {
switch (tmpLib->linkerProgramHeader[i].phType) {
case 1:
case 2:
newLoc = (char *)tmpLib->linkerProgramHeader[i].phVaddr + (uInt32)tmpLib->output;
fseek(linkerFd,tmpLib->linkerProgramHeader[i].phOffset,0);
fread(newLoc,tmpLib->linkerProgramHeader[i].phFilesz,1,linkerFd);
break;
default:
printf("Unhandled Header\n");
break;
}
}
}
if (tmpLib->linkerSectionHeader == 0x0) {
tmpLib->linkerSectionHeader = (elfSectionHeader *)malloc(sizeof(elfSectionHeader)*tmpLib->linkerHeader->eShnum);
fseek(linkerFd,tmpLib->linkerHeader->eShoff,0);
fread(tmpLib->linkerSectionHeader,sizeof(elfSectionHeader),tmpLib->linkerHeader->eShnum,linkerFd);
if (tmpLib->linkerShStr == 0x0) {
tmpLib->linkerShStr = (char *)malloc(tmpLib->linkerSectionHeader[tmpLib->linkerHeader->eShstrndx].shSize);
fseek(linkerFd,tmpLib->linkerSectionHeader[tmpLib->linkerHeader->eShstrndx].shOffset,0);
fread(tmpLib->linkerShStr,tmpLib->linkerSectionHeader[tmpLib->linkerHeader->eShstrndx].shSize,1,linkerFd);
}
for (i=0x0;i<tmpLib->linkerHeader->eShnum;i++) {
switch (tmpLib->linkerSectionHeader[i].shType) {
case 3:
if (!strcmp((tmpLib->linkerShStr + tmpLib->linkerSectionHeader[i].shName),".dynstr")) {
if (tmpLib->linkerDynStr == 0x0) {
tmpLib->linkerDynStr = (char *)malloc(tmpLib->linkerSectionHeader[i].shSize);
fseek(linkerFd,tmpLib->linkerSectionHeader[i].shOffset,0);
fread(tmpLib->linkerDynStr,tmpLib->linkerSectionHeader[i].shSize,1,linkerFd);
}
}
break;
case 9:
rel = i;
break;
case 11:
if (tmpLib->linkerRelSymTab == 0x0) {
tmpLib->linkerRelSymTab = (elfDynSym *)malloc(tmpLib->linkerSectionHeader[i].shSize);
fseek(linkerFd,tmpLib->linkerSectionHeader[i].shOffset,0);
fread(tmpLib->linkerRelSymTab,tmpLib->linkerSectionHeader[i].shSize,1,linkerFd);
tmpLib->sym = i;
}
break;
}
}
}
if (tmpLib->linkerElfRel == 0x0) {
tmpLib->linkerElfRel = (elfPltInfo *)malloc(tmpLib->linkerSectionHeader[rel].shSize);
fseek(linkerFd,tmpLib->linkerSectionHeader[rel].shOffset,0x0);
fread(tmpLib->linkerElfRel,tmpLib->linkerSectionHeader[rel].shSize,1,linkerFd);
for (i=0x0;i<tmpLib->linkerSectionHeader[rel].shSize/sizeof(elfPltInfo);i++) {
x = ELF32_R_SYM(tmpLib->linkerElfRel[i].pltInfo);
reMap = (uInt32 *)((uInt32)tmpLib->output + tmpLib->linkerElfRel[i].pltOffset);
switch (ELF32_R_TYPE(tmpLib->linkerElfRel[i].pltInfo)) {
case R_386_32:
*reMap += ((uInt32)tmpLib->output + tmpLib->linkerRelSymTab[x].dynValue);
break;
case R_386_PC32:
*reMap += ((uInt32)tmpLib->output + tmpLib->linkerRelSymTab[x].dynValue) - (uInt32)reMap;
break;
case R_386_RELATIVE:
*reMap += (uInt32)tmpLib->output;
break;
default:
//printf("[0x%X][0x%X](%i)[%s]\n",elfRel[i].pltOffset,elfRel[i].pltInfo,x,elfGetRelType(ELF32_R_TYPE(elfRel[i].pltInfo)));
//printf("relTab [%s][0x%X][0x%X]\n",dynStr + relSymTab[x].dynName,relSymTab[x].dynValue,relSymTab[x].dynName);
printf("Unhandled sym\n");
break;
}
}
}
libs->prev = tmpLib;
tmpLib->prev = 0x0;
tmpLib->next = libs;
libs = tmpLib;
return(tmpLib);
}