ldgen: fix sections info parsing

Fixes an issure where the first part of an object file name is not
included, due to matching the rule for a section entry previously.

Reduce depedency on matching literal strings in sections which might
change depending on toolchain (ex. matching 'elf32-xtensa-le')

Make sure parsing rule succeeds for the entirety of the sections info
string by adding 'parseAll=True'.

Add test for sections info parsing.
This commit is contained in:
Renz Bagaporo 2020-11-16 13:55:22 +08:00 committed by Angus Gratton
parent ffefe603ae
commit 23aff378f4
4 changed files with 47 additions and 15 deletions

View File

@ -21,7 +21,7 @@ import fnmatch
from fragments import Sections, Scheme, Mapping, Fragment
from pyparsing import Suppress, White, ParseException, Literal, Group, ZeroOrMore
from pyparsing import Word, OneOrMore, nums, alphanums, alphas, Optional, restOfLine
from pyparsing import Word, OneOrMore, nums, alphas, restOfLine, SkipTo
from ldgen_common import LdGenFailure
@ -608,7 +608,7 @@ class SectionsInfo(dict):
results = None
try:
results = parser.parseString(first_line)
results = parser.parseString(first_line, parseAll=True)
except ParseException as p:
raise ParseException("Parsing sections info for library " + sections_info_dump.name + " failed. " + p.message)
@ -616,26 +616,26 @@ class SectionsInfo(dict):
self.sections[archive] = SectionsInfo.__info(sections_info_dump.name, sections_info_dump.read())
def _get_infos_from_file(self, info):
# Object file line: '{object}: file format elf32-xtensa-le'
object = Fragment.ENTITY.setResultsName("object") + Literal(":").suppress() + Literal("file format elf32-xtensa-le").suppress()
# {object}: file format elf32-xtensa-le
object_line = SkipTo(":").setResultsName("object") + Suppress(restOfLine)
# Sections table
header = Suppress(Literal("Sections:") + Literal("Idx") + Literal("Name") + Literal("Size") + Literal("VMA") +
Literal("LMA") + Literal("File off") + Literal("Algn"))
entry = Word(nums).suppress() + Fragment.ENTITY + Suppress(OneOrMore(Word(alphanums, exact=8)) +
Word(nums + "*") + ZeroOrMore(Word(alphas.upper()) +
Optional(Literal(","))))
# Sections:
# Idx Name ...
section_start = Suppress(Literal("Sections:"))
section_header = Suppress(OneOrMore(Word(alphas)))
# Content is object file line + sections table
content = Group(object + header + Group(ZeroOrMore(entry)).setResultsName("sections"))
# 00 {section} 0000000 ...
# CONTENTS, ALLOC, ....
section_entry = Suppress(Word(nums)) + SkipTo(' ') + Suppress(restOfLine) + \
Suppress(ZeroOrMore(Word(alphas) + Literal(",")) + Word(alphas))
content = Group(object_line + section_start + section_header + Group(OneOrMore(section_entry)).setResultsName("sections"))
parser = Group(ZeroOrMore(content)).setResultsName("contents")
sections_info_text = info.content
results = None
try:
results = parser.parseString(sections_info_text)
results = parser.parseString(info.content, parseAll=True)
except ParseException as p:
raise ParseException("Unable to parse section info file " + info.filename + ". " + p.message)

View File

@ -1,4 +1,4 @@
In archive /home/user/ãóç+ěščřžýáíé/build/esp-idf/freertos/libfreertos.a:
In archive /home/user/build/esp-idf/freertos/libfreertos.a:
FreeRTOS-openocd.c.obj: file format elf32-xtensa-le

View File

@ -0,0 +1,19 @@
In archive /home/user/ãóç+ěščřžýáíé/build/esp-idf/freertos/libsections_parse.a:
croutine.c.obj: file format elf32-littleriscv
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000034 2**0
ALLOC
FreeRTOS-openocd.c.obj: file format elf32-xtensa-le // 'F' should not get included in match for 'CONTENTS, ALLOC, LOAD ...' prior
Sections:
Idx Name Size VMA LMA File off Algn
0 .literal.prvCheckPendingReadyList 00000018 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE

View File

@ -1422,6 +1422,19 @@ entries:
self.assertListEqual(actual["flash_text"], expected["flash_text"])
self.assertListEqual(actual["iram0_text"], expected["iram0_text"])
def test_sections_info_parsing(self):
self.sections_info = SectionsInfo()
with open("data/sections_parse.info") as sections_info_file_obj:
self.sections_info.add_sections_info(sections_info_file_obj)
sections = self.sections_info.get_obj_sections("libsections_parse.a", "croutine")
self.assertEqual(set(sections), set([".text", ".data", ".bss"]))
sections = self.sections_info.get_obj_sections("libsections_parse.a", "FreeRTOS-openocd")
self.assertEqual(set(sections), set([".literal.prvCheckPendingReadyList"]))
if __name__ == "__main__":
unittest.main()