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)
|