+def IterateLinkageChain(queue_head, element_type, field_name, field_ofst=0):
+ """ Iterate over a Linkage Chain queue in kernel of type queue_head_t. (osfmk/kern/queue.h method 1)
+ This is equivalent to the qe_foreach_element() macro
+ params:
+ queue_head - value : Value object for queue_head.
+ element_type - lldb.SBType : pointer type of the element which contains the queue_chain_t. Typically its structs like thread, task etc..
+ - str : OR a string describing the type. ex. 'task *'
+ field_name - str : Name of the field (in element) which holds a queue_chain_t
+ field_ofst - int : offset from the 'field_name' (in element) which holds a queue_chain_t
+ This is mostly useful if a particular element contains an array of queue_chain_t
+ returns:
+ A generator does not return. It is used for iterating.
+ value : An object thats of type (element_type). Always a pointer object
+ example usage:
+ coalq = kern.GetGlobalVariable('coalitions_q')
+ for coal in IterateLinkageChain(coalq, 'struct coalition *', 'coalitions'):
+ print GetCoalitionInfo(coal)
+ """
+ global kern
+ if type(element_type) == str:
+ element_type = gettype(element_type)
+
+ if unsigned(queue_head) == 0:
+ return
+
+ if element_type.IsPointerType():
+ elem_ofst = getfieldoffset(element_type.GetPointeeType(), field_name) + field_ofst
+ else:
+ elem_ofst = getfieldoffset(element_type, field_name) + field_ofst
+
+ link = queue_head.next
+ while (unsigned(link) != unsigned(queue_head)):
+ addr = unsigned(link) - elem_ofst;
+ # I can't use the GetValueFromAddress function of the kernel class
+ # because I have no instance of that class!
+ obj = value(link.GetSBValue().CreateValueFromExpression(None,'(void *)'+str(addr)))
+ obj = cast(obj, element_type)
+ yield obj
+ link = link.next
+
+def IterateCircleQueue(queue_head, element_ptr_type, element_field_name):
+ """ iterate over a circle queue in kernel of type circle_queue_head_t. refer to osfmk/kern/circle_queue.h
+ params:
+ queue_head - lldb.SBValue : Value object for queue_head.
+ element_type - lldb.SBType : a pointer type of the element 'next' points to. Typically its structs like thread, task etc..
+ element_field_name - str : name of the field in target struct.
+ returns:
+ A generator does not return. It is used for iterating.
+ SBValue : an object thats of type (element_type) queue_head->next. Always a pointer object
+ """
+ head = queue_head.head.GetSBValue()
+ queue_head_addr = 0x0
+ if head.TypeIsPointerType():
+ queue_head_addr = head.GetValueAsUnsigned()
+ else:
+ queue_head_addr = head.GetAddress().GetLoadAddress(osplugin_target_obj)
+ cur_elt = head
+ while True:
+ if not cur_elt.IsValid() or cur_elt.GetValueAsUnsigned() == 0:
+ break
+ yield containerof(value(cur_elt), element_ptr_type, element_field_name)
+ cur_elt = cur_elt.GetChildMemberWithName('next')
+ if cur_elt.GetValueAsUnsigned() == queue_head_addr:
+ break
+
+def IterateQueue(queue_head, element_ptr_type, element_field_name, backwards=False, unpack_ptr_fn=None):
+ """ Iterate over an Element Chain queue in kernel of type queue_head_t. (osfmk/kern/queue.h method 2)