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

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 26 Nov 2013 16:41:16 +0100 (CET)

hrev46449 adds 1 changeset to branch 'master'
old head: 509755e136168e2930dd7e1301d979f6e9244778
new head: 8d23c440f7b0433f0daccf7e4018f99b8d3c3459
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=8d23c44+%5E509755e

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

8d23c44: runtime loader: Add support for $ORIGIN in rpath
  
  Like in Linux it resolves to the directory of the shared object whose
  needed library is to be loaded.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

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

Revision:    hrev46449
Commit:      8d23c440f7b0433f0daccf7e4018f99b8d3c3459
URL:         http://cgit.haiku-os.org/haiku/commit/?id=8d23c44
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Tue Nov 26 15:39:50 2013 UTC

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

5 files changed, 78 insertions(+), 37 deletions(-)
src/system/runtime_loader/elf.cpp                |  8 +-
src/system/runtime_loader/elf_load_image.cpp     |  4 +-
src/system/runtime_loader/elf_load_image.h       |  2 +-
src/system/runtime_loader/runtime_loader.cpp     | 98 ++++++++++++++------
.../runtime_loader/runtime_loader_private.h      |  3 +-

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

diff --git a/src/system/runtime_loader/elf.cpp 
b/src/system/runtime_loader/elf.cpp
index 430ee9f..e7d7514 100644
--- a/src/system/runtime_loader/elf.cpp
+++ b/src/system/runtime_loader/elf.cpp
@@ -119,7 +119,7 @@ load_immediate_dependencies(image_t *image)
                                const char *name = STRING(image, neededOffset);
 
                                status_t loadStatus = load_image(name, 
B_LIBRARY_IMAGE,
-                                       rpath, &image->needed[j]);
+                                       rpath, image->path, &image->needed[j]);
                                if (loadStatus < B_OK) {
                                        status = loadStatus;
                                        // correct error code in case the file 
could not been found
@@ -308,7 +308,7 @@ preload_image(char const* path)
        KTRACE("rld: preload_image(\"%s\")", path);
 
        image_t *image = NULL;
-       status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, &image);
+       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));
@@ -410,7 +410,7 @@ load_program(char const *path, void **_entry)
 
        TRACE(("rld: load %s\n", path));
 
-       status = load_image(path, B_APP_IMAGE, NULL, &gProgramImage);
+       status = load_image(path, B_APP_IMAGE, NULL, NULL, &gProgramImage);
        if (status < B_OK)
                goto err;
 
@@ -516,7 +516,7 @@ load_library(char const *path, uint32 flags, bool addOn, 
void** _handle)
                }
        }
 
-       status = load_image(path, type, NULL, &image);
+       status = load_image(path, type, NULL, NULL, &image);
        if (status < B_OK) {
                rld_unlock();
                KTRACE("rld: load_library(\"%s\") failed to load container: 
%s", path,
diff --git a/src/system/runtime_loader/elf_load_image.cpp 
b/src/system/runtime_loader/elf_load_image.cpp
index 2b12538..f1c17b4 100644
--- a/src/system/runtime_loader/elf_load_image.cpp
+++ b/src/system/runtime_loader/elf_load_image.cpp
@@ -377,7 +377,7 @@ parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize,
 
 status_t
 load_image(char const* name, image_type type, const char* rpath,
-       image_t** _image)
+       const char* requestingObjectPath, image_t** _image)
 {
        int32 pheaderSize, sheaderSize;
        char path[PATH_MAX];
@@ -421,7 +421,7 @@ load_image(char const* name, image_type type, const char* 
rpath,
 
        // find and open the file
        fd = open_executable(path, type, rpath, get_program_path(),
-               sSearchPathSubDir);
+               requestingObjectPath, sSearchPathSubDir);
        if (fd < 0) {
                FATAL("Cannot open file %s: %s\n", name, strerror(fd));
                KTRACE("rld: load_container(\"%s\"): failed to open file", 
name);
diff --git a/src/system/runtime_loader/elf_load_image.h 
b/src/system/runtime_loader/elf_load_image.h
index e7c4e23..77ead88 100644
--- a/src/system/runtime_loader/elf_load_image.h
+++ b/src/system/runtime_loader/elf_load_image.h
@@ -11,7 +11,7 @@
 status_t       parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize,
                                int32* _sheaderSize);
 status_t       load_image(char const* name, image_type type, const char* rpath,
-                               image_t** _image);
+                               const char* requestingObjectPath, image_t** 
_image);
 
 
 #endif // ELF_LOAD_IMAGE_H
diff --git a/src/system/runtime_loader/runtime_loader.cpp 
b/src/system/runtime_loader/runtime_loader.cpp
index 664cf72..8864ef3 100644
--- a/src/system/runtime_loader/runtime_loader.cpp
+++ b/src/system/runtime_loader/runtime_loader.cpp
@@ -94,10 +94,59 @@ search_path_for_type(image_type type)
 }
 
 
+static bool
+replace_executable_path_placeholder(const char*& dir, int& dirLength,
+       const char* placeholder, size_t placeholderLength,
+       const char* replacementSubPath, char*& buffer, size_t& bufferSize,
+       status_t& _error)
+{
+       if (dirLength < (int)placeholderLength
+               || strncmp(dir, placeholder, placeholderLength) != 0) {
+               return false;
+       }
+
+       if (replacementSubPath == NULL) {
+               _error = B_ENTRY_NOT_FOUND;
+               return true;
+       }
+
+       char* lastSlash = strrchr(replacementSubPath, '/');
+
+       // Copy replacementSubPath without the last component (the application 
file
+       // name, respectively the requesting executable file name).
+       size_t toCopy;
+       if (lastSlash != NULL) {
+               toCopy = lastSlash - replacementSubPath;
+               strlcpy(buffer, replacementSubPath,
+                       std::min((ssize_t)bufferSize, lastSlash + 1 - 
replacementSubPath));
+       } else {
+               replacementSubPath = ".";
+               toCopy = 1;
+               strlcpy(buffer, ".", bufferSize);
+       }
+
+       if (toCopy >= bufferSize) {
+               _error = B_NAME_TOO_LONG;
+               return true;
+       }
+
+       memcpy(buffer, replacementSubPath, toCopy);
+       buffer[toCopy] = '\0';
+
+       buffer += toCopy;
+       bufferSize -= toCopy;
+       dir += placeholderLength;
+       dirLength -= placeholderLength;
+
+       _error = B_OK;
+       return true;
+}
+
+
 static int
 try_open_executable(const char *dir, int dirLength, const char *name,
-       const char *programPath, const char *abiSpecificSubDir, char *path,
-       size_t pathLength)
+       const char *programPath, const char *requestingObjectPath,
+       const char *abiSpecificSubDir, char *path, size_t pathLength)
 {
        size_t nameLength = strlen(name);
        struct stat stat;
@@ -111,24 +160,12 @@ try_open_executable(const char *dir, int dirLength, const 
char *name,
                if (programPath == NULL)
                        programPath = gProgramArgs->program_path;
 
-               if (dirLength >= 2 && strncmp(dir, "%A", 2) == 0) {
-                       // Replace %A with current app folder path (of course,
-                       // this must be the first part of the path)
-                       char *lastSlash = strrchr(programPath, '/');
-                       int bytesCopied;
-
-                       // copy what's left (when the application name is 
removed)
-                       if (lastSlash != NULL) {
-                               strlcpy(buffer, programPath,
-                                       std::min((long)pathLength, lastSlash + 
1 - programPath));
-                       } else
-                               strlcpy(buffer, ".", pathLength);
-
-                       bytesCopied = strlen(buffer);
-                       buffer += bytesCopied;
-                       pathLength -= bytesCopied;
-                       dir += 2;
-                       dirLength -= 2;
+               if (replace_executable_path_placeholder(dir, dirLength, "%A", 2,
+                               programPath, buffer, pathLength, status)
+                       || replace_executable_path_placeholder(dir, dirLength, 
"$ORIGIN", 7,
+                               requestingObjectPath, buffer, pathLength, 
status)) {
+                       if (status != B_OK)
+                               return status;
                } else if (abiSpecificSubDir != NULL) {
                        // We're looking for a library or an add-on and the 
executable has
                        // not been compiled with a compiler using the same ABI 
as the one
@@ -187,8 +224,8 @@ try_open_executable(const char *dir, int dirLength, const 
char *name,
 
 static int
 search_executable_in_path_list(const char *name, const char *pathList,
-       int pathListLen, const char *programPath, const char *abiSpecificSubDir,
-       char *pathBuffer, size_t pathBufferLength)
+       int pathListLen, const char *programPath, const char 
*requestingObjectPath,
+       const char *abiSpecificSubDir, char *pathBuffer, size_t 
pathBufferLength)
 {
        const char *pathListEnd = pathList + pathListLen;
        status_t status = B_ENTRY_NOT_FOUND;
@@ -205,7 +242,8 @@ search_executable_in_path_list(const char *name, const char 
*pathList,
                        pathEnd++;
 
                fd = try_open_executable(pathList, pathEnd - pathList, name,
-                       programPath, abiSpecificSubDir, pathBuffer, 
pathBufferLength);
+                       programPath, requestingObjectPath, abiSpecificSubDir, 
pathBuffer,
+                       pathBufferLength);
                if (fd >= 0) {
                        // see if it's a dir
                        struct stat stat;
@@ -228,7 +266,8 @@ search_executable_in_path_list(const char *name, const char 
*pathList,
 
 int
 open_executable(char *name, image_type type, const char *rpath,
-       const char *programPath, const char *abiSpecificSubDir)
+       const char *programPath, const char *requestingObjectPath,
+       const char *abiSpecificSubDir)
 {
        char buffer[PATH_MAX];
        int fd = B_ENTRY_NOT_FOUND;
@@ -266,12 +305,13 @@ open_executable(char *name, image_type type, const char 
*rpath,
                        // If there is no ';', we set only secondList to 
simplify things.
                if (firstList) {
                        fd = search_executable_in_path_list(name, firstList,
-                               semicolon - firstList, programPath, NULL, 
buffer,
-                               sizeof(buffer));
+                               semicolon - firstList, programPath, 
requestingObjectPath, NULL,
+                               buffer, sizeof(buffer));
                }
                if (fd < 0) {
                        fd = search_executable_in_path_list(name, secondList,
-                               strlen(secondList), programPath, NULL, buffer, 
sizeof(buffer));
+                               strlen(secondList), programPath, 
requestingObjectPath, NULL,
+                               buffer, sizeof(buffer));
                }
        }
 
@@ -280,7 +320,7 @@ open_executable(char *name, image_type type, const char 
*rpath,
        if (fd < 0) {
                if (const char *paths = search_path_for_type(type)) {
                        fd = search_executable_in_path_list(name, paths, 
strlen(paths),
-                               programPath, abiSpecificSubDir, buffer, 
sizeof(buffer));
+                               programPath, NULL, abiSpecificSubDir, buffer, 
sizeof(buffer));
                }
        }
 
@@ -337,7 +377,7 @@ test_executable(const char *name, char *invoker)
 
        strlcpy(path, name, sizeof(path));
 
-       fd = open_executable(path, B_APP_IMAGE, NULL, NULL, NULL);
+       fd = open_executable(path, B_APP_IMAGE, NULL, NULL, NULL, NULL);
        if (fd < B_OK)
                return fd;
 
diff --git a/src/system/runtime_loader/runtime_loader_private.h 
b/src/system/runtime_loader/runtime_loader_private.h
index 81dabfe..036a465 100644
--- a/src/system/runtime_loader/runtime_loader_private.h
+++ b/src/system/runtime_loader/runtime_loader_private.h
@@ -56,7 +56,8 @@ extern "C" {
 
 int runtime_loader(void* arg, void* commpage);
 int open_executable(char* name, image_type type, const char* rpath,
-       const char* programPath, const char* abiSpecificSubDir);
+       const char* programPath, const char* requestingObjectPath,
+       const char* abiSpecificSubDir);
 status_t test_executable(const char* path, char* interpreter);
 status_t get_executable_architecture(const char* path,
        const char** _architecture);


Other related posts:

  • » [haiku-commits] haiku: hrev46449 - src/system/runtime_loader - ingo_weinhold