void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIEpilogStart() { auto &S = getStreamer(); WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc()); if (!CurFrame) return; InEpilogCFI = true; CurrentEpilog = S.EmitCFILabel(); }
int TableGenMain(char *argv0, TableGenMainFn *MainFn) { RecordKeeper Records; try { // Parse the input file. OwningPtr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { errs() << "Could not open input file '" << InputFilename << "': " << ec.message() <<"\n"; return 1; } MemoryBuffer *F = File.take(); // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(F, SMLoc()); // Record the location of the include directory so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); TGParser Parser(SrcMgr, Records); if (Parser.ParseFile()) return 1; std::string Error; tool_output_file Out(OutputFilename.c_str(), Error); if (!Error.empty()) { errs() << argv0 << ": error opening " << OutputFilename << ":" << Error << "\n"; return 1; } if (!DependFilename.empty()) if (int Ret = createDependencyFile(Parser, argv0)) return Ret; if (MainFn(Out.os(), Records)) return 1; // Declare success. Out.keep(); return 0; } catch (const TGError &Error) { PrintError(Error); } catch (const std::string &Error) { PrintError(Error); } catch (const char *Error) { PrintError(Error); } catch (...) { errs() << argv0 << ": Unknown unexpected exception occurred.\n"; } return 1; }
void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIEpilogEnd() { auto &S = getStreamer(); WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc()); if (!CurFrame) return; InEpilogCFI = false; MCSymbol *Label = S.EmitCFILabel(); WinEH::Instruction Inst = WinEH::Instruction(Win64EH::UOP_End, Label, -1, 0); CurFrame->EpilogMap[CurrentEpilog].push_back(Inst); CurrentEpilog = nullptr; }
// The functions below handle opcodes that can end up in either a prolog or // an epilog, but not both. void AArch64TargetWinCOFFStreamer::EmitARM64WinCFIPrologEnd() { auto &S = getStreamer(); WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc()); if (!CurFrame) return; MCSymbol *Label = S.EmitCFILabel(); CurFrame->PrologEnd = Label; WinEH::Instruction Inst = WinEH::Instruction(Win64EH::UOP_End, Label, -1, 0); auto it = CurFrame->Instructions.begin(); CurFrame->Instructions.insert(it, Inst); }
// Helper function to common out unwind code setup for those codes that can // belong to both prolog and epilog. // There are three types of Windows ARM64 SEH codes. They can // 1) take no operands: SEH_Nop, SEH_PrologEnd, SEH_EpilogStart, SEH_EpilogEnd // 2) take an offset: SEH_StackAlloc, SEH_SaveFPLR, SEH_SaveFPLR_X // 3) take a register and an offset/size: all others void AArch64TargetWinCOFFStreamer::EmitARM64WinUnwindCode(unsigned UnwindCode, int Reg, int Offset) { auto &S = getStreamer(); WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc()); if (!CurFrame) return; MCSymbol *Label = S.EmitCFILabel(); auto Inst = WinEH::Instruction(UnwindCode, Label, Reg, Offset); if (InEpilogCFI) CurFrame->EpilogMap[CurrentEpilog].push_back(Inst); else CurFrame->Instructions.push_back(Inst); }
void SSPParser::printError(StringRef Msg, bool PrintLoc) { StringRef BufferData = Buf->getBuffer(); const char *Data = BufferData.data(); unsigned Pos = CurPos; if (Pos > 0) { // The actual error will be one less than the *current* character --Pos; } if (Pos >= BufferData.size()) { Pos = BufferData.size()-1; } SMLoc Loc = SMLoc(); if (PrintLoc) { Loc = SMLoc::getFromPointer(Data+Pos); } SrcMgr.PrintMessage(Loc, SourceMgr::DK_Error, Msg); }
LLVM_ATTRIBUTE_NORETURN void MCWinCOFFStreamer::FatalError(const Twine &Msg) const { getContext().reportFatalError(SMLoc(), Msg); }
void MCWinCOFFStreamer::Error(const Twine &Msg) const { getContext().reportError(SMLoc(), Msg); }
int TableGenMain(char *argv0, TableGenAction &Action) { RecordKeeper Records; try { // Parse the input file. OwningPtr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { errs() << "Could not open input file '" << InputFilename << "': " << ec.message() <<"\n"; return 1; } MemoryBuffer *F = File.take(); // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(F, SMLoc()); // Record the location of the include directory so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); TGParser Parser(SrcMgr, Records); if (Parser.ParseFile()) return 1; std::string Error; tool_output_file Out(OutputFilename.c_str(), Error); if (!Error.empty()) { errs() << argv0 << ": error opening " << OutputFilename << ":" << Error << "\n"; return 1; } if (!DependFilename.empty()) { if (OutputFilename == "-") { errs() << argv0 << ": the option -d must be used together with -o\n"; return 1; } tool_output_file DepOut(DependFilename.c_str(), Error); if (!Error.empty()) { errs() << argv0 << ": error opening " << DependFilename << ":" << Error << "\n"; return 1; } DepOut.os() << OutputFilename << ":"; const std::vector<std::string> &Dependencies = Parser.getDependencies(); for (std::vector<std::string>::const_iterator I = Dependencies.begin(), E = Dependencies.end(); I != E; ++I) { DepOut.os() << " " << (*I); } DepOut.os() << "\n"; DepOut.keep(); } if (Action(Out.os(), Records)) return 1; // Declare success. Out.keep(); return 0; } catch (const TGError &Error) { PrintError(Error); } catch (const std::string &Error) { PrintError(Error); } catch (const char *Error) { PrintError(Error); } catch (...) { errs() << argv0 << ": Unknown unexpected exception occurred.\n"; } return 1; }
SSPParser::SSPParser(MemoryBuffer *Buffer, SourceMgr &SM) : SrcMgr(SM), Buf(Buffer), G(NULL) { SM.AddNewSourceBuffer(Buffer, SMLoc()); }
void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, uint64_t Size = 0, unsigned ByteAlignment = 0, SMLoc Loc = SMLoc()) override {}
int main(int ac, char **av) { SourceMgr SrcMgr; //LLVMInitializeX86TargetInfo(); llvm::InitializeAllTargetInfos(); //LLVMInitializeX86AsmParser(); llvm::InitializeAllTargetMCs(); //LLVMInitializeX86TargetMC(); llvm::InitializeAllAsmParsers(); //LLVMInitializeX86AsmParser(); llvm::InitializeAllDisassemblers(); //LLVMInitializeX86Disassembler(); // arg0: // llvm::Target encapsulating the "x86_64-apple-darwin14.5.0" information // see /lib/Support/Triple.cpp for the details //spec = llvm::sys::getDefaultTargetTriple(); //std::string machSpec = "x86_64-apple-windows"; // will produce a COFF //std::string machSpec = "x86_64-apple-darwin14.5.0"; // will produce a Mach-O std::string machSpec = "arm-none-none-eabi"; // //std::string machSpec = "x86_64-apple-darwin"; //std::string machSpec = "x86_64-thumb-linux-gnu"; //std::string machSpec = "x86_64-unknown-linux-gnu"; printf("machine spec: %s\n", machSpec.c_str()); machSpec = Triple::normalize(machSpec); printf("machine spec (normalized): %s\n", machSpec.c_str()); Triple TheTriple(machSpec); // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(/*arch*/"", TheTriple, Error); if (!TheTarget) { errs() << Error; return -1; } machSpec = TheTriple.getTriple(); printf("machine spec (returned): %s\n", machSpec.c_str()); printf("Target.getName(): %s\n", TheTarget->getName()); printf("Target.getShortDescription(): %s\n", TheTarget->getShortDescription()); /* from the target we get almost everything */ std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(machSpec)); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, machSpec)); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); /* describes target instruction set */ MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(machSpec, "", ""); /* subtarget instr set */ MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, machSpec, /* specific CPU */ ""); // arg0: // llvm::SourceMgr (Support/SourceMgr.h) that holds assembler source // has vector of llvm::SrcBuffer encaps (Support/MemoryBuffer.h) and vector of include dirs //std::string asmSrc = ".org 0x100, 0xAA\nfoo:\nxor %eax, %ebx\npush %rbp\njmp foo\nrdtsc\n"; //std::string asmSrc = ".text\n" "ldr pc, data_foo\n" "\n" "data_foo:\n" " .int 0x8\n" "\n" "loop:\n" "b loop\n"; //std::string asmSrc = ".text\n" "mov r2, r1\n"; std::string asmSrc = ".text\n" "ldr pc, data_foo\n" "data_foo:\n" ".int 0x8\n" "loop:\n" "b loop\n"; std::unique_ptr<MemoryBuffer> memBuf = MemoryBuffer::getMemBuffer(asmSrc); SrcMgr.AddNewSourceBuffer(std::move(memBuf), SMLoc()); // arg1: the machine code context MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); MOFI.InitMCObjectFileInfo(TheTriple, Reloc::Default, CodeModel::Default, Ctx); // this is the assembler interface // -methods per .s statements (emit bytes, handle directive, etc.) // -remembers current section // -implementations that write a .s, or .o in various formats // // 1. the output stream ... a formatted_raw_ostream wraps a raw_ostream to provide // tracking of line and column position for padding and shit // // but raw_ostream is abstract and is implemented by raw_fd_ostream, raw_string_ostream, etc. /* output stream: raw_svector_ostream is a raw_pwrite_stream is a raw_ostream since a SmallString is SmallVector (svector) we can use this and retrieve bytes later with its .data() method */ SmallString<1024> smallString; raw_svector_ostream rso(smallString); /* code emitter needs 1) instruction set info 2) register info */ MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCStreamer *as = TheTarget->createMCObjectStreamer( TheTriple, /* Triple */ Ctx, /* the MCContext */ *MAB, /* the AsmBackend, (fixups, relaxation, objs and elfs) */ rso, /* output stream raw_pwrite_stream */ CE, /* code emitter */ *STI, /* subtarget info */ true, /* relax all fixups */ true, /* incremental linker compatible */ false /* DWARFMustBeAtTheEnd */ ); std::string abi = "none"; MCTargetOptions toptions; toptions.MCUseDwarfDirectory = false; toptions.ABIName = abi; printf("trying to assemble, let's go..\n"); AssembleInput(TheTarget, SrcMgr, Ctx, *as, *MAI, *STI, *MCII, toptions); printf("done with AssembleInput()\n"); /* dump to file for debugging */ FILE *fp; fp = fopen("out.bin", "wb"); fwrite(smallString.data(), 1, smallString.size(), fp); fclose(fp); //int n = smallString.size(); int codeOffset=0, codeSize = 0; char *data = smallString.data(); if(*(uint32_t *)data == 0xFEEDFACF) { unsigned int idx = 0; idx += 0x20; /* skip mach_header_64 to first command */ idx += 0x48; /* advance into segment_command_64 to first section */ idx += 0x28; /* advance into section_64 to size */ uint64_t scn_size = *(uint64_t *)(data + idx); idx += 0x8; /* advance into section_64 to offset */ uint64_t scn_offset = *(uint64_t *)(data + idx); codeOffset = scn_offset; codeSize = scn_size; } else if(0==memcmp(data, "\x7F" "ELF\x01\x01\x01\x00", 8)) { /* assume four sections: NULL, .strtab, .text, .symtab */ uint32_t e_shoff = *(uint32_t *)(data + 0x20); uint32_t sh_offset = *(uint32_t *)(data + e_shoff + 2*0x28 + 0x10); /* second shdr */ uint32_t sh_size = *(uint32_t *)(data + e_shoff + 2*0x28 + 0x14); /* second shdr */ codeOffset = sh_offset; codeSize = sh_size; } else { printf("ERROR: couldn't identify type of output file\n"); } dump_bytes((unsigned char *)data + codeOffset, codeSize, 0); return 0; }