| 3384 | cm::optional<std::string>&, std::string const&, char const*, std::string*)>; |
| 3385 | |
| 3386 | cm::optional<bool> AdjustRPathELF(std::string const& file, |
| 3387 | EmptyCallback const& emptyCallback, |
| 3388 | AdjustCallback const& adjustCallback, |
| 3389 | std::string* emsg, bool* changed) |
| 3390 | { |
| 3391 | if (changed) { |
| 3392 | *changed = false; |
| 3393 | } |
| 3394 | int rp_count = 0; |
| 3395 | bool remove_rpath = true; |
| 3396 | cmSystemToolsRPathInfo rp[2]; |
| 3397 | { |
| 3398 | // Parse the ELF binary. |
| 3399 | cmELF elf(file.c_str()); |
| 3400 | if (!elf) { |
| 3401 | return cm::nullopt; // Not a valid ELF file. |
| 3402 | } |
| 3403 | |
| 3404 | if (!elf.HasDynamicSection()) { |
| 3405 | return true; // No dynamic section to update. |
| 3406 | } |
| 3407 | |
| 3408 | // Get the RPATH and RUNPATH entries from it. |
| 3409 | int se_count = 0; |
| 3410 | cmELF::StringEntry const* se[2] = { nullptr, nullptr }; |
| 3411 | char const* se_name[2] = { nullptr, nullptr }; |
| 3412 | if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) { |
| 3413 | se[se_count] = se_rpath; |
| 3414 | se_name[se_count] = "RPATH"; |
| 3415 | ++se_count; |
| 3416 | } |
| 3417 | if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) { |
| 3418 | se[se_count] = se_runpath; |
| 3419 | se_name[se_count] = "RUNPATH"; |
| 3420 | ++se_count; |
| 3421 | } |
| 3422 | if (se_count == 0) { |
| 3423 | return emptyCallback(emsg, elf); |
| 3424 | } |
| 3425 | |
| 3426 | for (int i = 0; i < se_count; ++i) { |
| 3427 | // If both RPATH and RUNPATH refer to the same string literal it |
| 3428 | // needs to be changed only once. |
| 3429 | if (rp_count && rp[0].Position == se[i]->Position) { |
| 3430 | continue; |
| 3431 | } |
| 3432 | |
| 3433 | // Store information about the entry in the file. |
| 3434 | rp[rp_count].Position = se[i]->Position; |
| 3435 | rp[rp_count].Size = se[i]->Size; |
| 3436 | rp[rp_count].Name = se_name[i]; |
| 3437 | |
| 3438 | // Adjust the rpath. |
| 3439 | cm::optional<std::string> outRPath; |
| 3440 | if (!adjustCallback(outRPath, se[i]->Value, se_name[i], emsg)) { |
| 3441 | return false; |
| 3442 | } |
| 3443 |
no test coverage detected
searching dependent graphs…