Skip to content

Instantly share code, notes, and snippets.

@riyadparvez
Created February 24, 2015 15:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save riyadparvez/45b7f457a303408867ad to your computer and use it in GitHub Desktop.
Save riyadparvez/45b7f457a303408867ad to your computer and use it in GitHub Desktop.
Run addr2line on all instructions in the binary. You need pybfd package.
#!/usr/bin/env python
# Import the disassembly library (libopcodes)
from pybfd.opcodes import Opcodes, OpcodesException
from pybfd.bfd import Bfd, BfdException
from sys import argv, exit
from subprocess import Popen, PIPE
def print_file_line_callback(address, size, branch_delay_insn,
insn_type, target, target2, disassembly):
"""
Callack on each disassembled instruction to print its information.
"""
#print("0x%X SZ=%d BD=%d IT=%d\t%s" % \
# (address, size, branch_delay_insn, insn_type, disassembly))
proc = Popen(["/usr/bin/addr2line", "-e", argv[1], "-C", "-f", "-p", "-a", address], stdout=PIPE, stderr=PIPE);
stdout, stderr = proc.communicate()
print(stdout)
return PYBFD_DISASM_CONTINUE
if len(argv) == 1:
print("Usage : %s <filename>" % argv[0])
exit(0)
bfd = None
path = None
try:
#
# Initialize BFD instance.
# We can either pass a filename or a file descriptor and they will be used
# in the same way.
#
print("[+] Creating BFD instance...")
path = argv[1]
bfd = Bfd(path)
# Print the file format and in case that its an archive then just show
# its files and leave.
print("[+] File format : %s" % bfd.file_format_name)
if bfd.is_archive:
print("[-] List of internal files:")
#for inner_filename in bfd.archive_filenames:
# print "\t%s" % inner_filename
for inner_bfd in bfd.archive_files:
print("\t%-40s - sections : %d - symbols : %s" % \
(inner_bfd.filename,
len(inner_bfd.sections),
len(inner_bfd.symbols)))
# The bfd.close() is executed below in the finally clause.
exit(0)
#
# Display some information about the currently open file.
#
print("[+] Architecture : %s (%d)" % \
(bfd.architecture_name, bfd.architecture))
print("[+] BFD target name : %s" % bfd.target)
print("[+] Entry point : 0x%X" % bfd.start_address)
print("[+] Sections : %d" % len(bfd.sections))
#print "\n".join([str(s) for s in bfd.sections])
#
# Get the .text section for further usage.
#
section_name = ".text"
section = bfd.sections.get(section_name)
if not section:
print("[-] No section \'%s\' available." % section_name)
exit(0)
#
# Display its name (we get it from the section instance) and its index
# inside the binary file.
#
print("[+] Selected section information:")
print("\tName : %s" % section.name)
print("\tIndex : %d" % section.index)
# Dump the section content to a buffer
content = section.content
# Display approximate section length.
length = len(content) / 1024
if length == 0:
length = len(content) % 1024
length_unit = "Bytes"
else:
length_unit = "Kbytes"
print("\tLength : %(length)d %(length_unit)s" % vars())
#
# At this point we'll disassemble the entire section content. We'll obtain
# instruction address, size, type and disassembly (in text format).
#
try:
# Create opcodes instance to start code section disassembly.
opcodes = Opcodes(bfd)
# Set the code area we'll move through.
opcodes.initialize_smart_disassemble(content, section.vma)
# Set an internal -ready to use- callback function to print disassembly
# information from the current section content.
#opcodes.start_smart_disassemble(0, opcodes.print_single_instruction_callback)
#opcodes.start_smart_disassemble(0, print_file_line_callback)
except OpcodesException, err:
print("[-] Opcodes exception : %s" % err)
for vma, size, disasm in opcodes.disassemble(content, bfd.start_address):
print("0x%X (%d)\t %s" % (vma, size, disasm))
proc = Popen(["/usr/bin/addr2line", "-e", path, "-C", "-f", "-p", "-a", str(vma)], stdout=PIPE, stderr=PIPE)
stdout, stderr = proc.communicate()
print(stdout)
#print(disasm, opcodes.build_instruction(vma, size, disasm))
pass
except BfdException, err:
#print_exc()
print("Error : %s" % err)
finally:
if bfd:
# Check is we're working with an archive and close archived files
# before closing the container.
try:
# Release inner BFD files in case we're an archive BFD.
if bfd.is_archive:
[inner_bfd.close() for inner_bfd in bfd.archive_files]
except TypeError, err:
pass
# Release the current BFD and leave.
bfd.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment