In order to facilitate the debugging needs of C6000 DSP, I need to obtain the addresses and sizes of all variables inside the DSP. The cg_xml package from TI does not provide variable size information, so I wrote this python script to extract variable information from the .out file and export it as a .csv file.

Description

This script contains:

First, use ofd6x to export the .out file information as xml information.

Then, use ElementTree to process the xml.

Finally, a csv file is generated.

The <elf32_sym> tag contains the symbols’ information. The tags are under the path object_file/elf/section_table/section/symbol_table/. The <elf32_sym> is like:

<elf32_sym>
    <index>0x11cf</index>
    <st_name>0xce40</st_name>
    <st_name_string>VariableName</st_name_string>
    <st_value>0x82825c</st_value>
    <st_size>0x2</st_size>
    <st_bind>STB_GLOBAL</st_bind>
    <st_type>STT_OBJECT</st_type>
    <st_visibility>STV_HIDDEN</st_visibility>
    <st_shndx>0x7</st_shndx>
    <st_shndx_string>.bss</st_shndx_string>
</elf32_sym>

This link gives the detailed information of Symbol Table Section. Note that, STT_OBJECT is associated with a data object, such as a variable, an array, and so forth. STT_COMMON labels an uninitialized common block. This symbol is treated exactly the same as STT_OBJECT.

The xml produced by ofd6x may contain some invalid characters if the .out contains paths of non-Ascii characters. This sentence removes the invalid characters:

output.decode('utf-8','ignore').encode('utf-8')

Python Script

import xml.etree.ElementTree as ET
import csv
import subprocess
import sys
import os

if len(sys.argv) != 2:
    sys.exit()

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

filename = sys.argv[1]

output = subprocess.Popen([resource_path("ofd6x.exe"), "-xg", filename], stdout=subprocess.PIPE).communicate()[0]

root = ET.fromstring(output.decode('utf-8','ignore').encode('utf-8'))

def get_name(sym):
    return sym.find('st_name_string').text
def get_type(sym):
    return sym.find('st_type').text
def get_addr(sym):
    return sym.find('st_value').text
def get_size(sym):
    return sym.find('st_size').text
def get_bind(sym):
    return sym.find('st_bind').text
def get_visibility(sym):
    return sym.find('st_visibility').text
def get_shndx(sym):
    return sym.find('st_shndx_string').text

with open(filename+'_syms.csv', 'w', newline='') as csvfile:
    fieldnames = ['name', 'addr', 'addr10', 'size', 'section','bind', 'technblogy.com']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    writer.writeheader()

    for sym in root.findall('object_file/elf/section_table/section/symbol_table/elf32_sym'):
        if (get_type(sym)=='STT_OBJECT' or get_type(sym)=='STT_COMMON') and get_name(sym)[0]!='$':
            c = {}
            c['name']    = get_name(sym)
            c['addr']    = get_addr(sym)
            c['addr10']  = int(get_addr(sym),16)
            c['size']    = int(get_size(sym),16)
            c['section'] = get_shndx(sym)
            c['bind']    = get_bind(sym)

            writer.writerow(c)

Reference

Software Development Organization (SDO) Applications Packages

Symbol Table Section – Linker and Libraries Guide

python – ElementTree and unicode – Stack Overflow

python – Bundling data files with PyInstaller (–onefile) – Stack Overflow

Reading and Writing CSV Files in Python – Real Python


0 Comments

Leave a Reply

Your email address will not be published.