aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2014-11-10 10:56:25 -0800
committerPaul Pluzhnikov <ppluzhnikov@google.com>2014-11-10 10:56:25 -0800
commit98337c55dbad460c5f8c2939b7d2fab3df60b140 (patch)
tree431a34d00881946f27b427b2b8663e622c8b3330
parent69f4e2a55db467bd22e6dda18b70c1ebaf62fce2 (diff)
downloadglibc-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.google5
-rw-r--r--elf/dl-load.c24
-rw-r--r--include/link.h6
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;