mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
79c6086d0d
`revng.api` now autodetects files (libraries, pipeline yamls) for initialization via the same mechanism used by `revng.cli`. This removes the need to pass them via environment variables from `revng daemon` and allows easy interaction with python's C API.
82 lines
2.1 KiB
Python
82 lines
2.1 KiB
Python
#
|
|
# This file is distributed under the MIT License. See LICENSE.md for details.
|
|
#
|
|
|
|
from pathlib import Path
|
|
from typing import List, Union
|
|
|
|
from elftools.elf.dynamic import DynamicSegment
|
|
from elftools.elf.elffile import ELFFile
|
|
|
|
|
|
def get_elf_needed(path: str) -> List[str]:
|
|
with open(path, "rb") as elf_file:
|
|
segments = [
|
|
segment
|
|
for segment in ELFFile(elf_file).iter_segments()
|
|
if isinstance(segment, DynamicSegment)
|
|
]
|
|
|
|
if len(segments) != 1:
|
|
return []
|
|
|
|
needed = [
|
|
to_string(tag.needed)
|
|
for tag in segments[0].iter_tags()
|
|
if tag.entry.d_tag == "DT_NEEDED"
|
|
]
|
|
|
|
elf_runpath: List[str] = [
|
|
tag.runpath for tag in segments[0].iter_tags() if tag.entry.d_tag == "DT_RUNPATH"
|
|
]
|
|
|
|
assert len(elf_runpath) < 2
|
|
|
|
if not elf_runpath:
|
|
return needed
|
|
|
|
runpaths = [
|
|
runpath.replace("$ORIGIN", str(Path(path).parent))
|
|
for runpath in elf_runpath[0].split(":")
|
|
]
|
|
absolute_needed = []
|
|
for lib in needed:
|
|
found = False
|
|
for runpath in runpaths:
|
|
full_path = Path(runpath) / lib
|
|
if full_path.is_file():
|
|
absolute_needed.append(str(full_path.resolve()))
|
|
found = True
|
|
break
|
|
|
|
if not found:
|
|
absolute_needed.append(lib)
|
|
|
|
return absolute_needed
|
|
|
|
|
|
def is_executable(path: str) -> bool:
|
|
with open(path, "rb") as program:
|
|
return program.read(4) == b"\x7fELF"
|
|
|
|
|
|
def is_dynamic(path: str) -> bool:
|
|
with open(path, "rb") as input_file:
|
|
return (
|
|
len(
|
|
[
|
|
segment
|
|
for segment in ELFFile(input_file).iter_segments()
|
|
if segment.header.p_type == "PT_DYNAMIC"
|
|
]
|
|
)
|
|
!= 0
|
|
)
|
|
|
|
|
|
# Use in case different version of pyelftools might give str or bytes
|
|
def to_string(obj: Union[str, bytes]) -> str:
|
|
if isinstance(obj, str):
|
|
return obj
|
|
return obj.decode("utf-8")
|