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