dwarf-assembly/stats/pyelftools_overlay.py

111 lines
3 KiB
Python
Raw Normal View History

2018-07-10 14:41:33 +02:00
""" Overlay of PyElfTools for quick access to what we want here """
from elftools.elf.elffile import ELFFile
from elftools.common.exceptions import ELFError, DWARFError
2018-07-17 11:36:56 +02:00
from stats_accu import ElfType
2018-07-10 14:41:33 +02:00
import os
2018-08-08 14:31:05 +02:00
ELF_BLACKLIST = [
'/usr/lib/libavcodec.so',
]
2018-07-10 14:41:33 +02:00
def get_cfi(path):
''' Get the CFI entries from the ELF at the provided path '''
try:
with open(path, 'rb') as file_handle:
elf_file = ELFFile(file_handle)
if not elf_file.has_dwarf_info():
2018-08-08 14:31:05 +02:00
print("No DWARF")
2018-07-10 14:41:33 +02:00
return None
dw_info = elf_file.get_dwarf_info()
if dw_info.has_CFI():
cfis = dw_info.CFI_entries()
elif dw_info.has_EH_CFI():
cfis = dw_info.EH_CFI_entries()
else:
2018-08-08 14:31:05 +02:00
print("No CFI")
2018-07-10 14:41:33 +02:00
return None
except ELFError:
2018-08-08 14:31:05 +02:00
print("ELF Error")
2018-07-10 14:41:33 +02:00
return None
except DWARFError:
2018-08-08 14:31:05 +02:00
print("DWARF Error")
2018-07-10 14:41:33 +02:00
return None
except PermissionError:
2018-08-08 14:31:05 +02:00
print("Permission Error")
return None
except KeyError:
print("Key Error")
2018-07-10 14:41:33 +02:00
return None
return cfis
def system_elfs():
''' Iterator over system libraries '''
def readlink_rec(path):
if not os.path.islink(path):
return path
return readlink_rec(
os.path.join(os.path.dirname(path),
os.readlink(path)))
sysbin_dirs = [
2018-07-17 11:36:56 +02:00
('/lib', ElfType.ELF_LIB),
('/usr/lib', ElfType.ELF_LIB),
('/usr/local/lib', ElfType.ELF_LIB),
('/bin', ElfType.ELF_BINARY),
('/usr/bin', ElfType.ELF_BINARY),
('/usr/local/bin', ElfType.ELF_BINARY),
('/sbin', ElfType.ELF_BINARY),
2018-07-10 14:41:33 +02:00
]
to_explore = sysbin_dirs
seen_elfs = set()
while to_explore:
2018-07-17 11:36:56 +02:00
bindir, elftype = to_explore.pop()
2018-07-10 14:41:33 +02:00
if not os.path.isdir(bindir):
continue
for direntry in os.scandir(bindir):
if not direntry.is_file():
if direntry.is_dir():
2018-07-17 11:36:56 +02:00
to_explore.append((direntry.path, elftype))
2018-07-10 14:41:33 +02:00
continue
canonical_name = readlink_rec(direntry.path)
2018-08-08 14:31:05 +02:00
for blacked in ELF_BLACKLIST:
if canonical_name.startswith(blacked):
continue
2018-07-10 14:41:33 +02:00
if canonical_name in seen_elfs:
continue
2018-07-17 11:36:56 +02:00
valid_elf = True
try:
with open(canonical_name, 'rb') as handle:
magic_bytes = handle.read(4)
if magic_bytes != b'\x7fELF':
valid_elf = False
2018-08-08 14:31:05 +02:00
elf_class = handle.read(1)
if elf_class != b'\x02': # ELF64
valid_elf = False
2018-07-17 11:36:56 +02:00
except Exception:
continue
if not valid_elf:
continue
2018-08-08 14:31:05 +02:00
if not os.path.isfile(canonical_name):
continue
2018-07-10 14:41:33 +02:00
seen_elfs.add(canonical_name)
2018-07-17 11:36:56 +02:00
yield (canonical_name, elftype)