[PATCH] ld/Linux: determine program name in a more reliable manner

Jan Beulich jbeulich@suse.com
Fri Nov 28 09:13:33 GMT 2025


What argv[0] holds can be pretty arbitrary. As long as it's used for just
diagnostics, that may be pretty okay to go from, but ld also uses it to
find linker scripts. For that we want to be sure we start from the real
executable name. Which on Linux we can determine from the /proc/self/exe
symbolic link target (provided of course procfs is mounted).

While there constify program_name as well.
---
Question is whether we should split program_name: Continue using argv[0]
for diagnostics (invokees may deliberately use more readable names there),
while using the /proc/self/exe target only for passing to
make_relative_prefix().

Further, to become independent of the ldscripts symlink placed (too late,
see PR ld/33629) in .libs when --enable-shared is in use, should we check
for .libs as the last path component, i.e. retry invoking
make_relative_prefix() with that path component removed?

--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -67,7 +67,7 @@ char *default_target;
 const char *output_filename = "a.out";
 
 /* Name this program was invoked by.  */
-char *program_name;
+const char *program_name;
 
 /* The prefix for system library directories.  */
 const char *ld_sysroot;
@@ -567,6 +567,19 @@ report_phases (FILE * file, time_t * sta
   fflush (file);
 }
 
+static void
+set_program_name (const char *argv0)
+{
+  program_name = argv0;
+
+#if defined (__linux__) && _POSIX_VERSION >= 200112L
+  char name[PATH_MAX];
+  ssize_t len = readlink ("/proc/self/exe", name, ARRAY_SIZE (name));
+  if (len > 0 && (size_t)len < ARRAY_SIZE (name))
+    program_name = xmemdup (name, len, len + 1);
+#endif
+}
+
 int
 main (int argc, char **argv)
 {
@@ -581,7 +594,7 @@ main (int argc, char **argv)
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 
-  program_name = argv[0];
+  set_program_name (argv[0]);
   xmalloc_set_program_name (program_name);
 
   /* Check the LD_STATS environment variable before parsing the command line
--- a/ld/ldmain.h
+++ b/ld/ldmain.h
@@ -21,7 +21,7 @@
 #ifndef LDMAIN_H
 #define LDMAIN_H
 
-extern char *program_name;
+extern const char *program_name;
 extern const char *ld_sysroot;
 extern char *ld_canon_sysroot;
 extern int ld_canon_sysroot_len;


More information about the Binutils mailing list