public void Run() { foreach (var file in Files) { using var stream = new FileStream(file, FileMode.Open, FileAccess.Read); if (ArArchiveFile.IsAr(stream)) { var options = new ArArchiveFileReaderOptions(ArArchiveKind.GNU); var archive = ArArchiveFile.Read(stream, options); foreach (var objFile in archive.Files) { if (objFile is ArElfFile elfFile) { ProcessElf(objFile.Name, elfFile.ElfObjectFile); } } } else if (ElfObjectFile.IsElf(stream)) { var elfObjectFile = ElfObjectFile.Read(stream, new ElfReaderOptions() { ReadOnly = true }); ProcessElf(Path.GetFileName(file), elfObjectFile); } } }
public void CheckLibraryWithELF() { var cppName = "helloworld"; var cppObj = $"{cppName}.o"; var cppLib = $"lib{cppName}.a"; File.Delete(cppObj); File.Delete(cppLib); LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -c -o {cppObj}"); LinuxUtil.RunLinuxExe("ar", $"rcs {cppLib} {cppObj}"); using (var stream = new FileStream(cppLib, FileMode.Open, FileAccess.Read)) { Assert.True(ArArchiveFile.IsAr(stream)); var arFile = ArArchiveFile.Read(stream, new ArArchiveFileReaderOptions(ArArchiveKind.GNU) { ProcessObjectFiles = false }); var elfFile = arFile.Files.FirstOrDefault(x => x.Name == cppObj); Assert.NotNull(elfFile, $"Unable to find {cppObj} file in {cppLib}"); Assert.NotNull(arFile.SymbolTable, $"Unable to find symbol table in {cppLib}"); Assert.AreEqual(1, arFile.SymbolTable.Symbols.Count, "Invalid number of symbols in Symbol table"); Assert.AreEqual("main", arFile.SymbolTable.Symbols[0].Name, "Invalid symbol found"); Assert.AreEqual(elfFile, arFile.SymbolTable.Symbols[0].File, "Invalid symbol to file found"); var outStream = new MemoryStream(); arFile.Write(outStream); var newArray = outStream.ToArray(); outStream.Position = 0; var cppLibCopy = $"lib{cppName}_copy.a"; using (var copyStream = new FileStream(cppLibCopy, FileMode.Create, FileAccess.Write)) { outStream.CopyTo(copyStream); } var originalStream = new MemoryStream(); stream.Position = 0; stream.CopyTo(originalStream); var originalArray = originalStream.ToArray(); Assert.AreEqual(originalArray, newArray, $"Non binary matching between file {cppLib} and {cppLibCopy}"); } }
public void CheckCreateArLibrary() { var libName = "libcustom.a"; var file = new ArArchiveFile(); using (var stream = new FileStream(libName, FileMode.Create, FileAccess.Write)) { var symbolTable = new ArSymbolTable(); file.AddFile(symbolTable); file.AddFile(new ArBinaryFile() { Name = "file2.txt", OwnerId = 0666, Stream = new MemoryStream(Encoding.UTF8.GetBytes("this is file")) }); file.AddFile(new ArBinaryFile() { Name = "file3.txt", OwnerId = 0777, GroupId = 0744, Stream = new MemoryStream(Encoding.UTF8.GetBytes("this is file3")) }); file.AddFile(new ArBinaryFile() { Name = "file4.txt", OwnerId = 0777, GroupId = 0744, Stream = new MemoryStream(Encoding.UTF8.GetBytes("this is file4")) }); file.AddFile(new ArBinaryFile() { Name = "file5.txt", OwnerId = 0706, GroupId = 0705, FileMode = 0x123456, Stream = new MemoryStream(Encoding.UTF8.GetBytes("this is file5")) }); file.AddFile(new ArBinaryFile() { Name = "long_file_name_large_file6.txt", Timestamp = DateTimeOffset.UtcNow.AddSeconds(-2), Stream = new MemoryStream(Encoding.UTF8.GetBytes("this is file6 yoyo")) }); symbolTable.Symbols.Add(new ArSymbol() { File = file.Files[1], Name = "my_symbol" }); file.Write(stream); stream.Flush(); } // Check that AR is able to read back what we just serialized { var fileNameBuilder = new StringBuilder(); foreach (var fileEntry in file.Files) { if (fileEntry.IsSystem) { continue; } fileNameBuilder.Append($"{fileEntry.Name}\n"); } var fileNameList = fileNameBuilder.ToString().Trim(); var fileNameListFromAr = LinuxUtil.RunLinuxExe("ar", $"t {libName}").Trim(); Assert.AreEqual(fileNameListFromAr, fileNameList); } // Display the content of each file via AR { var contentBuilder = new StringBuilder(); foreach (var fileEntry in file.Files) { if (!(fileEntry is ArBinaryFile arBinary)) { continue; } arBinary.Stream.Position = 0; contentBuilder.Append(Encoding.UTF8.GetString(((MemoryStream)arBinary.Stream).ToArray())); } var content = contentBuilder.ToString().Trim(); var contentFromAr = LinuxUtil.RunLinuxExe("ar", $"p {libName}").Trim(); Assert.AreEqual(contentFromAr, content); } ArArchiveFile file2; using (var stream = new FileStream(libName, FileMode.Open, FileAccess.Read)) { file2 = ArArchiveFile.Read(stream, ArArchiveKind.GNU); } Assert.NotNull(file2.SymbolTable); CompareArFiles(file, file2); var libNameBsd = "libcustom_bsd.a"; file.Kind = ArArchiveKind.BSD; using (var stream = new FileStream(libNameBsd, FileMode.Create, FileAccess.Write)) { file.Write(stream); stream.Flush(); } ArArchiveFile archiveFileBsd; using (var stream = new FileStream(libNameBsd, FileMode.Open, FileAccess.Read)) { archiveFileBsd = ArArchiveFile.Read(stream, ArArchiveKind.BSD); } CompareArFiles(file, archiveFileBsd); }