From a56e1a4303e1b26b9c49962d732e92e7c1311c58 Mon Sep 17 00:00:00 2001 From: gdbdev Date: Wed, 20 Jan 2021 00:07:30 -0800 Subject: [PATCH] Added support for dlmopen. Introduced new dynamic section entry (DT_DEBUG_DLMOPEN). Glibc and linker require associated patch for this feature to work. --- elfcpp/elfcpp.h | 1 + gdb/gdbserver/linux-low.c | 18 ++++++-- gdb/solib-svr4.c | 88 +++++++++++++++++++++++++++++---------- gdb/solib-svr4.h | 6 +++ include/elf/common.h | 1 + 5 files changed, 88 insertions(+), 26 deletions(-) diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index d94db26071e..47b281c70e4 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -714,6 +714,7 @@ enum DT DT_FINI_ARRAYSZ = 28, DT_RUNPATH = 29, DT_FLAGS = 30, + DT_DEBUG_DLMOPEN = 38, // This is used to mark a range of dynamic tags. It is not really // a tag value. diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 4255795ea67..247a8d78f10 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -6856,6 +6856,12 @@ struct link_map_offsets /* Offset to l_prev field in struct link_map. */ int l_prev_offset; + + /* Offset of r_debug_dlmopen.r_debug. */ + int r_debug_dlm_offset; + + /* Offset of r_debug_dlmopen.r_next. */ + int r_next_dlm_offset; }; /* Construct qXfer:libraries-svr4:read reply. */ @@ -6877,7 +6883,9 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, 4, /* l_name offset in link_map. */ 8, /* l_ld offset in link_map. */ 12, /* l_next offset in link_map. */ - 16 /* l_prev offset in link_map. */ + 16, /* l_prev offset in link_map. */ + 0, /* r_debug_dlm offset. */ + 4 /* r_next_dlm offset. */ }; static const struct link_map_offsets lmo_64bit_offsets = @@ -6888,7 +6896,9 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, 8, /* l_name offset in link_map. */ 16, /* l_ld offset in link_map. */ 24, /* l_next offset in link_map. */ - 32 /* l_prev offset in link_map. */ + 32, /* l_prev offset in link_map. */ + 0, /* r_debug_dlm offset. */ + 8 /* r_next_dlm offset. */ }; const struct link_map_offsets *lmo; unsigned int machine; @@ -6953,7 +6963,7 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, if (linux_read_memory (priv->r_debug + lmo->r_version_offset, (unsigned char *) &r_version, sizeof (r_version)) != 0 - || r_version != 1) + || (r_version != 1 && r_version != 3)) { warning ("unexpected r_debug version %d", r_version); } @@ -6982,12 +6992,14 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, { unsigned char libname[PATH_MAX]; +#if 0 if (lm_prev != l_prev) { warning ("Corrupted shared library list: 0x%lx != 0x%lx", (long) lm_prev, (long) l_prev); break; } +#endif /* Ignore the first entry even if it has valid name as the first entry corresponds to the main executable. The first entry should not be diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 3714c59748b..2763e8ae534 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -851,14 +851,10 @@ locate_base (struct svr4_info *info) /* Find the first element in the inferior's dynamic link map, and return its address in the inferior. Return zero if the address - could not be determined. - - FIXME: Perhaps we should validate the info somehow, perhaps by - checking r_version for a known version number, or r_state for - RT_CONSISTENT. */ + could not be determined. */ static CORE_ADDR -solib_svr4_r_map (struct svr4_info *info) +solib_svr4_r_map (CORE_ADDR debug_base) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; @@ -866,7 +862,7 @@ solib_svr4_r_map (struct svr4_info *info) try { - addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset, + addr = read_memory_typed_address (debug_base + lmo->r_map_offset, ptr_type); } catch (const gdb_exception_error &ex) @@ -913,7 +909,7 @@ solib_svr4_r_ldsomap (struct svr4_info *info) exception_print (gdb_stderr, ex); } - if (version < 2 || lmo->r_ldsomap_offset == -1) + if (version != 2 || lmo->r_ldsomap_offset == -1) return 0; return read_memory_typed_address (info->debug_base + lmo->r_ldsomap_offset, @@ -979,7 +975,7 @@ open_symbol_file_object (int from_tty) return 0; /* failed somehow... */ /* First link map member should be the executable. */ - lm = solib_svr4_r_map (info); + lm = solib_svr4_r_map (info->debug_base); if (lm == 0) return 0; /* failed somehow... */ @@ -1294,6 +1290,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm, { CORE_ADDR first_l_name = 0; CORE_ADDR next_lm; + (void)prev_lm; for (; lm != 0; prev_lm = lm, lm = next_lm) { @@ -1308,7 +1305,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm, return 0; next_lm = li->l_next; - +#if 0 if (li->l_prev != prev_lm) { warning (_("Corrupted shared library list: %s != %s"), @@ -1316,6 +1313,7 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm, paddress (target_gdbarch (), li->l_prev)); return 0; } +#endif /* For SVR4 versions, the first entry in the link map is for the inferior executable, so we must ignore it. For some versions of @@ -1362,6 +1360,29 @@ svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm, return 1; } +/* Locate address of _r_debug_dlmopen struct. */ +static CORE_ADDR +locate_dlmopen_base () +{ + struct bound_minimal_symbol msymbol; + CORE_ADDR dyn_ptr; + + /* Find DT_DEBUG_DLMOPEN entry in .dynamic section. + DT_DEBUG_DLMOPEN entry is not yet introduced.*/ + if (scan_dyntag (DT_DEBUG_DLMOPEN, exec_bfd, &dyn_ptr, NULL) + || scan_dyntag_auxv (DT_DEBUG_DLMOPEN, &dyn_ptr, NULL)) + return dyn_ptr; + + /* This may be a static executable. Look for the symbol + conventionally named _r_debug_dlmopen. */ + msymbol = lookup_minimal_symbol ("_r_debug_dlmopen", NULL, symfile_objfile); + if (msymbol.minsym != NULL) + return BMSYMBOL_VALUE_ADDRESS (msymbol); + + /* _r_debug_dlmopen struct not found. */ + return 0; +} + /* Read the full list of currently loaded shared objects directly from the inferior, without referring to any libraries read and stored by the probes interface. Handle special cases relating @@ -1375,6 +1396,11 @@ svr4_current_sos_direct (struct svr4_info *info) struct so_list **link_ptr = &head; int ignore_first; struct svr4_library_list library_list; + struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); + CORE_ADDR r_debug_ptr; + CORE_ADDR r_debug_dlmopen_ptr = 0; + struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; /* Fall back to manual examination of the target if the packet is not supported or gdbserver failed to find DT_DEBUG. gdb.server/solib-list.exp @@ -1415,11 +1441,28 @@ svr4_current_sos_direct (struct svr4_info *info) svr4_free_library_list (&head); }); - /* Walk the inferior's link map list, and build our list of - `struct so_list' nodes. */ - lm = solib_svr4_r_map (info); - if (lm) - svr4_read_so_list (info, lm, 0, &link_ptr, ignore_first); + r_debug_ptr = info->debug_base; + r_debug_dlmopen_ptr = locate_dlmopen_base (); + do + { + /* Walk the inferior's link map list, and build our list of + `struct so_list' nodes. */ + lm = solib_svr4_r_map (r_debug_ptr); + if (lm) + svr4_read_so_list (info, lm, 0, &link_ptr, ignore_first); + ignore_first = 0; + if (r_debug_dlmopen_ptr != 0){ + r_debug_dlmopen_ptr + = read_memory_typed_address (r_debug_dlmopen_ptr + + lmo->r_next_dlm_offset, ptr_type); + if (r_debug_dlmopen_ptr != 0) + r_debug_ptr + = read_memory_typed_address ( r_debug_dlmopen_ptr + + lmo->r_debug_dlm_offset, ptr_type); + else + r_debug_ptr = 0; + } + } while ((r_debug_dlmopen_ptr !=0) && (r_debug_ptr != 0)); /* On Solaris, the dynamic linker is not in the normal list of shared objects, so make sure we pick it up too. Having @@ -1944,13 +1987,6 @@ svr4_handle_solib_event (void) if (locate_base (info) == 0) return; - /* GDB does not currently support libraries loaded via dlmopen - into namespaces other than the initial one. We must ignore - any namespace other than the initial namespace here until - support for this is added to GDB. */ - if (debug_base != info->debug_base) - action = DO_NOTHING; - if (action == UPDATE_OR_RELOAD) { try @@ -2212,7 +2248,7 @@ enable_break (struct svr4_info *info, int from_tty) solib_add (NULL, from_tty, auto_solib_add); sym_addr = 0; - if (info->debug_base && solib_svr4_r_map (info) != 0) + if (info->debug_base && solib_svr4_r_map (info->debug_base) != 0) sym_addr = solib_svr4_r_brk (info); if (sym_addr != 0) @@ -3160,6 +3196,9 @@ svr4_ilp32_fetch_link_map_offsets (void) lmo.r_brk_offset = 8; lmo.r_ldsomap_offset = 20; + lmo.r_debug_dlm_offset = 0; + lmo.r_next_dlm_offset = 4; + /* Everything we need is in the first 20 bytes. */ lmo.link_map_size = 20; lmo.l_addr_offset = 0; @@ -3191,6 +3230,9 @@ svr4_lp64_fetch_link_map_offsets (void) lmo.r_brk_offset = 16; lmo.r_ldsomap_offset = 40; + lmo.r_debug_dlm_offset = 0; + lmo.r_next_dlm_offset = 8; + /* Everything we need is in the first 40 bytes. */ lmo.link_map_size = 40; lmo.l_addr_offset = 0; diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h index 30dd6bc0b36..2700d54d733 100644 --- a/gdb/solib-svr4.h +++ b/gdb/solib-svr4.h @@ -66,6 +66,12 @@ struct link_map_offsets /* Offset of r_debug.r_ldsomap. */ int r_ldsomap_offset; + /* Offset of r_debug_dlmopen.r_debug_dlm. */ + int r_debug_dlm_offset; + + /* Offset of r_debug_dlmopen.r_next_dlm. */ + int r_next_dlm_offset; + /* Size of struct link_map (or equivalent), or at least enough of it to be able to obtain the fields below. */ int link_map_size; diff --git a/include/elf/common.h b/include/elf/common.h index 75c4fb7e9d7..5bd1abc1c59 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -975,6 +975,7 @@ #define DT_FINI_ARRAYSZ 28 #define DT_RUNPATH 29 #define DT_FLAGS 30 +#define DT_DEBUG_DLMOPEN 38 #define DT_ENCODING 32 #define DT_PREINIT_ARRAY 32 #define DT_PREINIT_ARRAYSZ 33 -- 2.26.2.Cisco