Implemented RObjectIx-based memoryaccess APIs.
Upshot is that objinfo now works again on platforms that define FSHELL_NO_DOBJECTIX_SUPPORT.
--- 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<ps|ps> (e.g. C<ps -A> or C<ps -At>), L<chunkinfo|chunkinfo> or L<svrinfo|svrinfo>). 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<ps|ps>, L<chunkinfo|chunkinfo>, L<svrinfo|svrinfo>
==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
--- 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
--- 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 <e32cmn.h>
@@ -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<TUint> 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;i<c;i++)
+ {
+ DThread *pT=(DThread *)threads[i];
+ if (ObjectIxContains(pT->iHandles, object))
+ {
+ TPckgBuf<TUint> 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<TUint> 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