mirror of
https://github.com/lief-project/LIEF
synced 2026-06-08 15:30:44 +00:00
814 lines
24 KiB
Python
814 lines
24 KiB
Python
#!/usr/bin/env python
|
|
"""Pretty-print the structure of an ELF binary.
|
|
|
|
Equivalent to ``readelf`` with a selection of the most useful flags
|
|
(``-h``, ``-S``, ``-l``, ``-d``, ``-s``, ``-r``, ``-V`` ...). The
|
|
target file is parsed with ``lief.ELF.parse`` and the requested
|
|
sections are rendered as formatted tables.
|
|
|
|
Example:
|
|
|
|
$ python elf_reader.py -a /bin/ls
|
|
"""
|
|
|
|
import argparse
|
|
import shutil
|
|
import sys
|
|
import textwrap
|
|
import traceback
|
|
|
|
import lief
|
|
from lief import ELF
|
|
|
|
_term_size = shutil.get_terminal_size((110, 100))
|
|
terminal_columns = _term_size.columns - 10
|
|
terminal_rows = _term_size.lines
|
|
|
|
|
|
class exceptions_handler(object):
|
|
func = None
|
|
|
|
def __init__(self, exceptions, on_except_callback=None):
|
|
self.exceptions = exceptions
|
|
self.on_except_callback = on_except_callback
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
if self.func is None:
|
|
self.func = args[0]
|
|
return self
|
|
try:
|
|
return self.func(*args, **kwargs)
|
|
except self.exceptions as e:
|
|
if self.on_except_callback is not None:
|
|
self.on_except_callback(e)
|
|
else:
|
|
print("-" * 60)
|
|
print("Exception in {}: {}".format(self.func.__name__, e))
|
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
traceback.print_tb(exc_traceback)
|
|
print("-" * 60)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_header(binary):
|
|
header = binary.header
|
|
identity = header.identity
|
|
|
|
print("== Header ==\n")
|
|
format_str = "{:<30} {:<30}"
|
|
format_hex = "{:<30} 0x{:<13x}"
|
|
format_dec = "{:<30} {:<30d}"
|
|
format_ide = "{:<30} {:<02x} {:<02x} {:<02x} {:<02x}"
|
|
|
|
eflags_str = ""
|
|
if header.machine_type == lief.ELF.ARCH.ARM:
|
|
eflags_str = " - ".join([str(s).split(".")[-1] for s in header.arm_flags_list])
|
|
|
|
if header.machine_type in [
|
|
lief.ELF.ARCH.MIPS,
|
|
lief.ELF.ARCH.MIPS_RS3_LE,
|
|
lief.ELF.ARCH.MIPS_X,
|
|
]:
|
|
eflags_str = " - ".join([str(s).split(".")[-1] for s in header.mips_flags_list])
|
|
|
|
if header.machine_type == lief.ELF.ARCH.PPC64:
|
|
eflags_str = " - ".join(
|
|
[str(s).split(".")[-1] for s in header.ppc64_flags_list]
|
|
)
|
|
|
|
if header.machine_type == lief.ELF.ARCH.HEXAGON:
|
|
eflags_str = " - ".join(
|
|
[str(s).split(".")[-1] for s in header.hexagon_flags_list]
|
|
)
|
|
|
|
if header.machine_type == lief.ELF.ARCH.LOONGARCH:
|
|
eflags_str = " - ".join(
|
|
[str(s).split(".")[-1] for s in header.loongarch_flags_list]
|
|
)
|
|
print(identity)
|
|
print(
|
|
format_ide.format("Magic:", identity[0], identity[1], identity[2], identity[3])
|
|
)
|
|
print(format_str.format("Class:", str(header.identity_class).split(".")[-1]))
|
|
print(format_str.format("Endianness:", str(header.identity_data).split(".")[-1]))
|
|
print(format_str.format("Version:", str(header.identity_version).split(".")[-1]))
|
|
print(format_str.format("OS/ABI:", str(header.identity_os_abi).split(".")[-1]))
|
|
print(format_dec.format("ABI Version:", header.identity_abi_version))
|
|
print(format_str.format("File Type:", str(header.file_type).split(".")[-1]))
|
|
print(format_str.format("Machine Type:", str(header.machine_type).split(".")[-1]))
|
|
print(
|
|
format_str.format(
|
|
"Object File Version:", str(header.object_file_version).split(".")[-1]
|
|
)
|
|
)
|
|
print(format_hex.format("Entry Point:", header.entrypoint))
|
|
print(format_hex.format("Program Header Offset:", header.program_header_offset))
|
|
print(format_hex.format("Section Header Offset:", header.section_header_offset))
|
|
print(format_hex.format("Processor flags:", header.processor_flag) + eflags_str)
|
|
print(format_dec.format("Header Size:", header.header_size))
|
|
print(format_dec.format("Program Header Size:", header.program_header_size))
|
|
print(format_dec.format("Section Header Size:", header.section_header_size))
|
|
print(format_dec.format("Number of segments:", header.numberof_segments))
|
|
print(format_dec.format("Number of sections:", header.numberof_sections))
|
|
print("")
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_sections(binary):
|
|
sections = binary.sections
|
|
if len(sections) > 0:
|
|
print("== Sections ==\n")
|
|
f_title = "|{:<30} | {:<12}| {:<17}| {:<12}| {:<10}| {:<8}| {:<8}|"
|
|
f_value = "|{:<30} | {:<12}| 0x{:<14x} | 0x{:<10x}| 0x{:<8x}| {:<8.2f}| {:<10}"
|
|
print(
|
|
f_title.format(
|
|
"Name",
|
|
"Type",
|
|
"Virtual address",
|
|
"File offset",
|
|
"Size",
|
|
"Entropy",
|
|
"Segment(s)",
|
|
)
|
|
)
|
|
|
|
for section in sections:
|
|
segments_str = " - ".join(
|
|
[str(s.type).split(".")[-1] for s in section.segments]
|
|
)
|
|
print(
|
|
f_value.format(
|
|
section.name,
|
|
str(section.type).split(".")[-1],
|
|
section.virtual_address,
|
|
section.file_offset,
|
|
section.size,
|
|
abs(section.entropy),
|
|
segments_str,
|
|
)
|
|
)
|
|
print("")
|
|
else:
|
|
print("No sections")
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_segments(binary):
|
|
segments = binary.segments
|
|
# Segments
|
|
if len(segments) > 0:
|
|
print("== Segments ==\n")
|
|
f_title = "|{:<30} | {:<10}| {:<18}| {:<17}| {:<17}| {:<17}| {:<19}|"
|
|
f_value = "|{:<30} | {:<10}| 0x{:<16x}| 0x{:<15x}| 0x{:<15x}| 0x{:<15x}| {}"
|
|
print(
|
|
f_title.format(
|
|
"Type",
|
|
"Flags",
|
|
"File offset",
|
|
"Virtual Address",
|
|
"Virtual Size",
|
|
"Size",
|
|
"Sections",
|
|
)
|
|
)
|
|
|
|
for segment in segments:
|
|
sections = segment.sections
|
|
s = ", ".join([section.name for section in sections])
|
|
flags_str = ["-"] * 3
|
|
if ELF.Segment.FLAGS.R in segment:
|
|
flags_str[0] = "r"
|
|
|
|
if ELF.Segment.FLAGS.W in segment:
|
|
flags_str[1] = "w"
|
|
|
|
if ELF.Segment.FLAGS.X in segment:
|
|
flags_str[2] = "x"
|
|
flags_str = "".join(flags_str)
|
|
|
|
print(
|
|
f_value.format(
|
|
str(segment.type).split(".")[-1],
|
|
flags_str,
|
|
segment.file_offset,
|
|
segment.virtual_address,
|
|
segment.virtual_size,
|
|
segment.physical_size,
|
|
s,
|
|
)
|
|
)
|
|
print("")
|
|
else:
|
|
print("No segments")
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_dynamic_entries(binary):
|
|
dynamic_entries = binary.dynamic_entries
|
|
# Dynamic entries
|
|
if len(dynamic_entries) == 0:
|
|
return
|
|
|
|
print("== Dynamic entries ==\n")
|
|
f_title = "|{:<16} | {:<10}| {:<20}|"
|
|
f_value = "|{:<16} | 0x{:<8x}| {:<20}|"
|
|
print(f_title.format("Tag", "Value", "Info"))
|
|
for entry in dynamic_entries:
|
|
if entry.tag == ELF.DynamicEntry.TAG.NULL:
|
|
continue
|
|
|
|
if entry.tag in [
|
|
ELF.DynamicEntry.TAG.SONAME,
|
|
ELF.DynamicEntry.TAG.NEEDED,
|
|
ELF.DynamicEntry.TAG.RUNPATH,
|
|
ELF.DynamicEntry.TAG.RPATH,
|
|
]:
|
|
print(
|
|
f_value.format(str(entry.tag).split(".")[-1], entry.value, entry.name)
|
|
)
|
|
elif (
|
|
type(entry) is ELF.DynamicEntryArray
|
|
): # [ELF.DynamicEntry.TAG.INIT_ARRAY,ELF.DynamicEntry.TAG.FINI_ARRAY]:
|
|
print(
|
|
f_value.format(
|
|
str(entry.tag).split(".")[-1],
|
|
entry.value,
|
|
", ".join(map(hex, entry.array)),
|
|
)
|
|
)
|
|
elif entry.tag == ELF.DynamicEntry.TAG.FLAGS:
|
|
flags_str = " - ".join(
|
|
[str(ELF.DynamicEntryFlags.FLAG(s)).split(".")[-1] for s in entry.flags]
|
|
)
|
|
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str))
|
|
elif entry.tag == ELF.DynamicEntry.TAG.FLAGS_1:
|
|
flags_str = " - ".join(
|
|
[str(ELF.DynamicEntryFlags.FLAG(s)).split(".")[-1] for s in entry.flags]
|
|
)
|
|
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str))
|
|
else:
|
|
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, ""))
|
|
|
|
print("")
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_symbols(symbols, no_trunc):
|
|
can_demangle = len(symbols) > 0 and len(symbols[0].demangled_name) > 0
|
|
if can_demangle:
|
|
maxsize = max([len(symbol.demangled_name) for symbol in symbols])
|
|
else:
|
|
maxsize = max([len(symbol.name) for symbol in symbols])
|
|
|
|
SIZE = 70
|
|
maxsize = (
|
|
min(maxsize, terminal_columns - SIZE)
|
|
if terminal_columns > SIZE
|
|
else terminal_columns
|
|
)
|
|
|
|
f_title = "|{:<" + str(maxsize) + "} | {:<7}| {:<8}| {:<10}| {:<8}| {:<4}| {:<14}|"
|
|
f_value = "|{:<" + str(maxsize) + "} | {:<7}| {:<8x}| {:<10}| {:<8}| {:<4}| {:<14}|"
|
|
|
|
print(
|
|
f_title.format(
|
|
"Name", "Type", "Value", "Visibility", "Binding", "I/E", "Version"
|
|
)
|
|
)
|
|
|
|
for symbol in symbols:
|
|
symbol_version = symbol.symbol_version if symbol.has_version else ""
|
|
|
|
import_export = ""
|
|
if symbol.imported:
|
|
import_export = "I"
|
|
|
|
if symbol.exported:
|
|
import_export = "E"
|
|
|
|
symbol_name = symbol.demangled_name
|
|
if len(symbol_name) == 0:
|
|
symbol_name = symbol.name
|
|
|
|
wrapped = textwrap.wrap(symbol_name, maxsize)
|
|
|
|
if len(wrapped) <= 1 or no_trunc:
|
|
symbol_name = symbol_name
|
|
else:
|
|
symbol_name = wrapped[0][:-3] + "..."
|
|
|
|
print(
|
|
f_value.format(
|
|
symbol_name,
|
|
str(symbol.type).split(".")[-1],
|
|
symbol.value,
|
|
str(symbol.visibility).split(".")[-1],
|
|
str(symbol.binding).split(".")[-1],
|
|
import_export,
|
|
str(symbol_version),
|
|
)
|
|
)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_dynamic_symbols(binary, args):
|
|
print("== Dynamic symbols ==\n")
|
|
print_symbols(binary.dynamic_symbols, args.no_trunc)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_symtab_symbols(binary, args):
|
|
print("== Symtab symbols ==\n")
|
|
print_symbols(binary.symtab_symbols, args.no_trunc)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_relocations(binary, relocations):
|
|
f_title = "|{:<10} | {:<10}| {:<8}| {:<8}| {:<8}| {:<15}| {:<30} |"
|
|
f_value = "|0x{:<8x} | {:<10}| {:<8d}| {:<8d}| {:<8x}| {:<15}| {:<30} |"
|
|
|
|
print(
|
|
f_title.format("Address", "Type", "Info", "Size", "Addend", "Purpose", "Symbol")
|
|
)
|
|
|
|
for relocation in relocations:
|
|
type = str(relocation.type)
|
|
if binary.header.machine_type == ELF.ARCH.x86_64:
|
|
type = str(relocation.type)
|
|
elif binary.header.machine_type == ELF.ARCH.i386:
|
|
type = str(relocation.type)
|
|
elif binary.header.machine_type == ELF.ARCH.ARM:
|
|
type = str(relocation.type)
|
|
elif binary.header.machine_type == ELF.ARCH.AARCH64:
|
|
type = str(relocation.type)
|
|
|
|
symbol_name = ""
|
|
if relocation.has_symbol:
|
|
symbol: lief.ELF.Symbol = relocation.symbol
|
|
if len(symbol.name) > 0:
|
|
symbol_name = symbol.name
|
|
elif symbol.type == lief.ELF.Symbol.TYPE.SECTION:
|
|
shndx = symbol.shndx
|
|
sections = binary.sections
|
|
if 0 < shndx and shndx < len(sections):
|
|
symbol_name = sections[shndx].name + " + " + hex(relocation.addend)
|
|
else:
|
|
symbol_name = "<section #{}>".format(shndx)
|
|
|
|
print(
|
|
f_value.format(
|
|
relocation.address,
|
|
type.split(".")[-1],
|
|
relocation.info,
|
|
relocation.size,
|
|
relocation.addend,
|
|
str(relocation.purpose).split(".")[-1],
|
|
symbol_name,
|
|
)
|
|
)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_all_relocations(binary):
|
|
dynamicrelocations = binary.dynamic_relocations
|
|
pltgot_relocations = binary.pltgot_relocations
|
|
object_relocations = binary.object_relocations
|
|
|
|
if len(dynamicrelocations) > 0:
|
|
print("== Dynamic Relocations ==\n")
|
|
print_relocations(binary, dynamicrelocations)
|
|
|
|
if len(pltgot_relocations) > 0:
|
|
print("== PLT/GOT Relocations ==\n")
|
|
print_relocations(binary, pltgot_relocations)
|
|
|
|
if len(object_relocations) > 0:
|
|
print("== Object Relocations ==\n")
|
|
print_relocations(binary, object_relocations)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_exported_symbols(binary, args):
|
|
symbols = binary.exported_symbols
|
|
|
|
print("== Exported symbols ==\n")
|
|
if len(symbols) == 0:
|
|
print("No exports!")
|
|
return
|
|
print_symbols(symbols, args.no_trunc)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_imported_symbols(binary, args):
|
|
symbols = binary.imported_symbols
|
|
print("== Imported symbols ==\n")
|
|
|
|
if len(symbols) == 0:
|
|
print("No imports!")
|
|
return
|
|
print_symbols(symbols, args.no_trunc)
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_information(binary):
|
|
print("== Information ==\n")
|
|
format_str = "{:<30} {:<30}"
|
|
format_hex = "{:<30} 0x{:<28x}"
|
|
print(format_hex.format("Address base:", binary.imagebase))
|
|
print(format_hex.format("Virtual size:", binary.virtual_size))
|
|
print(format_str.format("PIE:", str(binary.is_pie)))
|
|
print(format_str.format("NX:", str(binary.has_nx)))
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_gnu_hash(binary):
|
|
print("== GNU Hash ==\n")
|
|
|
|
if not binary.use_gnu_hash:
|
|
return
|
|
|
|
gnu_hash = binary.gnu_hash
|
|
|
|
format_str = "{:<30} {}"
|
|
format_hex = "{:<30} 0x{:<28x}"
|
|
format_dec = "{:<30} {:<30d}"
|
|
|
|
print(format_dec.format("Number of buckets:", gnu_hash.nb_buckets))
|
|
print(format_dec.format("First symbol index:", gnu_hash.symbol_index))
|
|
print(format_hex.format("Shift Count:", gnu_hash.shift2))
|
|
print(format_str.format("Bloom filters:", gnu_hash.bloom_filters))
|
|
print(format_str.format("Buckets:", gnu_hash.buckets))
|
|
print(format_str.format("Hash values:", gnu_hash.hash_values))
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_sysv_hash(binary):
|
|
print("== SYSV Hash ==\n")
|
|
|
|
if not binary.use_sysv_hash:
|
|
return
|
|
|
|
sysv_hash = binary.sysv_hash
|
|
|
|
format_str = "{:<30} {}"
|
|
format_dec = "{:<30} {:<30d}"
|
|
|
|
print(format_dec.format("Number of buckets:", sysv_hash.nbucket))
|
|
print(format_dec.format("Number of chains:", sysv_hash.nchain))
|
|
print(format_str.format("Buckets:", sysv_hash.buckets))
|
|
print(format_str.format("Chains:", sysv_hash.chains))
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_notes(binary):
|
|
print("== Notes ==\n")
|
|
|
|
format_str = "{:<19} {}"
|
|
format_dec = "{:<19} {:<30d}"
|
|
|
|
notes = binary.notes
|
|
for idx, note in enumerate(notes):
|
|
description = note.description
|
|
description_str = " ".join(map(lambda e: "{:02x}".format(e), description[:16]))
|
|
if len(description) > 16:
|
|
description_str += " ..."
|
|
|
|
print("Note #{:d}".format(idx))
|
|
|
|
type_str = note.type_core if note.is_core else note.type
|
|
type_str = str(type_str).split(".")[-1]
|
|
|
|
print(format_str.format("Name:", note.name))
|
|
print(format_str.format("Type:", type_str))
|
|
print(format_str.format("Description:", description_str))
|
|
|
|
note_details = note.details
|
|
|
|
if isinstance(note_details, lief.ELF.AndroidIdent):
|
|
print(format_dec.format("SDK Version:", note_details.sdk_version))
|
|
print(format_str.format("NDK Version:", note_details.ndk_version))
|
|
print(format_str.format("NDK build number:", note_details.ndk_build_number))
|
|
|
|
if isinstance(note_details, lief.ELF.NoteAbi):
|
|
version = note_details.version
|
|
version_str = "{:d}.{:d}.{:d}".format(version[0], version[1], version[2])
|
|
|
|
print(format_str.format("ABI:", note_details.abi))
|
|
print(format_str.format("Version:", version_str))
|
|
|
|
if note.type == ELF.Note.TYPE.GNU_GOLD_VERSION:
|
|
print(format_str.format("Version:", "".join(map(chr, note.description))))
|
|
|
|
if note.is_core:
|
|
print(note_details)
|
|
|
|
print("\n")
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_ctor(binary):
|
|
print("== Constructors ==\n")
|
|
|
|
print("Functions: ({:d})".format(len(binary.ctor_functions)))
|
|
for idx, f in enumerate(binary.ctor_functions):
|
|
print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address))
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_strings(binary):
|
|
print("== Strings ==\n")
|
|
|
|
strings = binary.strings
|
|
print("Strings: ({:d})".format(len(binary.strings)))
|
|
for s in strings:
|
|
print(" {}".format(s))
|
|
|
|
|
|
@exceptions_handler(Exception)
|
|
def print_functions(binary):
|
|
print("== Functions ==\n")
|
|
|
|
functions = binary.functions
|
|
print("Functions: ({:d})".format(len(functions)))
|
|
for idx, f in enumerate(functions):
|
|
print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address))
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(add_help=False, prog=sys.argv[0])
|
|
parser.add_argument("elf_file")
|
|
|
|
parser.add_argument(
|
|
"-a",
|
|
"--all",
|
|
action="store_true",
|
|
dest="show_all",
|
|
help="Equivalent to: -h -l -S -s -r -d -V",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-d",
|
|
"--dynamic",
|
|
action="store_true",
|
|
dest="show_dynamic_tags",
|
|
help="Display the dynamic section",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-H", "--help", action="help", dest="help", help="Display this information"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-h",
|
|
"--file-header",
|
|
action="store_true",
|
|
dest="show_file_header",
|
|
help="Display the ELF file header",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-i",
|
|
"--imported",
|
|
action="store_true",
|
|
dest="show_imported_symbols",
|
|
help="Display imported symbols",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-l",
|
|
"--program-headers",
|
|
"--segments",
|
|
action="store_true",
|
|
dest="show_program_header",
|
|
help="Display the program headers",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-S",
|
|
"--section-headers",
|
|
"--sections",
|
|
action="store_true",
|
|
dest="show_section_header",
|
|
help="Display the sections' headers",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-e",
|
|
"--headers",
|
|
action="store_true",
|
|
dest="show_all_headers",
|
|
help="Equivalent to: -h -l -S",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-s",
|
|
"--symbols",
|
|
"--syms",
|
|
action="store_true",
|
|
dest="show_symbols",
|
|
help="Display the symbol table",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--dynamic-symbols",
|
|
"--dsyms",
|
|
action="store_true",
|
|
dest="show_dynamic_symbols",
|
|
help="Display the dynamic symbols",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--symtab-symbols",
|
|
"--ssyms",
|
|
action="store_true",
|
|
dest="show_symtab_symbols",
|
|
help="Display the symtab symbols",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-r",
|
|
"--relocs",
|
|
action="store_true",
|
|
dest="show_relocs",
|
|
help="Display the relocations (if present)",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-V",
|
|
"--version-info",
|
|
action="store_true",
|
|
dest="show_version_info",
|
|
help="Display the version sections (if present)",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-x",
|
|
"--exported",
|
|
action="store_true",
|
|
dest="show_exported_symbols",
|
|
help="Display exported symbols",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--gnu-hash", action="store_true", dest="show_gnu_hash", help="Display GNU Hash"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--sysv-hash",
|
|
action="store_true",
|
|
dest="show_sysv_hash",
|
|
help="Display SYSV Hash",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-n", "--notes", action="store_true", dest="show_notes", help="Display Notes"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--no-trunc",
|
|
action="store_true",
|
|
dest="no_trunc",
|
|
default=False,
|
|
help="Do not trunc symbol names ...",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--ctor", action="store_true", dest="show_ctor", help="Constructor functions"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--strings",
|
|
action="store_true",
|
|
dest="show_strings",
|
|
help="Strings present in the current ELF",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--functions",
|
|
action="store_true",
|
|
dest="show_functions",
|
|
help="List all function addresses found",
|
|
)
|
|
|
|
# Logging setup
|
|
logger_group = parser.add_argument_group("Logger")
|
|
verbosity = logger_group.add_mutually_exclusive_group()
|
|
|
|
verbosity.add_argument(
|
|
"--debug",
|
|
dest="main_verbosity",
|
|
action="store_const",
|
|
const=lief.logging.LEVEL.DEBUG,
|
|
)
|
|
|
|
verbosity.add_argument(
|
|
"--trace",
|
|
dest="main_verbosity",
|
|
action="store_const",
|
|
const=lief.logging.LEVEL.TRACE,
|
|
)
|
|
|
|
verbosity.add_argument(
|
|
"--info",
|
|
dest="main_verbosity",
|
|
action="store_const",
|
|
const=lief.logging.LEVEL.INFO,
|
|
)
|
|
|
|
verbosity.add_argument(
|
|
"--warn",
|
|
dest="main_verbosity",
|
|
action="store_const",
|
|
const=lief.logging.LEVEL.WARN,
|
|
)
|
|
|
|
verbosity.add_argument(
|
|
"--err",
|
|
dest="main_verbosity",
|
|
action="store_const",
|
|
const=lief.logging.LEVEL.ERROR,
|
|
)
|
|
|
|
verbosity.add_argument(
|
|
"--critical",
|
|
dest="main_verbosity",
|
|
action="store_const",
|
|
const=lief.logging.LEVEL.CRITICAL,
|
|
)
|
|
|
|
parser.set_defaults(main_verbosity=lief.logging.LEVEL.WARN)
|
|
|
|
args = parser.parse_args()
|
|
|
|
lief.logging.set_level(args.main_verbosity)
|
|
binary = ELF.parse(args.elf_file)
|
|
if binary is None:
|
|
print(f"Error: failed to parse '{args.elf_file}' as ELF", file=sys.stderr)
|
|
return 1
|
|
|
|
print_information(binary)
|
|
if args.show_all:
|
|
do_file_header = do_section_header = do_program_header = True
|
|
|
|
if args.show_all_headers:
|
|
do_file_header = do_section_header = do_program_header = True
|
|
else:
|
|
do_file_header = args.show_file_header
|
|
do_section_header = args.show_section_header
|
|
do_program_header = args.show_program_header
|
|
|
|
if do_file_header or args.show_all:
|
|
print_header(binary)
|
|
|
|
if do_section_header or args.show_all:
|
|
print_sections(binary)
|
|
|
|
if do_program_header or args.show_all:
|
|
print_segments(binary)
|
|
|
|
if args.show_dynamic_tags or args.show_all:
|
|
print_dynamic_entries(binary)
|
|
|
|
if (args.show_symbols or args.show_all or args.show_dynamic_symbols) and len(
|
|
binary.dynamic_symbols
|
|
) > 0:
|
|
print_dynamic_symbols(binary, args)
|
|
|
|
if (args.show_symbols or args.show_all or args.show_symtab_symbols) and len(
|
|
binary.symtab_symbols
|
|
) > 0:
|
|
print_symtab_symbols(binary, args)
|
|
|
|
if args.show_relocs or args.show_all:
|
|
print_all_relocations(binary)
|
|
|
|
if args.show_imported_symbols or args.show_all:
|
|
print_imported_symbols(binary, args)
|
|
|
|
if args.show_exported_symbols or args.show_all:
|
|
print_exported_symbols(binary, args)
|
|
|
|
if (args.show_gnu_hash or args.show_all) and binary.use_gnu_hash:
|
|
print_gnu_hash(binary)
|
|
|
|
if (args.show_sysv_hash or args.show_all) and binary.use_sysv_hash:
|
|
print_sysv_hash(binary)
|
|
|
|
if args.show_notes or args.show_all:
|
|
print_notes(binary)
|
|
|
|
if args.show_ctor or args.show_all:
|
|
print_ctor(binary)
|
|
|
|
if args.show_strings or args.show_all:
|
|
print_strings(binary)
|
|
|
|
if args.show_functions:
|
|
print_functions(binary)
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|