Ejemplo n.º 1
0
    def test_equivalent_conditional_fragment(self):
        test_fragment1 = self.create_fragment_file(u"""
if A = y:
    [sections:test1]
    entries:
        value_1
else:
    [sections:test2]
    entries:
        value_2
""")
        fragment_file1 = parse_fragment_file(test_fragment1, self.sdkconfig)

        self.assertEqual(fragment_file1.fragments[0].name, 'test1')
        self.assertEqual(fragment_file1.fragments[0].entries, {'value_1'})

        test_fragment2 = self.create_fragment_file(u"""
[sections:test1]
entries:
    if A = y:
        value_1
    else:
        value_2
""")
        fragment_file2 = parse_fragment_file(test_fragment2, self.sdkconfig)

        self.assertEqual(fragment_file2.fragments[0].name, 'test1')
        self.assertEqual(fragment_file2.fragments[0].entries, {'value_1'})
Ejemplo n.º 2
0
    def test_unsupported_key(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
key_1:
    value_a
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 3
0
    def test_improper_grammar(self):
        test_fragment = self.create_fragment_file(u"""
[scheme:test]
entries:
    sections1, target1 # improper separator
""")

        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 4
0
    def test_settings_unmatch_indent(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
 value_1
  value_2 # first element dictates indent
  value_3
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 5
0
    def test_flags_entries_multiple_flags_and_entries(self):
        # Not an error, generation step handles this, since
        # it that step has a more complete information
        # about all mappings. This can happen across multiple
        # mapping fragments.
        test_fragment = self.create_fragment_file(u"""
[mapping:map]
archive: libmain.a
entries:
    obj1 (default);
        text->flash_text ALIGN(4) KEEP() SURROUND(sym1) SORT(name)
    obj1 (default);
        text->flash_text ALIGN(4) KEEP() SURROUND(sym1) SORT(name)
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        fragment = fragment_file.fragments[0]

        expected = [
            Flag('text', 'flash_text', [
                Align(4, True, False),
                Keep(),
                Surround('sym1'),
                Sort('name')
            ]),
            Flag('text', 'flash_text', [
                Align(4, True, False),
                Keep(),
                Surround('sym1'),
                Sort('name')
            ])
        ]
        actual = fragment.flags[('obj1', None, 'default')]
        self.assertEqual(expected, actual)
Ejemplo n.º 6
0
    def test_empty_entries(self):
        test_fragment = self.create_fragment_file(u"""
[scheme:test]
entries:
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[scheme:test]
entries:
    if B = y:
        sections1 -> target1
""")
        with self.assertRaises(ParseFatalException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 7
0
    def test_flag_order(self):
        # Test that the order in which the flags are specified is retained
        test_fragment = self.create_fragment_file(u"""
[mapping:map]
archive: libmain.a
entries:
    obj1 (default);
        text->flash_text ALIGN(4) KEEP() SURROUND(sym1) ALIGN(8) SORT(name),
        rodata->flash_rodata KEEP() ALIGN(4) KEEP() SURROUND(sym1) ALIGN(8) ALIGN(4) SORT(name)
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        fragment = fragment_file.fragments[0]

        expected = [
            Flag('text', 'flash_text', [
                Align(4, True, False),
                Keep(),
                Surround('sym1'),
                Align(8, True, False),
                Sort('name')
            ]),
            Flag('rodata', 'flash_rodata', [
                Keep(),
                Align(4, True, False),
                Keep(),
                Surround('sym1'),
                Align(8, True, False),
                Align(4, True, False),
                Sort('name')
            ])
        ]
        actual = fragment.flags[('obj1', None, 'default')]
        self.assertEqual(expected, actual)
Ejemplo n.º 8
0
    def test_sort_flag(self):
        # Test parsing combinations and orders of flags
        test_fragment = self.create_fragment_file(u"""
[mapping:map]
archive: libmain.a
entries:
    obj1 (default);
        text->flash_text SORT(name),
        rodata->flash_rodata SORT(alignment),
        data->dram0_data SORT(init_priority),
        bss->dram0_bss SORT(name, alignment),
        common->dram0_bss SORT(alignment, name),
        iram->iram0_text SORT(name, name),
        dram->dram0_data SORT(alignment, alignment)
""")

        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        fragment = fragment_file.fragments[0]

        expected = [
            Flag('text', 'flash_text', [Sort('name')]),
            Flag('rodata', 'flash_rodata', [Sort('alignment')]),
            Flag('data', 'dram0_data', [Sort('init_priority')]),
            Flag('bss', 'dram0_bss', [Sort('name', 'alignment')]),
            Flag('common', 'dram0_bss', [Sort('alignment', 'name')]),
            Flag('iram', 'iram0_text', [Sort('name', 'name')]),
            Flag('dram', 'dram0_data', [Sort('alignment', 'alignment')])
        ]
        actual = fragment.flags[('obj1', None, 'default')]
        self.assertEqual(expected, actual)
Ejemplo n.º 9
0
    def test_basic(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    .section1
    .section2
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual(fragment_file.fragments[0].entries,
                         {'.section1', '.section2'})
Ejemplo n.º 10
0
    def test_archive_allowed_names(self):
        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive:
    libstdc++.a
entries:
    * (default)
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual('libstdc++.a', fragment_file.fragments[0].archive)
Ejemplo n.º 11
0
    def test_archive(self):
        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive:
entries:
    * (default)
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive:
    lib1.a
    lib2.a
entries:
    * (default)
""")
        with self.assertRaises(ParseFatalException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 12
0
    def test_out_of_order_conditional(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    elif B = y:
        value_1
    else:
        value_2
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    else:
        value_2
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 13
0
    def test_basic(self):
        test_fragment = self.create_fragment_file(u"""
[scheme:test]
entries:
    sections1 -> target1
    sections2 -> target2
""")

        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual(fragment_file.fragments[0].entries,
                         {('sections1', 'target1'), ('sections2', 'target2')})
Ejemplo n.º 14
0
    def test_align_flag(self):
        # Test parsing combinations and orders of flags
        test_fragment = self.create_fragment_file(u"""
[mapping:map]
archive: libmain.a
entries:
    obj1 (default);
        text->flash_text ALIGN(8),
        rodata->flash_rodata ALIGN(8, pre),
        data->dram0_data ALIGN(8, pre, post),
        bss->dram0_bss ALIGN(8, post),
        common->dram0_bss ALIGN(8, pre, post) ALIGN(8)
""")

        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        fragment = fragment_file.fragments[0]

        expected = [
            Flag('text', 'flash_text', [Align(8, True, False)]),
            Flag('rodata', 'flash_rodata', [Align(8, True, False)]),
            Flag('data', 'dram0_data', [Align(8, True, True)]),
            Flag('bss', 'dram0_bss', [Align(8, False, True)]),
            Flag('common', 'dram0_bss',
                 [Align(8, True, True),
                  Align(8, True, False)])
        ]
        actual = fragment.flags[('obj1', None, 'default')]

        self.assertEqual(expected, actual)

        # Wrong post, pre order
        test_fragment = self.create_fragment_file(u"""
[mapping:map]
archive: libmain.a
entries:
    obj1 (noflash)
        text->iram0_text ALIGN(8, post, pre)
""")

        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 15
0
    def test_setting_indent(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
 value_1
 value_2
 value_3
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        self.assertEqual(fragment_file.fragments[0].name, 'test')
        self.assertEqual(fragment_file.fragments[0].entries,
                         {'value_1', 'value_2', 'value_3'})
Ejemplo n.º 16
0
    def test_duplicate_entries(self):
        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive:
    lib.a
entries:
    obj:symbol (noflash)
    obj:symbol (noflash)
""")

        expected = {('obj', 'symbol', 'noflash')}

        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual(expected, fragment_file.fragments[0].entries)
Ejemplo n.º 17
0
    def test_surround_flag(self):
        # Test parsing combinations and orders of flags
        test_fragment = self.create_fragment_file(u"""
[mapping:map]
archive: libmain.a
entries:
    obj1 (default);
        text->flash_text SURROUND(sym1)
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        fragment = fragment_file.fragments[0]

        expected = [Flag('text', 'flash_text', [Surround('sym1')])]
        actual = fragment.flags[('obj1', None, 'default')]
        self.assertEqual(expected, actual)
Ejemplo n.º 18
0
    def test_empty_entries(self):
        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive:
    lib.a
entries:
    if B = y:
        * (noflash) # if condition is false, then no 'entries' key value
""")

        expected = set()

        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual(expected, fragment_file.fragments[0].entries)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive:
    lib.a
entries:
""")

        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 19
0
    def test_basic(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    value_1
    value_2 # comments should be ignored
    value_3
# this is a comment as well
    value_a
# this is the last comment
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        self.assertEqual(fragment_file.fragments[0].name, 'test')
        self.assertEqual(fragment_file.fragments[0].entries,
                         {'value_1', 'value_2', 'value_3', 'value_a'})
Ejemplo n.º 20
0
    def test_entries_grammar(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    _valid1
    valid2.
    .valid3_-
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual(fragment_file.fragments[0].entries,
                         {'_valid1', 'valid2.', '.valid3_-'})

        # invalid starting char
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    1invalid
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    -invalid
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        # + notation
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    valid+
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual(fragment_file.fragments[0].entries, {'valid+'})

        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    inva+lid+
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 21
0
    def test_multiple_fragments(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test1]
entries:
    value_1

[scheme:test2]
entries:
    section -> target
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        self.assertEqual(fragment_file.fragments[0].name, 'test1')
        self.assertEqual(fragment_file.fragments[0].entries, {'value_1'})
        self.assertEqual(fragment_file.fragments[1].name, 'test2')
        self.assertEqual(fragment_file.fragments[1].entries,
                         {('section', 'target')})
Ejemplo n.º 22
0
    def test_keep_flag(self):
        # Test parsing combinations and orders of flags
        test_fragment = self.create_fragment_file(u"""
[mapping:map]
archive: libmain.a
entries:
    obj1 (default);
        text->flash_text KEEP(),
        rodata->flash_rodata KEEP() KEEP()
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        fragment = fragment_file.fragments[0]

        expected = [
            Flag('text', 'flash_text', [Keep()]),
            Flag('rodata', 'flash_rodata', [Keep(), Keep()])
        ]
        actual = fragment.flags[('obj1', None, 'default')]

        self.assertEqual(expected, actual)
Ejemplo n.º 23
0
    def test_whole_conditional_fragment(self):
        test_fragment = self.create_fragment_file(u"""
if B = y:
    [sections:test1]
    entries:
        value_1
else:
    [sections:test2]
    entries:
        value_2

    if A = y:
        [sections:test3]
        entries:
            value_3
            if C = y:
                value_6

    [sections:test4]
    entries:
        value_4

[sections:test5]
entries:
    value_5
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        self.assertEqual(len(fragment_file.fragments), 4)
        self.assertEqual(fragment_file.fragments[0].name, 'test2')
        self.assertEqual(fragment_file.fragments[0].entries, {'value_2'})
        self.assertEqual(fragment_file.fragments[1].name, 'test3')
        self.assertEqual(fragment_file.fragments[1].entries,
                         {'value_3', 'value_6'})
        self.assertEqual(fragment_file.fragments[2].name, 'test4')
        self.assertEqual(fragment_file.fragments[2].entries, {'value_4'})
        self.assertEqual(fragment_file.fragments[3].name, 'test5')
        self.assertEqual(fragment_file.fragments[3].entries, {'value_5'})
Ejemplo n.º 24
0
    def test_conditional(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    value_1
    if A = y:
        value_2
    value_3
    if A = n:
        value_4
    if B = n:
        value_5
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        self.assertEqual(fragment_file.fragments[0].name, 'test')
        self.assertEqual(fragment_file.fragments[0].entries,
                         {'value_1', 'value_2', 'value_3', 'value_5'})

        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    value_1
    if B = y:
        value_2
    elif C = y:
        value_3
    elif A = y:
        value_4
    else:
        value_5
    value_6
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        self.assertEqual(fragment_file.fragments[0].name, 'test')
        self.assertEqual(fragment_file.fragments[0].entries,
                         {'value_1', 'value_3', 'value_6'})

        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    value_1
    if A = y:
        value_2
        if B = y:
            value_3
        else:
            value_4
            if C = y:
                value_5
            value_6
        value_7
""")
        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)

        self.assertEqual(fragment_file.fragments[0].name, 'test')
        self.assertEqual(
            fragment_file.fragments[0].entries,
            {'value_1', 'value_2', 'value_4', 'value_5', 'value_6', 'value_7'})

        test_fragment = self.create_fragment_file(u"""
[sections:test]
entries:
    if A = n:
        value_2
""")
        with self.assertRaises(ParseFatalException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 25
0
    def test_invalid_grammar(self):
        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive:
    lib.a
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
entries:
    * (default)
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive: lib.a
entries:
    obj: (noflash)
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive: lib.a
entries:
    obj: ()
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive: lib.a
entries:
    obj:symbol
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive: lib.a
entries:
    (noflash)
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive: lib.a
entries:
    obj:* (noflash)
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive: lib.a
entries:
    :symbol (noflash)
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)

        test_fragment = self.create_fragment_file(u"""
[mapping:test]
archive: lib.a
entries:
    *:symbol (noflash)
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)
Ejemplo n.º 26
0
    def test_empty_file(self):
        test_fragment = self.create_fragment_file(u"""
""")

        fragment_file = parse_fragment_file(test_fragment, self.sdkconfig)
        self.assertEqual(len(fragment_file.fragments), 0)
Ejemplo n.º 27
0
def main():

    argparser = argparse.ArgumentParser(
        description='ESP-IDF linker script generator')

    argparser.add_argument('--input',
                           '-i',
                           help='Linker template file',
                           type=argparse.FileType('r'))

    fragments_group = argparser.add_mutually_exclusive_group()

    fragments_group.add_argument('--fragments',
                                 '-f',
                                 type=argparse.FileType('r'),
                                 help='Input fragment files',
                                 nargs='+')

    fragments_group.add_argument(
        '--fragments-list',
        help='Input fragment files as a semicolon-separated list',
        type=str)

    argparser.add_argument(
        '--libraries-file',
        type=argparse.FileType('r'),
        help='File that contains the list of libraries in the build')

    argparser.add_argument('--output',
                           '-o',
                           help='Output linker script',
                           type=str)

    argparser.add_argument('--config', '-c', help='Project configuration')

    argparser.add_argument('--kconfig', '-k', help='IDF Kconfig file')

    argparser.add_argument(
        '--check-mapping',
        help='Perform a check if a mapping (archive, obj, symbol) exists',
        action='store_true')

    argparser.add_argument('--check-mapping-exceptions',
                           help='Mappings exempted from check',
                           type=argparse.FileType('r'))

    argparser.add_argument(
        '--env',
        '-e',
        action='append',
        default=[],
        help='Environment to set when evaluating the config file',
        metavar='NAME=VAL')

    argparser.add_argument(
        '--env-file',
        type=argparse.FileType('r'),
        help='Optional file to load environment variables from. Contents '
        'should be a JSON object where each key/value pair is a variable.')

    argparser.add_argument('--objdump', help='Path to toolchain objdump')

    args = argparser.parse_args()

    input_file = args.input
    libraries_file = args.libraries_file
    config_file = args.config
    output_path = args.output
    kconfig_file = args.kconfig
    objdump = args.objdump

    fragment_files = []
    if args.fragments_list:
        fragment_files = args.fragments_list.split(';')
    elif args.fragments:
        fragment_files = args.fragments

    check_mapping = args.check_mapping
    if args.check_mapping_exceptions:
        check_mapping_exceptions = [
            line.strip() for line in args.check_mapping_exceptions
        ]
    else:
        check_mapping_exceptions = None

    try:
        sections_infos = EntityDB()
        for library in libraries_file:
            library = library.strip()
            if library:
                new_env = os.environ.copy()
                new_env['LC_ALL'] = 'C'
                dump = StringIO(
                    subprocess.check_output([objdump, '-h', library],
                                            env=new_env).decode())
                dump.name = library
                sections_infos.add_sections_info(dump)

        generation_model = Generation(check_mapping, check_mapping_exceptions)

        _update_environment(
            args)  # assign args.env and args.env_file to os.environ

        sdkconfig = SDKConfig(kconfig_file, config_file)

        for fragment_file in fragment_files:
            try:
                fragment_file = parse_fragment_file(fragment_file, sdkconfig)
            except (ParseException, ParseFatalException) as e:
                # ParseException is raised on incorrect grammar
                # ParseFatalException is raised on correct grammar, but inconsistent contents (ex. duplicate
                # keys, key unsupported by fragment, unexpected number of values, etc.)
                raise LdGenFailure('failed to parse %s\n%s' %
                                   (fragment_file, str(e)))
            generation_model.add_fragments_from_file(fragment_file)

        mapping_rules = generation_model.generate(sections_infos)

        script_model = LinkerScript(input_file)
        script_model.fill(mapping_rules)

        with tempfile.TemporaryFile('w+') as output:
            script_model.write(output)
            output.seek(0)

            if not os.path.exists(os.path.dirname(output_path)):
                try:
                    os.makedirs(os.path.dirname(output_path))
                except OSError as exc:
                    if exc.errno != errno.EEXIST:
                        raise

            with open(
                    output_path, 'w'
            ) as f:  # only create output file after generation has suceeded
                f.write(output.read())
    except LdGenFailure as e:
        print('linker script generation failed for %s\nERROR: %s' %
              (input_file.name, e))
        sys.exit(1)
Ejemplo n.º 28
0
    def test_empty_fragment(self):
        test_fragment = self.create_fragment_file(u"""
[sections:test]
""")
        with self.assertRaises(ParseException):
            parse_fragment_file(test_fragment, self.sdkconfig)