]>
git.saurik.com Git - apple/xnu.git/blob - tools/lldbmacros/zonetriage.py 
   2      Triage Macros for zone related panics    4      Supported panic strings from xnu/osfmk/kern/zalloc.c:     5          "a freed zone element has been modified in zone  %s : expected %p but found %p, bits changed %p, at offset  %d  of  %d  in element %p, cookies %p %p" and    6          "zalloc: zone map exhausted while allocating from zone  %s , likely due to memory leak in zone  %s  (%lu total bytes,  %d  elements allocated)"    7      These macros are dependant on the above panic strings. If the strings are modified in any way, this script must be updated to reflect the change.    9      To support more zone panic strings:   10          1.  Add the panic string regex to the globals and include in the named capture group 'zone' (the zone to be    11              logged) as well as any other info necessary to parse out of the panic string.   12          2.  Add a check for the panic string regex in ZoneTriage(), which then calls into the function you create.   13          3.  Add a check for the panic string regex in CheckZoneBootArgs() which sets the variable panic_string_regex to your    14              panic string regex if found.   15          4.  Create a function that can be called either through the zonetriage macro ZoneTriage() or using its own macro.    16              This function should handle all lldb commands you want to run for this type of zone panic.   27  ## If the following panic strings are modified in xnu/osfmk/kern/zalloc.c, they must be updated here to reflect the change.   28  zone_element_modified 
=  ".*a freed zone element has been modified in zone (?P<zone>.+): expected (0x)?([0-9A-Fa-f]*)? but found (0x)?([0-9A-Fa-f]*)?, bits changed (0x)?([0-9A-Fa-f]*)?, at offset ([0-9]*)? of ([0-9]*)? in element (?P<element>0x[0-9A-Fa-f]*), cookies (0x)?([0-9A-Fa-f]*)? (0x)?([0-9A-Fa-f]*)?.*"   29  zone_map_exhausted 
=  ".*zalloc: zone map exhausted while allocating from zone .+, likely due to memory leak in zone (?P<zone>.+) \(([0-9]*)? total bytes, ([0-9]*)? elements allocated\).*"   31  # Macro: zonetriage, zonetriage_freedelement, zonetriage_memoryleak   32  @lldb_command ( 'zonetriage' )   33  def  ZoneTriage ( cmd_args
= None ):   34      """ Calls function specific to type of zone panic based on the panic string   37      if  panic_string 
is None :   39              panic_string 
=  lldb_run_command ( "paniclog" ). split ( ' \n ' ,  1 )[ 0 ]   42      if  re
. match ( zone_element_modified
,  panic_string
)  is not None :   43          ZoneTriageFreedElement ()   44      elif  re
. match ( zone_map_exhausted
,  panic_string
)  is not None :   45          ZoneTriageMemoryLeak ()   47          print  "zonetriage does not currently support this panic string."   49  @lldb_command ( 'zonetriage_freedelement' )   50  def  ZoneTriageFreedElement ( cmd_args
= None ):   51      """ Runs zstack_findelem on the element and zone being logged based on the panic string regex   54      if  panic_string 
is None :   56              panic_string 
=  lldb_run_command ( "paniclog" ). split ( ' \n ' ,  1 )[ 0 ]   60      ## Run showzonesbeinglogged.    61      print  "(lldb) zstack_showzonesbeinglogged \n %s \n "  %  lldb_run_command ( "zstack_showzonesbeinglogged" )   62      ## Capture zone and element from panic string.   63      values 
=  re
. search ( zone_element_modified
,  panic_string
)   64      if  values 
is None or  'zone'  not in  values
. group ()  or  'element'  not in  values
. group ():   66      element 
=  values
. group ( 'element' )   67      zone 
=  values
. group ( 'zone' )   68      btlog 
=  FindZoneBTLog ( zone
)   70          print  "(lldb) zstack_findelem "  +  btlog 
+  " "  +  element
  71          findelem_output 
=  lldb_run_command ( "zstack_findelem "  +  btlog 
+  " "  +  element
)   72          findelem_output 
=  re
. sub ( 'Scanning is ongoing. [0-9]* items scanned since last check. \n ' ,  '' ,  findelem_output
)   75  @lldb_command ( 'zonetriage_memoryleak' )   76  def  ZoneTriageMemoryLeak ( cmd_args
= None ):   77      """ Runs zstack_findtop and zstack_findleak on all zones being logged   81      ## Run showzonesbeinglogged.    82      print  "(lldb) zstack_showzonesbeinglogged \n %s \n "  %  lldb_run_command ( "zstack_showzonesbeinglogged" )   83      for  zval 
in  kern
. zones
:   85              print  ' %s :'  %  zval
. z_name
  86              print  "(lldb) zstack_findtop -N 5 0x%lx"  %  zval
. zlog_btlog
  87              print  lldb_run_command ( "zstack_findtop -N 5 0x%lx"  %  zval
. zlog_btlog
)   88              print  "(lldb) zstack_findleak 0x%lx"  %  zval
. zlog_btlog
  89              print  lldb_run_command ( "zstack_findleak 0x%lx"  %  zval
. zlog_btlog
)   91  def  CheckZoneBootArgs ( cmd_args
= None ):   92      """ Check boot args to see if zone is being logged, if not, suggest new boot args   95      if  panic_string 
is None :   97              panic_string 
=  lldb_run_command ( "paniclog" ). split ( ' \n ' ,  1 )[ 0 ]  100      panic_string_regex 
=  ""  101      if  re
. match ( zone_element_modified
,  panic_string
)  is not None :  102          panic_string_regex 
=  zone_element_modified
 103      if  re
. match ( zone_map_exhausted
,  panic_string
)  is not None :  104          panic_string_regex 
=  zone_map_exhausted
 105      values 
=  re
. search ( panic_string_regex
,  panic_string
)  106      if  values 
is None or  'zone'  not in  values
. group ():  108      zone 
=  values
. group ( 'zone' )  109      bootargs 
=  lldb_run_command ( "showbootargs" )  110      correct_boot_args 
=  re
. search ( 'zlog([1-9]|10)?='  +  re
. sub ( ' ' ,  '.' ,  zone
),  bootargs
)  111      if  correct_boot_args 
is None :  112          print  "Current boot-args: \n "  +  bootargs
 113          print  "You may need to include: -zc -zp zlog([1-9]|10)?="  +  re
. sub ( ' ' ,  '.' ,  zone
)  115  def  FindZoneBTLog ( zone
):  116      """ Returns the btlog address in the format 0x%lx for the zone name passed as a parameter  119      for  zval 
in  kern
. zones
:  121              if  zone 
==  " %s "  %  zval
. z_name
:  122                  return  "0x%lx"  %  zval
. zlog_btlog
 124  # EndMacro: zonetriage, zonetriage_freedelement, zonetriage_memoryleak