public CIE(DwarfFrameReader frame, long offset, CIE next)
            {
                this.frame  = frame;
                this.offset = offset;
                this.next   = next;

                DwarfBinaryReader reader = new DwarfBinaryReader(
                    frame.bfd, frame.blob, false);

                read_cie(reader);
            }
        private long ReadEncodedValue(DwarfBinaryReader reader, int encoding)
        {
            long base_addr;

            switch (encoding & 0x70)
            {
            case 0:
                base_addr = 0;
                break;

            case (byte)DW_EH_PE.pcrel:
                base_addr = vma + reader.Position;
                break;

            default:
                throw new DwarfException(
                          reader.Bfd, "Unknown encoding `{0:x}' in CIE",
                          encoding);
            }

            long value;

            switch (encoding & 0x0f)
            {
            case (byte)DW_EH_PE.udata4:
                value = reader.ReadUInt32();
                break;

            case (byte)DW_EH_PE.sdata4:
                value = reader.ReadInt32();
                break;

            default:
                throw new DwarfException(
                          reader.Bfd, "Unknown encoding `{0:x}' in CIE",
                          encoding);
            }

            return(base_addr + value);
        }
            void read_cie(DwarfBinaryReader reader)
            {
                long length  = reader.ReadInitialLength();
                long end_pos = reader.Position + length;
                int  id      = reader.ReadInt32();

                bool is_cie;

                if (frame.is_ehframe)
                {
                    is_cie = id == 0;
                }
                else
                {
                    is_cie = id == -1;
                }
                if (!is_cie)
                {
                    throw new InvalidOperationException();
                }

                int version = reader.ReadByte();

                if (version != 1)
                {
                    throw new DwarfException(
                              reader.Bfd, "Unknown version {0} in CIE",
                              version);
                }

                string augmentation = reader.ReadString();

                if (augmentation.StartsWith("eh"))
                {
                    reader.ReadAddress();
                    augmentation = augmentation.Substring(2);
                }

                code_alignment  = reader.ReadLeb128();
                data_alignment  = reader.ReadSLeb128();
                return_register = reader.ReadByte();

                for (int pos = 0; pos < augmentation.Length; pos++)
                {
                    if (augmentation [pos] == 'z')
                    {
                        reader.ReadLeb128();
                        // has_z_augmentation = true;
                        continue;
                    }

                    if (augmentation [pos] == 'L')
                    {
                        continue;
                    }
                    else if (augmentation [pos] == 'R')
                    {
                        encoding = reader.ReadByte();
                        continue;
                    }
                    else if (augmentation [pos] == 'P')
                    {
                        continue;
                    }

                    throw new DwarfException(
                              reader.Bfd, "Unknown augmentation `{0}' in CIE",
                              augmentation[pos]);
                }

                columns = new Column [return_register + 2];
                for (int i = 0; i < columns.Length; i++)
                {
                    columns [i] = new Column(State.Undefined);
                }

                Entry entry = new Entry(this);

                entry.Read(reader, end_pos);

                reader.Position = end_pos;
            }
        public StackFrame UnwindStack(StackFrame frame, TargetMemoryAccess target,
                                      Architecture arch)
        {
            if (frame.TargetAddress.IsNull)
            {
                return(null);
            }

            TargetAddress address = frame.TargetAddress;

            DwarfBinaryReader reader = new DwarfBinaryReader(bfd, blob, false);

            while (reader.Position < reader.Size)
            {
                long length = reader.ReadInitialLength();
                if (length == 0)
                {
                    break;
                }
                long end_pos = reader.Position + length;

                long cie_pointer = reader.ReadOffset();
                bool is_cie;
                if (is_ehframe)
                {
                    is_cie = cie_pointer == 0;
                }
                else
                {
                    is_cie = cie_pointer == -1;
                }

                if (is_cie)
                {
                    reader.Position = end_pos;
                    continue;
                }

                if (is_ehframe)
                {
                    cie_pointer = reader.Position - cie_pointer -
                                  target.TargetMemoryInfo.TargetAddressSize;
                }

                CIE cie = find_cie(cie_pointer);

                long initial, range;
                if (is_ehframe)
                {
                    initial = ReadEncodedValue(reader, cie.Encoding);
                    range   = ReadEncodedValue(reader, cie.Encoding & 0x0f);
                }
                else
                {
                    initial = reader.ReadAddress();
                    range   = reader.ReadAddress();
                }

                TargetAddress start = new TargetAddress(target.AddressDomain, initial);

                if ((address < start) || (address > start + range))
                {
                    reader.Position = end_pos;
                    continue;
                }

                Entry fde = new Entry(cie, start, address);
                fde.Read(reader, end_pos);
                return(fde.Unwind(frame, target, arch));
            }

            return(null);
        }
            public void Read(DwarfBinaryReader reader, long end_pos)
            {
                while (reader.Position < end_pos)
                {
                    byte first  = reader.ReadByte();
                    int  opcode = first >> 6;
                    int  low    = first & 0x3f;

                    if (opcode == (int)DW_CFA.offset)
                    {
                        int offset = reader.ReadLeb128();
                        offset *= cie.DataAlignment;

                        columns [low + 1].State    = State.Offset;
                        columns [low + 1].Register = 0;
                        columns [low + 1].Offset   = offset;
                        continue;
                    }
                    else if (opcode == (int)DW_CFA.advance_loc)
                    {
                        current_address += low;
                        if (current_address > address)
                        {
                            return;
                        }
                        continue;
                    }
                    else if (opcode != 0)
                    {
                        continue;
                    }

                    switch ((DW_CFA)low)
                    {
                    case DW_CFA.nop:
                        break;

                    case DW_CFA.def_cfa:
                        columns [0].State    = State.Register;
                        columns [0].Register = reader.ReadLeb128();
                        columns [0].Offset   = reader.ReadLeb128();
                        break;

                    case DW_CFA.def_cfa_register:
                        columns [0].State    = State.Register;
                        columns [0].Register = reader.ReadLeb128();
                        break;

                    case DW_CFA.def_cfa_offset:
                        columns [0].Offset = reader.ReadLeb128();
                        break;

                    case DW_CFA.gnu_args_size:
                        // Ignored.
                        reader.ReadLeb128();
                        break;

                    default:
                        break;
                    }
                }
            }