private IEnumerable <ELFProgramSegment> ReadSegments() { Header.IsProgramHeaderCountReasonable.CheckThrowing(); IsHeaderProgramHeaderOffsetValid.CheckThrowing(); IsHeaderProgramHeaderEntrySizeValid.CheckThrowing(); // Calculate the loadBias. It is usually just the base address except for some executable modules. ulong loadBias = _position; if (loadBias > 0) { for (uint i = 0; i < Header.ProgramHeaderCount; i++) { ulong programHeaderOffset = _position + Header.ProgramHeaderOffset + i * Header.ProgramHeaderEntrySize; ELFProgramHeader header = DataSourceReader.Read <ELFProgramHeader>(programHeaderOffset); if (header.Type == ELFProgramHeaderType.Load && header.FileOffset == 0) { loadBias -= header.VirtualAddress; } } } // Build the program segments List <ELFProgramSegment> segments = new List <ELFProgramSegment>(); for (uint i = 0; i < Header.ProgramHeaderCount; i++) { ulong programHeaderOffset = _position + Header.ProgramHeaderOffset + i * Header.ProgramHeaderEntrySize; segments.Add(new ELFProgramSegment(DataSourceReader, loadBias, programHeaderOffset, _isDataSourceVirtualAddressSpace)); } return(segments); }
public uint Read(ulong position, byte[] buffer, uint bufferOffset, uint count) { uint bytesRead = 0; while (bytesRead != count) { int i = 0; for (; i < _segments.Length; i++) { ELFProgramHeader header = _segments[i].Header; ulong upperAddress = header.VirtualAddress + header.VirtualSize; if (header.VirtualAddress <= position && position < upperAddress) { uint bytesToReadRange = (uint)Math.Min(count - bytesRead, upperAddress - position); ulong segmentOffset = position - header.VirtualAddress; uint bytesReadRange = _segments[i].Contents.Read(segmentOffset, buffer, bufferOffset, bytesToReadRange); if (bytesReadRange == 0) { goto done; } position += bytesReadRange; bufferOffset += bytesReadRange; bytesRead += bytesReadRange; break; } } if (i == _segments.Length) { break; } } done: if (bytesRead == 0) { throw new InvalidVirtualAddressException(string.Format("Virtual address range is not mapped {0:X16} {1}", position, count)); } // Zero the rest of the buffer if read less than requested Array.Clear(buffer, (int)bufferOffset, (int)(count - bytesRead)); return(bytesRead); }
public uint Read(ulong position, byte[] buffer, uint bufferOffset, uint count) { for (int i = 0; i < _segments.Length; i++) { ELFProgramHeader header = _segments[i].Header; // FileSize == 0 means the segment isn't backed by any data if (header.FileSize > 0 && header.VirtualAddress <= position && position + count <= header.VirtualAddress + header.VirtualSize) { ulong segmentOffset = position - header.VirtualAddress; uint fileBytes = (uint)Math.Min(count, header.FileSize); uint bytesRead = _segments[i].Contents.Read(segmentOffset, buffer, bufferOffset, fileBytes); //zero the rest of the buffer if it is in the virtual address space but not the physical address space if (bytesRead == fileBytes && fileBytes != count) { Array.Clear(buffer, (int)(bufferOffset + fileBytes), (int)(count - fileBytes)); bytesRead = count; } return(bytesRead); } } throw new InvalidVirtualAddressException(string.Format("Virtual address range is not mapped {0:X16} {1}", position, count)); }