< prev index next >

agent/src/os/linux/libproc_impl.c

Print this page
rev 8846 : 7127191: SA JSDB does not display native symbols correctly for transported Linux cores
Summary: Better handle SA_ALTROOT
Reviewed-by: sla, sspitsyn
rev 8847 : 8140482: Various minor code improvements (runtime)
Reviewed-by: dholmes, coleenp, sspitsyn, dsamersoff

@@ -27,55 +27,62 @@
 #include <string.h>
 #include <fcntl.h>
 #include <thread_db.h>
 #include "libproc_impl.h"
 
-static const char* alt_root = NULL;
-static int alt_root_len = -1;
-
 #define SA_ALTROOT "SA_ALTROOT"
 
-static void init_alt_root() {
-   if (alt_root_len == -1) {
+int pathmap_open(const char* name) {
+  static const char *alt_root = NULL;
+  static int alt_root_initialized = 0;
+
+  int fd;
+  char alt_path[PATH_MAX + 1], *alt_path_end;
+  const char *s;
+  int free_space;
+
+  if (!alt_root_initialized) {
+    alt_root_initialized = -1;
       alt_root = getenv(SA_ALTROOT);
-      if (alt_root) {
-         alt_root_len = strlen(alt_root);
-      } else {
-         alt_root_len = 0;
-      }
    }
-}
 
-int pathmap_open(const char* name) {
-   int fd;
-   char alt_path[PATH_MAX + 1];
+  if (alt_root == NULL) {
+    return open(name, O_RDONLY);
+  }
 
-   init_alt_root();
 
-   if (alt_root_len > 0) {
-      strcpy(alt_path, alt_root);
-      strcat(alt_path, name);
-      fd = open(alt_path, O_RDONLY);
-      if (fd >= 0) {
-         print_debug("path %s substituted for %s\n", alt_path, name);
-         return fd;
+  if (strlen(alt_root) + strlen(name) < PATH_MAX) {
+    // Buffer too small.
+    return -1;
       }
 
-      if (strrchr(name, '/')) {
-         strcpy(alt_path, alt_root);
-         strcat(alt_path, strrchr(name, '/'));
+  strncpy(alt_path, alt_root, PATH_MAX);
+  alt_path[PATH_MAX] = '\0';
+  alt_path_end = alt_path + strlen(alt_path);
+  free_space = PATH_MAX + 1 - (alt_path_end-alt_path);
+
+  // Strip path items one by one and try to open file with alt_root prepended.
+  s = name;
+  while (1) {
+    strncat(alt_path, s, free_space);
+    s += 1;  // Skip /.
+
          fd = open(alt_path, O_RDONLY);
          if (fd >= 0) {
             print_debug("path %s substituted for %s\n", alt_path, name);
             return fd;
          }
+
+    // Linker always put full path to solib to process, so we can rely
+    // on presence of /. If slash is not present, it means, that SOlib doesn't
+    // physically exist (e.g. linux-gate.so) and we fail opening it anyway
+    if ((s = strchr(s, '/')) == NULL) {
+      break;
       }
-   } else {
-      fd = open(name, O_RDONLY);
-      if (fd >= 0) {
-         return fd;
-      }
+
+    // Cut off what we appended above.
+    *alt_path_end = '\0';
    }
 
    return -1;
 }
 
< prev index next >