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)); }
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); }