[PATCH] D82051: [llvm-install-name-tool] Add -rpath option

Sameer Arora via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 22 22:33:01 PDT 2020


sameerarora101 marked 8 inline comments as done.
sameerarora101 added inline comments.


================
Comment at: llvm/tools/llvm-objcopy/CopyConfig.cpp:852
+    StringRef NewRPath = Arg->getValue(1);
+
+    // Cannot specify duplicate -rpath entries
----------------
alexshap wrote:
> 
>   # llvm::find_if - since the code is already inside the namespace "llvm" the prefix is unnecessary. 
> 
>   # StringRef can be passed by value 
> 
>   # You can reuse your code a tiny bit further + I would probably rename some things here:
> 
> ```
> auto Match  = [=](StringRef RPath) { return RPath == Old || RPath == New; };
>     
> auto It1 = find_if(Config.RPathsToUpdate, [](const std::pair<StringRef, StringRef> & OldNew) { 
>                                       return Match(OldNew.first) || Match(OldNew.second); });
> ```
nice, thanks! 😊 


================
Comment at: llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp:120
+template <typename T>
+static void updateLoadCommandName(LoadCommand *LC, StringRef NewName) {
+  uint32_t NewCmdsize = alignTo(sizeof(T) + NewName.size() + 1, 8);
----------------
alexshap wrote:
> Different load commands have very different payloads, so i think this function is a bit misleading.
> What about this:
> ```
> static void updateRPathLoadCommand(LoadCommand &LC, StringRef NewRPath) {
>     assert( ....  ); // make sure that LC is indeed LC_RPATH;
>     ...
> }
> ```
So it turns out the way to update LC name follows the same logic (as above) for all the options `-rpath`, `-id`, and `-change` for `llvm-install-name-tool`. Here is how I was thinking about using it :

`-rpath` : `updateLoadCommandName<MachO::rpath_command>(&LC, NewRPath);`,

`-id` : `updateLoadCommandName<MachO::dylib_command>(&LC, NewID);`

`-change` : `updateLoadCommandName<MachO::dylib_command>(&LC, NewInstallName);`

This allowed me to refactor the common logic of updating the name payload of any load command (instead of making it specific for rpath). Would this not be ok?


================
Comment at: llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp:269
 
+  for (std::pair<StringRef, StringRef> RPair : Config.RPathsToUpdate) {
+    StringRef OldRPath = RPair.first;
----------------
alexshap wrote:
> ```
> StringRef Old, New;
> for (std::tie(Old, New) : Config.RPathsToUpdate) {
>     ...
> }
> 
> ```
`for (std::tie(Old, New) : Config.RPathsToUpdate)` is perhaps not allowed : it says `for range declaration must declare a variable`. 

I have updated it to
```
StringRef OldRPath, NewRPath;
for (auto &RPair : Config.RPathsToUpdate) {
   std::tie(OldRPath, NewRPath) = RPair;
   ...
}
```
I hope this works?


================
Comment at: llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp:276
+      if (LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH) {
+        StringRef CurrentRPath =
+            StringRef(reinterpret_cast<char *>(LC.Payload.data()),
----------------
alexshap wrote:
> If I'm not mistaken there are multiple places where this construction is used, so i think we need to factor out it into a helper function.
> ```
>      StringRef getRPath(const LoadCommand &LC) {
>          assert(LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH &&
>                    "LC_RPATH is expected");
>          return StringRef(reinterpret_cast<char *>(LC.Payload.data()),
>                                    LC.Payload.size()).rtrim('\0');
>      }
> ```
> 
> Plus I would slightly reorganize the code (see below):
> 
> ```
> StringRef Old, New;
> for (std::tie(Old, New) : Config.RPathsToUpdate) {
>      auto It = find_if(Obj.LoadCommands, [](const LoadCommand &LC) { 
>                               return LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH &&
>                                          getRPath(LC) == Old); });
>      if (It == Obj.LoadCommands.end())
>          ...
>      if (getRPath(*It) == New)
>         ...
>      updateRPathLoadCommand(*It, New);
> }
> ```
Ok, I refactored getting the RPath construction into a separate function and updated it to be used by `add_rpath`, `delete_rpath` and `rpath` options.

For the reorganization, we need to check that `New` doesn't exists for **any** of the LC_RPATH commands. Please correct me in case I am wrong, but it seems that the above suggested code finds an LC_RPATH that matches `Old`. However, above, we throw an error only when either we can't find such a command (`It == Obj.LoadCommands.end()`) or if the command's rpath equals the `New` value(`getRPath(*It) == New`). But we need to throw the latter error in case **any** command's value equals `New`. Here is what I have done now:

```
StringRef Old, New;
  for (auto &RPair : Config.RPathsToUpdate) {
    std::tie(Old, New) = RPair;

    auto Match = [&Obj] (StringRef RPath) {
      return find_if(Obj.LoadCommands, [=](const LoadCommand &LC) {
        return LC.MachOLoadCommand.load_command_data.cmd == MachO::LC_RPATH &&
               getRPath(LC) == RPath;
      });
    };

    auto NewIt = Match(New);
    if (NewIt != Obj.LoadCommands.end())
      return Error

    auto OldIt = Match(Old);
    if (OldIt == Obj.LoadCommands.end())
        return Error

    updateLoadCommandName<MachO::rpath_command>(&(*OldIt), New);
  }

```
Would this work? Thanks.




Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82051/new/

https://reviews.llvm.org/D82051





More information about the llvm-commits mailing list