#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; 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: tmpLib->linkerElfRel = (elfPltInfo *)malloc(tmpLib->linkerSectionHeader[i].shSize); 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); 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; default: printf("Unhandled sym\n"); 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; } } } libs->prev = tmpLib; tmpLib->prev = 0x0; tmpLib->next = libs; libs = tmpLib; if (linkerFd) { fclose(linkerFd); } return(tmpLib); }