[yocto] [EDT][prelink-cross] LD_PRELOAD Implementation in Prelink
Mark Hatle
mark.hatle at windriver.com
Fri Sep 11 07:10:24 PDT 2015
Merged to the staging branch.
On 5/18/15 12:17 AM, Maninder Singh wrote:
> 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)
> {
>
More information about the yocto
mailing list