Skip to content

Commit

Permalink
Merge pull request #85 from EdwinFairchild/find-symbol-address-given-…
Browse files Browse the repository at this point in the history
…name

Find symbol address given name
  • Loading branch information
EdwinFairchild authored Oct 27, 2023
2 parents 0dea7fa + 57e5858 commit f12d2d0
Show file tree
Hide file tree
Showing 8 changed files with 533 additions and 24 deletions.
35 changes: 35 additions & 0 deletions getSymbol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pyocd
from elftools.elf.elffile import ELFFile
import logging
import time

# Replace 'your_elf_file.elf' with the path to your ELF file
elf_file_path = 'max32655.elf'

# Replace 'your_symbol_name' with the symbol name you want to retrieve the address for
symbol_name = 'testVal'



# Connect to the target with your probe
with pyocd.target.get_device_count() as session:
if session > 0:
with pyocd.target.Session() as target:
try:
# Load the ELF file onto the target
target.load_binary(elf_file_path)

# Get the address of the symbol
address = target.get_symbol_address(symbol_name)

if address is not None:
logger.info(f"The address of '{symbol_name}' is 0x{address:08X}")
else:
logger.info(f"Symbol '{symbol_name}' not found.")

except Exception as e:
logger.warning(f"Error while connecting to the probe: {e}")
else:
logger.info("No probe found!")

# Rest of your code (variable monitoring, etc.) goes here...
2 changes: 1 addition & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def openCloseRightBox():
self.watch_vars_chart_container.setLayout(self.watch_vars_chart_layout)
self.ui.insights_scroll_area.setWidget(self.watch_vars_chart_container)


self.ui.stats_frame.hide()

# SHOW APP
self.show()
Expand Down
245 changes: 236 additions & 9 deletions main.ui

Large diffs are not rendered by default.

Binary file added max32655.elf
Binary file not shown.
21 changes: 19 additions & 2 deletions modules/btn_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def handle_checkbox_state_change(state, var_name, address, address_dict, main_wi
address_dict[var_name] = {"address": address, "watched_row_position": watched_row_position, "graphed": False}

# TODO make user chose from a drop down
address_dict[var_name]['var_type'] = 'float'
address_dict[var_name]['var_type'] = 'None'


else:
Expand Down Expand Up @@ -637,6 +637,21 @@ def start_ota(main_window):
return
main_window.connectedDevice.device_ota_update_start.emit(main_window.connectedDevice , main_window.fileName, main_window.fileLen, main_window.fileCrc32)

def btn_hide_core_regs(main_window):
main_window.var_watcher.symbolName = 'bbConnStats'

def enable_connection_stats(main_window):
logger = logging.getLogger("PDexLogger")
if main_window.ui.connection_stats_enable.isChecked():
main_window.var_watcher.getConnStats = True
main_window.ui.stats_frame.show()
logger.info("Getting connection stats")
else:
main_window.var_watcher.getConnStats = False
logger.info("Not getting connection stats")
main_window.ui.stats_frame.hide()


def register_button_callbacks(main_window):
logger = logging.getLogger("PDexLogger")
try:
Expand All @@ -653,7 +668,9 @@ def register_button_callbacks(main_window):
main_window.var_watcher.core_regs_tuple.connect(main_window.get_core_regs_handler)
main_window.ui.btn_refreshCoreRegs.clicked.connect(lambda: get_core_regs(main_window))
# graphing checkbox callbacks
main_window.ui.graph_enabled.stateChanged.connect(lambda: disable_graphing(main_window))
main_window.ui.graph_enabled.stateChanged.connect(lambda: disable_graphing(main_window))
main_window.ui.btn_hideCoreRegs.clicked.connect(lambda: btn_hide_core_regs(main_window))
main_window.ui.connection_stats_enable.stateChanged.connect(lambda: enable_connection_stats(main_window))

#register slot/signal for disconnecting from device
main_window.ui.btn_clear_logs.clicked.connect(lambda: clear_logs(main_window))
Expand Down
102 changes: 97 additions & 5 deletions modules/elf_insights.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import logging
import time
import sys

import struct
from PySide6.QtCore import QThread

class ExtractGlobalVariablesThread(QThread):
Expand Down Expand Up @@ -47,21 +47,26 @@ def run(self):
# if exit_early is true then exit the thread
if self.exit_early:
return
# TODO make this a user setting, possibly slider to select sample rate
time.sleep(0.005)

time.sleep(0.001)
self.logger.info("Finished extracting global variables")



class MonitoringThread(QThread):
signal_update_variable = Signal(str, object) # Signal to update the variable value
var_monitor_active = Signal(bool)

monitor_active = False
exit_early = False
logger = logging.getLogger("PDexLogger")
getCoreRegs = False
core_regs_tuple = Signal(zip)

symbolName = None
getConnStats = False
connStatsAddress = None
#make a signal to update the connection stats as list
connStatValues = Signal(list)
def __init__(self, address_dict):
super().__init__()
self.address_dict = address_dict #vars_watched_dict from main.py
Expand Down Expand Up @@ -143,6 +148,74 @@ def monitor_variables(self, target, addresses):
if self.getCoreRegs is True:
self.print_core_registers(target)
self.getCoreRegs = False

if self.getConnStats is True:
if self.connStatsAddress is None:
try:
self.connStatsAddress = self.get_symbol_address_from_elf('/home/eddie/projects/BLE-PyDex/max32655.elf', 'bbConnStats')
except Exception as e:
self.logger.setLevel(logging.WARNING)
self.logger.warning("Error while monitoring variables: %s", e)
self.logger.setLevel(logging.INFO)
if self.connStatsAddress is not None:
#print address in hex
# print("0x{:08x}".format(address))
data = self.read_struct_from_memory(target,self.connStatsAddress, 20)
# Define the format string for the struct
# The format string corresponds to the data types and order in the struct
format_string = '<IIIII' # Use '<' for little-endian byte order

# Unpack the binary data into a tuple
struct_byes = bytes(data)
struct_data = struct.unpack(format_string, struct_byes)

# Now, struct_data contains the values according to the struct's meaning
rxData, rxDataCrc, rxDataTimeout, txData, errData= struct_data
# check for division by zero
if (rxDataCrc + rxDataTimeout) != 0 and (rxData +rxDataCrc + rxDataTimeout) != 0:
#if none of the stats are zero then we are connected
per = (rxDataCrc + rxDataTimeout) / (rxData +rxDataCrc + rxDataTimeout)
else:
per = 0
#conver PER to percent
per = per * 100
#only 2 decimal places
per = round(per, 2)

self.connStatValues.emit([rxData, rxDataCrc, rxDataTimeout, txData, errData, per])



if self.symbolName is not None:
address = self.get_symbol_address_from_elf('/home/eddie/projects/BLE-PyDex/max32655.elf', self.symbolName)
if address is not None:
#print address in hex
# print("0x{:08x}".format(address))
data = self.read_struct_from_memory(target,address, 20)
# Define the format string for the struct
# The format string corresponds to the data types and order in the struct
format_string = '<IIIIIHHHH' # Use '<' for little-endian byte order

# Unpack the binary data into a tuple
struct_byes = bytes(data)
struct_data = struct.unpack(format_string, struct_byes)

# Now, struct_data contains the values according to the struct's meaning
rxData, rxDataCrc, rxDataTimeout, txData, errData= struct_data

# Print the values
print(f"rxData: {rxData}")
print(f"rxDataCrc: {rxDataCrc}")
print(f"rxDataTimeout: {rxDataTimeout}")
print(f"txData: {txData}")
print(f"errData: {errData}")


print(data)
else:
self.logger.warning("Symbol '%s' not found in ELF file.", self.symbolName)
self.symbolName = None
# TODO make this use the slider value
time.sleep(0.010) # Adjust the refresh rate as needed
except Exception as e:
self.logger.setLevel(logging.WARNING)
Expand All @@ -157,7 +230,26 @@ def monitor_variables(self, target, addresses):
self.exit_early = False
monitor_active = False


def get_symbol_address_from_elf(self, elf_path, symbol_name):
try:
with open(elf_path, 'rb') as elf_file:
elf = ELFFile(elf_file)
for section in elf.iter_sections():
if section.name == '.symtab':
symbol_table = section
for symbol in symbol_table.iter_symbols():
if symbol.name == symbol_name:
return symbol['st_value']
except Exception as e:
self.logger.warning("Error while getting symbol address from ELF: %s", e)
return None
def read_struct_from_memory(self, target, address, struct_size):
try:
data = target.read_memory_block8(address, struct_size)
return data
except Exception as e:
self.logger.warning("Error while reading struct from memory: %s", e)
return None
def mass_erase(self):
pass

Expand Down
13 changes: 13 additions & 0 deletions modules/slots.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ def device_disconnected_cb(interface):

# clean up gui elements
interface.cleanUp.emit("dummy data")
def update_connection_stats(interface, stats):
interface.ui.lbl_rx_data_count.setText("RX Data Count: " + str(stats[0]))
interface.ui.lbl_rx_data_crc_err.setText("RX Data CRC Error: " + str(stats[1]))
interface.ui.lbl_rx_data_timeout.setText("RX Data Timeout: " + str(stats[2]))
interface.ui.lbl_tx_data_count.setText("TX Data Count: " + str(stats[3]))
interface.ui.lbl_tx_data_err.setText("TX Data Error: " + str(stats[4]))
interface.ui.lbl_PER.setText("PER: " + str(stats[5]) + "%")




def init_signals_and_slots(interface):
interface.bleScanner.discovered_devices.connect(lambda device : update_discovered_devices(interface,device))
Expand All @@ -89,6 +99,9 @@ def init_signals_and_slots(interface):
# show Gatt explorer when connected
interface.connectedDevice.connection_established.connect(lambda: interface.stacked_widget_show_connected())

#singal/slot for connection stats
interface.var_watcher.connStatValues.connect(lambda stats: update_connection_stats(interface, stats))




Expand Down
Loading

0 comments on commit f12d2d0

Please sign in to comment.