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

change_rpath differs in behaviour from install_name_tool when handling duplicates #436

Closed
carlocab opened this issue Jan 18, 2022 · 4 comments · Fixed by #438
Closed

change_rpath differs in behaviour from install_name_tool when handling duplicates #436

carlocab opened this issue Jan 18, 2022 · 4 comments · Fixed by #438

Comments

@carlocab
Copy link
Member

Suppose I compile a dylib with a duplicate RPATH:

❯ clang -xc /dev/null -shared -rpath dupe -rpath dupe -o libdupes.dylib
❯ otool -l libdupes.dylib | rg -A2 LC_RPATH
          cmd LC_RPATH
      cmdsize 24
         path dupe (offset 12)
--
          cmd LC_RPATH
      cmdsize 24
         path dupe (offset 12)

(Admittedly, I don't know why one would do this, but pdnsrec still does.)

change_rpath handles changing one RPATH just fine, but chokes on the second:

❯ brew ruby -e 'MachO::Tools.change_rpath("libdupes.dylib", "dupe", "notdupe")'
❯ otool -l libdupes.dylib | rg -A2 LC_RPATH
          cmd LC_RPATH
      cmdsize 24
         path notdupe (offset 12)
--
          cmd LC_RPATH
      cmdsize 24
         path dupe (offset 12)
❯ brew ruby -e 'MachO::Tools.change_rpath("libdupes.dylib", "dupe", "notdupe")'
/usr/local/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-macho-3.0.0/lib/macho/macho_file.rb:388:in `change_rpath': notdupe already exists (MachO::RpathExistsError)
        from /usr/local/Homebrew/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/ruby-macho-3.0.0/lib/macho/tools.rb:60:in `change_rpath'
        from -e:1:in `<main>'

install_name_tool chugs along just fine, though:

❯ install_name_tool -rpath dupe notdupe libdupes.dylib
❯ otool -l libdupes.dylib | rg -A2 LC_RPATH
          cmd LC_RPATH
      cmdsize 24
         path notdupe (offset 12)
--
          cmd LC_RPATH
      cmdsize 24
         path notdupe (offset 12)

This is slightly related to changes we made in #362 and #366, and I think I realised this shortly after, but this slipped off my radar.

It might be that this is intentional and nothing needs changing here, but I just wanted to bring this up just in case you want ruby-macho to behave more look install_name_tool here.

@woodruffw
Copy link
Member

Yeah, I think #362 caused the deviation.

That change_rpath behavior is definitely not ideal, IMO: we should either change exactly one RPATH always (if possible) or change all of them at once, and never fail if some change is possible.

The MachO::Tool namespace is intended to imply some level of compatibility with otool and install_name_tool, so we should probably do what install_name_tool does in this case (even though I think that changing all RPATHs at once is more reasonable behavior).

@carlocab
Copy link
Member Author

carlocab commented Jan 18, 2022

To be fair, before #362 there was a different deviation.

Edit: No, I think the below is not true. I was misremembering how change_rpath works.


Note that emulating install_name_tool here might require rethinking how change_rpath works: currently, change_rpath deletes an rpath and then adds one. ruby-macho fails at the second step because it refuses to add an rpath that already exists.

This is also how install_name_tool behaves:

❯ otool -l libdupes.dylib | rg -A2 LC_RPATH
          cmd LC_RPATH
      cmdsize 24
         path dupe3 (offset 12)
--
          cmd LC_RPATH
      cmdsize 24
         path dupe (offset 12)
❯ install_name_tool -add_rpath dupe libdupes.dylib
error: /Library/Developer/CommandLineTools/usr/bin/install_name_tool: for: libdupes.dylib (for architecture x86_64) option "-add_rpath dupe" would duplicate path, file already has LC_RPATH for: dupe

I suppose you could have a special ignore_duplicates flag for add_rpath that's used inside change_rpath.

carlocab added a commit to carlocab/ruby-macho that referenced this issue Jan 18, 2022
This causes a deviation in behaviour from `install_name_tool`, which
will happily change an existing rpath to one that already exists.

Closes Homebrew#436.
carlocab added a commit to carlocab/ruby-macho that referenced this issue Jan 18, 2022
This causes a deviation in behaviour from `install_name_tool`, which
will happily change an existing rpath to one that already exists.

Closes Homebrew#436.
carlocab added a commit to carlocab/ruby-macho that referenced this issue Jan 18, 2022
This causes a deviation in behaviour from `install_name_tool`, which
will happily change an existing rpath to one that already exists.

Closes Homebrew#436.
@github-actions
Copy link

github-actions bot commented Feb 9, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@github-actions github-actions bot added the Stale label Feb 9, 2022
@woodruffw woodruffw removed the Stale label Feb 9, 2022
@github-actions
Copy link

github-actions bot commented Mar 3, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@github-actions github-actions bot added the Stale label Mar 3, 2022
woodruffw added a commit that referenced this issue Mar 3, 2022
This causes a deviation in behaviour from `install_name_tool`, which
will happily change an existing rpath to one that already exists.

Closes #436.

Co-authored-by: William Woodruff <[email protected]>
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants