From 6f9557ac2ebba75161875563ba43fcd4a881e149 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Mon, 10 Nov 2014 10:56:25 -0800 Subject: [PATCH] For b/18243822, fix dlopen_with_offset to not reuse the same link_map entry when called on the same file with different offsets. --- elf/dl-load.c | 24 ++++++++++++++++++++++-- include/link.h | 6 ++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/elf/dl-load.c b/elf/dl-load.c index e49d0862f9c..b6c4aa8da02 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -840,7 +840,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, off_t of /* Look again to see if the real name matched another already loaded. */ for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next) - if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id)) + if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id) + && l->l_off == offset) { /* The object is already loaded. Just bump its reference count and return it. */ @@ -947,8 +948,25 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, off_t of else assert (r->r_state == RT_ADD); + if (offset != 0) + { + /* Google-specific: to help GDB, and for b/18243822, turn realname + into "realname/@0x" */ + realname = realloc (realname, strlen(realname) + 16 + 4 /* "/@0x" */); + if (realname == NULL) + { + errstring = N_("unable to realloc"); + goto call_lose_errno; + } + strcat(realname, "/@0x"); + + char tmp[20]; + tmp[19] = '\0'; + strcat(realname, _itoa(offset, &tmp[18], 16, 0)); + } + /* Enter the new object in the list of loaded objects. */ - l = _dl_new_object (realname, name, l_type, loader, mode, nsid); + l = _dl_new_object (realname, (offset ? realname : name), l_type, loader, mode, nsid); if (__glibc_unlikely (l == NULL)) { #ifdef SHARED @@ -1320,6 +1338,8 @@ cannot enable executable stack as shared object requires"); assert (origname == NULL); #endif + l->l_off = offset; + /* When we profile the SONAME might be needed for something else but loading. Add it right away. */ if (__glibc_unlikely (GLRO(dl_profile) != NULL) diff --git a/include/link.h b/include/link.h index 5924594548e..22c3eec73d0 100644 --- a/include/link.h +++ b/include/link.h @@ -246,6 +246,12 @@ struct link_map object is the same as one already loaded. */ struct r_file_id l_file_id; + /* Google-specific extension, intended to be part of public interface + to the debugger. As such, it belongs right after l_prev... except + putting it there causes Google libunwind to crash due to its own + peeking into glibc internals (see grte_v1_glibc_link_map). */ + size_t l_off; /* File offset to Elf_Ehdr. */ + /* Collected information about own RUNPATH directories. */ struct r_search_path_struct l_runpath_dirs; -- 2.47.2