bool ObjIeeeAscii::LocalSymbol(const char *buffer, eParseType ParseType) { if (!file) ThrowSyntax(buffer, ParseType); int index = 0; ObjString name = GetSymbolName(buffer, &index); ObjSymbol *sym = factory->MakeLocalSymbol(name, index); PutSymbol(locals, index, sym); sym->SetSourceFile(GetFile(0)); return false; }
bool ObjIeeeAscii::TypeSpec(const char *buffer, eParseType ParseType) { if (!file) ThrowSyntax(buffer, ParseType); int pos = 2; char ch = buffer[pos++]; int index = ObjUtil::FromHex(buffer, &pos); if (buffer[pos++] != ',') ThrowSyntax(buffer, ParseType); switch (ch) { case 'A': case 'E': case 'X': case 'N': case 'I': { ObjSymbol *symbol = FindSymbol(ch, index); if (!symbol) ThrowSyntax(buffer, ParseType); if (buffer[pos++] != 'T') ThrowSyntax(buffer, ParseType); index = ObjUtil::FromHex(buffer, &pos); CheckTerm(buffer + pos); ObjType *type; /* won't get a 'special' type deriving type here */ if (index < ObjType::eReservedTop) type = factory->MakeType((ObjType::eType)index); else type = GetType(index); if (!type) ThrowSyntax(buffer, ParseType); symbol->SetBaseType(type); break; } case 'T': { DefineType(index, buffer, &pos); CheckTerm(buffer + pos); break; } default: ThrowSyntax(buffer, ParseType); break; } return false; }
bool ObjIeeeAscii::GetOffset(const char *buffer, eParseType ParseType) { if (!file) ThrowSyntax(buffer, ParseType); int pos =3 ; char ch = buffer[2]; int index = 0; if (ch != 'G') index = ObjUtil::FromHex(buffer, &pos); if (buffer[pos++] != ',') ThrowSyntax(buffer, ParseType); ObjExpression *exp = GetExpression(buffer, &pos); CheckTerm(buffer + pos); switch(ch) { case 'G': SetStartAddress(file, exp); break; case 'S': { ObjSection *sect = GetSection(index); if (!sect) ThrowSyntax(buffer, ParseType); sect->SetSize(exp); break; } case 'L': { ObjSection *sect = GetSection(index); if (!sect) ThrowSyntax(buffer, ParseType); sect->SetOffset(exp); break; } default: { ObjSymbol *sym = FindSymbol(ch, index); if (!sym) ThrowSyntax(buffer, ParseType); sym->SetOffset(exp); break; } } return false; }
bool ObjIeeeAscii::AutoSymbol(const char *buffer, eParseType ParseType) { if (!file) ThrowSyntax(buffer, ParseType); int index = 0; ObjString name = GetSymbolName(buffer, &index); ObjSymbol *sym = GetSymbol(autos,index); // autos can be forward declared in function type declarations if (sym) { sym->SetName(name); } else { sym = factory->MakeAutoSymbol(name, index); PutSymbol(autos, index, sym); } return false; }
ObjFile *CoffFile::ConvertToObject(std::string outputName, ObjFactory &factory) { ObjFile *fil = new ObjFile(outputName); std::vector<ObjSection *> objectSections; std::map<int, ObjSymbol *> externalMapping; // Create the sections; for (int i=0; i < header.NumberOfSections; i++) { if (!(sections[i].Characteristics & (IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_LNK_INFO)) && strnicmp(sections[i].Name, ".debug", 6)) { std::string sectname = GetSectionName(i); ObjSection * sect = factory.MakeSection(sectname); CoffSectionAux *aux = (CoffSectionAux *)& sectionSymbols[i][1]; sect->SetSize(new ObjExpression(aux->Length)); sect->SetAlignment(IMAGE_SCN_ALIGN(sections[i].Characteristics)); sect->SetQuals(GetSectionQualifiers(i)); fil->Add(sect); objectSections.push_back(sect); } else { objectSections.push_back(NULL); } } // dump comdefs for (int i=1; i < header.NumberOfSymbols; i+= symbols[i].NumberOfAuxSymbols + 1) { if (symbols[i].SectionNumber > header.NumberOfSections && symbols[i].StorageClass == IMAGE_SYM_CLASS_EXTERNAL && symbols[i].Value) { char *sname = symbols[i].Name; std::string symbolName; if (*(unsigned *)sname == 0) { symbolName = strings + *(unsigned *)(sname + 4); } else { symbolName = symbols[i].Name; if (symbolName.size() > 8) symbolName = symbolName.substr(0, 8); } symbolName = std::string("vsb") + symbolName; ObjSection * sect = factory.MakeSection(symbolName); sect->SetSize(new ObjExpression(symbols[i].Value)); sect->SetAlignment(8); sect->SetQuals(ObjSection::ram | ObjSection::max | ObjSection::virt); fil->Add(sect); objectSections.push_back(sect); } } // create the symbols for (int i=0; i < header.NumberOfSymbols; i+= symbols[i].NumberOfAuxSymbols + 1) { if (symbols[i].StorageClass == IMAGE_SYM_CLASS_EXTERNAL && symbols[i].SectionNumber <= header.NumberOfSections) { if (symbols[i].SectionNumber <= 0 || (((CoffSectionAux *)§ionSymbols[symbols[i].SectionNumber-1][1])->Selection <= 1)) { char *sname = symbols[i].Name; std::string symbolName; if (*(unsigned *)sname == 0) { symbolName = strings + *(unsigned *)(sname + 4); if (symbolName == "_WinMain@16") symbolName = "WinMain"; } else { symbolName = symbols[i].Name; if (symbolName.size() > 8) symbolName = symbolName.substr(0, 8); } if (symbols[i].SectionNumber == -1) { ObjSymbol *symbol = factory.MakePublicSymbol(symbolName); ObjExpression *exp = new ObjExpression(symbols[i].Value); symbol->SetOffset(exp); fil->Add(symbol); } else if (symbols[i].SectionNumber) { ObjSymbol *symbol = factory.MakePublicSymbol(symbolName); ObjExpression *exp = new ObjExpression(ObjExpression::eAdd, new ObjExpression(objectSections[symbols[i].SectionNumber-1]), new ObjExpression(symbols[i].Value)); symbol->SetOffset(exp); fil->Add(symbol); } else { ObjSymbol *symbol = factory.MakeExternalSymbol(symbolName); externalMapping[i] = symbol; fil->Add(symbol); } } } } // dump data to the sections for (int i=0; i < header.NumberOfSections; i++) { if (objectSections[i]) { int len = sections[i].SizeOfRawData; if (len) { inputFile->seekg(sections[i].PointerToRawData + libOffset); int relocCount = sections[i].NumberOfRelocations; CoffReloc * relocPointer = relocs[i]; if (relocCount == 0xffff && (sections[i].Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL)) { relocCount = relocPointer[0].VirtualAddress; relocPointer++; } unsigned offset = 0; inputFile->clear(); while (offset < sections[i].SizeOfRawData) { if (!relocCount) { ObjByte *data = new ObjByte[sections[i].SizeOfRawData-offset]; inputFile->read((char *)data, sections[i].SizeOfRawData-offset); if (inputFile->fail()) { return NULL; } ObjMemory *newMem = new ObjMemory(data, sections[i].SizeOfRawData-offset); objectSections[i]->Add(newMem); offset = sections[i].SizeOfRawData; } else { unsigned fixupOffset; int n = relocPointer->VirtualAddress - offset; if (n) { ObjByte *data = new ObjByte[n]; inputFile->read((char *)data, n); if (inputFile->fail()) { return NULL; } ObjMemory *newMem = new ObjMemory(data, n); objectSections[i]->Add(newMem); } inputFile->read((char *)&fixupOffset, sizeof(unsigned)); if (inputFile->fail()) { return NULL; } switch (relocPointer->Type) { ObjExpression *fixupExpr; case IMAGE_REL_I386_DIR32: case IMAGE_REL_I386_REL32: if (symbols[relocPointer->SymbolTableIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL) { if (symbols[relocPointer->SymbolTableIndex].SectionNumber == 0) { // external fixupExpr = new ObjExpression(externalMapping[relocPointer->SymbolTableIndex]); } else if (symbols[relocPointer->SymbolTableIndex].SectionNumber > header.NumberOfSections) { fixupExpr = new ObjExpression(ObjExpression::eAdd, new ObjExpression(objectSections[symbols[relocPointer->SymbolTableIndex].SectionNumber-1]), new ObjExpression(0)); } else { // public fixupExpr = new ObjExpression(ObjExpression::eAdd, new ObjExpression(objectSections[symbols[relocPointer->SymbolTableIndex].SectionNumber-1]), new ObjExpression(symbols[relocPointer->SymbolTableIndex].Value)); } } else { // local static fixupExpr = new ObjExpression(ObjExpression::eAdd, new ObjExpression(objectSections[symbols[relocPointer->SymbolTableIndex].SectionNumber-1]), new ObjExpression(symbols[relocPointer->SymbolTableIndex].Value)); } if (relocPointer->Type == IMAGE_REL_I386_REL32) { fixupExpr = new ObjExpression(ObjExpression::eAdd, fixupExpr, new ObjExpression(fixupOffset - 4)); fixupExpr = new ObjExpression(ObjExpression::eSub, fixupExpr, new ObjExpression(ObjExpression::ePC) ); } else if (fixupOffset) { fixupExpr = new ObjExpression(ObjExpression::eAdd, fixupExpr, new ObjExpression(fixupOffset)); } objectSections[i]->Add(new ObjMemory(fixupExpr, 4)); break; default: std::cout << "Invalid relocation" << std::endl; return NULL; } offset += n + 4; relocPointer++; relocCount--; } } } } } for (int i=1; i < header.NumberOfSymbols; i+= symbols[i].NumberOfAuxSymbols + 1) { if (symbols[i].SectionNumber > header.NumberOfSections && symbols[i].StorageClass == IMAGE_SYM_CLASS_EXTERNAL && symbols[i].Value) { int n = symbols[i].SectionNumber-1; ObjByte *data = new ObjByte[symbols[i].Value]; memset(data,0, symbols[i].Value); ObjMemory *newMem = new ObjMemory(data, symbols[i].Value); objectSections[n]->Add(newMem); } } return fil; }
void PEImportObject::Setup(ObjInt &endVa, ObjInt &endPhys) { if (virtual_addr == 0) { virtual_addr = endVa; } else { if (virtual_addr != endVa) Utils::fatal("Internal error"); } raw_addr = endPhys; std::map<ObjString, ObjSymbol *> externs; for (ObjFile::SymbolIterator it = file->ExternalBegin(); it != file->ExternalEnd(); ++it) { externs[(*it)->GetName()] = (*it); } std::map<std::string, Module *> modules; int nameSize = 0; int impNameSize = 0; int importCount = 0; int dllCount = 0; for (ObjFile::SymbolIterator it = file->ImportBegin(); it != file->ImportEnd(); ++it) { ObjImportSymbol *s = (ObjImportSymbol *)(*it); // uppercase the module name for NT... 98 doesn't need it but can accept it std::string name = s->GetDllName(); for (int i =0; i < name.size(); i++) name[i] = toupper(name[i]); s->SetDllName(name); if (externs.find((*it)->GetName()) != externs.end()) { Module *m = modules[s->GetDllName()]; int sz = s->GetDllName().size() + 1; if (sz & 1) sz ++; nameSize += sz; if (m == NULL) { modules[s->GetDllName()] = m = new Module; m->module = s->GetDllName(); dllCount++; } if (s->GetExternalName().size() == 0) { m->externalNames.push_back(s->GetName()); sz = s->GetName().size() + 1; } else { m->externalNames.push_back(s->GetExternalName()); sz = s->GetExternalName().size() + 1; } sz += 2; if (sz & 1) sz ++; impNameSize += sz; m->publicNames.push_back(s->GetName()); m->ordinals.push_back(s->GetByOrdinal() ? s->GetOrdinal() : 0xffffffff); importCount ++; } } data = new unsigned char[(modules.size() + 1) * sizeof(Dir) + ((nameSize + 3) & ~3) + (importCount + dllCount) * sizeof(Entry) * 2 + ((impNameSize + 3) & ~3)]; Dir *dirPos = (Dir *)data; char *namePos = (char *)data + sizeof(Dir) * (modules.size() + 1); Entry *lookupPos = (Entry *)((char *)namePos + ((nameSize + 3) & ~3)); char *hintPos = ((char *)lookupPos) + (importCount + dllCount) * sizeof(Entry); Entry *addressPos = (Entry *)(hintPos + ((impNameSize + 3) & ~3)); size = initSize = (unsigned)(((unsigned char *)addressPos) - data + (importCount + dllCount) * sizeof(Entry)); memset(data, 0, size); // note this does clean out some areas we deliberately are not initializing for (std::map<std::string, Module *>::iterator it = modules.begin(); it != modules.end(); ++it) { dirPos->time = 0; dirPos->version = 0; dirPos->dllName = (unsigned char *)namePos - data + virtual_addr; dirPos->thunkPos = ((unsigned char *)lookupPos) - data + virtual_addr; dirPos->thunkPos2 = ((unsigned char *)addressPos) - data + virtual_addr; dirPos++; strcpy(namePos, it->first.c_str()); int n = it->first.size() + 1; if (n & 1) n++; namePos += n; for (int i = 0; i < it->second->externalNames.size(); i++) { const std::string &str = it->second->externalNames[i]; if (str.size()) { lookupPos->ord_or_rva = (unsigned char *)hintPos - data + virtual_addr; addressPos->ord_or_rva = (unsigned char *) hintPos - data + virtual_addr; *(short *)hintPos = 0; //it->second->ordinals[i]; hintPos += 2; strcpy(hintPos, str.c_str()); int n = str.size() + 1; if (n & 1) n++; hintPos += n; } else { lookupPos->ord_or_rva = addressPos->ord_or_rva = it->second->ordinals[i] | IMPORT_BY_ORDINAL; } // next up we make a thunk that will get us from the rel calls genned by // the compiler to the import table; ObjSymbol *sym = externs[it->second->publicNames[i]]; int en = sym->GetIndex(); for (std::deque<PEObject *>::iterator it1 = objects.begin(); it1 != objects.end(); ++ it1) { ObjInt val; if ((val = (*it1)->SetThunk(en, ((unsigned char *)lookupPos) - data + virtual_addr + imageBase)) != -1) sym->SetOffset(new ObjExpression(val)); } lookupPos++; addressPos++; } // skip the null entry at the end of a module lookupPos++; addressPos++; } for (std::map<std::string, Module *>::iterator it = modules.begin(); it != modules.end(); ++it) { Module *p = it->second; delete p; } endVa = ObjectAlign(objectAlign, endVa + size); endPhys = ObjectAlign(fileAlign, endPhys + initSize); }