def test_output(self): # Test the kernel before weaving. out = StringIO() elf = PreparedElfFile(filename="data/eg_weave/l4kernel") kcp = find_kernel_config(elf) kcp.output(out) # Test the kernel in a build image. out = StringIO() elf = PreparedElfFile(filename="data/eg_weave/image_ia32.elf") kcp = find_kernel_config(elf) kcp.output(out)
def test_remove_nobits(self): for file_name in ["data/null_elf", "data/arm_exec", "data/arm_stripped_exec", "data/arm_exec_nosect", "data/arm_object", "data/mips64_exec", "data/mips32_exec", "data/ia32_exec", "data/amd64_exec", "data/ia64_exec", ]: ef = PreparedElfFile(filename=file_name) if ef.segments: seg_sizes = [] for segment in ef.segments: seg_sizes.append((segment.get_memsz(), segment.get_filesz())) ef.remove_nobits() for segment, seg_size in zip(ef.segments, seg_sizes): self.assertEqual(segment.get_memsz(), segment.get_filesz()) self.assertEqual(segment.get_memsz(), seg_size[0]) ef = UnpreparedElfFile() sec = UnpreparedElfSection(None, section_type=SHT_NOBITS, data=10) self.assertEqual(sec.get_size(), 10) ef.add_section(sec) ef.remove_nobits() sec = ef.sections[1] self.assertEqual(sec.type, SHT_PROGBITS) self.assertEqual(sec.get_size(), 10) self.assertEqual(sec.get_file_data(), ByteArray('\0' * 10))
def test_find_section_named(self): ef = PreparedElfFile(filename="data/arm_exec") sect = ef.find_section_named(".kip") self.assertEqual(sect.name, ".kip") sect = ef.find_section_named("notexist") self.assertEqual(sect, None)
def test_get_first_paddr(self): for filename in elf_address: ef = PreparedElfFile(filename=filename) if elf_address[filename][3] is None: self.assertRaises(InvalidArgument, ef.get_first_addr, "physical") else: self.assertEqual(ef.get_first_addr("physical"), elf_address[filename][3])
def test_set_config(self): kconfig = find_kernel_config( PreparedElfFile(filename="data/eg_weave/l4kernel")) kconfig.set_config("spaces", 10) kconfig.set_config("mutexes", 10) kconfig.set_config("root_caps", 10) self.assertRaises(weaver.MergeError, kconfig.set_config, "unknown", 10)
def test_lots_memory_descriptor(self): """Add more descriptors than are allowed in the outout image.""" kconfig = find_kernel_config( PreparedElfFile(filename="data/eg_weave/l4kernel")) for i in range(0x1000, 0x600000, 0x20000): kconfig.add_meminfo(0x1, 0x2, True, i, i + 0x1000) self.assertRaises(weaver.MergeError, kconfig.update_data)
def test_find_segment_by_vaddr(self): ef = PreparedElfFile(filename="data/arm_exec") seg = ef.find_segment_by_vaddr(0xf0001000L) self.assertEqual(0xf0001000L in seg.get_span(), True) seg = ef.find_segment_by_vaddr(0xa0001000L) self.assertEqual(seg, None)
def test_get_address_span(self): for fn in elf_address: ef = PreparedElfFile(filename=fn) self.assertEqual( ef.get_address_span(), elf_address[fn][0] - elf_address[fn][2], "%s 0x%x != 0x%x" % (fn, ef.get_address_span(), elf_address[fn][0] - elf_address[fn][2]))
def test_add_memory_descriptor(self): kconfig = find_kernel_config( PreparedElfFile(filename="data/eg_weave/l4kernel")) kconfig.add_meminfo(0x1, 0x2, True, 0x1000, 0x2000) # This will merge with the previous descriptor. kconfig.add_meminfo(0x1, 0x2, True, 0x3000, 0x4000) kconfig.add_mem_descriptor( MemoryDescriptor(0x1, 0x2, True, 0x1000, 0x2000))
def test_find_symbol(self): ef = PreparedElfFile(filename="data/arm_exec") self.assertEquals(ef.find_symbol("notexistant"), None) sym = ef.find_symbol("do_ipc_copy") self.assertEqual(sym.name, "do_ipc_copy") sym = ef.find_symbol("_end_kip") self.assertEqual(sym.name, "_end_kip")
def test_lots_add_mapping(self): """Add more mappings than are allowed in the outout image.""" kconfig = find_kernel_config( PreparedElfFile(filename="data/eg_weave/l4kernel")) for i in range(0, 10): kconfig.add_mapping((0x1000, 0x100000, 0x4000)) self.assertRaises(weaver.MergeError, kconfig.update_data)
def test_init(self): for fn in elf_address: ef = PreparedElfFile(filename=fn) ef.init_and_prepare_from_filename(fn) if not ef.sections: continue for section in ef.sections: for symbols in section.symbols: pass
def test_print_headers_summary(self): for fn in expected_output: output = StringIO() elf = PreparedElfFile(filename=fn) weaver.display.print_sheaders(elf, True, output) expected_data = open("%s.readelf.S" % fn).read() #self.assertEquals(output.getvalue(), expected_data, # "Failed on: %s Got: \n%s \nExpected: \n%s" % (fn, output.getvalue(), expected_data)) output.close()
def test_get_address_span_phys(self): for filename in elf_address: ef = PreparedElfFile(filename=filename) if elf_address[filename][1] is None: self.assertRaises(InvalidArgument, ef.get_last_addr, "physical") else: self.assertEqual(ef.get_address_span("physical"), elf_address[filename][1] - elf_address[filename][3], "%s 0x%x != 0x%x" % (filename, ef.get_address_span(), elf_address[filename][1] - elf_address[filename][3]))
def test_get_last_paddr(self): for fn in elf_address: ef = PreparedElfFile(filename=fn) if elf_address[fn][1] is None: self.assertRaises(InvalidArgument, ef.get_last_addr, "physical") else: self.assertEqual( ef.get_last_addr("physical"), elf_address[fn][1], "%s 0x%x != 0x%x" % (fn, ef.get_last_addr("physical"), elf_address[fn][1]))
def test_round_trip(self): for file_name in ["data/null_elf", "data/arm_exec", "data/arm_stripped_exec", "data/arm_exec_nosect", "data/arm_object", "data/arm_scatter_load", "data/mips64_exec", "data/mips32_exec", "data/ia32_exec", "data/amd64_exec", "data/ia64_exec", ]: ef = PreparedElfFile(filename=file_name) ef.to_filename("elf.tmp") # FIXME # self.assertEqual(open("elf.tmp", "rb").read(), open(file_name, "rb").read(), "%s: failed to read back correctly" % file_name) os.remove("elf.tmp")
def get_section_names(objects): sections = [] not_elf = [] for obj in objects: try: elf = PreparedElfFile(filename=obj) for section in elf.sections: if section.name not in sections: if section.flags & SHF_ALLOC: sections.append(section.name) except ElfFormatError: # some toolchains pass libgcc here, which shouldn't be treated as an # additional linker script, as not_elf is destined to be if not obj.endswith(".a"): not_elf.append(obj) return (sections, not_elf)
def check_segment_addr(self, xml_filename, elf_filename): parsed_elf = PreparedElfFile(filename=elf_filename) elf_paddrs = [] for segment in parsed_elf.segments: elf_paddrs.append(segment.paddr) parsed_xml = weaver.parse_spec.parse_spec_xml(xml_filename) mergable_elements = [ elm for elm in parsed_xml.children if elm.tag in ["kernel", "rootprogram", "program"] ] segment_elements = {} for elm in mergable_elements: for elm_segchild in elm.find_children("segment"): if hasattr(elm, "name"): segment_elements[elm_segchild] = elm.name else: segment_elements[elm_segchild] = elm.tagname xml_paddrs = [elm.phys_addr for elm in segment_elements.keys()] xml_paddrs.sort() elf_paddrs.sort() if xml_paddrs == elf_paddrs: return segment_elements, parsed_elf xml_paddrs_copy = [] + xml_paddrs for x_paddr in xml_paddrs_copy: for e_paddr in elf_paddrs: if e_paddr == x_paddr: elf_paddrs.remove(e_paddr) xml_paddrs.remove(x_paddr) break if (len(elf_paddrs) and (len(xml_paddrs) == 0)): raise weaver.merge.MergeError, "Too many segments in elf file" if (len(xml_paddrs) and (len(elf_paddrs) == 0)): raise weaver.merge.MergeError, "Missing segments in elf file" if (len(xml_paddrs) and len(elf_paddrs)): raise weaver.merge.MergeError, "Non matching segment physical address between elf and xml files" raise weaver.merge.MergeError, "Should not be here"
def test_from_file(self): for filename in elf_address: ef = PreparedElfFile(filename=filename) # self.assertEqual(len(ef.sections), elf_address[filename][4]) self.assertEqual(len(ef.segments), elf_address[filename][5])
def print_cmd(args): """Display an ELF file. args contains command line arguments passed from sys.argv. These are parsed using option parser.""" parser = OptionParser("%prog print [options] file", add_help_option=0) parser.add_option("-H", "--help", action="help") parser.add_option("-a", "--all", action="store_true", dest="all", help="Print all information") parser.add_option("-h", "--header", action="store_true", dest="header", help="Print ELF header") parser.add_option("-l", "--pheaders", action="store_true", dest="pheaders", help="Print ELF sections headers") parser.add_option("-S", "--sheaders", action="store_true", dest="sheaders", help="Print ELF sections headers") parser.add_option("-k", "--kconfig", action="store_true", dest="kconfig", help="Print L4 kernel config data structure (Default)") parser.add_option("-B", "--bootinfo", action="store_true", dest="bootinfo", help="Print L4 Bootinfo") parser.add_option("-s", "--segnames", action="store_true", dest="segnames", help="Print segment names") (options, args) = parser.parse_args(args) if len(args) != 1: parser.error("incorrect number of arguments") if options.all: options.header = options.pheaders = options.sheaders = \ options.kconfig = options.bootinfo = True elf = PreparedElfFile(filename=args[0]) if options.header: elf.get_elf_header().output(sys.stdout) if options.sheaders: print_sheaders(elf, not options.header, sys.stdout) if options.pheaders: print_pheaders(elf, not options.header, sys.stdout) if options.kconfig: print kconfig = find_kernel_config(elf) if kconfig: kconfig.output(sys.stdout) else: print "There is no kernel configuration in this file." if options.bootinfo: print bootinfo = find_bootinfo(elf) if bootinfo: bootinfo.output(sys.stdout) else: print "There is no Bootinfo section in this file." if options.segnames: print segnames = get_segnames(elf) if segnames: for segname in segnames.strings: idx = segname.index('\x00') segname = segname[:idx] segname = segname.strip() if segname == "": continue print segname else: # TODO - use the first section in each segment # as the segment name and print that. print "There is no .segnames section in this file" return 0
def collect_pd_element(pd_el, ignore_name, namespace, image, machine, bootinfo, pools): """Collect the attributes of a PD element.""" # New namespace for objects living in the PD. pd_namespace = namespace.add_namespace(pd_el.name) pd = weaver.bootinfo.PD(pd_el.name, pd_namespace, image, machine, pools) virtpool = getattr(pd_el, 'virtpool', None) physpool = getattr(pd_el, 'physpool', None) direct = getattr(pd_el, 'direct', None) pd.set_platform_control(getattr(pd_el, "platform_control", False)) if hasattr(pd_el, 'pager'): pager = make_pager_attr(pd_el.pager) else: pager = None # Push the overriding attributes for the pd. image.push_attrs(virtual = virtpool, physical = physpool, pager = pager, direct = direct) pd.set_default_pools(image, bootinfo) # Collect the object environment env = collect_environment_element(pd_el.find_child('environment'), pd_namespace, machine, pools, image, bootinfo) if hasattr(pd_el, "file"): elf = PreparedElfFile(filename=pd_el.file) if elf.elf_type != ET_EXEC: raise MergeError, "All the merged ELF files must be of EXEC type." segment_els = pd_el.find_all_children("segment") segs = collect_elf_segments(elf, image.PROGRAM, segment_els, pd_el.name, pd_namespace, image, machine, pools) segs_ms = [bootinfo.record_segment_info(pd_el.name, seg, image, machine, pools) for seg in segs] for seg_ms in segs_ms: pd.attach_memsection(seg_ms) # Record any patches being made to the program. patch_els = pd_el.find_children("patch") collect_patches(elf, patch_els, image) # Collect threads in the PD. for thread_el in pd_el.find_children('thread'): if not ignore_name.match(thread_el.name): thread = collect_thread(elf, thread_el, ignore_name, pd_namespace, image, machine, pools, entry = "_thread_start") pd.add_thread(thread) # Record the thread and its stack in the environment. env.add_entry(key = thread.get_name(), cap_name = thread.get_name() + '/master') env.add_entry(key = thread.get_name() + "/STACK", cap_name = thread.get_name() + '/stack/master', attach = thread.get_stack().get_attrs().attach) # Collect memsections in the PD. for ms_el in pd_el.find_children('memsection'): if not ignore_name.match(ms_el.name): ms = collect_memsection_element(ms_el, ignore_name, pd_namespace, image, machine, pools) pd.attach_memsection(ms) image.add_group(0, [ms.get_ms()]) env.add_entry(key = ms.get_name(), cap_name = ms.get_name() + '/master', attach = ms.get_attrs().attach) # Collect any zones in the program. for zone_el in pd_el.find_children('zone'): (zone, non_zone_ms) = \ collect_zone_element(zone_el, ignore_name, pd_namespace, pools, image, bootinfo, machine) pd.attach_zone(zone) # Attach zones that aren't part of the zone to the program. for ms in non_zone_ms: pd.attach_memsection(ms) image.add_group(0, [ms.get_ms()]) env.add_entry(key = ms.get_name(), cap_name = ms.get_name() + '/master', attach = ms.get_attrs().attach) pd.add_environment(env) bootinfo.add_pd(pd) image.pop_attrs()
def test_find_kcp_valid(self): elf = PreparedElfFile(filename="data/eg_weave/l4kernel") find_kernel_config(elf)
def test_get_paddr(self): ef = PreparedElfFile(filename="data/arm_exec") self.assertEqual(ef.get_paddr(), 0xa0100000) ef = PreparedElfFile(filename="data/arm_object") self.assertRaises(InvalidArgument, ef.get_paddr)
def print_cmd(args): """Display an ELF file. args contains command line arguments passed from sys.argv. These are parsed using option parser.""" parser = OptionParser("%prog print [options] file", add_help_option=0) parser.add_option("-H", "--help", action="help") parser.add_option("-a", "--all", action="store_true", dest="all", help="Print all information") parser.add_option("-h", "--header", action="store_true", dest="header", help="Print ELF header") parser.add_option("-l", "--pheaders", action="store_true", dest="pheaders", help="Print ELF sections headers") parser.add_option("-S", "--sheaders", action="store_true", dest="sheaders", help="Print ELF sections headers") parser.add_option("-k", "--kconfig", action="store_true", dest="kconfig", help="Print L4 kernel config data structure (Default)") parser.add_option("-B", "--bootinfo", action="store_true", dest="bootinfo", help="Print L4 Bootinfo") parser.add_option("-m", "--segnames", action="store_true", dest="segnames", help="Print segment names") parser.add_option("-s", "--syms", action="store_true", dest="symbols", help="Print the symbol table") parser.add_option("-r", "--relocs", action="store_true", dest="relocs", help="Display the relocations (if present)") parser.add_option("-W", "--wide", action="store_true", dest="wide", default=False, help="Allow output width to exceed 80 characters") parser.add_option("-e", "--elfweaver-info", action="store_true", dest="elfweaverinfo", help="Print elfweaver info section") (options, args) = parser.parse_args(args) if len(args) != 1: parser.error("incorrect number of arguments") if options.all: options.header = options.pheaders = options.sheaders = \ options.kconfig = options.bootinfo = \ options.elfweaverinfo = options.segnames = True elf = PreparedElfFile(filename=args[0]) if options.header: elf.get_elf_header().output(sys.stdout) if options.sheaders: print_sheaders(elf, not options.header, sys.stdout) if options.pheaders: print_pheaders(elf, not options.header, sys.stdout) if options.symbols: print_symbol_table(elf, sys.stdout, options.wide) if options.relocs: print_relocations(elf, sys.stdout, options.wide) if options.kconfig: kern_ver = check_api_versions(elf) if kern_ver == NANO_KERNEL_API_VERSION: kconfig = find_nano_heap(elf) else: # kern_ver == MICRO_KERNEL_API_VERSION: kconfig = find_kernel_config(elf) print if kconfig: kconfig.output(sys.stdout) else: print "There is no kernel configuration in this file." if kern_ver != NANO_KERNEL_API_VERSION: print initscript = find_init_script(elf) if initscript: initscript.output(sys.stdout) else: print "There is no initialisation script in this file." if options.elfweaverinfo: print elfweaverinfo = find_elfweaver_info(elf) if elfweaverinfo: elfweaverinfo.output(sys.stdout) else: print "There is no elfweaver info section in this file." if options.bootinfo: print bootinfo = find_bootinfo(elf) if bootinfo: bootinfo.output(sys.stdout) else: print "There is no Bootinfo section in this file." if options.segnames: segcount = 0 print segnames = get_segnames(elf) if segnames: print "Segment Name" for segname in segnames.strings[1:]: idx = segname.index('\x00') segname = segname[:idx] segname = segname.strip() if segname != "": print " %02d %s" % (segcount, segname) segcount += 1 else: # TODO - use the first section in each segment # as the segment name and print that. print "There is no .segnames section in this file" return 0
def test_find_kcp_valid(self): elf = PreparedElfFile(filename="data/arm_object") self.assertEquals(find_kernel_config(elf), None)
def test_get_last_addr(self): for filename in elf_address: ef = PreparedElfFile(filename=filename) self.assertEqual(ef.get_last_addr(), elf_address[filename][0], "%s 0x%x != 0x%x" % (filename, ef.get_last_addr(), elf_address[filename][0]))
def test_get_first_addr(self): for filename in elf_address: ef = PreparedElfFile(filename=filename) self.assertEqual(ef.get_first_addr(), elf_address[filename][2])
def memstats_cmd(args): """Memory Usage Statistics program implementation""" parser = OptionParser("%prog memstats [options] file [file]", add_help_option=0) parser.add_option("-H", "--help", action="help") parser.add_option("-x", "--xml", action="store_true", dest="output_xml", help="Produces an XML file containing memory statistics" \ " in the same directory as the supplied ELF.") parser.add_option("-y", "--verify", action="store_true", dest="verify_xml", help="Verify the XML file.") parser.add_option("-r", "--report", action="store", dest="report", metavar="NAME", help="Parse a memory statistics XML file and output "\ "the named report. Valid reports are: '%s'." % "', '".join(REPORTS_SET.keys())) parser.add_option("-v", "--verbose", action="store_true", dest="verbose_report", help="Produce the verbose form of the requested report.") parser.add_option("-l", "--largest-num", action="store", dest="n_objs", type="int", help="Print, at most, the largest N_OBJS " \ "text and code objects.") parser.add_option("-d", "--diff", action="store_true", dest="output_diff", help="Used on a report, to indicate there are two " "files and the differences should be reported.") parser.add_option("-R", "--repository", action="store", dest="repository", default=None, help="Include the version control repository in the " "XML file.") parser.add_option("-c", "--changeset", action="store", dest="changeset", default=None, help="Include the version control changeset in the " "XML file.") (options, args) = parser.parse_args(args) IdList.reset() Heap.reset() if len(args) < 1 or args[0] is "": parser.error("Missing file argument(s)") input_file = args[0] if not os.path.exists(input_file): print >> sys.stderr, 'Error: File "%s" does not exist.' % input_file return 1 if options.output_xml: elf = PreparedElfFile(filename=input_file) if not elf.segments: print >> sys.stderr, \ 'Error: ELF file "%s" contains no segments.' % input_file return 1 if options.output_diff and not options.report: parser.error("Diff only makes sense on a report.") return # -x implies input is an ELF # -t implies input is XML if options.output_xml: notes_sec = notes.find_elfweaver_notes(elf) memstats = Memstats(elf.machine, notes_sec.cpu, notes_sec.poolname, notes_sec.memsecs, notes_sec.cell_names, notes_sec.space_names, notes_sec.mappings) programs = [] parse_segments(elf, programs, elf.segments, memstats) xml_file = os.path.join(os.path.dirname(input_file), "memstats.xml") hg_stats = (options.repository, options.changeset) memstats.set_revision(hg_stats) kern_ver = check_api_versions(elf) if kern_ver == MICRO_KERNEL_API_VERSION: memstats.env.env_type = "Micro" import weaver.kernel_micro_elf script = weaver.kernel_micro_elf.find_init_script(elf, memstats) elif kern_ver == NANO_KERNEL_API_VERSION: memstats.env.env_type = "Nano" import weaver.kernel_nano_elf heap = weaver.kernel_nano_elf.find_nano_heap(elf) heap.decode(memstats) else: print >> sys.stderr, "Unknown kernel type." return 1 xml_f = open(xml_file, "w") xml_f.write(memstats.format()) xml_f.close() if options.verify_xml: xml_verify(xml_file) if options.report: if options.output_xml: input_file = xml_file if options.output_diff: if len(args) != 2: parser.error("Report diffs require two files.") diff_file = args[1] if options.verify_xml: xml_verify(input_file) xml_verify(diff_file) gen_diff_report(options.report, input_file, diff_file, options.n_objs, options.verbose_report) else: if options.verify_xml: xml_verify(input_file) gen_report(options.report, input_file, options.n_objs, options.verbose_report)
def test_contains_vaddr(self): ef = PreparedElfFile(filename="data/arm_exec") seg = ef.find_segment_by_vaddr(0xf0001000L) self.assertEqual(seg.contains_vaddr(0xf0001000L), True)
def test_vtop(self): ef = PreparedElfFile(filename="data/arm_exec") seg = ef.find_segment_by_vaddr(0xf0001000L) self.assertEqual(seg.vtop(0xf0001000L), 0xa0101000L) self.assertRaises(InvalidArgument, seg.vtop, 0xa0001000L)