diff options
author | Paul Pluzhnikov <ppluzhnikov@google.com> | 2014-11-10 10:56:25 -0800 |
---|---|---|
committer | Paul Pluzhnikov <ppluzhnikov@google.com> | 2014-11-10 10:56:25 -0800 |
commit | 98337c55dbad460c5f8c2939b7d2fab3df60b140 (patch) | |
tree | 431a34d00881946f27b427b2b8663e622c8b3330 | |
parent | 69f4e2a55db467bd22e6dda18b70c1ebaf62fce2 (diff) | |
download | glibc-98337c55dbad460c5f8c2939b7d2fab3df60b140.zip glibc-98337c55dbad460c5f8c2939b7d2fab3df60b140.tar.gz glibc-98337c55dbad460c5f8c2939b7d2fab3df60b140.tar.bz2 |
For b/18243822, fix dlopen_with_offset to not reuse the same link_map entry when called on the same file with different offsets.
-rw-r--r-- | README.google | 5 | ||||
-rw-r--r-- | elf/dl-load.c | 24 | ||||
-rw-r--r-- | include/link.h | 6 |
3 files changed, 33 insertions, 2 deletions
diff --git a/README.google b/README.google index 6ffe14b..a4a32aa 100644 --- a/README.google +++ b/README.google @@ -390,3 +390,8 @@ stdlib/secure-getenv.c time. (bmoses, google-local) +elf/dl-load.c +include/link.h + For b/18243822, fix dlopen_with_offset to not reuse the same link_map + entry when called on the same file with different offsets. + (ppluzhnikov, google-local) diff --git a/elf/dl-load.c b/elf/dl-load.c index 4f114fd..8adb07f 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -956,7 +956,8 @@ _dl_map_object_from_fd (const char *name, int fd, off_t offset, /* Look again to see if the real name matched another already loaded. */ for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) - if (l->l_removed == 0 && l->l_ino == st.st_ino && l->l_dev == st.st_dev) + if (l->l_removed == 0 && l->l_ino == st.st_ino && l->l_dev == st.st_dev + && l->l_off == offset) { /* The object is already loaded. Just bump its reference count and return it. */ @@ -1064,8 +1065,26 @@ _dl_map_object_from_fd (const char *name, int fd, off_t offset, else assert (r->r_state == RT_ADD); + if (offset != 0) + { + /* Google-specific: to help GDB, and for b/18243822, turn realname + into "realname/@0x<offset>" */ + 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 (__builtin_expect (l == NULL, 0)) { #ifdef SHARED @@ -1597,6 +1616,7 @@ cannot enable executable stack as shared object requires"); /* Finally the file information. */ l->l_dev = st.st_dev; l->l_ino = st.st_ino; + l->l_off = offset; /* When we profile the SONAME might be needed for something else but loading. Add it right away. */ diff --git a/include/link.h b/include/link.h index 670d401..10c159d 100644 --- a/include/link.h +++ b/include/link.h @@ -238,6 +238,12 @@ struct link_map dev_t l_dev; ino64_t l_ino; + /* 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; |