#include <stdio.h>
#include <stdlib.h>
#include "ld.h"
ldLibrary *ldAddLibrary(const char *lib) {
int i = 0x0;
int x = 0x0;
int rel = 0x0;
uInt32 *reMap = 0x0;
char *newLoc = 0x0;
FILE *linkerFd = 0x0;
char tmpFile[1024];
ldLibrary *tmpLib = 0x0;
if ((tmpLib = (ldLibrary *)malloc(sizeof(ldLibrary))) == 0x0) {
printf("malloc failed: tmpLib\n");
exit(0x1);
}
if (tmpLib->output == 0x0) {
/* Hack because we have no ld path set */
sprintf(tmpFile,"sys:/lib/%s",lib);
linkerFd = fopen(tmpFile,"rb");
if (linkerFd->fd == 0x0) {
printf("Could not open library: %s\n",lib);
exit(-1);
}
//if ((tmpLib->output = (char *)malloc((linkerFd->size+0x4000))) == 0x0) {
//if ((tmpLib->output = (char *)malloc(0x111000)) == 0x0) {
if ((tmpLib->output = (char *)getPage((0x111000/0x1000),2)) == 0x0) {
printf("malloc failed: tmpLib->output\n");
exit(0x1);
}
sprintf(tmpLib->name,lib);
}
printf("Base: {0x%X}\n",tmpLib->output);
if (tmpLib->linkerHeader == 0x0) {
fseek(linkerFd,0x0,0x0);
if ((tmpLib->linkerHeader = (elfHeader *)malloc(sizeof(elfHeader))) == 0x0) {
printf("malloc failed: tmpLib->linkerHeader\n");
exit(0x1);
}
fread(tmpLib->linkerHeader,sizeof(elfHeader),1,linkerFd);
}
if (tmpLib->linkerProgramHeader == 0x0) {
if ((tmpLib->linkerProgramHeader = (elfProgramHeader *)malloc(sizeof(elfProgramHeader)*tmpLib->linkerHeader->ePhnum)) == 0x0) {
printf("malloc failed: tmpLib->linkerProgramHeader\n");
exit(0x1);
}
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 PT_LOAD:
case PT_DYNAMIC:
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;
case PT_GNU_STACK:
/* Tells us if the stack should be executable. Failsafe to
executable until we add checking */
printf("NOT DEF1\n");
break;
case PT_PAX_FLAGS:
/* Not sure... */
printf("NOT DEF2\n");
break;
default:
printf("Unhandled Header (ld.so) : %08x\n", tmpLib->linkerProgramHeader[i].phType);
break;
}
}
}
if (tmpLib->linkerSectionHeader == 0x0) {
if ((tmpLib->linkerSectionHeader = (elfSectionHeader *)malloc(sizeof(elfSectionHeader)*tmpLib->linkerHeader->eShnum)) == 0x0) {
printf("malloc failed: tmpLib->linkerSectionHeader\n");
exit(0x1);
}
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) {
if ((tmpLib->linkerDynStr = (char *)malloc(tmpLib->linkerSectionHeader[i].shSize)) == 0x0) {
printf("malloc failed: tmpLib->linkerDynStr\n");
exit(0x1);
}
fseek(linkerFd,tmpLib->linkerSectionHeader[i].shOffset,0);
fread(tmpLib->linkerDynStr,tmpLib->linkerSectionHeader[i].shSize,1,linkerFd);
}
}
break;
case 9:
if ((tmpLib->linkerElfRel = (elfPltInfo *)malloc(tmpLib->linkerSectionHeader[i].shSize)) == 0x0) {
printf("malloc failed: tmpLib->linkerElfRel\n");
exit(0x1);
}
fseek(linkerFd,tmpLib->linkerSectionHeader[i].shOffset,0x0);
fread(tmpLib->linkerElfRel,tmpLib->linkerSectionHeader[i].shSize,1,linkerFd);
for (x=0x0;x<tmpLib->linkerSectionHeader[i].shSize/sizeof(elfPltInfo);x++) {
rel = ELF32_R_SYM(tmpLib->linkerElfRel[x].pltInfo);
reMap = (uInt32 *)((uInt32)tmpLib->output + tmpLib->linkerElfRel[x].pltOffset);
switch (ELF32_R_TYPE(tmpLib->linkerElfRel[x].pltInfo)) {
case R_386_32:
*reMap += ((uInt32)tmpLib->output + tmpLib->linkerRelSymTab[rel].dynValue);
//printf("[0x%X]",*reMap);
break;
case R_386_PC32:
*reMap += ((uInt32)tmpLib->output + tmpLib->linkerRelSymTab[rel].dynValue) - (uInt32)reMap;
break;
case R_386_RELATIVE:
*reMap += (uInt32)tmpLib->output;
break;
case R_386_JMP_SLOT:
*reMap += (uInt32)tmpLib->output;
break;
case R_386_GLOB_DAT:
*reMap = ((uInt32)tmpLib->output + tmpLib->linkerRelSymTab[rel].dynValue);
break;
default:
printf("Unhandled sym: [0x%X]\n", ELF32_R_TYPE(tmpLib->linkerElfRel[x].pltInfo));
while (1);
break;
}
}
free(tmpLib->linkerElfRel);
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 (libs != 0x0)
libs->prev = tmpLib;
tmpLib->prev = 0x0;
tmpLib->next = libs;
libs = tmpLib;
if (linkerFd) {
fclose(linkerFd);
}
return(tmpLib);
}