Merge branch 'feature/sysview_heap_tracing' into 'master'
SystemView based heap and log tracing See merge request idf/esp-idf!3952
This commit is contained in:
commit
fd91818074
78 changed files with 4515 additions and 3148 deletions
1
.flake8
1
.flake8
|
@ -160,5 +160,4 @@ exclude =
|
||||||
components/wifi_provisioning/python/wifi_constants_pb2.py,
|
components/wifi_provisioning/python/wifi_constants_pb2.py,
|
||||||
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
|
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
|
||||||
# temporary list (should be empty)
|
# temporary list (should be empty)
|
||||||
tools/esp_app_trace/pylibelf,
|
|
||||||
tools/mass_mfg/mfg_gen.py,
|
tools/mass_mfg/mfg_gen.py,
|
||||||
|
|
|
@ -643,6 +643,30 @@ test_espcoredump:
|
||||||
- cd components/espcoredump/test/
|
- cd components/espcoredump/test/
|
||||||
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_espcoredump.sh
|
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_espcoredump.sh
|
||||||
|
|
||||||
|
test_logtrace_proc:
|
||||||
|
<<: *host_test_template
|
||||||
|
artifacts:
|
||||||
|
when: on_failure
|
||||||
|
paths:
|
||||||
|
- tools/esp_app_trace/test/logtrace/output
|
||||||
|
- tools/esp_app_trace/test/logtrace/.coverage
|
||||||
|
expire_in: 1 week
|
||||||
|
script:
|
||||||
|
- cd ${IDF_PATH}/tools/esp_app_trace/test/logtrace
|
||||||
|
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test.sh
|
||||||
|
|
||||||
|
test_sysviewtrace_proc:
|
||||||
|
<<: *host_test_template
|
||||||
|
artifacts:
|
||||||
|
when: on_failure
|
||||||
|
paths:
|
||||||
|
- tools/esp_app_trace/test/sysview/output
|
||||||
|
- tools/esp_app_trace/test/sysview/.coverage
|
||||||
|
expire_in: 1 week
|
||||||
|
script:
|
||||||
|
- cd ${IDF_PATH}/tools/esp_app_trace/test/sysview
|
||||||
|
- ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test.sh
|
||||||
|
|
||||||
push_to_github:
|
push_to_github:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
|
||||||
|
|
|
@ -13,11 +13,17 @@ if(CONFIG_SYSVIEW_ENABLE)
|
||||||
list(APPEND COMPONENT_SRCS "sys_view/SEGGER/SEGGER_SYSVIEW.c"
|
list(APPEND COMPONENT_SRCS "sys_view/SEGGER/SEGGER_SYSVIEW.c"
|
||||||
"sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c"
|
"sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c"
|
||||||
"sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c"
|
"sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c"
|
||||||
"sys_view/esp32/SEGGER_RTT_esp32.c")
|
"sys_view/esp32/SEGGER_RTT_esp32.c"
|
||||||
|
"sys_view/ext/heap_trace_module.c"
|
||||||
|
"sys_view/ext/logging.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_HEAP_TRACING_TOHOST)
|
||||||
|
list(APPEND COMPONENT_SRCS "heap_trace_tohost.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(COMPONENT_REQUIRES)
|
set(COMPONENT_REQUIRES)
|
||||||
set(COMPONENT_PRIV_REQUIRES)
|
set(COMPONENT_PRIV_REQUIRES heap)
|
||||||
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
|
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
|
||||||
|
|
||||||
register_component()
|
register_component()
|
||||||
|
|
|
@ -107,6 +107,14 @@ menu "Application Level Tracing"
|
||||||
help
|
help
|
||||||
Configures maximum supported tasks in sysview debug
|
Configures maximum supported tasks in sysview debug
|
||||||
|
|
||||||
|
config SYSVIEW_BUF_WAIT_TMO
|
||||||
|
int "Trace buffer wait timeout"
|
||||||
|
depends on SYSVIEW_ENABLE
|
||||||
|
default 500
|
||||||
|
help
|
||||||
|
Configures timeout (in us) to wait for free space in trace buffer.
|
||||||
|
Set to -1 to wait forever and avoid lost events.
|
||||||
|
|
||||||
config SYSVIEW_EVT_OVERFLOW_ENABLE
|
config SYSVIEW_EVT_OVERFLOW_ENABLE
|
||||||
bool "Trace Buffer Overflow Event"
|
bool "Trace Buffer Overflow Event"
|
||||||
depends on SYSVIEW_ENABLE
|
depends on SYSVIEW_ENABLE
|
||||||
|
|
|
@ -929,6 +929,9 @@ esp_err_t esp_apptrace_read(esp_apptrace_dest_t dest, void *buf, uint32_t *size,
|
||||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
if (buf == NULL || size == NULL || *size == 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: callback system
|
//TODO: callback system
|
||||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||||
|
@ -963,8 +966,10 @@ uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size,
|
||||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (size == NULL || *size == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// ESP_APPTRACE_LOGE("esp_apptrace_down_buffer_get %d", *size);
|
|
||||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||||
return hw->get_down_buffer(size, &tmo);
|
return hw->get_down_buffer(size, &tmo);
|
||||||
}
|
}
|
||||||
|
@ -985,6 +990,9 @@ esp_err_t esp_apptrace_down_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, u
|
||||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||||
return hw->put_down_buffer(ptr, &tmo);
|
return hw->put_down_buffer(ptr, &tmo);
|
||||||
|
@ -1007,6 +1015,9 @@ esp_err_t esp_apptrace_write(esp_apptrace_dest_t dest, const void *data, uint32_
|
||||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
if (data == NULL || size == 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||||
ptr = hw->get_up_buffer(size, &tmo);
|
ptr = hw->get_up_buffer(size, &tmo);
|
||||||
|
@ -1040,6 +1051,9 @@ int esp_apptrace_vprintf_to(esp_apptrace_dest_t dest, uint32_t user_tmo, const c
|
||||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
if (fmt == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||||
ESP_APPTRACE_LOGD("fmt %x", fmt);
|
ESP_APPTRACE_LOGD("fmt %x", fmt);
|
||||||
|
@ -1101,6 +1115,9 @@ uint8_t *esp_apptrace_buffer_get(esp_apptrace_dest_t dest, uint32_t size, uint32
|
||||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (size == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||||
return hw->get_up_buffer(size, &tmo);
|
return hw->get_up_buffer(size, &tmo);
|
||||||
|
@ -1122,6 +1139,9 @@ esp_err_t esp_apptrace_buffer_put(esp_apptrace_dest_t dest, uint8_t *ptr, uint32
|
||||||
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!");
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
esp_apptrace_tmo_init(&tmo, user_tmo);
|
esp_apptrace_tmo_init(&tmo, user_tmo);
|
||||||
return hw->put_up_buffer(ptr, &tmo);
|
return hw->put_up_buffer(ptr, &tmo);
|
||||||
|
|
|
@ -23,7 +23,8 @@ COMPONENT_SRCDIRS += \
|
||||||
sys_view/SEGGER \
|
sys_view/SEGGER \
|
||||||
sys_view/Sample/OS \
|
sys_view/Sample/OS \
|
||||||
sys_view/Sample/Config \
|
sys_view/Sample/Config \
|
||||||
sys_view/esp32
|
sys_view/esp32 \
|
||||||
|
sys_view/ext
|
||||||
else
|
else
|
||||||
COMPONENT_SRCDIRS += gcov
|
COMPONENT_SRCDIRS += gcov
|
||||||
endif
|
endif
|
||||||
|
|
114
components/app_trace/heap_trace_tohost.c
Normal file
114
components/app_trace/heap_trace_tohost.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
|
||||||
|
#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
|
||||||
|
#include "esp_heap_trace.h"
|
||||||
|
#undef HEAP_TRACE_SRCFILE
|
||||||
|
|
||||||
|
#if CONFIG_SYSVIEW_ENABLE
|
||||||
|
#include "esp_app_trace.h"
|
||||||
|
#include "esp_sysview_trace.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||||
|
|
||||||
|
#ifdef CONFIG_HEAP_TRACING_TOHOST
|
||||||
|
|
||||||
|
#if !CONFIG_SYSVIEW_ENABLE
|
||||||
|
#error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool s_tracing;
|
||||||
|
|
||||||
|
esp_err_t heap_trace_init_tohost()
|
||||||
|
{
|
||||||
|
if (s_tracing) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
|
||||||
|
{
|
||||||
|
#if CONFIG_SYSVIEW_ENABLE
|
||||||
|
esp_err_t ret = esp_sysview_heap_trace_start((uint32_t)-1);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
s_tracing = true;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t heap_trace_stop(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_ERR_NOT_SUPPORTED;
|
||||||
|
#if CONFIG_SYSVIEW_ENABLE
|
||||||
|
ret = esp_sysview_heap_trace_stop();
|
||||||
|
#endif
|
||||||
|
s_tracing = false;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t heap_trace_resume(void)
|
||||||
|
{
|
||||||
|
return heap_trace_start(HEAP_TRACE_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t heap_trace_get_count(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
|
||||||
|
{
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heap_trace_dump(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a new allocation to the heap trace records */
|
||||||
|
static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
|
||||||
|
{
|
||||||
|
if (!s_tracing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if CONFIG_SYSVIEW_ENABLE
|
||||||
|
esp_sysview_heap_trace_alloc(record->address, record->size, record->alloced_by);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* record a free event in the heap trace log
|
||||||
|
|
||||||
|
For HEAP_TRACE_ALL, this means filling in the freed_by pointer.
|
||||||
|
For HEAP_TRACE_LEAKS, this means removing the record from the log.
|
||||||
|
*/
|
||||||
|
static IRAM_ATTR void record_free(void *p, void **callers)
|
||||||
|
{
|
||||||
|
if (!s_tracing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if CONFIG_SYSVIEW_ENABLE
|
||||||
|
esp_sysview_heap_trace_free(p, callers);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "heap_trace.inc"
|
||||||
|
|
||||||
|
#endif /*CONFIG_HEAP_TRACING_TOHOST*/
|
||||||
|
|
|
@ -145,6 +145,9 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char
|
||||||
esp_apptrace_fopen_args_t cmd_args;
|
esp_apptrace_fopen_args_t cmd_args;
|
||||||
|
|
||||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fopen '%s' '%s'", path, mode);
|
ESP_EARLY_LOGV(TAG, "esp_apptrace_fopen '%s' '%s'", path, mode);
|
||||||
|
if (path == NULL || mode == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cmd_args.path = path;
|
cmd_args.path = path;
|
||||||
cmd_args.path_len = strlen(path) + 1;
|
cmd_args.path_len = strlen(path) + 1;
|
||||||
|
@ -213,6 +216,10 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
|
||||||
|
|
||||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);
|
ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);
|
||||||
|
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cmd_args.buf = (void *)ptr;
|
cmd_args.buf = (void *)ptr;
|
||||||
cmd_args.size = size * nmemb;
|
cmd_args.size = size * nmemb;
|
||||||
cmd_args.file = stream;
|
cmd_args.file = stream;
|
||||||
|
@ -248,6 +255,10 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
|
||||||
|
|
||||||
ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);
|
ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);
|
||||||
|
|
||||||
|
if (ptr == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
cmd_args.size = size * nmemb;
|
cmd_args.size = size * nmemb;
|
||||||
cmd_args.file = stream;
|
cmd_args.file = stream;
|
||||||
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
|
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
|
||||||
|
|
80
components/app_trace/include/esp_sysview_trace.h
Normal file
80
components/app_trace/include/esp_sysview_trace.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
#ifndef ESP_SYSVIEW_TRACE_H_
|
||||||
|
#define ESP_SYSVIEW_TRACE_H_
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "SEGGER_RTT.h" // SEGGER_RTT_ESP32_Flush
|
||||||
|
#include "esp_app_trace_util.h" // ESP_APPTRACE_TMO_INFINITE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flushes remaining data in SystemView trace buffer to host.
|
||||||
|
*
|
||||||
|
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||||
|
*
|
||||||
|
* @return ESP_OK.
|
||||||
|
*/
|
||||||
|
static inline esp_err_t esp_sysview_flush(uint32_t tmo)
|
||||||
|
{
|
||||||
|
SEGGER_RTT_ESP32_Flush(0, tmo);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief vprintf-like function to sent log messages to the host.
|
||||||
|
*
|
||||||
|
* @param format Address of format string.
|
||||||
|
* @param args List of arguments.
|
||||||
|
*
|
||||||
|
* @return Number of bytes written.
|
||||||
|
*/
|
||||||
|
int esp_sysview_vprintf(const char * format, va_list args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts SystemView heap tracing.
|
||||||
|
*
|
||||||
|
* @param tmo Timeout (in us) to wait for the host to be connected. Use -1 to wait forever.
|
||||||
|
*
|
||||||
|
* @return ESP_OK on success, ESP_ERR_TIMEOUT if operation has been timed out.
|
||||||
|
*/
|
||||||
|
esp_err_t esp_sysview_heap_trace_start(uint32_t tmo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stops SystemView heap tracing.
|
||||||
|
*
|
||||||
|
* @return ESP_OK.
|
||||||
|
*/
|
||||||
|
esp_err_t esp_sysview_heap_trace_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends heap allocation event to the host.
|
||||||
|
*
|
||||||
|
* @param addr Address of allocated block.
|
||||||
|
* @param size Size of allocated block.
|
||||||
|
* @param callers Pointer to array with callstack addresses.
|
||||||
|
* Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
|
||||||
|
*/
|
||||||
|
void esp_sysview_heap_trace_alloc(void *addr, uint32_t size, const void *callers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends heap de-allocation event to the host.
|
||||||
|
*
|
||||||
|
* @param addr Address of de-allocated block.
|
||||||
|
* @param callers Pointer to array with callstack addresses.
|
||||||
|
* Array size must be CONFIG_HEAP_TRACING_STACK_DEPTH.
|
||||||
|
*/
|
||||||
|
void esp_sysview_heap_trace_free(void *addr, const void *callers);
|
||||||
|
|
||||||
|
#endif //ESP_SYSVIEW_TRACE_H_
|
|
@ -1,7 +1,12 @@
|
||||||
[mapping]
|
[mapping]
|
||||||
archive: libapp_trace.a
|
archive: libapp_trace.a
|
||||||
entries:
|
entries:
|
||||||
* (noflash)
|
app_trace (noflash)
|
||||||
|
app_trace_util (noflash)
|
||||||
|
SEGGER_SYSVIEW (noflash)
|
||||||
|
SEGGER_RTT_esp32 (noflash)
|
||||||
|
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
|
||||||
|
SEGGER_SYSVIEW_FreeRTOS (noflash)
|
||||||
|
|
||||||
[mapping]
|
[mapping]
|
||||||
archive: libdriver.a
|
archive: libdriver.a
|
||||||
|
|
|
@ -160,6 +160,7 @@ unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const voi
|
||||||
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
|
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
|
||||||
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||||
void SEGGER_RTT_ESP32_FlushNoLock (unsigned long min_sz, unsigned long tmo);
|
void SEGGER_RTT_ESP32_FlushNoLock (unsigned long min_sz, unsigned long tmo);
|
||||||
|
void SEGGER_RTT_ESP32_Flush (unsigned long min_sz, unsigned long tmo);
|
||||||
//
|
//
|
||||||
// Function macro for performance optimization
|
// Function macro for performance optimization
|
||||||
//
|
//
|
||||||
|
|
|
@ -1689,6 +1689,10 @@ void SEGGER_SYSVIEW_Stop(void) {
|
||||||
RECORD_END();
|
RECORD_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U8 SEGGER_SYSVIEW_Started(void) {
|
||||||
|
return _SYSVIEW_Globals.EnableState;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
* SEGGER_SYSVIEW_GetSysDesc()
|
* SEGGER_SYSVIEW_GetSysDesc()
|
||||||
|
@ -2678,7 +2682,7 @@ void SEGGER_SYSVIEW_ErrorfTarget(const char* s, ...) {
|
||||||
void SEGGER_SYSVIEW_Print(const char* s) {
|
void SEGGER_SYSVIEW_Print(const char* s) {
|
||||||
U8* pPayload;
|
U8* pPayload;
|
||||||
U8* pPayloadStart;
|
U8* pPayloadStart;
|
||||||
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN);
|
RECORD_START(SEGGER_SYSVIEW_INFO_SIZE + 2 * SEGGER_SYSVIEW_QUANTA_U32 + SEGGER_SYSVIEW_MAX_STRING_LEN + 3/*1 or 3 bytes for string length*/);
|
||||||
//
|
//
|
||||||
pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN);
|
pPayload = _EncodeStr(pPayloadStart, s, SEGGER_SYSVIEW_MAX_STRING_LEN);
|
||||||
ENCODE_U32(pPayload, SEGGER_SYSVIEW_LOG);
|
ENCODE_U32(pPayload, SEGGER_SYSVIEW_LOG);
|
||||||
|
|
|
@ -230,6 +230,8 @@ void SEGGER_SYSVIEW_GetSysDesc (void);
|
||||||
void SEGGER_SYSVIEW_SendTaskList (void);
|
void SEGGER_SYSVIEW_SendTaskList (void);
|
||||||
void SEGGER_SYSVIEW_SendTaskInfo (const SEGGER_SYSVIEW_TASKINFO* pInfo);
|
void SEGGER_SYSVIEW_SendTaskInfo (const SEGGER_SYSVIEW_TASKINFO* pInfo);
|
||||||
void SEGGER_SYSVIEW_SendSysDesc (const char* sSysDesc);
|
void SEGGER_SYSVIEW_SendSysDesc (const char* sSysDesc);
|
||||||
|
// Checks whether tracing has been started
|
||||||
|
U8 SEGGER_SYSVIEW_Started(void);
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
|
|
|
@ -244,8 +244,10 @@ Notes:
|
||||||
#define traceQUEUE_SEND( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0, 0, xCopyPosition)
|
#define traceQUEUE_SEND( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), 0, 0, xCopyPosition)
|
||||||
#endif
|
#endif
|
||||||
#define traceQUEUE_SEND_FAILED( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
|
#define traceQUEUE_SEND_FAILED( pxQueue ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSEND, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, xTicksToWait, xCopyPosition)
|
||||||
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
#define traceQUEUE_SEND_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
|
||||||
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XQUEUEGENERICSENDFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pvItemToQueue, (U32)pxHigherPriorityTaskWoken, xCopyPosition)
|
||||||
|
#define traceQUEUE_GIVE_FROM_ISR( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||||
|
#define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_XQUEUEGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue), (U32)pxHigherPriorityTaskWoken)
|
||||||
|
|
||||||
#if( portSTACK_GROWTH < 0 )
|
#if( portSTACK_GROWTH < 0 )
|
||||||
#define traceTASK_CREATE(pxNewTCB) if (pxNewTCB != NULL) { \
|
#define traceTASK_CREATE(pxNewTCB) if (pxNewTCB != NULL) { \
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "SEGGER_RTT.h"
|
#include "SEGGER_RTT.h"
|
||||||
#include "SEGGER_SYSVIEW.h"
|
#include "SEGGER_SYSVIEW.h"
|
||||||
|
#include "SEGGER_SYSVIEW_Conf.h"
|
||||||
|
|
||||||
#include "esp32/rom/ets_sys.h"
|
#include "esp32/rom/ets_sys.h"
|
||||||
#include "esp_app_trace.h"
|
#include "esp_app_trace.h"
|
||||||
|
@ -27,8 +28,12 @@ const static char *TAG = "segger_rtt";
|
||||||
|
|
||||||
// size of down channel data buf
|
// size of down channel data buf
|
||||||
#define SYSVIEW_DOWN_BUF_SIZE 32
|
#define SYSVIEW_DOWN_BUF_SIZE 32
|
||||||
#define SEGGER_HOST_WAIT_TMO 500 //us
|
|
||||||
#define SEGGER_STOP_WAIT_TMO 1000000 //us
|
#define SEGGER_STOP_WAIT_TMO 1000000 //us
|
||||||
|
#if CONFIG_SYSVIEW_BUF_WAIT_TMO == -1
|
||||||
|
#define SEGGER_HOST_WAIT_TMO ESP_APPTRACE_TMO_INFINITE
|
||||||
|
#else
|
||||||
|
#define SEGGER_HOST_WAIT_TMO CONFIG_SYSVIEW_BUF_WAIT_TMO
|
||||||
|
#endif
|
||||||
|
|
||||||
static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
|
static uint8_t s_events_buf[SYSVIEW_EVENTS_BUF_SZ];
|
||||||
static uint16_t s_events_buf_filled;
|
static uint16_t s_events_buf_filled;
|
||||||
|
@ -57,10 +62,13 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
|
||||||
*/
|
*/
|
||||||
void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo)
|
void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo)
|
||||||
{
|
{
|
||||||
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo);
|
esp_err_t res;
|
||||||
|
if (s_events_buf_filled > 0) {
|
||||||
|
res = esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, s_events_buf, s_events_buf_filled, tmo);
|
||||||
if (res != ESP_OK) {
|
if (res != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res);
|
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!\n", res);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// flush even if we failed to write buffered events, because no new events will be sent after STOP
|
// flush even if we failed to write buffered events, because no new events will be sent after STOP
|
||||||
res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, min_sz, tmo);
|
res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_TRAX, min_sz, tmo);
|
||||||
if (res != ESP_OK) {
|
if (res != ESP_OK) {
|
||||||
|
@ -69,6 +77,27 @@ void SEGGER_RTT_ESP32_FlushNoLock(unsigned long min_sz, unsigned long tmo)
|
||||||
s_events_buf_filled = 0;
|
s_events_buf_filled = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
*
|
||||||
|
* SEGGER_RTT_ESP32_Flush()
|
||||||
|
*
|
||||||
|
* Function description
|
||||||
|
* Flushes buffered events.
|
||||||
|
*
|
||||||
|
* Parameters
|
||||||
|
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
|
||||||
|
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
|
||||||
|
*
|
||||||
|
* Return value
|
||||||
|
* None.
|
||||||
|
*/
|
||||||
|
void SEGGER_RTT_ESP32_Flush(unsigned long min_sz, unsigned long tmo)
|
||||||
|
{
|
||||||
|
SEGGER_SYSVIEW_LOCK();
|
||||||
|
SEGGER_RTT_ESP32_FlushNoLock(min_sz, tmo);
|
||||||
|
SEGGER_SYSVIEW_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
* SEGGER_RTT_ReadNoLock()
|
* SEGGER_RTT_ReadNoLock()
|
||||||
|
|
100
components/app_trace/sys_view/ext/heap_trace_module.c
Normal file
100
components/app_trace/sys_view/ext/heap_trace_module.c
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include "SEGGER_SYSVIEW.h"
|
||||||
|
#include "SEGGER_RTT.h"
|
||||||
|
#include "esp_app_trace.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
const static char *TAG = "sysview_heap_trace";
|
||||||
|
|
||||||
|
#ifdef CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||||
|
#define CALLSTACK_SIZE CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||||
|
#else
|
||||||
|
#define CALLSTACK_SIZE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
|
||||||
|
.sModule = "ESP32 SystemView Heap Tracing Module",
|
||||||
|
.NumEvents = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool s_mod_registered;
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_sysview_heap_trace_start(uint32_t tmo)
|
||||||
|
{
|
||||||
|
uint32_t tmo_ticks = tmo/(1000*portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
ESP_EARLY_LOGV(TAG, "%s", __func__);
|
||||||
|
do {
|
||||||
|
if (tmo != (uint32_t)-1) {
|
||||||
|
// Currently timeout implementation is simple and has granularity of 1 OS tick,
|
||||||
|
// so just count down the number of times to call vTaskDelay
|
||||||
|
if (tmo_ticks-- == 0) {
|
||||||
|
return ESP_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelay(1);
|
||||||
|
} while(!SEGGER_SYSVIEW_Started());
|
||||||
|
|
||||||
|
SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module);
|
||||||
|
s_mod_registered = true;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_sysview_heap_trace_stop(void)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGV(TAG, "%s", __func__);
|
||||||
|
SEGGER_RTT_ESP32_Flush(0, ESP_APPTRACE_TMO_INFINITE);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers)
|
||||||
|
{
|
||||||
|
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
|
||||||
|
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
|
||||||
|
U32 *calls = (U32 *)callers;
|
||||||
|
|
||||||
|
if (!s_mod_registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_EARLY_LOGV(TAG, "%s %p %lu", __func__, addr, size);
|
||||||
|
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
|
||||||
|
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, size);
|
||||||
|
for (int i = 0; i < CALLSTACK_SIZE; i++) {
|
||||||
|
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
|
||||||
|
}
|
||||||
|
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sysview_heap_trace_free(const void *addr, const void *callers)
|
||||||
|
{
|
||||||
|
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
|
||||||
|
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
|
||||||
|
U32 *calls = (U32 *)callers;
|
||||||
|
|
||||||
|
if (!s_mod_registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ESP_EARLY_LOGV(TAG, "%s %p", __func__, addr);
|
||||||
|
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, (U32)addr);
|
||||||
|
for (int i = 0; i < CALLSTACK_SIZE; i++) {
|
||||||
|
pPayload = SEGGER_SYSVIEW_EncodeU32(pPayload, calls[i]);
|
||||||
|
}
|
||||||
|
SEGGER_SYSVIEW_SendPacket(&aPacket[0], pPayload, s_esp_sysview_heap_module.EventOffset + 1);
|
||||||
|
}
|
34
components/app_trace/sys_view/ext/logging.c
Normal file
34
components/app_trace/sys_view/ext/logging.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include "SEGGER_SYSVIEW_Int.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
|
||||||
|
static portMUX_TYPE s_log_mutex = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
|
int esp_sysview_vprintf(const char * format, va_list args)
|
||||||
|
{
|
||||||
|
static char log_buffer[SEGGER_SYSVIEW_MAX_STRING_LEN];
|
||||||
|
|
||||||
|
portENTER_CRITICAL(&s_log_mutex);
|
||||||
|
size_t len = vsnprintf(log_buffer, sizeof(log_buffer), format, args);
|
||||||
|
if (len > sizeof(log_buffer) - 1) {
|
||||||
|
log_buffer[sizeof(log_buffer - 1)] = 0;
|
||||||
|
}
|
||||||
|
SEGGER_SYSVIEW_Print(log_buffer);
|
||||||
|
portEXIT_CRITICAL(&s_log_mutex);
|
||||||
|
return len;
|
||||||
|
}
|
|
@ -514,6 +514,14 @@ extern "C" {
|
||||||
#define traceTASK_CREATE( pxNewTCB )
|
#define traceTASK_CREATE( pxNewTCB )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceQUEUE_GIVE_FROM_ISR
|
||||||
|
#define traceQUEUE_GIVE_FROM_ISR( pxQueue )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef traceQUEUE_GIVE_FROM_ISR_FAILED
|
||||||
|
#define traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue )
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef traceTASK_CREATE_FAILED
|
#ifndef traceTASK_CREATE_FAILED
|
||||||
#define traceTASK_CREATE_FAILED()
|
#define traceTASK_CREATE_FAILED()
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1333,7 +1333,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||||
space'. */
|
space'. */
|
||||||
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
|
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
|
||||||
{
|
{
|
||||||
traceQUEUE_SEND_FROM_ISR( pxQueue );
|
traceQUEUE_GIVE_FROM_ISR( pxQueue );
|
||||||
|
|
||||||
/* A task can only have an inherited priority if it is a mutex
|
/* A task can only have an inherited priority if it is a mutex
|
||||||
holder - and if there is a mutex holder then the mutex cannot be
|
holder - and if there is a mutex holder then the mutex cannot be
|
||||||
|
@ -1427,7 +1427,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
|
traceQUEUE_GIVE_FROM_ISR_FAILED( pxQueue );
|
||||||
xReturn = errQUEUE_FULL;
|
xReturn = errQUEUE_FULL;
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL_ISR(&pxQueue->mux);
|
taskEXIT_CRITICAL_ISR(&pxQueue->mux);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
set(COMPONENT_SRCS "heap_caps.c"
|
set(COMPONENT_SRCS "heap_caps.c"
|
||||||
"heap_caps_init.c"
|
"heap_caps_init.c"
|
||||||
"heap_trace.c"
|
|
||||||
"multi_heap.c")
|
"multi_heap.c")
|
||||||
|
|
||||||
if(NOT CONFIG_HEAP_POISONING_DISABLED)
|
if(NOT CONFIG_HEAP_POISONING_DISABLED)
|
||||||
|
@ -11,6 +10,10 @@ if(CONFIG_HEAP_TASK_TRACKING)
|
||||||
list(APPEND COMPONENT_SRCS "heap_task_info.c")
|
list(APPEND COMPONENT_SRCS "heap_task_info.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_HEAP_TRACING_STANDALONE)
|
||||||
|
list(APPEND COMPONENT_SRCS "heap_trace_standalone.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
||||||
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
|
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
|
||||||
set(COMPONENT_REQUIRES "")
|
set(COMPONENT_REQUIRES "")
|
||||||
|
|
|
@ -17,14 +17,31 @@ menu "Heap memory debugging"
|
||||||
bool "Comprehensive"
|
bool "Comprehensive"
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config HEAP_TRACING
|
choice HEAP_TRACING_DEST
|
||||||
bool "Enable heap tracing"
|
bool "Heap tracing"
|
||||||
|
default HEAP_TRACING_OFF
|
||||||
help
|
help
|
||||||
Enables the heap tracing API defined in esp_heap_trace.h.
|
Enables the heap tracing API defined in esp_heap_trace.h.
|
||||||
|
|
||||||
This function causes a moderate increase in IRAM code side and a minor increase in heap function
|
This function causes a moderate increase in IRAM code side and a minor increase in heap function
|
||||||
(malloc/free/realloc) CPU overhead, even when the tracing feature is not used. So it's best to keep it
|
(malloc/free/realloc) CPU overhead, even when the tracing feature is not used.
|
||||||
disabled unless tracing is being used.
|
So it's best to keep it disabled unless tracing is being used.
|
||||||
|
|
||||||
|
config HEAP_TRACING_OFF
|
||||||
|
bool "Disabled"
|
||||||
|
config HEAP_TRACING_STANDALONE
|
||||||
|
bool "Standalone"
|
||||||
|
select HEAP_TRACING
|
||||||
|
config HEAP_TRACING_TOHOST
|
||||||
|
bool "Host-based"
|
||||||
|
select HEAP_TRACING
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config HEAP_TRACING
|
||||||
|
bool
|
||||||
|
default F
|
||||||
|
help
|
||||||
|
Enables/disables heap tracing API.
|
||||||
|
|
||||||
config HEAP_TRACING_STACK_DEPTH
|
config HEAP_TRACING_STACK_DEPTH
|
||||||
int "Heap tracing stack depth"
|
int "Heap tracing stack depth"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Component Makefile
|
# Component Makefile
|
||||||
#
|
#
|
||||||
|
|
||||||
COMPONENT_OBJS := heap_caps_init.o heap_caps.o multi_heap.o heap_trace.o
|
COMPONENT_OBJS := heap_caps_init.o heap_caps.o multi_heap.o
|
||||||
|
|
||||||
ifndef CONFIG_HEAP_POISONING_DISABLED
|
ifndef CONFIG_HEAP_POISONING_DISABLED
|
||||||
COMPONENT_OBJS += multi_heap_poisoning.o
|
COMPONENT_OBJS += multi_heap_poisoning.o
|
||||||
|
@ -12,6 +12,12 @@ COMPONENT_OBJS += heap_task_info.o
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_HEAP_TRACING_STANDALONE
|
||||||
|
|
||||||
|
COMPONENT_OBJS += heap_trace_standalone.o
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_HEAP_TRACING
|
ifdef CONFIG_HEAP_TRACING
|
||||||
|
|
||||||
WRAP_FUNCTIONS = calloc malloc free realloc heap_caps_malloc heap_caps_free heap_caps_realloc heap_caps_malloc_default heap_caps_realloc_default
|
WRAP_FUNCTIONS = calloc malloc free realloc heap_caps_malloc heap_caps_free heap_caps_realloc heap_caps_malloc_default heap_caps_realloc_default
|
||||||
|
|
|
@ -12,23 +12,21 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sdkconfig.h>
|
#include <sdkconfig.h>
|
||||||
|
|
||||||
#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
|
#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
|
||||||
#include "esp_heap_trace.h"
|
#include "esp_heap_trace.h"
|
||||||
#undef HEAP_TRACE_SRCFILE
|
#undef HEAP_TRACE_SRCFILE
|
||||||
|
|
||||||
#include "esp_heap_caps.h"
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "soc/soc_memory_layout.h"
|
|
||||||
|
|
||||||
#include "heap_private.h"
|
|
||||||
|
|
||||||
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
|
#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
|
||||||
|
|
||||||
|
#if CONFIG_HEAP_TRACING_STANDALONE
|
||||||
|
|
||||||
static portMUX_TYPE trace_mux = portMUX_INITIALIZER_UNLOCKED;
|
static portMUX_TYPE trace_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
static bool tracing;
|
static bool tracing;
|
||||||
static heap_trace_mode_t mode;
|
static heap_trace_mode_t mode;
|
||||||
|
@ -55,10 +53,6 @@ static bool has_overflowed = false;
|
||||||
|
|
||||||
esp_err_t heap_trace_init_standalone(heap_trace_record_t *record_buffer, size_t num_records)
|
esp_err_t heap_trace_init_standalone(heap_trace_record_t *record_buffer, size_t num_records)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_HEAP_TRACING
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
@ -70,13 +64,10 @@ esp_err_t heap_trace_init_standalone(heap_trace_record_t *record_buffer, size_t
|
||||||
|
|
||||||
esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
|
esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_HEAP_TRACING
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (buffer == NULL || total_records == 0) {
|
if (buffer == NULL || total_records == 0) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
portENTER_CRITICAL(&trace_mux);
|
portENTER_CRITICAL(&trace_mux);
|
||||||
|
|
||||||
tracing = false;
|
tracing = false;
|
||||||
|
@ -93,9 +84,6 @@ esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
|
||||||
|
|
||||||
static esp_err_t set_tracing(bool enable)
|
static esp_err_t set_tracing(bool enable)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_HEAP_TRACING
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
#endif
|
|
||||||
if (tracing == enable) {
|
if (tracing == enable) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
@ -120,9 +108,6 @@ size_t heap_trace_get_count(void)
|
||||||
|
|
||||||
esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
|
esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_HEAP_TRACING
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
#endif
|
|
||||||
if (record == NULL) {
|
if (record == NULL) {
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
@ -141,10 +126,6 @@ esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
|
||||||
|
|
||||||
void heap_trace_dump(void)
|
void heap_trace_dump(void)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_HEAP_TRACING
|
|
||||||
printf("no data, heap tracing is disabled.\n");
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
size_t delta_size = 0;
|
size_t delta_size = 0;
|
||||||
size_t delta_allocs = 0;
|
size_t delta_allocs = 0;
|
||||||
printf("%u allocations trace (%u entry buffer)\n",
|
printf("%u allocations trace (%u entry buffer)\n",
|
||||||
|
@ -192,6 +173,10 @@ void heap_trace_dump(void)
|
||||||
/* Add a new allocation to the heap trace records */
|
/* Add a new allocation to the heap trace records */
|
||||||
static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
|
static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
|
||||||
{
|
{
|
||||||
|
if (!tracing || record->address == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
portENTER_CRITICAL(&trace_mux);
|
portENTER_CRITICAL(&trace_mux);
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
if (count == total_records) {
|
if (count == total_records) {
|
||||||
|
@ -224,6 +209,10 @@ static void remove_record(int index);
|
||||||
*/
|
*/
|
||||||
static IRAM_ATTR void record_free(void *p, void **callers)
|
static IRAM_ATTR void record_free(void *p, void **callers)
|
||||||
{
|
{
|
||||||
|
if (!tracing || p == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
portENTER_CRITICAL(&trace_mux);
|
portENTER_CRITICAL(&trace_mux);
|
||||||
if (tracing && count > 0) {
|
if (tracing && count > 0) {
|
||||||
total_frees++;
|
total_frees++;
|
||||||
|
@ -261,179 +250,6 @@ static IRAM_ATTR void remove_record(int index)
|
||||||
count--;
|
count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Encode the CPU ID in the LSB of the ccount value */
|
#include "heap_trace.inc"
|
||||||
inline static uint32_t get_ccount(void)
|
|
||||||
{
|
|
||||||
uint32_t ccount = xthal_get_ccount() & ~3;
|
|
||||||
#ifndef CONFIG_FREERTOS_UNICORE
|
|
||||||
ccount |= xPortGetCoreID();
|
|
||||||
#endif
|
|
||||||
return ccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Caller is 2 stack frames deeper than we care about
|
#endif /*CONFIG_HEAP_TRACING_STANDALONE*/
|
||||||
#define STACK_OFFSET 2
|
|
||||||
|
|
||||||
#define TEST_STACK(N) do { \
|
|
||||||
if (STACK_DEPTH == N) { \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
callers[N] = __builtin_return_address(N+STACK_OFFSET); \
|
|
||||||
if (!esp_ptr_executable(callers[N])) { \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/* Static function to read the call stack for a traced heap call.
|
|
||||||
|
|
||||||
Calls to __builtin_return_address are "unrolled" via TEST_STACK macro as gcc requires the
|
|
||||||
argument to be a compile-time constant.
|
|
||||||
*/
|
|
||||||
static IRAM_ATTR __attribute__((noinline)) void get_call_stack(void **callers)
|
|
||||||
{
|
|
||||||
bzero(callers, sizeof(void *) * STACK_DEPTH);
|
|
||||||
TEST_STACK(0);
|
|
||||||
TEST_STACK(1);
|
|
||||||
TEST_STACK(2);
|
|
||||||
TEST_STACK(3);
|
|
||||||
TEST_STACK(4);
|
|
||||||
TEST_STACK(5);
|
|
||||||
TEST_STACK(6);
|
|
||||||
TEST_STACK(7);
|
|
||||||
TEST_STACK(8);
|
|
||||||
TEST_STACK(9);
|
|
||||||
}
|
|
||||||
|
|
||||||
_Static_assert(STACK_DEPTH >= 0 && STACK_DEPTH <= 10, "CONFIG_HEAP_TRACING_STACK_DEPTH must be in range 0-10");
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TRACE_MALLOC_CAPS,
|
|
||||||
TRACE_MALLOC_DEFAULT
|
|
||||||
} trace_malloc_mode_t;
|
|
||||||
|
|
||||||
|
|
||||||
void *__real_heap_caps_malloc(size_t size, uint32_t caps);
|
|
||||||
void *__real_heap_caps_malloc_default( size_t size );
|
|
||||||
void *__real_heap_caps_realloc_default( void *ptr, size_t size );
|
|
||||||
|
|
||||||
/* trace any 'malloc' event */
|
|
||||||
static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint32_t caps, trace_malloc_mode_t mode)
|
|
||||||
{
|
|
||||||
uint32_t ccount = get_ccount();
|
|
||||||
void *p;
|
|
||||||
if ( mode == TRACE_MALLOC_CAPS ) {
|
|
||||||
p = __real_heap_caps_malloc(size, caps);
|
|
||||||
} else { //TRACE_MALLOC_DEFAULT
|
|
||||||
p = __real_heap_caps_malloc_default(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tracing && p != NULL) {
|
|
||||||
heap_trace_record_t rec = {
|
|
||||||
.address = p,
|
|
||||||
.ccount = ccount,
|
|
||||||
.size = size,
|
|
||||||
};
|
|
||||||
get_call_stack(rec.alloced_by);
|
|
||||||
record_allocation(&rec);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __real_heap_caps_free(void *p);
|
|
||||||
|
|
||||||
/* trace any 'free' event */
|
|
||||||
static IRAM_ATTR __attribute__((noinline)) void trace_free(void *p)
|
|
||||||
{
|
|
||||||
if (tracing && p != NULL) {
|
|
||||||
void *callers[STACK_DEPTH];
|
|
||||||
get_call_stack(callers);
|
|
||||||
record_free(p, callers);
|
|
||||||
}
|
|
||||||
__real_heap_caps_free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void * __real_heap_caps_realloc(void *p, size_t size, uint32_t caps);
|
|
||||||
|
|
||||||
/* trace any 'realloc' event */
|
|
||||||
static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t size, uint32_t caps, trace_malloc_mode_t mode)
|
|
||||||
{
|
|
||||||
void *callers[STACK_DEPTH];
|
|
||||||
uint32_t ccount = get_ccount();
|
|
||||||
if (tracing && p != NULL && size == 0) {
|
|
||||||
get_call_stack(callers);
|
|
||||||
record_free(p, callers);
|
|
||||||
}
|
|
||||||
void *r;
|
|
||||||
if (mode == TRACE_MALLOC_CAPS ) {
|
|
||||||
r = __real_heap_caps_realloc(p, size, caps);
|
|
||||||
} else { //TRACE_MALLOC_DEFAULT
|
|
||||||
r = __real_heap_caps_realloc_default(p, size);
|
|
||||||
}
|
|
||||||
if (tracing && r != NULL) {
|
|
||||||
get_call_stack(callers);
|
|
||||||
if (p != NULL) {
|
|
||||||
/* trace realloc as free-then-alloc */
|
|
||||||
record_free(p, callers);
|
|
||||||
}
|
|
||||||
heap_trace_record_t rec = {
|
|
||||||
.address = r,
|
|
||||||
.ccount = ccount,
|
|
||||||
.size = size,
|
|
||||||
};
|
|
||||||
memcpy(rec.alloced_by, callers, sizeof(void *) * STACK_DEPTH);
|
|
||||||
record_allocation(&rec);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: this changes the behaviour of libc malloc/realloc/free a bit,
|
|
||||||
as they no longer go via the libc functions in ROM. But more or less
|
|
||||||
the same in the end. */
|
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_malloc(size_t size)
|
|
||||||
{
|
|
||||||
return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
IRAM_ATTR void __wrap_free(void *p)
|
|
||||||
{
|
|
||||||
trace_free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_realloc(void *p, size_t size)
|
|
||||||
{
|
|
||||||
return trace_realloc(p, size, 0, TRACE_MALLOC_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_calloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
size = size * nmemb;
|
|
||||||
void *result = trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
|
||||||
if (result != NULL) {
|
|
||||||
memset(result, 0, size);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_heap_caps_malloc(size_t size, uint32_t caps)
|
|
||||||
{
|
|
||||||
return trace_malloc(size, caps, TRACE_MALLOC_CAPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __wrap_heap_caps_free(void *p) __attribute__((alias("__wrap_free")));
|
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_heap_caps_realloc(void *p, size_t size, uint32_t caps)
|
|
||||||
{
|
|
||||||
return trace_realloc(p, size, caps, TRACE_MALLOC_CAPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_heap_caps_malloc_default( size_t size )
|
|
||||||
{
|
|
||||||
return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
IRAM_ATTR void *__wrap_heap_caps_realloc_default( void *ptr, size_t size )
|
|
||||||
{
|
|
||||||
return trace_realloc(ptr, size, 0, TRACE_MALLOC_DEFAULT);
|
|
||||||
}
|
|
|
@ -47,7 +47,6 @@ typedef struct {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialise heap tracing in standalone mode.
|
* @brief Initialise heap tracing in standalone mode.
|
||||||
* @note Standalone mode is the only mode currently supported.
|
|
||||||
*
|
*
|
||||||
* This function must be called before any other heap tracing functions.
|
* This function must be called before any other heap tracing functions.
|
||||||
*
|
*
|
||||||
|
@ -63,6 +62,17 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
esp_err_t heap_trace_init_standalone(heap_trace_record_t *record_buffer, size_t num_records);
|
esp_err_t heap_trace_init_standalone(heap_trace_record_t *record_buffer, size_t num_records);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialise heap tracing in host-based mode.
|
||||||
|
*
|
||||||
|
* This function must be called before any other heap tracing functions.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_ERR_INVALID_STATE Heap tracing is currently in progress.
|
||||||
|
* - ESP_OK Heap tracing initialised successfully.
|
||||||
|
*/
|
||||||
|
esp_err_t heap_trace_init_tohost(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start heap tracing. All heap allocations & frees will be traced, until heap_trace_stop() is called.
|
* @brief Start heap tracing. All heap allocations & frees will be traced, until heap_trace_stop() is called.
|
||||||
*
|
*
|
||||||
|
|
189
components/heap/include/heap_trace.inc
Normal file
189
components/heap/include/heap_trace.inc
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
#include <string.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include "soc/soc_memory_layout.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
|
||||||
|
/* Encode the CPU ID in the LSB of the ccount value */
|
||||||
|
inline static uint32_t get_ccount(void)
|
||||||
|
{
|
||||||
|
uint32_t ccount = xthal_get_ccount() & ~3;
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
ccount |= xPortGetCoreID();
|
||||||
|
#endif
|
||||||
|
return ccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caller is 2 stack frames deeper than we care about
|
||||||
|
#define STACK_OFFSET 2
|
||||||
|
|
||||||
|
#define TEST_STACK(N) do { \
|
||||||
|
if (STACK_DEPTH == N) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
callers[N] = __builtin_return_address(N+STACK_OFFSET); \
|
||||||
|
if (!esp_ptr_executable(callers[N])) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* Static function to read the call stack for a traced heap call.
|
||||||
|
|
||||||
|
Calls to __builtin_return_address are "unrolled" via TEST_STACK macro as gcc requires the
|
||||||
|
argument to be a compile-time constant.
|
||||||
|
*/
|
||||||
|
static IRAM_ATTR __attribute__((noinline)) void get_call_stack(void **callers)
|
||||||
|
{
|
||||||
|
bzero(callers, sizeof(void *) * STACK_DEPTH);
|
||||||
|
TEST_STACK(0);
|
||||||
|
TEST_STACK(1);
|
||||||
|
TEST_STACK(2);
|
||||||
|
TEST_STACK(3);
|
||||||
|
TEST_STACK(4);
|
||||||
|
TEST_STACK(5);
|
||||||
|
TEST_STACK(6);
|
||||||
|
TEST_STACK(7);
|
||||||
|
TEST_STACK(8);
|
||||||
|
TEST_STACK(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Static_assert(STACK_DEPTH >= 0 && STACK_DEPTH <= 10, "CONFIG_HEAP_TRACING_STACK_DEPTH must be in range 0-10");
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TRACE_MALLOC_CAPS,
|
||||||
|
TRACE_MALLOC_DEFAULT
|
||||||
|
} trace_malloc_mode_t;
|
||||||
|
|
||||||
|
|
||||||
|
void *__real_heap_caps_malloc(size_t size, uint32_t caps);
|
||||||
|
void *__real_heap_caps_malloc_default( size_t size );
|
||||||
|
void *__real_heap_caps_realloc_default( void *ptr, size_t size );
|
||||||
|
|
||||||
|
/* trace any 'malloc' event */
|
||||||
|
static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint32_t caps, trace_malloc_mode_t mode)
|
||||||
|
{
|
||||||
|
uint32_t ccount = get_ccount();
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if ( mode == TRACE_MALLOC_CAPS ) {
|
||||||
|
p = __real_heap_caps_malloc(size, caps);
|
||||||
|
} else { //TRACE_MALLOC_DEFAULT
|
||||||
|
p = __real_heap_caps_malloc_default(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_trace_record_t rec = {
|
||||||
|
.address = p,
|
||||||
|
.ccount = ccount,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
get_call_stack(rec.alloced_by);
|
||||||
|
record_allocation(&rec);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __real_heap_caps_free(void *p);
|
||||||
|
|
||||||
|
/* trace any 'free' event */
|
||||||
|
static IRAM_ATTR __attribute__((noinline)) void trace_free(void *p)
|
||||||
|
{
|
||||||
|
void *callers[STACK_DEPTH];
|
||||||
|
get_call_stack(callers);
|
||||||
|
record_free(p, callers);
|
||||||
|
|
||||||
|
__real_heap_caps_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void * __real_heap_caps_realloc(void *p, size_t size, uint32_t caps);
|
||||||
|
|
||||||
|
/* trace any 'realloc' event */
|
||||||
|
static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t size, uint32_t caps, trace_malloc_mode_t mode)
|
||||||
|
{
|
||||||
|
void *callers[STACK_DEPTH];
|
||||||
|
uint32_t ccount = get_ccount();
|
||||||
|
void *r;
|
||||||
|
|
||||||
|
/* trace realloc as free-then-alloc */
|
||||||
|
get_call_stack(callers);
|
||||||
|
record_free(p, callers);
|
||||||
|
|
||||||
|
if (mode == TRACE_MALLOC_CAPS ) {
|
||||||
|
r = __real_heap_caps_realloc(p, size, caps);
|
||||||
|
} else { //TRACE_MALLOC_DEFAULT
|
||||||
|
r = __real_heap_caps_realloc_default(p, size);
|
||||||
|
}
|
||||||
|
/* realloc with zero size is a free */
|
||||||
|
if (size != 0) {
|
||||||
|
heap_trace_record_t rec = {
|
||||||
|
.address = r,
|
||||||
|
.ccount = ccount,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
memcpy(rec.alloced_by, callers, sizeof(void *) * STACK_DEPTH);
|
||||||
|
record_allocation(&rec);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: this changes the behaviour of libc malloc/realloc/free a bit,
|
||||||
|
as they no longer go via the libc functions in ROM. But more or less
|
||||||
|
the same in the end. */
|
||||||
|
|
||||||
|
IRAM_ATTR void *__wrap_malloc(size_t size)
|
||||||
|
{
|
||||||
|
return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void __wrap_free(void *p)
|
||||||
|
{
|
||||||
|
trace_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void *__wrap_realloc(void *p, size_t size)
|
||||||
|
{
|
||||||
|
return trace_realloc(p, size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void *__wrap_calloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
size = size * nmemb;
|
||||||
|
void *result = trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
|
if (result != NULL) {
|
||||||
|
memset(result, 0, size);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void *__wrap_heap_caps_malloc(size_t size, uint32_t caps)
|
||||||
|
{
|
||||||
|
return trace_malloc(size, caps, TRACE_MALLOC_CAPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __wrap_heap_caps_free(void *p) __attribute__((alias("__wrap_free")));
|
||||||
|
|
||||||
|
IRAM_ATTR void *__wrap_heap_caps_realloc(void *p, size_t size, uint32_t caps)
|
||||||
|
{
|
||||||
|
return trace_realloc(p, size, caps, TRACE_MALLOC_CAPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void *__wrap_heap_caps_malloc_default( size_t size )
|
||||||
|
{
|
||||||
|
return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRAM_ATTR void *__wrap_heap_caps_realloc_default( void *ptr, size_t size )
|
||||||
|
{
|
||||||
|
return trace_realloc(ptr, size, 0, TRACE_MALLOC_DEFAULT);
|
||||||
|
}
|
|
@ -184,6 +184,7 @@ INPUT = \
|
||||||
## Application Level Tracing - API Reference
|
## Application Level Tracing - API Reference
|
||||||
##
|
##
|
||||||
../../components/app_trace/include/esp_app_trace.h \
|
../../components/app_trace/include/esp_app_trace.h \
|
||||||
|
../../components/app_trace/include/esp_sysview_trace.h \
|
||||||
### Power management
|
### Power management
|
||||||
../../components/esp_common/include/esp_pm.h \
|
../../components/esp_common/include/esp_pm.h \
|
||||||
../../components/esp32/include/esp32/pm.h \
|
../../components/esp32/include/esp32/pm.h \
|
||||||
|
|
|
@ -15,4 +15,5 @@ API Reference
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
.. include:: /_build/inc/esp_app_trace.inc
|
.. include:: /_build/inc/esp_app_trace.inc
|
||||||
|
.. include:: /_build/inc/esp_sysview_trace.inc
|
||||||
|
|
||||||
|
|
|
@ -122,11 +122,10 @@ Calls to :cpp:func:`heap_caps_check_integrity` may print errors relating to 0xFE
|
||||||
Heap Tracing
|
Heap Tracing
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Heap Tracing allows tracing of code which allocates/frees memory.
|
Heap Tracing allows tracing of code which allocates/frees memory. Two tracing modes are supported:
|
||||||
|
|
||||||
.. note::
|
- Standalone. In this mode trace data are kept on-board, so the size of gathered information is limited by the buffer assigned for that purposes. Analysis is done by the on-board code. There are a couple of APIs available for accessing and dumping collected info.
|
||||||
|
- Host-based. This mode does not have the limitation of the standalone mode, because trace data are sent to the host over JTAG connection using app_trace library. Later on they can be analysed using special tools.
|
||||||
Heap tracing "standalone" mode is currently implemented, meaning that tracing does not require any external hardware but uses internal memory to hold trace data. Heap tracing via JTAG trace port is also planned.
|
|
||||||
|
|
||||||
Heap tracing can perform two functions:
|
Heap tracing can perform two functions:
|
||||||
|
|
||||||
|
@ -138,9 +137,13 @@ How To Diagnose Memory Leaks
|
||||||
|
|
||||||
If you suspect a memory leak, the first step is to figure out which part of the program is leaking memory. Use the :cpp:func:`xPortGetFreeHeapSize`, :cpp:func:`heap_caps_get_free_size`, or :ref:`related functions <heap-information>` to track memory use over the life of the application. Try to narrow the leak down to a single function or sequence of functions where free memory always decreases and never recovers.
|
If you suspect a memory leak, the first step is to figure out which part of the program is leaking memory. Use the :cpp:func:`xPortGetFreeHeapSize`, :cpp:func:`heap_caps_get_free_size`, or :ref:`related functions <heap-information>` to track memory use over the life of the application. Try to narrow the leak down to a single function or sequence of functions where free memory always decreases and never recovers.
|
||||||
|
|
||||||
|
|
||||||
|
Standalone Mode
|
||||||
|
+++++++++++++++
|
||||||
|
|
||||||
Once you've identified the code which you think is leaking:
|
Once you've identified the code which you think is leaking:
|
||||||
|
|
||||||
- Under ``make menuconfig``, navigate to ``Component settings`` -> ``Heap Memory Debugging`` and set :ref:`CONFIG_HEAP_TRACING`.
|
- Under ``make menuconfig``, navigate to ``Component settings`` -> ``Heap Memory Debugging`` -> ``Heap tracing`` and select ``Standalone`` option (see :ref:`CONFIG_HEAP_TRACING_DEST`).
|
||||||
- Call the function :cpp:func:`heap_trace_init_standalone` early in the program, to register a buffer which can be used to record the memory trace.
|
- Call the function :cpp:func:`heap_trace_init_standalone` early in the program, to register a buffer which can be used to record the memory trace.
|
||||||
- Call the function :cpp:func:`heap_trace_start` to begin recording all mallocs/frees in the system. Call this immediately before the piece of code which you suspect is leaking memory.
|
- Call the function :cpp:func:`heap_trace_start` to begin recording all mallocs/frees in the system. Call this immediately before the piece of code which you suspect is leaking memory.
|
||||||
- Call the function :cpp:func:`heap_trace_stop` to stop the trace once the suspect piece of code has finished executing.
|
- Call the function :cpp:func:`heap_trace_stop` to stop the trace once the suspect piece of code has finished executing.
|
||||||
|
@ -208,6 +211,164 @@ Finally, the total number of 'leaked' bytes (bytes allocated but not freed while
|
||||||
|
|
||||||
A warning will be printed if the trace buffer was not large enough to hold all the allocations which happened. If you see this warning, consider either shortening the tracing period or increasing the number of records in the trace buffer.
|
A warning will be printed if the trace buffer was not large enough to hold all the allocations which happened. If you see this warning, consider either shortening the tracing period or increasing the number of records in the trace buffer.
|
||||||
|
|
||||||
|
|
||||||
|
Host-Based Mode
|
||||||
|
+++++++++++++++
|
||||||
|
|
||||||
|
Once you've identified the code which you think is leaking:
|
||||||
|
|
||||||
|
- Under ``make menuconfig``, navigate to ``Component settings`` -> ``Heap Memory Debugging`` -> ``Heap tracing`` and select ``Host-Based`` option (see :ref:`CONFIG_HEAP_TRACING_DEST`).
|
||||||
|
- Under ``make menuconfig``, navigate to ``Component settings`` -> ``Application Level Tracing`` -> ``Data Destination`` and select ``Trace memory``.
|
||||||
|
- Under ``make menuconfig``, navigate to ``Component settings`` -> ``Application Level Tracing`` -> ``FreeRTOS SystemView Tracing`` and check ``SystemView Tracing Enable``.
|
||||||
|
- Call the function :cpp:func:`heap_trace_init_tohost` early in the program, to initialize JTAG heap tracing module.
|
||||||
|
- Call the function :cpp:func:`heap_trace_start` to begin recording all mallocs/frees in the system. Call this immediately before the piece of code which you suspect is leaking memory.
|
||||||
|
In host-based mode argument to this function is ignored and heap tracing module behaves like ``HEAP_TRACE_ALL`` was passed: all allocations and deallocations are sent to the host.
|
||||||
|
- Call the function :cpp:func:`heap_trace_stop` to stop the trace once the suspect piece of code has finished executing.
|
||||||
|
|
||||||
|
An example::
|
||||||
|
|
||||||
|
#include "esp_heap_trace.h"
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
void app_main()
|
||||||
|
{
|
||||||
|
...
|
||||||
|
ESP_ERROR_CHECK( heap_trace_init_tohost() );
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
void some_function()
|
||||||
|
{
|
||||||
|
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||||
|
|
||||||
|
do_something_you_suspect_is_leaking();
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK( heap_trace_stop() );
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
To gather and analyse heap trace do the following on the host:
|
||||||
|
|
||||||
|
1. Build the program and download it to the target as described in :doc:`Build and Flash </get-started/make-project>`.
|
||||||
|
|
||||||
|
2. Run OpenOCD (see :doc:`JTAG Debugging </api-guides/jtag-debugging/index>`).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
In order to use this feature you need OpenOCD version `v0.10.0-esp32-20181105` or later.
|
||||||
|
|
||||||
|
3. You can use GDB to start and/or stop tracing automatically. To do this you need to prepare special ``gdbinit`` file::
|
||||||
|
|
||||||
|
target remote :3333
|
||||||
|
|
||||||
|
mon reset halt
|
||||||
|
flushregs
|
||||||
|
|
||||||
|
tb heap_trace_start
|
||||||
|
commands
|
||||||
|
mon esp32 sysview start file:///tmp/heap.svdat
|
||||||
|
c
|
||||||
|
end
|
||||||
|
|
||||||
|
tb heap_trace_stop
|
||||||
|
commands
|
||||||
|
mon esp32 sysview stop
|
||||||
|
end
|
||||||
|
|
||||||
|
c
|
||||||
|
|
||||||
|
Using this file GDB will connect to the target, reset it, and start tracing when program hits breakpoint at :cpp:func:`heap_trace_start`. Trace data will be saved to ``/tmp/heap_log.svdat``. Tracing will be stopped when program hits breakpoint at :cpp:func:`heap_trace_stop`.
|
||||||
|
|
||||||
|
4. Run GDB using the following command ``xtensa-esp32-elf-gdb -x gdbinit </path/to/program/elf>``
|
||||||
|
|
||||||
|
5. Quit GDB when program stops at :cpp:func:`heap_trace_stop`. Trace data are saved in ``/tmp/heap.svdat``
|
||||||
|
|
||||||
|
6. Run processing script ``$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py /tmp/heap_log.svdat </path/to/program/elf>``
|
||||||
|
|
||||||
|
The output from the heap trace will look something like this::
|
||||||
|
|
||||||
|
Parse trace from '/tmp/heap.svdat'...
|
||||||
|
Stop parsing trace. (Timeout 0.000000 sec while reading 1 bytes!)
|
||||||
|
Process events from '['/tmp/heap.svdat']'...
|
||||||
|
[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.002258425] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.002563725] HEAP: Freed bytes @ 0x3ffaffe0 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.002782950] HEAP: Freed bytes @ 0x3ffb40b8 from task "main" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
|
||||||
|
[0.002798700] HEAP: Freed bytes @ 0x3ffb50bc from task "main" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
|
||||||
|
[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.102449800] HEAP: Allocated 4 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.102666150] HEAP: Freed bytes @ 0x3ffaffe8 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202451725] HEAP: Allocated 6 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202667075] HEAP: Freed bytes @ 0x3ffafff0 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302451475] HEAP: Allocated 8 bytes @ 0x3ffb40b8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302667500] HEAP: Freed bytes @ 0x3ffb40b8 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
Processing completed.
|
||||||
|
Processed 1019 events
|
||||||
|
=============== HEAP TRACE REPORT ===============
|
||||||
|
Processed 14 heap events.
|
||||||
|
[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
Found 10 leaked bytes in 4 blocks.
|
||||||
|
|
||||||
Heap Tracing To Find Heap Corruption
|
Heap Tracing To Find Heap Corruption
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -15,15 +15,15 @@ To compile with ESP-IDF you need to get the following packages:
|
||||||
|
|
||||||
- CentOS 7::
|
- CentOS 7::
|
||||||
|
|
||||||
sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache
|
sudo yum install git wget ncurses-devel flex bison gperf python pyserial python-pyelftools cmake ninja-build ccache
|
||||||
|
|
||||||
- Ubuntu and Debian::
|
- Ubuntu and Debian::
|
||||||
|
|
||||||
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing cmake ninja-build ccache
|
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing cmake ninja ccache
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing python2-pyelftools cmake ninja ccache
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake".
|
CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake".
|
||||||
|
|
|
@ -13,15 +13,15 @@ To compile with ESP-IDF you need to get the following packages:
|
||||||
|
|
||||||
- CentOS 7::
|
- CentOS 7::
|
||||||
|
|
||||||
sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache
|
sudo yum install git wget ncurses-devel flex bison gperf python pyserial python-pyelftools cmake ninja-build ccache
|
||||||
|
|
||||||
- Ubuntu and Debian::
|
- Ubuntu and Debian::
|
||||||
|
|
||||||
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing cmake ninja-build ccache
|
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing cmake ninja ccache
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing python2-pyelftools cmake ninja ccache
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake".
|
CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake".
|
||||||
|
|
|
@ -14,11 +14,11 @@ To compile with ESP-IDF you need to get the following packages:
|
||||||
|
|
||||||
- Ubuntu and Debian::
|
- Ubuntu and Debian::
|
||||||
|
|
||||||
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing
|
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing python-pyelftools
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing python2-pyelftools
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,11 @@ To compile with ESP-IDF you need to get the following packages:
|
||||||
|
|
||||||
- Ubuntu and Debian::
|
- Ubuntu and Debian::
|
||||||
|
|
||||||
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing
|
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing python-pyelftools
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing python2-pyelftools
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -15,15 +15,15 @@
|
||||||
|
|
||||||
- CentOS 7::
|
- CentOS 7::
|
||||||
|
|
||||||
sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache
|
sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache python-pyelftools
|
||||||
|
|
||||||
- Ubuntu 和 Debian::
|
- Ubuntu 和 Debian::
|
||||||
|
|
||||||
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing cmake ninja-build ccache
|
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing cmake ninja-build ccache python-pyelftools
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing cmake ninja ccache
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing cmake ninja ccache python2-pyelftools
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早版本的 Linux 可能需要升级才能向后移植仓库,或安装 "cmake3" 软件包,而不是安装 "cmake"。
|
使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早版本的 Linux 可能需要升级才能向后移植仓库,或安装 "cmake3" 软件包,而不是安装 "cmake"。
|
||||||
|
|
|
@ -13,15 +13,15 @@ Linux 平台工具链的标准设置 (CMake)
|
||||||
|
|
||||||
- CentOS 7::
|
- CentOS 7::
|
||||||
|
|
||||||
sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache
|
sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache python-pyelftools
|
||||||
|
|
||||||
- Ubuntu 和 Debian::
|
- Ubuntu 和 Debian::
|
||||||
|
|
||||||
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing cmake ninja-build ccache
|
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing cmake ninja-build ccache python-pyelftools
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing cmake ninja ccache
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing cmake ninja ccache python2-pyelftools
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早版本的 Linux 可能需要升级才能向后移植仓库,或安装 "cmake3" 软件包,而不是安装 "cmake"。
|
使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早版本的 Linux 可能需要升级才能向后移植仓库,或安装 "cmake3" 软件包,而不是安装 "cmake"。
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
|
|
||||||
- Ubuntu 和 Debian::
|
- Ubuntu 和 Debian::
|
||||||
|
|
||||||
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing
|
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing python-pyelftools
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing python2-pyelftools
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -12,15 +12,15 @@ Linux 平台工具链的标准设置
|
||||||
|
|
||||||
- CentOS 7::
|
- CentOS 7::
|
||||||
|
|
||||||
sudo yum install gcc git wget make ncurses-devel flex bison gperf python pyserial
|
sudo yum install gcc git wget make ncurses-devel flex bison gperf python pyserial python-pyelftools
|
||||||
|
|
||||||
- Ubuntu and Debian::
|
- Ubuntu and Debian::
|
||||||
|
|
||||||
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing
|
sudo apt-get install gcc git wget make libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-cryptography python-future python-pyparsing python-pyelftools
|
||||||
|
|
||||||
- Arch::
|
- Arch::
|
||||||
|
|
||||||
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing
|
sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial python2-cryptography python2-future python2-pyparsing python2-pyelftools
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -198,9 +198,12 @@ void app_main()
|
||||||
|
|
||||||
#if CONFIG_SYSVIEW_ENABLE && CONFIG_USE_CUSTOM_EVENT_ID
|
#if CONFIG_SYSVIEW_ENABLE && CONFIG_USE_CUSTOM_EVENT_ID
|
||||||
// Currently OpenOCD does not support requesting module info from target. So do the following...
|
// Currently OpenOCD does not support requesting module info from target. So do the following...
|
||||||
// Give SystemView tracing module some time to handle START command from host,
|
// Wait untill SystemView module receives START command from host,
|
||||||
// after that data can be sent to the host using onboard API, so user module description does not need to be requested by OpenOCD itself.
|
// after that data can be sent to the host using onboard API,
|
||||||
|
// so user module description does not need to be requested by OpenOCD itself.
|
||||||
|
while(!SEGGER_SYSVIEW_Started()) {
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
|
}
|
||||||
SEGGER_SYSVIEW_RegisterModule(&s_example_sysview_module);
|
SEGGER_SYSVIEW_RegisterModule(&s_example_sysview_module);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
# Enable single core mode by default
|
||||||
CONFIG_MEMMAP_SMP=n
|
CONFIG_MEMMAP_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=y
|
CONFIG_FREERTOS_UNICORE=y
|
||||||
|
# 1ms tick period
|
||||||
CONFIG_FREERTOS_HZ=1000
|
CONFIG_FREERTOS_HZ=1000
|
||||||
# Enable application tracing by default
|
# Enable application tracing by default
|
||||||
CONFIG_ESP32_APPTRACE_DEST_TRAX=y
|
CONFIG_ESP32_APPTRACE_DEST_TRAX=y
|
||||||
|
|
6
examples/system/sysview_tracing_heap_log/CMakeLists.txt
Normal file
6
examples/system/sysview_tracing_heap_log/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||||
|
# in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(sysview_tracing_heap_log)
|
9
examples/system/sysview_tracing_heap_log/Makefile
Normal file
9
examples/system/sysview_tracing_heap_log/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#
|
||||||
|
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||||
|
# project subdirectory.
|
||||||
|
#
|
||||||
|
|
||||||
|
PROJECT_NAME := sysview_tracing_heap_log
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
|
164
examples/system/sysview_tracing_heap_log/README.md
Normal file
164
examples/system/sysview_tracing_heap_log/README.md
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
# SystemView Heap and Log Tracing Example
|
||||||
|
|
||||||
|
Heap memory leaking is quite widespread software bug. IDF provides [heap tracing feature](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/heap_debug.html#heap-tracing) which allows to collect information related to heap operations (allocations/deallocations) and detect potential memory leaks. This feature can be used in two modes: standalone and host-based. In standalone mode collected data are kept on-board, so this mode is limited by avaialable memory in the system. Host-based mode does not have such limitation because collected data are sent to the host and can be analysed there using special tools. One of such tool is SEGGER SystemView. For description of [SystemView tracing feature](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/app_trace.html#system-behaviour-analysis-with-segger-systemview) please refer to **ESP32 Programming Guide**, section **Application Level Tracing library**. SystemView is also can be useful to show log message sent from the target.
|
||||||
|
This example shows how to use this tool and IDF's scripts for host-based heap and log tracing analysis.
|
||||||
|
|
||||||
|
Consider the following situation. User program have two tasks. One task allocates memory and puts obtained addresses into the queue. Another task waits on that queue, reads sent pointers and frees memory. The first task queues only part of the pointers so some of the allocated blocks are not freed and become leaked. Both tasks uses IDF's logging API to report their actions. This example uses IDF's heap tracing module to record allocations and deallocations to detect memory leaks. Both heap tracing records and log mesages are redirected to the host.
|
||||||
|
|
||||||
|
## How to use example
|
||||||
|
|
||||||
|
### Hardware and tools required
|
||||||
|
|
||||||
|
This example does not require any special hardware, and can be run on any common development board.
|
||||||
|
This example requires the following tools:
|
||||||
|
1. [OpenOCD](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/jtag-debugging/index.html#run-openocd).
|
||||||
|
NOTE: In order to run this example you need OpenOCD version `v0.10.0-esp32-20190313` or later.
|
||||||
|
|
||||||
|
2. [GDB](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html#setup-toolchain) can be used to start and/or stop tracing automatically. To do this you need to prepare special GDB command file. Having provided with `gdbinit` file from the example project directory GDB will connect to the target, reset it, start and stop tracing automatically.
|
||||||
|
when program hits breakpoint at `heap_trace_start`. Trace data will be saved to `/tmp/hesp_log.svdat`. Tracing will be stopped when program hits breakpoint at `heap_trace_stop`.
|
||||||
|
|
||||||
|
3. [SEGGER SystemView tool](https://www.segger.com/products/development-tools/systemview/). By default SystemView shows only numeric values of IDs and parameters for IDF's heap messages in `Events` view. To make them pretty-looking you need to copy `SYSVIEW_FreeRTOS.txt` from the project's root directory to SystemView installation one.
|
||||||
|
|
||||||
|
### Configure the project
|
||||||
|
|
||||||
|
If using Make based build system, run `make menuconfig` and set serial port under Serial Flasher Options.
|
||||||
|
|
||||||
|
If using CMake based build system, no configuration is required.
|
||||||
|
|
||||||
|
### Build and flash
|
||||||
|
|
||||||
|
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||||
|
|
||||||
|
```
|
||||||
|
make -j4 flash monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, for CMake based build system (replace PORT with serial port name):
|
||||||
|
|
||||||
|
```
|
||||||
|
idf.py -p PORT flash monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||||
|
|
||||||
|
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||||
|
|
||||||
|
### Collect And View Trace Data
|
||||||
|
|
||||||
|
To run the example and collect trace data:
|
||||||
|
|
||||||
|
1. Run GDB using the following command from the project root directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
xtensa-esp32-elf-gdb -x gdbinit build/sysview_tracing_heap_log.elf
|
||||||
|
```
|
||||||
|
2. When program stops at `heap_trace_stop` quit GDB.
|
||||||
|
|
||||||
|
3. Open trace data file in SystemView tool.
|
||||||
|
|
||||||
|
4. Now you can inspect all collected events. Log messages are shown in `Terminal` view.
|
||||||
|
|
||||||
|
5. You can filter out API related and heap events by right-clicking on any item in `Events` view and select `Show APIs only`.
|
||||||
|
|
||||||
|
### Auto-detect Heap Leaks
|
||||||
|
|
||||||
|
Since SystemView tool is mostly intended for OS level analysis. It allows just to inspect custom events' timestamps and parameters. So it can require some efforts to analyse heap operations flow. IDF provides special script to make the life a bit more easy. This script parses SystemView trace file sand reports detected memory leaks. The script also prints found log messages. To run it type the following from the project root directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
$IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -p /tmp/heap_log.svdat build/sysview_tracing_heap_log.elf
|
||||||
|
```
|
||||||
|
|
||||||
|
Below is the sample scripts output.
|
||||||
|
|
||||||
|
```
|
||||||
|
Parse trace from '/tmp/heap_log.svdat'...
|
||||||
|
Stop parsing trace. (Timeout 0.000000 sec while reading 1 bytes!)
|
||||||
|
Process events from '['/tmp/heap_log.svdat']'...
|
||||||
|
[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.002258425] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.002405000] LOG: I (264) example: Task[0x3ffb6cf4]: allocated 2 bytes @ 0x3ffaffe0
|
||||||
|
[0.002553425] LOG: I (265) example: Task[0x3ffb7660]: free memory @ 0x3ffaffe0
|
||||||
|
[0.002563725] HEAP: Freed bytes @ 0x3ffaffe0 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.002782950] HEAP: Freed bytes @ 0x3ffb40b8 from task "main" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
|
||||||
|
[0.002798700] HEAP: Freed bytes @ 0x3ffb50bc from task "main" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/tasks.c:4590
|
||||||
|
|
||||||
|
[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.102449800] HEAP: Allocated 4 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.102536400] LOG: I (365) example: Task[0x3ffb6cf4]: allocated 4 bytes @ 0x3ffaffe8
|
||||||
|
[0.102655625] LOG: I (365) example: Task[0x3ffb7660]: free memory @ 0x3ffaffe8
|
||||||
|
[0.102666150] HEAP: Freed bytes @ 0x3ffaffe8 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202451725] HEAP: Allocated 6 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202538225] LOG: I (465) example: Task[0x3ffb6cf4]: allocated 6 bytes @ 0x3ffafff0
|
||||||
|
[0.202654475] LOG: I (465) example: Task[0x3ffb7660]: free memory @ 0x3ffafff0
|
||||||
|
[0.202667075] HEAP: Freed bytes @ 0x3ffafff0 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302451475] HEAP: Allocated 8 bytes @ 0x3ffb40b8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:48
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302540900] LOG: I (565) example: Task[0x3ffb6cf4]: allocated 8 bytes @ 0x3ffb40b8
|
||||||
|
[0.302657050] LOG: I (565) example: Task[0x3ffb7660]: free memory @ 0x3ffb40b8
|
||||||
|
[0.302667500] HEAP: Freed bytes @ 0x3ffb40b8 from task "free" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:31 (discriminator 9)
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
Processing completed.
|
||||||
|
Processed 1027 events
|
||||||
|
=============== LOG TRACE REPORT ===============
|
||||||
|
Processed 8 log messages.
|
||||||
|
=============== HEAP TRACE REPORT ===============
|
||||||
|
Processed 14 heap events.
|
||||||
|
[0.002244575] HEAP: Allocated 1 bytes @ 0x3ffaffd8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.102436025] HEAP: Allocated 2 bytes @ 0x3ffaffe0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.202436200] HEAP: Allocated 3 bytes @ 0x3ffaffe8 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.302436000] HEAP: Allocated 4 bytes @ 0x3ffafff0 from task "alloc" on core 0 by:
|
||||||
|
/home/user/projects/esp/esp-idf/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c:47
|
||||||
|
/home/user/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
Found 10 leaked bytes in 4 blocks.
|
||||||
|
```
|
107
examples/system/sysview_tracing_heap_log/SYSVIEW_FreeRTOS.txt
Normal file
107
examples/system/sysview_tracing_heap_log/SYSVIEW_FreeRTOS.txt
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
128 vTaskAllocateMPURegions xTask=%t pxRegions=%u
|
||||||
|
33 vTaskDelete xTaskToDelete=%t
|
||||||
|
34 vTaskDelay xTicksToDelay=%u
|
||||||
|
35 vTaskDelayUntil
|
||||||
|
129 uxTaskPriorityGet xTask=%t
|
||||||
|
56 uxTaskPriorityGetFromISR xTask=%t
|
||||||
|
130 eTaskGetState xTask=%t
|
||||||
|
55 vTaskPrioritySet xTask=%t uxNewPriority=%u
|
||||||
|
36 vTaskSuspend xTaskToSuspend=%t
|
||||||
|
40 vTaskResume xTaskToResume=%t
|
||||||
|
43 xTaskResumeFromISR xTaskToResume=%t
|
||||||
|
131 vTaskStartScheduler
|
||||||
|
132 vTaskEndScheduler
|
||||||
|
133 vTaskSuspendAll
|
||||||
|
134 xTaskResumeAll
|
||||||
|
135 xTaskGetTickCount
|
||||||
|
57 xTaskGetTickCountFromISR
|
||||||
|
136 uxTaskGetNumberOfTasks
|
||||||
|
137 pcTaskGetTaskName xTaskToQuery=%t
|
||||||
|
138 uxTaskGetStackHighWaterMark xTask=%t
|
||||||
|
139 vTaskSetApplicationTaskTag xTask=%t pxHookFunction=%u
|
||||||
|
140 xTaskGetApplicationTaskTag xTask=%t
|
||||||
|
141 vTaskSetThreadLocalStoragePointer xTaskToSet=%T xIndex=%u pvValue=%u
|
||||||
|
142 pvTaskGetThreadLocalStoragePointer xTaskToQuery=%T xIndex=%u
|
||||||
|
143 xTaskCallApplicationTaskHook xTask=%T pvParameter=%u
|
||||||
|
144 xTaskGetIdleTaskHandle
|
||||||
|
145 uxTaskGetSystemState pxTaskStatusArray=%u uxArraySize=%u pulTotalRunTime=%u
|
||||||
|
146 vTaskList pcWriteBuffer=%u
|
||||||
|
147 vTaskGetRunTimeStats pcWriteBuffer=%u
|
||||||
|
44 xTaskGenericNotify xTaskToNotify=%t ulValue=%u eAction=%u pulPreviousNotificationValue=%u
|
||||||
|
45 xTaskGenericNotifyFromISR xTaskToNotify=%t ulValue=%u eAction=%u pulPreviousNotificationValue=%u pxHigherPriorityTaskWoken=%u
|
||||||
|
46 xTaskNotifyWait ulBitsToClearOnEntry=%u ulBitsToClearOnExit=%u pulNotificationValue=%u xTicksToWait=%u
|
||||||
|
38 vTaskNotifyGiveFromISR xTaskToNotify=%t pxHigherPriorityTaskWoken=%u
|
||||||
|
37 ulTaskNotifyTake xClearCountOnExit=%u xTicksToWait=%u
|
||||||
|
148 xTaskNotifyStateClear xTask=%t
|
||||||
|
149 xTaskGetCurrentTaskHandle
|
||||||
|
150 vTaskSetTimeOutState pxTimeOut=%u
|
||||||
|
151 xTaskCheckForTimeOut pxTimeOut=%u pxTicksToWait=%u
|
||||||
|
152 vTaskMissedYield
|
||||||
|
153 xTaskGetSchedulerState
|
||||||
|
39 vTaskPriorityInherit pxMutexHolder=%p
|
||||||
|
42 xTaskPriorityDisinherit pxMutexHolder=%p
|
||||||
|
154 xTaskGenericCreate pxTaskCode=%u pcName=%u usStackDepth=%u pvParameters=%u uxPriority=%u pxCreatedTask=%u puxStackBuffer=%u xRegions=%u
|
||||||
|
155 uxTaskGetTaskNumber xTask=%u
|
||||||
|
156 vTaskSetTaskNumber xTask=%u uxHandle=%u
|
||||||
|
41 vTaskStepTick xTicksToJump=%u
|
||||||
|
157 eTaskConfirmSleepModeStatus
|
||||||
|
158 xTimerCreate pcTimerName=%u xTimerPeriodInTicks=%u uxAutoReload=%u pvTimerID=%u pxCallbackFunction=%u
|
||||||
|
159 pvTimerGetTimerID xTimer=%u
|
||||||
|
160 vTimerSetTimerID xTimer=%u pvNewID=%u
|
||||||
|
161 xTimerIsTimerActive xTimer=%u
|
||||||
|
162 xTimerGetTimerDaemonTaskHandle
|
||||||
|
163 xTimerPendFunctionCallFromISR xFunctionToPend=%u pvParameter1=%u ulParameter2=%u pxHigherPriorityTaskWoken=%u
|
||||||
|
164 xTimerPendFunctionCall xFunctionToPend=%u pvParameter1=%u ulParameter2=%u xTicksToWait=%u
|
||||||
|
165 pcTimerGetTimerName xTimer=%u
|
||||||
|
166 xTimerCreateTimerTask
|
||||||
|
167 xTimerGenericCommand xTimer=%u xCommandID=%u xOptionalValue=%u pxHigherPriorityTaskWoken=%u xTicksToWait=%u
|
||||||
|
53 xQueueGenericSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u xCopyPosition=%u
|
||||||
|
50 xQueuePeekFromISR xQueue=%I pvBuffer=%p
|
||||||
|
49 xQueueGenericReceive xQueue=%I pvBuffer=%p xTicksToWait=%u xJustPeek=%u
|
||||||
|
168 uxQueueMessagesWaiting xQueue=%I
|
||||||
|
169 uxQueueSpacesAvailable xQueue=%I
|
||||||
|
48 vQueueDelete xQueue=%I
|
||||||
|
54 xQueueGenericSendFromISR xQueue=%I pvItemToQueue=%p pxHigherPriorityTaskWoken=%u xCopyPosition=%u
|
||||||
|
61 xQueueGiveFromISR xQueue=%I pxHigherPriorityTaskWoken=%u
|
||||||
|
51 xQueueReceiveFromISR xQueue=%I pvBuffer=%p pxHigherPriorityTaskWoken=%u
|
||||||
|
62 xQueueIsQueueEmptyFromISR xQueue=%I
|
||||||
|
63 xQueueIsQueueFullFromISR xQueue=%I
|
||||||
|
170 uxQueueMessagesWaitingFromISR xQueue=%I
|
||||||
|
171 xQueueAltGenericSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u xCopyPosition=%u
|
||||||
|
172 xQueueAltGenericReceive xQueue=%I pvBuffer=%p xTicksToWait=%u xJustPeeking=%u
|
||||||
|
173 xQueueCRSendFromISR xQueue=%I pvItemToQueue=%p xCoRoutinePreviouslyWoken=%u
|
||||||
|
174 xQueueCRReceiveFromISR xQueue=%I pvBuffer=%p pxTaskWoken=%u
|
||||||
|
175 xQueueCRSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u
|
||||||
|
176 xQueueCRReceive xQueue=%I pvBuffer=%p xTicksToWait=%u
|
||||||
|
177 xQueueCreateMutex ucQueueType=%u
|
||||||
|
178 xQueueCreateCountingSemaphore uxMaxCount=%u uxInitialCount=%u
|
||||||
|
179 xQueueGetMutexHolder xSemaphore=%u
|
||||||
|
180 xQueueTakeMutexRecursive xMutex=%u xTicksToWait=%u
|
||||||
|
181 xQueueGiveMutexRecursive pxMutex=%u
|
||||||
|
52 vQueueAddToRegistry xQueue=%I pcName=%u
|
||||||
|
182 vQueueUnregisterQueue xQueue=%I
|
||||||
|
47 xQueueGenericCreate uxQueueLength=%u uxItemSize=%u ucQueueType=%u
|
||||||
|
183 xQueueCreateSet uxEventQueueLength=%u
|
||||||
|
184 xQueueAddToSet xQueueOrSemaphore=%u xQueueSet=%u
|
||||||
|
185 xQueueRemoveFromSet xQueueOrSemaphore=%u xQueueSet=%u
|
||||||
|
186 xQueueSelectFromSet xQueueSet=%u xTicksToWait=%u
|
||||||
|
187 xQueueSelectFromSetFromISR xQueueSet=%u
|
||||||
|
188 xQueueGenericReset xQueue=%I xNewQueue=%u
|
||||||
|
189 vListInitialise pxList=%u
|
||||||
|
190 vListInitialiseItem pxItem=%u
|
||||||
|
191 vListInsert pxList=%u pxNewListItem=%u
|
||||||
|
192 vListInsertEnd pxList=%u pxNewListItem=%u
|
||||||
|
193 uxListRemove pxItemToRemove=%u
|
||||||
|
194 xEventGroupCreate
|
||||||
|
195 xEventGroupWaitBits xEventGroup=%u uxBitsToWaitFor=%u xClearOnExit=%u xWaitForAllBits=%u xTicksToWait=%u
|
||||||
|
196 xEventGroupClearBits xEventGroup=%u uxBitsToClear=%u
|
||||||
|
58 xEventGroupClearBitsFromISR xEventGroup=%u uxBitsToSet=%u
|
||||||
|
197 xEventGroupSetBits xEventGroup=%u uxBitsToSet=%u
|
||||||
|
59 xEventGroupSetBitsFromISR xEventGroup=%u uxBitsToSet=%u pxHigherPriorityTaskWoken=%u
|
||||||
|
198 xEventGroupSync xEventGroup=%u uxBitsToSet=%u uxBitsToWaitFor=%u xTicksToWait=%u
|
||||||
|
60 xEventGroupGetBitsFromISR xEventGroup=%u
|
||||||
|
199 vEventGroupDelete xEventGroup=%u
|
||||||
|
200 uxEventGroupGetNumber xEventGroup=%u
|
||||||
|
|
||||||
|
512 esp_sysview_heap_trace_alloc addr=%p size=%u callers=%x
|
||||||
|
513 esp_sysview_heap_trace_free addr=%p callers=%x
|
17
examples/system/sysview_tracing_heap_log/gdbinit
Normal file
17
examples/system/sysview_tracing_heap_log/gdbinit
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
target remote :3333
|
||||||
|
|
||||||
|
mon reset halt
|
||||||
|
flushregs
|
||||||
|
|
||||||
|
tb heap_trace_start
|
||||||
|
commands
|
||||||
|
mon esp32 sysview start file:///tmp/heap_log.svdat
|
||||||
|
c
|
||||||
|
end
|
||||||
|
|
||||||
|
tb heap_trace_stop
|
||||||
|
commands
|
||||||
|
mon esp32 sysview stop
|
||||||
|
end
|
||||||
|
|
||||||
|
c
|
|
@ -0,0 +1,4 @@
|
||||||
|
set(COMPONENT_SRCS "sysview_heap_log.c")
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||||
|
|
||||||
|
register_component()
|
|
@ -0,0 +1,3 @@
|
||||||
|
#
|
||||||
|
# Main Makefile. This is basically the same as a component makefile.
|
||||||
|
#
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* Application Trace to Host Example
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_sysview_trace.h"
|
||||||
|
#include "esp_heap_trace.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char *TAG = "example";
|
||||||
|
|
||||||
|
// waits on queue for memory addresses and frees memory allocated by 'alloc_task'
|
||||||
|
static void free_task(void *p)
|
||||||
|
{
|
||||||
|
QueueHandle_t queue = (QueueHandle_t)p;
|
||||||
|
while (1) {
|
||||||
|
void *p = NULL;
|
||||||
|
if (xQueueReceive(queue, ( void * )&p, portMAX_DELAY) != pdPASS) {
|
||||||
|
ESP_LOGE(TAG, "Failed to send to queue!");
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "Task[%p]: free memory @ %p", xTaskGetCurrentTaskHandle(), p);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocates memory and puts addresses to the queue
|
||||||
|
static void alloc_task(void *p)
|
||||||
|
{
|
||||||
|
QueueHandle_t queue = (QueueHandle_t)p;
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(free_task, "free", 2048, queue, 5, NULL, portNUM_PROCESSORS-1);
|
||||||
|
|
||||||
|
// here GDB will stop at brekpoint and execute OpenOCD command to start tracing
|
||||||
|
heap_trace_start(HEAP_TRACE_ALL);
|
||||||
|
for(int i = 1; i < 5; i++) {
|
||||||
|
uint32_t sz = 2*i;
|
||||||
|
void *p = malloc(sz/2);
|
||||||
|
// WARNING: the previous allocated memory is intentionally not deallocated in order to cause memory leak!
|
||||||
|
p = malloc(sz);
|
||||||
|
ESP_LOGI(TAG, "Task[%p]: allocated %d bytes @ %p", xTaskGetCurrentTaskHandle(), sz, p);
|
||||||
|
if (xQueueSend(queue, ( void * )&p, portMAX_DELAY) != pdPASS) {
|
||||||
|
ESP_LOGE(TAG, "Failed to send to queue!");
|
||||||
|
}
|
||||||
|
vTaskDelay(100/portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
// here GDB will stop at brekpoint and execute OpenOCD command to stop tracing
|
||||||
|
heap_trace_stop();
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main()
|
||||||
|
{
|
||||||
|
// redirect log messages to the host using SystemView tracing module
|
||||||
|
esp_log_set_vprintf(&esp_sysview_vprintf);
|
||||||
|
QueueHandle_t queue = xQueueCreate(10, sizeof(void *));
|
||||||
|
if(queue == 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to create queue!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// init host-based heap tracing
|
||||||
|
if(heap_trace_init_tohost() != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to init heap trace!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xTaskCreatePinnedToCore(alloc_task, "alloc", 2048, queue, 5, NULL, 0);
|
||||||
|
}
|
28
examples/system/sysview_tracing_heap_log/sdkconfig.defaults
Normal file
28
examples/system/sysview_tracing_heap_log/sdkconfig.defaults
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Enable single core mode by default
|
||||||
|
CONFIG_MEMMAP_SMP=n
|
||||||
|
CONFIG_FREERTOS_UNICORE=y
|
||||||
|
# 1ms tick period
|
||||||
|
CONFIG_FREERTOS_HZ=1000
|
||||||
|
# Enable application tracing by default
|
||||||
|
CONFIG_ESP32_APPTRACE_DEST_TRAX=y
|
||||||
|
CONFIG_ESP32_APPTRACE_ENABLE=y
|
||||||
|
# Enable FreeRTOS SystemView Tracing by default
|
||||||
|
CONFIG_SYSVIEW_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_TS_SOURCE_TIMER_00=y
|
||||||
|
CONFIG_SYSVIEW_EVT_OVERFLOW_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_ISR_ENTER_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_ISR_EXIT_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_ISR_TO_SCHEDULER_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TASK_START_EXEC_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TASK_STOP_EXEC_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TASK_START_READY_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TASK_STOP_READY_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TASK_CREATE_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TASK_TERMINATE_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_IDLE_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TIMER_ENTER_ENABLE=y
|
||||||
|
CONFIG_SYSVIEW_EVT_TIMER_EXIT_ENABLE=y
|
||||||
|
# Disable color output in logs
|
||||||
|
CONFIG_LOG_COLORS=
|
||||||
|
# Enable heap tracing to host
|
||||||
|
CONFIG_HEAP_TRACING_TOHOST=y
|
|
@ -9,3 +9,4 @@ pyserial>=3.0
|
||||||
future>=0.15.2
|
future>=0.15.2
|
||||||
cryptography>=2.1.4
|
cryptography>=2.1.4
|
||||||
pyparsing>=2.0.3
|
pyparsing>=2.0.3
|
||||||
|
pyelftools>=0.22
|
||||||
|
|
|
@ -34,8 +34,10 @@ tools/ci/test_build_system_cmake.sh
|
||||||
tools/ci/test_configure_ci_environment.sh
|
tools/ci/test_configure_ci_environment.sh
|
||||||
tools/cmake/convert_to_cmake.py
|
tools/cmake/convert_to_cmake.py
|
||||||
tools/cmake/run_cmake_lint.sh
|
tools/cmake/run_cmake_lint.sh
|
||||||
tools/esp_app_trace/apptrace_proc.py
|
|
||||||
tools/esp_app_trace/logtrace_proc.py
|
tools/esp_app_trace/logtrace_proc.py
|
||||||
|
tools/esp_app_trace/sysviewtrace_proc.py
|
||||||
|
tools/esp_app_trace/test/logtrace/test.sh
|
||||||
|
tools/esp_app_trace/test/sysview/test.sh
|
||||||
tools/format.sh
|
tools/format.sh
|
||||||
tools/gen_esp_err_to_name.py
|
tools/gen_esp_err_to_name.py
|
||||||
tools/idf.py
|
tools/idf.py
|
||||||
|
|
107
tools/esp_app_trace/SYSVIEW_FreeRTOS.txt
Normal file
107
tools/esp_app_trace/SYSVIEW_FreeRTOS.txt
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
128 vTaskAllocateMPURegions xTask=%t pxRegions=%u
|
||||||
|
33 vTaskDelete xTaskToDelete=%t
|
||||||
|
34 vTaskDelay xTicksToDelay=%u
|
||||||
|
35 vTaskDelayUntil
|
||||||
|
129 uxTaskPriorityGet xTask=%t
|
||||||
|
56 uxTaskPriorityGetFromISR xTask=%t
|
||||||
|
130 eTaskGetState xTask=%t
|
||||||
|
55 vTaskPrioritySet xTask=%t uxNewPriority=%u
|
||||||
|
36 vTaskSuspend xTaskToSuspend=%t
|
||||||
|
40 vTaskResume xTaskToResume=%t
|
||||||
|
43 xTaskResumeFromISR xTaskToResume=%t
|
||||||
|
131 vTaskStartScheduler
|
||||||
|
132 vTaskEndScheduler
|
||||||
|
133 vTaskSuspendAll
|
||||||
|
134 xTaskResumeAll
|
||||||
|
135 xTaskGetTickCount
|
||||||
|
57 xTaskGetTickCountFromISR
|
||||||
|
136 uxTaskGetNumberOfTasks
|
||||||
|
137 pcTaskGetTaskName xTaskToQuery=%t
|
||||||
|
138 uxTaskGetStackHighWaterMark xTask=%t
|
||||||
|
139 vTaskSetApplicationTaskTag xTask=%t pxHookFunction=%u
|
||||||
|
140 xTaskGetApplicationTaskTag xTask=%t
|
||||||
|
141 vTaskSetThreadLocalStoragePointer xTaskToSet=%T xIndex=%u pvValue=%u
|
||||||
|
142 pvTaskGetThreadLocalStoragePointer xTaskToQuery=%T xIndex=%u
|
||||||
|
143 xTaskCallApplicationTaskHook xTask=%T pvParameter=%u
|
||||||
|
144 xTaskGetIdleTaskHandle
|
||||||
|
145 uxTaskGetSystemState pxTaskStatusArray=%u uxArraySize=%u pulTotalRunTime=%u
|
||||||
|
146 vTaskList pcWriteBuffer=%u
|
||||||
|
147 vTaskGetRunTimeStats pcWriteBuffer=%u
|
||||||
|
44 xTaskGenericNotify xTaskToNotify=%t ulValue=%u eAction=%u pulPreviousNotificationValue=%u
|
||||||
|
45 xTaskGenericNotifyFromISR xTaskToNotify=%t ulValue=%u eAction=%u pulPreviousNotificationValue=%u pxHigherPriorityTaskWoken=%u
|
||||||
|
46 xTaskNotifyWait ulBitsToClearOnEntry=%u ulBitsToClearOnExit=%u pulNotificationValue=%u xTicksToWait=%u
|
||||||
|
38 vTaskNotifyGiveFromISR xTaskToNotify=%t pxHigherPriorityTaskWoken=%u
|
||||||
|
37 ulTaskNotifyTake xClearCountOnExit=%u xTicksToWait=%u
|
||||||
|
148 xTaskNotifyStateClear xTask=%t
|
||||||
|
149 xTaskGetCurrentTaskHandle
|
||||||
|
150 vTaskSetTimeOutState pxTimeOut=%u
|
||||||
|
151 xTaskCheckForTimeOut pxTimeOut=%u pxTicksToWait=%u
|
||||||
|
152 vTaskMissedYield
|
||||||
|
153 xTaskGetSchedulerState
|
||||||
|
39 vTaskPriorityInherit pxMutexHolder=%p
|
||||||
|
42 xTaskPriorityDisinherit pxMutexHolder=%p
|
||||||
|
154 xTaskGenericCreate pxTaskCode=%u pcName=%u usStackDepth=%u pvParameters=%u uxPriority=%u pxCreatedTask=%u puxStackBuffer=%u xRegions=%u
|
||||||
|
155 uxTaskGetTaskNumber xTask=%u
|
||||||
|
156 vTaskSetTaskNumber xTask=%u uxHandle=%u
|
||||||
|
41 vTaskStepTick xTicksToJump=%u
|
||||||
|
157 eTaskConfirmSleepModeStatus
|
||||||
|
158 xTimerCreate pcTimerName=%u xTimerPeriodInTicks=%u uxAutoReload=%u pvTimerID=%u pxCallbackFunction=%u
|
||||||
|
159 pvTimerGetTimerID xTimer=%u
|
||||||
|
160 vTimerSetTimerID xTimer=%u pvNewID=%u
|
||||||
|
161 xTimerIsTimerActive xTimer=%u
|
||||||
|
162 xTimerGetTimerDaemonTaskHandle
|
||||||
|
163 xTimerPendFunctionCallFromISR xFunctionToPend=%u pvParameter1=%u ulParameter2=%u pxHigherPriorityTaskWoken=%u
|
||||||
|
164 xTimerPendFunctionCall xFunctionToPend=%u pvParameter1=%u ulParameter2=%u xTicksToWait=%u
|
||||||
|
165 pcTimerGetTimerName xTimer=%u
|
||||||
|
166 xTimerCreateTimerTask
|
||||||
|
167 xTimerGenericCommand xTimer=%u xCommandID=%u xOptionalValue=%u pxHigherPriorityTaskWoken=%u xTicksToWait=%u
|
||||||
|
53 xQueueGenericSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u xCopyPosition=%u
|
||||||
|
50 xQueuePeekFromISR xQueue=%I pvBuffer=%p
|
||||||
|
49 xQueueGenericReceive xQueue=%I pvBuffer=%p xTicksToWait=%u xJustPeek=%u
|
||||||
|
168 uxQueueMessagesWaiting xQueue=%I
|
||||||
|
169 uxQueueSpacesAvailable xQueue=%I
|
||||||
|
48 vQueueDelete xQueue=%I
|
||||||
|
54 xQueueGenericSendFromISR xQueue=%I pvItemToQueue=%p pxHigherPriorityTaskWoken=%u xCopyPosition=%u
|
||||||
|
61 xQueueGiveFromISR xQueue=%I pxHigherPriorityTaskWoken=%u
|
||||||
|
51 xQueueReceiveFromISR xQueue=%I pvBuffer=%p pxHigherPriorityTaskWoken=%u
|
||||||
|
62 xQueueIsQueueEmptyFromISR xQueue=%I
|
||||||
|
63 xQueueIsQueueFullFromISR xQueue=%I
|
||||||
|
170 uxQueueMessagesWaitingFromISR xQueue=%I
|
||||||
|
171 xQueueAltGenericSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u xCopyPosition=%u
|
||||||
|
172 xQueueAltGenericReceive xQueue=%I pvBuffer=%p xTicksToWait=%u xJustPeeking=%u
|
||||||
|
173 xQueueCRSendFromISR xQueue=%I pvItemToQueue=%p xCoRoutinePreviouslyWoken=%u
|
||||||
|
174 xQueueCRReceiveFromISR xQueue=%I pvBuffer=%p pxTaskWoken=%u
|
||||||
|
175 xQueueCRSend xQueue=%I pvItemToQueue=%p xTicksToWait=%u
|
||||||
|
176 xQueueCRReceive xQueue=%I pvBuffer=%p xTicksToWait=%u
|
||||||
|
177 xQueueCreateMutex ucQueueType=%u
|
||||||
|
178 xQueueCreateCountingSemaphore uxMaxCount=%u uxInitialCount=%u
|
||||||
|
179 xQueueGetMutexHolder xSemaphore=%u
|
||||||
|
180 xQueueTakeMutexRecursive xMutex=%u xTicksToWait=%u
|
||||||
|
181 xQueueGiveMutexRecursive pxMutex=%u
|
||||||
|
52 vQueueAddToRegistry xQueue=%I pcName=%u
|
||||||
|
182 vQueueUnregisterQueue xQueue=%I
|
||||||
|
47 xQueueGenericCreate uxQueueLength=%u uxItemSize=%u ucQueueType=%u
|
||||||
|
183 xQueueCreateSet uxEventQueueLength=%u
|
||||||
|
184 xQueueAddToSet xQueueOrSemaphore=%u xQueueSet=%u
|
||||||
|
185 xQueueRemoveFromSet xQueueOrSemaphore=%u xQueueSet=%u
|
||||||
|
186 xQueueSelectFromSet xQueueSet=%u xTicksToWait=%u
|
||||||
|
187 xQueueSelectFromSetFromISR xQueueSet=%u
|
||||||
|
188 xQueueGenericReset xQueue=%I xNewQueue=%u
|
||||||
|
189 vListInitialise pxList=%u
|
||||||
|
190 vListInitialiseItem pxItem=%u
|
||||||
|
191 vListInsert pxList=%u pxNewListItem=%u
|
||||||
|
192 vListInsertEnd pxList=%u pxNewListItem=%u
|
||||||
|
193 uxListRemove pxItemToRemove=%u
|
||||||
|
194 xEventGroupCreate
|
||||||
|
195 xEventGroupWaitBits xEventGroup=%u uxBitsToWaitFor=%u xClearOnExit=%u xWaitForAllBits=%u xTicksToWait=%u
|
||||||
|
196 xEventGroupClearBits xEventGroup=%u uxBitsToClear=%u
|
||||||
|
58 xEventGroupClearBitsFromISR xEventGroup=%u uxBitsToSet=%u
|
||||||
|
197 xEventGroupSetBits xEventGroup=%u uxBitsToSet=%u
|
||||||
|
59 xEventGroupSetBitsFromISR xEventGroup=%u uxBitsToSet=%u pxHigherPriorityTaskWoken=%u
|
||||||
|
198 xEventGroupSync xEventGroup=%u uxBitsToSet=%u uxBitsToWaitFor=%u xTicksToWait=%u
|
||||||
|
60 xEventGroupGetBitsFromISR xEventGroup=%u
|
||||||
|
199 vEventGroupDelete xEventGroup=%u
|
||||||
|
200 uxEventGroupGetNumber xEventGroup=%u
|
||||||
|
|
||||||
|
512 esp_sysview_heap_trace_alloc addr=%p size=%u callers=%x
|
||||||
|
513 esp_sysview_heap_trace_free addr=%p callers=%x
|
|
@ -1,130 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
import argparse
|
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
class bcolors:
|
|
||||||
HEADER = '\033[95m'
|
|
||||||
OKBLUE = '\033[94m'
|
|
||||||
OKGREEN = '\033[92m'
|
|
||||||
WARNING = '\033[93m'
|
|
||||||
FAIL = '\033[91m'
|
|
||||||
ENDC = '\033[0m'
|
|
||||||
BOLD = '\033[1m'
|
|
||||||
UNDERLINE = '\033[4m'
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
ESP32_TRACE_BLOCK_HDR_SZ = 8
|
|
||||||
ESP32_TRACE_BLOCK_TASK_IDX = 0
|
|
||||||
ESP32_TRACE_BLOCK_TS_IDX = 1
|
|
||||||
ESP32_TRACE_BLOCK_DATA_IDX = 2
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='ESP32 App Trace Parse Tool')
|
|
||||||
|
|
||||||
parser.add_argument('file', help='Path to app trace file', type=str)
|
|
||||||
parser.add_argument('--print-tasks', '-p', help='Print tasks', action='store_true')
|
|
||||||
parser.add_argument('--print-details', '-d', help='Print detailed stats', action='store_true')
|
|
||||||
parser.add_argument('--no-errors', '-n', help='Do not print errors', action='store_true')
|
|
||||||
parser.add_argument('--block-len', '-b', help='Block length', type=int, default=1024)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
print("====================================================================")
|
|
||||||
try:
|
|
||||||
ftrc = open(args.file, 'rb')
|
|
||||||
except IOError as e:
|
|
||||||
print("Failed to open trace file (%s)!" % e)
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
passed = True
|
|
||||||
off = 0
|
|
||||||
data_stats = {}
|
|
||||||
last_ts = None
|
|
||||||
tot_discont = 0
|
|
||||||
while True:
|
|
||||||
# ftrc.seek(off)
|
|
||||||
task = None
|
|
||||||
ts = 0
|
|
||||||
trc_buf = ftrc.read(args.block_len)
|
|
||||||
if len(trc_buf) == 0:
|
|
||||||
# print('EOF')
|
|
||||||
break
|
|
||||||
trc_data = struct.unpack('<LL%sB' % (len(trc_buf) - ESP32_TRACE_BLOCK_HDR_SZ), trc_buf)
|
|
||||||
if len(trc_data):
|
|
||||||
# print("%x %x, len %d" % (trc_data[0], trc_data[1], len(trc_data) - 2))
|
|
||||||
# print(trc_data[2:])
|
|
||||||
# sys.exit(0)
|
|
||||||
task = trc_data[ESP32_TRACE_BLOCK_TASK_IDX]
|
|
||||||
ts = trc_data[ESP32_TRACE_BLOCK_TS_IDX]
|
|
||||||
# print(ts)
|
|
||||||
if last_ts and last_ts >= ts:
|
|
||||||
# print("Global TS discontinuity %x -> %x, task %x, stamp %x at %x" % (last_ts, ts, task,
|
|
||||||
# data_stats[task]['stamp'], off))
|
|
||||||
if args.print_details:
|
|
||||||
print("Global TS discontinuity %x -> %x, task %x at %x" % (last_ts, ts, task, off))
|
|
||||||
# tot_discont += 1
|
|
||||||
# passed = False
|
|
||||||
last_ts = ts
|
|
||||||
if task not in data_stats:
|
|
||||||
print("%x: NEW TASK" % task)
|
|
||||||
data_stats[task] = {'stamp': trc_data[ESP32_TRACE_BLOCK_DATA_IDX], 'last_ts': ts, 'count': 1, 'discont_offs': [], 'inv_stamps_offs': []}
|
|
||||||
else:
|
|
||||||
if data_stats[task]['last_ts'] == ts:
|
|
||||||
print("Task TS discontinuity %x -> %x, task %x, stamp %x at %x" % (last_ts, ts, task, data_stats[task]['stamp'], off))
|
|
||||||
data_stats[task]['discont_offs'].append(off)
|
|
||||||
tot_discont += 1
|
|
||||||
passed = False
|
|
||||||
data_stats[task]['last_ts'] = ts
|
|
||||||
data_stats[task]['count'] += 1
|
|
||||||
if len(trc_data) > ESP32_TRACE_BLOCK_DATA_IDX:
|
|
||||||
# print("DATA = %x %x %x %x" % (trc_data[-4], trc_data[-3], trc_data[-2], trc_data[-1]))
|
|
||||||
if args.print_tasks:
|
|
||||||
print("Task[%d] %x, ts %08x, stamp %x" % (off / args.block_len, task, ts, trc_data[ESP32_TRACE_BLOCK_DATA_IDX]))
|
|
||||||
else:
|
|
||||||
print("%x: NO DATA" % task)
|
|
||||||
else:
|
|
||||||
print("Failed to unpack data!")
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
# check data
|
|
||||||
for i in range(ESP32_TRACE_BLOCK_DATA_IDX, len(trc_data)):
|
|
||||||
if trc_data[i] != data_stats[task]['stamp']:
|
|
||||||
if not args.no_errors:
|
|
||||||
print("Invalid stamp %x->%x at %x, task %x" % (data_stats[task]['stamp'], trc_data[i], off + ESP32_TRACE_BLOCK_HDR_SZ + i, task))
|
|
||||||
passed = False
|
|
||||||
data_stats[task]['stamp'] = trc_data[i]
|
|
||||||
data_stats[task]['inv_stamps_offs'].append(off)
|
|
||||||
# break
|
|
||||||
if len(trc_buf) < args.block_len:
|
|
||||||
print('Last block (not full)')
|
|
||||||
break
|
|
||||||
|
|
||||||
if data_stats[task]['stamp'] is not None:
|
|
||||||
data_stats[task]['stamp'] = (data_stats[task]['stamp'] + 1) & 0xFF
|
|
||||||
# print("stamp=%x" % data_stats[task][ESP32_TRACE_STAMP_IDX])
|
|
||||||
off += args.block_len
|
|
||||||
|
|
||||||
ftrc.close()
|
|
||||||
print("====================================================================")
|
|
||||||
print("Trace size %d bytes, discont %d\n" % (off, tot_discont))
|
|
||||||
for t in data_stats:
|
|
||||||
print("Task %x. Total count %d. Inv stamps %d. TS Discontinuities %d." % (t, data_stats[t]['count'],
|
|
||||||
len(data_stats[t]['inv_stamps_offs']), len(data_stats[t]['discont_offs'])))
|
|
||||||
if args.print_details:
|
|
||||||
print('Invalid stamps offs: [{}]'.format(', '.join(hex(x) for x in data_stats[t]['inv_stamps_offs'])))
|
|
||||||
print('TS Discontinuities offs: [{}]'.format(', '.join(hex(x) for x in data_stats[t]['discont_offs'])))
|
|
||||||
print("\n")
|
|
||||||
|
|
||||||
if passed:
|
|
||||||
print("Data - OK")
|
|
||||||
else:
|
|
||||||
print("Data - FAILED!")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
5
tools/esp_app_trace/espytrace/README.md
Normal file
5
tools/esp_app_trace/espytrace/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# espytrace Python package
|
||||||
|
|
||||||
|
This package implements base routines and classes for processing ESP32 application level trace data.
|
||||||
|
- `apptrace.py` includes functionality which is common for all types of trace data.
|
||||||
|
- `sysview.py` includes functionality which is specific for SystemView trace data format.
|
0
tools/esp_app_trace/espytrace/__init__.py
Normal file
0
tools/esp_app_trace/espytrace/__init__.py
Normal file
720
tools/esp_app_trace/espytrace/apptrace.py
Normal file
720
tools/esp_app_trace/espytrace/apptrace.py
Normal file
|
@ -0,0 +1,720 @@
|
||||||
|
import os
|
||||||
|
try:
|
||||||
|
from urlparse import urlparse
|
||||||
|
except ImportError:
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
try:
|
||||||
|
import SocketServer
|
||||||
|
except ImportError:
|
||||||
|
import socketserver as SocketServer
|
||||||
|
import threading
|
||||||
|
import tempfile
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
import os.path
|
||||||
|
import elftools.elf.elffile as elffile
|
||||||
|
import elftools.elf.constants as elfconst
|
||||||
|
|
||||||
|
|
||||||
|
def addr2line(toolchain, elf_path, addr):
|
||||||
|
"""
|
||||||
|
Creates trace reader.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
toolchain : string
|
||||||
|
toolchain prefix to retrieve source line locations using addresses
|
||||||
|
elf_path : string
|
||||||
|
path to ELF file to use
|
||||||
|
addr : int
|
||||||
|
address to retrieve source line location
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
string
|
||||||
|
source line location string
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return subprocess.check_output(['%saddr2line' % toolchain, '-e', elf_path, '0x%x' % addr]).decode("utf-8")
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
class ParseError(RuntimeError):
|
||||||
|
"""
|
||||||
|
Parse error exception
|
||||||
|
"""
|
||||||
|
def __init__(self, message):
|
||||||
|
RuntimeError.__init__(self, message)
|
||||||
|
|
||||||
|
|
||||||
|
class ReaderError(RuntimeError):
|
||||||
|
"""
|
||||||
|
Trace reader error exception
|
||||||
|
"""
|
||||||
|
def __init__(self, message):
|
||||||
|
RuntimeError.__init__(self, message)
|
||||||
|
|
||||||
|
|
||||||
|
class ReaderTimeoutError(ReaderError):
|
||||||
|
"""
|
||||||
|
Trace reader timeout error
|
||||||
|
"""
|
||||||
|
def __init__(self, tmo, sz):
|
||||||
|
ReaderError.__init__(self, 'Timeout %f sec while reading %d bytes!' % (tmo, sz))
|
||||||
|
|
||||||
|
|
||||||
|
class ReaderShutdownRequest(ReaderError):
|
||||||
|
"""
|
||||||
|
Trace reader shutdown request error
|
||||||
|
Raised when user presses CTRL+C (SIGINT).
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
ReaderError.__init__(self, 'Shutdown request!')
|
||||||
|
|
||||||
|
|
||||||
|
class Reader:
|
||||||
|
"""
|
||||||
|
Base abstract reader class
|
||||||
|
"""
|
||||||
|
def __init__(self, tmo):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
tmo : int
|
||||||
|
read timeout
|
||||||
|
"""
|
||||||
|
self.timeout = tmo
|
||||||
|
self.need_stop = False
|
||||||
|
|
||||||
|
def read(self, sz):
|
||||||
|
"""
|
||||||
|
Reads a number of bytes
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
sz : int
|
||||||
|
number of bytes to read
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bytes object
|
||||||
|
read bytes
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
ReaderTimeoutError
|
||||||
|
if timeout expires
|
||||||
|
ReaderShutdownRequest
|
||||||
|
if SIGINT was received during reading
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def readline(self):
|
||||||
|
"""
|
||||||
|
Reads line
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
sz : int
|
||||||
|
number of bytes to read
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
string
|
||||||
|
read line
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def forward(self, sz):
|
||||||
|
"""
|
||||||
|
Moves read pointer to a number of bytes
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
sz : int
|
||||||
|
number of bytes to read
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""
|
||||||
|
Cleans up reader
|
||||||
|
"""
|
||||||
|
self.need_stop = True
|
||||||
|
|
||||||
|
|
||||||
|
class FileReader(Reader):
|
||||||
|
"""
|
||||||
|
File reader class
|
||||||
|
"""
|
||||||
|
def __init__(self, path, tmo):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
path : string
|
||||||
|
path to file to read
|
||||||
|
tmo : int
|
||||||
|
see Reader.__init__()
|
||||||
|
"""
|
||||||
|
Reader.__init__(self, tmo)
|
||||||
|
self.trace_file_path = path
|
||||||
|
self.trace_file = open(path, 'rb')
|
||||||
|
|
||||||
|
def read(self, sz):
|
||||||
|
"""
|
||||||
|
see Reader.read()
|
||||||
|
"""
|
||||||
|
data = b''
|
||||||
|
start_tm = time.clock()
|
||||||
|
while not self.need_stop:
|
||||||
|
data += self.trace_file.read(sz - len(data))
|
||||||
|
if len(data) == sz:
|
||||||
|
break
|
||||||
|
if self.timeout != -1 and time.clock() >= start_tm + self.timeout:
|
||||||
|
raise ReaderTimeoutError(self.timeout, sz)
|
||||||
|
if self.need_stop:
|
||||||
|
raise ReaderShutdownRequest()
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_pos(self):
|
||||||
|
"""
|
||||||
|
Retrieves current file read position
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
int
|
||||||
|
read position
|
||||||
|
"""
|
||||||
|
return self.trace_file.tell()
|
||||||
|
|
||||||
|
def readline(self, linesep=os.linesep):
|
||||||
|
"""
|
||||||
|
see Reader.read()
|
||||||
|
"""
|
||||||
|
line = ''
|
||||||
|
start_tm = time.clock()
|
||||||
|
while not self.need_stop:
|
||||||
|
line += self.trace_file.readline().decode("utf-8")
|
||||||
|
if line.endswith(linesep):
|
||||||
|
break
|
||||||
|
if self.timeout != -1 and time.clock() >= start_tm + self.timeout:
|
||||||
|
raise ReaderTimeoutError(self.timeout, 1)
|
||||||
|
if self.need_stop:
|
||||||
|
raise ReaderShutdownRequest()
|
||||||
|
return line
|
||||||
|
|
||||||
|
def forward(self, sz):
|
||||||
|
"""
|
||||||
|
see Reader.read()
|
||||||
|
"""
|
||||||
|
cur_pos = self.trace_file.tell()
|
||||||
|
start_tm = time.clock()
|
||||||
|
while not self.need_stop:
|
||||||
|
file_sz = os.path.getsize(self.trace_file_path)
|
||||||
|
if file_sz - cur_pos >= sz:
|
||||||
|
break
|
||||||
|
if self.timeout != -1 and time.clock() >= start_tm + self.timeout:
|
||||||
|
raise ReaderTimeoutError(self.timeout, sz)
|
||||||
|
if self.need_stop:
|
||||||
|
raise ReaderShutdownRequest()
|
||||||
|
self.trace_file.seek(sz, os.SEEK_CUR)
|
||||||
|
|
||||||
|
|
||||||
|
class NetRequestHandler:
|
||||||
|
"""
|
||||||
|
Handler for incoming network requests (connections, datagrams)
|
||||||
|
"""
|
||||||
|
def handle(self):
|
||||||
|
while not self.server.need_stop:
|
||||||
|
data = self.rfile.read(1024)
|
||||||
|
if len(data) == 0:
|
||||||
|
break
|
||||||
|
self.server.wtrace.write(data)
|
||||||
|
self.server.wtrace.flush()
|
||||||
|
|
||||||
|
|
||||||
|
class NetReader(FileReader):
|
||||||
|
"""
|
||||||
|
Base netwoek socket reader class
|
||||||
|
"""
|
||||||
|
def __init__(self, tmo):
|
||||||
|
"""
|
||||||
|
see Reader.__init__()
|
||||||
|
"""
|
||||||
|
fhnd,fname = tempfile.mkstemp()
|
||||||
|
FileReader.__init__(self, fname, tmo)
|
||||||
|
self.wtrace = os.fdopen(fhnd, 'wb')
|
||||||
|
self.server_thread = threading.Thread(target=self.serve_forever)
|
||||||
|
self.server_thread.start()
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""
|
||||||
|
see Reader.cleanup()
|
||||||
|
"""
|
||||||
|
FileReader.cleanup(self)
|
||||||
|
self.shutdown()
|
||||||
|
self.server_close()
|
||||||
|
self.server_thread.join()
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.trace_file.close()
|
||||||
|
self.wtrace.close()
|
||||||
|
|
||||||
|
|
||||||
|
class TCPRequestHandler(NetRequestHandler, SocketServer.StreamRequestHandler):
|
||||||
|
"""
|
||||||
|
Handler for incoming TCP connections
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class TCPReader(NetReader, SocketServer.TCPServer):
|
||||||
|
"""
|
||||||
|
TCP socket reader class
|
||||||
|
"""
|
||||||
|
def __init__(self, host, port, tmo):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
host : string
|
||||||
|
see SocketServer.BaseServer.__init__()
|
||||||
|
port : int
|
||||||
|
see SocketServer.BaseServer.__init__()
|
||||||
|
tmo : int
|
||||||
|
see Reader.__init__()
|
||||||
|
"""
|
||||||
|
SocketServer.TCPServer.__init__(self, (host, port), TCPRequestHandler)
|
||||||
|
NetReader.__init__(self, tmo)
|
||||||
|
|
||||||
|
|
||||||
|
class UDPRequestHandler(NetRequestHandler, SocketServer.DatagramRequestHandler):
|
||||||
|
"""
|
||||||
|
Handler for incoming UDP datagrams
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UDPReader(NetReader, SocketServer.UDPServer):
|
||||||
|
"""
|
||||||
|
UDP socket reader class
|
||||||
|
"""
|
||||||
|
def __init__(self, host, port, tmo):
|
||||||
|
"""
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
host : string
|
||||||
|
see SocketServer.BaseServer.__init__()
|
||||||
|
port : int
|
||||||
|
see SocketServer.BaseServer.__init__()
|
||||||
|
tmo : int
|
||||||
|
see Reader.__init__()
|
||||||
|
"""
|
||||||
|
SocketServer.UDPServer.__init__(self, (host, port), UDPRequestHandler)
|
||||||
|
NetReader.__init__(self, tmo)
|
||||||
|
|
||||||
|
|
||||||
|
def reader_create(trc_src, tmo):
|
||||||
|
"""
|
||||||
|
Creates trace reader.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
trc_src : string
|
||||||
|
trace source URL. Supports 'file:///path/to/file' or (tcp|udp)://host:port
|
||||||
|
tmo : int
|
||||||
|
read timeout
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
Reader
|
||||||
|
reader object or None if URL scheme is not supported
|
||||||
|
"""
|
||||||
|
url = urlparse(trc_src)
|
||||||
|
if len(url.scheme) == 0 or url.scheme == 'file':
|
||||||
|
if os.name == 'nt':
|
||||||
|
# workaround for Windows path
|
||||||
|
return FileReader(trc_src[7:], tmo)
|
||||||
|
else:
|
||||||
|
return FileReader(url.path, tmo)
|
||||||
|
if url.scheme == 'tcp':
|
||||||
|
return TCPReader(url.hostname, url.port, tmo)
|
||||||
|
if url.scheme == 'udp':
|
||||||
|
return UDPReader(url.hostname, url.port, tmo)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class TraceDataProcessor:
|
||||||
|
"""
|
||||||
|
Base abstract class for all trace data processors.
|
||||||
|
"""
|
||||||
|
def __init__(self, print_events, keep_all_events=False):
|
||||||
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
print_events : bool
|
||||||
|
if True every event will be printed as they arrive
|
||||||
|
keep_all_events : bool
|
||||||
|
if True all events will be kept in self.events in the order they arrive
|
||||||
|
"""
|
||||||
|
self.print_events = print_events
|
||||||
|
self.keep_all_events = keep_all_events
|
||||||
|
self.total_events = 0
|
||||||
|
self.events = []
|
||||||
|
# This can be changed by the root procesor that includes several sub-processors.
|
||||||
|
# It is used access some method of root processor which can contain methods/data common for all sub-processors.
|
||||||
|
# Common info could be current execution context, info about running tasks, available IRQs etc.
|
||||||
|
self.root_proc = self
|
||||||
|
|
||||||
|
def _print_event(self, event):
|
||||||
|
"""
|
||||||
|
Base method to print an event.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
event : object
|
||||||
|
Event object
|
||||||
|
"""
|
||||||
|
print("EVENT[{:d}]: {}".format(self.total_events, event))
|
||||||
|
|
||||||
|
def print_report(self):
|
||||||
|
"""
|
||||||
|
Base method to print report.
|
||||||
|
"""
|
||||||
|
print("Processed {:d} events".format(self.total_events))
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""
|
||||||
|
Base method to make cleanups.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_new_event(self, event):
|
||||||
|
"""
|
||||||
|
Base method to process event.
|
||||||
|
"""
|
||||||
|
if self.print_events:
|
||||||
|
self._print_event(event)
|
||||||
|
if self.keep_all_events:
|
||||||
|
self.events.append(event)
|
||||||
|
self.total_events += 1
|
||||||
|
|
||||||
|
|
||||||
|
class LogTraceParseError(ParseError):
|
||||||
|
"""
|
||||||
|
Log trace parse error exception.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_str_from_elf(felf, str_addr):
|
||||||
|
"""
|
||||||
|
Retrieves string from ELF file.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
felf : elffile.ELFFile
|
||||||
|
open ELF file handle to retrive format string from
|
||||||
|
str_addr : int
|
||||||
|
address of the string
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
string
|
||||||
|
string or None if it was not found
|
||||||
|
"""
|
||||||
|
tgt_str = ''
|
||||||
|
for sect in felf.iter_sections():
|
||||||
|
if sect['sh_addr'] == 0 or (sect['sh_flags'] & elfconst.SH_FLAGS.SHF_ALLOC) == 0:
|
||||||
|
continue
|
||||||
|
if str_addr < sect['sh_addr'] or str_addr >= sect['sh_addr'] + sect['sh_size']:
|
||||||
|
continue
|
||||||
|
sec_data = sect.data()
|
||||||
|
for i in range(str_addr - sect['sh_addr'], sect['sh_size']):
|
||||||
|
if type(sec_data) is str:
|
||||||
|
ch = sec_data[i]
|
||||||
|
else:
|
||||||
|
ch = str(chr(sec_data[i]))
|
||||||
|
if ch == '\0':
|
||||||
|
break
|
||||||
|
tgt_str += ch
|
||||||
|
if len(tgt_str) > 0:
|
||||||
|
return tgt_str
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class LogTraceEvent:
|
||||||
|
"""
|
||||||
|
Log trace event.
|
||||||
|
"""
|
||||||
|
def __init__(self, fmt_addr, log_args):
|
||||||
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fmt_addr : int
|
||||||
|
address of the format string
|
||||||
|
log_args : list
|
||||||
|
list of log message arguments
|
||||||
|
"""
|
||||||
|
self.fmt_addr = fmt_addr
|
||||||
|
self.args = log_args
|
||||||
|
|
||||||
|
def get_message(self, felf):
|
||||||
|
"""
|
||||||
|
Retrieves log message.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
felf : elffile.ELFFile
|
||||||
|
open ELF file handle to retrive format string from
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
string
|
||||||
|
formatted log message
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
LogTraceParseError
|
||||||
|
if format string has not been found in ELF file
|
||||||
|
"""
|
||||||
|
fmt_str = get_str_from_elf(felf, self.fmt_addr)
|
||||||
|
if not fmt_str:
|
||||||
|
raise LogTraceParseError('Failed to find format string for 0x%x' % self.fmt_addr)
|
||||||
|
prcnt_idx = 0
|
||||||
|
for i, arg in enumerate(self.args):
|
||||||
|
prcnt_idx = fmt_str.find('%', prcnt_idx, -2) # TODO: check str ending with %
|
||||||
|
if prcnt_idx == -1:
|
||||||
|
break
|
||||||
|
prcnt_idx += 1 # goto next char
|
||||||
|
if fmt_str[prcnt_idx] == 's':
|
||||||
|
# find string
|
||||||
|
arg_str = get_str_from_elf(felf, self.args[i])
|
||||||
|
if arg_str:
|
||||||
|
self.args[i] = arg_str
|
||||||
|
else:
|
||||||
|
self.args[i] = '<None>'
|
||||||
|
fmt_str = fmt_str.replace('%p', '%x')
|
||||||
|
return fmt_str % tuple(self.args)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseLogTraceDataProcessorImpl:
|
||||||
|
"""
|
||||||
|
Base implementation for log data processors.
|
||||||
|
"""
|
||||||
|
def __init__(self, print_log_events=False, elf_path=''):
|
||||||
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
print_log_events : bool
|
||||||
|
if True every log event will be printed as they arrive
|
||||||
|
elf_path : string
|
||||||
|
path to ELF file to retrieve format strings for log messages
|
||||||
|
"""
|
||||||
|
if len(elf_path):
|
||||||
|
self.felf = elffile.ELFFile(open(elf_path, 'rb'))
|
||||||
|
else:
|
||||||
|
self.felf = None
|
||||||
|
self.print_log_events = print_log_events
|
||||||
|
self.messages = []
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
"""
|
||||||
|
Cleanup
|
||||||
|
"""
|
||||||
|
if self.felf:
|
||||||
|
self.felf.stream.close()
|
||||||
|
|
||||||
|
def print_report(self):
|
||||||
|
"""
|
||||||
|
Prints log report
|
||||||
|
"""
|
||||||
|
print("=============== LOG TRACE REPORT ===============")
|
||||||
|
print("Processed {:d} log messages.".format(len(self.messages)))
|
||||||
|
|
||||||
|
def on_new_event(self, event):
|
||||||
|
"""
|
||||||
|
Processes log events.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
event : LogTraceEvent
|
||||||
|
Event object.
|
||||||
|
"""
|
||||||
|
msg = event.get_message(self.felf)
|
||||||
|
self.messages.append(msg)
|
||||||
|
if self.print_log_events:
|
||||||
|
print(msg),
|
||||||
|
|
||||||
|
|
||||||
|
class HeapTraceParseError(ParseError):
|
||||||
|
"""
|
||||||
|
Heap trace parse error exception.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class HeapTraceDuplicateAllocError(HeapTraceParseError):
|
||||||
|
"""
|
||||||
|
Heap trace duplicate allocation error exception.
|
||||||
|
"""
|
||||||
|
def __init__(self, addr, new_size, prev_size):
|
||||||
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
addr : int
|
||||||
|
memory block address
|
||||||
|
new_size : int
|
||||||
|
size of the new allocation
|
||||||
|
prev_size : int
|
||||||
|
size of the previous allocation
|
||||||
|
"""
|
||||||
|
HeapTraceParseError.__init__(self, """Duplicate alloc @ 0x{:x}!
|
||||||
|
New alloc is {:d} bytes,
|
||||||
|
previous is {:d} bytes.""".format(addr, new_size, prev_size))
|
||||||
|
|
||||||
|
|
||||||
|
class HeapTraceEvent:
|
||||||
|
"""
|
||||||
|
Heap trace event.
|
||||||
|
"""
|
||||||
|
def __init__(self, ctx_name, in_irq, core_id, ts, alloc, size, addr, callers, toolchain='', elf_path=''):
|
||||||
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
ctx_name : string
|
||||||
|
name of event context (task or IRQ name)
|
||||||
|
in_irq : bool
|
||||||
|
True if event has been generated in IRQ context, otherwise False
|
||||||
|
core_id : int
|
||||||
|
core which generated the event
|
||||||
|
ts : float
|
||||||
|
event timestamp
|
||||||
|
alloc : bool
|
||||||
|
True for allocation event, otherwise False
|
||||||
|
size : int
|
||||||
|
size of allocation; has no meaning for de-allocation event
|
||||||
|
addr : int
|
||||||
|
address of allocation/de-allocation
|
||||||
|
callers : list
|
||||||
|
list of callers (callstack) for event
|
||||||
|
toolchain_pref : string
|
||||||
|
toolchain prefix to retrieve source line locations using addresses
|
||||||
|
elf_path : string
|
||||||
|
path to ELF file to retrieve format strings for log messages
|
||||||
|
"""
|
||||||
|
self.ctx_name = ctx_name
|
||||||
|
self.in_irq = in_irq
|
||||||
|
self.core_id = core_id
|
||||||
|
self.ts = ts
|
||||||
|
self.alloc = alloc
|
||||||
|
self.size = size
|
||||||
|
self.addr = addr
|
||||||
|
self.callers = callers
|
||||||
|
self.toolchain = toolchain
|
||||||
|
self.elf_path = elf_path
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if len(self.toolchain) and len(self.elf_path):
|
||||||
|
callers = os.linesep
|
||||||
|
for addr in self.callers:
|
||||||
|
callers += '{}'.format(addr2line(self.toolchain, self.elf_path, addr))
|
||||||
|
else:
|
||||||
|
callers = ''
|
||||||
|
for addr in self.callers:
|
||||||
|
if len(callers):
|
||||||
|
callers += ':'
|
||||||
|
callers += '0x{:x}'.format(addr)
|
||||||
|
if self.in_irq:
|
||||||
|
ctx_desc = 'IRQ "%s"' % self.ctx_name
|
||||||
|
else:
|
||||||
|
ctx_desc = 'task "%s"' % self.ctx_name
|
||||||
|
if self.alloc:
|
||||||
|
return "[{:.9f}] HEAP: Allocated {:d} bytes @ 0x{:x} from {} on core {:d} by: {}".format(self.ts, self.size,
|
||||||
|
self.addr, ctx_desc,
|
||||||
|
self.core_id, callers)
|
||||||
|
else:
|
||||||
|
return "[{:.9f}] HEAP: Freed bytes @ 0x{:x} from {} on core {:d} by: {}".format(self.ts, self.addr, ctx_desc,
|
||||||
|
self.core_id, callers)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseHeapTraceDataProcessorImpl:
|
||||||
|
"""
|
||||||
|
Base implementation for heap data processors.
|
||||||
|
"""
|
||||||
|
def __init__(self, print_heap_events=False):
|
||||||
|
"""
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
print_heap_events : bool
|
||||||
|
if True every heap event will be printed as they arrive
|
||||||
|
"""
|
||||||
|
self._alloc_addrs = {}
|
||||||
|
self.allocs = []
|
||||||
|
self.frees = []
|
||||||
|
self.heap_events_count = 0
|
||||||
|
self.print_heap_events = print_heap_events
|
||||||
|
|
||||||
|
def on_new_event(self, event):
|
||||||
|
"""
|
||||||
|
Processes heap events. Keeps track of active allocations list.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
event : HeapTraceEvent
|
||||||
|
Event object.
|
||||||
|
"""
|
||||||
|
self.heap_events_count += 1
|
||||||
|
if self.print_heap_events:
|
||||||
|
print(event)
|
||||||
|
if event.alloc:
|
||||||
|
if event.addr in self._alloc_addrs:
|
||||||
|
raise HeapTraceDuplicateAllocError(event.addr, event.size, self._alloc_addrs[event.addr].size)
|
||||||
|
self.allocs.append(event)
|
||||||
|
self._alloc_addrs[event.addr] = event
|
||||||
|
else:
|
||||||
|
# do not treat free on unknown addresses as errors, because these blocks coould be allocated when tracing was disabled
|
||||||
|
if event.addr in self._alloc_addrs:
|
||||||
|
event.size = self._alloc_addrs[event.addr].size
|
||||||
|
self.allocs.remove(self._alloc_addrs[event.addr])
|
||||||
|
del self._alloc_addrs[event.addr]
|
||||||
|
else:
|
||||||
|
self.frees.append(event)
|
||||||
|
|
||||||
|
def print_report(self):
|
||||||
|
"""
|
||||||
|
Prints heap report
|
||||||
|
"""
|
||||||
|
print("=============== HEAP TRACE REPORT ===============")
|
||||||
|
print("Processed {:d} heap events.".format(self.heap_events_count))
|
||||||
|
if len(self.allocs) == 0:
|
||||||
|
print("OK - Heap errors was not found.")
|
||||||
|
return
|
||||||
|
leaked_bytes = 0
|
||||||
|
for alloc in self.allocs:
|
||||||
|
leaked_bytes += alloc.size
|
||||||
|
print(alloc)
|
||||||
|
for free in self.frees:
|
||||||
|
if free.addr > alloc.addr and free.addr <= alloc.addr + alloc.size:
|
||||||
|
print("Possible wrong free operation found")
|
||||||
|
print(free)
|
||||||
|
print("Found {:d} leaked bytes in {:d} blocks.".format(leaked_bytes, len(self.allocs)))
|
1220
tools/esp_app_trace/espytrace/sysview.py
Normal file
1220
tools/esp_app_trace/espytrace/sysview.py
Normal file
File diff suppressed because it is too large
Load diff
|
@ -5,11 +5,8 @@ from __future__ import print_function
|
||||||
import argparse
|
import argparse
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import pylibelf as elf
|
import elftools.elf.elffile as elffile
|
||||||
import pylibelf.util as elfutil
|
import espytrace.apptrace as apptrace
|
||||||
import pylibelf.iterators as elfiter
|
|
||||||
import pylibelf.constants as elfconst
|
|
||||||
import ctypes
|
|
||||||
|
|
||||||
|
|
||||||
class ESPLogTraceParserError(RuntimeError):
|
class ESPLogTraceParserError(RuntimeError):
|
||||||
|
@ -77,34 +74,14 @@ def logtrace_parse(fname):
|
||||||
return recs
|
return recs
|
||||||
|
|
||||||
|
|
||||||
def logtrace_get_str_from_elf(felf, str_addr):
|
|
||||||
tgt_str = ""
|
|
||||||
for sect in elfiter.sections(felf):
|
|
||||||
hdr = elfutil.section_hdr(felf, sect)
|
|
||||||
if hdr.sh_addr == 0 or hdr.sh_type != elfconst.SHT_PROGBITS:
|
|
||||||
continue
|
|
||||||
if str_addr < hdr.sh_addr or str_addr >= hdr.sh_addr + hdr.sh_size:
|
|
||||||
continue
|
|
||||||
# print("Found SECT: %x..%x @ %x" % (hdr.sh_addr, hdr.sh_addr + hdr.sh_size, str_addr - hdr.sh_addr))
|
|
||||||
sec_data = elfiter.getOnlyData(sect).contents
|
|
||||||
buf = ctypes.cast(sec_data.d_buf, ctypes.POINTER(ctypes.c_char))
|
|
||||||
for i in range(str_addr - hdr.sh_addr, hdr.sh_size):
|
|
||||||
if buf[i] == "\0":
|
|
||||||
break
|
|
||||||
tgt_str += buf[i]
|
|
||||||
if len(tgt_str) > 0:
|
|
||||||
return tgt_str
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def logtrace_formated_print(recs, elfname, no_err):
|
def logtrace_formated_print(recs, elfname, no_err):
|
||||||
try:
|
try:
|
||||||
felf = elfutil.open_elf(elfname)
|
felf = elffile.ELFFile(open(elfname, 'rb'))
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise ESPLogTraceParserError("Failed to open ELF file (%s)!" % e)
|
raise ESPLogTraceParserError("Failed to open ELF file (%s)!" % e)
|
||||||
|
|
||||||
for lrec in recs:
|
for lrec in recs:
|
||||||
fmt_str = logtrace_get_str_from_elf(felf, lrec.fmt_addr)
|
fmt_str = apptrace.get_str_from_elf(felf, lrec.fmt_addr)
|
||||||
i = 0
|
i = 0
|
||||||
prcnt_idx = 0
|
prcnt_idx = 0
|
||||||
while i < len(lrec.args):
|
while i < len(lrec.args):
|
||||||
|
@ -114,7 +91,7 @@ def logtrace_formated_print(recs, elfname, no_err):
|
||||||
prcnt_idx += 1 # goto next char
|
prcnt_idx += 1 # goto next char
|
||||||
if fmt_str[prcnt_idx] == 's':
|
if fmt_str[prcnt_idx] == 's':
|
||||||
# find string
|
# find string
|
||||||
arg_str = logtrace_get_str_from_elf(felf, lrec.args[i])
|
arg_str = apptrace.get_str_from_elf(felf, lrec.args[i])
|
||||||
if arg_str:
|
if arg_str:
|
||||||
lrec.args[i] = arg_str
|
lrec.args[i] = arg_str
|
||||||
i += 1
|
i += 1
|
||||||
|
@ -129,8 +106,7 @@ def logtrace_formated_print(recs, elfname, no_err):
|
||||||
if not no_err:
|
if not no_err:
|
||||||
print("Print error (%s)" % e)
|
print("Print error (%s)" % e)
|
||||||
print("\nFmt = {%s}, args = %d/%s" % (fmt_str, len(lrec.args), lrec.args))
|
print("\nFmt = {%s}, args = %d/%s" % (fmt_str, len(lrec.args), lrec.args))
|
||||||
|
felf.stream.close()
|
||||||
elf.elf_end(felf)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
59
tools/esp_app_trace/pylibelf/.gitignore
vendored
59
tools/esp_app_trace/pylibelf/.gitignore
vendored
|
@ -1,59 +0,0 @@
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
env/
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.coverage
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
target/
|
|
||||||
|
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
*.swn
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 d1m0
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
pylibelf
|
|
||||||
========
|
|
||||||
|
|
||||||
Python binding for libelf.
|
|
||||||
|
|
|
@ -1,155 +0,0 @@
|
||||||
from types import *
|
|
||||||
from constants import *
|
|
||||||
from ctypes import *
|
|
||||||
|
|
||||||
lelf=CDLL("libelf.so.1")
|
|
||||||
|
|
||||||
__all__ = []
|
|
||||||
|
|
||||||
all_objs = []
|
|
||||||
|
|
||||||
class ElfError(Exception):
|
|
||||||
def __init__(self, msg):
|
|
||||||
self.msg = msg
|
|
||||||
self.errno = elf_errno()
|
|
||||||
self.elfmsg = elf_errmsg(self.errno)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return "ElfError(%d, %s): %s" % (self.errno, self.elfmsg, self.msg)
|
|
||||||
|
|
||||||
__all__.append("ElfError")
|
|
||||||
|
|
||||||
def nonNullDec(f):
|
|
||||||
def decorated(*args):
|
|
||||||
res = f(*args)
|
|
||||||
try:
|
|
||||||
a = res.contents
|
|
||||||
all_objs.append(res)
|
|
||||||
except ValueError: # NULL
|
|
||||||
raise ElfError(f.__name__ + " returned NULL")
|
|
||||||
return res
|
|
||||||
return decorated
|
|
||||||
|
|
||||||
def nonNegDec(f):
|
|
||||||
def decorated(*args):
|
|
||||||
res = f(*args)
|
|
||||||
if 0 > res:
|
|
||||||
raise ElfError(f.__name__ + " returned %d" % (res,))
|
|
||||||
return res
|
|
||||||
return decorated
|
|
||||||
|
|
||||||
def badValDec(badVal):
|
|
||||||
def decorator(f):
|
|
||||||
def decorated(*args):
|
|
||||||
res = f(*args)
|
|
||||||
if res == badVal:
|
|
||||||
raise ElfError(f.__name__ + " returned %s" % (str(res),))
|
|
||||||
return res
|
|
||||||
return decorated
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
def define(f, argtypes, restype, err_decorator = None):
|
|
||||||
f.argtypes = argtypes
|
|
||||||
f.restype = restype
|
|
||||||
name = f.__name__
|
|
||||||
__all__.append(name)
|
|
||||||
|
|
||||||
if (err_decorator != None):
|
|
||||||
f = err_decorator(f)
|
|
||||||
|
|
||||||
globals()[name] = f
|
|
||||||
|
|
||||||
define(lelf.elf_version, [ c_int ], c_int )
|
|
||||||
|
|
||||||
if (elf_version(EV_CURRENT) == EV_NONE):
|
|
||||||
raise Exception("Version mismatch")
|
|
||||||
|
|
||||||
off_t = c_size_t # TODO(dbounov): Figure out actual off_t type
|
|
||||||
|
|
||||||
define(lelf.elf_begin, [ c_int, Elf_Cmd, ElfP ], ElfP)
|
|
||||||
define(lelf.elf_getident, [ ElfP, POINTER(c_int) ], POINTER(Elf_IdentT), nonNullDec)
|
|
||||||
define(lelf.elf_end, [ ElfP ], c_int, nonNegDec )
|
|
||||||
define(lelf.elf_cntl, [ ElfP, c_int ], c_int, nonNegDec)
|
|
||||||
define(lelf.elf_errmsg, [ c_int ], c_char_p)
|
|
||||||
define(lelf.elf_errno, [ ], c_int)
|
|
||||||
define(lelf.elf_fill, [ c_int ], None)
|
|
||||||
define(lelf.elf_flagdata, [ Elf_DataP, c_int, c_uint ], c_uint)
|
|
||||||
define(lelf.elf_flagehdr, [ ElfP, c_int, c_uint ], c_uint)
|
|
||||||
define(lelf.elf_flagelf, [ ElfP, c_int, c_uint ], c_uint)
|
|
||||||
define(lelf.elf_flagphdr, [ ElfP, c_int, c_uint ], c_uint)
|
|
||||||
define(lelf.elf_flagscn, [ Elf_ScnP, c_int, c_uint ], c_uint)
|
|
||||||
define(lelf.elf_flagshdr, [ Elf_ScnP, c_int, c_uint ], c_uint)
|
|
||||||
define(lelf.elf_getarhdr, [ ElfP ], POINTER(Elf_Arhdr))
|
|
||||||
#define(lelf.elf_getarsym, [ ], )
|
|
||||||
define(lelf.elf_getbase, [ ElfP ], off_t, nonNegDec)
|
|
||||||
define(lelf.elf_getdata, [ Elf_ScnP, Elf_DataP ], Elf_DataP)
|
|
||||||
define(lelf.elf_getscn, [ ElfP, c_size_t ], Elf_ScnP, nonNullDec )
|
|
||||||
define(lelf.elf_getshnum, [ ElfP, POINTER(c_size_t) ], c_int, nonNegDec )
|
|
||||||
define(lelf.elf_getshstrndx, [ ElfP, POINTER(c_size_t) ], c_int, nonNegDec )
|
|
||||||
define(lelf.elf_hash, [ c_char_p ], c_ulong)
|
|
||||||
define(lelf.elf_kind, [ ElfP ], c_int )
|
|
||||||
define(lelf.elf_memory, [ POINTER(c_char), c_size_t ], ElfP, nonNullDec)
|
|
||||||
define(lelf.elf_ndxscn, [ Elf_ScnP ], c_size_t, badValDec(SHN_UNDEF))
|
|
||||||
define(lelf.elf_newdata, [ Elf_ScnP ], Elf_DataP, nonNullDec)
|
|
||||||
define(lelf.elf_newscn, [ ElfP ], Elf_ScnP, nonNullDec)
|
|
||||||
#define(lelf.elf_next, [ ], )
|
|
||||||
define(lelf.elf_nextscn, [ ElfP, Elf_ScnP ], Elf_ScnP)
|
|
||||||
#define(lelf.elf_rand, [ ], )
|
|
||||||
define(lelf.elf_rawdata, [ Elf_ScnP, Elf_DataP ], Elf_DataP)
|
|
||||||
#define(lelf.elf_rawfile, [ ], )
|
|
||||||
define(lelf.elf_strptr, [ ElfP, c_size_t, c_size_t ], c_char_p)
|
|
||||||
define(lelf.elf_update, [ ElfP, c_int], off_t, nonNegDec)
|
|
||||||
|
|
||||||
define(lelf.elf32_checksum, [ ElfP ], c_long)
|
|
||||||
define(lelf.elf32_fsize, [ c_int, c_size_t, c_uint ], c_size_t, nonNegDec)
|
|
||||||
define(lelf.elf32_getehdr, [ ElfP ], POINTER(Elf32_Ehdr), nonNullDec)
|
|
||||||
define(lelf.elf32_getphdr, [ ElfP ], POINTER(Elf32_Phdr), nonNullDec)
|
|
||||||
define(lelf.elf32_getshdr, [ Elf_ScnP ], POINTER(Elf32_Shdr), nonNullDec)
|
|
||||||
define(lelf.elf32_newehdr, [ ElfP ], POINTER(Elf32_Ehdr), nonNullDec)
|
|
||||||
define(lelf.elf32_newphdr, [ ElfP, c_size_t ], POINTER(Elf32_Phdr), nonNullDec)
|
|
||||||
define(lelf.elf32_xlatetof, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec)
|
|
||||||
define(lelf.elf32_xlatetom, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec)
|
|
||||||
|
|
||||||
|
|
||||||
define(lelf.elf64_checksum, [ ElfP ], c_long )
|
|
||||||
define(lelf.elf64_fsize, [ c_int, c_size_t, c_uint ], c_size_t, nonNegDec)
|
|
||||||
define(lelf.elf64_getehdr,[ ElfP ], POINTER(Elf64_Ehdr), nonNullDec)
|
|
||||||
define(lelf.elf64_getphdr, [ ElfP ], POINTER(Elf64_Phdr), nonNullDec)
|
|
||||||
define(lelf.elf64_getshdr, [ Elf_ScnP ], POINTER(Elf64_Shdr), nonNullDec)
|
|
||||||
define(lelf.elf64_newehdr, [ ElfP ], POINTER(Elf64_Ehdr), nonNullDec)
|
|
||||||
define(lelf.elf64_newphdr, [ ElfP, c_size_t ], POINTER(Elf64_Phdr), nonNullDec)
|
|
||||||
define(lelf.elf64_xlatetof, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec)
|
|
||||||
define(lelf.elf64_xlatetom, [ Elf_DataP, Elf_DataP, c_uint ], Elf_DataP, nonNullDec)
|
|
||||||
|
|
||||||
# NOTE(dbounov): Ignoring gelf functions for now
|
|
||||||
|
|
||||||
#define(lelf.gelf_checksum, [ ], )
|
|
||||||
#define(lelf.gelf_fsize, [ ], )
|
|
||||||
#define(lelf.gelf_getcap, [ ], )
|
|
||||||
#define(lelf.gelf_getclass, [ ], )
|
|
||||||
#define(lelf.gelf_getdyn, [ ], )
|
|
||||||
#define(lelf.gelf_getehdr, [ ], )
|
|
||||||
#define(lelf.gelf_getmove, [ ], )
|
|
||||||
#define(lelf.gelf_getphdr, [ ], )
|
|
||||||
#define(lelf.gelf_getrel, [ ], )
|
|
||||||
#define(lelf.gelf_getrela, [ ], )
|
|
||||||
#define(lelf.gelf_getshdr, [ ], )
|
|
||||||
#define(lelf.gelf_getsym, [ ], )
|
|
||||||
#define(lelf.gelf_getsyminfo, [ ], )
|
|
||||||
#define(lelf.gelf_getsymshndx, [ ], )
|
|
||||||
#define(lelf.gelf_newehdr, [ ], )
|
|
||||||
#define(lelf.gelf_newphdr, [ ], )
|
|
||||||
#define(lelf.gelf_update_cap, [ ], )
|
|
||||||
#define(lelf.gelf_update_dyn, [ ], )
|
|
||||||
#define(lelf.gelf_update_ehdr, [ ], )
|
|
||||||
#define(lelf.gelf_update_move, [ ], )
|
|
||||||
#define(lelf.gelf_update_phdr, [ ], )
|
|
||||||
#define(lelf.gelf_update_rel, [ ], )
|
|
||||||
#define(lelf.gelf_update_rela, [ ], )
|
|
||||||
#define(lelf.gelf_update_shdr, [ ], )
|
|
||||||
#define(lelf.gelf_update_sym, [ ], )
|
|
||||||
#define(lelf.gelf_update_symshndx, [ ], )
|
|
||||||
#define(lelf.gelf_update_syminfo, [ ], )
|
|
||||||
#define(lelf.gelf_xlatetof, [ ], )
|
|
||||||
#define(lelf.gelf_xlatetom, [ ], )
|
|
||||||
#define(lelf.nlist, [ ], )
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,216 +0,0 @@
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from .. import *
|
|
||||||
from ..constants import *
|
|
||||||
from ..types import *
|
|
||||||
from ..util import *
|
|
||||||
from ctypes import *
|
|
||||||
|
|
||||||
def sections(elf, **kwargs):
|
|
||||||
i = None
|
|
||||||
ndx = 0 # we skip the first null section
|
|
||||||
if 'info' in kwargs:
|
|
||||||
if (isinstance(kwargs['info'], Elf_Scn)):
|
|
||||||
info = elf_ndxscn(kwargs['info'])
|
|
||||||
else:
|
|
||||||
info = kwargs['info']
|
|
||||||
else:
|
|
||||||
info = None
|
|
||||||
while 1:
|
|
||||||
i = elf_nextscn(elf, i)
|
|
||||||
ndx += 1
|
|
||||||
|
|
||||||
if (not bool(i)):
|
|
||||||
break
|
|
||||||
|
|
||||||
try:
|
|
||||||
if ('name' in kwargs and section_name(elf, i) != kwargs['name']):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ('type' in kwargs and section_type(elf, i) != kwargs['type']):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ('link' in kwargs and section_link(elf, i) != kwargs['link']):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if (info != None and section_hdr(elf, i).sh_info != info):
|
|
||||||
continue
|
|
||||||
except ValueError:
|
|
||||||
print "Error iterating over section ", i
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ('ndx' in kwargs and kwargs['ndx']):
|
|
||||||
yield (ndx, i.contents)
|
|
||||||
else:
|
|
||||||
yield i.contents
|
|
||||||
|
|
||||||
|
|
||||||
def shdrs(elf):
|
|
||||||
i = None
|
|
||||||
while 1:
|
|
||||||
i = elf_nextscn(elf, i)
|
|
||||||
if (not bool(i)):
|
|
||||||
break
|
|
||||||
|
|
||||||
yield select(elf, 'getshdr')(i.contents).contents
|
|
||||||
|
|
||||||
def phdrs(elf):
|
|
||||||
phdrTbl = select(elf, "getphdr")(elf)
|
|
||||||
ehdr = select(elf, "getehdr")(elf).contents
|
|
||||||
phdrCnt = ehdr.e_phnum
|
|
||||||
|
|
||||||
for i in xrange(0, phdrCnt):
|
|
||||||
yield phdrTbl[i]
|
|
||||||
|
|
||||||
def data(elf_scn):
|
|
||||||
i = None
|
|
||||||
while 1:
|
|
||||||
i = elf_getdata(elf_scn, i)
|
|
||||||
|
|
||||||
if (not bool(i)):
|
|
||||||
break
|
|
||||||
|
|
||||||
yield i.contents
|
|
||||||
|
|
||||||
def strings(v):
|
|
||||||
if (isinstance(v, Elf_Data)):
|
|
||||||
strtab_data = v
|
|
||||||
size = strtab_data.d_size
|
|
||||||
buf = cast(strtab_data.d_buf, POINTER(c_char))
|
|
||||||
start = 0;
|
|
||||||
while start < size:
|
|
||||||
end = start;
|
|
||||||
while buf[end] != '\x00': end += 1
|
|
||||||
yield (strtab_data.d_off + start, buf[start:end])
|
|
||||||
|
|
||||||
start = end+1
|
|
||||||
elif (isinstance(v, Elf_Scn)):
|
|
||||||
for d in data(v):
|
|
||||||
strtab_data = d
|
|
||||||
size = strtab_data.d_size
|
|
||||||
buf = cast(strtab_data.d_buf, POINTER(c_char))
|
|
||||||
start = 0;
|
|
||||||
while start < size:
|
|
||||||
end = start;
|
|
||||||
while buf[end] != '\x00': end += 1
|
|
||||||
yield (strtab_data.d_off + start, buf[start:end])
|
|
||||||
|
|
||||||
start = end+1
|
|
||||||
|
|
||||||
|
|
||||||
def arr_iter(data, itemT, ind = False):
|
|
||||||
size = data.d_size
|
|
||||||
|
|
||||||
if size % sizeof(itemT) != 0:
|
|
||||||
raise Exception("Data size not a multiple of symbol size!")
|
|
||||||
|
|
||||||
buf = cast(data.d_buf, POINTER(itemT))
|
|
||||||
nelems = size / sizeof(itemT)
|
|
||||||
|
|
||||||
for i in xrange(0, nelems):
|
|
||||||
if ind:
|
|
||||||
yield (i, buf[i])
|
|
||||||
else:
|
|
||||||
yield buf[i]
|
|
||||||
|
|
||||||
def syms(elf, v = None):
|
|
||||||
symT = Elf32_Sym if (is32(elf)) else Elf64_Sym
|
|
||||||
if v == None:
|
|
||||||
for s in sections(elf):
|
|
||||||
hdr = section_hdr(elf, s)
|
|
||||||
|
|
||||||
if (hdr.sh_type != SHT_SYMTAB and hdr.sh_type != SHT_DYNSYM):
|
|
||||||
continue
|
|
||||||
|
|
||||||
for d in data(s):
|
|
||||||
for (ind, sym) in arr_iter(d, symT, True):
|
|
||||||
yield (ind, sym)
|
|
||||||
elif isinstance(v, Elf_Scn):
|
|
||||||
for d in data(v):
|
|
||||||
for (ind, sym) in arr_iter(d, symT, True):
|
|
||||||
yield (ind, sym)
|
|
||||||
else:
|
|
||||||
assert isinstance(v, Elf_Data)
|
|
||||||
for (ind, sym) in arr_iter(v, symT, True):
|
|
||||||
yield (ind, sym)
|
|
||||||
|
|
||||||
def rels(elf, **kwargs):
|
|
||||||
relT = Elf32_Rel if (is32(elf)) else Elf64_Rel
|
|
||||||
if 'section' in kwargs:
|
|
||||||
secl = sections(elf, type = SHT_REL, info = kwargs['section'])
|
|
||||||
else:
|
|
||||||
secl = sections(elf, type = SHT_REL)
|
|
||||||
|
|
||||||
|
|
||||||
if 'range' in kwargs:
|
|
||||||
for scn in secl:
|
|
||||||
for d in data(scn):
|
|
||||||
for rel in arr_iter(d, relT):
|
|
||||||
if (rel.r_offset >= kwargs['range'][0] and
|
|
||||||
rel.r_offset < kwargs['range'][1]):
|
|
||||||
yield (rel, section_hdr(elf, scn).sh_link)
|
|
||||||
else:
|
|
||||||
for scn in secl:
|
|
||||||
for d in data(scn):
|
|
||||||
for rel in arr_iter(d, relT):
|
|
||||||
yield (rel, section_hdr(elf, scn).sh_link)
|
|
||||||
|
|
||||||
def relas(elf, **kwargs):
|
|
||||||
relT = Elf32_Rela if (is32(elf)) else Elf64_Rela
|
|
||||||
if 'section' in kwargs:
|
|
||||||
scn = kwargs['section']
|
|
||||||
if (type(scn) == str): scn = list(sections(elf, name=scn))[0]
|
|
||||||
if (isinstance(scn, Elf_Scn)): scn = elf_ndxscn(byref(scn))
|
|
||||||
secl = list(sections(elf, type = SHT_RELA, info = scn))
|
|
||||||
else:
|
|
||||||
secl = list(sections(elf, type = SHT_RELA))
|
|
||||||
|
|
||||||
if 'range' in kwargs:
|
|
||||||
for scn in secl:
|
|
||||||
for d in data(scn):
|
|
||||||
for rel in arr_iter(d, relT):
|
|
||||||
if (rel.r_offset + rel.r_addend >= kwargs['range'][0] and
|
|
||||||
rel.r_offset + rel.r_addend < kwargs['range'][1]):
|
|
||||||
yield (rel, section_hdr(elf, scn).sh_link)
|
|
||||||
else:
|
|
||||||
addSecId = kwargs['withSectionId']==True \
|
|
||||||
if 'withSectionId' in kwargs \
|
|
||||||
else False
|
|
||||||
if not addSecId:
|
|
||||||
for scn in secl:
|
|
||||||
for d in data(scn):
|
|
||||||
for rel in arr_iter(d, relT):
|
|
||||||
yield (rel, section_hdr(elf, scn).sh_link)
|
|
||||||
else:
|
|
||||||
for scn in secl:
|
|
||||||
for d in data(scn):
|
|
||||||
for rel in arr_iter(d, relT):
|
|
||||||
yield (rel, section_hdr(elf, scn).sh_info)
|
|
||||||
|
|
||||||
def getOnlyData(scn):
|
|
||||||
d = elf_getdata(scn, None);
|
|
||||||
assert bool(elf_getdata(scn, d)) == False
|
|
||||||
return d
|
|
||||||
|
|
||||||
def dyns(elf):
|
|
||||||
relT = Elf64_Dyn
|
|
||||||
for scn in sections(elf, name=".dynamic"):
|
|
||||||
for d in data(scn):
|
|
||||||
for dyn in arr_iter(d, relT):
|
|
||||||
yield dyn
|
|
||||||
|
|
||||||
def elfs(fname):
|
|
||||||
fd = os.open(fname, os.O_RDONLY)
|
|
||||||
ar = elf_begin(fd, ELF_C_READ, None)
|
|
||||||
|
|
||||||
i = None
|
|
||||||
while 1:
|
|
||||||
i = elf_begin(fd, ELF_C_READ, ar)
|
|
||||||
if (not bool(i)):
|
|
||||||
break
|
|
||||||
|
|
||||||
yield i
|
|
||||||
|
|
||||||
elf_end(ar)
|
|
||||||
os.close(fd)
|
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
def ELF32_R_SYM(i):
|
|
||||||
if type(i) == str:
|
|
||||||
assert(len(i) == 1) # Single char
|
|
||||||
i = ord(i)
|
|
||||||
return i >> 8
|
|
||||||
|
|
||||||
def ELF32_R_TYPE(i):
|
|
||||||
if type(i) == str:
|
|
||||||
assert(len(i) == 1) # Single char
|
|
||||||
i = ord(i)
|
|
||||||
return i % 256 # Lowest 8 bits
|
|
||||||
|
|
||||||
def ELF32_R_INFO(sym, typ):
|
|
||||||
return (((sym) << 8) + typ % 256)
|
|
||||||
|
|
||||||
def ELF64_R_SYM(i):
|
|
||||||
if type(i) == str:
|
|
||||||
assert(len(i) == 1) # Single char
|
|
||||||
i = ord(i)
|
|
||||||
return i >> 32
|
|
||||||
|
|
||||||
def ELF64_R_TYPE(i):
|
|
||||||
if type(i) == str:
|
|
||||||
assert(len(i) == 1) # Single char
|
|
||||||
i = ord(i)
|
|
||||||
return i & 0xffffffffL
|
|
||||||
|
|
||||||
def ELF64_R_INFO(sym, typ):
|
|
||||||
return ((sym << 32) + (typ & 0xffffffffL))
|
|
||||||
|
|
||||||
# symbol st_info
|
|
||||||
|
|
||||||
def ELF32_ST_BIND(val):
|
|
||||||
if type(val) == str:
|
|
||||||
assert(len(val) == 1) # Single char
|
|
||||||
val = ord(val)
|
|
||||||
return val >> 4
|
|
||||||
|
|
||||||
def ELF32_ST_TYPE(val):
|
|
||||||
if type(val) == str:
|
|
||||||
assert(len(val) == 1) # Single char
|
|
||||||
val = ord(val)
|
|
||||||
return val & 0xf
|
|
||||||
|
|
||||||
def ELF32_ST_INFO(bind, type):
|
|
||||||
return (((bind) << 4) + ((type) & 0xf))
|
|
||||||
|
|
||||||
def ELF64_ST_BIND(val):
|
|
||||||
return ELF32_ST_BIND(val)
|
|
||||||
|
|
||||||
def ELF64_ST_TYPE(val):
|
|
||||||
return ELF32_ST_TYPE(val)
|
|
||||||
|
|
||||||
def ELF64_ST_INFO(bind, type):
|
|
||||||
return ELF32_ST_INFO(bind, type)
|
|
|
@ -1,274 +0,0 @@
|
||||||
from ctypes import *
|
|
||||||
from ..constants import EI_NIDENT
|
|
||||||
|
|
||||||
# Obtained from /usr/lib/elf.h
|
|
||||||
|
|
||||||
# Type for a 16-bit quantity.
|
|
||||||
Elf32_Half = c_uint16
|
|
||||||
Elf64_Half = c_uint16
|
|
||||||
|
|
||||||
# Types for signed and unsigned 32-bit quantities.
|
|
||||||
Elf32_Word = c_uint32
|
|
||||||
Elf32_Sword = c_int32
|
|
||||||
Elf64_Word = c_uint32
|
|
||||||
Elf64_Sword = c_int32
|
|
||||||
|
|
||||||
# Types for signed and unsigned 64-bit quantities.
|
|
||||||
Elf32_Xword = c_uint64
|
|
||||||
Elf32_Sxword = c_int64
|
|
||||||
Elf64_Xword = c_uint64
|
|
||||||
Elf64_Sxword = c_int64
|
|
||||||
|
|
||||||
# Type of addresses.
|
|
||||||
Elf32_Addr = c_uint32
|
|
||||||
Elf64_Addr = c_uint64
|
|
||||||
|
|
||||||
# Type of file offsets.
|
|
||||||
Elf32_Off = c_uint32
|
|
||||||
Elf64_Off = c_uint64
|
|
||||||
|
|
||||||
# Type for section indices, which are 16-bit quantities.
|
|
||||||
Elf32_Section = c_uint16
|
|
||||||
Elf64_Section = c_uint16
|
|
||||||
|
|
||||||
# Type for version symbol information.
|
|
||||||
Elf32_Versym = Elf32_Half
|
|
||||||
Elf64_Versym = Elf64_Half
|
|
||||||
|
|
||||||
# The ELF file header. This appears at the start of every ELF file.
|
|
||||||
|
|
||||||
Elf_IdentT = c_char * EI_NIDENT
|
|
||||||
|
|
||||||
Elf_Cmd = c_int
|
|
||||||
|
|
||||||
class _ElfStructure(Structure):
|
|
||||||
def __str__(self):
|
|
||||||
return self.__class__.__name__ + '(' + \
|
|
||||||
','.join([field[0] + '=' + str(getattr(self, field[0])) for field in self._fields_]) + ')'
|
|
||||||
|
|
||||||
class _ElfUnion(Union):
|
|
||||||
def __str__(self):
|
|
||||||
return self.__class__.__name__ + '(' + \
|
|
||||||
','.join([field[0] + '=' + str(getattr(self, field[0])) for field in self._fields_]) + ')'
|
|
||||||
|
|
||||||
# Libelf opaque handles
|
|
||||||
class Elf(_ElfStructure):
|
|
||||||
_fields_ = []
|
|
||||||
class Elf_Scn(_ElfStructure):
|
|
||||||
_fields_ = []
|
|
||||||
|
|
||||||
class Elf_Data(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('d_buf', c_void_p),
|
|
||||||
('d_type', c_int),
|
|
||||||
('d_size', c_size_t),
|
|
||||||
('d_off', c_size_t),
|
|
||||||
('d_align', c_size_t),
|
|
||||||
('d_version', c_uint)
|
|
||||||
]
|
|
||||||
|
|
||||||
ElfP = POINTER(Elf)
|
|
||||||
Elf_ScnP = POINTER(Elf_Scn)
|
|
||||||
Elf_DataP = POINTER(Elf_Data)
|
|
||||||
|
|
||||||
class Elf32_Ehdr(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('e_ident', Elf_IdentT ), # Magic number and other info
|
|
||||||
('e_type', Elf32_Half ), # Object file type
|
|
||||||
('e_machine', Elf32_Half ), # Architecture
|
|
||||||
('e_version', Elf32_Word ), # Object file version
|
|
||||||
('e_entry', Elf32_Addr ), # Entry point virtual address
|
|
||||||
('e_phoff', Elf32_Off), # Program header table file offset
|
|
||||||
('e_shoff', Elf32_Off), # Section header table file offset
|
|
||||||
('e_flags', Elf32_Word ), # Processor-specific flags
|
|
||||||
('e_ehsize', Elf32_Half ), # ELF header size in bytes
|
|
||||||
('e_phentsize', Elf32_Half ), # Program header table entry size
|
|
||||||
('e_phnum', Elf32_Half ), # Program header table entry count
|
|
||||||
('e_shentsize', Elf32_Half ), # Section header table entry size
|
|
||||||
('e_shnum', Elf32_Half ), # Section header table entry count
|
|
||||||
('e_shstrndx', Elf32_Half ), # Section header string table index
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Ehdr(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('e_ident', Elf_IdentT ), # Magic number and other info
|
|
||||||
('e_type', Elf64_Half ), # Object file type
|
|
||||||
('e_machine', Elf64_Half ), # Architecture
|
|
||||||
('e_version', Elf64_Word ), # Object file version
|
|
||||||
('e_entry', Elf64_Addr ), # Entry point virtual address
|
|
||||||
('e_phoff', Elf64_Off), # Program header table file offset
|
|
||||||
('e_shoff', Elf64_Off), # Section header table file offset
|
|
||||||
('e_flags', Elf64_Word ), # Processor-specific flags
|
|
||||||
('e_ehsize', Elf64_Half ), # ELF header size in bytes
|
|
||||||
('e_phentsize', Elf64_Half ), # Program header table entry size
|
|
||||||
('e_phnum', Elf64_Half ), # Program header table entry count
|
|
||||||
('e_shentsize', Elf64_Half ), # Section header table entry size
|
|
||||||
('e_shnum', Elf64_Half ), # Section header table entry count
|
|
||||||
('e_shstrndx', Elf64_Half ), # Section header string table index
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf32_Shdr(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('sh_name', Elf32_Word), # Section name (string tbl index)
|
|
||||||
('sh_type', Elf32_Word), # Section type
|
|
||||||
('sh_flags', Elf32_Word), # Section flags
|
|
||||||
('sh_addr', Elf32_Addr), # Section virtual addr at execution
|
|
||||||
('sh_offset', Elf32_Off), # Section file offset
|
|
||||||
('sh_size', Elf32_Word), # Section size in bytes
|
|
||||||
('sh_link', Elf32_Word), # Link to another section
|
|
||||||
('sh_info', Elf32_Word), # Additional section information
|
|
||||||
('sh_addralign', Elf32_Word), # Section alignment
|
|
||||||
('sh_entsize', Elf32_Word), # Entry size if section holds table
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Shdr(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('sh_name', Elf64_Word), # Section name (string tbl index)
|
|
||||||
('sh_type', Elf64_Word), # Section type
|
|
||||||
('sh_flags', Elf64_Xword), # Section flags
|
|
||||||
('sh_addr', Elf64_Addr), # Section virtual addr at execution
|
|
||||||
('sh_offset', Elf64_Off), # Section file offset
|
|
||||||
('sh_size', Elf64_Xword), # Section size in bytes
|
|
||||||
('sh_link', Elf64_Word), # Link to another section
|
|
||||||
('sh_info', Elf64_Word), # Additional section information
|
|
||||||
('sh_addralign', Elf64_Xword), # Section alignment
|
|
||||||
('sh_entsize', Elf64_Xword), # Entry size if section holds table
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf32_Phdr(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('p_type', Elf32_Word), # Segment type
|
|
||||||
('p_offset', Elf32_Off), # Segment file offset
|
|
||||||
('p_vaddr', Elf32_Addr), # Segment virtual address
|
|
||||||
('p_paddr', Elf32_Addr), # Segment physical address
|
|
||||||
('p_filesz', Elf32_Word), # Segment size in file
|
|
||||||
('p_memsz', Elf32_Word), # Segment size in memory
|
|
||||||
('p_flags', Elf32_Word), # Segment flags
|
|
||||||
('p_align', Elf32_Word), # Segment alignment
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Phdr(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('p_type', Elf64_Word), # Segment type
|
|
||||||
('p_flags', Elf64_Word), # Segment flags
|
|
||||||
('p_offset', Elf64_Off), # Segment file offset
|
|
||||||
('p_vaddr', Elf64_Addr), # Segment virtual address
|
|
||||||
('p_paddr', Elf64_Addr), # Segment physical address
|
|
||||||
('p_filesz', Elf64_Xword), # Segment size in file
|
|
||||||
('p_memsz', Elf64_Xword), # Segment size in memory
|
|
||||||
('p_align', Elf64_Xword), # Segment alignment
|
|
||||||
]
|
|
||||||
|
|
||||||
# /* Symbol table entry. */
|
|
||||||
class Elf32_Sym(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('st_name', Elf32_Word), # Symbol name (string tbl index)
|
|
||||||
('st_value', Elf32_Addr), # Symbol value
|
|
||||||
('st_size', Elf32_Word), # Symbol size
|
|
||||||
('st_info', c_char), # Symbol type and binding
|
|
||||||
('st_other', c_char), # Symbol visibility
|
|
||||||
('st_shndx', Elf32_Section), # Section index
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Sym(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('st_name', Elf64_Word), # Symbol name (string tbl index)
|
|
||||||
('st_info', c_char), # Symbol type and binding
|
|
||||||
('st_other', c_char), # Symbol visibility
|
|
||||||
('st_shndx', Elf64_Section), # Section index
|
|
||||||
('st_value', Elf64_Addr), # Symbol value
|
|
||||||
('st_size', Elf64_Xword), # Symbol size
|
|
||||||
]
|
|
||||||
|
|
||||||
#/* The syminfo section if available contains additional information about
|
|
||||||
# every dynamic symbol. */
|
|
||||||
|
|
||||||
class Elf32_Syminfo(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('si_boundto', Elf32_Half), # Direct bindings, symbol bound to
|
|
||||||
('si_flags', Elf32_Half), # Per symbol flags
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Syminfo(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('si_boundto', Elf64_Half), # Direct bindings, symbol bound to
|
|
||||||
('si_flags', Elf64_Half), # Per symbol flags
|
|
||||||
]
|
|
||||||
|
|
||||||
# /* Relocation table entry without addend (in section of type SHT_REL). */
|
|
||||||
|
|
||||||
class Elf32_Rel(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('r_offset', Elf32_Addr), # Address
|
|
||||||
('r_info', Elf32_Word), # Relocation type and symbol index
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Rel(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('r_offset', Elf64_Addr), # Address
|
|
||||||
('r_info', Elf64_Xword), # Relocation type and symbol index
|
|
||||||
]
|
|
||||||
|
|
||||||
# # Relocation table entry with addend (in section of type SHT_RELA).
|
|
||||||
|
|
||||||
class Elf32_Rela(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('r_offset', Elf32_Addr), # Address
|
|
||||||
('r_info', Elf32_Word), # Relocation type and symbol index
|
|
||||||
('r_addend', Elf32_Sword), # Addend
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Rela(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('r_offset', Elf64_Addr), # Address
|
|
||||||
('r_info', Elf64_Xword), # Relocation type and symbol index
|
|
||||||
('r_addend', Elf64_Sxword), # Addend
|
|
||||||
]
|
|
||||||
|
|
||||||
time_t = c_int64
|
|
||||||
uid_t = c_int32
|
|
||||||
gid_t = c_int32
|
|
||||||
mode_t = c_int32
|
|
||||||
off_t = c_int64
|
|
||||||
|
|
||||||
class Elf_Arhdr(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('ar_name', c_char_p),
|
|
||||||
('ar_date', time_t),
|
|
||||||
('ar_uid', uid_t),
|
|
||||||
('ar_gid', gid_t),
|
|
||||||
('ar_mode', mode_t),
|
|
||||||
('ar_size', off_t),
|
|
||||||
('ar_fmag', POINTER(c_char)),
|
|
||||||
]
|
|
||||||
|
|
||||||
class _Elf64_DynUnion(_ElfUnion):
|
|
||||||
_fields_ = [
|
|
||||||
('d_val', Elf64_Xword),
|
|
||||||
('d_ptr', Elf64_Addr),
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Dyn(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('d_tag', Elf64_Xword),
|
|
||||||
('d_un', _Elf64_DynUnion),
|
|
||||||
]
|
|
||||||
|
|
||||||
# GNU Extensions
|
|
||||||
class Elf64_Verneed(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('vn_version', Elf64_Half),
|
|
||||||
('vn_cnt', Elf64_Half),
|
|
||||||
('vn_file', Elf64_Word),
|
|
||||||
('vn_aux', Elf64_Word),
|
|
||||||
('vn_next', Elf64_Word),
|
|
||||||
]
|
|
||||||
|
|
||||||
class Elf64_Vernaux(_ElfStructure):
|
|
||||||
_fields_ = [
|
|
||||||
('vna_hash', Elf64_Word),
|
|
||||||
('vna_flags', Elf64_Half),
|
|
||||||
('vna_other', Elf64_Half),
|
|
||||||
('vna_name', Elf64_Word),
|
|
||||||
('vna_next', Elf64_Word),
|
|
||||||
]
|
|
|
@ -1,38 +0,0 @@
|
||||||
from .. import *
|
|
||||||
from ..types import *
|
|
||||||
from ..constants import *
|
|
||||||
from ctypes import *
|
|
||||||
import os
|
|
||||||
|
|
||||||
def _class(elf): return ord(elf_getident(elf, None).contents[EI_CLASS])
|
|
||||||
|
|
||||||
def is32(elf): return _class(elf) == ELFCLASS32
|
|
||||||
def is64(elf): return _class(elf) == ELFCLASS64
|
|
||||||
|
|
||||||
def select(elf, fname):
|
|
||||||
if is32(elf):
|
|
||||||
return globals()['elf32_' + fname]
|
|
||||||
else:
|
|
||||||
return globals()['elf64_' + fname]
|
|
||||||
|
|
||||||
def section_name(elfP, secP):
|
|
||||||
shstrndx = c_size_t()
|
|
||||||
r = elf_getshstrndx(elfP, byref(shstrndx))
|
|
||||||
shdr = select(elfP, 'getshdr')(secP)
|
|
||||||
return elf_strptr(elfP, shstrndx, shdr.contents.sh_name)
|
|
||||||
|
|
||||||
def section_type(elfP, secP):
|
|
||||||
return select(elfP, 'getshdr')(secP).contents.sh_type
|
|
||||||
|
|
||||||
def section_link(elfP, secP):
|
|
||||||
return select(elfP, 'getshdr')(secP).contents.sh_link
|
|
||||||
|
|
||||||
def section_hdr(elfP, secP):
|
|
||||||
return select(elfP, 'getshdr')(secP).contents
|
|
||||||
|
|
||||||
def open_elf(fname):
|
|
||||||
fd = os.open(fname, os.O_RDONLY)
|
|
||||||
return elf_begin(fd, ELF_C_READ, None)
|
|
||||||
|
|
||||||
def sym_name(elf, scn, sym):
|
|
||||||
return elf_strptr(elf, section_link(elf, scn), sym.st_name)
|
|
|
@ -1,58 +0,0 @@
|
||||||
from .. import *
|
|
||||||
from ...types import *
|
|
||||||
from ...iterators import *
|
|
||||||
|
|
||||||
def defined(s): return s.st_shndx != SHN_UNDEF
|
|
||||||
|
|
||||||
def defines(elf, symN):
|
|
||||||
s = findSymbol(elf, symN)
|
|
||||||
print elf, symN, s
|
|
||||||
if s != None:
|
|
||||||
print s.st_shndx, s.st_name
|
|
||||||
return s != None and defined(s[1])
|
|
||||||
|
|
||||||
def derefSymbol(elf, s):
|
|
||||||
assert defined(s)
|
|
||||||
if s.st_shndx == SHN_ABS:
|
|
||||||
raise Exception("NYI")
|
|
||||||
else:
|
|
||||||
scn = elf_getscn(elf, s.st_shndx)
|
|
||||||
shdr = section_hdr(elf, scn);
|
|
||||||
off = 0
|
|
||||||
base = shdr.sh_addr if shdr.sh_addr != 0 else 0
|
|
||||||
start = s.st_value
|
|
||||||
end = s.st_value + s.st_size
|
|
||||||
r = ''
|
|
||||||
for d in data(scn):
|
|
||||||
if start >= end: break;
|
|
||||||
off = base + d.d_off
|
|
||||||
if start >= off and start < off + d.d_size:
|
|
||||||
c = cast(d.d_buf, POINTER(c_char))
|
|
||||||
l = min(off + d.d_size, end) - start
|
|
||||||
r += c[start- off : start - off + l]
|
|
||||||
start += l
|
|
||||||
|
|
||||||
return r
|
|
||||||
|
|
||||||
def derefSymbolFull(elf, s):
|
|
||||||
""" Given an elf file and a Elf{32/64}_Sym defined in the elf file,
|
|
||||||
return a tuple with the contents of memory refered to by the symbol,
|
|
||||||
and any Rel's and Rela's inside that memory.
|
|
||||||
"""
|
|
||||||
assert (defined(s))
|
|
||||||
contents = derefSymbol(elf, s)
|
|
||||||
relL = list(rels(elf, section=s.st_shndx, \
|
|
||||||
range=(s.st_value, s.st_size + s.st_value)))
|
|
||||||
relaL = list(relas(elf, section=s.st_shndx, \
|
|
||||||
range=(s.st_value, s.st_size + s.st_value)))
|
|
||||||
return (contents, relL, relaL)
|
|
||||||
|
|
||||||
# Given a symbol name return the symbol and section in which it occurs
|
|
||||||
def findSymbol(elf, s):
|
|
||||||
for scn in sections(elf, type=SHT_SYMTAB):
|
|
||||||
strndx = section_link(elf, scn)
|
|
||||||
for d in data(scn):
|
|
||||||
for (ind, sym) in syms(elf, d):
|
|
||||||
if s == elf_strptr(elf, strndx, sym.st_name):
|
|
||||||
return (scn, sym)
|
|
||||||
return None
|
|
119
tools/esp_app_trace/sysviewtrace_proc.py
Executable file
119
tools/esp_app_trace/sysviewtrace_proc.py
Executable file
|
@ -0,0 +1,119 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# This is python script to process various types trace data streams in SystemView format.
|
||||||
|
# Trace data can be provided in multiple trace files (one per CPU). After processing phase
|
||||||
|
# script prints report for every type of trace data stream which was found.
|
||||||
|
#
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import os.path
|
||||||
|
import signal
|
||||||
|
import traceback
|
||||||
|
import espytrace.apptrace as apptrace
|
||||||
|
import espytrace.sysview as sysview
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='ESP32 SEGGER SystemView Trace Parsing Tool')
|
||||||
|
|
||||||
|
parser.add_argument('trace_sources', help='Trace data sources. Format: [file://]/path/to/file.', nargs='+', type=str)
|
||||||
|
parser.add_argument('elf_file', help='Path to program ELF file.', type=str)
|
||||||
|
parser.add_argument('--tmo', '-w', help='Data wait timeout in sec. -1: infinite, 0: no wait', type=int, default=0)
|
||||||
|
parser.add_argument('--dump-events', '-d', help='Dump all events.', action='store_true')
|
||||||
|
parser.add_argument('--print-events', '-p', help='Print events of selected types. By default only reports are printed', action='store_true')
|
||||||
|
parser.add_argument('--include-events', '-i', help='Events types to be included into report.', type=str, choices=['heap', 'log', 'all'], default='all')
|
||||||
|
parser.add_argument('--toolchain', '-t', help='Toolchain prefix.', type=str, default='xtensa-esp32-elf-')
|
||||||
|
parser.add_argument('--events-map', '-e', help='Events map file.', type=str, default=os.path.join(os.path.dirname(__file__), 'SYSVIEW_FreeRTOS.txt'))
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
def sig_int_handler(signum, frame):
|
||||||
|
reader.cleanup()
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, sig_int_handler)
|
||||||
|
|
||||||
|
include_events = {'heap': False, 'log': False}
|
||||||
|
if args.include_events == 'all':
|
||||||
|
for k in include_events:
|
||||||
|
include_events[k] = True
|
||||||
|
elif args.include_events == 'heap':
|
||||||
|
include_events['heap'] = True
|
||||||
|
elif args.include_events == 'log':
|
||||||
|
include_events['log'] = True
|
||||||
|
|
||||||
|
# parse trace files
|
||||||
|
parsers = []
|
||||||
|
for i, trace_source in enumerate(args.trace_sources):
|
||||||
|
try:
|
||||||
|
parser = sysview.SysViewMultiTraceDataParser(print_events=False, core_id=i)
|
||||||
|
if include_events['heap']:
|
||||||
|
parser.add_stream_parser(sysview.SysViewTraceDataParser.STREAMID_HEAP,
|
||||||
|
sysview.SysViewHeapTraceDataParser(print_events=False, core_id=i))
|
||||||
|
if include_events['log']:
|
||||||
|
parser.add_stream_parser(sysview.SysViewTraceDataParser.STREAMID_LOG,
|
||||||
|
sysview.SysViewLogTraceDataParser(print_events=False, core_id=i))
|
||||||
|
parsers.append(parser)
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to create data parser ({})!".format(e))
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(2)
|
||||||
|
reader = apptrace.reader_create(trace_source, args.tmo)
|
||||||
|
if not reader:
|
||||||
|
print("Failed to create trace reader!")
|
||||||
|
sys.exit(2)
|
||||||
|
try:
|
||||||
|
print("Parse trace from '{}'...".format(trace_source))
|
||||||
|
sysview.parse_trace(reader, parser, args.events_map)
|
||||||
|
print("Parsing completed.")
|
||||||
|
except (apptrace.ReaderTimeoutError, apptrace.ReaderShutdownRequest) as e:
|
||||||
|
print("Stop parsing trace. ({})".format(e))
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to parse trace ({})!".format(e))
|
||||||
|
parser.cleanup()
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(2)
|
||||||
|
finally:
|
||||||
|
reader.cleanup()
|
||||||
|
|
||||||
|
# merge and process traces
|
||||||
|
try:
|
||||||
|
proc = sysview.SysViewMultiTraceDataProcessor(traces=parsers, print_events=args.dump_events)
|
||||||
|
if include_events['heap']:
|
||||||
|
proc.add_stream_processor(sysview.SysViewTraceDataParser.STREAMID_HEAP,
|
||||||
|
sysview.SysViewHeapTraceDataProcessor(args.toolchain, args.elf_file, print_heap_events=args.print_events))
|
||||||
|
if include_events['log']:
|
||||||
|
proc.add_stream_processor(sysview.SysViewTraceDataParser.STREAMID_LOG,
|
||||||
|
sysview.SysViewLogTraceDataProcessor(print_log_events=args.print_events))
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to create data processor ({})!".format(e))
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(2)
|
||||||
|
try:
|
||||||
|
print("Process events from '{}'...".format(args.trace_sources))
|
||||||
|
proc.merge_and_process()
|
||||||
|
print("Processing completed.")
|
||||||
|
except Exception as e:
|
||||||
|
print("Failed to process trace ({})!".format(e))
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(2)
|
||||||
|
finally:
|
||||||
|
proc.print_report()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
BIN
tools/esp_app_trace/test/logtrace/adc_log.trc
Normal file
BIN
tools/esp_app_trace/test/logtrace/adc_log.trc
Normal file
Binary file not shown.
436
tools/esp_app_trace/test/logtrace/expected_output
Normal file
436
tools/esp_app_trace/test/logtrace/expected_output
Normal file
|
@ -0,0 +1,436 @@
|
||||||
|
Parse trace file 'adc_log.trc'...
|
||||||
|
Unprocessed 7 bytes of log record args!
|
||||||
|
Parsing completed.
|
||||||
|
====================================================================
|
||||||
|
[0;32mI (75854) example: Sample:1, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:2, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:3, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:4, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:5, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:6, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:7, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:8, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:9, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:10, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:11, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:12, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:13, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:14, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:15, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:16, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:17, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:18, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:19, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:20, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:21, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:22, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:23, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:24, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:25, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:26, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:27, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:28, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:29, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:30, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:31, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:32, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:33, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:34, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:35, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:36, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:37, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:38, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:39, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:40, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:41, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:42, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:43, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:44, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:45, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:46, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:47, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:48, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:49, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:50, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:51, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:52, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:53, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:54, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:55, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:56, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:57, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:58, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:59, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:60, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:61, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:62, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:63, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:64, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:65, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:66, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:67, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:68, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:69, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:70, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:71, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:72, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:73, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:74, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:75, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:76, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:77, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:78, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:79, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:80, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:81, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:82, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:83, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:84, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:85, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:86, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:87, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:88, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:89, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:90, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:91, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:92, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:93, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:94, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:95, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:96, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:97, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:98, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:99, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:100, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:101, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:102, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:103, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:104, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:105, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:106, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:107, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:108, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:109, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:110, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:111, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:112, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:113, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:114, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:115, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:116, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:117, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:118, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:119, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:120, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:121, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:122, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:123, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:124, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:125, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:126, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:127, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:128, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:129, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:130, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:131, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:132, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:133, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:134, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:135, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:136, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:137, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:138, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:139, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:140, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:141, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:142, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:143, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:144, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:145, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:146, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:147, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:148, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:149, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:150, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:151, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:152, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:153, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:154, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:155, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:156, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:157, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:158, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:159, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:160, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:161, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:162, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:163, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:164, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:165, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:166, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:167, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:168, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:169, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:170, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:171, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:172, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:173, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:174, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:175, Value:0[0m
|
||||||
|
[0;32mI (75854) example: Sample:176, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:177, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:178, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:179, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:180, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:181, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:182, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:183, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:184, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:185, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:186, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:187, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:188, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:189, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:190, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:191, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:192, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:193, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:194, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:195, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:196, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:197, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:198, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:199, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:200, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:201, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:202, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:203, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:204, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:205, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:206, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:207, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:208, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:209, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:210, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:211, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:212, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:213, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:214, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:215, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:216, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:217, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:218, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:219, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:220, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:221, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:222, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:223, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:224, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:225, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:226, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:227, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:228, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:229, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:230, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:231, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:232, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:233, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:234, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:235, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:236, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:237, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:238, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:239, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:240, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:241, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:242, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:243, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:244, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:245, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:246, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:247, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:248, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:249, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:250, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:251, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:252, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:253, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:254, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:255, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:256, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:257, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:258, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:259, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:260, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:261, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:262, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:263, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:264, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:265, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:266, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:267, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:268, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:269, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:270, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:271, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:272, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:273, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:274, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:275, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:276, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:277, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:278, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:279, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:280, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:281, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:282, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:283, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:284, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:285, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:286, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:287, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:288, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:289, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:290, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:291, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:292, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:293, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:294, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:295, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:296, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:297, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:298, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:299, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:300, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:301, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:302, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:303, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:304, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:305, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:306, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:307, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:308, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:309, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:310, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:311, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:312, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:313, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:314, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:315, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:316, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:317, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:318, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:319, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:320, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:321, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:322, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:323, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:324, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:325, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:326, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:327, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:328, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:329, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:330, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:331, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:332, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:333, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:334, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:335, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:336, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:337, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:338, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:339, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:340, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:341, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:342, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:343, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:344, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:345, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:346, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:347, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:348, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:349, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:350, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:351, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:352, Value:0[0m
|
||||||
|
[0;32mI (75864) example: Sample:353, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:1, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:2, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:3, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:4, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:5, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:6, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:7, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:8, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:9, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:10, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:11, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:12, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:13, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:14, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:15, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:16, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:17, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:18, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:19, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:20, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:21, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:22, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:23, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:24, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:25, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:26, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:27, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:28, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:29, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:30, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:31, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:32, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:33, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:34, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:35, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:36, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:37, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:38, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:39, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:40, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:41, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:42, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:43, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:44, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:45, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:46, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:47, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:48, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:49, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:50, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:51, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:52, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:53, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:54, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:55, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:56, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:57, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:58, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:59, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:60, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:61, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:62, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:63, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:64, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:65, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:66, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:67, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:68, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:69, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:70, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:71, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:72, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:73, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:74, Value:0[0m
|
||||||
|
[0;32mI (77894) example: Sample:75, Value:0[0m
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
Log records count: 428
|
BIN
tools/esp_app_trace/test/logtrace/test.elf
Normal file
BIN
tools/esp_app_trace/test/logtrace/test.elf
Normal file
Binary file not shown.
8
tools/esp_app_trace/test/logtrace/test.sh
Executable file
8
tools/esp_app_trace/test/logtrace/test.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
{ coverage debug sys \
|
||||||
|
&& coverage erase &> output \
|
||||||
|
&& coverage run -a $IDF_PATH/tools/esp_app_trace/logtrace_proc.py adc_log.trc test.elf &>> output \
|
||||||
|
&& diff output expected_output \
|
||||||
|
&& coverage report \
|
||||||
|
; } || { echo 'The test for logtrace_proc has failed. Please examine the artifacts.' ; exit 1; }
|
88
tools/esp_app_trace/test/sysview/blink.c
Normal file
88
tools/esp_app_trace/test/sysview/blink.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/* Blink Example
|
||||||
|
|
||||||
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, this
|
||||||
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_heap_trace.h"
|
||||||
|
|
||||||
|
/* Can run 'make menuconfig' to choose the GPIO to blink,
|
||||||
|
or you can edit the following line and set a number here.
|
||||||
|
*/
|
||||||
|
#define BLINK_GPIO CONFIG_BLINK_GPIO
|
||||||
|
|
||||||
|
void blink_task2(void *pvParameter)
|
||||||
|
{
|
||||||
|
TaskHandle_t task = (TaskHandle_t)pvParameter;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
if (xTaskNotifyWait(0, 0, NULL, portMAX_DELAY) != pdPASS) {
|
||||||
|
printf("Failed to wait for main task!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void *a = malloc(65);
|
||||||
|
printf("Alloced 65 bytes @ %p\n", a);
|
||||||
|
void *b = malloc(97);
|
||||||
|
printf("Alloced 97 bytes @ %p\n", b);
|
||||||
|
free(a);
|
||||||
|
printf("Freed @ %p\n", a);
|
||||||
|
b = malloc(11);
|
||||||
|
printf("Alloced 11 bytes @ %p\n", b);
|
||||||
|
b = malloc(24);
|
||||||
|
printf("Alloced 24 bytes @ %p\n", b);
|
||||||
|
free(b);
|
||||||
|
printf("Freed @ %p\n", b);
|
||||||
|
if (xTaskNotify(task, 0, eNoAction) != pdPASS) {
|
||||||
|
printf("Failed to notify main task!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void blink_task(void *pvParameter)
|
||||||
|
{
|
||||||
|
TaskHandle_t task = 0;
|
||||||
|
|
||||||
|
if(heap_trace_init_tohost() != ESP_OK) {
|
||||||
|
printf("Failed to init heap trace!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xTaskCreatePinnedToCore(&blink_task2, "blink_task2", 2048, xTaskGetCurrentTaskHandle(), 5, &task, 1);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
heap_trace_start(HEAP_TRACE_ALL);
|
||||||
|
if (xTaskNotify(task, 0, eNoAction) != pdPASS) {
|
||||||
|
printf("Failed to notify slave task!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void *a = malloc(64);
|
||||||
|
printf("Alloced 64 bytes @ %p\n", a);
|
||||||
|
void *b = malloc(96);
|
||||||
|
printf("Alloced 96 bytes @ %p\n", b);
|
||||||
|
free(a);
|
||||||
|
printf("Freed @ %p\n", a);
|
||||||
|
b = malloc(10);
|
||||||
|
printf("Alloced 10 bytes @ %p\n", b);
|
||||||
|
b = malloc(23);
|
||||||
|
printf("Alloced 23 bytes @ %p\n", b);
|
||||||
|
free(b);
|
||||||
|
printf("Freed @ %p\n", b);
|
||||||
|
if (xTaskNotifyWait(0, 0, NULL, portMAX_DELAY) != pdPASS) {
|
||||||
|
printf("Failed to wait for slave task!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
heap_trace_stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main()
|
||||||
|
{
|
||||||
|
xTaskCreatePinnedToCore(&blink_task, "blink_task", 2048, NULL, 5, NULL, 0);
|
||||||
|
}
|
BIN
tools/esp_app_trace/test/sysview/cpu0.svdat
Normal file
BIN
tools/esp_app_trace/test/sysview/cpu0.svdat
Normal file
Binary file not shown.
BIN
tools/esp_app_trace/test/sysview/cpu1.svdat
Normal file
BIN
tools/esp_app_trace/test/sysview/cpu1.svdat
Normal file
Binary file not shown.
450
tools/esp_app_trace/test/sysview/expected_output
Normal file
450
tools/esp_app_trace/test/sysview/expected_output
Normal file
|
@ -0,0 +1,450 @@
|
||||||
|
Parse trace from 'cpu0.svdat'...
|
||||||
|
Stop parsing trace. (Timeout 0.000000 sec while reading 1 bytes!)
|
||||||
|
Parse trace from 'cpu1.svdat'...
|
||||||
|
Stop parsing trace. (Timeout 0.000000 sec while reading 1 bytes!)
|
||||||
|
Process events from '['cpu0.svdat', 'cpu1.svdat']'...
|
||||||
|
EVENT[0]: 0.000000000 - core[0].svTraceStart(10), plen 0: []
|
||||||
|
EVENT[1]: 0.000000000 - core[1].svTraceStart(10), plen 0: []
|
||||||
|
EVENT[2]: 0.000010950 - core[0].svInit(24), plen 14: [sys_freq: 40000000, cpu_freq: 160000000, ram_base: 1061158912, id_shift: 0]
|
||||||
|
EVENT[3]: 0.000010950 - core[1].svInit(24), plen 14: [sys_freq: 40000000, cpu_freq: 160000000, ram_base: 1061158912, id_shift: 0]
|
||||||
|
EVENT[4]: 0.000024800 - core[0].svSysDesc(14), plen 0: [desc: N=FreeRTOS Application,D=ESP32,C=Xtensa,O=FreeRTOS]
|
||||||
|
EVENT[5]: 0.000024800 - core[1].svSysDesc(14), plen 0: [desc: N=FreeRTOS Application,D=ESP32,C=Xtensa,O=FreeRTOS]
|
||||||
|
EVENT[6]: 0.000051650 - core[0].svSysDesc(14), plen 0: [desc: I#5=SysTick]
|
||||||
|
EVENT[7]: 0.000051650 - core[1].svSysDesc(14), plen 0: [desc: I#5=SysTick]
|
||||||
|
EVENT[8]: 0.000104150 - core[0].svSysDesc(14), plen 0: [desc: I#6=WIFI_MAC]
|
||||||
|
EVENT[9]: 0.000104150 - core[1].svSysDesc(14), plen 0: [desc: I#6=WIFI_MAC]
|
||||||
|
EVENT[10]: 0.000121100 - core[0].svSysDesc(14), plen 0: [desc: I#7=WIFI_NMI]
|
||||||
|
EVENT[11]: 0.000121100 - core[1].svSysDesc(14), plen 0: [desc: I#7=WIFI_NMI]
|
||||||
|
EVENT[12]: 0.000138125 - core[0].svSysDesc(14), plen 0: [desc: I#8=WIFI_BB]
|
||||||
|
EVENT[13]: 0.000138125 - core[1].svSysDesc(14), plen 0: [desc: I#8=WIFI_BB]
|
||||||
|
EVENT[14]: 0.000154825 - core[0].svSysDesc(14), plen 0: [desc: I#9=BT_MAC]
|
||||||
|
EVENT[15]: 0.000154825 - core[1].svSysDesc(14), plen 0: [desc: I#9=BT_MAC]
|
||||||
|
EVENT[16]: 0.000193350 - core[0].svSysDesc(14), plen 0: [desc: I#10=BT_BB]
|
||||||
|
EVENT[17]: 0.000193350 - core[1].svSysDesc(14), plen 0: [desc: I#10=BT_BB]
|
||||||
|
EVENT[18]: 0.000212875 - core[0].svSysDesc(14), plen 0: [desc: I#11=BT_BB_NMI]
|
||||||
|
EVENT[19]: 0.000212875 - core[1].svSysDesc(14), plen 0: [desc: I#11=BT_BB_NMI]
|
||||||
|
EVENT[20]: 0.000231625 - core[0].svSysDesc(14), plen 0: [desc: I#12=RWBT]
|
||||||
|
EVENT[21]: 0.000231625 - core[1].svSysDesc(14), plen 0: [desc: I#12=RWBT]
|
||||||
|
EVENT[22]: 0.000250250 - core[0].svSysDesc(14), plen 0: [desc: I#13=RWBLE]
|
||||||
|
EVENT[23]: 0.000250250 - core[1].svSysDesc(14), plen 0: [desc: I#13=RWBLE]
|
||||||
|
EVENT[24]: 0.000269450 - core[0].svSysDesc(14), plen 0: [desc: I#14=RWBT_NMI]
|
||||||
|
EVENT[25]: 0.000269450 - core[1].svSysDesc(14), plen 0: [desc: I#14=RWBT_NMI]
|
||||||
|
EVENT[26]: 0.000288925 - core[0].svSysDesc(14), plen 0: [desc: I#15=RWBLE_NMI]
|
||||||
|
EVENT[27]: 0.000288925 - core[1].svSysDesc(14), plen 0: [desc: I#15=RWBLE_NMI]
|
||||||
|
EVENT[28]: 0.000310575 - core[0].svSysDesc(14), plen 0: [desc: I#16=SLC0]
|
||||||
|
EVENT[29]: 0.000310575 - core[1].svSysDesc(14), plen 0: [desc: I#16=SLC0]
|
||||||
|
EVENT[30]: 0.000329150 - core[0].svSysDesc(14), plen 0: [desc: I#17=SLC1]
|
||||||
|
EVENT[31]: 0.000329150 - core[1].svSysDesc(14), plen 0: [desc: I#17=SLC1]
|
||||||
|
EVENT[32]: 0.000347675 - core[0].svSysDesc(14), plen 0: [desc: I#18=UHCI0]
|
||||||
|
EVENT[33]: 0.000347675 - core[1].svSysDesc(14), plen 0: [desc: I#18=UHCI0]
|
||||||
|
EVENT[34]: 0.000366225 - core[0].svSysDesc(14), plen 0: [desc: I#19=UHCI1]
|
||||||
|
EVENT[35]: 0.000366225 - core[1].svSysDesc(14), plen 0: [desc: I#19=UHCI1]
|
||||||
|
EVENT[36]: 0.000386350 - core[0].svSysDesc(14), plen 0: [desc: I#20=TG0_T0_LEVEL]
|
||||||
|
EVENT[37]: 0.000386350 - core[1].svSysDesc(14), plen 0: [desc: I#20=TG0_T0_LEVEL]
|
||||||
|
EVENT[38]: 0.000406575 - core[0].svSysDesc(14), plen 0: [desc: I#21=TG0_T1_LEVEL]
|
||||||
|
EVENT[39]: 0.000406575 - core[1].svSysDesc(14), plen 0: [desc: I#21=TG0_T1_LEVEL]
|
||||||
|
EVENT[40]: 0.000427300 - core[0].svSysDesc(14), plen 0: [desc: I#22=TG0_WDT_LEVEL]
|
||||||
|
EVENT[41]: 0.000427300 - core[1].svSysDesc(14), plen 0: [desc: I#22=TG0_WDT_LEVEL]
|
||||||
|
EVENT[42]: 0.000448000 - core[0].svSysDesc(14), plen 0: [desc: I#23=TG0_LACT_LEVEL]
|
||||||
|
EVENT[43]: 0.000448000 - core[1].svSysDesc(14), plen 0: [desc: I#23=TG0_LACT_LEVEL]
|
||||||
|
EVENT[44]: 0.000468250 - core[0].svSysDesc(14), plen 0: [desc: I#24=TG1_T0_LEVEL]
|
||||||
|
EVENT[45]: 0.000468250 - core[1].svSysDesc(14), plen 0: [desc: I#24=TG1_T0_LEVEL]
|
||||||
|
EVENT[46]: 0.000488500 - core[0].svSysDesc(14), plen 0: [desc: I#25=TG1_T1_LEVEL]
|
||||||
|
EVENT[47]: 0.000488500 - core[1].svSysDesc(14), plen 0: [desc: I#25=TG1_T1_LEVEL]
|
||||||
|
EVENT[48]: 0.000508975 - core[0].svSysDesc(14), plen 0: [desc: I#26=TG1_WDT_LEVEL]
|
||||||
|
EVENT[49]: 0.000508975 - core[1].svSysDesc(14), plen 0: [desc: I#26=TG1_WDT_LEVEL]
|
||||||
|
EVENT[50]: 0.000529850 - core[0].svSysDesc(14), plen 0: [desc: I#27=TG1_LACT_LEVEL]
|
||||||
|
EVENT[51]: 0.000529850 - core[1].svSysDesc(14), plen 0: [desc: I#27=TG1_LACT_LEVEL]
|
||||||
|
EVENT[52]: 0.000548375 - core[0].svSysDesc(14), plen 0: [desc: I#28=GPIO]
|
||||||
|
EVENT[53]: 0.000548375 - core[1].svSysDesc(14), plen 0: [desc: I#28=GPIO]
|
||||||
|
EVENT[54]: 0.000570825 - core[0].svSysDesc(14), plen 0: [desc: I#29=GPIO_NMI]
|
||||||
|
EVENT[55]: 0.000570825 - core[1].svSysDesc(14), plen 0: [desc: I#29=GPIO_NMI]
|
||||||
|
EVENT[56]: 0.000590425 - core[0].svSysDesc(14), plen 0: [desc: I#30=FROM_CPU0]
|
||||||
|
EVENT[57]: 0.000590425 - core[1].svSysDesc(14), plen 0: [desc: I#30=FROM_CPU0]
|
||||||
|
EVENT[58]: 0.000610000 - core[0].svSysDesc(14), plen 0: [desc: I#31=FROM_CPU1]
|
||||||
|
EVENT[59]: 0.000610000 - core[1].svSysDesc(14), plen 0: [desc: I#31=FROM_CPU1]
|
||||||
|
EVENT[60]: 0.000629625 - core[0].svSysDesc(14), plen 0: [desc: I#32=FROM_CPU2]
|
||||||
|
EVENT[61]: 0.000629625 - core[1].svSysDesc(14), plen 0: [desc: I#32=FROM_CPU2]
|
||||||
|
EVENT[62]: 0.000649425 - core[0].svSysDesc(14), plen 0: [desc: I#33=FROM_CPU3]
|
||||||
|
EVENT[63]: 0.000649425 - core[1].svSysDesc(14), plen 0: [desc: I#33=FROM_CPU3]
|
||||||
|
EVENT[64]: 0.000667975 - core[0].svSysDesc(14), plen 0: [desc: I#34=SPI0]
|
||||||
|
EVENT[65]: 0.000667975 - core[1].svSysDesc(14), plen 0: [desc: I#34=SPI0]
|
||||||
|
EVENT[66]: 0.000686500 - core[0].svSysDesc(14), plen 0: [desc: I#35=SPI1]
|
||||||
|
EVENT[67]: 0.000686500 - core[1].svSysDesc(14), plen 0: [desc: I#35=SPI1]
|
||||||
|
EVENT[68]: 0.000704825 - core[0].svSysDesc(14), plen 0: [desc: I#36=SPI2]
|
||||||
|
EVENT[69]: 0.000704825 - core[1].svSysDesc(14), plen 0: [desc: I#36=SPI2]
|
||||||
|
EVENT[70]: 0.000723100 - core[0].svSysDesc(14), plen 0: [desc: I#37=SPI3]
|
||||||
|
EVENT[71]: 0.000723100 - core[1].svSysDesc(14), plen 0: [desc: I#37=SPI3]
|
||||||
|
EVENT[72]: 0.000741550 - core[0].svSysDesc(14), plen 0: [desc: I#38=I2S0]
|
||||||
|
EVENT[73]: 0.000741550 - core[1].svSysDesc(14), plen 0: [desc: I#38=I2S0]
|
||||||
|
EVENT[74]: 0.000760000 - core[0].svSysDesc(14), plen 0: [desc: I#39=I2S1]
|
||||||
|
EVENT[75]: 0.000760000 - core[1].svSysDesc(14), plen 0: [desc: I#39=I2S1]
|
||||||
|
EVENT[76]: 0.000778475 - core[0].svSysDesc(14), plen 0: [desc: I#40=UART0]
|
||||||
|
EVENT[77]: 0.000778475 - core[1].svSysDesc(14), plen 0: [desc: I#40=UART0]
|
||||||
|
EVENT[78]: 0.000797050 - core[0].svSysDesc(14), plen 0: [desc: I#41=UART1]
|
||||||
|
EVENT[79]: 0.000797050 - core[1].svSysDesc(14), plen 0: [desc: I#41=UART1]
|
||||||
|
EVENT[80]: 0.000815625 - core[0].svSysDesc(14), plen 0: [desc: I#42=UART2]
|
||||||
|
EVENT[81]: 0.000815625 - core[1].svSysDesc(14), plen 0: [desc: I#42=UART2]
|
||||||
|
EVENT[82]: 0.000835000 - core[0].svSysDesc(14), plen 0: [desc: I#43=SDIO_HOST]
|
||||||
|
EVENT[83]: 0.000835000 - core[1].svSysDesc(14), plen 0: [desc: I#43=SDIO_HOST]
|
||||||
|
EVENT[84]: 0.000854075 - core[0].svSysDesc(14), plen 0: [desc: I#44=ETH_MAC]
|
||||||
|
EVENT[85]: 0.000854075 - core[1].svSysDesc(14), plen 0: [desc: I#44=ETH_MAC]
|
||||||
|
EVENT[86]: 0.000875600 - core[0].svSysDesc(14), plen 0: [desc: I#45=PWM0]
|
||||||
|
EVENT[87]: 0.000875600 - core[1].svSysDesc(14), plen 0: [desc: I#45=PWM0]
|
||||||
|
EVENT[88]: 0.000893850 - core[0].svSysDesc(14), plen 0: [desc: I#46=PWM1]
|
||||||
|
EVENT[89]: 0.000893850 - core[1].svSysDesc(14), plen 0: [desc: I#46=PWM1]
|
||||||
|
EVENT[90]: 0.000912375 - core[0].svSysDesc(14), plen 0: [desc: I#47=PWM2]
|
||||||
|
EVENT[91]: 0.000912375 - core[1].svSysDesc(14), plen 0: [desc: I#47=PWM2]
|
||||||
|
EVENT[92]: 0.000930950 - core[0].svSysDesc(14), plen 0: [desc: I#48=PWM3]
|
||||||
|
EVENT[93]: 0.000930950 - core[1].svSysDesc(14), plen 0: [desc: I#48=PWM3]
|
||||||
|
EVENT[94]: 0.000949375 - core[0].svSysDesc(14), plen 0: [desc: I#49=LEDC]
|
||||||
|
EVENT[95]: 0.000949375 - core[1].svSysDesc(14), plen 0: [desc: I#49=LEDC]
|
||||||
|
EVENT[96]: 0.000968075 - core[0].svSysDesc(14), plen 0: [desc: I#50=EFUSE]
|
||||||
|
EVENT[97]: 0.000968075 - core[1].svSysDesc(14), plen 0: [desc: I#50=EFUSE]
|
||||||
|
EVENT[98]: 0.000986275 - core[0].svSysDesc(14), plen 0: [desc: I#51=CAN]
|
||||||
|
EVENT[99]: 0.000986275 - core[1].svSysDesc(14), plen 0: [desc: I#51=CAN]
|
||||||
|
EVENT[100]: 0.001005625 - core[0].svSysDesc(14), plen 0: [desc: I#52=RTC_CORE]
|
||||||
|
EVENT[101]: 0.001005625 - core[1].svSysDesc(14), plen 0: [desc: I#52=RTC_CORE]
|
||||||
|
EVENT[102]: 0.001023700 - core[0].svSysDesc(14), plen 0: [desc: I#53=RMT]
|
||||||
|
EVENT[103]: 0.001023700 - core[1].svSysDesc(14), plen 0: [desc: I#53=RMT]
|
||||||
|
EVENT[104]: 0.001042050 - core[0].svSysDesc(14), plen 0: [desc: I#54=PCNT]
|
||||||
|
EVENT[105]: 0.001042050 - core[1].svSysDesc(14), plen 0: [desc: I#54=PCNT]
|
||||||
|
EVENT[106]: 0.001061500 - core[0].svSysDesc(14), plen 0: [desc: I#55=I2C_EXT0]
|
||||||
|
EVENT[107]: 0.001061500 - core[1].svSysDesc(14), plen 0: [desc: I#55=I2C_EXT0]
|
||||||
|
EVENT[108]: 0.001081100 - core[0].svSysDesc(14), plen 0: [desc: I#56=I2C_EXT1]
|
||||||
|
EVENT[109]: 0.001081100 - core[1].svSysDesc(14), plen 0: [desc: I#56=I2C_EXT1]
|
||||||
|
EVENT[110]: 0.001099425 - core[0].svSysDesc(14), plen 0: [desc: I#57=RSA]
|
||||||
|
EVENT[111]: 0.001099425 - core[1].svSysDesc(14), plen 0: [desc: I#57=RSA]
|
||||||
|
EVENT[112]: 0.001118625 - core[0].svSysDesc(14), plen 0: [desc: I#58=SPI1_DMA]
|
||||||
|
EVENT[113]: 0.001118625 - core[1].svSysDesc(14), plen 0: [desc: I#58=SPI1_DMA]
|
||||||
|
EVENT[114]: 0.001137775 - core[0].svSysDesc(14), plen 0: [desc: I#59=SPI2_DMA]
|
||||||
|
EVENT[115]: 0.001137775 - core[1].svSysDesc(14), plen 0: [desc: I#59=SPI2_DMA]
|
||||||
|
EVENT[116]: 0.001156950 - core[0].svSysDesc(14), plen 0: [desc: I#60=SPI3_DMA]
|
||||||
|
EVENT[117]: 0.001156950 - core[1].svSysDesc(14), plen 0: [desc: I#60=SPI3_DMA]
|
||||||
|
EVENT[118]: 0.001175175 - core[0].svSysDesc(14), plen 0: [desc: I#61=WDT]
|
||||||
|
EVENT[119]: 0.001175175 - core[1].svSysDesc(14), plen 0: [desc: I#61=WDT]
|
||||||
|
EVENT[120]: 0.001197300 - core[0].svSysDesc(14), plen 0: [desc: I#62=TIMER1]
|
||||||
|
EVENT[121]: 0.001197300 - core[1].svSysDesc(14), plen 0: [desc: I#62=TIMER1]
|
||||||
|
EVENT[122]: 0.001216250 - core[0].svSysDesc(14), plen 0: [desc: I#63=TIMER2]
|
||||||
|
EVENT[123]: 0.001216250 - core[1].svSysDesc(14), plen 0: [desc: I#63=TIMER2]
|
||||||
|
EVENT[124]: 0.001236175 - core[0].svSysDesc(14), plen 0: [desc: I#64=TG0_T0_EDGE]
|
||||||
|
EVENT[125]: 0.001236175 - core[1].svSysDesc(14), plen 0: [desc: I#64=TG0_T0_EDGE]
|
||||||
|
EVENT[126]: 0.001256275 - core[0].svSysDesc(14), plen 0: [desc: I#65=TG0_T1_EDGE]
|
||||||
|
EVENT[127]: 0.001256275 - core[1].svSysDesc(14), plen 0: [desc: I#65=TG0_T1_EDGE]
|
||||||
|
EVENT[128]: 0.001276675 - core[0].svSysDesc(14), plen 0: [desc: I#66=TG0_WDT_EDGE]
|
||||||
|
EVENT[129]: 0.001276675 - core[1].svSysDesc(14), plen 0: [desc: I#66=TG0_WDT_EDGE]
|
||||||
|
EVENT[130]: 0.001297375 - core[0].svSysDesc(14), plen 0: [desc: I#67=TG0_LACT_EDGE]
|
||||||
|
EVENT[131]: 0.001297375 - core[1].svSysDesc(14), plen 0: [desc: I#67=TG0_LACT_EDGE]
|
||||||
|
EVENT[132]: 0.001317425 - core[0].svSysDesc(14), plen 0: [desc: I#68=TG1_T0_EDGE]
|
||||||
|
EVENT[133]: 0.001317425 - core[1].svSysDesc(14), plen 0: [desc: I#68=TG1_T0_EDGE]
|
||||||
|
EVENT[134]: 0.001337650 - core[0].svSysDesc(14), plen 0: [desc: I#69=TG1_T1_EDGE]
|
||||||
|
EVENT[135]: 0.001337650 - core[1].svSysDesc(14), plen 0: [desc: I#69=TG1_T1_EDGE]
|
||||||
|
EVENT[136]: 0.001357950 - core[0].svSysDesc(14), plen 0: [desc: I#70=TG1_WDT_EDGE]
|
||||||
|
EVENT[137]: 0.001357950 - core[1].svSysDesc(14), plen 0: [desc: I#70=TG1_WDT_EDGE]
|
||||||
|
EVENT[138]: 0.001378625 - core[0].svSysDesc(14), plen 0: [desc: I#71=TG1_LACT_EDGE]
|
||||||
|
EVENT[139]: 0.001378625 - core[1].svSysDesc(14), plen 0: [desc: I#71=TG1_LACT_EDGE]
|
||||||
|
EVENT[140]: 0.001397500 - core[0].svSysDesc(14), plen 0: [desc: I#72=MMU_IA]
|
||||||
|
EVENT[141]: 0.001397500 - core[1].svSysDesc(14), plen 0: [desc: I#72=MMU_IA]
|
||||||
|
EVENT[142]: 0.001416425 - core[0].svSysDesc(14), plen 0: [desc: I#73=MPU_IA]
|
||||||
|
EVENT[143]: 0.001416425 - core[1].svSysDesc(14), plen 0: [desc: I#73=MPU_IA]
|
||||||
|
EVENT[144]: 0.001435550 - core[0].svSysDesc(14), plen 0: [desc: I#74=CACHE_IA]
|
||||||
|
EVENT[145]: 0.001435550 - core[1].svSysDesc(14), plen 0: [desc: I#74=CACHE_IA]
|
||||||
|
EVENT[146]: 0.001441950 - core[0].svSysTimeUs(13), plen 0: [time: 10000]
|
||||||
|
EVENT[147]: 0.001441950 - core[1].svSysTimeUs(13), plen 0: [time: 10000]
|
||||||
|
EVENT[148]: 0.001647400 - core[0].svTaskInfo(9), plen 0: [tid: 12253880, prio: 22, name: esp_timer]
|
||||||
|
EVENT[149]: 0.001647400 - core[1].svTaskInfo(9), plen 0: [tid: 12253880, prio: 22, name: esp_timer]
|
||||||
|
EVENT[150]: 0.001652000 - core[0].svStackInfo(21), plen 0: [tid: 12253880, base: 1073408692, sz: 3436, unused: 0]
|
||||||
|
EVENT[151]: 0.001652000 - core[1].svStackInfo(21), plen 0: [tid: 12253880, base: 1073408692, sz: 3436, unused: 0]
|
||||||
|
EVENT[152]: 0.001738550 - core[0].svTaskInfo(9), plen 0: [tid: 12254636, prio: 24, name: ipc0]
|
||||||
|
EVENT[153]: 0.001738550 - core[1].svTaskInfo(9), plen 0: [tid: 12254636, prio: 24, name: ipc0]
|
||||||
|
EVENT[154]: 0.001742750 - core[0].svStackInfo(21), plen 0: [tid: 12254636, base: 1073430180, sz: 1388, unused: 0]
|
||||||
|
EVENT[155]: 0.001742750 - core[1].svStackInfo(21), plen 0: [tid: 12254636, base: 1073430180, sz: 1388, unused: 0]
|
||||||
|
EVENT[156]: 0.001828975 - core[0].svTaskInfo(9), plen 0: [tid: 12275372, prio: 24, name: ipc1]
|
||||||
|
EVENT[157]: 0.001828975 - core[1].svTaskInfo(9), plen 0: [tid: 12275372, prio: 24, name: ipc1]
|
||||||
|
EVENT[158]: 0.001833225 - core[0].svStackInfo(21), plen 0: [tid: 12275372, base: 1073432232, sz: 1384, unused: 0]
|
||||||
|
EVENT[159]: 0.001833225 - core[1].svStackInfo(21), plen 0: [tid: 12275372, base: 1073432232, sz: 1384, unused: 0]
|
||||||
|
EVENT[160]: 0.001871225 - core[0].svTaskInfo(9), plen 0: [tid: 12291908, prio: 5, name: blink_task]
|
||||||
|
EVENT[161]: 0.001871225 - core[1].svTaskInfo(9), plen 0: [tid: 12291908, prio: 5, name: blink_task]
|
||||||
|
EVENT[162]: 0.001875650 - core[0].svStackInfo(21), plen 0: [tid: 12291908, base: 1073448452, sz: 524, unused: 0]
|
||||||
|
EVENT[163]: 0.001875650 - core[1].svStackInfo(21), plen 0: [tid: 12291908, base: 1073448452, sz: 524, unused: 0]
|
||||||
|
EVENT[164]: 0.002070800 - core[0].svTaskInfo(9), plen 0: [tid: 12282660, prio: 1, name: main]
|
||||||
|
EVENT[165]: 0.002070800 - core[1].svTaskInfo(9), plen 0: [tid: 12282660, prio: 1, name: main]
|
||||||
|
EVENT[166]: 0.002075200 - core[0].svStackInfo(21), plen 0: [tid: 12282660, base: 1073437472, sz: 3296, unused: 0]
|
||||||
|
EVENT[167]: 0.002075200 - core[1].svStackInfo(21), plen 0: [tid: 12282660, base: 1073437472, sz: 3296, unused: 0]
|
||||||
|
EVENT[168]: 0.002153375 - core[0].svTaskInfo(9), plen 0: [tid: 12284560, prio: 0, name: IDLE0]
|
||||||
|
EVENT[169]: 0.002153375 - core[1].svTaskInfo(9), plen 0: [tid: 12284560, prio: 0, name: IDLE0]
|
||||||
|
EVENT[170]: 0.002157850 - core[0].svStackInfo(21), plen 0: [tid: 12284560, base: 1073441932, sz: 1236, unused: 0]
|
||||||
|
EVENT[171]: 0.002157850 - core[1].svStackInfo(21), plen 0: [tid: 12284560, base: 1073441932, sz: 1236, unused: 0]
|
||||||
|
EVENT[172]: 0.002228950 - core[0].svTaskInfo(9), plen 0: [tid: 12286460, prio: 0, name: IDLE1]
|
||||||
|
EVENT[173]: 0.002228950 - core[1].svTaskInfo(9), plen 0: [tid: 12286460, prio: 0, name: IDLE1]
|
||||||
|
EVENT[174]: 0.002233250 - core[0].svStackInfo(21), plen 0: [tid: 12286460, base: 1073443832, sz: 1112, unused: 0]
|
||||||
|
EVENT[175]: 0.002233250 - core[1].svStackInfo(21), plen 0: [tid: 12286460, base: 1073443832, sz: 1112, unused: 0]
|
||||||
|
EVENT[176]: 0.002319675 - core[0].svTaskInfo(9), plen 0: [tid: 12289116, prio: 1, name: Tmr Svc]
|
||||||
|
EVENT[177]: 0.002319675 - core[1].svTaskInfo(9), plen 0: [tid: 12289116, prio: 1, name: Tmr Svc]
|
||||||
|
EVENT[178]: 0.002324100 - core[0].svStackInfo(21), plen 0: [tid: 12289116, base: 1073445976, sz: 1384, unused: 0]
|
||||||
|
EVENT[179]: 0.002324100 - core[1].svStackInfo(21), plen 0: [tid: 12289116, base: 1073445976, sz: 1384, unused: 0]
|
||||||
|
EVENT[180]: 0.002431200 - core[0].svTaskInfo(9), plen 0: [tid: 12294320, prio: 5, name: blink_task2]
|
||||||
|
EVENT[181]: 0.002431200 - core[1].svTaskInfo(9), plen 0: [tid: 12294320, prio: 5, name: blink_task2]
|
||||||
|
EVENT[182]: 0.002438750 - core[0].svStackInfo(21), plen 0: [tid: 12294320, base: 1073451180, sz: 1748, unused: 0]
|
||||||
|
EVENT[183]: 0.002438750 - core[1].svStackInfo(21), plen 0: [tid: 12294320, base: 1073451180, sz: 1748, unused: 0]
|
||||||
|
EVENT[184]: 0.002446150 - core[0].svNumModules(27), plen 1: [mod_cnt: 0]
|
||||||
|
EVENT[185]: 0.002446150 - core[1].svNumModules(27), plen 1: [mod_cnt: 0]
|
||||||
|
EVENT[186]: 0.002484225 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[187]: 0.002496125 - core[0].svTaskStopReady(7), plen 0: [tid: 12291908, cause: 4]
|
||||||
|
EVENT[188]: 0.002508025 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[189]: 0.002516350 - core[0].svIsrEnter(2), plen 0: [irq_num: 30]
|
||||||
|
EVENT[190]: 0.002524325 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[191]: 0.002532350 - core[0].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[192]: 0.002541200 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[193]: 0.002548475 - core[0].svTaskStartExec(4), plen 0: [tid: 12282660]
|
||||||
|
EVENT[194]: 0.002556375 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[195]: 0.002564450 - core[0].vTaskDelete(33), plen 4: [xTaskToDelete: 12282660]
|
||||||
|
EVENT[196]: 0.002577700 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[197]: 0.002585225 - core[0].svIsrEnter(2), plen 0: [irq_num: 30]
|
||||||
|
EVENT[198]: 0.002592950 - core[0].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[199]: 0.002605950 - core[0].svIdle(17), plen 0: []
|
||||||
|
EVENT[200]: 0.008819550 - core[0].svIsrEnter(2), plen 0: [irq_num: 5]
|
||||||
|
EVENT[201]: 0.008828075 - core[0].svTaskStartReady(6), plen 0: [tid: 12291908]
|
||||||
|
EVENT[202]: 0.008828075 - core[1].svTaskStartReady(6), plen 0: [tid: 12291908]
|
||||||
|
EVENT[203]: 0.008837475 - core[0].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[204]: 0.008850450 - core[0].svTaskStartExec(4), plen 0: [tid: 12291908]
|
||||||
|
EVENT[205]: 0.008872650 - core[0].svModuleDesc(22), plen 0: [mod_id: 0, evt_off: 512, desc: ESP32 SystemView Heap Tracing Module]
|
||||||
|
EVENT[206]: 0.008872650 - core[1].svModuleDesc(22), plen 0: [mod_id: 0, evt_off: 512, desc: ESP32 SystemView Heap Tracing Module]
|
||||||
|
EVENT[207]: 0.008886175 - core[0].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[208]: 0.008886175 - core[1].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[209]: 0.008897425 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[210]: 0.008906150 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[211]: 0.008919900 - core[0].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073450504, size: 64, callers: [1074601571, 1074296884]]
|
||||||
|
[0.008919900] HEAP: Allocated 64 bytes @ 0x3ffb8e08 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:65
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[212]: 0.008928250 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[213]: 0.008957950 - core[0].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073450572, size: 80, callers: [1074298654, 1074299267]]
|
||||||
|
[0.008957950] HEAP: Allocated 80 bytes @ 0x3ffb8e4c from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
|
||||||
|
EVENT[214]: 0.008967250 - core[0].xQueueGenericCreate(47), plen 3: [uxQueueLength: 1, uxItemSize: 0, ucQueueType: 4]
|
||||||
|
EVENT[215]: 0.008977300 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[216]: 0.008984625 - core[1].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073450656, size: 65, callers: [1074601382, 1074296884]]
|
||||||
|
[0.008984625] HEAP: Allocated 65 bytes @ 0x3ffb8ea0 from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:30
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[217]: 0.008995725 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[218]: 0.009010075 - core[1].svIsrEnter(2), plen 0: [irq_num: 5]
|
||||||
|
EVENT[219]: 0.009018025 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[220]: 0.009031900 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[221]: 0.009089600 - core[0].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073434644, size: 80, callers: [1074298654, 1074299267]]
|
||||||
|
[0.009089600] HEAP: Allocated 80 bytes @ 0x3ffb5014 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
|
||||||
|
EVENT[222]: 0.009098175 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[223]: 0.009106300 - core[0].xQueueGenericCreate(47), plen 3: [uxQueueLength: 1, uxItemSize: 0, ucQueueType: 4]
|
||||||
|
EVENT[224]: 0.009113825 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[225]: 0.009121600 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[226]: 0.009129000 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[227]: 0.009137900 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[228]: 0.009145425 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[229]: 0.009169600 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[230]: 0.009185225 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[231]: 0.009195125 - core[0].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[232]: 0.009195125 - core[1].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[233]: 0.009207000 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[234]: 0.009215575 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[235]: 0.009223275 - core[0].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073434728, size: 96, callers: [1074601587, 1074296884]]
|
||||||
|
[0.009223275] HEAP: Allocated 96 bytes @ 0x3ffb5068 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:68
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[236]: 0.009231050 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[237]: 0.009241875 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[238]: 0.009257225 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[239]: 0.009269200 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[240]: 0.009278275 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[241]: 0.009286275 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[242]: 0.009303450 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[243]: 0.009310950 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[244]: 0.009329625 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[245]: 0.009339525 - core[0].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[246]: 0.009339525 - core[1].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[247]: 0.009351425 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[248]: 0.009359450 - core[0].esp_sysview_heap_trace_free(513), plen 15: [addr: 1073450504, callers: [1074601600, 1074296884]]
|
||||||
|
[0.009359450] HEAP: Freed bytes @ 0x3ffb8e08 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:70
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[249]: 0.009367800 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[250]: 0.009378950 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[251]: 0.009387450 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[252]: 0.009402575 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[253]: 0.009414900 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[254]: 0.009423125 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[255]: 0.009430250 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[256]: 0.009445425 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[257]: 0.009453075 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[258]: 0.009469225 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[259]: 0.009479025 - core[0].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[260]: 0.009479025 - core[1].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[261]: 0.009490950 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[262]: 0.009499475 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[263]: 0.009507600 - core[0].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073450504, size: 10, callers: [1074601615, 1074296884]]
|
||||||
|
[0.009507600] HEAP: Allocated 10 bytes @ 0x3ffb8e08 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:72
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[264]: 0.009515300 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[265]: 0.009526100 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[266]: 0.009541550 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[267]: 0.009553850 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[268]: 0.009561100 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[269]: 0.009568400 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[270]: 0.009585075 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[271]: 0.009593375 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[272]: 0.009609150 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[273]: 0.009621875 - core[0].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[274]: 0.009621875 - core[1].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[275]: 0.009633775 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[276]: 0.009642300 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[277]: 0.009649475 - core[0].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073450520, size: 23, callers: [1074601628, 1074296884]]
|
||||||
|
[0.009649475] HEAP: Allocated 23 bytes @ 0x3ffb8e18 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:73
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[278]: 0.009657875 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[279]: 0.009666025 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[280]: 0.009681500 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[281]: 0.009693375 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[282]: 0.009702800 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[283]: 0.009710550 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[284]: 0.009726725 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[285]: 0.010504825 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[286]: 0.010520650 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[287]: 0.010530550 - core[0].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[288]: 0.010530550 - core[1].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[289]: 0.010542400 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[290]: 0.010550025 - core[0].esp_sysview_heap_trace_free(513), plen 15: [addr: 1073450520, callers: [1074601643, 1074296884]]
|
||||||
|
[0.010550025] HEAP: Freed bytes @ 0x3ffb8e18 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:76
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[291]: 0.010557450 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[292]: 0.010569700 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[293]: 0.010577700 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[294]: 0.010592825 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[295]: 0.010605950 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[296]: 0.010613575 - core[0].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[297]: 0.010620900 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[298]: 0.010637050 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[299]: 0.012240950 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[300]: 0.012256775 - core[0].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[301]: 0.012266650 - core[0].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[302]: 0.012266650 - core[1].svTaskStartReady(6), plen 0: [tid: 12294320]
|
||||||
|
EVENT[303]: 0.012281350 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[304]: 0.012289475 - core[0].svTaskStopReady(7), plen 0: [tid: 12291908, cause: 27]
|
||||||
|
EVENT[305]: 0.012297450 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[306]: 0.012306350 - core[0].svIsrEnter(2), plen 0: [irq_num: 30]
|
||||||
|
EVENT[307]: 0.012312875 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[308]: 0.012320700 - core[0].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[309]: 0.012328950 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[310]: 0.012338100 - core[0].svIdle(17), plen 0: []
|
||||||
|
EVENT[311]: 0.012640475 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[312]: 0.014931850 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[313]: 0.014963325 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[314]: 0.014984150 - core[1].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073434828, size: 97, callers: [1074601399, 1074296884]]
|
||||||
|
[0.014984150] HEAP: Allocated 97 bytes @ 0x3ffb50cc from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:33
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[315]: 0.014997400 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[316]: 0.015031050 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[317]: 0.017622800 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[318]: 0.017638675 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[319]: 0.017656375 - core[1].esp_sysview_heap_trace_free(513), plen 15: [addr: 1073450656, callers: [1074601412, 1074296884]]
|
||||||
|
[0.017656375] HEAP: Freed bytes @ 0x3ffb8ea0 from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:35
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[320]: 0.017674025 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[321]: 0.017701700 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[322]: 0.018819550 - core[0].svIsrEnter(2), plen 0: [irq_num: 5]
|
||||||
|
EVENT[323]: 0.018829625 - core[0].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[324]: 0.018844750 - core[0].svIdle(17), plen 0: []
|
||||||
|
EVENT[325]: 0.019010075 - core[1].svIsrEnter(2), plen 0: [irq_num: 5]
|
||||||
|
EVENT[326]: 0.019017950 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[327]: 0.019033200 - core[1].svTaskStartExec(4), plen 0: [tid: 12294320]
|
||||||
|
EVENT[328]: 0.019358925 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[329]: 0.019374600 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[330]: 0.019395425 - core[1].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073450520, size: 11, callers: [1074601427, 1074296884]]
|
||||||
|
[0.019395425] HEAP: Allocated 11 bytes @ 0x3ffb8e18 from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:37
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[331]: 0.019412600 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[332]: 0.019446250 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[333]: 0.022049900 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[334]: 0.022065775 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[335]: 0.022086625 - core[1].esp_sysview_heap_trace_alloc(512), plen 16: [addr: 1073450536, size: 24, callers: [1074601440, 1074296884]]
|
||||||
|
[0.022086625] HEAP: Allocated 24 bytes @ 0x3ffb8e28 from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:38
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[336]: 0.022103925 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[337]: 0.022137550 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[338]: 0.024740850 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[339]: 0.024756725 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[340]: 0.024770475 - core[1].esp_sysview_heap_trace_free(513), plen 15: [addr: 1073450536, callers: [1074601455, 1074296884]]
|
||||||
|
[0.024770475] HEAP: Freed bytes @ 0x3ffb8e28 from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:41
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
EVENT[341]: 0.024791750 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12291660, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[342]: 0.024819500 - core[1].xQueueGenericReceive(49), plen 15: [xQueue: 12275732, pvBuffer: 3233808384, xTicksToWait: 4294967295, xJustPeek: 0]
|
||||||
|
EVENT[343]: 0.026476950 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12275732, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[344]: 0.026495700 - core[1].xQueueGenericSend(53), plen 7: [xQueue: 12291660, pvItemToQueue: 0, xTicksToWait: 0, xCopyPosition: 0]
|
||||||
|
EVENT[345]: 0.026506975 - core[0].svTaskStartReady(6), plen 0: [tid: 12291908]
|
||||||
|
EVENT[346]: 0.026506975 - core[1].svTaskStartReady(6), plen 0: [tid: 12291908]
|
||||||
|
EVENT[347]: 0.026518525 - core[1].svTaskStopReady(7), plen 0: [tid: 12294320, cause: 27]
|
||||||
|
EVENT[348]: 0.026526625 - core[0].svIsrEnter(2), plen 0: [irq_num: 30]
|
||||||
|
EVENT[349]: 0.026535575 - core[0].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[350]: 0.026544075 - core[1].svIsrEnter(2), plen 0: [irq_num: 31]
|
||||||
|
EVENT[351]: 0.026551650 - core[0].svTaskStartExec(4), plen 0: [tid: 12291908]
|
||||||
|
EVENT[352]: 0.026559500 - core[1].svExitIsrToScheduler(18), plen 0: []
|
||||||
|
EVENT[353]: 0.148816725 - core[1].svIdle(17), plen 0: []
|
||||||
|
EVENT[354]: 0.148825750 - core[0].vTaskDelay(34), plen 1: [xTicksToDelay: 1]
|
||||||
|
EVENT[355]: 0.148833200 - core[0].svTaskStopReady(7), plen 0: [tid: 12291908, cause: 4]
|
||||||
|
EVENT[356]: 0.148839250 - core[0].svTraceStop(11), plen 0: []
|
||||||
|
EVENT[357]: 0.148839250 - core[1].svTraceStop(11), plen 0: []
|
||||||
|
Processing completed.
|
||||||
|
Processed 358 events
|
||||||
|
=============== LOG TRACE REPORT ===============
|
||||||
|
Processed 0 log messages.
|
||||||
|
=============== HEAP TRACE REPORT ===============
|
||||||
|
Processed 14 heap events.
|
||||||
|
[0.008957950] HEAP: Allocated 80 bytes @ 0x3ffb8e4c from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
|
||||||
|
[0.009089600] HEAP: Allocated 80 bytes @ 0x3ffb5014 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/queue.c:2037
|
||||||
|
|
||||||
|
[0.009223275] HEAP: Allocated 96 bytes @ 0x3ffb5068 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:68
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.009507600] HEAP: Allocated 10 bytes @ 0x3ffb8e08 from task "blink_task" on core 0 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:72
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.014984150] HEAP: Allocated 97 bytes @ 0x3ffb50cc from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:33
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
[0.019395425] HEAP: Allocated 11 bytes @ 0x3ffb8e18 from task "blink_task2" on core 1 by:
|
||||||
|
/home/alexey/projects/esp/esp-idf/examples/get-started/blink/main/blink.c:37
|
||||||
|
/home/alexey/projects/esp/esp-idf/components/freertos/port.c:355 (discriminator 1)
|
||||||
|
|
||||||
|
Found 374 leaked bytes in 6 blocks.
|
19
tools/esp_app_trace/test/sysview/gdbinit
Normal file
19
tools/esp_app_trace/test/sysview/gdbinit
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
target remote :3333
|
||||||
|
|
||||||
|
mon reset halt
|
||||||
|
flushregs
|
||||||
|
|
||||||
|
b heap_trace_start
|
||||||
|
commands
|
||||||
|
clear heap_trace_start
|
||||||
|
mon esp32 sysview start file://cpu0.svdat file://cpu1.svdat
|
||||||
|
c
|
||||||
|
end
|
||||||
|
|
||||||
|
b heap_trace_stop
|
||||||
|
commands
|
||||||
|
clear heap_trace_stop
|
||||||
|
mon esp32 sysview stop
|
||||||
|
end
|
||||||
|
|
||||||
|
c
|
BIN
tools/esp_app_trace/test/sysview/test.elf
Normal file
BIN
tools/esp_app_trace/test/sysview/test.elf
Normal file
Binary file not shown.
8
tools/esp_app_trace/test/sysview/test.sh
Executable file
8
tools/esp_app_trace/test/sysview/test.sh
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
{ coverage debug sys \
|
||||||
|
&& coverage erase &> output \
|
||||||
|
&& coverage run -a $IDF_PATH/tools/esp_app_trace/sysviewtrace_proc.py -d -p cpu0.svdat cpu1.svdat test.elf &>> output \
|
||||||
|
&& diff output expected_output \
|
||||||
|
&& coverage report \
|
||||||
|
; } || { echo 'The test for sysviewtrace_proc has failed. Please examine the artifacts.' ; exit 1; }
|
Loading…
Reference in a new issue