Exemplo n.º 1
0
 def test_nulltable(self):
     st = UnpreparedElfStringTable(None)
     self.assertEqual(st.get_string_idx(0), "")
     self.assertEqual(st.index_of(""), 0)
     self.assertEqual(st.index_of("anything"), None)
     self.assertEqual(st.offset_of(""), 0)
     self.assertEqual(st.offset_of("anything"), None)
     self.assertEqual(st.get_file_data(), array.array('B', '\x00'))
Exemplo n.º 2
0
 def test_fromdata(self):
     data = ByteArray('\0name.\0Variable\0able\0xx\0')
     st = UnpreparedElfStringTable(None, data = data)
     st = st.prepare(0, 0, 0)
     self.assertEqual(len(st.get_strings()), 5)
     self.assertEqual(st.get_string_idx(1), "name.")
     self.assertEqual(st.get_string_idx(2), "Variable")
     self.assertEqual(st.get_string_idx(3), "able")
     self.assertEqual(st.get_string_idx(4), "xx")
     self.assertEqual(st.get_string_ofs(0), "")
     self.assertEqual(st.get_string_ofs(1), "name.")
     self.assertEqual(st.get_string_ofs(7), "Variable")
     self.assertEqual(st.get_string_ofs(11), "able")
     self.assertEqual(st.get_string_ofs(16), "able")                                
     self.assertEqual(st.get_file_data(), data)
Exemplo n.º 3
0
    def test_copy_into(self):
        elf_from = UnpreparedElfFile()
        elf_to = UnpreparedElfFile()

        sect = BaseElfSection(elf_from, "test")
        # FIXME
        #self.assertRaises(NotImplementedError, sect.copy_into, elf_to)

        sect = UnpreparedElfSection(elf_from, "test")
        new_sect = sect.copy_into(elf_to)
        self.assertEquals(sect.name, new_sect.name)
        
        prep_sect = sect.prepare(0, 0, 0)
        # FIXME
        #self.assertRaises(NotImplementedError, prep_sect.copy_into, elf_to)

        sect = UnpreparedElfSection(elf_from, "test", SHT_NOBITS)
        new_sect = sect.copy_into(elf_to)
        self.assertEquals(sect.name, new_sect.name)

        sect = UnpreparedElfStringTable(elf_from, "string")
        strings = ["foo", "bar", "baz"]
        for string in strings:
            sect.add_string(string)
        new_sect = sect.copy_into(elf_to)
        for i in range(len(strings)):
            self.assertEquals(sect.get_string_idx(i), new_sect.get_string_idx(i))
Exemplo n.º 4
0
    def test_prepare_sections(self):        
        empty_sec_seg, full_sec_seg, _, _, _, _ = self._get_segments()

        for seg in [empty_sec_seg, full_sec_seg]:
            all_sections = seg.sections
            sh_string_table = UnpreparedElfStringTable(None)
            ofs = 0x1000
            seg.prepare(ofs)
            seg.prepare_sections(all_sections, sh_string_table)
Exemplo n.º 5
0
 def test_add_symbols(self):
     ef = UnpreparedElfFile()
     sect = UnpreparedElfSection(ef, "test_sect")
     symtab = UnpreparedElfSymbolTable(ef, ".symtab")
     for name in ["foo", "bar"]:
         symtab.add_symbol(ElfSymbol(name, sect))
     
     ef = UnpreparedElfFile()
     sect = UnpreparedElfSection(ef, "test_ect")
     strtab = UnpreparedElfStringTable(ef, ".strtab")
     symtab = UnpreparedElfSymbolTable(ef, ".symtab", link=strtab)
     for name in ["foo", "bar"]:
         symtab.add_symbol(ElfSymbol(name, sect))
Exemplo n.º 6
0
    def add_symbols(self, symbols):
        """
        Add a list of symbols to this files symbol table. If the symbol table
        doesn't exit yet, it will be created.

        symbols: a list of ElfSymbol objects
        """
        symtab = self.get_symbol_table()
        if symtab is None:
            # we need to create a symbol table
            string_table = UnpreparedElfStringTable(self, ".strtab")
            symtab = UnpreparedElfSymbolTable(self,
                                              ".symtab",
                                              link=string_table)
            self.sections.append(string_table)
            self.sections.append(symtab)

        for sym in symbols:
            symtab.add_symbol(sym)
Exemplo n.º 7
0
def main(args):
    """Main program entry point."""

    # We should be able ot use 'elfadorn ld' as a drop-in replacement for 'ld'
    # Here we detect if this is the case, and patch the command line args appropriately.
    # This way we avoid maintainid two different methods of dealing with args
    if "--" not in args:
        args = [args[0] , "--"] + args[1:]

    parser = optparse.OptionParser("%prog [options] -- <linker> [linker_options]",
                                   add_help_option=0)
    parser.add_option("-H", "--help", action="help")
    parser.add_option("-o", "--output", dest="target", metavar="FILE",
                        help="Linker will create FILE.")
    parser.add_option("-f", "--file-segment-list", dest="file_segment_list", metavar="FILE",
                        help="File containing segment names to be added to .segment_names, \
                        one per line")
    parser.add_option("-c", "--cmd-segment-list", dest="cmd_segment_list",
                        help="quoted list of comma separated segment names to be added to .segment_names,")

    parser.add_option("-s", "--create-segments", dest="create_segments", action="store_true",
                        help="Set to enable gathering orphaned sections and placing each in a new segment")

    (options, args) = parser.parse_args(args)



    if not options.target:
        i = 0
        for a in args:
            if a == "-o":
                options.target = args[i+1]
                break
            i = i + 1

        if not options.target:
            print "Error: -o flag must be supplied." 
            sys.exit(1)


    # we need to parse the options
    # we are interested in any -T, --scatter or --script= options
    # plus the ordinary files specified on the command line    
    scripts = get_script_names(args)

    objects = remove_arguments(args)
    linker_name = objects[1]
    objects = objects[2:]

    linker_type = get_linker_name(args, linker_name)
    if linker_type == "rvct":
        if options.create_segments:
            print "Warning: creating segments from sections not applicable to RVCT. Disabling option."
        options.create_segments = False

    # next get section names
    (sections, additional_scripts) = get_section_names(objects)
    scripts = scripts + additional_scripts

    # then get the text of the linker script
    script_text = get_linker_script_text(linker_name, scripts, additional_scripts, [])

    if options.create_segments:
        # get rid of any sections named in the script_text
        mentioned_sections = linker_script_sections(script_text)
        orphaned_sections = sections
        for section in mentioned_sections:
        # Our grammar is not perfect, sometimes it gets confused and gives back *
        # as a section but it is actually a filename
            if section != "*":
                remove_sections_wildcard(orphaned_sections, section)

        # mips-ld treats .reginfo sections somewhat magically, we do not want to treat this
        # as an orphan and create a segment for him, else ld will drop the text data and bss
        # sections completely. Magic.
        if '.reginfo' in orphaned_sections:
            orphaned_sections.remove('.reginfo')



        # work out the new linker command line
        if scripts == []:
            default = get_linker_script_text(args[1], [], [], args[2:])
            open("default.lds", "w").write(default)
            if len(orphaned_sections) != 0:
                args += ["--script=default.lds"]

        # write out an additional linker script file to pass to the linker
        if len(orphaned_sections) != 0:
            write_linker_script(orphaned_sections, "additional.lds")
            additional_scripts.append("additional.lds")
            args += ["--script=additional.lds"]
    else:       
        # if we dont care about these, just say there are none.
        orphaned_sections = []

    # execute the linker
    if os.spawnvp(os.P_WAIT, args[1], args[1:]) != 0:
        sys.exit(1)

    # load the elf file
    elf = UnpreparedElfFile(filename=options.target)
    wordsize = elf.wordsize
    endianess = elf.endianess
    seglist = get_segment_names(options, elf, scripts, linker_type, orphaned_sections)

    # create the string table
    segname_tab = UnpreparedElfStringTable(".segment_names")

    # add the segment names
    for segname in seglist:
        segname = segname.strip()
        segname_tab.add_string("%s" % segname)

    # add the table to the file
    elf.add_section(segname_tab)

    elf = elf.prepare(wordsize, endianess)
    # write the file
    elf.to_filename(options.target)
Exemplo n.º 8
0
 def test_simpletable(self):
     st = UnpreparedElfStringTable(None)
     self.assertEqual(st.add_string("name."), 1)
     self.assertEqual(st.add_string("Variable"), 7)
     self.assertEqual(st.add_string("able"), 16) # this isn't a good test. we don't know it will be at 16, it'd just be obvious. it could also be at 11 or so
     self.assertEqual(st.add_string("xx"), 21)
     self.assertEqual(len(st.get_strings()), 5)
     self.assertEqual(st.get_string_idx(1), "name.")
     self.assertEqual(st.get_string_idx(2), "Variable")
     self.assertEqual(st.get_string_idx(3), "able")
     self.assertEqual(st.get_string_idx(4), "xx")
     self.assertEqual(st.get_string_ofs(0), "")
     self.assertEqual(st.get_string_ofs(1), "name.")
     self.assertEqual(st.get_string_ofs(7), "Variable")
     self.assertEqual(st.get_string_ofs(11), "able")
     self.assertEqual(st.get_string_ofs(16), "able")                                
     self.assertEqual(st.get_file_data(), array.array('B', '\0name.\0Variable\0able\0xx\0'))
Exemplo n.º 9
0
 def test_getstringidx_out_of_bounds(self):
     st = UnpreparedElfStringTable(None)
     self.assertEqual(st.get_string_idx(1), None)
Exemplo n.º 10
0
    def _get_string_tables(self):
        empty_st = UnpreparedElfStringTable(None)
        added_st = UnpreparedElfStringTable(None)
        added_st.add_string("name.")
        added_st.add_string("Variable")
        added_st.add_string("able")
        added_st.add_string("xx")
        data = ByteArray('\0name.\0Variable\0able\0\0xx\0')
        data_st = UnpreparedElfStringTable(None, data = data)

        prep_empty_st = UnpreparedElfStringTable(None)
        prep_added_st = UnpreparedElfStringTable(None)
        prep_added_st.add_string("name.")
        prep_added_st.add_string("Variable")
        prep_added_st.add_string("able")
        prep_added_st.add_string("xx")
        data = ByteArray('\0name.\0Variable\0able\0xx\0')
        prep_data_st = UnpreparedElfStringTable(None, data = data)
        prep_empty_st = prep_empty_st.prepare(1, 2, 3)
        prep_added_st = prep_added_st.prepare(1, 2, 3)
        prep_data_st = prep_data_st.prepare(1, 2, 3)
        return empty_st, added_st, data_st, prep_empty_st, prep_added_st, prep_data_st
Exemplo n.º 11
0
 def __init__(self, elffile):
     UnpreparedElfStringTable.__init__(self, elffile, ".segment_names")
Exemplo n.º 12
0
def main(args):
    """Main program entry point."""

    # We should be able ot use 'elfadorn ld' as a drop-in replacement for 'ld'
    # Here we detect if this is the case, and patch the command line args appropriately.
    # This way we avoid maintainid two different methods of dealing with args
    if "--" not in args:
        args = [args[0], "--"] + args[1:]

    parser = optparse.OptionParser(
        "%prog [options] -- <linker> [linker_options]", add_help_option=0)
    parser.add_option("-H", "--help", action="help")
    parser.add_option("-o",
                      "--output",
                      dest="target",
                      metavar="FILE",
                      help="Linker will create FILE.")
    parser.add_option(
        "-f",
        "--file-segment-list",
        dest="file_segment_list",
        metavar="FILE",
        help="File containing segment names to be added to .segment_names, \
                        one per line")
    parser.add_option(
        "-c",
        "--cmd-segment-list",
        dest="cmd_segment_list",
        help=
        "quoted list of comma separated segment names to be added to .segment_names,"
    )

    parser.add_option(
        "-s",
        "--create-segments",
        dest="create_segments",
        action="store_true",
        help=
        "Set to enable gathering orphaned sections and placing each in a new segment"
    )

    (options, args) = parser.parse_args(args)

    if not options.target:
        i = 0
        for a in args:
            if a == "-o":
                options.target = args[i + 1]
                break
            i = i + 1

        if not options.target:
            print "Error: -o flag must be supplied."
            sys.exit(1)

    # we need to parse the options
    # we are interested in any -T, --scatter or --script= options
    # plus the ordinary files specified on the command line
    scripts = get_script_names(args)

    objects = remove_arguments(args)
    linker_name = objects[1]
    objects = objects[2:]

    linker_type = get_linker_name(args, linker_name)
    if linker_type == "rvct":
        if options.create_segments:
            print "Warning: creating segments from sections not applicable to RVCT. Disabling option."
        options.create_segments = False

    # next get section names
    (sections, additional_scripts) = get_section_names(objects)
    scripts = scripts + additional_scripts

    # then get the text of the linker script
    script_text = get_linker_script_text(linker_name, scripts,
                                         additional_scripts, [])

    if options.create_segments:
        # get rid of any sections named in the script_text
        mentioned_sections = linker_script_sections(script_text)
        orphaned_sections = sections
        for section in mentioned_sections:
            # Our grammar is not perfect, sometimes it gets confused and gives back *
            # as a section but it is actually a filename
            if section != "*":
                remove_sections_wildcard(orphaned_sections, section)

        # mips-ld treats .reginfo sections somewhat magically, we do not want to treat this
        # as an orphan and create a segment for him, else ld will drop the text data and bss
        # sections completely. Magic.
        if '.reginfo' in orphaned_sections:
            orphaned_sections.remove('.reginfo')

        # work out the new linker command line
        if scripts == []:
            default = get_linker_script_text(args[1], [], [], args[2:])
            open("default.lds", "w").write(default)
            if len(orphaned_sections) != 0:
                args += ["--script=default.lds"]

        # write out an additional linker script file to pass to the linker
        if len(orphaned_sections) != 0:
            write_linker_script(orphaned_sections, "additional.lds")
            additional_scripts.append("additional.lds")
            args += ["--script=additional.lds"]
    else:
        # if we dont care about these, just say there are none.
        orphaned_sections = []

    # execute the linker
    if os.spawnvp(os.P_WAIT, args[1], args[1:]) != 0:
        sys.exit(1)

    # load the elf file
    elf = UnpreparedElfFile(filename=options.target)
    wordsize = elf.wordsize
    endianess = elf.endianess
    seglist = get_segment_names(options, elf, scripts, linker_type,
                                orphaned_sections)

    # create the string table
    segname_tab = UnpreparedElfStringTable(".segment_names")

    # add the segment names
    for segname in seglist:
        segname = segname.strip()
        segname_tab.add_string("%s" % segname)

    # add the table to the file
    elf.add_section(segname_tab)

    elf = elf.prepare(wordsize, endianess)
    # write the file
    elf.to_filename(options.target)
Exemplo n.º 13
0
 def __init__(self, elffile):
     UnpreparedElfStringTable.__init__(self, elffile, ".segment_names")