From 23aff378f4b7e558f509b1268fae975d686bb7fa Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Mon, 16 Nov 2020 13:55:22 +0800 Subject: [PATCH] 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. --- tools/ldgen/generation.py | 28 +++++++++++------------ tools/ldgen/test/data/sections.info | 2 +- tools/ldgen/test/data/sections_parse.info | 19 +++++++++++++++ tools/ldgen/test/test_generation.py | 13 +++++++++++ 4 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 tools/ldgen/test/data/sections_parse.info diff --git a/tools/ldgen/generation.py b/tools/ldgen/generation.py index 01e6e51c4b..79ae83342f 100644 --- a/tools/ldgen/generation.py +++ b/tools/ldgen/generation.py @@ -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) diff --git a/tools/ldgen/test/data/sections.info b/tools/ldgen/test/data/sections.info index 860d2163fc..75c699702d 100644 --- a/tools/ldgen/test/data/sections.info +++ b/tools/ldgen/test/data/sections.info @@ -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 diff --git a/tools/ldgen/test/data/sections_parse.info b/tools/ldgen/test/data/sections_parse.info new file mode 100644 index 0000000000..cd2f137e88 --- /dev/null +++ b/tools/ldgen/test/data/sections_parse.info @@ -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 diff --git a/tools/ldgen/test/test_generation.py b/tools/ldgen/test/test_generation.py index 50bed4aee5..72d345ecef 100755 --- a/tools/ldgen/test/test_generation.py +++ b/tools/ldgen/test/test_generation.py @@ -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()