Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'fix/idf_monitor_pc_addr_intervals' into 'master'
Tools: IDF Monitor: Determine possible instruction addresses based on ELF segments Closes IDF-6174 See merge request espressif/esp-idf!21393
- Loading branch information
Showing
11 changed files
with
160 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# 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 potentional addresses which will consequently run through the external addr2line command to | ||
indentify 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: | ||
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 | ||
|
||
# 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 depending on of "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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
cmake_minimum_required(VERSION 3.16) | ||
|
||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
project(monitor_addr_lookup) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | | ||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | |
2 changes: 2 additions & 0 deletions
2
tools/test_apps/system/monitor_addr_lookup/main/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
idf_component_register(SRCS "main.c" | ||
INCLUDE_DIRS "") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Unlicense OR CC0-1.0 | ||
*/ | ||
#include <time.h> | ||
|
||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
|
||
static volatile bool s_initialization_done = false; | ||
|
||
static void initialize(void) | ||
{ | ||
srand(time(0)); | ||
} | ||
|
||
static int get_random_number(void) | ||
{ | ||
if (!s_initialization_done) { | ||
initialize(); | ||
s_initialization_done = true; | ||
} | ||
return rand(); | ||
} | ||
|
||
void app_main(void) | ||
{ | ||
volatile int number = get_random_number(); | ||
int *n = malloc(sizeof(int)); | ||
|
||
assert(n); | ||
|
||
*n = number; | ||
|
||
printf("app_main is running from 0x%x\n", (int) app_main); | ||
printf("Initializer function at 0x%x\n", (int) initialize); | ||
printf("Got %d stored at 0x%x and 0x%x from a function from 0x%x\n", *n, (int) n, (int) (&number), (int) get_random_number); | ||
printf("This is the end of the report\n"); | ||
|
||
free(n); | ||
} |
44 changes: 44 additions & 0 deletions
44
tools/test_apps/system/monitor_addr_lookup/pytest_monitor_addr_lookup.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | ||
# SPDX-License-Identifier: Unlicense OR CC0-1.0 | ||
import os | ||
import re | ||
import sys | ||
|
||
import pexpect | ||
import pytest | ||
from pytest_embedded import Dut | ||
|
||
|
||
@pytest.mark.generic | ||
@pytest.mark.supported_targets | ||
def test_monitor_addr_lookup(config: str, dut: Dut) -> None: | ||
# The port needs to be closed because idf_monitor.py will connect to it | ||
dut.serial.stop_redirect_thread() | ||
|
||
monitor_py = os.path.join(os.environ['IDF_PATH'], 'tools', 'idf_monitor.py') | ||
monitor_cmd = ' '.join([sys.executable, monitor_py, os.path.join(dut.app.binary_path, 'monitor_addr_lookup.elf'), | ||
'--port', str(dut.serial.port)]) | ||
monitor_log_path = os.path.join(dut.logdir, 'monitor.txt') | ||
|
||
with open(monitor_log_path, 'w') as log, pexpect.spawn(monitor_cmd, logfile=log, timeout=5, encoding='utf-8', codec_errors='ignore') as p: | ||
p.expect_exact('main_task: Calling app_main()') | ||
|
||
ADDRESS = '0x[a-f0-9]{8}' | ||
|
||
p.expect(re.compile(r'app_main is running from ({})'.format(ADDRESS))) | ||
a = p.match.group(1) | ||
p.expect_exact('{}: app_main at'.format(a)) | ||
|
||
p.expect(re.compile(r'Initializer function at ({})'.format(ADDRESS))) | ||
a = p.match.group(1) | ||
p.expect_exact('{}: initialize at'.format(a)) | ||
|
||
p.expect(re.compile(r'Got \d+ stored at ({}) and ({}) from a function from ({})'.format(ADDRESS, ADDRESS, ADDRESS))) | ||
var1 = p.match.group(1) | ||
var2 = p.match.group(2) | ||
func = p.match.group(3) | ||
match_index = p.expect([str(var1), str(var2), pexpect.TIMEOUT]) | ||
assert match_index == 2 # should be TIMEOUT because addr2line should not match addresses of variables | ||
p.expect_exact('{}: get_random_number at'.format(func)) | ||
|
||
p.expect_exact('This is the end of the report') |