mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-08 04:02:27 +00:00

Since the introduction of PCAddressMatcher, the executable produced by the build system is passed to elftools.elf.elffile.ELFFile. However on macOS, native executables are not ELF files, so the ELFFile class raises a rather unhelpful AssertionError exception. Given that the rest of the idf_monitor.py doesn't have assumptions that the "elf_file" argument is an ELF file (rather than just an executable), check if the file is a real ELF file inside PCAddressMatcher.
61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
from elftools.elf.constants import SH_FLAGS
|
|
from elftools.elf.elffile import ELFFile
|
|
|
|
|
|
class PcAddressMatcher(object):
|
|
"""
|
|
Class for detecting potential addresses which will consequently run through the external addr2line command to
|
|
identify and print information about it.
|
|
|
|
The input to this class is the path to the ELF file. Addresses of sections with executable flag are stored and
|
|
used later for lookup.
|
|
"""
|
|
|
|
def __init__(self, elf_path): # type: (str) -> None
|
|
self.intervals = []
|
|
try:
|
|
with open(elf_path, 'rb') as f:
|
|
# Is this an ELF file?
|
|
elf_magic = f.read(4)
|
|
if elf_magic != b'\x7fELF':
|
|
# Probably not an ELF file
|
|
# (could be Mach-O format on macOS, for example)
|
|
raise NotImplementedError()
|
|
f.seek(0)
|
|
|
|
elf = ELFFile(f)
|
|
|
|
for section in elf.iter_sections():
|
|
if section['sh_flags'] & SH_FLAGS.SHF_EXECINSTR:
|
|
start = section['sh_addr']
|
|
size = section['sh_size']
|
|
end = start + size
|
|
self.intervals.append((start, end))
|
|
|
|
except FileNotFoundError:
|
|
# ELF file is just an optional argument
|
|
pass
|
|
except NotImplementedError:
|
|
pass
|
|
|
|
# sort them in order to have faster lookup
|
|
self.intervals = sorted(self.intervals)
|
|
|
|
def is_executable_address(self, addr): # type: (int) -> bool
|
|
"""
|
|
Returns True/False if "addr" is in one of the ELF sections with executable flag set.
|
|
"""
|
|
|
|
for start, end in self.intervals:
|
|
if start > addr:
|
|
# The intervals are sorted. This means that loop can end because all remaining intervals starts are
|
|
# greater than the current start
|
|
return False
|
|
if start <= addr < end:
|
|
return True
|
|
|
|
return False
|