mirror of
https://github.com/google/pebble.git
synced 2025-03-15 00:31:21 +00:00
136 lines
4.3 KiB
Python
136 lines
4.3 KiB
Python
#!/usr/bin/env python
|
|
# 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 re
|
|
import sh
|
|
|
|
class SectionInfo(object):
|
|
def __init__(self, name, begin, end):
|
|
self.name = name
|
|
self.begin = begin
|
|
self.end = end
|
|
|
|
def read_section_info(elf_file):
|
|
section_headers_output = sh.arm_none_eabi_readelf('-S', elf_file)
|
|
|
|
line_pattern = re.compile(r"""\[\s*\d+\]\s+ # Number
|
|
(\S+)\s+ # Name
|
|
\S+\s+ # Type
|
|
([0-9a-f]+)\s+ # Virtual Address
|
|
[0-9a-f]+\s+ # Load Address
|
|
([0-9a-f]+)\s+ # Size
|
|
""", flags=re.VERBOSE)
|
|
|
|
sections = []
|
|
|
|
for line in section_headers_output:
|
|
match = line_pattern.search(line)
|
|
|
|
if match is None:
|
|
continue
|
|
|
|
name = match.group(1)
|
|
addr = int(match.group(2), 16)
|
|
size = int(match.group(3), 16)
|
|
|
|
if (addr < 0x20000000 or addr > 0x20030000) and (addr < 0x10000000 or addr > 0x10010000):
|
|
# We only care about stuff that goes into ram or CCM
|
|
continue
|
|
|
|
if (name == 'DISCARD'):
|
|
continue
|
|
|
|
sections.append(SectionInfo(name, addr, addr + size))
|
|
|
|
return sections
|
|
|
|
def find_symbol(word):
|
|
return re.compile(r"""\b({0})$""".format(word)).search
|
|
|
|
def read_layout_symbols(elf_file):
|
|
symbols_output = sh.arm_none_eabi_objdump('-t', elf_file)
|
|
|
|
desired_symbols = [ 'system_stm32f4xx.c',
|
|
'_heap_start',
|
|
'_heap_end' ]
|
|
|
|
symbols = {}
|
|
|
|
line_pattern = re.compile(r"""^(\S+)""")
|
|
|
|
for line in symbols_output:
|
|
for s in desired_symbols:
|
|
if find_symbol(s)(line):
|
|
match = line_pattern.search(line)
|
|
symbols[s] = int(match.group(1), 16)
|
|
|
|
return symbols
|
|
|
|
def analyze_layout(elf_file):
|
|
sections = read_section_info(elf_file)
|
|
symbols = read_layout_symbols(elf_file)
|
|
|
|
ram_start_address = 0x20000000
|
|
ram_end_address = 0x20020000
|
|
|
|
if 'system_stm32f4xx.c' in symbols:
|
|
# We have a snowy! Adjust the RAM size to be larger
|
|
ram_end_address = 0x20030000
|
|
|
|
# Add a dummy section that spans where the kernel heap is
|
|
sections.append(SectionInfo('<KERNEL HEAP>', symbols['_heap_start'], symbols['_heap_end']))
|
|
|
|
sections = sorted(sections, key=lambda x: x.begin)
|
|
|
|
last_end = 0
|
|
padding_total = 0
|
|
|
|
for s in sections:
|
|
if last_end != 0 and last_end != s.begin:
|
|
# There's a gap between sections! Use the last section's name to identify what it is.
|
|
|
|
padding_end = s.begin
|
|
|
|
# Don't insert a padding after CCM and before RAM
|
|
if padding_end != ram_start_address:
|
|
if last_name == '.worker_bss' or last_name == '.workerlib_paddin':
|
|
name = 'WORKER CODE + HEAP'
|
|
else:
|
|
name = 'PADDING'
|
|
padding_total += padding_end - last_end
|
|
|
|
print "0x%x - 0x%x %6u bytes <%s>" % \
|
|
(last_end, padding_end, padding_end - last_end, name)
|
|
|
|
print "0x%x - 0x%x %6u bytes %s" % (s.begin, s.end, s.end - s.begin, s.name)
|
|
|
|
last_end = s.end
|
|
last_name = s.name
|
|
|
|
# The app code + heap region doesn't have a section for it, it just takes up everything at the
|
|
# end of the address space.
|
|
print "0x%x - 0x%x %6u bytes <APP CODE + HEAP>" % (last_end, ram_end_address, ram_end_address - last_end)
|
|
|
|
print 'Total padding: %u bytes' % padding_total
|
|
|
|
if (__name__ == '__main__'):
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('elf_file')
|
|
args = parser.parse_args()
|
|
|
|
sections = analyze_layout(args.elf_file)
|
|
|