private static List ReadData()

in src/BinaryParsers/ElfBinary/Dwarf/DwarfLineNumberProgram.cs [176:375]


        private static List<DwarfFileInformation> ReadData(DwarfMemoryReader debugLine, NormalizeAddressDelegate addressNormalizer)
        {
            // Read header
            ulong length = debugLine.ReadLength(out bool is64bit);
            int endPosition = debugLine.Position + (int)length;

            if (endPosition > debugLine.Data.Length - 1)
            {
                endPosition = debugLine.Data.Length - 1;
            }

            debugLine.ReadUshort(); // version
            debugLine.ReadOffset(is64bit); // headerLength
            byte minimumInstructionLength = debugLine.ReadByte();
            bool defaultIsStatement = debugLine.ReadByte() != 0;
            sbyte lineBase = (sbyte)debugLine.ReadByte();
            byte lineRange = debugLine.ReadByte();
            byte operationCodeBase = debugLine.ReadByte();

            if (operationCodeBase <= 0)
            {
                return new List<DwarfFileInformation>();
            }

            // Read operation code lengths
            uint[] operationCodeLengths = new uint[operationCodeBase];

            operationCodeLengths[0] = 0;
            for (int i = 1; i < operationCodeLengths.Length && debugLine.Position < endPosition; i++)
            {
                operationCodeLengths[i] = debugLine.LEB128();
            }

            // Read directories
            List<string> directories = new List<string>();

            while (debugLine.Position < endPosition && debugLine.Peek() != 0)
            {
                string directory = debugLine.ReadString();

                directory = directory.Replace('/', Path.DirectorySeparatorChar);
                directories.Add(directory);
            }
            debugLine.ReadByte(); // Skip zero termination byte

            // Read files
            List<DwarfFileInformation> files = new List<DwarfFileInformation>();

            while (debugLine.Position < endPosition && debugLine.Peek() != 0)
            {
                files.Add(ReadFile(debugLine, directories));
            }
            debugLine.ReadByte(); // Skip zero termination byte

            // Parse lines
            ParsingState state = new ParsingState(files.FirstOrDefault(), defaultIsStatement, minimumInstructionLength);
            uint lastAddress = 0;

            while (debugLine.Position < endPosition)
            {
                byte operationCode = debugLine.ReadByte();

                if (operationCode >= operationCodeLengths.Length)
                {
                    // Special operation code
                    int adjustedOperationCode = operationCode - operationCodeBase;
                    int operationAdvance = adjustedOperationCode / lineRange;
                    state.AdvanceAddress(operationAdvance);
                    int lineAdvance = lineBase + (adjustedOperationCode % lineRange);
                    state.Line += (uint)lineAdvance;
                    state.AddCurrentLineInfo();
                    state.IsBasicBlock = false;
                    state.IsPrologueEnd = false;
                    state.IsEpilogueEnd = false;
                    state.Discriminator = 0;
                }
                else
                {
                    switch ((DwarfLineNumberStandardOpcode)operationCode)
                    {
                        case DwarfLineNumberStandardOpcode.Extended:
                        {
                            uint extendedLength = debugLine.LEB128();
                            int newPosition = debugLine.Position + (int)extendedLength;
                            DwarfLineNumberExtendedOpcode extendedCode = DwarfLineNumberExtendedOpcode.Unknown;
                            if (debugLine.Position + 1 <= debugLine.Data.Length)
                            {
                                extendedCode = (DwarfLineNumberExtendedOpcode)debugLine.ReadByte();
                            }

                            switch (extendedCode)
                            {
                                case DwarfLineNumberExtendedOpcode.EndSequence:
                                    lastAddress = state.Address;
                                    state.IsSequenceEnd = true;
                                    state.AddCurrentLineInfo();
                                    state.Reset(files.FirstOrDefault());
                                    break;

                                case DwarfLineNumberExtendedOpcode.SetAddress:
                                {
                                    state.Address = debugLine.ReadUint();
                                    if (state.Address == 0)
                                    {
                                        state.Address = lastAddress;
                                    }
                                    state.OperationIndex = 0;
                                }
                                break;

                                case DwarfLineNumberExtendedOpcode.DefineFile:
                                    state.File = ReadFile(debugLine, directories);
                                    files.Add(state.File);
                                    break;

                                case DwarfLineNumberExtendedOpcode.SetDiscriminator:
                                    state.Discriminator = debugLine.LEB128();
                                    break;

                                default:
                                    break;
                            }
                            debugLine.Position = newPosition;
                        }
                        break;

                        case DwarfLineNumberStandardOpcode.Copy:
                            state.AddCurrentLineInfo();
                            state.IsBasicBlock = false;
                            state.IsPrologueEnd = false;
                            state.IsEpilogueEnd = false;
                            state.Discriminator = 0;
                            break;

                        case DwarfLineNumberStandardOpcode.AdvancePc:
                            state.AdvanceAddress((int)debugLine.LEB128());
                            break;

                        case DwarfLineNumberStandardOpcode.AdvanceLine:
                            state.Line += debugLine.SLEB128();
                            break;

                        case DwarfLineNumberStandardOpcode.SetFile:
                            int index = (int)debugLine.LEB128() - 1;
                            if (index >= 0 && index < files.Count)
                            {
                                state.File = files[index];
                            }
                            break;

                        case DwarfLineNumberStandardOpcode.SetColumn:
                            state.Column = debugLine.LEB128();
                            break;

                        case DwarfLineNumberStandardOpcode.NegateStmt:
                            state.IsStatement = !state.IsStatement;
                            break;

                        case DwarfLineNumberStandardOpcode.SetBasicBlock:
                            state.IsBasicBlock = true;
                            break;

                        case DwarfLineNumberStandardOpcode.ConstAddPc:
                            state.AdvanceAddress((255 - operationCodeBase) / lineRange);
                            break;

                        case DwarfLineNumberStandardOpcode.FixedAdvancePc:
                            state.Address += debugLine.ReadUshort();
                            state.OperationIndex = 0;
                            break;

                        case DwarfLineNumberStandardOpcode.SetPrologueEnd:
                            state.IsPrologueEnd = true;
                            break;

                        case DwarfLineNumberStandardOpcode.SetEpilogueBegin:
                            state.IsEpilogueEnd = true;
                            break;

                        case DwarfLineNumberStandardOpcode.SetIsa:
                            state.Isa = debugLine.LEB128();
                            break;

                        default:
                            // Special opcodes(13 or greater)
                            break;
                    }
                }
            }

            // Fix lines in files...
            foreach (DwarfFileInformation file in files)
            {
                for (int i = 0; i < file.Lines.Count; i++)
                {
                    file.Lines[i].Address = (uint)addressNormalizer(file.Lines[i].Address);
                }
            }
            return files;
        }