Beispiel #1
0
        public void SimpleDwarf()
        {
            var cppName = "helloworld";
            var cppExe  = $"{cppName}_debug";

            LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -g -o {cppExe}");

            ElfObjectFile elf;

            using (var inStream = File.OpenRead(cppExe))
            {
                Console.WriteLine($"ReadBack from {cppExe}");
                elf = ElfObjectFile.Read(inStream);
                elf.Print(Console.Out);
            }

            var debugInfo   = (ElfCustomSection)elf.Sections.FirstOrDefault(x => x.Name.Value == ".debug_info");
            var debugAbbrev = (ElfCustomSection)elf.Sections.FirstOrDefault(x => x.Name.Value == ".debug_abbrev");
            var debugStr    = (ElfCustomSection)elf.Sections.FirstOrDefault(x => x.Name.Value == ".debug_str");

            //var dwarfReader = new DwarfReaderWriter(debugInfo.Stream, debugAbbrev.Stream, debugStr.Stream);

            DwarfDebugStringTable stringTable = new DwarfDebugStringTable()
            {
                Stream = debugStr.Stream
            };
            DwarfDebugAbbrevTable abbrevTable = new DwarfDebugAbbrevTable()
            {
                Stream = debugAbbrev.Stream
            };

            var debugInfoReadContext = new DwarfDebugInfoReadContext(stringTable, abbrevTable);

            DwarfDebugInfoSection.TryRead(debugInfo.Stream, elf.Encoding == ElfEncoding.Lsb, debugInfoReadContext, out var debugInfoSection, out var diagnostics);
        }
Beispiel #2
0
        public void TestHelloWorld()
        {
            var cppName = "helloworld";

            LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -o {cppName}");

            ElfObjectFile elf;

            using (var inStream = File.OpenRead(cppName))
            {
                Console.WriteLine($"ReadBack from {cppName}");
                elf = ElfObjectFile.Read(inStream);
                elf.Print(Console.Out);
            }

            using (var outStream = File.OpenWrite($"{cppName}_copy"))
            {
                elf.Write(outStream);
                outStream.Flush();
            }

            var expected = LinuxUtil.ReadElf(cppName);
            var result   = LinuxUtil.ReadElf($"{cppName}_copy");

            if (expected != result)
            {
                Console.WriteLine("=== Result:");
                Console.WriteLine(result);

                Console.WriteLine("=== Expected:");
                Console.WriteLine(expected);

                Assert.AreEqual(expected, result);
            }
        }
Beispiel #3
0
        public void TestDebugInfoSmall()
        {
            var cppName = "small";
            var cppObj  = $"{cppName}_debug.o";

            LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -g -c -o {cppObj}");

            ElfObjectFile elf;

            using (var inStream = File.OpenRead(cppObj))
            {
                elf = ElfObjectFile.Read(inStream);
                elf.Print(Console.Out);
            }

            var elfContext   = new DwarfElfContext(elf);
            var inputContext = new DwarfReaderContext(elfContext);
            var dwarf        = DwarfFile.Read(inputContext);

            dwarf.AbbreviationTable.Print(Console.Out);
            dwarf.InfoSection.Print(Console.Out);
            dwarf.AddressRangeTable.Print(Console.Out);

            PrintStreamLength(inputContext);

            Console.WriteLine();
            Console.WriteLine("====================================================================");
            Console.WriteLine("Write Back");
            Console.WriteLine("====================================================================");

            var outputContext = new DwarfWriterContext
            {
                IsLittleEndian          = inputContext.IsLittleEndian,
                AddressSize             = inputContext.AddressSize,
                DebugAbbrevStream       = new MemoryStream(),
                DebugLineStream         = new MemoryStream(),
                DebugInfoStream         = new MemoryStream(),
                DebugStringStream       = new MemoryStream(),
                DebugAddressRangeStream = new MemoryStream()
            };

            dwarf.Write(outputContext);

            dwarf.AbbreviationTable.Print(Console.Out);
            dwarf.InfoSection.Print(Console.Out);
            dwarf.InfoSection.PrintRelocations(Console.Out);
            dwarf.AddressRangeTable.Print(Console.Out);
            dwarf.AddressRangeTable.PrintRelocations(Console.Out);

            dwarf.WriteToElf(elfContext);

            var cppObj2 = $"{cppName}_debug2.o";

            using (var outStream = new FileStream(cppObj2, FileMode.Create))
            {
                elf.Write(outStream);
            }

            PrintStreamLength(outputContext);
        }
Beispiel #4
0
        public void TestDebugLineSmall()
        {
            var cppName = "small";
            var cppObj  = $"{cppName}_debug.o";

            LinuxUtil.RunLinuxExe("gcc", $"{cppName}.cpp -g -c -o {cppObj}");
            ElfObjectFile elf;

            using (var inStream = File.OpenRead(cppObj))
            {
                Console.WriteLine($"ReadBack from {cppObj}");
                elf = ElfObjectFile.Read(inStream);
                elf.Print(Console.Out);
            }

            var elfContext   = new DwarfElfContext(elf);
            var inputContext = new DwarfReaderContext(elfContext);

            inputContext.DebugLinePrinter = Console.Out;
            var dwarf = DwarfFile.Read(inputContext);

            inputContext.DebugLineStream.Position = 0;
            var copyInputDebugLineStream = new MemoryStream();

            inputContext.DebugLineStream.CopyTo(copyInputDebugLineStream);
            inputContext.DebugLineStream.Position = 0;

            var outputContext = new DwarfWriterContext
            {
                IsLittleEndian  = inputContext.IsLittleEndian,
                AddressSize     = inputContext.AddressSize,
                DebugLineStream = new MemoryStream()
            };

            dwarf.Write(outputContext);

            Console.WriteLine();
            Console.WriteLine("=====================================================");
            Console.WriteLine("Readback");
            Console.WriteLine("=====================================================");
            Console.WriteLine();

            var reloadContext = new DwarfReaderContext()
            {
                IsLittleEndian  = outputContext.IsLittleEndian,
                AddressSize     = outputContext.AddressSize,
                DebugLineStream = outputContext.DebugLineStream
            };

            reloadContext.DebugLineStream.Position = 0;
            reloadContext.DebugLineStream          = outputContext.DebugLineStream;
            reloadContext.DebugLinePrinter         = Console.Out;

            var dwarf2 = DwarfFile.Read(reloadContext);

            var inputDebugLineBuffer  = copyInputDebugLineStream.ToArray();
            var outputDebugLineBuffer = ((MemoryStream)reloadContext.DebugLineStream).ToArray();

            Assert.AreEqual(inputDebugLineBuffer, outputDebugLineBuffer);
        }
Beispiel #5
0
        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}");
            }
        }
Beispiel #6
0
        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);
        }