Author: ion
Date: Sun Sep 2 01:17:42 2012
New Revision: 57215
URL: http://svn.reactos.org/svn/reactos?rev=57215&view=rev
Log:
[NTOSKRNL]: Do not return data in failure cases in NtProtectVirtualMemory.
[NTOSKRNL]: No longer support non-ARM3 sections in NtProtectVirtualMemory, as the only OS calls were already NO-OPS.
[NTOSKRNL]: Always use ARM3 sections unless SEC_PHYSICAL_MEMORY is used, and make the check explicit.
[NTOSKRNL]: No longer support allocating memory on top of non-ARM3 sections.
[NTOSKRNL]: No longer ASSERT when certain features are not yet implemented, instead return an error code.
[NTOSKRNL]: Add another check in NtFreevirtualMemory when invalid memory is being freed, insert of ASSERTing.
[NTOSKRNL]: Implement and use MiIsEntireRangeCommitted when protecting memory to make sure the entire range is committed.
This patch removes multiple hacks, ASSERTs, and evil mixing of ARM3 and non-ARM3 code/memory.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/section.c
trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sun Sep 2 01:17:42 2012
@@ -2009,20 +2009,6 @@
NTSTATUS
NTAPI
-MiRosAllocateVirtualMemory(
- IN HANDLE ProcessHandle,
- IN PEPROCESS Process,
- IN PMEMORY_AREA MemoryArea,
- IN PMMSUPPORT AddressSpace,
- IN OUT PVOID* UBaseAddress,
- IN BOOLEAN Attached,
- IN OUT PSIZE_T URegionSize,
- IN ULONG AllocationType,
- IN ULONG Protect
-);
-
-NTSTATUS
-NTAPI
MiRosUnmapViewInSystemSpace(
IN PVOID MappedBase
);
Modified: trunk/reactos/ntoskrnl/mm/ARM3/section.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/section.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/section.c [iso-8859-1] Sun Sep 2 01:17:42 2012
@@ -2217,7 +2217,6 @@
/* Yep, use the entered size */
Section.SizeOfSection.QuadPart = InputMaximumSize->QuadPart;
}
-
}
else
{
Modified: trunk/reactos/ntoskrnl/mm/ARM3/virtual.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/virtual.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/virtual.c [iso-8859-1] Sun Sep 2 01:17:42 2012
@@ -1749,6 +1749,82 @@
return Status;
}
+ULONG
+NTAPI
+MiIsEntireRangeCommitted(IN ULONG_PTR StartingAddress,
+ IN ULONG_PTR EndingAddress,
+ IN PMMVAD Vad,
+ IN PEPROCESS Process)
+{
+ PMMPTE PointerPte, LastPte, PointerPde;
+ BOOLEAN OnBoundary = TRUE;
+ PAGED_CODE();
+
+ /* Get the PDE and PTE addresses */
+ PointerPde = MiAddressToPde(StartingAddress);
+ PointerPte = MiAddressToPte(StartingAddress);
+ LastPte = MiAddressToPte(EndingAddress);
+
+ /* Loop all the PTEs */
+ while (PointerPte <= LastPte)
+ {
+ /* Check if we've hit an new PDE boundary */
+ if (OnBoundary)
+ {
+ /* Is this PDE demand zero? */
+ PointerPde = MiAddressToPte(PointerPte);
+ if (PointerPde->u.Long != 0)
+ {
+ /* It isn't -- is it valid? */
+ if (PointerPde->u.Hard.Valid == 0)
+ {
+ /* Nope, fault it in */
+ PointerPte = MiPteToAddress(PointerPde);
+ MiMakeSystemAddressValid(PointerPte, Process);
+ }
+ }
+ else
+ {
+ /* The PTE was already valid, so move to the next one */
+ PointerPde++;
+ PointerPte = MiPteToAddress(PointerPde);
+
+ /* Is the entire VAD committed? If not, fail */
+ if (!Vad->u.VadFlags.MemCommit) return FALSE;
+
+ /* Everything is committed so far past the range, return true */
+ if (PointerPte > LastPte) return TRUE;
+ }
+ }
+
+ /* Is the PTE demand zero? */
+ if (PointerPte->u.Long == 0)
+ {
+ /* Is the entire VAD committed? If not, fail */
+ if (!Vad->u.VadFlags.MemCommit) return FALSE;
+ }
+ else
+ {
+ /* It isn't -- is it a decommited, invalid, or faulted PTE? */
+ if ((PointerPte->u.Soft.Protection == MM_DECOMMIT) &&
+ (PointerPte->u.Hard.Valid == 0) &&
+ ((PointerPte->u.Soft.Prototype == 0) ||
+ (PointerPte->u.Soft.PageFileHigh == MI_PTE_LOOKUP_NEEDED)))
+ {
+ /* Then part of the range is decommitted, so fail */
+ return FALSE;
+ }
+ }
+
+ /* Move to the next PTE */
+ PointerPte++;
+ OnBoundary = MiIsPteOnPdeBoundary(PointerPte);
+ }
+
+ /* All PTEs seem valid, and no VAD checks failed, the range is okay */
+ return TRUE;
+}
+
NTSTATUS
NTAPI
MiProtectVirtualMemory(IN PEPROCESS Process,
@@ -1765,19 +1841,9 @@
MMPTE PteContents;
//PUSHORT UsedPageTableEntries;
PMMPFN Pfn1;
- ULONG ProtectionMask;
+ ULONG ProtectionMask, OldProtect;
+ BOOLEAN Committed;
NTSTATUS Status = STATUS_SUCCESS;
-
- /* Check for ROS specific memory area */
- MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, *BaseAddress);
- if ((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW))
- {
- return MiRosProtectVirtualMemory(Process,
- BaseAddress,
- NumberOfBytesToProtect,
- NewAccessProtection,
- OldAccessProtection);
- }
/* Calcualte base address for the VAD */
StartingAddress = (ULONG_PTR)PAGE_ALIGN((*BaseAddress));
@@ -1838,10 +1904,53 @@
goto FailPath;
}
+ /* Check for ROS specific memory area */
+ MemoryArea = MmLocateMemoryAreaByAddress(&Process->Vm, *BaseAddress);
+ if ((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW))
+ {
+ /* Empirical evidence suggests this is only used in one critical scenario and is always a no-op */
+ OldProtect = NewAccessProtection;
+ goto RosReturn;
+ }
+
+ /* Is this section, or private memory? */
if (Vad->u.VadFlags.PrivateMemory == 0)
{
- /* This is a section, handled by the ROS specific code above */
- UNIMPLEMENTED;
+ /* Not yet supported */
+ if (Vad->u.VadFlags.VadType == VadLargePageSection)
+ {
+ DPRINT1("Illegal VAD for attempting to set protection\n");
+ Status = STATUS_CONFLICTING_ADDRESSES;
+ goto FailPath;
+ }
+
+ /* Rotate VADs are not yet supported */
+ if (Vad->u.VadFlags.VadType == VadRotatePhysical)
+ {
+ DPRINT1("Illegal VAD for attempting to set protection\n");
+ Status = STATUS_CONFLICTING_ADDRESSES;
+ goto FailPath;
+ }
+
+ /* Not valid on section files */
+ if (NewAccessProtection & (PAGE_NOCACHE | PAGE_WRITECOMBINE))
+ {
+ /* Fail */
+ DPRINT1("Invalid protection flags for section\n");
+ Status = STATUS_INVALID_PARAMETER_4;
+ goto FailPath;
+ }
+
+ /* Check if data or page file mapping protection PTE is compatible */
+ if (!Vad->ControlArea->u.Flags.Image)
+ {
+ /* Not yet */
+ DPRINT1("Fixme: Not checking for valid protection\n");
+ }
+
+ /* This is a section, and this is not yet supported */
+ DPRINT1("Section protection not yet supported\n");
+ OldProtect = 0;
}
else
{
@@ -1849,13 +1958,26 @@
if ((NewAccessProtection & PAGE_WRITECOPY) ||
(NewAccessProtection & PAGE_EXECUTE_WRITECOPY))
{
+ DPRINT1("Invalid protection flags for private memory\n");
Status = STATUS_INVALID_PARAMETER_4;
goto FailPath;
}
//MiLockProcessWorkingSet(Thread, Process);
- /* TODO: Check if all pages in this range are committed */
+ /* Check if all pages in this range are committed */
+ Committed = MiIsEntireRangeCommitted(StartingAddress,
+ EndingAddress,
+ Vad,
+ Process);
+ if (!Committed)
+ {
+ /* Fail */
+ DPRINT1("The entire range is not committed\n");
+ Status = STATUS_NOT_COMMITTED;
+ //MiUnlockProcessWorkingSet(Thread, Process);
+ goto FailPath;
+ }
/* Compute starting and ending PTE and PDE addresses */
PointerPde = MiAddressToPde(StartingAddress);
@@ -1869,13 +1991,13 @@
if (PointerPte->u.Long != 0)
{
/* Capture the page protection and make the PDE valid */
- *OldAccessProtection = MiGetPageProtection(PointerPte);
+ OldProtect = MiGetPageProtection(PointerPte);
MiMakePdeExistAndMakeValid(PointerPde, Process, MM_NOIRQL);
}
else
{
/* Grab the old protection from the VAD itself */
- *OldAccessProtection = MmProtectToValue[Vad->u.VadFlags.Protection];
+ OldProtect = MmProtectToValue[Vad->u.VadFlags.Protection];
}
/* Loop all the PTEs now */
@@ -1911,19 +2033,18 @@
if ((NewAccessProtection & PAGE_NOACCESS) ||
(NewAccessProtection & PAGE_GUARD))
{
- /* TODO */
+ /* The page should be in the WS and we should make it transition now */
UNIMPLEMENTED;
+ //continue;
}
- else
- {
- /* Write the protection mask and write it with a TLB flush */
- Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
- MiFlushTbAndCapture(Vad,
- PointerPte,
- ProtectionMask,
- Pfn1,
- TRUE);
- }
+
+ /* Write the protection mask and write it with a TLB flush */
+ Pfn1->OriginalPte.u.Soft.Protection = ProtectionMask;
+ MiFlushTbAndCapture(Vad,
+ PointerPte,
+ ProtectionMask,
+ Pfn1,
+ TRUE);
}
else
{
@@ -1933,23 +2054,29 @@
/* The PTE is already demand-zero, just update the protection mask */
PointerPte->u.Soft.Protection = ProtectionMask;
- }
-
+ ASSERT(PointerPte->u.Long != 0);
+ }
+
+ /* Move to the next PTE */
PointerPte++;
}
- /* Unlock the working set and update quota charges if needed, then return */
+ /* Unlock the working set */
//MiUnlockProcessWorkingSet(Thread, Process);
}
-
-FailPath:
+RosReturn:
/* Unlock the address space */
MmUnlockAddressSpace(AddressSpace);
- /* Return parameters */
- *NumberOfBytesToProtect = (SIZE_T)((PUCHAR)EndingAddress - (PUCHAR)StartingAddress + 1);
+ /* Return parameters and success */
+ *NumberOfBytesToProtect = EndingAddress - StartingAddress + 1;
*BaseAddress = (PVOID)StartingAddress;
-
+ *OldAccessProtection = OldProtect;
+ return STATUS_SUCCESS;
+
+FailPath:
+ /* Unlock the address space and return the failure code */
+ MmUnlockAddressSpace(AddressSpace);
return Status;
}
@@ -3668,15 +3795,50 @@
}
//
- // Assert on the things we don't yet support
- //
- ASSERT(ZeroBits == 0);
- ASSERT((AllocationType & MEM_LARGE_PAGES) == 0);
- ASSERT((AllocationType & MEM_PHYSICAL) == 0);
- ASSERT((AllocationType & MEM_WRITE_WATCH) == 0);
- ASSERT((AllocationType & MEM_TOP_DOWN) == 0);
- ASSERT((AllocationType & MEM_RESET) == 0);
- ASSERT(Process->VmTopDown == 0);
+ // Fail on the things we don't yet support
+ //
+ if (ZeroBits != 0)
+ {
+ DPRINT1("Zero bits not supported\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto FailPathNoLock;
+ }
+ if ((AllocationType & MEM_LARGE_PAGES) == 1)
+ {
+ DPRINT1("MEM_LARGE_PAGES not supported\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto FailPathNoLock;
+ }
+ if ((AllocationType & MEM_PHYSICAL) == 1)
+ {
+ DPRINT1("MEM_PHYSICAL not supported\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto FailPathNoLock;
+ }
+ if ((AllocationType & MEM_WRITE_WATCH) == 1)
+ {
+ DPRINT1("MEM_WRITE_WATCH not supported\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto FailPathNoLock;
+ }
+ if ((AllocationType & MEM_TOP_DOWN) == 1)
+ {
+ DPRINT1("MEM_TOP_DOWN not supported\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto FailPathNoLock;
+ }
+ if ((AllocationType & MEM_RESET) == 1)
+ {
+ DPRINT1("MEM_RESET not supported\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto FailPathNoLock;
+ }
+ if (Process->VmTopDown == 1)
+ {
+ DPRINT1("VmTopDown not supported\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto FailPathNoLock;
+ }
//
// Check if the caller is reserving memory, or committing memory and letting
@@ -3895,24 +4057,10 @@
}
//
- // If this is an existing section view, we call the old RosMm routine which
- // has the relevant code required to handle the section scenario. In the future
- // we will limit this even more so that there's almost nothing that the code
- // needs to do, and it will become part of section.c in RosMm
+ // Make sure this is an ARM3 section
//
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)PAGE_ROUND_DOWN(PBaseAddress));
- if (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)
- {
- return MiRosAllocateVirtualMemory(ProcessHandle,
- Process,
- MemoryArea,
- AddressSpace,
- UBaseAddress,
- Attached,
- URegionSize,
- AllocationType,
- Protect);
- }
+ ASSERT(MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3);
// Is this a previously reserved section being committed? If so, enter the
// special section path
@@ -4324,12 +4472,21 @@
}
//
- // These ASSERTs are here because ReactOS ARM3 does not currently implement
- // any other kinds of VADs.
- //
- ASSERT(Vad->u.VadFlags.PrivateMemory == 1);
+ // Only private memory (except rotate VADs) can be freed through here */
+ //
+ if ((!(Vad->u.VadFlags.PrivateMemory) &&
+ (Vad->u.VadFlags.VadType != VadRotatePhysical)) ||
+ (Vad->u.VadFlags.VadType == VadDevicePhysicalMemory))
+ {
+ DPRINT1("Attempt to free section memory\n");
+ Status = STATUS_UNABLE_TO_DELETE_SECTION;
+ goto FailPath;
+ }
+
+ //
+ // ARM3 does not yet handle protected VM
+ //
ASSERT(Vad->u.VadFlags.NoChange == 0);
- ASSERT(Vad->u.VadFlags.VadType == VadNone);
//
// Finally, make sure there is a ReactOS Mm MEMORY_AREA for this allocation
@@ -4345,6 +4502,11 @@
//
if (FreeType & MEM_RELEASE)
{
+ //
+ // ARM3 only supports this VAD in this path
+ //
+ ASSERT(Vad->u.VadFlags.VadType == VadNone);
+
//
// Is the caller trying to remove the whole VAD, or remove only a portion
// of it? If no region size is specified, then the assumption is that the
Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Sun Sep 2 01:17:42 2012
@@ -2716,7 +2716,7 @@
&Obj,
&SectionSize,
PAGE_EXECUTE_READWRITE,
- 0,
+ SEC_PHYSICALMEMORY,
NULL,
NULL);
if (!NT_SUCCESS(Status))
@@ -4860,7 +4860,7 @@
PROS_SECTION_OBJECT *SectionObject = (PROS_SECTION_OBJECT *)Section;
/* Check if an ARM3 section is being created instead */
- if (!(AllocationAttributes & SEC_IMAGE) && (AllocationAttributes))
+ if (!(AllocationAttributes & (SEC_IMAGE | SEC_PHYSICALMEMORY)))
{
if (!(FileObject) && !(FileHandle))
{
@@ -4986,6 +4986,7 @@
#endif
else
{
+ ASSERT(AllocationAttributes & SEC_PHYSICALMEMORY);
Status = MmCreatePageFileSection(SectionObject,
DesiredAccess,
ObjectAttributes,
@@ -4997,133 +4998,4 @@
return Status;
}
-VOID
-MmModifyAttributes(IN PMMSUPPORT AddressSpace,
- IN PVOID BaseAddress,
- IN SIZE_T RegionSize,
- IN ULONG OldType,
- IN ULONG OldProtect,
- IN ULONG NewType,
- IN ULONG NewProtect)
-{
- //
- // This function is deprecated but remains in order to support VirtualAlloc
- // calls with MEM_COMMIT on top of MapViewOfFile calls with SEC_RESERVE.
- //
- // Win32k's shared user heap, for example, uses that mechanism. The two
- // conditions when this function needs to do something are ASSERTed for,
- // because they should not arise.
- //
- if (NewType == MEM_RESERVE && OldType == MEM_COMMIT)
- {
- ASSERT(FALSE);
- }
-
- if ((NewType == MEM_COMMIT) && (OldType == MEM_COMMIT))
- {
- ASSERT(OldProtect == NewProtect);
- }
-}
-
-NTSTATUS
-NTAPI
-MiRosAllocateVirtualMemory(IN HANDLE ProcessHandle,
- IN PEPROCESS Process,
- IN PMEMORY_AREA MemoryArea,
- IN PMMSUPPORT AddressSpace,
- IN OUT PVOID* UBaseAddress,
- IN BOOLEAN Attached,
- IN OUT PSIZE_T URegionSize,
- IN ULONG AllocationType,
- IN ULONG Protect)
-{
- ULONG_PTR PRegionSize;
- ULONG Type, RegionSize;
- NTSTATUS Status;
- PVOID PBaseAddress, BaseAddress;
- KAPC_STATE ApcState;
-
- PBaseAddress = *UBaseAddress;
- PRegionSize = *URegionSize;
-
- BaseAddress = (PVOID)PAGE_ROUND_DOWN(PBaseAddress);
- RegionSize = PAGE_ROUND_UP((ULONG_PTR)PBaseAddress + PRegionSize) -
- PAGE_ROUND_DOWN(PBaseAddress);
- Type = (AllocationType & MEM_COMMIT) ? MEM_COMMIT : MEM_RESERVE;
-
- ASSERT(PBaseAddress != 0);
- ASSERT(Type == MEM_COMMIT);
- ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW);
- ASSERT(((ULONG_PTR)BaseAddress + RegionSize) <= (ULONG_PTR)MemoryArea->EndingAddress);
- ASSERT(((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress) >= RegionSize);
- ASSERT(MemoryArea->Data.SectionData.RegionListHead.Flink);
-
- Status = MmAlterRegion(AddressSpace,
- MemoryArea->StartingAddress,
- &MemoryArea->Data.SectionData.RegionListHead,
- BaseAddress,
- RegionSize,
- Type,
- Protect,
- MmModifyAttributes);
-
- MmUnlockAddressSpace(AddressSpace);
- if (Attached) KeUnstackDetachProcess(&ApcState);
- if (ProcessHandle != NtCurrentProcess()) ObDereferenceObject(Process);
- if (NT_SUCCESS(Status))
- {
- *UBaseAddress = BaseAddress;
- *URegionSize = RegionSize;
- }
-
- return Status;
-}
-
-NTSTATUS
-NTAPI
-MiRosProtectVirtualMemory(IN PEPROCESS Process,
- IN OUT PVOID *BaseAddress,
- IN OUT PSIZE_T NumberOfBytesToProtect,
- IN ULONG NewAccessProtection,
- OUT PULONG OldAccessProtection OPTIONAL)
-{
- PMEMORY_AREA MemoryArea;
- PMMSUPPORT AddressSpace;
- ULONG OldAccessProtection_;
- NTSTATUS Status;
-
- *NumberOfBytesToProtect = PAGE_ROUND_UP((ULONG_PTR)(*BaseAddress) + (*NumberOfBytesToProtect)) - PAGE_ROUND_DOWN(*BaseAddress);
- *BaseAddress = (PVOID)PAGE_ROUND_DOWN(*BaseAddress);
-
- AddressSpace = &Process->Vm;
- MmLockAddressSpace(AddressSpace);
- MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, *BaseAddress);
- if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
- {
- MmUnlockAddressSpace(AddressSpace);
- return STATUS_UNSUCCESSFUL;
- }
-
- if (OldAccessProtection == NULL) OldAccessProtection = &OldAccessProtection_;
-
- if (MemoryArea->Type == MEMORY_AREA_SECTION_VIEW)
- {
- Status = MmProtectSectionView(AddressSpace,
- MemoryArea,
- *BaseAddress,
- *NumberOfBytesToProtect,
- NewAccessProtection,
- OldAccessProtection);
- }
- else
- {
- /* FIXME: Should we return failure or success in this case? */
- Status = STATUS_CONFLICTING_ADDRESSES;
- }
-
- MmUnlockAddressSpace(AddressSpace);
-
- return Status;
-}
-
/* EOF */
Author: tkreuzer
Date: Sat Sep 1 17:01:05 2012
New Revision: 57214
URL: http://svn.reactos.org/svn/reactos?rev=57214&view=rev
Log:
[INTRIN]
Mark intrinsics on gcc with __attribute__((artificial)) so that they appear as one unit in the debug info. This way traces don't point inside the implementations, when they cause an eception, but rather to the line where they are used.
Modified:
trunk/reactos/include/crt/mingw32/intrin.h
Modified: trunk/reactos/include/crt/mingw32/intrin.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/crt/mingw32/intrin…
==============================================================================
--- trunk/reactos/include/crt/mingw32/intrin.h [iso-8859-1] (original)
+++ trunk/reactos/include/crt/mingw32/intrin.h [iso-8859-1] Sat Sep 1 17:01:05 2012
@@ -30,8 +30,14 @@
#ifndef RC_INVOKED
+#ifdef __clang__
+#define __ATTRIBUTE_ARTIFICIAL
+#else
+#define __ATTRIBUTE_ARTIFICIAL __attribute__((artificial))
+#endif
+
#define _PRAGMA_WARNING_SUPPRESS(x) /* Only for MSVC */
-#define __INTRIN_INLINE extern __inline__ __attribute__((__always_inline__,__gnu_inline__))
+#define __INTRIN_INLINE extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) __ATTRIBUTE_ARTIFICIAL
#ifndef _SIZE_T_DEFINED
#define _SIZE_T_DEFINED