mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-06-15 12:59:27 +00:00
696c195395
- Bug 1161686 - libmar's |SECU_GetModulePassword| can leak allocated string (command line build utility). Free unused return of GetPasswordString. r=bbondy (25107e4c3e)
- Bug 1253775 - Remove libmar and libbz2 Makefile.ins; r=ted (7d693933b8)
- Bug 1186934 - update jemalloc to upstream HEAD; r=glandium (cd4fdf0c93)
- Bug 1254850 - Update jemalloc 4 to version 4.1.0. r=njn (6cc351fb51)
- Bug 1254948 - Remove makefiles used to transition from jemalloc_config.c to jemalloc_config.cpp; r=glandium (c8e0684478)
- Bug 1263735: Update libcubeb to remove wasapi stubbing for enumeration r=kinetik (156c7e4ef8)
- Bug 1264594 - Update libcubeb to revision 727121. r=kinetik (e982bc0eef)
- Bug 1264892: Use system declaration of |__system_property_get| on B2G, r=padenot (b50185e037)
- Bug 1265692 - Update cubeb to 0bc02f9. r=padenot,kinetik (420c905a02)
- Bug 1251502 - Add a duplex AudioUnit implementation. r=kinetik,padenot (a4e00f217a)
- Bug 1266753 - Update cubeb to revision dbdfb to pick up OSX device notification changes. r=padenot (12532f1cf6)
- Bug 1266753 - Fix mac bustage: use the old enum values, on a CLOSED TREE. r=padenot (afe9874670)
- Bug 1251502 - Compile the resampling code in cubeb for OSX and Linux. r=kinetik (6f07d50796)
- Bug 1236937 - Use correct value for Pi in AAFilter.cpp. r=padenot (d54113bf18)
- Bug 1235675 - Add the source directory to the -include directive in media/libsoundtouch/src/moz.build. r=mshal (0d56029898)
- Bug 1135942 - Enable MMX/SSE code unconditionally in libsoundtouch, it does runtime detection anyways. r=padenot (1e1c3c6c84)
- Bug 1134744 - Fix baseline for form controls when line is inverted relative to block dir. r=smontagu (8be618ce3f)
- Bug 1261284: Don't include <button>'s children in overflow areas, if we know we're going to clip them when painting. r=mats (094dd9c33b)
- Bug 1263773 - Mark a bunch of classes in layout as MOZ_RAII. r=dholbert (e28d735a60)
- Bug 1249664 - Save the combobox's dropped-down state across frame reconstruction. r=dbaron (6caf06c91e)
- Bug 1253977 part 1 - Update focus state on combobox frame destruction/construction properly. r=tn (0c1841dc35)
- Bug 1253977 part 2 - Reftests. (985b87a008)
- Bug 1212688 - Drill through any <optgroup> scroll frames to get at its <option> child frames when estimating the list's row size. r=roc (67b9ac481c)
- Bug 1228670 - Null-check GetContentInsertionFrame() before using it. r=bz (bffbf4769c)
- Bug 1208978 - Limit the size of a potentially-scrollable dropdown list to the actual size of its contents, as our estimate based on row count may be too large if the row heights vary. r=roc (b9447f9f1c)
- Bug 1121515 - Error tapping empty listitem in a <select> box, r=roc, wesj (bffe267a89)
- Bug 1194733 - Don't honor DefaultPrevented for mouseup events in list control frames. r=enndeakin@gmail.com (37c43372b6)
- bits of 1225280 (1869476ed8)
- Bug 1239504 - Avoid ASan leak report by holding PseudoStack in ImageBridgeChild. r=sotaro (d9125680ad)
- Bug 1223193: P1. Make ImageBridgeChild::mShuttingDown atomic. r=nical (3a5b496dae)
- Bug 1223193: P2. Cancel ImageBridge proxy functions if shutdown has started. r=nical (a66cd45878)
- Bug 1243466 - Don't crash if DeallocPImageContainerChild is called prematurely. r=sotaro (e8d4776fde)
- Bug 1251808 (Followup) - Mark the new SourceSurfaceImage constructor explicit. r=me (1087add7d0)
- Bug 1260391: Fix |ImageBridgeChild::UseOverlaySource|, r=dvander (e423cc3a27)
- Bug 1255823 - Add a two-step destruction process to PAPZ. r=dvander (3d53adaecc)
- Bug 1261321 - Null-check when the CompositableClient when forcing its destruction at shutdown. r=jnicol (7180c6d737)
- Bug 1259301 - Remove GeckoContentController::RequestFlingSnap(). r=kats (d94da5f624)
- Bug 1253512 (part 1) - Overhaul DMD's "sampling". r=erahm. (536dcdf84e)
- Bug 1282185 (part 1) - Remove a bogus assertion in DMD. r=erahm. (ec09953fac)
- Bug 1253512 (part 2) - Aggregate live blocks. r=erahm. (57db2ffa75)
- Bug 1254029 - Do not wait in ImageBridgeChild::FlushAllImages() except gonk r=nical (aeac940199)
- Bug 1175895 - separate tier start message for mach; r=ted (cd56ddae05)
- Bug 1077670 - Package tests in parallel. r=gps (28b531ba3d)
- Bug 1253478 - Use Atomic<uint64_t> in AsyncTransactionTracker r=nical (c1f2cf892f)
- Bug 1150338 - Use the tooltool gcc in automation rather than /tools, r=terrence (15f1fa12bc)
- Bug 1259848 - Various fixes for finding gcc in the correct location for spidermonkey TC builds and hazard shell builds, r=terrence (9963274899)
262 lines
7.9 KiB
Python
262 lines
7.9 KiB
Python
#!/usr/bin/python
|
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
# From a scan mode DMD log, extract some information about a
|
|
# particular block, such as its allocation stack or which other blocks
|
|
# contain pointers to it. This can be useful when investigating leaks
|
|
# caused by unknown references to refcounted objects.
|
|
|
|
import json
|
|
import gzip
|
|
import sys
|
|
import argparse
|
|
import re
|
|
|
|
|
|
# The DMD output version this script handles.
|
|
outputVersion = 5
|
|
|
|
# If --ignore-alloc-fns is specified, stack frames containing functions that
|
|
# match these strings will be removed from the *start* of stack traces. (Once
|
|
# we hit a non-matching frame, any subsequent frames won't be removed even if
|
|
# they do match.)
|
|
allocatorFns = [
|
|
'malloc (',
|
|
'replace_malloc',
|
|
'replace_calloc',
|
|
'replace_realloc',
|
|
'replace_memalign',
|
|
'replace_posix_memalign',
|
|
'malloc_zone_malloc',
|
|
'moz_xmalloc',
|
|
'moz_xcalloc',
|
|
'moz_xrealloc',
|
|
'operator new(',
|
|
'operator new[](',
|
|
'g_malloc',
|
|
'g_slice_alloc',
|
|
'callocCanGC',
|
|
'reallocCanGC',
|
|
'vpx_malloc',
|
|
'vpx_calloc',
|
|
'vpx_realloc',
|
|
'vpx_memalign',
|
|
'js_malloc',
|
|
'js_calloc',
|
|
'js_realloc',
|
|
'pod_malloc',
|
|
'pod_calloc',
|
|
'pod_realloc',
|
|
'nsTArrayInfallibleAllocator::Malloc',
|
|
# This one necessary to fully filter some sequences of allocation functions
|
|
# that happen in practice. Note that ??? entries that follow non-allocation
|
|
# functions won't be stripped, as explained above.
|
|
'???',
|
|
]
|
|
|
|
####
|
|
|
|
# Command line arguments
|
|
|
|
def range_1_24(string):
|
|
value = int(string)
|
|
if value < 1 or value > 24:
|
|
msg = '{:s} is not in the range 1..24'.format(string)
|
|
raise argparse.ArgumentTypeError(msg)
|
|
return value
|
|
|
|
parser = argparse.ArgumentParser(description='Analyze the heap graph to find out things about an object. \
|
|
By default this prints out information about blocks that point to the given block.')
|
|
|
|
parser.add_argument('dmd_log_file_name',
|
|
help='clamped DMD log file name')
|
|
|
|
parser.add_argument('block',
|
|
help='address of the block of interest')
|
|
|
|
parser.add_argument('--info', dest='info', action='store_true',
|
|
default=False,
|
|
help='Print out information about the block.')
|
|
|
|
parser.add_argument('-sfl', '--max-stack-frame-length', type=int,
|
|
default=150,
|
|
help='Maximum number of characters to print from each stack frame')
|
|
|
|
parser.add_argument('-a', '--ignore-alloc-fns', action='store_true',
|
|
help='ignore allocation functions at the start of traces')
|
|
|
|
parser.add_argument('-f', '--max-frames', type=range_1_24,
|
|
help='maximum number of frames to consider in each trace')
|
|
|
|
parser.add_argument('-c', '--chain-reports', action='store_true',
|
|
help='if only one block is found to hold onto the object, report the next one, too')
|
|
|
|
|
|
####
|
|
|
|
|
|
class BlockData:
|
|
def __init__(self, json_block):
|
|
self.addr = json_block['addr']
|
|
|
|
if 'contents' in json_block:
|
|
contents = json_block['contents']
|
|
else:
|
|
contents = []
|
|
self.contents = []
|
|
for c in contents:
|
|
self.contents.append(int(c, 16))
|
|
|
|
self.req_size = json_block['req']
|
|
|
|
self.alloc_stack = json_block['alloc']
|
|
|
|
|
|
def print_trace_segment(args, stacks, block):
|
|
(traceTable, frameTable) = stacks
|
|
|
|
for l in traceTable[block.alloc_stack]:
|
|
# The 5: is to remove the bogus leading "#00: " from the stack frame.
|
|
print ' ', frameTable[l][5:args.max_stack_frame_length]
|
|
|
|
|
|
def show_referrers(args, blocks, stacks, block):
|
|
visited = set([])
|
|
|
|
anyFound = False
|
|
|
|
while True:
|
|
referrers = {}
|
|
|
|
for b, data in blocks.iteritems():
|
|
which_edge = 0
|
|
for e in data.contents:
|
|
if e == block:
|
|
# 8 is the number of bytes per word on a 64-bit system.
|
|
# XXX This means that this output will be wrong for logs from 32-bit systems!
|
|
referrers.setdefault(b, []).append(8 * which_edge)
|
|
anyFound = True
|
|
which_edge += 1
|
|
|
|
for r in referrers:
|
|
sys.stdout.write('0x{} size = {} bytes'.format(blocks[r].addr, blocks[r].req_size))
|
|
plural = 's' if len(referrers[r]) > 1 else ''
|
|
sys.stdout.write(' at byte offset' + plural + ' ' + (', '.join(str(x) for x in referrers[r])))
|
|
print
|
|
print_trace_segment(args, stacks, blocks[r])
|
|
print
|
|
|
|
if args.chain_reports:
|
|
if len(referrers) == 0:
|
|
sys.stdout.write('Found no more referrers.\n')
|
|
break
|
|
if len(referrers) > 1:
|
|
sys.stdout.write('Found too many referrers.\n')
|
|
break
|
|
|
|
sys.stdout.write('Chaining to next referrer.\n\n')
|
|
for r in referrers:
|
|
block = r
|
|
if block in visited:
|
|
sys.stdout.write('Found a loop.\n')
|
|
break
|
|
visited.add(block)
|
|
else:
|
|
break
|
|
|
|
if not anyFound:
|
|
print 'No referrers found.'
|
|
|
|
|
|
def show_block_info(args, blocks, stacks, block):
|
|
b = blocks[block]
|
|
sys.stdout.write('block: 0x{}\n'.format(b.addr))
|
|
sys.stdout.write('requested size: {} bytes\n'.format(b.req_size))
|
|
sys.stdout.write('\n')
|
|
sys.stdout.write('block contents: ')
|
|
for c in b.contents:
|
|
v = '0' if c == 0 else blocks[c].addr
|
|
sys.stdout.write('0x{} '.format(v))
|
|
sys.stdout.write('\n\n')
|
|
sys.stdout.write('allocation stack:\n')
|
|
print_trace_segment(args, stacks, b)
|
|
return
|
|
|
|
|
|
def cleanupTraceTable(args, frameTable, traceTable):
|
|
# Remove allocation functions at the start of traces.
|
|
if args.ignore_alloc_fns:
|
|
# Build a regexp that matches every function in allocatorFns.
|
|
escapedAllocatorFns = map(re.escape, allocatorFns)
|
|
fn_re = re.compile('|'.join(escapedAllocatorFns))
|
|
|
|
# Remove allocator fns from each stack trace.
|
|
for traceKey, frameKeys in traceTable.items():
|
|
numSkippedFrames = 0
|
|
for frameKey in frameKeys:
|
|
frameDesc = frameTable[frameKey]
|
|
if re.search(fn_re, frameDesc):
|
|
numSkippedFrames += 1
|
|
else:
|
|
break
|
|
if numSkippedFrames > 0:
|
|
traceTable[traceKey] = frameKeys[numSkippedFrames:]
|
|
|
|
# Trim the number of frames.
|
|
for traceKey, frameKeys in traceTable.items():
|
|
if len(frameKeys) > args.max_frames:
|
|
traceTable[traceKey] = frameKeys[:args.max_frames]
|
|
|
|
|
|
def loadGraph(options):
|
|
# Handle gzipped input if necessary.
|
|
isZipped = options.dmd_log_file_name.endswith('.gz')
|
|
opener = gzip.open if isZipped else open
|
|
|
|
with opener(options.dmd_log_file_name, 'rb') as f:
|
|
j = json.load(f)
|
|
|
|
if j['version'] != outputVersion:
|
|
raise Exception("'version' property isn't '{:d}'".format(outputVersion))
|
|
|
|
invocation = j['invocation']
|
|
|
|
block_list = j['blockList']
|
|
blocks = {}
|
|
|
|
for json_block in block_list:
|
|
blocks[int(json_block['addr'], 16)] = BlockData(json_block)
|
|
|
|
traceTable = j['traceTable']
|
|
frameTable = j['frameTable']
|
|
|
|
cleanupTraceTable(options, frameTable, traceTable)
|
|
|
|
return (blocks, (traceTable, frameTable))
|
|
|
|
|
|
def analyzeLogs():
|
|
options = parser.parse_args()
|
|
|
|
(blocks, stacks) = loadGraph(options)
|
|
|
|
block = int(options.block, 16)
|
|
|
|
if not block in blocks:
|
|
print 'Object', block, 'not found in traces.'
|
|
print 'It could still be the target of some nodes.'
|
|
return
|
|
|
|
if options.info:
|
|
show_block_info(options, blocks, stacks, block)
|
|
return
|
|
|
|
show_referrers(options, blocks, stacks, block)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
analyzeLogs()
|