scripts: logging/dictionary/sys-t: log module info in collateral
This updates the MIPI Sys-T collateral generation to include log modules in the XML file. This allows the parser to show where each log message is coming from. Note that the addition of Name propety in sys:Client is to clarify that this collateral is from Zephyr. Also note he addition of Mask property in syst:Guid is for parser to match this collateral to any incoming messages, as the module IDs are encoded in the set bits in the GUID. Without the mask, the parser will discard any messages with non-zero module IDs. This is based on the observation of the reference parser, systprint, where pseudo GUIDs are generated from the module/unit IDs (origin unit) in the incoming messages for matching with collaterals. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
64c804ad3b
commit
2e2c8cc931
4 changed files with 49 additions and 25 deletions
|
@ -23,6 +23,7 @@ import sys
|
||||||
import dictionary_parser.log_database
|
import dictionary_parser.log_database
|
||||||
from dictionary_parser.log_database import LogDatabase
|
from dictionary_parser.log_database import LogDatabase
|
||||||
from dictionary_parser.utils import extract_one_string_in_section
|
from dictionary_parser.utils import extract_one_string_in_section
|
||||||
|
from dictionary_parser.utils import find_string_in_mappings
|
||||||
|
|
||||||
import elftools
|
import elftools
|
||||||
from elftools.elf.constants import SH_FLAGS
|
from elftools.elf.constants import SH_FLAGS
|
||||||
|
@ -166,7 +167,7 @@ def find_log_const_symbols(elf):
|
||||||
return ret_list
|
return ret_list
|
||||||
|
|
||||||
|
|
||||||
def parse_log_const_symbols(database, log_const_section, log_const_symbols):
|
def parse_log_const_symbols(database, log_const_section, log_const_symbols, string_mappings):
|
||||||
"""Find the log instances and map source IDs to names"""
|
"""Find the log instances and map source IDs to names"""
|
||||||
if database.is_tgt_little_endian():
|
if database.is_tgt_little_endian():
|
||||||
formatter = "<"
|
formatter = "<"
|
||||||
|
@ -210,7 +211,9 @@ def parse_log_const_symbols(database, log_const_section, log_const_symbols):
|
||||||
str_ptr, level = struct.unpack(formatter, datum)
|
str_ptr, level = struct.unpack(formatter, datum)
|
||||||
|
|
||||||
# Offset to rodata section for string
|
# Offset to rodata section for string
|
||||||
instance_name = database.find_string(str_ptr)
|
instance_name = find_string_in_mappings(string_mappings, str_ptr)
|
||||||
|
if instance_name is None:
|
||||||
|
instance_name = "unknown"
|
||||||
|
|
||||||
logger.info("Found Log Instance: %s, level: %d", instance_name, level)
|
logger.info("Found Log Instance: %s, level: %d", instance_name, level)
|
||||||
|
|
||||||
|
@ -255,7 +258,7 @@ def process_kconfigs(elf, database):
|
||||||
kconfigs['CONFIG_LOG_TIMESTAMP_64BIT'])
|
kconfigs['CONFIG_LOG_TIMESTAMP_64BIT'])
|
||||||
|
|
||||||
|
|
||||||
def extract_logging_subsys_information(elf, database):
|
def extract_logging_subsys_information(elf, database, string_mappings):
|
||||||
"""
|
"""
|
||||||
Extract logging subsys related information and store in database.
|
Extract logging subsys related information and store in database.
|
||||||
|
|
||||||
|
@ -274,7 +277,7 @@ def extract_logging_subsys_information(elf, database):
|
||||||
|
|
||||||
# Find all "log_const_*" symbols and parse them
|
# Find all "log_const_*" symbols and parse them
|
||||||
log_const_symbols = find_log_const_symbols(elf)
|
log_const_symbols = find_log_const_symbols(elf)
|
||||||
parse_log_const_symbols(database, section_log_const, log_const_symbols)
|
parse_log_const_symbols(database, section_log_const, log_const_symbols, string_mappings)
|
||||||
|
|
||||||
|
|
||||||
def is_die_attr_ref(attr):
|
def is_die_attr_ref(attr):
|
||||||
|
@ -510,9 +513,7 @@ def extract_static_strings(elf, database, section_extraction=False):
|
||||||
if one_str not in string_mappings:
|
if one_str not in string_mappings:
|
||||||
string_mappings[one_str] = rawstr_map[one_str]
|
string_mappings[one_str] = rawstr_map[one_str]
|
||||||
|
|
||||||
if len(string_mappings) > 0:
|
return string_mappings
|
||||||
database.set_string_mappings(string_mappings)
|
|
||||||
logger.info("Found %d strings", len(string_mappings))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -536,12 +537,10 @@ def main():
|
||||||
if args.json:
|
if args.json:
|
||||||
logger.info("JSON Database file %s", args.json)
|
logger.info("JSON Database file %s", args.json)
|
||||||
section_extraction = True
|
section_extraction = True
|
||||||
get_subsys_info = True
|
|
||||||
|
|
||||||
if args.syst:
|
if args.syst:
|
||||||
logger.info("MIPI Sys-T Collateral file %s", args.syst)
|
logger.info("MIPI Sys-T Collateral file %s", args.syst)
|
||||||
section_extraction = False
|
section_extraction = False
|
||||||
get_subsys_info = False
|
|
||||||
|
|
||||||
elf = ELFFile(elffile)
|
elf = ELFFile(elffile)
|
||||||
|
|
||||||
|
@ -574,11 +573,20 @@ def main():
|
||||||
PTR_FMT = '0x%016x'
|
PTR_FMT = '0x%016x'
|
||||||
|
|
||||||
# Extract strings from ELF files
|
# Extract strings from ELF files
|
||||||
extract_static_strings(elf, database, section_extraction)
|
string_mappings = extract_static_strings(elf, database, section_extraction)
|
||||||
|
if len(string_mappings) > 0:
|
||||||
|
database.set_string_mappings(string_mappings)
|
||||||
|
logger.info("Found %d strings", len(string_mappings))
|
||||||
|
|
||||||
# Extract information related to logging subsystem
|
# Extract information related to logging subsystem
|
||||||
if get_subsys_info:
|
if not section_extraction:
|
||||||
extract_logging_subsys_information(elf, database)
|
# The logging subsys information (e.g. log module names)
|
||||||
|
# may require additional strings outside of those extracted
|
||||||
|
# via ELF DWARF variables. So generate a new string mappings
|
||||||
|
# with strings in various ELF sections.
|
||||||
|
string_mappings = extract_static_strings(elf, database, section_extraction=True)
|
||||||
|
|
||||||
|
extract_logging_subsys_information(elf, database, string_mappings)
|
||||||
|
|
||||||
# Write database file
|
# Write database file
|
||||||
if args.json:
|
if args.json:
|
||||||
|
|
|
@ -14,6 +14,7 @@ import json
|
||||||
|
|
||||||
from .mipi_syst import gen_syst_xml_file
|
from .mipi_syst import gen_syst_xml_file
|
||||||
from .utils import extract_one_string_in_section
|
from .utils import extract_one_string_in_section
|
||||||
|
from .utils import find_string_in_mappings
|
||||||
|
|
||||||
|
|
||||||
ARCHS = {
|
ARCHS = {
|
||||||
|
@ -190,17 +191,7 @@ class LogDatabase():
|
||||||
Find string pointed by string_ptr in the string mapping
|
Find string pointed by string_ptr in the string mapping
|
||||||
list. Return None if not found.
|
list. Return None if not found.
|
||||||
"""
|
"""
|
||||||
if string_ptr in self.database['string_mappings']:
|
return find_string_in_mappings(self.database['string_mappings'], string_ptr)
|
||||||
return self.database['string_mappings'][string_ptr]
|
|
||||||
|
|
||||||
# No direct match on pointer value.
|
|
||||||
# This may be a combined string. So check for that.
|
|
||||||
for ptr, string in self.database['string_mappings'].items():
|
|
||||||
if ptr <= string_ptr < (ptr + len(string)):
|
|
||||||
whole_str = self.database['string_mappings'][ptr]
|
|
||||||
return whole_str[string_ptr - ptr:]
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def __find_string_in_sections(self, string_ptr):
|
def __find_string_in_sections(self, string_ptr):
|
||||||
|
|
|
@ -18,7 +18,7 @@ XML_HEADER = """
|
||||||
xsi:schemaLocation="http://www.mipi.org/1.0/sys-t
|
xsi:schemaLocation="http://www.mipi.org/1.0/sys-t
|
||||||
https://www.mipi.org/schema/sys-t/sys-t_1-0.xsd">
|
https://www.mipi.org/schema/sys-t/sys-t_1-0.xsd">
|
||||||
|
|
||||||
<syst:Client>
|
<syst:Client Name="Zephyr">
|
||||||
"""
|
"""
|
||||||
|
|
||||||
XML_FOOTER = """
|
XML_FOOTER = """
|
||||||
|
@ -59,7 +59,8 @@ XML_CATALOG64_FOOTER = """
|
||||||
|
|
||||||
XML_GUIDS = """
|
XML_GUIDS = """
|
||||||
<syst:Guids>
|
<syst:Guids>
|
||||||
<syst:Guid ID="{00000000-0000-0000-0000-000000000000}"><![CDATA[Zephyr]]></syst:Guid>
|
<syst:Guid ID="{00000000-0000-0000-0000-000000000000}"
|
||||||
|
Mask="{00000000-0000-0000-FF00-000000000000}"><![CDATA[Zephyr]]></syst:Guid>
|
||||||
</syst:Guids>
|
</syst:Guids>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -41,3 +41,27 @@ def extract_one_string_in_section(section, str_ptr):
|
||||||
offset += 1
|
offset += 1
|
||||||
|
|
||||||
return ret_str
|
return ret_str
|
||||||
|
|
||||||
|
|
||||||
|
def find_string_in_mappings(string_mappings, str_ptr):
|
||||||
|
"""
|
||||||
|
Find string pointed by string_ptr in the string mapping
|
||||||
|
list. Return None if not found.
|
||||||
|
"""
|
||||||
|
if string_mappings is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(string_mappings) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if str_ptr in string_mappings:
|
||||||
|
return string_mappings[str_ptr]
|
||||||
|
|
||||||
|
# No direct match on pointer value.
|
||||||
|
# This may be a combined string. So check for that.
|
||||||
|
for ptr, string in string_mappings.items():
|
||||||
|
if ptr <= str_ptr < (ptr + len(string)):
|
||||||
|
whole_str = string_mappings[ptr]
|
||||||
|
return whole_str[str_ptr - ptr:]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue