/// <summary> /// Checks and sanitizes assembly and encoding /// </summary> /// <param name="check"></param> /// <param name="encoding"></param> /// <returns></returns> private bool Parse_CheckEncoding(string check, string encoding, CommentSubType checkSubType) { //interestingly, there's at least 1 broken LLVM test //arm64-aliases.S -> ; CHECK: tlbi alle1 ; encoding: [0x9f,0x87,0x0c,0xd5 //someone forgot to add a closing "]" if (!encoding.StartsWith("[") /* || !encoding.EndsWith("]")*/) { throw new InvalidDataException($"Invalid syntax for encoding => '{encoding}'"); } if (!encoding.EndsWith("]")) { //encodingTypoPresent = true; } encoding = encoding.Substring(1, encoding.Length - 2); if (encoding == string.Empty) { return(false); } if (encoding.Contains("0b") || encoding.Contains("'")) { return(false); } this.Check = check; this.Encoding = encoding; return(true); }
private static void PrintX86UnitTest(string assembly, string encoding, CommentSubType modifier) { string template = @" [Test] public void Dis_{0}() {{ var instr = Disassemble64({1}); Assert.AreEqual(""{2}"", instr.ToString()); }}" ; string testName = ConvertTestName(assembly); string unitTest = string.Format(template, testName, encoding, assembly); WriteUnitTest( testName, Architecture.x86, unitTest ); }
private static void PrintMipsUnitTest(string assembly, string encoding, CommentSubType modifier) { string template = @" [Test] public void MipsDis_{0}() {{ AssertCode(""{1}"", 0x{2:X8}); }}" ; string testName = ConvertTestName(assembly); string unitTest = string.Format(template, testName, assembly, ToValueBe(encoding) ); WriteUnitTest( testName, Architecture.Mips, unitTest ); }
private static void PrintArmUnitTest(string assembly, string encoding, CommentSubType modifier) { string template = @" [Test] public void ArmDasm_{0}() {{ var instr = Disassemble32(0x{2:X8}); Assert.AreEqual(""{1}"", instr.ToString()); }}" ; string testName = ConvertTestName(assembly); string unitTest = string.Format(template, testName, assembly, ToValueBe(encoding) ); WriteUnitTest( testName, Architecture.Arm, unitTest ); }
private static void PrintAArch64UnitTest(string assembly, string encoding, CommentSubType modifier) { StringBuilder sb = new StringBuilder(); UInt32 valueBe = ToValueBe(encoding); UInt32 valueLe = ToValueLe(encoding); string template = @" [Test] // Little-endian: {0:X8} public void AArch64Dis_0x{1:X8}() {{ Given_Instruction(0x{1:X8}); Expect_Code(""{2}""); }}" ; string unitTest = string.Format(template, valueLe, valueBe, assembly); WriteUnitTest( Convert.ToString(valueBe), Architecture.AArch64, unitTest ); }
private static void PrintPowerPcUnitTest(string assembly, string encoding, CommentSubType modifier) { string template = @" [Test] public void PPCDis_{0}() {{ var instr = DisassembleWord(0x{2:X8}); Assert.AreEqual(""{1}"", instr.ToString()); }}" ; string testName = string.Format("{0:X8}", ToValueBe(encoding)); switch (modifier) { case CommentSubType.PPCServer: testName += "_server"; break; case CommentSubType.PPCEmbedded: testName += "_embedded"; break; case CommentSubType.PPCBigEndian: testName += "_be"; break; case CommentSubType.PPCLittleEndian: testName += "_le"; break; } string unitTest = string.Format(template, testName, assembly, ToValueBe(encoding) ); WriteUnitTest( testName, Architecture.PowerPc, unitTest ); }
private static void PrintSparcUnitTest(string assembly, string encoding, CommentSubType modifier) { string template = @" [Test] public void SparcDis_{0}() {{ AssertInstruction(0x{2:X8}, ""{1}""); }}" ; string testName = ConvertTestName(assembly); if (modifier == CommentSubType.SparcNoCasa) { testName += "_no_casa"; } string unitTest = string.Format(template, testName, assembly, ToValueBe(encoding) ); WriteUnitTest( testName, Architecture.Sparc, unitTest ); }
/// <summary> /// Detects the type of comments for a given comment line /// </summary> /// <param name="line"></param> /// <param name="type"></param> /// <returns>The remaining part of the comment, without the leading tag (e.g CHECK)</returns> private string DetectCommment( string line, out CommentType type, out CommentSubType subType ) { string[] parts = line.Split(':'); subType = CommentSubType.Invalid; if (parts.Length <= 1) { type = CommentType.Invalid; return(line); } string commentType = parts[0]; line = string.Join(":", parts.Skip(1)).Trim(); switch (commentType) { case "RUN": type = CommentType.Run; break; case "CHECK": type = CommentType.Check; break; case "CHECK-SHA": type = CommentType.Check; subType = CommentSubType.Sha; break; case "SERVER": type = CommentType.Check; subType = CommentSubType.PPCServer; break; case "EMBEDDED": type = CommentType.Check; subType = CommentSubType.PPCEmbedded; break; case "CHECK-BE": type = CommentType.Check; subType = CommentSubType.PPCBigEndian; break; case "CHECK-LE": type = CommentType.Check; subType = CommentSubType.PPCLittleEndian; break; case "INTEL": type = CommentType.Check; subType = CommentSubType.IntelEncoding; break; case "CHECK_NO_CASA": type = CommentType.Check; subType = CommentSubType.SparcNoCasa; break; case "encoding": type = CommentType.Encoding; break; default: type = CommentType.Invalid; break; } return(line); }
/// <summary> /// Handles a comment line /// </summary> /// <param name="currentLine"></param> /// <returns></returns> private bool HandleComment(string currentLine, out CommentSubType modifier) { /* * We want to have the following layout * lines[0] -> CHECK * lines[1] -> CHECK encoding * So if the comment style is OneLine, we split the line * If the comment style is TwoLines, we read and process the next line */ List <string> lines = new List <string>() { currentLine }; modifier = CommentSubType.Invalid; string commentData = DetectCommment(RemoveCommentToken(currentLine), out CommentType commentType, out CommentSubType commentSubType); if (!runVerified) { if (commentType == CommentType.Run) { if (!commentData.Contains("-show-encoding")) { stopHandling = true; return(false); } } runVerified = true; } commentType = CommentType.Invalid; string line0, line1; LineType line1Type; CommentType commentType0, commentType1; CommentSubType commentSubType0, commentSubType1; CommentSubType checkSubType = CommentSubType.Invalid; switch (fileCommentStyle) { case CommentStyle.Invalid: return(false); case CommentStyle.OneLine: line0 = lines[0]; string[] parts = line0.Split(new string[] { fileCommentToken }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 2) { return(false); } string check = parts[0].Trim(); string encoding = parts[1].Trim(); check = DetectCommment(check, out CommentType checkType, out checkSubType); encoding = DetectCommment(encoding, out CommentType encodingType, out CommentSubType encodingSubType); if (checkType != CommentType.Check || encodingType != CommentType.Encoding) { return(false); } lines[0] = check; lines.Add(encoding); break; case CommentStyle.TwoLines: line1 = ReadLine(out line1Type); if (line1Type != LineType.Comment) { return(false); } line1 = DetectCommment(RemoveCommentToken(line1), out commentType1, out commentSubType1); if (commentType1 != CommentType.Check) { return(false); } line1 = DetectCommment(line1, out commentType1, out commentSubType1); if (commentType1 != CommentType.Encoding) { return(false); } line0 = lines[0]; line0 = DetectCommment(RemoveCommentToken(line0), out commentType0, out commentSubType0); switch (commentType0) { case CommentType.Check: break; default: throw new InvalidDataException("This was supposed to be a CHECK comment"); } checkSubType = commentSubType0; lines[0] = line0; lines.Add(line1); break; case CommentStyle.TwoLinesAsm: line1 = ReadLine(out line1Type); if (line1Type != LineType.Assembly) { return(false); } line0 = lines[0]; lines[0] = DetectCommment(RemoveCommentToken(line0), out commentType0, out commentSubType0); if (commentType0 != CommentType.Check) { return(false); } checkSubType = commentSubType0; lines.Add(line1); // invert string tmp = lines[0]; lines[0] = lines[1]; lines[1] = tmp; lines[1] = DetectCommment(lines[1], out commentType1, out commentSubType1); if (commentType1 != CommentType.Encoding) { return(false); } break; } /* * Console.WriteLine($"Check => {lines[0]}"); * Console.WriteLine($"Encoding => {lines[1]}"); */ modifier = checkSubType; return(Parse_CheckEncoding(lines[0], lines[1], checkSubType)); }