/*
         * Create a new memory region in the address space.
         *
         * If there are any overlaps between the current address space and the requested one,
         * this function will unamp the overlapped portions of the address space before
         * mapping in the new memory region.
         *
         * Several clients, including the dynamic linker relies on this feature. See mmap(2)
         * for details.
         *
         * This function requires vaddr and memorySize are aligned to the page boundary.
         */
        internal int AddMapping(uint access, int flags, File file, uint fileOffset, int fileSize, Pointer vaddr, int memorySize)
        {
            Contract.Requires(file == null || file.GhostOwner == GhostOwner);
            Contract.Requires(0 <= fileSize && fileSize <= memorySize);
            Contract.Requires(file == null || fileSize > 0);
            Contract.Requires(file != null || (fileSize == 0 && fileOffset == 0));
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            if (memorySize <= 0 || Arch.ArchDefinition.PageOffset(memorySize) != 0)
                return -ErrorCode.EINVAL;

            var diff = Arch.ArchDefinition.PageOffset(vaddr.ToUInt32());
            if (diff != 0)
                return -ErrorCode.EINVAL;

            var r = RemoveMapping(vaddr, memorySize);
            if (r != 0)
            {
                return r;
            }

            var newRegion = new MemoryRegion(GhostOwner, access, flags, file, fileOffset, fileSize, vaddr, memorySize, false);
            Insert(newRegion);
            return 0;
        }
Exemple #2
0
        // Create an empty user-space memory region
        // reserve the first page as well as the kernel space
        public static MemoryRegion CreateUserSpaceRegion(Process owner)
        {
            Contract.Ensures(Contract.Result<MemoryRegion>().GhostOwner == owner);

            var r = new MemoryRegion(owner, 0, 0, null, 0, 0, Pointer.Zero, Arch.ArchDefinition.PageSize, true);
            var r1 = new MemoryRegion(owner, 0, 0, null, 0, 0, new Pointer(AddressSpace.KERNEL_OFFSET), AddressSpace.KERNEL_SIZE, true);
            r.Next = r1;
            return r;
        }
        internal MemoryRegion(Process owner, uint access, int flags, File file, uint fileOffset, int fileSize, Pointer vaddr, int size, bool isFixed)
        {
            Contract.Requires(file == null || file.GhostOwner == owner);
            Contract.Ensures(GhostOwner == owner);

            this.Access = access;
            this.Flags = flags;
            this.BackingFile = file;
            this.FileOffset = fileOffset;
            this.FileSize = fileSize;
            this.StartAddress = vaddr;
            this.Size = size;
            this.Next = null;
            this.IsFixed = isFixed;
            this.GhostOwner = owner;

            if (file != null)
                file.inode.IncreaseRefCount();
        }
        private void RemoveMappingCenter(Pointer vaddr, int size, ref MemoryRegion prev, out int ret, out bool changed)
        {
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            changed = false;
            var r = prev.Next;
            var end = vaddr + size;
            while (r != null && !r.IsFixed && r.End <= end)
            {
                changed = true;
                RemoveNode(prev, r);
                r = prev.Next;
            }
            if (r != null && r.End <= end && r.IsFixed)
            {
                ret = -ErrorCode.EINVAL;
                return;
            }

            if (r == null || r.StartAddress >= end)
            {
                ret = 0;
                return;
            }
            ret = 1;
            return;
        }
        void InsertOrMerge(MemoryRegion prev, MemoryRegion r, MemoryRegion next)
        {
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            if (MemoryRegion.CanMerge(prev, r))
            {
                prev.Expand(r);
                return;
            }

            InsertNode(prev, r);
            TryMergeWithNext(r);
        }
        void InsertNode(MemoryRegion prev, MemoryRegion r)
        {
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            r.Next = prev.Next;
            prev.Next = r;
        }
        void Insert(MemoryRegion r)
        {
            Contract.Requires(r != null && r.GhostOwner == GhostOwner);
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            var h = Head.Next;
            var prev = Head;

            while (h != null && h.End <= r.StartAddress)
            {
                prev = h;
                h = h.Next;
            }
            InsertOrMerge(prev, r, h);
            return;
        }
        internal static bool CanMerge(MemoryRegion prev, MemoryRegion next)
        {
            var same_inode = (prev.BackingFile == next.BackingFile ||
                (prev.BackingFile != null && next.BackingFile != null
                && prev.BackingFile.inode == next.BackingFile.inode));

            return same_inode
                    && prev.Access == next.Access
                    && prev.End == next.StartAddress
                    && (prev.BackingFile == null || prev.FileEnd == next.FileOffset);
        }
 void UpdateAccessRights(MemoryRegion r, uint newaccess)
 {
     r.UpdateAccessRights(this, newaccess);
 }
        //
        // Separate region into two. It returns the rightmost part of the region
        //
        MemoryRegion Split(MemoryRegion r, int offset)
        {
            Contract.Requires(r.BackingFile == null || r.BackingFile.GhostOwner == r.GhostOwner);
            //Contract.Ensures(Contract.Result<MemoryRegion>().BackingFile.GhostOwner == Contract.Result<MemoryRegion>().GhostOwner);
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            MemoryRegion next;
            if (offset >= r.FileSize)
            {
                next = new MemoryRegion(r.GhostOwner, r.Access, r.Flags, null, 0, 0, r.StartAddress + offset, r.Size - offset, r.IsFixed);
            }
            else
            {
                next = new MemoryRegion(r.GhostOwner, r.Access, r.Flags, r.BackingFile, (uint)(r.FileOffset + (uint)offset),
                    (int)(r.FileSize - offset), r.StartAddress + offset, r.Size - offset, r.IsFixed);
            }

            r.CutRight(r.Size - offset);
            InsertNode(r, next);
            return next;
        }
Exemple #11
0
 void InsertNode(MemoryRegion prev, MemoryRegion r)
 {
     r.Next = prev.Next;
     prev.Next = r;
 }
Exemple #12
0
        private static Pointer ToShadowProcessAddress(Pointer faultAddress, MemoryRegion region)
        {
            var f = region.BackingFile;
            Pointer vaddr = Pointer.Zero;
            switch (f.inode.kind)
            {
                case GenericINode.INodeKind.BinderSharedINodeKind:
                case GenericINode.INodeKind.ScreenBufferINodeKind:
                case GenericINode.INodeKind.AshmemINodeKind:
                    vaddr = f.inode.AlienSharedMemoryINode.vaddrInShadowProcess;
                    break;

                default:
                    Arch.ArchDefinition.Panic();
                    break;
            }
            return vaddr + (faultAddress - region.StartAddress);
        }
Exemple #13
0
        private static bool IsAlienSharedRegion(MemoryRegion region)
        {
            if ((region.Flags & Memory.MAP_SHARED) == 0)
                return false;

            if (region.BackingFile == null)
                return false;

            return region.BackingFile.inode.kind == GenericINode.INodeKind.BinderSharedINodeKind
                || region.BackingFile.inode.kind == GenericINode.INodeKind.AshmemINodeKind
                || region.BackingFile.inode.kind == GenericINode.INodeKind.ScreenBufferINodeKind;
        }
 internal void Expand(MemoryRegion r)
 {
     Size += r.Size;
     if (BackingFile != null)
         FileSize += r.FileSize;
 }
        private void RemoveMappingLeft(Pointer vaddr, int size, out int ret, out bool changed, out MemoryRegion prev)
        {
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            prev = Head;
            var r = prev.Next;
            var end = vaddr + size;
            var oldBrk = Brk;

            if (Head.OverlappedInt(vaddr, size))
            {
                ret = -ErrorCode.EINVAL;
                changed = false;
                return;
            }

            while (r != null && r.End <= vaddr)
            {
                prev = r;
                r = r.Next;
            }

            // No overlaps
            if (r == null || r.StartAddress >= end)
            {
                ret = 0;
                changed = false;
                return;
            }

            if (r.IsFixed)
            {
                ret = -ErrorCode.EINVAL;
                changed = false;
                return;
            }

            if (r.StartAddress < vaddr)
            {
                if (end < r.End)
                {
                    var offset = vaddr - r.StartAddress;
                    var middleRegion = Split(r, offset);
                }
                else
                {
                    r.CutRight(r.End - vaddr);
                }
                prev = r;
                r = r.Next;
                ret = 1;
                changed = true;
                Contract.Assert(Brk == oldBrk);
                return;
            }
            ret = 1;
            changed = false;
            return;
        }
        void RemoveNode(MemoryRegion prev, MemoryRegion r)
        {
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            prev.Next = r.Next;
        }
Exemple #17
0
        void InsertOrMerge(MemoryRegion prev, MemoryRegion r, MemoryRegion next)
        {
            if (MemoryRegion.CanMerge(prev, r))
            {
                prev.Expand(r);
                return;
            }

            InsertNode(prev, r);
            TryMergeWithNext(r);
        }
        bool TryMergeWithNext(MemoryRegion r)
        {
            Contract.Ensures(Brk == Contract.OldValue(Brk));

            var next = r.Next;
            if (next != null && MemoryRegion.CanMerge(r, next))
            {
                RemoveNode(r, next);
                r.Expand(next);
                return true;
            }
            else
            {
                return false;
            }
        }
Exemple #19
0
 void RemoveNode(MemoryRegion prev, MemoryRegion r)
 {
     prev.Next = r.Next;
 }
Exemple #20
0
 bool TryMergeWithNext(MemoryRegion r)
 {
     var next = r.Next;
     if (next != null && MemoryRegion.CanMerge(r, next))
     {
         RemoveNode(r, next);
         r.Expand(next);
         return true;
     }
     else
     {
         return false;
     }
 }
 public bool Overlapped(MemoryRegion rhs)
 {
     return OverlappedInt(rhs.StartAddress, rhs.Size);
 }