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)
def run_adorn(linker_cmd, target=None, create_segments=False, file_segment_list=None, cmd_segment_list=None): """ The programming interface to elf adorn. linker_cmd: A list of strings representing the linker command to be executed target: A target file into which to place the final output. If not specified, a "-o" option is expected in the linker_cmd create_segment: A boolean indicating whether orphaned sections should be gathered and each placed in a new segment file_segment_list: The filename of a file containing segment names to be added to .segment_names. (Mutually exclusive with cmd_segment_list, this takes precedence if both given) cmd_segment_list: A list of segment names to be added to .segment_names. (Mutually exclusive with file_segment_names) """ (linker_name, linker_args, linker_type, scripts, object_files) = _parse_linker_cmd(linker_cmd) target = _get_target(target, linker_args) if linker_type == "rvct": if create_segments: print "Warning: creating segments from sections not applicable " \ "to RVCT. Disabling option." create_segments = False # segments specifed in a file if file_segment_list: segfile = open(file_segment_list, 'r') seglist = segfile.readlines() # segments specified on command line elif cmd_segment_list: seglist = cmd_segment_list else: seglist = None # next get section names (sections, additional_scripts) = get_section_names(object_files) scripts += additional_scripts # then get the text of the linker script # FIXME: why no linker args? script_text = get_linker_script_text(linker_name, scripts, additional_scripts, []) if 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(linker_name, [], [], linker_args) open("default.lds", "w").write(default) scripts.append("default.lds") if len(orphaned_sections) != 0: linker_cmd += ["--script=default.lds"] # write out an additional linker script file to pass to the linker if orphaned_sections: write_linker_script(orphaned_sections, "additional.lds") scripts.append("additional.lds") linker_cmd += ["--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, linker_name, linker_cmd) != 0: sys.exit(1) _update_elf_file(target, seglist, scripts, linker_type, orphaned_sections)
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)