Example #1
0
        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);
        }
Example #2
0
        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
                    });
                }
            }
        }