Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-writing load commands results in "Can't get the last load command" #1125

Open
palmerc opened this issue Nov 8, 2024 · 2 comments
Open

Comments

@palmerc
Copy link

palmerc commented Nov 8, 2024

Describe the bug
Rewriting the LOAD_DYLIB commands results in "Can't get the last load command"

To Reproduce

The general idea is you have some load_dylib command, so you create the new list of load_dylib commands and wipe out the old ones. Here is a sketch:

b = lief.parse(binary_path)

for library in b.libraries:
    library_path = pathlib.Path(library.name)
    print(f'\t{library_path}')
    if path_to_replace and replacement_path:
        if library.name.startswith(path_to_replace.as_posix()):
            relative_library_path = library_path.relative_to(path_to_replace)
            library_path = replacement_path / relative_library_path
        lc_dylib = lief.MachO.DylibCommand.load_dylib(name=library_path.as_posix(),
                                                      timestamp=library.timestamp)
        lc_dylib.compatibility_version = library.compatibility_version
        lc_dylib.current_version = library.current_version
        new_library = lc_dylib

        old_libraries.append(library)
        new_libraries.append(new_library)

Modifying the name property directly wrecks the load commands, hence, create a new load_dylib instead. Then b.remove and b.add the old and new version of the load_dylib commands maintaining the original ordering.

Expected behavior
Success. Instead each call to add gives "Can't get the last load command" and nothing is added.

Environment (please complete the following information):
Lief 15.1

xar.zip

@palmerc
Copy link
Author

palmerc commented Nov 8, 2024

As a workaround you can use lief to get the values and call out to install_name_tool

for old_library, new_library in zip(old_libraries, new_libraries):
  if old_library.name != new_library.name:
      install_name_tool_cmd = ['install_name_tool',
                               '-change', old_library.name, new_library.name,
                               binary_path]
      print(f'\t{install_name_tool_cmd}')
      subprocess.check_output(install_name_tool_cmd)

@romainthomas
Copy link
Member

Hi @palmerc

Sorry for the late reply. I confirm this issue and I'll see to support extending the DylibCommand path

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

No branches or pull requests

2 participants