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); }
public DwarfData(ElfFile file) { _file = file; //extract compilation units compilationUnits = DwarfCompilationUnit.ReadCompilationUnits(file); //extract abbreviations var abbrevSection = file.GetSection(DwarfSections.Abbrev); int id = 0; foreach (var cu in compilationUnits) { cu.Abbrev = DwarfAbbreviation.Read(file, (long)cu.AbbrevOffset + abbrevSection.Header.offset); cu.ReadValues(file); id++; } //build file items tables var nameTable = new Dictionary <string, DwarfCompilationUnitItem>(); var pcTable = new Dictionary <ulong, DwarfCompilationUnitItem>(); foreach (var unit in compilationUnits) { foreach (var dwarfAbbreviationEntry in unit.Abbrev.entries) { foreach (var attr in dwarfAbbreviationEntry.attributes) { if (attr.attribute == DwarfConstants.DwarfAttribute.DW_AT_MIPS_linkage_name) { Console.WriteLine("LN"); } } } foreach (var item in unit.Items) { if (item.Pc != 0) { pcTable[item.Pc] = item; } if (!string.IsNullOrEmpty(item.Name)) { nameTable[item.Name] = item; } } } var symbols = file.Sections.SelectMany(v => v.Symbols).ToArray(); var tmpItems = new List <DwarfCompilationUnitItem>(); foreach (var symbol in symbols) { DwarfCompilationUnitItem item = null; //find item corresponding to symbol if (!string.IsNullOrEmpty(symbol.Name) && nameTable.TryGetValue(symbol.Name, out item) || symbol.Header.ValueAddr != 0 && pcTable.TryGetValue(symbol.Header.ValueAddr, out item)) { if ((int)item.Size == 0) { item.Size = symbol.Header.Size; } if ((long)item.Pc == 0L) { item.Pc = symbol.Header.ValueAddr; } //dictionary3[mem.pc] = true; if (string.IsNullOrEmpty(item.Name)) { item.Name = symbol.Name; } } else { if (!string.IsNullOrEmpty(symbol.Name)) { item = new DwarfCompilationUnitItem(symbol); } } if (item != null && item.Size != 0 && !string.IsNullOrEmpty(item.Name) && item.HasLine()) { tmpItems.Add(item); } } //sort members by pc tmpItems.Sort(((mem, member) => mem.Pc.CompareTo(member.Pc))); foreach (var unitItem in tmpItems) { if (unitItem.Size != 0) { DwarfCompilationUnitItem item = null; if (globalItems.Count > 0) { item = globalItems[globalItems.Count - 1]; } if (item != null && (item.Pc == unitItem.Pc)) { if (!item.HasLine() && unitItem.HasLine()) { globalItems[globalItems.Count - 1] = unitItem; } else { continue; } } else if (item != null && item.Pc <= unitItem.Pc && item.Pc + item.Size > unitItem.Pc) { item.Size = (uint)(unitItem.Pc - item.Pc); } globalItems.Add(unitItem); } } //fill sections with items foreach (var item in globalItems) { if (item.Size != 0) { var index = file.GetSectionId(item.Pc); if (index >= 0) { var section = file.Sections[index]; section.Items.Add(item); } } } foreach (var section in file.Sections) { ulong itemsSize = section.Items.Aggregate <DwarfCompilationUnitItem, ulong>(0, (current, item) => current + item.Size); var diff = section.Header.size - itemsSize; if (diff != 0) { section.Items.Add(new DwarfCompilationUnitItem() { Name = "other", Size = diff }); } } }