Skip to content

Instantly share code, notes, and snippets.

@thewh1teagle
Last active February 2, 2024 09:09
Show Gist options
  • Save thewh1teagle/20d412f54333cd4951b49d8a1584ac13 to your computer and use it in GitHub Desktop.
Save thewh1teagle/20d412f54333cd4951b49d8a1584ac13 to your computer and use it in GitHub Desktop.
print dependencies of binary
from typing import List
from pathlib import Path
import os
import re
import subprocess
import sys
class Dependency:
def __init__(self, parent: Path, name: str, path: Path, address: str):
self.parent = parent
self.name = name
self.path = path
self.address = address
def __str__(self):
return f"{self.name} => {self.path} ({self.address})"
def __repr__(self) -> str:
return self.__str__()
class DependencyFinder:
def __init__(self):
pass
@staticmethod
def normalize_msys2_path(path: Path) -> Path:
path = str(path)
if path.startswith('/c'):
path = 'C:\\' + path[2:]
path = str(path).replace('/', '\\')
return Path(path)
def find_deps(self, path: Path, recursive=False, max_depth=None, current_depth=0, additional_search_paths: List[Path] = []) -> List[Dependency]:
"""
Get list of shared libraries dependencies from path
"""
result = []
# Convert to path
if not isinstance(path, Path):
path = Path(path)
if os.getenv('MSYSTEM'):
path = self.normalize_msys2_path(path)
# Check exists
if not path.exists():
raise FileNotFoundError(f"No file at {path}")
env = os.environ.copy()
if additional_search_paths:
for search_path in additional_search_paths:
PATH = env['PATH']
env['PATH'] = f'{search_path};{PATH}'
res = subprocess.run(['ldd', str(path)], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
res.check_returncode()
output = res.stdout.decode('utf-8')
pattern = re.compile("\s*(\S+) => (.+) \((.+)\)")
matches = re.findall(pattern, output)
for match in matches:
name, dep_path, addr = match
dep = Dependency(path, name, Path(dep_path), addr)
result.append(dep)
# Recursively find dependencies if the 'recursive' flag is set and max_depth is not reached
if recursive and (max_depth is None or current_depth < max_depth):
result.extend(self.find_deps(Path(dep_path), recursive=True, max_depth=max_depth, current_depth=current_depth + 1))
return result
finder = DependencyFinder()
deps = finder.find_deps(sys.argv[1], recursive=True, max_depth=1, additional_search_paths=[Path('./vibe_0.0.4_x64-setup').absolute()])
dep_set = set()
for dep in deps:
if "Windows/" not in str(dep.path):
dep_set.add(dep)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment