From patchwork Tue Jul 4 16:22:31 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wolfgang Grandegger X-Patchwork-Id: 784183 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3x28Sz2xYGz9t0j for ; Wed, 5 Jul 2017 02:23:47 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id B454987BA6; Tue, 4 Jul 2017 16:23:33 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id sMKHY78AfRdl; Tue, 4 Jul 2017 16:23:27 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by fraxinus.osuosl.org (Postfix) with ESMTP id C5D14879BE; Tue, 4 Jul 2017 16:23:20 +0000 (UTC) X-Original-To: buildroot@lists.busybox.net Delivered-To: buildroot@osuosl.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by ash.osuosl.org (Postfix) with ESMTP id 0FF931C42BB for ; Tue, 4 Jul 2017 16:22:51 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 0858788CB7 for ; Tue, 4 Jul 2017 16:22:51 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6fiaCE2YBuBq for ; Tue, 4 Jul 2017 16:22:49 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mailproxy01.manitu.net (mailproxy01.manitu.net [217.11.48.65]) by hemlock.osuosl.org (Postfix) with ESMTPS id A87E788A23 for ; Tue, 4 Jul 2017 16:22:48 +0000 (UTC) Received: from onex.fritz.box (aftr-88-217-180-55.dynamic.mnet-online.de [88.217.180.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: wg@grandegger.com) by mailproxy01.manitu.net (Postfix) with ESMTPSA id 9EF161260627; Tue, 4 Jul 2017 18:22:46 +0200 (CEST) From: Wolfgang Grandegger To: buildroot@buildroot.org Date: Tue, 4 Jul 2017 18:22:31 +0200 Message-Id: <1499185359-8293-3-git-send-email-wg@grandegger.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1499185359-8293-1-git-send-email-wg@grandegger.com> References: <1499185359-8293-1-git-send-email-wg@grandegger.com> Cc: Wolfgang Grandegger Subject: [Buildroot] [PATCH v6 02/10] package/patchelf: add patch for rpath sanitization under a root directory X-BeenThere: buildroot@busybox.net X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Discussion and development of buildroot List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: buildroot-bounces@busybox.net Sender: "buildroot" The patch allows to use patchelf to sanitize the rpath of the buildroot libraries and binaries using the option "--make-rpath-relative ". Recent versions of patchelf will not built on old Debian and RHEL systems due to C++11 constructs. Therefore we stick with v0.9 for the time being. Signed-off-by: Wolfgang Grandegger Signed-off-by: ... --- ...move-apparently-incorrect-usage-of-static.patch | 49 +++ ...unction-for-splitting-a-colon-separated-s.patch | 58 +++ ...to-make-the-rpath-relative-under-a-specif.patch | 419 +++++++++++++++++++++ 3 files changed, 526 insertions(+) create mode 100644 package/patchelf/0001-Remove-apparently-incorrect-usage-of-static.patch create mode 100644 package/patchelf/0002-Extract-a-function-for-splitting-a-colon-separated-s.patch create mode 100644 package/patchelf/0003-Add-option-to-make-the-rpath-relative-under-a-specif.patch diff --git a/package/patchelf/0001-Remove-apparently-incorrect-usage-of-static.patch b/package/patchelf/0001-Remove-apparently-incorrect-usage-of-static.patch new file mode 100644 index 0000000..46fd123 --- /dev/null +++ b/package/patchelf/0001-Remove-apparently-incorrect-usage-of-static.patch @@ -0,0 +1,49 @@ +From a365bcb7d7025da51b33165ef7ebc7180199a05e Mon Sep 17 00:00:00 2001 +From: Eelco Dolstra +Date: Mon, 19 Sep 2016 17:31:37 +0200 +Subject: [PATCH 14/30] Remove apparently incorrect usage of "static" + +--- + src/patchelf.cc | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +Index: patchelf-0.9.old/src/patchelf.cc +=================================================================== +--- patchelf-0.9.old.orig/src/patchelf.cc 2017-07-03 09:06:12.292069400 +0200 ++++ patchelf-0.9.old/src/patchelf.cc 2017-07-03 09:20:57.000000000 +0200 +@@ -941,7 +941,6 @@ + assert(strTabAddr == rdi(shdrDynStr.sh_addr)); + + /* Walk through the dynamic section, look for the DT_SONAME entry. */ +- static vector neededLibs; + dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); + Elf_Dyn * dynSoname = 0; + char * soname = 0; +@@ -949,8 +948,7 @@ + if (rdi(dyn->d_tag) == DT_SONAME) { + dynSoname = dyn; + soname = strTab + rdi(dyn->d_un.d_val); +- } else if (rdi(dyn->d_tag) == DT_INIT) +- neededLibs.push_back(string(strTab + rdi(dyn->d_un.d_val))); ++ } + } + + if (op == printSoname) { +@@ -1058,7 +1056,7 @@ + unless you use its `--enable-new-dtag' option, in which case it + generates a DT_RPATH and DT_RUNPATH pointing at the same + string. */ +- static vector neededLibs; ++ vector neededLibs; + dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); + Elf_Dyn * dynRPath = 0, * dynRunPath = 0; + char * rpath = 0; +@@ -1091,7 +1089,7 @@ + /* For each directory in the RPATH, check if it contains any + needed library. */ + if (op == rpShrink) { +- static vector neededLibFound(neededLibs.size(), false); ++ vector neededLibFound(neededLibs.size(), false); + + newRPath = ""; + diff --git a/package/patchelf/0002-Extract-a-function-for-splitting-a-colon-separated-s.patch b/package/patchelf/0002-Extract-a-function-for-splitting-a-colon-separated-s.patch new file mode 100644 index 0000000..63f3bce --- /dev/null +++ b/package/patchelf/0002-Extract-a-function-for-splitting-a-colon-separated-s.patch @@ -0,0 +1,58 @@ +From 2e3fdc2030c75c19df6fc2924083cfad53856562 Mon Sep 17 00:00:00 2001 +From: Tuomas Tynkkynen +Date: Fri, 3 Jun 2016 23:03:51 +0300 +Subject: [PATCH 08/30] Extract a function for splitting a colon-separated + string + +We're going to need this logic in another place, so make a function of +this. +--- + src/patchelf.cc | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +Index: patchelf-0.9/src/patchelf.cc +=================================================================== +--- patchelf-0.9.orig/src/patchelf.cc 2017-07-03 14:04:36.988281130 +0200 ++++ patchelf-0.9/src/patchelf.cc 2017-07-03 14:04:36.988281130 +0200 +@@ -57,6 +57,22 @@ + #define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym + + ++static vector splitColonDelimitedString(const char * s){ ++ vector parts; ++ const char * pos = s; ++ while (*pos) { ++ const char * end = strchr(pos, ':'); ++ if (!end) end = strchr(pos, 0); ++ ++ parts.push_back(string(pos, end - pos)); ++ if (*end == ':') ++end; ++ pos = end; ++ } ++ ++ return parts; ++} ++ ++ + static unsigned int getPageSize(){ + return pageSize; + } +@@ -1093,15 +1109,9 @@ + + newRPath = ""; + +- char * pos = rpath; +- while (*pos) { +- char * end = strchr(pos, ':'); +- if (!end) end = strchr(pos, 0); +- +- /* Get the name of the directory. */ +- string dirName(pos, end - pos); +- if (*end == ':') ++end; +- pos = end; ++ vector rpathDirs = splitColonDelimitedString(rpath); ++ for (vector::iterator it = rpathDirs.begin(); it != rpathDirs.end(); ++it) { ++ const string & dirName = *it; + + /* Non-absolute entries are allowed (e.g., the special + "$ORIGIN" hack). */ diff --git a/package/patchelf/0003-Add-option-to-make-the-rpath-relative-under-a-specif.patch b/package/patchelf/0003-Add-option-to-make-the-rpath-relative-under-a-specif.patch new file mode 100644 index 0000000..4f700d9 --- /dev/null +++ b/package/patchelf/0003-Add-option-to-make-the-rpath-relative-under-a-specif.patch @@ -0,0 +1,419 @@ +From af8d4a24a0ef613bdb47f0b1c3d962d59c53a4be Mon Sep 17 00:00:00 2001 +From: Wolfgang Grandegger +Date: Mon, 20 Feb 2017 16:29:24 +0100 +Subject: [PATCH] Add option to make the rpath relative under a specified root + directory + +Running "patchelf" with the option "--make-rpath-relative ROOTDIR" will +modify or delete the RPATHDIRs according the following rules +similar to Martin's patches [1] making the Buildroot toolchaing/SDK +relocatable. + +RPATHDIR starts with "$ORIGIN": + The original build-system already took care of setting a relative + RPATH, resolve it and test if it's valid (does exist) + +RPATHDIR starts with ROOTDIR: + The original build-system added some absolute RPATH (absolute on + the build machine). Test if it's valid (does exist). + +ROOTDIR/RPATHDIR exists: + The original build-system already took care of setting an absolute + RPATH (absolute in the final rootfs), resolve it and test if it's + valid (does exist). + +RPATHDIR points somewhere else: + (can be anywhere: build trees, staging tree, host location, + non-existing location, etc.). Just discard such a path. + +The option "--no-standard-libs" will discard RPATHDIRs ROOTDIR/lib and +ROOTDIR/usr/lib. Like "--shrink-rpath", RPATHDIRs are also discarded +if the directories do not contain a library referenced by the +DT_NEEDED fields. +If the option "--relative-to-file" is given, the rpath will start +with "$ORIGIN" making it relative to the ELF file, otherwise an +absolute path relative to ROOTDIR will be used. + +[1] http://lists.busybox.net/pipermail/buildroot/2016-April/159422.html + +Signed-off-by: Wolfgang Grandegger +--- + src/patchelf.cc | 187 ++++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 161 insertions(+), 26 deletions(-) + +Index: patchelf-0.9/src/patchelf.cc +=================================================================== +--- patchelf-0.9.orig/src/patchelf.cc 2017-07-03 14:05:07.196281487 +0200 ++++ patchelf-0.9/src/patchelf.cc 2017-07-03 16:13:38.590374530 +0200 +@@ -46,13 +46,16 @@ + + static bool forceRPath = false; + ++static bool noStandardLibDirs = false; ++ ++static bool relativeToFile = false; ++ + static string fileName; + static int pageSize = PAGESIZE; + + off_t fileSize, maxSize; + unsigned char * contents = 0; + +- + #define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn, class Elf_Sym + #define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym + +@@ -77,6 +80,49 @@ + return pageSize; + } + ++static bool absolutePathExists(const string & path, string & canonicalPath) ++{ ++ char *cpath = realpath(path.c_str(), NULL); ++ if (cpath) { ++ canonicalPath = cpath; ++ free(cpath); ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++static string makePathRelative(const string & path, ++ const string & refPath) ++{ ++ string relPath = "$ORIGIN"; ++ string p = path, refP = refPath; ++ size_t pos; ++ ++ /* Strip the common part of path and refPath */ ++ while (true) { ++ pos = p.find_first_of('/', 1); ++ if (refP.find_first_of('/', 1) != pos) ++ break; ++ if (p.substr(0, pos) != refP.substr(0, pos)) ++ break; ++ if (pos == string::npos) ++ break; ++ p = p.substr(pos); ++ refP = refP.substr(pos); ++ } ++ /* Check if both pathes are equal */ ++ if (p != refP) { ++ pos = 0; ++ while (pos != string::npos) { ++ pos =refP.find_first_of('/', pos + 1); ++ relPath.append("/.."); ++ } ++ relPath.append(p); ++ } ++ ++ return relPath; ++} + + template + class ElfFile +@@ -183,14 +229,18 @@ + + void setInterpreter(const string & newInterpreter); + +- typedef enum { rpPrint, rpShrink, rpSet, rpRemove } RPathOp; ++ typedef enum { rpPrint, rpShrink, rpMakeRelative, rpSet, rpRemove} RPathOp; + +- void modifyRPath(RPathOp op, string newRPath); ++ bool libFoundInRPath(const string & dirName, ++ const vector neededLibs, ++ vector & neededLibFound); ++ ++ void modifyRPath(RPathOp op, string rootDir, string newRPath); + + void addNeeded(set libs); + + void removeNeeded(set libs); +- ++ + void replaceNeeded(map& libs); + + void printNeededLibs(); +@@ -1041,7 +1091,27 @@ + + + template +-void ElfFile::modifyRPath(RPathOp op, string newRPath) ++bool ElfFile::libFoundInRPath(const string & dirName, ++ const vector neededLibs, vector & neededLibFound) ++{ ++ /* For each library that we haven't found yet, see if it ++ exists in this directory. */ ++ bool libFound = false; ++ for (unsigned int j = 0; j < neededLibs.size(); ++j) ++ if (!neededLibFound[j]) { ++ string libName = dirName + "/" + neededLibs[j]; ++ struct stat st; ++ if (stat(libName.c_str(), &st) == 0) { ++ neededLibFound[j] = true; ++ libFound = true; ++ } ++ } ++ return libFound; ++} ++ ++ ++template ++void ElfFile::modifyRPath(RPathOp op, string rootDir, string newRPath) + { + Elf_Shdr & shdrDynamic = findSection(".dynamic"); + +@@ -1096,6 +1166,11 @@ + return; + } + ++ if (op == rpMakeRelative && !rpath) { ++ debug("no RPATH to make relative\n"); ++ return; ++ } ++ + if (op == rpShrink && !rpath) { + debug("no RPATH to shrink\n"); + return; +@@ -1120,26 +1195,86 @@ + continue; + } + +- /* For each library that we haven't found yet, see if it +- exists in this directory. */ +- bool libFound = false; +- for (unsigned int j = 0; j < neededLibs.size(); ++j) +- if (!neededLibFound[j]) { +- string libName = dirName + "/" + neededLibs[j]; +- struct stat st; +- if (stat(libName.c_str(), &st) == 0) { +- neededLibFound[j] = true; +- libFound = true; +- } +- } +- +- if (!libFound) ++ if (!libFoundInRPath(dirName, neededLibs, neededLibFound)) + debug("removing directory `%s' from RPATH\n", dirName.c_str()); + else + concatToRPath(newRPath, dirName); + } + } + ++ /* Make the the RPATH relative to the specified path */ ++ if (op == rpMakeRelative) { ++ vector neededLibFound(neededLibs.size(), false); ++ string fileDir = fileName.substr(0, fileName.find_last_of("/")); ++ ++ newRPath = ""; ++ ++ vector rpathDirs = splitColonDelimitedString(rpath); ++ for (vector::iterator it = rpathDirs.begin(); it != rpathDirs.end(); ++it) { ++ const string & dirName = *it; ++ ++ string canonicalPath; ++ ++ /* Figure out if we should keep or discard the path. There are several ++ cases to be handled: ++ "dirName" starts with "$ORIGIN": ++ The original build-system already took care of setting a relative ++ RPATH. Resolve it and test if it's valid (does exist). ++ "dirName" start with "rootDir": ++ The original build-system added some absolute RPATH (absolute on ++ the build machine). Test if it's valid (does exist). ++ "rootDir"/"dirName" exists: ++ The original build-system already took care of setting an absolute ++ RPATH (absolute in the final rootfs). Resolve it and test if it's ++ valid (does exist). ++ "dirName" points somewhere else: ++ (can be anywhere: build trees, staging tree, host location, ++ non-existing location, etc.). Just discard such a path. */ ++ if (!dirName.compare(0, 7, "$ORIGIN")) { ++ string path = fileDir + dirName.substr(7); ++ if (!absolutePathExists(path, canonicalPath)) { ++ debug("removing directory '%s' from RPATH because '%s' doesn't exist\n", ++ dirName.c_str(), path.c_str()); ++ continue; ++ } ++ } else if (!dirName.compare(0, rootDir.length(), rootDir)) { ++ if (!absolutePathExists(dirName, canonicalPath)) { ++ debug("removing directory '%s' from RPATH because it doesn't exist\n", dirName.c_str()); ++ continue; ++ } ++ } else { ++ string path = rootDir + dirName; ++ if (!absolutePathExists(path, canonicalPath)) { ++ debug("removing directory '%s' from RPATH because it's not in rootdir\n", ++ dirName.c_str()); ++ continue; ++ } ++ } ++ ++ if (noStandardLibDirs) { ++ if (!canonicalPath.compare(rootDir + "/lib") || ++ !canonicalPath.compare(rootDir + "/usr/lib")) { ++ debug("removing directory '%s' from RPATH because it's a standard library directory\n", ++ dirName.c_str()); ++ continue; ++ } ++ } ++ ++ if (!libFoundInRPath(canonicalPath, neededLibs, neededLibFound)) { ++ debug("removing directory '%s' from RPATH because it does not contain needed libs\n", ++ dirName.c_str()); ++ continue; ++ } ++ ++ /* Finally make "canonicalPath" relative to "filedir" in "rootDir" */ ++ if (relativeToFile) ++ concatToRPath(newRPath, makePathRelative(canonicalPath, fileDir)); ++ else ++ concatToRPath(newRPath, canonicalPath.substr(rootDir.length())); ++ debug("keeping relative path of %s\n", canonicalPath.c_str()); ++ } ++ } ++ + if (op == rpRemove) { + if (!rpath) { + debug("no RPATH to delete\n"); +@@ -1261,35 +1396,35 @@ + void ElfFile::replaceNeeded(map& libs) + { + if (libs.empty()) return; +- ++ + Elf_Shdr & shdrDynamic = findSection(".dynamic"); + Elf_Shdr & shdrDynStr = findSection(".dynstr"); + char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); + + Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); +- ++ + unsigned int dynStrAddedBytes = 0; +- ++ + for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) { + if (rdi(dyn->d_tag) == DT_NEEDED) { + char * name = strTab + rdi(dyn->d_un.d_val); + if (libs.find(name) != libs.end()) { + const string & replacement = libs[name]; +- ++ + debug("replacing DT_NEEDED entry `%s' with `%s'\n", name, replacement.c_str()); +- ++ + // technically, the string referred by d_val could be used otherwise, too (although unlikely) + // we'll therefore add a new string + debug("resizing .dynstr ..."); +- ++ + string & newDynStr = replaceSection(".dynstr", + rdi(shdrDynStr.sh_size) + replacement.size() + 1 + dynStrAddedBytes); + setSubstr(newDynStr, rdi(shdrDynStr.sh_size) + dynStrAddedBytes, replacement + '\0'); +- ++ + dyn->d_un.d_val = shdrDynStr.sh_size + dynStrAddedBytes; +- ++ + dynStrAddedBytes += replacement.size() + 1; +- ++ + changed = true; + } else { + debug("keeping DT_NEEDED entry `%s'\n", name); +@@ -1311,7 +1446,7 @@ + for (set::iterator it = libs.begin(); it != libs.end(); it++) { + length += it->size() + 1; + } +- ++ + string & newDynStr = replaceSection(".dynstr", + rdi(shdrDynStr.sh_size) + length + 1); + set libStrings; +@@ -1321,7 +1456,7 @@ + libStrings.insert(rdi(shdrDynStr.sh_size) + pos); + pos += it->size() + 1; + } +- ++ + /* add all new needed entries to the dynamic section */ + string & newDynamic = replaceSection(".dynamic", + rdi(shdrDynamic.sh_size) + sizeof(Elf_Dyn) * libs.size()); +@@ -1342,7 +1477,7 @@ + wri(newDyn.d_un.d_val, *it); + setSubstr(newDynamic, i * sizeof(Elf_Dyn), string((char *) &newDyn, sizeof(Elf_Dyn))); + } +- ++ + changed = true; + } + +@@ -1413,7 +1548,9 @@ + static bool removeRPath = false; + static bool setRPath = false; + static bool printRPath = false; ++static bool makeRPathRelative = false; + static string newRPath; ++static string rootDir; + static set neededLibsToRemove; + static map neededLibsToReplace; + static set neededLibsToAdd; +@@ -1438,14 +1575,16 @@ + elfFile.setInterpreter(newInterpreter); + + if (printRPath) +- elfFile.modifyRPath(elfFile.rpPrint, ""); ++ elfFile.modifyRPath(elfFile.rpPrint, "", ""); + + if (shrinkRPath) +- elfFile.modifyRPath(elfFile.rpShrink, ""); ++ elfFile.modifyRPath(elfFile.rpShrink, "", ""); + else if (removeRPath) +- elfFile.modifyRPath(elfFile.rpRemove, ""); ++ elfFile.modifyRPath(elfFile.rpRemove, "", ""); + else if (setRPath) +- elfFile.modifyRPath(elfFile.rpSet, newRPath); ++ elfFile.modifyRPath(elfFile.rpSet, "", newRPath); ++ else if (makeRPathRelative) ++ elfFile.modifyRPath(elfFile.rpMakeRelative, rootDir, ""); + + if (printNeeded) elfFile.printNeededLibs(); + +@@ -1508,6 +1647,9 @@ + [--set-rpath RPATH]\n\ + [--remove-rpath]\n\ + [--shrink-rpath]\n\ ++ [--make-rpath-relative ROOTDIR]\n\ ++ [--no-standard-lib-dirs]\n\ ++ [--relative-to-file]\n\ + [--print-rpath]\n\ + [--force-rpath]\n\ + [--add-needed LIBRARY]\n\ +@@ -1541,7 +1683,7 @@ + if (++i == argc) error("missing argument"); + pageSize = atoi(argv[i]); + if (pageSize <= 0) error("invalid argument to --page-size"); +- } ++ } + else if (arg == "--print-interpreter") { + printInterpreter = true; + } +@@ -1564,6 +1706,17 @@ + setRPath = true; + newRPath = argv[i]; + } ++ else if (arg == "--make-rpath-relative") { ++ if (++i == argc) error("missing argument to --make-rpath-relative"); ++ makeRPathRelative = true; ++ rootDir = argv[i]; ++ } ++ else if (arg == "--no-standard-lib-dirs") { ++ noStandardLibDirs = true; ++ } ++ else if (arg == "--relative-to-file") { ++ relativeToFile = true; ++ } + else if (arg == "--print-rpath") { + printRPath = true; + }