From cf981a295153f12efdbe50d7bef54f13385d443c Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 30 Apr 2018 15:44:56 +0200 Subject: Provided some initial samples of Python bindings usage. --- python/ins_collect.py | 80 +++++++ python/ins_stats.py | 62 ++++++ python/readelf.py | 574 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 716 insertions(+) create mode 100644 python/ins_collect.py create mode 100644 python/ins_stats.py create mode 100644 python/readelf.py diff --git a/python/ins_collect.py b/python/ins_collect.py new file mode 100644 index 0000000..f48a49e --- /dev/null +++ b/python/ins_collect.py @@ -0,0 +1,80 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +import sys +import pychrysalide +from pychrysalide.analysis.contents import FileContent +from pychrysalide.format.elf import ElfFormat +from pychrysalide.analysis import LoadedBinary + + +if len(sys.argv) != 2: + print('Usage: %s ' % sys.argv[0]) + sys.exit(1) + + +# Load the provided binary + +cnt = FileContent(sys.argv[1]) + +fmt = ElfFormat(cnt) + +binary = LoadedBinary(fmt) + +binary.analyze_and_wait() + + +# Compute some stats + +ins_count = 0 + +opsize_0 = 0 +opsize_1 = 0 + +srcsz_0 = 0 +srcsz_1 = 0 + +destsz_0 = 0 +destsz_1 = 0 + +for ins in binary.processor.instrs: + + ins_count += 1 + + size = len(ins.operands) + + if size == 0: + opsize_0 += 1 + + elif size == 1: + opsize_1 += 1 + + size = len(ins.sources) + + if size == 0: + srcsz_0 += 1 + + elif size == 1: + srcsz_1 += 1 + + size = len(ins.destinations) + + if size == 0: + destsz_0 += 1 + + elif size == 1: + destsz_1 += 1 + + +# Display the results + +print('=== Collected %d instructions ===' % ins_count) + +print('No operand: %u' % opsize_0) +print('One operand: %u' % opsize_1) + +print('No source: %u' % srcsz_0) +print('One source: %u' % srcsz_1) + +print('No destination: %u' % destsz_0) +print('One destination: %u' % destsz_1) diff --git a/python/ins_stats.py b/python/ins_stats.py new file mode 100644 index 0000000..d9b5602 --- /dev/null +++ b/python/ins_stats.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +import sys +import pychrysalide +from pychrysalide.analysis.contents import FileContent +from pychrysalide.format.dex import DexFormat +from pychrysalide.analysis import LoadedBinary +from threading import Event + + +if len(sys.argv) != 2: + print('Usage: %s ' % sys.argv[0]) + sys.exit(1) + + +# Load the provided binary + +cnt = FileContent(sys.argv[1]) + +fmt = DexFormat(cnt) + +binary = LoadedBinary(fmt) + +binary.analyze_and_wait() + + +# Compute some stats + +raw = [ "dn", "db", "dw", "dd", "dq" ] + +collected = { } + +max_len = 0 +ins_count = 0 + +for ins in binary.processor.instrs: + + if ins.keyword in raw: + continue + + if len(ins.keyword) > max_len: + max_len = len(ins.keyword) + + ins_count += 1 + + if ins.keyword in collected.keys(): + collected[ins.keyword] += 1 + else: + collected[ins.keyword] = 1 + + +# Display the results + +stats = [ (k, v) for k, v in collected.items() ] + +stats = sorted(stats, key = lambda s: s[1], reverse = True) + +print('=== Collected %d instructions ===' % ins_count) + +for s in stats: + print(' %s %d (%d%%)' % (s[0].ljust(max_len + 2, '.'), s[1], (s[1] * 100) / ins_count)) diff --git a/python/readelf.py b/python/readelf.py new file mode 100644 index 0000000..5bc5e93 --- /dev/null +++ b/python/readelf.py @@ -0,0 +1,574 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +import argparse +import math +import sys +import pychrysalide +from collections import OrderedDict +from pychrysalide.analysis.contents import FileContent +from pychrysalide.analysis import LoadedBinary +from pychrysalide.arch import vmpa +from pychrysalide.format.elf import ElfFormat + + +def _get_string(fmt, start, offset): + """Extract a given string.""" + + string = None + + maxlen = fmt.content.compute_size() + + end = start + offset + + while end < maxlen: + + byte = fmt.content.read_u8(vmpa(end, vmpa.VMPA_NO_VIRTUAL)) + + if byte == 0x00: + break + + end += 1 + + string = fmt.content.read_raw(vmpa(start + offset, vmpa.VMPA_NO_VIRTUAL), end - start) + + return string.decode('utf-8') + + +def display_elf_header(fmt): + """Displays the information contained in the file's main header.""" + + # File class + elf_classes = { + ElfFormat.ELFCLASS32 : 'ELF32', + ElfFormat.ELFCLASS64 : 'ELF64' + } + + # Data encoding + elf_encodings = { + ElfFormat.ELFDATA2LSB : "2's complement, little endian", + ElfFormat.ELFDATA2MSB : "2's complement, big endian" + } + + # Object file type + elf_types = { + ElfFormat.ET_REL : 'Relocatable file', + ElfFormat.ET_EXEC : 'Executable file', + ElfFormat.ET_DYN : 'Shared object file', + ElfFormat.ET_CORE : 'Core file' + } + + # Architecture + elf_machines = { + ElfFormat.EM_ARM : 'ARM', + ElfFormat.EM_AARCH64 : 'ARM AARCH64' + } + + # ELF Header + + header = fmt.get_header() + + fields = OrderedDict() + + fields['Magic'] = ' '.join([ '%02x' % c for c in header.e_ident ]) + fields['Class'] = elf_classes[header.e_ident[ElfFormat.EI_CLASS]] if header.e_ident[ElfFormat.EI_CLASS] in elf_classes.keys() else 'Invalid' + fields['Data'] = elf_encodings[header.e_ident[ElfFormat.EI_DATA]] if header.e_ident[ElfFormat.EI_DATA] in elf_encodings.keys() else 'Invalid' + fields['Version'] = '%u' % header.e_ident[ElfFormat.EI_VERSION] + fields['OS/ABI'] = 'UNIX - System V' if header.e_ident[ElfFormat.EI_OSABI] == ElfFormat.ELFOSABI_SYSV else 'Other than UNIX' + fields['ABI Version'] = '%u' % header.e_ident[ElfFormat.EI_ABIVERSION] + fields['Type'] = elf_types[header.e_type] if header.e_type in elf_types.keys() else 'Other file type' + fields['Machine'] = elf_machines[header.e_machine] if header.e_machine in elf_machines.keys() else 'Other architecture' + fields['Version'] = '0x%x' % header.e_version + fields['Entry point address'] = '0x%x' % header.e_entry + fields['Start of program headers'] = '%u (bytes into file)' % header.e_phoff + fields['Start of section headers'] = '%u (bytes into file)' % header.e_shoff + fields['Flags'] = '0x%x' % header.e_flags + fields['Size of this header'] = '%u (bytes)' % header.e_ehsize + fields['Size of program headers'] = '%u (bytes)' % header.e_phentsize + fields['Number of program headers'] = '%u' % header.e_phnum + fields['Size of section headers'] = '%u (bytes)' % header.e_shentsize + fields['Number of section headers'] = '%u' % header.e_shnum + fields['Section header string table index'] = '%u' % header.e_shstrndx + + # Compute the max length and the relative format + + max_len = 0 + + for k in fields.keys(): + if len(k) > max_len: + max_len = len(k) + + max_len += len(':') + + line = ' {0:<%d} {1}' % max_len + + # Final display + + print('ELF Header:') + + for k, v in fields.items(): + print(line.format(k + ':', v)) + + print() + + +def display_elf_program_headers(fmt): + """Displays the information contained in the file's program headers, if it has any.""" + + # Segment type + segment_types = { + ElfFormat.PT_NULL : 'NULL', + ElfFormat.PT_LOAD : 'LOAD', + ElfFormat.PT_DYNAMIC : 'DYNAMIC', + ElfFormat.PT_INTERP : 'INTERP', + ElfFormat.PT_NOTE : 'NOTE', + ElfFormat.PT_SHLIB : 'SHLIB', + ElfFormat.PT_PHDR : 'PHDR', + ElfFormat.PT_TLS : 'TLS', + ElfFormat.PT_GNU_EH_FRAME : 'GNU_EH_FRAME', + ElfFormat.PT_GNU_STACK : 'GNU_STACK', + ElfFormat.PT_GNU_RELRO : 'GNU_RELRO' + } + + # Data computing + + header = fmt.get_header() + + fields = [] + + fields.append([ 'Type', 'Offset', 'VirtAddr', 'PhysAddr', 'FileSiz', 'MemSiz', 'Flg', 'Align' ]) + + for i in range(header.e_phnum): + + phdr = fmt.find_program_by_index(i) + + fields.append([ segment_types[phdr.p_type] if phdr.p_type in segment_types.keys() else 'UNKNOWN', + '0x%x' % phdr.p_offset, + '0x%x' % phdr.p_vaddr, + '0x%x' % phdr.p_paddr, + '0x%x' % phdr.p_filesz, + '0x%x' % phdr.p_memsz, + '%c%c%c' % ('R' if phdr.p_flags & ElfFormat.PF_R else ' ', + 'W' if phdr.p_flags & ElfFormat.PF_W else ' ', + 'X' if phdr.p_flags & ElfFormat.PF_X else ' '), + '0x%x' % phdr.p_align]) + + # Max string length + + count = len(fields[0]) + lengths = [ 0 for i in range(count) ] + + for f in fields: + for c in range(count): + + if len(f[c]) > lengths[c]: + lengths[c] = len(f[c]) + + # Relative format string + + line = ' ' + + for c in range(count): + line += '{%u:<%u}' % (c, lengths[c] + 1) + + # Final display + + print('Program Headers:') + + for f in fields: + print(line.format(*f)) + + print() + + # Second final display + + line = ' {0:<7} {1}' + + print('Section to Segment mapping:') + + print(line.format('Segment', 'Sections...')) + + for i in range(header.e_phnum): + + phdr = fmt.find_program_by_index(i) + + contained = '' + + for j in range(header.e_shnum): + + section = fmt.find_section_by_index(j) + + if not (section.sh_flags & ElfFormat.SHF_ALLOC): + continue + + if section.sh_addr < phdr.p_vaddr: + continue + + if (section.sh_addr + section.sh_size) > (phdr.p_vaddr + phdr.p_memsz): + continue + + if len(contained) > 0: + contained += ' ' + section.name + else: + contained = section.name + + print(line.format(i, contained)) + + print() + + +def display_elf_section_headers(fmt): + """Displays the information contained in the file's section headers, if it has any.""" + + # Section type + section_types = { + ElfFormat.SHT_NULL : 'NULL', + ElfFormat.SHT_PROGBITS : 'PROGBITS', + ElfFormat.SHT_SYMTAB : 'SYMTAB', + ElfFormat.SHT_STRTAB : 'STRTAB', + ElfFormat.SHT_RELA : 'RELA', + ElfFormat.SHT_HASH : 'HASH', + ElfFormat.SHT_DYNAMIC : 'DYNAMIC', + ElfFormat.SHT_NOTE : 'NOTE', + ElfFormat.SHT_NOBITS : 'NOBITS', + ElfFormat.SHT_REL : 'REL', + ElfFormat.SHT_SHLIB : 'SHLIB', + ElfFormat.SHT_DYNSYM : 'DYNSYM', + ElfFormat.SHT_INIT_ARRAY : 'NIT_ARRAY', + ElfFormat.SHT_FINI_ARRAY : 'FINI_ARRAY', + ElfFormat.SHT_PREINIT_ARRAY : 'PREINIT_ARRAY', + ElfFormat.SHT_GROUP : 'GROUP', + ElfFormat.SHT_SYMTAB_SHNDX : 'SYMTAB_SHNDX', + ElfFormat.SHT_GNU_ATTRIBUTES : 'GNU_ATTRIBUTES', + ElfFormat.SHT_GNU_HASH : 'GNU_HASH', + ElfFormat.SHT_GNU_LIBLIST : 'GNU_LIBLIST', + ElfFormat.SHT_CHECKSUM : 'CHECKSUM', + ElfFormat.SHT_SUNW_move : 'SUNW_move', + ElfFormat.SHT_SUNW_COMDAT : 'SUNW_COMDAT', + ElfFormat.SHT_SUNW_syminfo : 'SUNW_syminfo', + ElfFormat.SHT_GNU_verdef : 'GNU_verdef', + ElfFormat.SHT_GNU_verneed : 'GNU_verneed', + ElfFormat.SHT_GNU_versym : 'GNU_versym' + } + + + def build_section_flags(flags): + + desc = '' + + desc += 'W' if flags & ElfFormat.SHF_WRITE else '' + desc += 'A' if flags & ElfFormat.SHF_ALLOC else '' + desc += 'X' if flags & ElfFormat.SHF_EXECINSTR else '' + desc += 'M' if flags & ElfFormat.SHF_MERGE else '' + desc += 'S' if flags & ElfFormat.SHF_STRINGS else '' + desc += 'I' if flags & ElfFormat.SHF_INFO_LINK else '' + desc += 'L' if flags & ElfFormat.SHF_LINK_ORDER else '' + desc += 'G' if flags & ElfFormat.SHF_GROUP else '' + desc += 'T' if flags & ElfFormat.SHF_TLS else '' + desc += 'X' if flags & ElfFormat.SHF_EXCLUDE else '' + + return desc + + + header = fmt.get_header() + + count = header.e_shnum + + + section = fmt.find_section_by_index(header.e_shstrndx) + + if section: + strtab_pos = section.sh_offset + else: + strtab_pos = None + + + # Compute max string lengths + + name_maxlen = 0 + type_maxlen = 0 + + esize_maxlen = 99 # ES (log10) + flags_maxlen = 3 # Flg + link_maxlen = 99 # Lk (log10) + info_maxlen = 999 # Inf (log10) + align_maxlen = 99 # Al (log10) + + for i in range(header.e_shnum): + + section = fmt.find_section_by_index(i) + + if len(section.name) > name_maxlen: + name_maxlen = len(section.name) + + if section.sh_type in section_types.keys(): + if len(section_types[section.sh_type]) > type_maxlen: + type_maxlen = len(section_types[section.sh_type]) + + if section.sh_entsize > esize_maxlen: + esize_maxlen = section.sh_entsize + + flags_desc = build_section_flags(section.sh_flags) + + if len(flags_desc) > flags_maxlen: + flags_maxlen = len(flags_desc) + + if section.sh_link > link_maxlen: + link_maxlen = section.sh_link + + if section.sh_info > info_maxlen: + info_maxlen = section.sh_info + + if section.sh_addralign > align_maxlen: + align_maxlen = section.sh_addralign + + # Relative format string + + esize_maxlen = math.log10(esize_maxlen) + link_maxlen = math.log10(link_maxlen) + info_maxlen = math.log10(info_maxlen) + align_maxlen = math.log10(align_maxlen) + + if esize_maxlen % 1: + esize_maxlen +=1 + + if link_maxlen % 1: + link_maxlen +=1 + if info_maxlen % 1: + info_maxlen +=1 + if align_maxlen % 1: + align_maxlen +=1 + + esize_maxlen = int(esize_maxlen) + link_maxlen = int(link_maxlen) + info_maxlen = int(info_maxlen) + align_maxlen = int(align_maxlen) + + line = ' [{0:>2}] {1:<%u} {2:<%u} {3:<8} {4:<8} {5:<8} {6:>%u} {7:>%u} {8:>%u} {9:>%u} {10:>%u}' \ + % (name_maxlen, type_maxlen, esize_maxlen, flags_maxlen, link_maxlen, info_maxlen, align_maxlen) + + # Final display + + headers = [ 'NR', 'Name', 'Type', 'Addr', 'Off', 'Size', 'ES', 'Flg', 'Lk', 'Inf', 'Al' ] + + print('Section Headers:') + print(line.format(*headers)) + + for i in range(header.e_shnum): + + section = fmt.find_section_by_index(i) + + if section.sh_type in section_types.keys(): + sec_type = section_types[section.sh_type] + else: + sec_type = '???' + + flags_desc = build_section_flags(section.sh_flags) + + print(line.format(i, section.name, sec_type, '%08x' % section.sh_addr, '%08x' % section.sh_offset, '%08x' % section.sh_size, + '%x' % section.sh_entsize, flags_desc, '%u' % section.sh_link, '%u' % section.sh_info, '%u' % section.sh_addralign)) + + print() + + print('Key to Flags:') + print(' W (write), A (alloc), X (execute), M (merge), S (strings)') + print(' I (info), L (link order), G (group), T (TLS), E (exclude)') + + print() + + +def display_elf_dynamic_items(fmt): + """Displays the information contained in the file's dynamic items, if it has any.""" + + # Dynamic entry types + elf_dynamic_types = { + ElfFormat.DT_NULL : 'NULL', + ElfFormat.DT_NEEDED : 'NEEDED', + ElfFormat.DT_PLTRELSZ : 'PLTRELSZ', + ElfFormat.DT_PLTGOT : 'PLTGOT', + ElfFormat.DT_HASH : 'HASH', + ElfFormat.DT_STRTAB : 'STRTAB', + ElfFormat.DT_SYMTAB : 'SYMTAB', + ElfFormat.DT_RELA : 'RELA', + ElfFormat.DT_RELASZ : 'RELASZ', + ElfFormat.DT_RELAENT : 'RELAENT', + ElfFormat.DT_STRSZ : 'STRSZ', + ElfFormat.DT_SYMENT : 'SYMENT', + ElfFormat.DT_INIT : 'INIT', + ElfFormat.DT_FINI : 'FINI', + ElfFormat.DT_SONAME : 'SONAME', + ElfFormat.DT_RPATH : 'RPATH', + ElfFormat.DT_SYMBOLIC : 'SYMBOLIC', + ElfFormat.DT_REL : 'REL', + ElfFormat.DT_RELSZ : 'RELSZ', + ElfFormat.DT_RELENT : 'RELENT', + ElfFormat.DT_PLTREL : 'PLTREL', + ElfFormat.DT_DEBUG : 'DEBUG', + ElfFormat.DT_TEXTREL : 'TEXTREL', + ElfFormat.DT_JMPREL : 'JMPREL', + ElfFormat.DT_BIND_NOW : 'BIND_NOW', + ElfFormat.DT_INIT_ARRAY : 'INIT_ARRAY', + ElfFormat.DT_FINI_ARRAY : 'FINI_ARRAY', + ElfFormat.DT_INIT_ARRAYSZ : 'INIT_ARRAYSZ', + ElfFormat.DT_FINI_ARRAYSZ : 'FINI_ARRAYSZ', + ElfFormat.DT_RUNPATH : 'RUNPATH', + ElfFormat.DT_FLAGS : 'FLAGS', + ElfFormat.DT_ENCODING : 'ENCODING', + ElfFormat.DT_PREINIT_ARRAY : 'PREINIT_ARRAY', + ElfFormat.DT_PREINIT_ARRAYSZ : 'PREINIT_ARRAYSZ' + } + + # See http://www.sco.com/developers/gabi/latest/ch5.dynamic.html + elf_dynamic_values = { + ElfFormat.DT_NULL : '0x%x', + ElfFormat.DT_NEEDED : 'Shared library: [%s]', + ElfFormat.DT_PLTRELSZ : '%u (bytes)', + ElfFormat.DT_PLTGOT : '0x%x', + ElfFormat.DT_HASH : '0x%x', + ElfFormat.DT_STRTAB : '0x%x', + ElfFormat.DT_SYMTAB : '0x%x', + ElfFormat.DT_RELA : '0x%x', + ElfFormat.DT_RELASZ : '%u (bytes)', + ElfFormat.DT_RELAENT : '%u (bytes)', + ElfFormat.DT_STRSZ : '%u (bytes)', + ElfFormat.DT_SYMENT : '%u (bytes)', + ElfFormat.DT_INIT : '0x%x', + ElfFormat.DT_FINI : '0x%x', + ElfFormat.DT_SONAME : '%u', + ElfFormat.DT_RPATH : '%u', + ElfFormat.DT_SYMBOLIC : '0x%x', + ElfFormat.DT_REL : '0x%x', + ElfFormat.DT_RELSZ : '%u (bytes)', + ElfFormat.DT_RELENT : '%u (bytes)', + ElfFormat.DT_PLTREL : '%u', + ElfFormat.DT_DEBUG : '0x%x', + ElfFormat.DT_TEXTREL : '0x%x', + ElfFormat.DT_JMPREL : '0x%x', + ElfFormat.DT_BIND_NOW : '0x%x', + ElfFormat.DT_INIT_ARRAY : '0x%x', + ElfFormat.DT_FINI_ARRAY : '0x%x', + ElfFormat.DT_INIT_ARRAYSZ : '%u (bytes)', + ElfFormat.DT_FINI_ARRAYSZ : '%u (bytes)', + ElfFormat.DT_RUNPATH : '%u', + ElfFormat.DT_FLAGS : '0x%x', + ElfFormat.DT_ENCODING : '0x%x', + ElfFormat.DT_PREINIT_ARRAY : '%u (bytes)', + ElfFormat.DT_PREINIT_ARRAYSZ : '%u (bytes)' + } + + # Find the right segment & data + + phdr = fmt.find_program_by_type(ElfFormat.PT_DYNAMIC) + + assert(phdr.p_filesz % fmt.sizeof_dyn == 0) + + count = int(phdr.p_filesz / fmt.sizeof_dyn) + + # Fix the item counter !? + + for i in range(count): + + item = fmt.find_dynamic_item_by_index(i) + + if item.d_tag == ElfFormat.DT_NULL: + break + + count = i + 1 + + # Get the string location + + strtab_pos = None + strtab_addr = None + + for i in range(count): + + item = fmt.find_dynamic_item_by_index(i) + + if item.d_tag == ElfFormat.DT_STRTAB: + strtab_addr = item['d_un.d_ptr'] + break + + loc = fmt.translate_address_into_vmpa(strtab_addr) + assert(loc) + + strtab_pos = loc.phys + + # Final display + + print('Dynamic section at offset 0x%x contains %u %s:' % (phdr.p_offset, count, 'entries' if count > 1 else 'entry')) + + line = ' {0:<10} {1:<30} {2}' + + print(line.format(' Tag', ' Type', ' Name/Value')) + + line = ' {0} {1:<30} {2}' + + for i in range(count): + + item = fmt.find_dynamic_item_by_index(i) + + item_type = '(%s)' % elf_dynamic_types[item.d_tag] if item.d_tag in elf_dynamic_types.keys() else '(UNKNOWN)' + + item_format = elf_dynamic_values[item.d_tag] if item.d_tag in elf_dynamic_values.keys() else '0x%x' + + if '%s' in item_format: + if strtab_pos is None: + item_value = item_format % item['d_un.d_val'] + else: + item_value = item_format % _get_string(fmt, strtab_pos, item['d_un.d_val']) + + elif '%u' in item_format: + item_value = item_format % item['d_un.d_val'] + + else: + item_value = item_format % item['d_un.d_ptr'] + + print(line.format('0x%08x' % item.d_tag, item_type, item_value)) + + if item.d_tag == ElfFormat.DT_NULL: + break + + print() + + +if __name__ == '__main__': + + parser = argparse.ArgumentParser(description='readelf - Displays information about ELF files.', add_help=False) + + parser.add_argument('-H', '--help', action='store_true', help='Display the command line options understood by readelf.') + + parser.add_argument('-a', '--all', action='store_true', help='Equivalent to specifying --file-header, --segments, --sections, --dynamic.') + parser.add_argument('-h', '--file-header', action='store_true', help='Displays the information contained in the ELF header at the start of the file.') + parser.add_argument('-l', '--program-headers', '--segments', action='store_true', help='Displays the information contained in the file\'s segment headers, if it has any.') + parser.add_argument('-S', '--section-headers', '--sections', action='store_true', help='Displays the information contained in the file\'s section headers, if it has any.') + parser.add_argument('-d', '--dynamic', action='store_true', help='Displays the contents of the file\'s dynamic section, if it has one.') + + parser.add_argument('elffile', type=str, help='The object file to be examined') + + args = parser.parse_args() + + if args.help: + parser.print_help() + sys.exit(1) + + cnt = FileContent(args.elffile) + + fmt = ElfFormat(cnt) + + binary = LoadedBinary(fmt) + + binary.analyze_and_wait() + + print() + + if args.all or args.file_header: + display_elf_header(fmt) + + if args.all or args.program_headers: + display_elf_program_headers(fmt) + + if args.all or args.section_headers: + display_elf_section_headers(fmt) + + if args.all or args.dynamic: + display_elf_dynamic_items(fmt) -- cgit v0.11.2-87-g4458