[haiku-commits] haiku: hrev53097 - src/system/runtime_loader

  • From: Jérôme Duval <jerome.duval@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 27 Apr 2019 04:59:13 -0400 (EDT)

hrev53097 adds 1 changeset to branch 'master'
old head: 888652929c4c95ab2d639a85ffa2691a6e6df81f
new head: 35fa85dba5398fd6f00a25f2ec1afb9cba4d15ed
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=35fa85dba539+%5E888652929c4c

----------------------------------------------------------------------------

35fa85dba539: runtime_loader: load "LD_PRELOAD" libraries after the executable.
  
  This makes the behavior more standard, is still to be used with 
libroot_debug.so
  for instance.
  
  The old behavior is obtained with "LD_PRELOAD_ADDONS"; in fact a 
runtime_loader add-on
  needs to be entirely loaded before the executable to be effective. To be used 
with
  libltrace_stub.so for instance.
  
  Change-Id: I8536c5b8873f975405bea9eb4e2b92febabfc78a
  Reviewed-on: https://review.haiku-os.org/c/1409
  Reviewed-by: Jérôme Duval <jerome.duval@xxxxxxxxx>

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev53097
Commit:      35fa85dba5398fd6f00a25f2ec1afb9cba4d15ed
URL:         https://git.haiku-os.org/haiku/commit/?id=35fa85dba539
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Thu Mar 14 19:37:06 2019 UTC

----------------------------------------------------------------------------

1 file changed, 104 insertions(+), 23 deletions(-)
src/system/runtime_loader/elf.cpp | 127 ++++++++++++++++++++++++++++------

----------------------------------------------------------------------------

diff --git a/src/system/runtime_loader/elf.cpp 
b/src/system/runtime_loader/elf.cpp
index 778064a8ef..916ed445cf 100644
--- a/src/system/runtime_loader/elf.cpp
+++ b/src/system/runtime_loader/elf.cpp
@@ -47,8 +47,8 @@ typedef void (*initfini_array_function)();
 bool gProgramLoaded = false;
 image_t* gProgramImage;
 
-static image_t** sPreloadedImages = NULL;
-static uint32 sPreloadedImageCount = 0;
+static image_t** sPreloadedAddons = NULL;
+static uint32 sPreloadedAddonCount = 0;
 
 static recursive_lock sLock = RECURSIVE_LOCK_INITIALIZER(kLockName);
 
@@ -68,8 +68,81 @@ find_dt_rpath(image_t *image)
 }
 
 
+image_id
+preload_image(char const* path, image_t **image)
+{
+       if (path == NULL)
+               return B_BAD_VALUE;
+
+       KTRACE("rld: preload_image(\"%s\")", path);
+
+       status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, image);
+       if (status < B_OK) {
+               KTRACE("rld: preload_image(\"%s\") failed to load container: 
%s", path,
+                       strerror(status));
+               return status;
+       }
+
+       if ((*image)->find_undefined_symbol == NULL)
+               (*image)->find_undefined_symbol = find_undefined_symbol_global;
+
+       KTRACE("rld: preload_image(\"%s\") done: id: %" B_PRId32, path, 
(*image)->id);
+
+       return (*image)->id;
+}
+
+
+static void
+preload_images(image_t **image, int32 *_count = NULL)
+{
+       const char* imagePaths = getenv("LD_PRELOAD");
+       if (imagePaths == NULL) {
+               if (_count != NULL)
+                       *_count = 0;
+               return;
+       }
+
+       int32 count = 0;
+
+       while (*imagePaths != '\0') {
+               // find begin of image path
+               while (*imagePaths != '\0' && isspace(*imagePaths))
+                       imagePaths++;
+
+               if (*imagePaths == '\0')
+                       break;
+
+               // find end of image path
+               const char* imagePath = imagePaths;
+               while (*imagePaths != '\0' && !isspace(*imagePaths))
+                       imagePaths++;
+
+               // extract the path
+               char path[B_PATH_NAME_LENGTH];
+               size_t pathLen = imagePaths - imagePath;
+               if (pathLen > sizeof(path) - 1)
+                       continue;
+
+               if (image == NULL) {
+                       count++;
+                       continue;
+               }
+               memcpy(path, imagePath, pathLen);
+               path[pathLen] = '\0';
+
+               // load the image
+               preload_image(path, &image[count++]);
+       }
+
+       KTRACE("rld: preload_images count: %d", count);
+
+       if (_count != NULL)
+               *_count = count;
+}
+
+
 static status_t
-load_immediate_dependencies(image_t *image)
+load_immediate_dependencies(image_t *image, bool preload)
 {
        elf_dyn *d = (elf_dyn *)image->dynamic_ptr;
        bool reportErrors = report_errors();
@@ -82,6 +155,11 @@ load_immediate_dependencies(image_t *image)
 
        image->flags |= RFLAG_DEPENDENCIES_LOADED;
 
+       int32 preloadedCount = 0;
+       if (preload) {
+               preload_images(NULL, &preloadedCount);
+               image->num_needed += preloadedCount;
+       }
        if (image->num_needed == 0)
                return B_OK;
 
@@ -97,9 +175,11 @@ load_immediate_dependencies(image_t *image)
        }
 
        memset(image->needed, 0, image->num_needed * sizeof(image_t *));
+       if (preload)
+               preload_images(image->needed);
        rpath = find_dt_rpath(image);
 
-       for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) {
+       for (i = 0, j = preloadedCount; d[i].d_tag != DT_NULL; i++) {
                switch (d[i].d_tag) {
                        case DT_NEEDED:
                        {
@@ -159,14 +239,15 @@ load_immediate_dependencies(image_t *image)
 
 
 static status_t
-load_dependencies(image_t* image)
+load_dependencies(image_t* image, bool preload = false)
 {
        // load dependencies (breadth-first)
        for (image_t* otherImage = image; otherImage != NULL;
                        otherImage = otherImage->next) {
-               status_t status = load_immediate_dependencies(otherImage);
+               status_t status = load_immediate_dependencies(otherImage, 
preload);
                if (status != B_OK)
                        return status;
+               preload = false;
        }
 
        // Check the needed versions for the given image and all newly loaded
@@ -297,34 +378,34 @@ inject_runtime_loader_api(image_t* rootImage)
 
 
 static status_t
-add_preloaded_image(image_t* image)
+add_preloaded_addon(image_t* image)
 {
        // We realloc() everytime -- not particularly efficient, but good 
enough for
-       // small number of preloaded images.
-       image_t** newArray = (image_t**)realloc(sPreloadedImages,
-               sizeof(image_t*) * (sPreloadedImageCount + 1));
+       // small number of preloaded addons.
+       image_t** newArray = (image_t**)realloc(sPreloadedAddons,
+               sizeof(image_t*) * (sPreloadedAddonCount + 1));
        if (newArray == NULL)
                return B_NO_MEMORY;
 
-       sPreloadedImages = newArray;
-       newArray[sPreloadedImageCount++] = image;
+       sPreloadedAddons = newArray;
+       newArray[sPreloadedAddonCount++] = image;
 
        return B_OK;
 }
 
 
 image_id
-preload_image(char const* path)
+preload_addon(char const* path)
 {
        if (path == NULL)
                return B_BAD_VALUE;
 
-       KTRACE("rld: preload_image(\"%s\")", path);
+       KTRACE("rld: preload_addon(\"%s\")", path);
 
        image_t *image = NULL;
        status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, &image);
        if (status < B_OK) {
-               KTRACE("rld: preload_image(\"%s\") failed to load container: 
%s", path,
+               KTRACE("rld: preload_addon(\"%s\") failed to load container: 
%s", path,
                        strerror(status));
                return status;
        }
@@ -342,7 +423,7 @@ preload_image(char const* path)
        if (status < B_OK)
                goto err;
 
-       status = add_preloaded_image(image);
+       status = add_preloaded_addon(image);
        if (status < B_OK)
                goto err;
 
@@ -359,12 +440,12 @@ preload_image(char const* path)
                add_add_on(image, addOnStruct);
        }
 
-       KTRACE("rld: preload_image(\"%s\") done: id: %" B_PRId32, path, 
image->id);
+       KTRACE("rld: preload_addon(\"%s\") done: id: %" B_PRId32, path, 
image->id);
 
        return image->id;
 
 err:
-       KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status));
+       KTRACE("rld: preload_addon(\"%s\") failed: %s", path, strerror(status));
 
        dequeue_loaded_image(image);
        delete_image(image);
@@ -373,9 +454,9 @@ err:
 
 
 static void
-preload_images()
+preload_addons()
 {
-       const char* imagePaths = getenv("LD_PRELOAD");
+       const char* imagePaths = getenv("LD_PRELOAD_ADDONS");
        if (imagePaths == NULL)
                return;
 
@@ -401,7 +482,7 @@ preload_images()
                path[pathLen] = '\0';
 
                // load the image
-               preload_image(path);
+               preload_addon(path);
        }
 }
 
@@ -420,7 +501,7 @@ load_program(char const *path, void **_entry)
        RecursiveLocker _(sLock);
                // for now, just do stupid simple global locking
 
-       preload_images();
+       preload_addons();
 
        TRACE(("rld: load %s\n", path));
 
@@ -431,7 +512,7 @@ load_program(char const *path, void **_entry)
        if (gProgramImage->find_undefined_symbol == NULL)
                gProgramImage->find_undefined_symbol = 
find_undefined_symbol_global;
 
-       status = load_dependencies(gProgramImage);
+       status = load_dependencies(gProgramImage, true);
        if (status < B_OK)
                goto err;
 


Other related posts:

  • » [haiku-commits] haiku: hrev53097 - src/system/runtime_loader - Jérôme Duval