void CArmInstruction::writeTempData(TempData& tempData) { char OpcodeName[32]; char str[256]; FormatOpcode(OpcodeName,Opcode.name); int pos = sprintf(str," %s",OpcodeName); while (pos < 11) str[pos++] = ' '; str[pos] = 0; FormatInstruction(Opcode.mask,&str[pos]); tempData.writeLine(RamPos,convertUtf8ToWString(str)); }
std::wstring Logger::formatError(ErrorType type, const std::wstring& text) { std::wstring fileName = convertUtf8ToWString(Global.FileInfo.FileList.GetEntry(Global.FileInfo.FileNum)); switch (type) { case Warning: return formatString(L"%s(%d) warning: %s",fileName.c_str(),Global.FileInfo.LineNumber,text.c_str()); case Error: return formatString(L"%s(%d) error: %s",fileName.c_str(),Global.FileInfo.LineNumber,text.c_str()); case FatalError: return formatString(L"%s(%d) fatal error: %s",fileName.c_str(),Global.FileInfo.LineNumber,text.c_str()); case Notice: return formatString(L"%s(%d) notice: %s",fileName.c_str(),Global.FileInfo.LineNumber,text.c_str()); } return L""; }
CThumbInstruction* ArmParser::parseThumbOpcode(Parser& parser) { const Token &token = parser.nextToken(); if (token.type != TokenType::Identifier) return nullptr; ThumbOpcodeVariables vars; bool paramFail = false; const std::wstring stringValue = token.getStringValue(); for (int z = 0; ThumbOpcodes[z].name != NULL; z++) { if ((ThumbOpcodes[z].flags & THUMB_ARM9) && !Arm.isArm9()) continue; // todo: save as wchar std::wstring name = convertUtf8ToWString(ThumbOpcodes[z].name); if (stringValue == name) { TokenizerPosition tokenPos = parser.getTokenizer()->getPosition(); if (parseThumbParameters(parser,ThumbOpcodes[z],vars) == true) { // success, return opcode return new CThumbInstruction(ThumbOpcodes[z],vars); } parser.getTokenizer()->setPosition(tokenPos); paramFail = true; } } if (paramFail == true) parser.printError(token,L"THUMB parameter failure"); else parser.printError(token,L"Invalid THUMB opcode"); return nullptr; }
int main(int argc, char* argv[]) { // convert input to wstring std::vector<std::wstring> wideStrings; for (int i = 0; i < argc; i++) { std::wstring str = convertUtf8ToWString(argv[i]); wideStrings.push_back(str); } // create argv replacement wchar_t** wargv = new wchar_t*[argc]; for (int i = 0; i < argc; i++) { wargv[i] = (wchar_t*) wideStrings[i].c_str(); } int result = wmain(argc,wargv); delete[] wargv; return result; }
bool CThumbInstruction::Validate() { CStringList List; RamPos = g_fileManager->getVirtualAddress(); if (RamPos & 1) { Logger::queueError(Logger::Warning,L"Opcode not halfword aligned"); } if (Opcode.flags & THUMB_DS) { Vars.rs = Vars.rd; } if (Opcode.flags & THUMB_IMMEDIATE) { if (ParsePostfix(Vars.ImmediateExpression,&List,Vars.Immediate) == false) { if (List.GetCount() == 0) { Logger::queueError(Logger::Error,L"Invalid expression"); } else { for (int l = 0; l < List.GetCount(); l++) { Logger::queueError(Logger::Error,convertUtf8ToWString(List.GetEntry(l))); } } return false; } Vars.OriginalImmediate = Vars.Immediate; if (Opcode.flags & THUMB_BRANCH) { if (Opcode.flags & THUMB_EXCHANGE) { if (Vars.Immediate & 3) { Logger::queueError(Logger::Error,L"Branch target must be word aligned"); return false; } } else { if (Vars.Immediate & 1) { Logger::queueError(Logger::Error,L"Branch target must be halfword aligned"); return false; } } int num = (Vars.Immediate-RamPos-4); if (num >= (1 << Vars.ImmediateBitLen) || num < (0-(1 << Vars.ImmediateBitLen))) { Logger::queueError(Logger::Error,L"Branch target %08X out of range",Vars.Immediate); return false; } Vars.Immediate = num >> 1; if (Opcode.flags & THUMB_EXCHANGE) { Vars.Immediate += Vars.Immediate&1; } } else if (Opcode.flags & THUMB_WORD) { if (Vars.Immediate & 3) // not allowed { Logger::queueError(Logger::Error,L"Immediate value must be a multiple of 4"); return false; } Vars.Immediate >>= 2; } else if (Opcode.flags & THUMB_HALFWORD)
bool ElfRelocator::init(const std::wstring& inputName) { relocator = Arch->getElfRelocator(); if (relocator == NULL) { Logger::printError(Logger::Error,L"Object importing not supported for this architecture"); return false; } auto inputFiles = loadArArchive(inputName); if (inputFiles.size() == 0) { Logger::printError(Logger::Error,L"Could not load library"); return false; } for (ArFileEntry& entry: inputFiles) { ElfRelocatorFile file; ElfFile* elf = new ElfFile(); if (elf->load(entry.data,false) == false) { Logger::printError(Logger::Error,L"Could not load object file %s",entry.name); return false; } if (elf->getType() != 1) { Logger::printError(Logger::Error,L"Unexpected ELF type %d in object file %s",elf->getType(),entry.name); return false; } if (elf->getSegmentCount() != 0) { Logger::printError(Logger::Error,L"Unexpected segment count %d in object file %s",elf->getSegmentCount(),entry.name); return false; } // load all relevant sections of this file for (size_t s = 0; s < elf->getSegmentlessSectionCount(); s++) { ElfSection* sec = elf->getSegmentlessSection(s); if (!(sec->getFlags() & SHF_ALLOC)) continue; if (sec->getType() == SHT_PROGBITS || sec->getType() == SHT_NOBITS || sec->getType() == SHT_INIT_ARRAY) { ElfRelocatorSection sectionEntry; sectionEntry.section = sec; sectionEntry.index = s; sectionEntry.relSection = NULL; sectionEntry.label = NULL; // search relocation section for (size_t k = 0; k < elf->getSegmentlessSectionCount(); k++) { ElfSection* relSection = elf->getSegmentlessSection(k); if (relSection->getType() != SHT_REL) continue; if (relSection->getInfo() != s) continue; // got it sectionEntry.relSection = relSection; break; } // keep track of constructor sections if (sec->getName() == ".ctors" || sec->getName() == ".init_array") { ElfRelocatorCtor ctor; ctor.symbolName = Global.symbolTable.getUniqueLabelName(); ctor.size = sec->getSize(); sectionEntry.label = Global.symbolTable.getLabel(ctor.symbolName,-1,-1); sectionEntry.label->setDefined(true); ctors.push_back(ctor); } file.sections.push_back(sectionEntry); } } // init exportable symbols for (int i = 0; i < elf->getSymbolCount(); i++) { Elf32_Sym symbol; bool found = elf->getSymbol(symbol, i); if (ELF32_ST_BIND(symbol.st_info) == STB_GLOBAL && symbol.st_shndx != 0) { ElfRelocatorSymbol symEntry; symEntry.type = ELF32_ST_TYPE(symbol.st_info); symEntry.name = convertUtf8ToWString(elf->getStrTableString(symbol.st_name)); symEntry.relativeAddress = symbol.st_value; symEntry.section = symbol.st_shndx; symEntry.size = symbol.st_size; symEntry.label = NULL; file.symbols.push_back(symEntry); } } file.elf = elf; file.name = entry.name; files.push_back(file); } return true; }
std::vector<ArFileEntry> loadArArchive(const std::wstring& inputName) { ByteArray input = ByteArray::fromFile(inputName); std::vector<ArFileEntry> result; if (memcmp(input.data(),"!<arch>\n",8) != 0) { if (memcmp(input.data(),"\x7F""ELF",4) != 0) return result; ArFileEntry entry; entry.name = getFileNameFromPath(inputName); entry.data = input; result.push_back(entry); return result; } size_t pos = 8; while (pos < input.size()) { ArFileHeader* header = (ArFileHeader*) input.data(pos); pos += sizeof(ArFileHeader); // get file size int size = 0; for (int i = 0; i < 10; i++) { if (header->fileSize[i] == ' ') break; size = size*10; size += (header->fileSize[i]-'0'); } // only ELF files are actually interesting if (memcmp(input.data(pos),"\x7F""ELF",4) == 0) { // get file name char fileName[17]; fileName[16] = 0; for (int i = 0; i < 16; i++) { if (header->fileName[i] == ' ') { // remove trailing slashes of file names if (i > 0 && fileName[i-1] == '/') i--; fileName[i] = 0; break;; } fileName[i] = header->fileName[i]; } ArFileEntry entry; entry.name = convertUtf8ToWString(fileName); entry.data = input.mid(pos,size); result.push_back(entry); } pos += size; if (pos % 2) pos++; } return result; }