kernelsystem-callsqnx

What is the best QNX alternatve to Linux strace


I used to analyze the system calls produced by a program in Linux using the strace tool which is quite useful. We can clearly see all the four categories presented by Modern Operating Systems(Tanenbaum et al., 2022): process management, file management, directory management, miscellaneous calls.

Now I want to do the same for QNX and that's a bit painful since QNX does not seem to provide a full tool for this purpose.

QNX provides tracelogger in https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.sat/topic/datacapture.html

The problem with this tool is that it's not quite complete.

I believe I need to customize it somehow, but the results are not quite straightforward as Linux's strace.

Can you please give me your insights so that I can follow a better approach?


Solution

  • After some investigation, I finally could find and validate what QNX provides, an IDE called Momentics that can receive as input a .kev file output by tracelogger: https://www.qnx.com/products/neutrino-rtos/qnx-momentics.html

    The tool is very slow, but with some pain, we can read and filter all the kernel traces by the following categories:

    Communication

    Control Events

    Interrups

    Process and Thread

    System

    I was expecting a big list of actual system calls, since QNX is a Microkernel, but since it's also POSIX compliant and mainly due to performance in a real time system (context switches are expensive), the list of actual system calls is actually very few as we can confirm in the Momentics IDE:

    1. CacheFlush(): flushes the contents of the indicated cache(s) for the specified addresses.
    2. ChannelCreate(),  ChannelCreate_r(), ChannelCreatePulsePool(),  ChannelCreate(): create a channel  to receive messages and pulses.
    3.  ChannelDestroy(), ChannelDestroy_r(): The opposite.
    4. ConnectAttach(), ConnectAttach_r(): For a  thread to get attached to communicate with a channel.
    5. ChannelConnectAttr: related to the previous.
    6. ClockAdjust(), ClockAdjust_r():  let you gradually adjust the time of the clock specified by id. Represent the amount of time the process or thread has spent running.
    7. ClockId(), ClockId_r(): clock ID of a process or thread CPU-time clock. Time the process or thread has spent running.
    8. ClockPeriod(), ClockPeriod_r(): get or set the clock period of the clock.
    9. ClockTime(), ClockTime_r(): get or set the system clock, get the CPU-time clock for a process or a particular thread.
    10. ConnectClientInfo(), ConnectClientInfo_r(): get information about a client connection identified by scoid, and store it in the buffer that info points to. 
    11. ConnectFlags(), ConnectFlags_r(): nonblocking calls to modify or query the flags associated with the specified connection. 
    12. ConnectDetach(), ConnectDetach_r():  detach the connection specified by the coid argument. 
    13. ConnectServerInfo(), ConnectServerInfo_r(): get information about the connection coid owned by process pid to store in the structure pointed to by info.
    14. InterruptAttach(), InterruptAttach_r(): attach the Interrupt Service Routine (ISR) identified by handler to the hardware interrupt specified by intr; automatically enable (i.e., unmask) the interrupt level. 
    15. InterruptDetach(), InterruptDetach_r(): detach the interrupt handler specified by the id argument. 
    16. InterruptMask(): disables the hardware interrupt specified by intr for the handler specified by id.
    17. InterruptUnmask():  enables the hardware interrupt specified by intr for the interrupt handler specified by id when the mask count reaches zero.
    18. InterruptWait(), InterruptWait_r():  wait for a hardware interrupt. The calling thread should have attached a handler to the interrupt.
    19. MsgReadv(), MsgReadv_r(): read data from a message sent by a thread identified by rcvid.
    20. MsgReceivePulsev(), MsgReceivePulsev_r(): wait for a pulse to arrive on the channel identified by chid and place the received data in the first element of the array of buffers pointed to by piov.
    21. MsgReceive(), MsgReceive_r(), MsgReceivev(), MsgReceivev_r(): wait for a message or pulse to arrive on the channel identified by chid and place the received data in the array of buffers pointed to by riov. 
    22. MsgReply(), MsgReply_r(), MsgReplyv(), MsgReplyv_r(): reply with a message to the thread identified by rcvid
    23. MsgSend(), MsgSend_r(), MsgSendvs(), MsgSendvs_r(), MsgSendnc(), MsgSendnc_r(), MsgSendvsnc(), MsgSendvsnc_r(): send a message to a process's channel via the connection identified by coid. 
    24. MsgSendPulsePtr(), MsgSendPulsePtr_r():  send a short, nonblocking message to a process's channel via the connection identified by coid.
    25. MsgVerifyEvent(), MsgVerifyEvent_r(): check the validity of the receive ID rcvid, and the event configuration. 
    26. MsgWritev(), MsgWritev_r(): write data to the reply buffer of a thread identified by rcvid. 
    27. MsgCurrent(), MsgCurrent_r(): announce to the kernel that you are resuming the processing of a previously received message.
    28. MsgError(), MsgError_r(): deliver an event from a server to a client through a channel connection.
    29. MsgInfo(), MsgInfo_r(): get additional information about a received message and store it in the specified _msg_info structure. 
    30. MsgKeyData(), MsgKeyData_r(): allow two privileged processes to pass data through a common client while verifying that the client hasn't modified the data.
    31. MsgPause(), MsgPause_r(): pause a message.
    32. MsgRead(), MsgRead_r(): read data from a message sent by a thread identified by rcvid. 
    33. MsgReceivePulse(), MsgReceivePulse_r():  wait for a pulse to arrive on the channel identified by chid and place the received data in the buffer pointed to by pulse.
    34. SchedCtl(), SchedCtl_r(): control the scheduler. 
    35. Network related: NetCred(), NetInfoScoid(), NetSignalKill(), NetUnblock(), NetVtid().
    36. __KER_NOP event: forces a thread into the kernel so that scheduling can take place.
    37. SchedGet(), SchedGet_r(): return the current scheduling policy and parameters for the thread specified by tid in the process specified by pid.
    38. SchedInfo(), SchedInfo_r(): return information about the kernel's thread scheduler, including the minimum and maximum thread priority.
    39. SchedSet(), SchedSet_r(): set both the scheduling policy and the associated parameters for the thread specified by tid in the process specified by pid.
    40. SchedYield(), SchedYield_r(): check to see if other threads at the same priority as that of the calling thread are ready to run. If so, the calling thread yields to them and places itself at the end of the READY thread queue for that priority. SchedYield() never yields to a lower-priority thread. Higher-priority threads always force a yield the instant they become ready to run. This call has no effect with respect to threads running at priorities other than the calling thread's.
    41. SchedWaypoint: related to the previous.
    42. SignalAction(), SignalAction_r(): let the calling process examine or specify (or both) the action to be associated with a specific signal in the process pid.
    43. SignalKill(), SignalKill_r(): send the signal signo with a code specified by code and a value specified by value to a process group, process, or thread.
    44. SignalKillSigval(), SignalKillSigval_r(): send the signal signo with the given code and the value specified by sigval to a process group, process, or thread.
    45. SignalProcmask(), SignalProcmask_r(): modify or examine the signal-blocked mask of the thread tid in process pid.
    46. SignalSuspend(), SignalSuspend_r(): replace the thread's signal mask with the set of signals pointed to by set and then suspends the thread until delivery of a signal whose action is either to execute a signal-catching function (then return), or to terminate the thread. On return, the previous signal mask is restored. 
    47. SignalReturn: related to the previous.
    48. SignalWaitinfo(), SignalWaitinfo_r(): select the pending signal from the set specified by set.
    49. SyncCondvarSignal(), SyncCondvarSignal_r(): wake up one or all threads that are blocked on the condition variable, condvar.
    50. SyncCondvarWait(), SyncCondvarWait_r(): block the calling thread on the condition variable, condvar. If more than one thread is blocked on the object, the threads are queued in priority order.
    51. SyncCreate(), SyncCreate_r(),  SyncTypeCreate(), SyncTypeCreate_r(): create a synchronization object in the kernel and initializes sync for use in other synchronization kernel calls.
    52. SyncDestroy(), SyncDestroy_r(): the opposite.
    53. SyncCtl(), SyncCtl_r(): set or get a ceiling priority for a mutex, attach an event to a mutex so you'll be notified when the mutex changes to the DEAD state, wake up threads that are blocked on a mutex.
    54. SyncMutexLock(), SyncMutexLock_r(): try to lock the mutex synchronization object sync. If the mutex isn't currently locked, the call returns immediately with the object locked. The mutex is considered unlocked if the owner field of sync is zero.
    55. SyncMutexRevive(), SyncMutexRevive_r(): revive a mutex, pointed to by sync, that's in the DEAD state. The mutex will be put into the LOCK state and will be owned by the calling thread. The mutex counter is set to one (for recursive mutexes).
    56. SyncMutexUnlock(), SyncMutexUnlock_r(): unlock the mutex passed as sync. If there are threads blocked on the mutex, the owner member of sync is set to the thread ID of the thread with the highest priority that has been waiting the longest and it's made ready to run.
    57. SyncSemPost(), SyncSemPost_r(): increment the semaphore referenced by the sync argument. If any threads are blocked on the semaphore, the one waiting the longest is unblocked and allowed to run.
    58. SyncSemWait(), SyncSemWait_r():  decrement the semaphore referred to by the sync argument. If the semaphore value isn't greater than zero and try is zero, then the calling process blocks until it can decrement the counter or the call is interrupted by signal.
    59. SysSrandom(), SysSrandom_r(): set one source of entropy that's used for the kernel's PRNG. The PRNG is used with ASLR.
    60. ThreadCancel(), ThreadCancel_r(): request that the thread specified by tid be canceled.
    61. ThreadCreate(), ThreadCreate_r(): create a new thread of execution, with attributes specified by attr, within the process specified by pid.
    62. ThreadDestroy(),ThreadDestroy_r() are the opposite.
    63. ThreadDetach(), ThreadDetach_r(), ThreadJoin(), ThreadJoin_r() are related.
    64. ThreadCtl(), ThreadCtl_r(), ThreadCtlExt(), ThreadCtlExt_r(): allow you to make OS-specific changes to a thread.
    65. TimerAlarm(), TimerAlarm_r(): activate an internal timer to schedule an alarm signal (SIGALRM) for delivery to the process. The signal will be delivered at the time specified by itime.
    66. TimerCreate(), TimerCreate_r(): create a per-process timer using the clock specified by id as the timing base.  
    67. TimerDestroy(), TimerDestroy_r() are the opposite.
    68. TimerInfo(), TimerInfo_r(): get time info.
    69. TimerSettime(), TimerSettime_r(): set the expiration time of the timer specified by id, or set the tolerance for that timer, depending on the flags provided.
    70. TimerTimeout(), TimerTimeout_r():  set a timeout on any kernel blocking state, block for a specified time, or set the timer tolerance for these timeouts, depending on the flags.
    71. TraceEvent():  lets you control all stages of the instrumentation process, including initializing, starting, stopping, controlling filters, and inserting events. These stages are broadly grouped into categories described in https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.lib_ref/topic/t/traceevent.html

    Overview on QNX Kernel Calls (https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.sat/topic/events_Kernel_call_class.html):