[yocto] [EDT][prelink-cross] LD_PRELOAD Implementation in Prelink

Maninder Singh maninder1.s at samsung.com
Sun May 17 22:17:22 PDT 2015


EP-F6AA0618C49C4AEDA73BFF1B39950BAB
Hi,

Subject: [PATCH 1/1] LD_PRELOAD Implementation in Prelink

prelink fails if  there are ld_preload libs present at target with below error.
	expect libsX.so.1, found /lib/libY.so in dependency order
	where libY.so.1 is ld_preload lib
 
To use this feature :
./prelink --ld-preload=libpreload1.so:libpreload2.so:.... upto 20 libs
Order of libraries to be preloaded is significant. Make sure sequence
mentioned in prelink
should be same as runtime sequence.

Signed-off-by: Vaneet Narang <v.narang at samsung.com>
Signed-off-by: Maninder Singh <maninder1.s at samsung.com>
Reviewed-by: Ajeet Yadav <ajeet.v at samsung.com>
Reviewed-by: Geon-ho Kim <gh007.kim at samsung.com>
---
 src/gather.c    |    8 +++++++-
 src/get.c       |    9 ++++++++-
 src/main.c      |    6 ++++++
 src/prelink.h   |    1 +
 src/rtld/rtld.c |   51 +++++++++++++++++++++++++++++++++++++++++++++------
 5 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/src/gather.c b/src/gather.c
index c3d3128..5ccd243 100644
--- a/src/gather.c
+++ b/src/gather.c
@@ -61,7 +61,7 @@ gather_deps (DSO *dso, struct prelink_entry *ent)
 {
   int i, j, seen = 0;
   FILE *f = NULL;
-  const char *argv[6];
+  const char *argv[8];
   const char *envp[5];
   char *line = NULL, *p, *q = NULL;
   const char **depends = NULL;
@@ -74,6 +74,7 @@ gather_deps (DSO *dso, struct prelink_entry *ent)
   int nliblist = 0;
   const char *dl;
   const char *ent_filename;
+  int etype = dso->ehdr.e_type;
 
   if (check_dso (dso))
     {
@@ -181,6 +182,11 @@ gather_deps (DSO *dso, struct prelink_entry *ent)
           argv[i++] = "--library-path";
           argv[i++] = ld_library_path;
         }
+
+      if(etype == ET_EXEC && ld_preload) {
+          argv[i++] = "--ld-preload";
+          argv[i++] = ld_preload;
+      }
       argv[i++] = "--target-paths";
       argv[i++] = ent_filename;
       argv[i] = NULL;
diff --git a/src/get.c b/src/get.c
index 6a63f02..043af22 100644
--- a/src/get.c
+++ b/src/get.c
@@ -641,12 +641,13 @@ prelink_get_relocations (struct prelink_info *info)
 {
   FILE *f;
   DSO *dso = info->dso;
-  const char *argv[6];
+  const char *argv[8];
   const char *envp[4];
   int i, ret, status;
   char *p;
   const char *dl = dynamic_linker ?: dso->arch->dynamic_linker;
   const char *ent_filename;
+  int etype = info->dso->ehdr.e_type;
 
   if (info->ent->type == ET_DYN)
     {
@@ -709,6 +710,12 @@ prelink_get_relocations (struct prelink_info *info)
           argv[i++] = "--library-path";
           argv[i++] = ld_library_path;
         }
+
+      if(etype == ET_EXEC && ld_preload) {
+          argv[i++] = "--ld-preload";
+          argv[i++] = ld_preload;
+      }      
+
       argv[i++] = "--target-paths";
       argv[i++] = ent_filename;
       argv[i] = NULL;
diff --git a/src/main.c b/src/main.c
index 15c1d53..a99816d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -59,6 +59,7 @@ const char *ld_library_path;
 const char *prelink_conf = PRELINK_CONF;
 const char *prelink_cache = PRELINK_CACHE;
 const char *undo_output;
+char *ld_preload = NULL;
 int noreexecinit;
 time_t initctime;
 
@@ -84,6 +85,7 @@ static char argp_doc[] = PRELINK_PROG " -- program to relocate and prelink ELF s
 #define OPT_SYSROOT		0x8d
 #define OPT_RTLD		0x8e
 #define OPT_ALLOW_TEXTREL	0x8f
+#define OPT_LD_PRELOAD          0x90
 
 static struct argp_option options[] = {
   {"all",		'a', 0, 0,  "Prelink all binaries" },
@@ -123,6 +125,7 @@ static struct argp_option options[] = {
   {"rtld",		OPT_RTLD, "RTLD", OPTION_HIDDEN, "" },
   {"init",		'i', 0, 0,  "Do not re-execute init" },
   {"allow-textrel",	OPT_ALLOW_TEXTREL, 0, 0, "Allow text relocations even on architectures where they may not work" },
+  {"ld-preload",       OPT_LD_PRELOAD, "LIBLIST", 0,  "List of libraries preloaded on target" },
   { 0 }
 };
 
@@ -250,6 +253,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case OPT_ALLOW_TEXTREL:
       allow_bad_textrel = 1;
       break;
+    case OPT_LD_PRELOAD:
+      ld_preload = arg;
+      break;
     default:
       return ARGP_ERR_UNKNOWN;
     }
diff --git a/src/prelink.h b/src/prelink.h
index 66aba99..a6ce607 100644
--- a/src/prelink.h
+++ b/src/prelink.h
@@ -597,6 +597,7 @@ extern enum verify_method_t verify_method;
 extern int quick;
 extern long long seed;
 extern GElf_Addr mmap_reg_start, mmap_reg_end, layout_page_size;
+extern char *ld_preload;
 
 extern const char *sysroot;
 
diff --git a/src/rtld/rtld.c b/src/rtld/rtld.c
index 2ad3ade..f014bea 100644
--- a/src/rtld/rtld.c
+++ b/src/rtld/rtld.c
@@ -47,6 +47,7 @@ unsigned int _dl_debug_mask = 0;
 /* LD_DYNAMIC_WEAK option.  Default is off, changing to 1
    is equivalent to setting LD_DYNAMIC_WEAK. */
 unsigned int _dl_dynamic_weak = 0;
+#define MAX_PRELOADED_LIBS   20
 
 struct search_path
 {
@@ -60,6 +61,7 @@ int host_paths;
 char * dst_ORIGIN;
 char * dst_PLATFORM = ""; /* undefined */
 char * dst_LIB = "lib";
+char * ld_preload = NULL;
 
 
 void string_to_path (struct search_path *path, const char *string);
@@ -73,11 +75,13 @@ static char argp_doc[] = PRELINK_RTLD_PROG " -- program to simulate the runtime
 #define OPT_SYSROOT		0x8c
 #define OPT_LIBRARY_PATH	0x8e
 #define OPT_TARGET_PATHS	0x8f
+#define OPT_LD_PRELOAD          0x90
 
 static struct argp_option options[] = {
   {"library-path",		OPT_LIBRARY_PATH, "LIBRARY_PATH", 0, "Set library search path to LIBRARY_PATH" },
   {"root",			OPT_SYSROOT, "ROOT_PATH", 0, "Prefix all paths with ROOT_PATH" },
   {"target-paths",		OPT_TARGET_PATHS, 0, 0, "Specified paths are based on ROOT_PATH" },
+  {"ld-preload",                OPT_LD_PRELOAD, "LIBLIST", 0, "List of libraries needs to be preloaded"},
   { 0 }
 };
 
@@ -95,6 +99,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case OPT_TARGET_PATHS:
       host_paths = 0;
       break;
+    case OPT_LD_PRELOAD:
+      ld_preload = arg;
+      break;
     default:
       return ARGP_ERR_UNKNOWN;
     }
@@ -582,6 +589,8 @@ load_dsos (DSO *dso, int host_paths)
 {
   struct dso_list *dso_list, *dso_list_tail, *cur_dso_ent, *new_dso_ent;
   struct stat64 st;
+  int total_preload = 0;
+  char * libname[MAX_PRELOADED_LIBS] = {NULL};
 
   /* Assume it's static unless we find DT_NEEDED entries */
   static_binary = 1;
@@ -604,6 +613,22 @@ load_dsos (DSO *dso, int host_paths)
 
   cur_dso_ent = dso_list_tail = dso_list;
 
+  if(dso->ehdr.e_type == ET_EXEC && ld_preload) {
+      char *next_lib =  ld_preload;
+      libname[total_preload] = ld_preload;
+      total_preload++;
+      next_lib=strchr(ld_preload,':');
+      while(next_lib!=NULL){
+	  *next_lib = '\0';
+	  next_lib++;
+	  libname[total_preload] = next_lib;
+	  total_preload++;
+	  next_lib=strchr(next_lib,':');
+      }
+  }
+  else {
+      total_preload = 0;
+  }
   while (cur_dso_ent != NULL)
     {
       DSO *cur_dso, *new_dso;
@@ -624,9 +649,16 @@ load_dsos (DSO *dso, int host_paths)
 	{
 	  int ndx, maxndx;
 	  maxndx = data->d_size / cur_dso->shdr[cur_dso->dynamic].sh_entsize;
-	  for (ndx = 0; ndx < maxndx; ++ndx)
+	  for (ndx = 0; ndx < maxndx + total_preload; ++ndx)
 	    {
-	      gelfx_getdyn (cur_dso->elf, data, ndx, &dyn);
+
+              if(ndx - total_preload >= 0) {
+                  gelfx_getdyn (cur_dso->elf, data, ndx - total_preload, &dyn);
+              }
+              else {
+                  dyn.d_tag = DT_NEEDED;
+              }
+
 	      if (dyn.d_tag == DT_NULL)
 		break;
 	      if (dyn.d_tag == DT_NEEDED)
@@ -635,10 +667,17 @@ load_dsos (DSO *dso, int host_paths)
 		  static_binary = 0;
 
 		  char *new_name=NULL, *new_canon_name=NULL;
-		  const char *soname = get_data (cur_dso,
-						 cur_dso->info[DT_STRTAB]
-						 + dyn.d_un.d_val,
-						 NULL, NULL);
+                  char * soname = NULL;  
+                  if(ndx - total_preload >= 0) {
+		      soname = get_data (cur_dso,
+		    	                 cur_dso->info[DT_STRTAB]
+			       	         + dyn.d_un.d_val,
+				         NULL, NULL);
+                  }
+                  else {
+                      soname = libname[ndx];
+                  }
+
 		  new_dso_ent = in_dso_list (dso_list, soname, NULL);
 		  if (new_dso_ent == NULL)
 		    {
-- 
1.7.1


Thanks 
Maninder Singh


More information about the yocto mailing list