Exemplo n.º 1
0
        bool AddFile(MappedFileCursor cur, List <string> files, List <string> folders)
        {
            string str;
            int    iDir;

            str = cur.ReadString();
            if (str.Length == 0)
            {
                return(false);
            }

            iDir = GetLeb(cur);         // directory index
            GetLeb(cur);                // file date
            GetLeb(cur);                // file size

            try
            {
                if (iDir != 0)
                {
                    str = Path.Combine(folders[iDir - 1], str);
                }
                str = Path.GetFullPath(str);
            }
            catch (ArgumentException)
            {
            }
            files.Add(str);
            return(true);
        }
Exemplo n.º 2
0
        public void GenLineInfo(MappedFileCursor curOut, LineItem[] lines)
        {
            uint pos;

            // Currently positioned just after header_length field
            pos          = curOut.Next - (uint)Marshal.SizeOf <LineHeaderPrefix>();
            curOut.Next += m_linePrefix.header_length;
            MakeLineProgram(curOut, lines);
            curOut.View.Write(pos, curOut.Next - pos - sizeof(uint));

            // Signal that space after this is unused. This is needed
            // if this program is run a second time on the same ELF file.
            pos = curOut.End - curOut.Next;
            if (pos == 0)
            {
                return;
            }
            if (pos < sizeof(uint))
            {
                throw new Exception("Unable to patch tiny hole");
            }
            if (pos < (uint)Marshal.SizeOf <LineHeaderPrefix>())
            {
                curOut.WriteUint(SkipUnit + pos);
                return;
            }

            m_linePrefix.unit_length   = SkipUnit + (uint)Marshal.SizeOf <LineHeaderPrefix>();
            m_linePrefix.version       = 0;
            m_linePrefix.header_length = pos;
            curOut.Write <LineHeaderPrefix>(ref m_linePrefix);
        }
Exemplo n.º 3
0
        public LineResult GetLineInfo(MappedFileCursor cur)
        {
            LineResult line;

            line = RunLineProgram(cur);
            return(line);
        }
Exemplo n.º 4
0
        void WriteSignedLeb(MappedFileCursor cur, int i)
        {
            byte b;

            do
            {
                b   = (byte)(i & 0x7F);
                i >>= 7;
                if ((i != 0 || (b & 0x40) != 0) && (i != -1 || (b & 0x40) == 0))
                {
                    b |= 0x80;
                }
                cur.WriteByte(b);
            } while ((b & 0x80) != 0);
        }
Exemplo n.º 5
0
        static void Main(string[] args)
        {
            ElfReader   elf;
            DwarfReader dwarf;

            DwarfReader.LineResult lineRes;
            MappedFileCursor       sectionCursor;
            MappedFileCursor       unitCursor;

            ElfReader.SectionInfo section;
            uint pos;
            uint size;
            bool fDumpOnly = false;

            Debug.WriteLine(args[0]);
            if (args.Length > 1 && args[1] == "/d")
            {
                fDumpOnly = true;
            }
            elf           = new ElfReader(args[0]);
            dwarf         = new DwarfReader(elf);
            section       = dwarf.OpenDebugLines();
            sectionCursor = section.Cursor;

            while (!sectionCursor.AtEnd)
            {
                size = dwarf.GetLineInfoSize(sectionCursor);
                if (size == 0)
                {
                    continue;                           // skip unit, cursor already advanced
                }
                unitCursor          = new MappedFileCursor(sectionCursor, size);
                pos                 = unitCursor.Next;
                sectionCursor.Next += size;
                lineRes             = dwarf.GetLineInfo(unitCursor);
                if (fDumpOnly)
                {
                    DumpLines(lineRes);
                    continue;
                }

                lineRes.lines = dwarf.FilterLines(lineRes.lines);
                //DumpLines(lineRes);
                unitCursor.Next = pos;
                dwarf.GenLineInfo(unitCursor, lineRes.lines);
            }
            elf.Close();
        }
Exemplo n.º 6
0
        void WriteLeb(MappedFileCursor cur, int i)
        {
            byte b;

            do
            {
                b   = (byte)(i & 0x7F);
                i >>= 7;
                if (i != 0)
                {
                    b |= 0x80;
                }

                cur.WriteByte(b);
            } while (i != 0);
        }
Exemplo n.º 7
0
        int GetLeb(MappedFileCursor cur)
        {
            uint i;
            uint b;
            int  shift;

            shift = 0;
            i     = 0;
            do
            {
                b      = cur.ReadByte();
                i     += (b & 0x7F) << shift;
                shift += 7;
            } while ((b & 0x80) != 0);
            return((int)i);
        }
Exemplo n.º 8
0
        int GetSignedLeb(MappedFileCursor cur)
        {
            uint i;
            uint b;
            int  shift;

            shift = 0;
            i     = 0;
            do
            {
                b      = cur.ReadByte();
                i     += (b & 0x7F) << shift;
                shift += 7;
            } while ((b & 0x80) != 0);
            if ((b & 0x40) != 0)
            {
                return((int)i | -(1 << shift));
            }
            return((int)i);
        }
Exemplo n.º 9
0
        public SectionInfo[] FindSections(string[] arstrSecName)
        {
            int          cFound;
            uint         off;
            string       strSecName;
            SectionEntry sec;

            SectionInfo[]    arSections;
            MappedFileCursor curString;

            cFound     = 0;
            arSections = new SectionInfo[arstrSecName.Length];
            curString  = new MappedFileCursor(m_view);
            off        = m_oSecHeader + m_oSecEntrySize;        // skip first entry
            for (int i = 1; i < m_cSecEntry; i++, off += m_oSecEntrySize)
            {
                m_view.Read <SectionEntry>(off, out sec);
                strSecName = curString.ReadString(m_oNameTable + sec.sh_name);
                for (int j = 0; j < arstrSecName.Length; j++)
                {
                    if (strSecName == arstrSecName[j])
                    {
                        if (arSections[j].Cursor == null)
                        {
                            arSections[j].Offset = off;
                            arSections[j].Cursor = new MappedFileCursor(m_view, sec.sh_offset, sec.sh_size);
                            cFound++;
                            if (cFound == arstrSecName.Length)
                            {
                                return(arSections);
                            }
                        }
                        break;
                    }
                }
            }
            return(arSections);
        }
Exemplo n.º 10
0
        public uint GetLineInfoSize(MappedFileCursor cur)
        {
            cur.Read(out m_linePrefix);
            if (m_linePrefix.unit_length >= SkipUnit)
            {
                // A special length value means we've processed this file
                // before and have a gap between units. Skip ahead
                // to the next unit and return 0 to inform the caller.
                cur.Next -= (uint)Marshal.SizeOf <LineHeaderPrefix>();
                uint u = m_linePrefix.unit_length - SkipUnit;
                if (u < (uint)Marshal.SizeOf <LineHeaderPrefix>())
                {
                    cur.Next += u;
                }
                else
                {
                    cur.Next += m_linePrefix.header_length;
                }
                return(0);
            }

            // Don't count version or header_length field we just read
            return(m_linePrefix.unit_length - sizeof(ushort) - sizeof(uint));
        }
Exemplo n.º 11
0
 public MappedFileCursor(MappedFileCursor cursor)
 {
     Next   = cursor.Next;
     m_view = cursor.m_view;
     m_end  = cursor.m_end;
 }
Exemplo n.º 12
0
 public MappedFileCursor(MappedFileCursor cursor, uint size)
 {
     Next   = cursor.Next;
     m_view = cursor.m_view;
     m_end  = Next + size;
 }
Exemplo n.º 13
0
 public MappedFileCursor(MappedFileCursor cursor, uint offset, uint size)
 {
     Next   = offset;
     m_view = cursor.m_view;
     m_end  = offset + size;
 }
Exemplo n.º 14
0
        void MakeLineProgram(MappedFileCursor cur, LineItem[] lines)
        {
            LineItem line;
            LineItem lineLast;
            int      iLine;
            int      iOpcode;
            int      iConstAddPc;
            int      iAddrDif;
            int      iLineDif;
            bool     fFixIt;

            iConstAddPc = (255 - m_lineHead.opcode_base) / m_lineHead.line_range;
            iLine       = 0;
            fFixIt      = false;

            for (; ;)
            {
                if (iLine >= lines.Length)
                {
                    break;
                }

                lineLast.Address = 0;
                lineLast.File    = 1;
                lineLast.Line    = 1;
                lineLast.Column  = 0;
                lineLast.Discr   = 0;
                lineLast.IsStmt  = m_lineHead.default_is_stmt != 0;

                for (; ;)
                {
                    line = lines[iLine++];

                    if (line.IsStmt != lineLast.IsStmt)
                    {
                        cur.WriteByte((byte)StdLineOp.DW_LNS_negate_stmt);
                    }

                    if (line.Discr != lineLast.Discr)
                    {
                        cur.WriteByte((byte)StdLineOp.DW_LNS_extended_op);
                        // count of following bytes depends on size of LEB128
                        byte cb  = 2;
                        uint val = (uint)line.Discr;
                        while ((val >>= 7) != 0)
                        {
                            cb++;
                        }
                        cur.WriteByte(cb);
                        cur.WriteByte((byte)ExtLineOp.DW_LNE_set_discriminator);
                        WriteLeb(cur, line.Discr);
                    }

                    if (line.File != lineLast.File)
                    {
                        cur.WriteByte((byte)StdLineOp.DW_LNS_set_file);
                        WriteLeb(cur, line.File);
                    }
                    if (line.Column != lineLast.Column)
                    {
                        cur.WriteByte((byte)StdLineOp.DW_LNS_set_column);
                        WriteLeb(cur, line.Column);
                    }

                    iLineDif = line.Line - lineLast.Line;
                    iAddrDif = (line.Address - lineLast.Address) / m_lineHead.minimum_instruction_length;

                    if (iAddrDif < 0)
                    {
                        cur.WriteByte((byte)StdLineOp.DW_LNS_extended_op);
                        cur.WriteByte(5);
                        cur.WriteByte((byte)ExtLineOp.DW_LNE_set_address);
                        cur.WriteUint((uint)line.Discr);
                        iAddrDif = 0;
                    }

                    if (line.IsEnd)
                    {
                        if (iLineDif != 0)
                        {
                            cur.WriteByte((byte)StdLineOp.DW_LNS_advance_line);
                            WriteSignedLeb(cur, iLineDif);
                        }
                        if (iAddrDif != 0)
                        {
                            cur.WriteByte((byte)StdLineOp.DW_LNS_advance_pc);
                            WriteLeb(cur, iAddrDif);
                        }
                        cur.WriteByte((byte)StdLineOp.DW_LNS_extended_op);
                        cur.WriteByte(1);                               // count of following bytes
                        cur.WriteByte((byte)ExtLineOp.DW_LNE_end_sequence);
                        break;
                    }

                    if (iLineDif < m_lineHead.line_base || iLineDif >= m_lineHead.line_base + m_lineHead.line_range)
                    {
                        // line dif exceeds range of special opcode
                        cur.WriteByte((byte)StdLineOp.DW_LNS_advance_line);
                        WriteSignedLeb(cur, iLineDif);
                        iLineDif = 0;
                    }

FixOpcode:
                    if (fFixIt || iAddrDif > iConstAddPc)
                    {
                        // address dif exceeds range of special opcode
                        if (fFixIt || iAddrDif > iConstAddPc * 2)
                        {
                            // Big dif, use multi-byte opcode
                            cur.WriteByte((byte)StdLineOp.DW_LNS_advance_pc);
                            WriteLeb(cur, iAddrDif);
                            iAddrDif = 0;
                        }
                        else
                        {
                            // Within range of single byte opcode
                            cur.WriteByte((byte)StdLineOp.DW_LNS_const_add_pc);
                            iAddrDif -= iConstAddPc;
                        }
                        fFixIt = false;
                    }

                    if (iAddrDif == 0 && iLineDif == 0)
                    {
                        cur.WriteByte((byte)StdLineOp.DW_LNS_copy);
                    }
                    else
                    {
                        // Compute special opcode
                        iOpcode = iLineDif - m_lineHead.line_base + m_lineHead.line_range * iAddrDif + m_lineHead.opcode_base;
                        if (iOpcode > 255)
                        {
                            fFixIt = true;
                            goto FixOpcode;
                        }
                        cur.WriteByte((byte)iOpcode);
                    }

                    // Move on to next line
                    if (iLine >= lines.Length)
                    {
                        throw new Exception("Line list did not end with End Sequence");
                    }
                    lineLast = line;
                }
            }
        }
Exemplo n.º 15
0
        LineResult RunLineProgram(MappedFileCursor cur)
        {
            byte[]          arbOpLen;
            List <string>   arstrFolders;
            List <string>   arstrFiles;
            List <LineItem> lstLine;
            string          str;
            byte            op;
            int             iConstAddPc;
            int             iLen;
            LineItem        line;
            LineResult      res;

            if (m_linePrefix.version == 4)
            {
                cur.Read(out m_lineHeadV4);
                if (m_lineHeadV4.maximum_operations_per_instruction != 1)
                {
                    Debug.WriteLine("Incompatible file format");
                }
                m_lineHead.minimum_instruction_length = m_lineHeadV4.minimum_instruction_length;
                m_lineHead.default_is_stmt            = m_lineHeadV4.default_is_stmt;
                m_lineHead.line_base   = m_lineHeadV4.line_base;
                m_lineHead.line_range  = m_lineHeadV4.line_range;
                m_lineHead.opcode_base = m_lineHeadV4.opcode_base;
            }
            else
            {
                cur.Read(out m_lineHead);
            }

            arbOpLen = new byte[m_lineHead.opcode_base];
            for (int i = 1; i < arbOpLen.Length; i++)
            {
                arbOpLen[i] = cur.ReadByte();
            }

            arstrFolders = new List <string>();
            for (; ;)
            {
                str = cur.ReadString();
                if (str.Length == 0)
                {
                    break;
                }
                arstrFolders.Add(str);
            }

            arstrFiles = new List <string>();
            while (AddFile(cur, arstrFiles, arstrFolders))
            {
                ;
            }

            iConstAddPc = (255 - m_lineHead.opcode_base) / m_lineHead.line_range * m_lineHead.minimum_instruction_length;
            lstLine     = new List <LineItem>();

            while (!cur.AtEnd)
            {
                line.Address = 0;
                line.File    = 1;
                line.Line    = 1;
                line.Column  = 0;
                line.Discr   = 0;
                line.IsStmt  = m_lineHead.default_is_stmt != 0;
                line.IsEnd   = false;
                m_lineLast   = line;

                while (!cur.AtEnd)
                {
                    op = cur.ReadByte();
                    if (op >= m_lineHead.opcode_base)
                    {
                        // Special opcode
                        op           -= m_lineHead.opcode_base;
                        line.Address += op / m_lineHead.line_range * m_lineHead.minimum_instruction_length;
                        line.Line    += op % m_lineHead.line_range + m_lineHead.line_base;
                        lstLine.Add(line);
                        m_lineLast = line;
                    }
                    else
                    {
                        switch ((StdLineOp)op)
                        {
                        case StdLineOp.DW_LNS_extended_op:
                            iLen = GetLeb(cur) - 1;
                            op   = cur.ReadByte();
                            switch ((ExtLineOp)op)
                            {
                            case ExtLineOp.DW_LNE_end_sequence:
                                line.IsEnd = true;
                                lstLine.Add(line);
                                goto NextSequence;

                            case ExtLineOp.DW_LNE_set_address:
                                line.Address = (int)cur.ReadUint();
                                break;

                            case ExtLineOp.DW_LNE_define_file:
                                AddFile(cur, arstrFiles, arstrFolders);
                                Debug.WriteLine("File added inline");
                                break;

                            case ExtLineOp.DW_LNE_set_discriminator:
                                line.Discr = GetLeb(cur);
                                break;

                            default:
                                Debug.WriteLine($"Ignored extended opcode {op}");
                                cur.Next += (uint)iLen;
                                break;
                            }
                            break;

                        case StdLineOp.DW_LNS_copy:
                            lstLine.Add(line);
                            m_lineLast = line;
                            break;

                        case StdLineOp.DW_LNS_advance_pc:
                            line.Address += GetLeb(cur) * m_lineHead.minimum_instruction_length;
                            break;

                        case StdLineOp.DW_LNS_advance_line:
                            line.Line += GetSignedLeb(cur);
                            break;

                        case StdLineOp.DW_LNS_set_file:
                            line.File = GetLeb(cur);
                            break;

                        case StdLineOp.DW_LNS_set_column:
                            line.Column = GetLeb(cur);
                            break;

                        case StdLineOp.DW_LNS_negate_stmt:
                            line.IsStmt = !line.IsStmt;
                            break;

                        case StdLineOp.DW_LNS_const_add_pc:
                            line.Address += iConstAddPc;
                            break;

                        case StdLineOp.DW_LNS_fixed_advance_pc:
                            line.Address += cur.ReadUshort();
                            break;

                        case StdLineOp.DW_LNS_set_basic_block:
                        case StdLineOp.DW_LNS_set_prologue_end:
                        case StdLineOp.DW_LNS_set_epilogue_begin:
                        default:
                            Debug.WriteLine($"Ignored opcode {Enum.GetName(typeof(StdLineOp), op)}");
                            for (int i = arbOpLen[op]; i > 0; i--)
                            {
                                GetLeb(cur);
                            }
                            break;
                        }
                    }
                }
                NextSequence :;
            }

            res.lines = lstLine.ToArray();
            res.files = arstrFiles.ToArray();
            return(res);
        }