mirror of
https://github.com/google/pebble.git
synced 2025-05-17 17:04:53 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
200
tools/parse_dump_malloc.py
Normal file
200
tools/parse_dump_malloc.py
Normal file
|
@ -0,0 +1,200 @@
|
|||
# Copyright 2024 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sh
|
||||
import sys
|
||||
|
||||
|
||||
total_alloc_size = 0
|
||||
alloc_count = 0
|
||||
total_free_size = 0
|
||||
free_count = 0
|
||||
largest_free_block = 0
|
||||
|
||||
per_file_dict = {}
|
||||
alloc_list = []
|
||||
|
||||
root_path = os.path.join(os.path.dirname(sys.argv[0]), '..')
|
||||
|
||||
min_addr = 0
|
||||
max_addr = 0
|
||||
current_size = 0
|
||||
high_water_mark = 0
|
||||
|
||||
def get_filename_linenumber(addr_str):
|
||||
try:
|
||||
line = sh.arm_none_eabi_addr2line(addr_str, exe=elf_path)
|
||||
except:
|
||||
return ("?", 0)
|
||||
|
||||
line = line.strip()
|
||||
|
||||
index = line.rfind(':')
|
||||
filename = line[:index]
|
||||
linenumber = line[index + 1:]
|
||||
if ':' not in filename:
|
||||
filename = os.path.relpath(filename, root_path)
|
||||
|
||||
return (filename, linenumber)
|
||||
|
||||
def handle_line(line, verbose):
|
||||
parts = line.split(' ')
|
||||
|
||||
# Skip gdb continuation prompts
|
||||
if parts[0].startswith('---'):
|
||||
return;
|
||||
|
||||
if parts[0] == 'Heap':
|
||||
metadata_name = ' '.join(parts[1:-1])
|
||||
if metadata_name == 'start':
|
||||
global min_addr
|
||||
min_addr = int(parts[-1].strip(), 16)
|
||||
elif metadata_name == 'end':
|
||||
global max_addr
|
||||
max_addr = int(parts[-1].strip(), 16)
|
||||
elif metadata_name == 'current size':
|
||||
global current_size
|
||||
current_size = int(parts[-1].strip())
|
||||
elif metadata_name == 'high water mark':
|
||||
global high_water_mark
|
||||
high_water_mark = int(parts[-1].strip())
|
||||
return
|
||||
|
||||
def get_part_value(index):
|
||||
return parts[index].split(':')[1]
|
||||
|
||||
pc = get_part_value(0)
|
||||
addr = get_part_value(1)
|
||||
actual_size = int(get_part_value(2))
|
||||
|
||||
filename, linenumber = get_filename_linenumber(pc)
|
||||
|
||||
is_free = (int(pc, 0) == 0)
|
||||
if verbose:
|
||||
if is_free:
|
||||
print "Size: %6u, Addr: 0x%08x PC: 0x%08x FREE" % (actual_size, int(addr, 0), int(pc, 0))
|
||||
else:
|
||||
print "Size: %6u, Addr: 0x%08x PC: 0x%08x %s:%s" % (actual_size, int(addr, 0), int(pc, 0), filename,
|
||||
linenumber)
|
||||
|
||||
global total_alloc_size
|
||||
global alloc_count
|
||||
global total_free_size
|
||||
global free_count
|
||||
global largest_free_block
|
||||
|
||||
# Capture largest free block size
|
||||
if is_free:
|
||||
total_free_size += actual_size
|
||||
free_count += 1
|
||||
if actual_size > largest_free_block:
|
||||
largest_free_block = actual_size
|
||||
return
|
||||
|
||||
total_alloc_size += actual_size
|
||||
alloc_count += 1
|
||||
|
||||
filename = filename
|
||||
try:
|
||||
per_file_dict[filename] += actual_size
|
||||
except:
|
||||
per_file_dict[filename] = actual_size
|
||||
|
||||
alloc_list.append([int(addr, base=16), actual_size])
|
||||
|
||||
def draw_image():
|
||||
import cairo
|
||||
|
||||
WIDTH, HEIGHT = 2048, 256
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
|
||||
ctx = cairo.Context(surface)
|
||||
|
||||
ctx.set_source_rgb(0.8, 0.8, 0.8)
|
||||
ctx.set_line_width(0)
|
||||
ctx.rectangle(0, 0, WIDTH, HEIGHT)
|
||||
ctx.fill()
|
||||
|
||||
def translate_to_pixels(addr):
|
||||
return (float(addr - min_addr) / float(max_addr - min_addr)) * WIDTH
|
||||
|
||||
def draw_section(start, end):
|
||||
ctx.set_source_rgb(0, 0, 0)
|
||||
ctx.set_line_width(0)
|
||||
ctx.rectangle(start, 0, end - start, HEIGHT)
|
||||
ctx.fill()
|
||||
|
||||
for alloc in alloc_list:
|
||||
addr = alloc[0]
|
||||
size = alloc[1]
|
||||
pixel_start = translate_to_pixels(addr)
|
||||
pixel_end = translate_to_pixels(addr + size)
|
||||
draw_section(pixel_start, pixel_end)
|
||||
|
||||
ctx.stroke()
|
||||
surface.write_to_png("dump_malloc.png")
|
||||
print "Drew image to dump_malloc.png"
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--image', action='store_true')
|
||||
parser.add_argument('--verbose', action='store_true')
|
||||
parser.add_argument('--elf_file', required=True)
|
||||
parser.add_argument('in_file')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
verbose = False
|
||||
if args.verbose is not None:
|
||||
verbose = args.verbose
|
||||
|
||||
elf_path = args.elf_file
|
||||
|
||||
with open(args.in_file, 'r') as f:
|
||||
infile = f.readlines()
|
||||
|
||||
for line in infile:
|
||||
line = line.strip()
|
||||
if len(line) > 0:
|
||||
handle_line(line, verbose)
|
||||
|
||||
if min_addr == 0 or max_addr == 0:
|
||||
min_addr = alloc_list[0][0]
|
||||
max_addr = alloc_list[0][0] + alloc_list[0][1]
|
||||
for alloc in alloc_list:
|
||||
low_addr = alloc[0]
|
||||
if low_addr < min_addr: min_addr = low_addr
|
||||
high_addr = low_addr + alloc[1]
|
||||
if high_addr > max_addr: max_addr = high_addr
|
||||
|
||||
if verbose:
|
||||
print ""
|
||||
print "Heap start: 0x%x" % min_addr
|
||||
print "Heap end: 0x%x" % max_addr
|
||||
print "Heap size: %u bytes" % (max_addr - min_addr)
|
||||
print "Total allocated: %u bytes, %u blocks" % (total_alloc_size, alloc_count);
|
||||
print "High water mark: %u" % high_water_mark
|
||||
print "Total free: %u bytes, %u blocks" % (total_free_size, free_count);
|
||||
print "Largest free block: %u" % largest_free_block
|
||||
print
|
||||
|
||||
per_file_list = [[k, v] for k, v in per_file_dict.iteritems()]
|
||||
sorted_per_file_list = sorted(per_file_list, key=lambda v: v[1], reverse=True)
|
||||
for k, v in sorted_per_file_list:
|
||||
print "%s: %u bytes" % (k, v)
|
||||
|
||||
if args.image:
|
||||
draw_image()
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue