Skip to content

Instantly share code, notes, and snippets.

@valgur
Created October 8, 2023 16:43
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 valgur/28fa0ee0e3c59af301a6e10396981e0c to your computer and use it in GitHub Desktop.
Save valgur/28fa0ee0e3c59af301a6e10396981e0c to your computer and use it in GitHub Desktop.
Downloads and extracts all .deb files of libc6-dev and its dependencies for given Ubuntu release
import re
import subprocess
import sys
import tempfile
from pathlib import Path
import requests
def get_package_info(package_name, ubuntu_version, arch):
domain = "https://launchpad.net"
print(f"Loading {package_name} info...")
path = f"/ubuntu/{ubuntu_version}/{arch}/{package_name}"
html = requests.get(f"{domain}{path}").text
latest_version = re.search(rf'href="{path}/([^"]+)"', html).group(1)
info_html = requests.get(f"{domain}{path}/{latest_version}").text
deb_url = re.search(rf'href="([^"]+\.deb)"', info_html).group(1)
depends = []
if '<dl id="depends">' in info_html:
depends_section = info_html.split('<dl id="depends">')[1].split("</dl>")[0]
depends = re.findall(rf'{arch}/([^/"]+)"', depends_section)
return latest_version, deb_url, depends
def get_transitive_dev_packages(root_package, ubuntu_version, arch="amd64"):
def recurse(pkg):
if pkg not in info and pkg.endswith("-dev"):
version, deb_url, depends = get_package_info(pkg, ubuntu_version, arch)
info[pkg] = version, deb_url
for dep in depends:
recurse(dep)
info = {}
recurse(root_package)
return info
def download_dev_packages(output_dir, ubuntu_version, pkg_name, arch="amd64"):
packages = get_transitive_dev_packages(pkg_name, ubuntu_version, arch)
for package, (version, deb_url) in packages.items():
print(f"Downloading {package} {version}...")
deb = requests.get(deb_url).content
with open(f"{output_dir}/{package}_{version}_{arch}.deb", "wb") as f:
f.write(deb)
def extract_deb(deb_path, output_dir):
return subprocess.check_call(["dpkg-deb", "-xv", deb_path, output_dir])
def main(argv):
output_dir = Path(argv[1])
ubuntu_version = argv[2]
pkg = "libc6-dev"
with tempfile.TemporaryDirectory() as temp_dir:
temp_dir = Path(temp_dir)
temp_dir.mkdir(exist_ok=True, parents=True)
download_dev_packages(temp_dir, ubuntu_version, pkg)
for deb in temp_dir.glob("*.deb"):
extract_deb(deb, output_dir)
if __name__ == "__main__":
main(sys.argv)
@valgur
Copy link
Author

valgur commented Oct 8, 2023

The list of symbols defined in the .a and .so files can then be dumped from the extracted files using:

find usr -name '*.a' -type f | xargs objdump -t | grep ' F .text' | awk 'NF>1{print $NF}' | sort -u > static.list
find usr -name '*.so' -type f | xargs objdump -T | grep ' DF .text' | awk 'NF>1{print $NF}' | sort -u > shared.list

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment