]>
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
. zone_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
. zone_name
:
122 return "0x%lx" % zval
. zlog_btlog
124 # EndMacro: zonetriage, zonetriage_freedelement, zonetriage_memoryleak