# HG changeset patch # User Tom Sutcliffe # Date 1291742949 0 # Node ID ceac7084e2e520f8e8aab0657fbdd70b6d047475 # Parent 17bed177107f1973d222917f020cd2e803d4547b Implemented RObjectIx-based memoryaccess APIs. Upshot is that objinfo now works again on platforms that define FSHELL_NO_DOBJECTIX_SUPPORT. diff -r 17bed177107f -r ceac7084e2e5 core/builtins/objinfo.cif --- a/core/builtins/objinfo.cif Tue Nov 30 11:11:58 2010 +0000 +++ b/core/builtins/objinfo.cif Tue Dec 07 17:29:09 2010 +0000 @@ -20,13 +20,21 @@ Given a kernel object address, prints details of the threads and processes that are currently holding handles to it (note, kernel objects addresses can be found using L (e.g. C or C), L or L). Given a thread or process identifier, lists details of all the owned objects. +To see all the threads and processes that have a handle open to the DObject 0x12345678: + + objinfo 0x12345678 + +For example, to see all the handles opened by process 23: + + objinfo --process-id 23 --all + ==see-also L, L, L ==argument uint object_address optional -The address of the kernel object to find the owners of. If not specified, a thread or process identifier must be specified using C<-t> or C<-p>. +The address of the kernel object to find the owners of. If not specified, a thread or process identifier must be specified using C<--thread-id> or C<--process-id>. ==option bool r referencers @@ -42,7 +50,7 @@ ==option bool a all -Include details of objects referenced by threads of a given process. Only useful in conjunction with the C<-p> option. +Include details of objects referenced by threads of a given process, ie show the thread-local handles held by threads in that process as well as the process-global handles. Only useful in conjunction with the C<--process-id> option. ==copyright diff -r 17bed177107f -r ceac7084e2e5 documentation/change_history.pod --- a/documentation/change_history.pod Tue Nov 30 11:11:58 2010 +0000 +++ b/documentation/change_history.pod Tue Dec 07 17:29:09 2010 +0000 @@ -14,6 +14,16 @@ =head1 FShell Change History +=head2 Release 003 [NOT YET MADE] + +=over 5 + +=item * + +Fixed objinfo command so that it works on modern (S^3 or later, S60 5th or later) baselines. + +=back + =head2 Release 002 =over 5 diff -r 17bed177107f -r ceac7084e2e5 libraries/memoryaccess/MemoryAccess.cpp --- a/libraries/memoryaccess/MemoryAccess.cpp Tue Nov 30 11:11:58 2010 +0000 +++ b/libraries/memoryaccess/MemoryAccess.cpp Tue Dec 07 17:29:09 2010 +0000 @@ -23,6 +23,8 @@ #ifdef FSHELL_DOBJECTIX_SUPPORT #include "dobject.h" // To pick up my defn of DObjectIx/DObjectIxNinePointOneHack +#else +TBool ObjectIxContains(RObjectIx& aHandles, DObject* aObj); #endif #include @@ -2114,31 +2116,10 @@ // Code adapted from ExecHandler::HandleInfo DObject* pO=(DObject*)aObj; TInt r = KErrNone; - /* - DThread& t = *iClient; - //TInt r=K::OpenObjectFromHandle(aHandle,pO); - //BEGIN this bit copied from K::OpenObjectFromHandle - TInt r=KErrBadHandle; - NKern::ThreadEnterCS(); - NKern::LockSystem(); - pO=t.ObjectFromHandle(aHandle); - if (pO) - r=pO->Open(); - NKern::UnlockSystem(); - if (r!=KErrNone) - { - pO=NULL; - NKern::ThreadLeaveCS(); - } - //END - */ if (r==KErrNone) { //DObjectIx::Wait(); //TOMSCI I can't call this frmo a device driver, why did the code I copied do it but none of the DMemoryAccess stuff that uses containers do it?? - //DProcess* pCurrentProcess=TheCurrentThread->iOwningProcess; - //hinfo.iNumOpenInThread=TheCurrentThread->iHandles->Count(pO); - //hinfo.iNumOpenInProcess=pCurrentProcess->iHandles->Count(pO); DObjectCon* const * cons=Kern::Containers(); DObjectCon& threads = *cons[EThread]; @@ -2164,9 +2145,6 @@ { buf.Append(idBuf); } - //++hinfo.iNumThreads; - //if (pT->iOwningProcess==pCurrentProcess) - // ++hinfo.iNumOpenInProcess; } } } @@ -2184,7 +2162,6 @@ TInt rr=((DObjectIxNinePointTwoHack*)handles)->At(pO); if (rr!=KErrNotFound) { - //++hinfo.iNumProcesses; TPckgBuf idBuf(pP->iId); if (buf.Length() + idBuf.Length() >= buf.MaxLength()) { @@ -2199,12 +2176,6 @@ } } processes.Signal(); - //DObjectIx::Signal(); - - - //DObjectIx::Signal(); - //pO->Close(NULL); - //NKern::ThreadLeaveCS(); } TInt clientLen = Kern::ThreadGetDesMaxLength(iClient, aOwnersBuf); @@ -2213,30 +2184,92 @@ if (writeErr) return writeErr; return (clientLen < buf.Length()) ? KErrOverflow : r; #else - return KErrNotSupported; + +#ifdef __HANDLES_USE_RW_SPIN_LOCK__ +#error "Memoryaccess doesn't support rw spin locks in RObjectIx!" #endif + + TBuf8<512> buf; + TInt r = KErrNone; + DObject* object = (DObject*)aObj; + + DObjectCon& threads = *Kern::Containers()[EThread]; + threads.Wait(); + TInt c=threads.Count(); + for (TInt i=0;iiHandles, object)) + { + TPckgBuf idBuf(pT->iId); + if (buf.Length() + idBuf.Length() > buf.MaxLength()) + { + r = KErrOverflow; + break; + } + else + { + buf.Append(idBuf); + } + + } + } + threads.Signal(); + + DObjectCon& processes = *Kern::Containers()[EProcess]; + processes.Wait(); + c = processes.Count(); + for (TInt i = 0; i < c; i++) + { + DProcess* proc = (DProcess*)processes[i]; + if (ObjectIxContains(proc->iHandles, object)) + { + TPckgBuf idBuf(proc->iId); + if (buf.Length() + idBuf.Length() > buf.MaxLength()) + { + r = KErrOverflow; + break; + } + else + { + buf.Append(idBuf); + } + } + } + processes.Signal(); + + TInt clientLen = Kern::ThreadGetDesMaxLength(iClient, aOwnersBuf); + if (clientLen < 0) return clientLen; + TInt writeErr = Kern::ThreadDesWrite(iClient, aOwnersBuf, buf, 0, KTruncateToMaxLength, NULL); + if (writeErr) return writeErr; + return (clientLen < buf.Length()) ? KErrOverflow : r; + +#endif // FSHELL_DOBJECTIX_SUPPORT } TInt DMemoryAccess::GetThreadHandles(TInt aThreadId, TAny* aHandlesBuf) { -#ifdef FSHELL_DOBJECTIX_SUPPORT - TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf); - TInt err = KErrNone; - + NKern::ThreadEnterCS(); DObjectCon* const * cons = Kern::Containers(); DObjectCon& container = *cons[EThread]; container.Wait(); - NKern::ThreadEnterCS(); DThread* thread = Kern::ThreadFromId(aThreadId); - //TOMSCI FIXME we don't increment thread's ref count - NKern::ThreadLeaveCS(); + if (thread && thread->Open() != KErrNone) + { + thread = NULL; + } container.Signal(); if (thread == NULL) { + NKern::ThreadLeaveCS(); return KErrNotFound; } +#ifdef FSHELL_DOBJECTIX_SUPPORT // Note, this code is inherently dodgy because it doesn't claim DObjectIx::HandleMutex. + TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf); + TInt err = KErrNone; + DObjectIxNinePointTwoHack* handles = (DObjectIxNinePointTwoHack*)thread->iHandles; if (handles) { @@ -2266,33 +2299,59 @@ } } } +#else + + TInt c = thread->iHandles.Count(); + HBuf8* buf = HBuf::New(c * sizeof(DObject*)); + TInt err = KErrNoMemory; + if (buf) + { + DObject** ptr = (DObject**)buf->Ptr(); + NKern::LockSystem(); + c = Min(thread->iHandles.Count(), c); // In case it's changed + buf->SetLength(c * sizeof(DObject*)); + for (TInt i = 0; i < c; i++) + { + ptr[i] = thread->iHandles[i]; + } + NKern::UnlockSystem(); - //TOMSCI What is this unlock doing here? TODO FIXME!!! - NKern::UnlockSystem(); + err = Kern::ThreadDesWrite(iClient, aHandlesBuf, *buf, 0); + delete buf; + } + else + { + err = KErrNoMemory; + } +#endif + + thread->Close(NULL); + NKern::ThreadLeaveCS(); return err; -#else - return KErrNotSupported; -#endif } TInt DMemoryAccess::GetProcessHandles(TInt aProcessId, TAny* aHandlesBuf) { -#ifdef FSHELL_DOBJECTIX_SUPPORT - TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf); - TInt err = KErrNone; - + NKern::ThreadEnterCS(); DObjectCon* const * cons = Kern::Containers(); DObjectCon& container = *cons[EProcess]; container.Wait(); - NKern::ThreadEnterCS(); - DProcess* process = Kern::ProcessFromId(aProcessId); - NKern::ThreadLeaveCS(); + DProcess* proc = Kern::ProcessFromId(aProcessId); + if (proc && proc->Open() != KErrNone) + { + proc = NULL; + } container.Signal(); - if (process == NULL) + if (proc == NULL) { + NKern::ThreadLeaveCS(); return KErrNotFound; } +#ifdef FSHELL_DOBJECTIX_SUPPORT + TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf); + TInt err = KErrNone; + // Note, this code is inherently dodgy because it doesn't claim DObjectIx::HandleMutex. DObjectIxNinePointTwoHack* handles = (DObjectIxNinePointTwoHack*)process->iHandles; if (handles) @@ -2324,10 +2383,35 @@ } } +#else // new RObjectIx code + + TInt c = proc->iHandles.Count(); + HBuf8* buf = HBuf::New(c * sizeof(DObject*)); + TInt err = KErrNoMemory; + if (buf) + { + DObject** ptr = (DObject**)buf->Ptr(); + NKern::LockSystem(); + c = Min(proc->iHandles.Count(), c); // In case it's changed + buf->SetLength(c * sizeof(DObject*)); + for (TInt i = 0; i < c; i++) + { + ptr[i] = proc->iHandles[i]; + } + NKern::UnlockSystem(); + + err = Kern::ThreadDesWrite(iClient, aHandlesBuf, *buf, 0); + delete buf; + } + else + { + err = KErrNoMemory; + } +#endif // FSHELL_DOBJECTIX_SUPPORT + + proc->Close(NULL); + NKern::ThreadLeaveCS(); return err; -#else - return KErrNotSupported; -#endif } TInt DMemoryAccess::SetCriticalFlags(TInt aThreadHandle, TUint aFlags) @@ -3113,3 +3197,32 @@ iClientBreakpointNotifyPkg = NULL; } } + +#ifndef FSHELL_DOBJECTIX_SUPPORT + +DObject* RObjectIx::operator[](TInt aIndex) + { + // Must be holding system lock (technically, the 'read' lock) + DObject* obj = 0; + SSlot* slot = iSlots + aIndex; + obj = Occupant(slot); + return obj; + } + +TBool ObjectIxContains(RObjectIx& aHandles, DObject* aObj) + { + NKern::LockSystem(); + TInt c = aHandles.Count(); + for (TInt i = 0; i < c; i++) + { + if (aHandles[i] == aObj) + { + NKern::UnlockSystem(); + return ETrue; + } + } + NKern::UnlockSystem(); + return EFalse; + } + +#endif