Author: jgardou
Date: Sat Aug 27 13:17:10 2016
New Revision: 72472
URL: http://svn.reactos.org/svn/reactos?rev=72472&view=rev
Log:
[NTOS/MM]
- Keep the control area as being created through the whole creation process in MmCreateArm3Section
- Use the segment length to find a suitable place for SEC_BASED sections
- Properly remove the global section node when deleting a based section
CORE-11900 #resolve
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/section.c
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] Sat Aug 27 13:17:10 2016
@@ -1564,6 +1564,9 @@
if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
+ /* We just allocated it */
+ ControlArea->u.Flags.BeingCreated = 1;
+
/* The subsection follows, write the mask, PTE count and point back to the CA */
Subsection = (PSUBSECTION)(ControlArea + 1);
Subsection->ControlArea = ControlArea;
@@ -2565,6 +2568,7 @@
/* Set the size here, and read the control area */
Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
ControlArea = NewSegment->ControlArea;
+ ASSERT(ControlArea->u.Flags.BeingCreated == 1);
}
/* Did we already have a segment? */
@@ -2663,6 +2667,60 @@
ASSERT(KernelCall == FALSE);
NewSection->u.Flags.UserReference = TRUE;
+ /* Is this a "based" allocation, in which all mappings are identical? */
+ if (AllocationAttributes & SEC_BASED)
+ {
+ /* Lock the VAD tree during the search */
+ KeAcquireGuardedMutex(&MmSectionBasedMutex);
+
+ /* Is it a brand new ControArea ? */
+ if (ControlArea->u.Flags.BeingCreated == 1)
+ {
+ ASSERT(ControlArea->u.Flags.Based == 1);
+ /* Then we must find a global address, top-down */
+ Status = MiFindEmptyAddressRangeDownBasedTree((SIZE_T)ControlArea->Segment->SizeOfSegment,
+ (ULONG_PTR)MmHighSectionBase,
+ _64K,
+ &MmSectionBasedRoot,
+ (ULONG_PTR*)&ControlArea->Segment->BasedAddress);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* No way to find a valid range. */
+ KeReleaseGuardedMutex(&MmSectionBasedMutex);
+ ControlArea->u.Flags.Based = 0;
+ NewSection->u.Flags.Based = 0;
+ ObDereferenceObject(NewSection);
+ return Status;
+ }
+
+ /* Compute the ending address and insert it into the VAD tree */
+ NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
+ NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
+ MiInsertBasedSection(NewSection);
+ }
+ else
+ {
+ /* FIXME : Should we deny section creation if SEC_BASED is not set ? Can we have two different section objects on the same based address ? Investigate !*/
+ ASSERT(FALSE);
+ }
+
+ KeReleaseGuardedMutex(&MmSectionBasedMutex);
+ }
+
+ /* The control area is not being created anymore */
+ if (ControlArea->u.Flags.BeingCreated == 1)
+ {
+ /* Acquire the PFN lock while we set control area flags */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Take off the being created flag, and then release the lock */
+ ControlArea->u.Flags.BeingCreated = 0;
+ NewSection->u.Flags.BeingCreated = 0;
+
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ }
+
/* Migrate the attribute into a flag */
if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
@@ -2670,40 +2728,6 @@
if (!(SectionPageProtection & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)))
{
NewSection->u.Flags.CopyOnWrite = TRUE;
- }
-
- /* Is this a "based" allocation, in which all mappings are identical? */
- if (AllocationAttributes & SEC_BASED)
- {
- /* Convert the flag, and make sure the section isn't too big */
- NewSection->u.Flags.Based = TRUE;
- if ((ULONGLONG)NewSection->SizeOfSection.QuadPart >
- (ULONG_PTR)MmHighSectionBase)
- {
- DPRINT1("BASED section is too large\n");
- ObDereferenceObject(NewSection);
- return STATUS_NO_MEMORY;
- }
-
- /* Lock the VAD tree during the search */
- KeAcquireGuardedMutex(&MmSectionBasedMutex);
-
- /* Find an address top-down */
- Status = MiFindEmptyAddressRangeDownBasedTree(NewSection->SizeOfSection.LowPart,
- (ULONG_PTR)MmHighSectionBase,
- _64K,
- &MmSectionBasedRoot,
- &NewSection->Address.StartingVpn);
- ASSERT(NT_SUCCESS(Status));
-
- /* Compute the ending address and insert it into the VAD tree */
- NewSection->Address.EndingVpn = NewSection->Address.StartingVpn +
- NewSection->SizeOfSection.LowPart -
- 1;
- MiInsertBasedSection(NewSection);
-
- /* Finally release the lock */
- KeReleaseGuardedMutex(&MmSectionBasedMutex);
}
/* Write down if this was a kernel call */
@@ -3141,6 +3165,14 @@
KIRQL OldIrql;
SectionObject = (PSECTION)ObjectBody;
+
+ if (SectionObject->u.Flags.Based == 1)
+ {
+ /* Remove the node from the global section address tree */
+ KeAcquireGuardedMutex(&MmSectionBasedMutex);
+ MiRemoveNode(&SectionObject->Address, &MmSectionBasedRoot);
+ KeReleaseGuardedMutex(&MmSectionBasedMutex);
+ }
/* Lock the PFN database */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
Author: jgardou
Date: Fri Aug 26 21:07:27 2016
New Revision: 72467
URL: http://svn.reactos.org/svn/reactos?rev=72467&view=rev
Log:
[KDGDB]
- Add a ugly and grotesque hack to give "o" back to RtlAssert so that we actually break on ASSERTs
- Check for the breakpoint instruction for deciding when to move forward the ProgramCounter. This is OK since KD removes all breakpoints set when hitting a soft BP
Modified:
trunk/reactos/drivers/base/kdgdb/gdb_input.c
trunk/reactos/drivers/base/kdgdb/kdgdb.h
trunk/reactos/drivers/base/kdgdb/kdpacket.c
Modified: trunk/reactos/drivers/base/kdgdb/gdb_input.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/gdb_inp…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/gdb_input.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/gdb_input.c [iso-8859-1] Fri Aug 26 21:07:27 2016
@@ -830,7 +830,7 @@
/* See if we should update the program counter */
if (Exception && (Exception->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT)
- && ProgramCounter == KdDebuggerDataBlock->BreakpointWithStatus.Pointer)
+ && ((*(KD_BREAKPOINT_TYPE*)ProgramCounter) == KD_BREAKPOINT_VALUE))
{
/* We must get past the breakpoint instruction */
KdpSetContextPc(&CurrentContext, ProgramCounter + KD_BREAKPOINT_SIZE);
Modified: trunk/reactos/drivers/base/kdgdb/kdgdb.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdgdb.h…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/kdgdb.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/kdgdb.h [iso-8859-1] Fri Aug 26 21:07:27 2016
@@ -121,7 +121,9 @@
((Context)->Eip)
# define KdpSetContextPc(Context, ProgramCounter) \
((Context)->Eip = (ProgramCounter))
+# define KD_BREAKPOINT_TYPE UCHAR
# define KD_BREAKPOINT_SIZE sizeof(UCHAR)
+# define KD_BREAKPOINT_VALUE 0xCC
/* Single step mode */
# define KdpSetSingleStep(Context) \
((Context)->EFlags |= EFLAGS_TF)
Modified: trunk/reactos/drivers/base/kdgdb/kdpacket.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/base/kdgdb/kdpacke…
==============================================================================
--- trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/base/kdgdb/kdpacket.c [iso-8859-1] Fri Aug 26 21:07:27 2016
@@ -183,6 +183,7 @@
switch (DebugIO->ApiNumber)
{
case DbgKdPrintStringApi:
+ case DbgKdGetStringApi:
gdb_send_debug_io(String, TRUE);
break;
default:
@@ -362,28 +363,34 @@
_Out_ PULONG DataLength,
_Inout_ PKD_CONTEXT KdContext)
{
- DBGKD_MANIPULATE_STATE64* State;
-
- /* Special handling for breakin packet */
if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
{
return KdpPollBreakIn();
}
- if (PacketType != PACKET_TYPE_KD_STATE_MANIPULATE)
- {
- /* What should we do ? */
- while (1);
- }
-
- State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
-
- /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */
- if (KdpManipulateStateHandler != NULL)
- return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext);
-
- /* Receive data from GDB and interpret it */
- return gdb_receive_and_interpret_packet(State, MessageData, DataLength, KdContext);
+ if (PacketType == PACKET_TYPE_KD_DEBUG_IO)
+ {
+ /* HACK ! RtlAssert asks for (boipt), always say "o" --> break once. */
+ MessageData->Length = 1;
+ MessageData->Buffer[0] = 'o';
+ return KdPacketReceived;
+ }
+
+ if (PacketType == PACKET_TYPE_KD_STATE_MANIPULATE)
+ {
+ DBGKD_MANIPULATE_STATE64* State = (DBGKD_MANIPULATE_STATE64*)MessageHeader->Buffer;
+
+ /* Maybe we are in a send<->receive loop that GDB doesn't need to know about */
+ if (KdpManipulateStateHandler != NULL)
+ return KdpManipulateStateHandler(State, MessageData, DataLength, KdContext);
+
+ /* Receive data from GDB and interpret it */
+ return gdb_receive_and_interpret_packet(State, MessageData, DataLength, KdContext);
+ }
+
+ /* What should we do ? */
+ while (1);
+ return KdPacketNeedsResend;
}
VOID