-
-
Notifications
You must be signed in to change notification settings - Fork 635
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial support for Apple's dyld shared cache
- Loading branch information
1 parent
91a4710
commit 442fb46
Showing
71 changed files
with
3,698 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#!/usr/bin/env python | ||
''' | ||
This script lists libraries embedded in a dyld shared cache file | ||
Note: this script is only working with the extended version of LIEF | ||
''' | ||
|
||
import sys | ||
import lief | ||
import argparse | ||
from pathlib import Path | ||
from typing import Optional | ||
|
||
def main() -> int: | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument("target", type=Path, | ||
help='Target dyld shared file (file or dir)') | ||
args = parser.parse_args() | ||
|
||
target: Path = args.target | ||
if not target.exists(): | ||
print(f"'{target}' does not exist") | ||
return 1 | ||
|
||
dyld_cache = lief.dsc.load(target) | ||
if dyld_cache is None: | ||
print(f"Can't parse '{target}'") | ||
|
||
for lib in dyld_cache.libraries: | ||
print(f"0x{lib.address:016x} {lib.path}") | ||
|
||
for idx, info in enumerate(dyld_cache.mapping_info): | ||
print(f"mapping_info[{idx:02d}]: [{info.address:016x}, {info.end_address:016x}] -> 0x{info.file_offset:016x}") | ||
|
||
for idx, subcache in enumerate(dyld_cache.subcaches): | ||
uuid_str = ':'.join(map(lambda e: f"{e:02x}", subcache.uuid)) | ||
print(f"cache[{idx:02d}]: {uuid_str} {subcache.suffix}") | ||
|
||
if __name__ == "__main__": | ||
raise SystemExit(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
from typing import Any, ClassVar, Optional | ||
|
||
from typing import overload | ||
import collections.abc | ||
import lief.MachO # type: ignore | ||
import lief.dsc # type: ignore | ||
import lief.dsc.DyldSharedCache # type: ignore | ||
import lief.dsc.Dylib # type: ignore | ||
import os | ||
|
||
class DyldSharedCache: | ||
class ARCH: | ||
ARM64: ClassVar[DyldSharedCache.ARCH] = ... | ||
ARM64E: ClassVar[DyldSharedCache.ARCH] = ... | ||
ARMV5: ClassVar[DyldSharedCache.ARCH] = ... | ||
ARMV6: ClassVar[DyldSharedCache.ARCH] = ... | ||
ARMV7: ClassVar[DyldSharedCache.ARCH] = ... | ||
I386: ClassVar[DyldSharedCache.ARCH] = ... | ||
UNKNOWN: ClassVar[DyldSharedCache.ARCH] = ... | ||
X86_64: ClassVar[DyldSharedCache.ARCH] = ... | ||
X86_64H: ClassVar[DyldSharedCache.ARCH] = ... | ||
__name__: str | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
def __ge__(self, other) -> bool: ... | ||
def __gt__(self, other) -> bool: ... | ||
def __hash__(self) -> int: ... | ||
def __index__(self) -> Any: ... | ||
def __int__(self) -> int: ... | ||
def __le__(self, other) -> bool: ... | ||
def __lt__(self, other) -> bool: ... | ||
|
||
class PLATFORM: | ||
ANY: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
BRIDGEOS: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
DRIVERKIT: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
FIRMWARE: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
IOS: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
IOSMAC: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
IOS_SIMULATOR: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
MACOS: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
SEPOS: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
TVOS: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
TVOS_SIMULATOR: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
UNKNOWN: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
VISIONOS: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
VISIONOS_SIMULATOR: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
WATCHOS: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
WATCHOS_SIMULATOR: ClassVar[DyldSharedCache.PLATFORM] = ... | ||
__name__: str | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
def __ge__(self, other) -> bool: ... | ||
def __gt__(self, other) -> bool: ... | ||
def __hash__(self) -> int: ... | ||
def __index__(self) -> Any: ... | ||
def __int__(self) -> int: ... | ||
def __le__(self, other) -> bool: ... | ||
def __lt__(self, other) -> bool: ... | ||
|
||
class VERSION: | ||
DYLD_1042_1: ClassVar[DyldSharedCache.VERSION] = ... | ||
DYLD_195_5: ClassVar[DyldSharedCache.VERSION] = ... | ||
DYLD_239_3: ClassVar[DyldSharedCache.VERSION] = ... | ||
DYLD_360_14: ClassVar[DyldSharedCache.VERSION] = ... | ||
DYLD_421_1: ClassVar[DyldSharedCache.VERSION] = ... | ||
DYLD_832_7_1: ClassVar[DyldSharedCache.VERSION] = ... | ||
DYLD_940: ClassVar[DyldSharedCache.VERSION] = ... | ||
DYLD_95_3: ClassVar[DyldSharedCache.VERSION] = ... | ||
UNKNOWN: ClassVar[DyldSharedCache.VERSION] = ... | ||
UNRELEASED: ClassVar[DyldSharedCache.VERSION] = ... | ||
__name__: str | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
def __ge__(self, other) -> bool: ... | ||
def __gt__(self, other) -> bool: ... | ||
def __hash__(self) -> int: ... | ||
def __index__(self) -> Any: ... | ||
def __int__(self) -> int: ... | ||
def __le__(self, other) -> bool: ... | ||
def __lt__(self, other) -> bool: ... | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
def enable_caching(self, target_dir: str) -> None: ... | ||
def find_lib_from_name(self, name: str) -> Optional[lief.dsc.Dylib]: ... | ||
def find_lib_from_path(self, path: str) -> Optional[lief.dsc.Dylib]: ... | ||
def find_lib_from_va(self, virtual_address: int) -> Optional[lief.dsc.Dylib]: ... | ||
def flush_cache(self) -> None: ... | ||
@staticmethod | ||
def from_files(files: list[str]) -> Optional[lief.dsc.DyldSharedCache]: ... | ||
@staticmethod | ||
def from_path(path: str, arch: str = ...) -> Optional[lief.dsc.DyldSharedCache]: ... | ||
@property | ||
def arch(self) -> lief.dsc.DyldSharedCache.ARCH: ... | ||
@property | ||
def arch_name(self) -> str: ... | ||
@property | ||
def filename(self) -> str: ... | ||
@property | ||
def filepath(self) -> str: ... | ||
@property | ||
def has_subcaches(self) -> bool: ... | ||
@property | ||
def libraries(self) -> collections.abc.Sequence[Optional[lief.dsc.Dylib]]: ... | ||
@property | ||
def load_address(self) -> int: ... | ||
@property | ||
def mapping_info(self) -> collections.abc.Sequence[Optional[lief.dsc.MappingInfo]]: ... | ||
@property | ||
def platform(self) -> lief.dsc.DyldSharedCache.PLATFORM: ... | ||
@property | ||
def subcaches(self) -> collections.abc.Sequence[Optional[lief.dsc.SubCache]]: ... | ||
@property | ||
def version(self) -> lief.dsc.DyldSharedCache.VERSION: ... | ||
|
||
class Dylib: | ||
class extract_opt_t: | ||
create_dyld_chained_fixup_cmd: bool | ||
fix_branches: bool | ||
fix_memory: bool | ||
fix_objc: bool | ||
fix_relocations: bool | ||
pack: bool | ||
def __init__(self) -> None: ... | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
def get(self, opt: lief.dsc.Dylib.extract_opt_t = ...) -> Optional[lief.MachO.Binary]: ... | ||
@property | ||
def address(self) -> int: ... | ||
@property | ||
def inode(self) -> int: ... | ||
@property | ||
def modtime(self) -> int: ... | ||
@property | ||
def padding(self) -> int: ... | ||
@property | ||
def path(self) -> str: ... | ||
|
||
class MappingInfo: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
@property | ||
def address(self) -> int: ... | ||
@property | ||
def end_address(self) -> int: ... | ||
@property | ||
def file_offset(self) -> int: ... | ||
@property | ||
def init_prot(self) -> int: ... | ||
@property | ||
def max_prot(self) -> int: ... | ||
@property | ||
def size(self) -> int: ... | ||
|
||
class SubCache: | ||
def __init__(self, *args, **kwargs) -> None: ... | ||
@property | ||
def cache(self) -> Optional[lief.dsc.DyldSharedCache]: ... | ||
@property | ||
def suffix(self) -> str: ... | ||
@property | ||
def uuid(self) -> list[int]: ... | ||
@property | ||
def vm_offset(self) -> int: ... | ||
|
||
@overload | ||
def enable_cache() -> bool: ... | ||
@overload | ||
def enable_cache(target_cache_dir: str) -> bool: ... | ||
@overload | ||
def load(files: list[str]) -> Optional[lief.dsc.DyldSharedCache]: ... | ||
@overload | ||
def load(path: os.PathLike, arch: str = ...) -> Optional[lief.dsc.DyldSharedCache]: ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
target_sources(pyLIEF PRIVATE | ||
init.cpp | ||
pyDyldSharedCache.cpp | ||
pyDylib.cpp | ||
pyMappingInfo.cpp | ||
pySubCache.cpp | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#include "DyldSharedCache/init.hpp" | ||
#include "DyldSharedCache/pyDyldSharedCache.hpp" | ||
#include "LIEF/DyldSharedCache/caching.hpp" | ||
|
||
#include <nanobind/stl/string.h> | ||
#include <nanobind/stl/unique_ptr.h> | ||
|
||
namespace LIEF::dsc { | ||
class DyldSharedCache; | ||
class Dylib; | ||
class SubCache; | ||
class MappingInfo; | ||
} | ||
|
||
namespace LIEF::dsc::py { | ||
void init(nb::module_& m) { | ||
nb::module_ mod = m.def_submodule("dsc"); | ||
|
||
mod.def("enable_cache", nb::overload_cast<>(&enable_cache), | ||
R"doc( | ||
Enable globally cache/memoization. One can also leverage this function | ||
by setting the environment variable ``DYLDSC_ENABLE_CACHE`` to ``1`` | ||
By default, LIEF will use the directory specified by the environment | ||
variable ``DYLDSC_CACHE_DIR`` as its cache-root directory: | ||
.. code-block:: console | ||
DYLDSC_ENABLE_CACHE=1 DYLDSC_CACHE_DIR=/tmp/my_dir python ./my-script.py | ||
Otherwise, if ``DYLDSC_CACHE_DIR`` is not set, LIEF will use the following | ||
directory (in this priority): | ||
1. System or user cache directory | ||
- macOS: ``DARWIN_USER_TEMP_DIR`` / ``DARWIN_USER_CACHE_DIR`` + ``/dyld_shared_cache`` | ||
- Linux: ``${XDG_CACHE_HOME}/dyld_shared_cache`` | ||
- Windows: ``%LOCALAPPDATA%\dyld_shared_cache`` | ||
2. Home directory | ||
- macOS/Linux: ``$HOME/.dyld_shared_cache`` | ||
- Windows: ``%USERPROFILE%\.dyld_shared_cache`` | ||
See :meth:`lief.dsc.DyldSharedCache.enable_caching` for a finer granularity | ||
)doc"_doc | ||
); | ||
|
||
mod.def("enable_cache", nb::overload_cast<const std::string&>(&enable_cache), | ||
R"doc( | ||
Same behavior as the other :meth:`~.enable_cache` function but using a | ||
user-provided cache directory instead of an inferred one. | ||
)doc"_doc, "target_cache_dir"_a | ||
); | ||
|
||
create<LIEF::dsc::DyldSharedCache>(mod); | ||
create<LIEF::dsc::Dylib>(mod); | ||
create<LIEF::dsc::SubCache>(mod); | ||
create<LIEF::dsc::MappingInfo>(mod); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifndef PY_LIEF_DSC_INIT_H | ||
#define PY_LIEF_DSC_INIT_H | ||
#include "pyLIEF.hpp" | ||
|
||
namespace LIEF::dsc::py { | ||
void init(nb::module_& m); | ||
} | ||
#endif |
Oops, something went wrong.