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); }
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); }
public void CreateDwarf() { // Create ELF object var elf = new ElfObjectFile(ElfArch.X86_64); var codeSection = new ElfBinarySection(new MemoryStream(new byte[0x64])).ConfigureAs(ElfSectionSpecialType.Text); elf.AddSection(codeSection); var stringSection = new ElfStringTable(); elf.AddSection(stringSection); elf.AddSection(new ElfSymbolTable() { Link = stringSection }); elf.AddSection(new ElfSectionHeaderStringTable()); var elfDiagnostics = new DiagnosticBag(); elf.UpdateLayout(elfDiagnostics); Assert.False(elfDiagnostics.HasErrors); // Create DWARF Object var dwarfFile = new DwarfFile(); // Create .debug_line information var fileName = new DwarfFileName() { Name = "check1.cpp", Directory = Environment.CurrentDirectory, }; var fileName2 = new DwarfFileName() { Name = "check2.cpp", Directory = Environment.CurrentDirectory, }; // First line table for (int i = 0; i < 2; i++) { var lineTable = new DwarfLineProgramTable(); dwarfFile.LineSection.AddLineProgramTable(lineTable); lineTable.AddressSize = DwarfAddressSize.Bit64; lineTable.FileNames.Add(fileName); lineTable.FileNames.Add(fileName2); lineTable.AddLineSequence(new DwarfLineSequence() { new DwarfLine() { File = fileName, Address = 0, Column = 1, Line = 1, }, new DwarfLine() { File = fileName, Address = 1, Column = 1, Line = 2, } } ); // NOTE: doesn't seem to be generated by regular GCC // (it seems that only one line sequence is usually used) lineTable.AddLineSequence(new DwarfLineSequence() { new DwarfLine() { File = fileName2, Address = 0, Column = 1, Line = 1, }, } ); } // Create .debug_info var rootDIE = new DwarfDIECompileUnit() { Name = fileName.Name, LowPC = 0, // 0 relative to base virtual address HighPC = (int)codeSection.Size, // default is offset/length after LowPC CompDir = fileName.Directory, StmtList = dwarfFile.LineSection.LineTables[0], }; var subProgram = new DwarfDIESubprogram() { Name = "MyFunction", }; rootDIE.AddChild(subProgram); var cu = new DwarfCompilationUnit() { AddressSize = DwarfAddressSize.Bit64, Root = rootDIE }; dwarfFile.InfoSection.AddUnit(cu); // AddressRange table dwarfFile.AddressRangeTable.AddressSize = DwarfAddressSize.Bit64; dwarfFile.AddressRangeTable.Unit = cu; dwarfFile.AddressRangeTable.Ranges.Add(new DwarfAddressRange(0, 0, codeSection.Size)); // Transfer DWARF To ELF var dwarfElfContext = new DwarfElfContext(elf); dwarfFile.WriteToElf(dwarfElfContext); var outputFileName = "create_dwarf.o"; using (var output = new FileStream(outputFileName, FileMode.Create)) { elf.Write(output); } elf.Print(Console.Out); Console.WriteLine(); dwarfFile.AbbreviationTable.Print(Console.Out); Console.WriteLine(); dwarfFile.AddressRangeTable.Print(Console.Out); Console.WriteLine(); dwarfFile.InfoSection.Print(Console.Out); Console.WriteLine("ReadBack --debug-dump=rawline"); var readelf = LinuxUtil.ReadElf(outputFileName, "--debug-dump=rawline").TrimEnd(); Console.WriteLine(readelf); }