diff mbox series

elf: Add -z [dt-debugsz|nodt-debugsz] to emit DT_DEBUGSZ

Message ID 20210815002338.2779683-1-hjl.tools@gmail.com
State Superseded
Headers show
Series elf: Add -z [dt-debugsz|nodt-debugsz] to emit DT_DEBUGSZ | expand

Checks

Context Check Description
dj/TryBot-apply_patch fail Patch failed to apply to master at the time it was sent
dj/TryBot-32bit fail Patch series failed to apply

Commit Message

H.J. Lu Aug. 15, 2021, 12:23 a.m. UTC
Add -z [dt-debugsz|nodt-debugsz] to emit a DT_DEBUGSZ dynamic tag so
that the dynamic linker can set its value to the size of the structure
of debugger interface, whose address is stored in the DT_DEBUG dynamic
tag, used by the dynamic linker.

bfd/

	PR gdb/11839
	* elf.c (_bfd_elf_print_private_bfd_data): Support DT_DEBUGSZ.
	* elflink.c (bfd_elf_size_dynamic_sections): Add DT_DEBUGSZ for
	-z dt-debugsz in executables.

binutils/

	PR gdb/11839
	* readelf.c (get_dynamic_type): Support DT_DEBUGSZ.

include/

	PR gdb/11839
	* bfdlink.h (bfd_link_info): Add emit_dt_debugsz.
	* elf/common.h (DT_DEBUGSZ): New.

ld/

	PR gdb/11839
	* NEWS: Mention -z dt-debugsz and -z nodt-debugsz.
	* configure.ac (--enable-dt-debugsz): New.  Default to yes.
	Define DEFAULT_EMIT_DT_DEBUGSZ.
	* ld.texi: Document -z dt-debugsz and -z nodt-debugsz.
	* ldmain.c (main): Initialize link_info.emit_dt_debugsz to
	DEFAULT_EMIT_DT_DEBUGSZ.
	* lexsup.c (elf_shlib_list_options): Add -z dt-debugsz and
	-z nodt-debugsz.
	* config.in: Regenerate
	* configure: Likewise.
	* emultempl/elf.em (gld${EMULATION_NAME}_handle_option): Handle
	-z dt-debugsz and -z nodt-debugsz.
	* testsuite/config/default.exp (LDFLAGS): Add "-z nodt-debugsz".
	* testsuite/ld-elf/dt-debugsz-1.d: New test.
	* testsuite/ld-elf/dt-debugsz-2.d: Likewise.
---
 bfd/elf.c                          |  1 +
 bfd/elflink.c                      |  5 +++++
 binutils/readelf.c                 |  1 +
 include/bfdlink.h                  |  3 +++
 include/elf/common.h               |  1 +
 ld/NEWS                            |  3 +++
 ld/config.in                       |  4 ++++
 ld/configure                       | 27 +++++++++++++++++++++++++--
 ld/configure.ac                    | 16 ++++++++++++++++
 ld/emultempl/elf.em                |  4 ++++
 ld/ld.texi                         |  4 ++++
 ld/ldmain.c                        |  1 +
 ld/lexsup.c                        |  4 ++++
 ld/testsuite/config/default.exp    |  3 +++
 ld/testsuite/ld-elf/dt-debugsz-1.d |  9 +++++++++
 ld/testsuite/ld-elf/dt-debugsz-2.d | 10 ++++++++++
 16 files changed, 94 insertions(+), 2 deletions(-)
 create mode 100644 ld/testsuite/ld-elf/dt-debugsz-1.d
 create mode 100644 ld/testsuite/ld-elf/dt-debugsz-2.d

Comments

Florian Weimer Aug. 15, 2021, 11:55 a.m. UTC | #1
* H. J. Lu via Gdb-patches:

> Add -z [dt-debugsz|nodt-debugsz] to emit a DT_DEBUGSZ dynamic tag so
> that the dynamic linker can set its value to the size of the structure
> of debugger interface, whose address is stored in the DT_DEBUG dynamic
> tag, used by the dynamic linker.

I do not think this is necessary.  We can increase the version number
in the existing DT_DEBUG structure.
H.J. Lu Aug. 15, 2021, 12:50 p.m. UTC | #2
On Sun, Aug 15, 2021 at 4:55 AM Florian Weimer <fw@deneb.enyo.de> wrote:
>
> * H. J. Lu via Gdb-patches:
>
> > Add -z [dt-debugsz|nodt-debugsz] to emit a DT_DEBUGSZ dynamic tag so
> > that the dynamic linker can set its value to the size of the structure
> > of debugger interface, whose address is stored in the DT_DEBUG dynamic
> > tag, used by the dynamic linker.
>
> I do not think this is necessary.  We can increase the version number
> in the existing DT_DEBUG structure.

Some debuggers expect r_version == 1.
H.J. Lu Aug. 15, 2021, 1:11 p.m. UTC | #3
On Sun, Aug 15, 2021 at 5:50 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sun, Aug 15, 2021 at 4:55 AM Florian Weimer <fw@deneb.enyo.de> wrote:
> >
> > * H. J. Lu via Gdb-patches:
> >
> > > Add -z [dt-debugsz|nodt-debugsz] to emit a DT_DEBUGSZ dynamic tag so
> > > that the dynamic linker can set its value to the size of the structure
> > > of debugger interface, whose address is stored in the DT_DEBUG dynamic
> > > tag, used by the dynamic linker.
> >
> > I do not think this is necessary.  We can increase the version number
> > in the existing DT_DEBUG structure.
>
> Some debuggers expect r_version == 1.

GDB has

         if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
                                 (unsigned char *) &r_version,
                                 sizeof (r_version)) != 0
              || r_version != 1)
            {
              warning ("unexpected r_debug version %d", r_version);
            }
          else if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
                                 &lm_addr, ptr_size) != 0)
            {
              warning ("unable to read r_map from 0x%lx",
                       (long) priv->r_debug + lmo->r_map_offset);
            }
Florian Weimer Aug. 15, 2021, 1:17 p.m. UTC | #4
* H. J. Lu:

> On Sun, Aug 15, 2021 at 5:50 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Sun, Aug 15, 2021 at 4:55 AM Florian Weimer <fw@deneb.enyo.de> wrote:
>> >
>> > * H. J. Lu via Gdb-patches:
>> >
>> > > Add -z [dt-debugsz|nodt-debugsz] to emit a DT_DEBUGSZ dynamic tag so
>> > > that the dynamic linker can set its value to the size of the structure
>> > > of debugger interface, whose address is stored in the DT_DEBUG dynamic
>> > > tag, used by the dynamic linker.
>> >
>> > I do not think this is necessary.  We can increase the version number
>> > in the existing DT_DEBUG structure.
>>
>> Some debuggers expect r_version == 1.
>
> GDB has
>
>          if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
>                                  (unsigned char *) &r_version,
>                                  sizeof (r_version)) != 0
>               || r_version != 1)
>             {
>               warning ("unexpected r_debug version %d", r_version);
>             }
>           else if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
>                                  &lm_addr, ptr_size) != 0)
>             {
>               warning ("unable to read r_map from 0x%lx",
>                        (long) priv->r_debug + lmo->r_map_offset);
>             }

Does this mean it's just a warning?
H.J. Lu Aug. 15, 2021, 1:48 p.m. UTC | #5
On Sun, Aug 15, 2021 at 6:17 AM Florian Weimer <fw@deneb.enyo.de> wrote:
>
> * H. J. Lu:
>
> > On Sun, Aug 15, 2021 at 5:50 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>
> >> On Sun, Aug 15, 2021 at 4:55 AM Florian Weimer <fw@deneb.enyo.de> wrote:
> >> >
> >> > * H. J. Lu via Gdb-patches:
> >> >
> >> > > Add -z [dt-debugsz|nodt-debugsz] to emit a DT_DEBUGSZ dynamic tag so
> >> > > that the dynamic linker can set its value to the size of the structure
> >> > > of debugger interface, whose address is stored in the DT_DEBUG dynamic
> >> > > tag, used by the dynamic linker.
> >> >
> >> > I do not think this is necessary.  We can increase the version number
> >> > in the existing DT_DEBUG structure.
> >>
> >> Some debuggers expect r_version == 1.
> >
> > GDB has
> >
> >          if (linux_read_memory (priv->r_debug + lmo->r_version_offset,
> >                                  (unsigned char *) &r_version,
> >                                  sizeof (r_version)) != 0
> >               || r_version != 1)
> >             {
> >               warning ("unexpected r_debug version %d", r_version);
> >             }
> >           else if (read_one_ptr (priv->r_debug + lmo->r_map_offset,
> >                                  &lm_addr, ptr_size) != 0)
> >             {
> >               warning ("unable to read r_map from 0x%lx",
> >                        (long) priv->r_debug + lmo->r_map_offset);
> >             }
>
> Does this mean it's just a warning?

When the warning happens, it won't read r_map.
diff mbox series

Patch

diff --git a/bfd/elf.c b/bfd/elf.c
index 380d64d699d..8e2ea1f2b36 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1775,6 +1775,7 @@  _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
 	    case DT_RELENT: name = "RELENT"; break;
 	    case DT_PLTREL: name = "PLTREL"; break;
 	    case DT_DEBUG: name = "DEBUG"; break;
+	    case DT_DEBUGSZ: name = "DEBUGSZ"; break;
 	    case DT_TEXTREL: name = "TEXTREL"; break;
 	    case DT_JMPREL: name = "JMPREL"; break;
 	    case DT_BIND_NOW: name = "BIND_NOW"; break;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index c9d5da2dab4..94be0a0e69a 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -7241,6 +7241,11 @@  bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
+      if (info->emit_dt_debugsz
+	  && bfd_link_executable (info)
+	  && !_bfd_elf_add_dynamic_entry (info, DT_DEBUGSZ, 0))
+	return false;
+
       if (elf_tdata (output_bfd)->cverdefs)
 	{
 	  unsigned int crefs = elf_tdata (output_bfd)->cverdefs;
diff --git a/binutils/readelf.c b/binutils/readelf.c
index bedd3893b59..92e696c5f0e 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -2198,6 +2198,7 @@  get_dynamic_type (Filedata * filedata, unsigned long type)
     case DT_RELENT:	return "RELENT";
     case DT_PLTREL:	return "PLTREL";
     case DT_DEBUG:	return "DEBUG";
+    case DT_DEBUGSZ:	return "DEBUGSZ";
     case DT_TEXTREL:	return "TEXTREL";
     case DT_JMPREL:	return "JMPREL";
     case DT_BIND_NOW:   return "BIND_NOW";
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 566529ee644..3f8606b11ad 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -429,6 +429,9 @@  struct bfd_link_info
   /* TRUE if .gnu.hash section should be created.  */
   unsigned int emit_gnu_hash: 1;
 
+  /* TRUE if DT_DEBUGSZ dynamic tag should be emitted.  */
+  unsigned int emit_dt_debugsz: 1;
+
   /* If TRUE reduce memory overheads, at the expense of speed. This will
      cause map file generation to use an O(N^2) algorithm and disable
      caching ELF symbol buffer.  */
diff --git a/include/elf/common.h b/include/elf/common.h
index 95ade894e98..f4f8467fe26 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -1125,6 +1125,7 @@ 
 #define DT_SYMINFO	0x6ffffeff
 #define DT_ADDRRNGHI	0x6ffffeff
 
+#define DT_DEBUGSZ	0x6ffffff8
 #define DT_RELACOUNT	0x6ffffff9
 #define DT_RELCOUNT	0x6ffffffa
 #define DT_FLAGS_1	0x6ffffffb
diff --git a/ld/NEWS b/ld/NEWS
index 6e0b56658d3..a8f4c026482 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,8 @@ 
 -*- text -*-
 
+* Add -z dt-debugsz and -z nodt-debugsz to ELF linker to control whether
+  DT_DEBUGSZ dynamic tag should be emitted.
+
 * Add -z indirect-extern-access/-z noindirect-extern-access to x86 ELF
   linker to control canonical function pointers and copy relocation.
 
diff --git a/ld/config.in b/ld/config.in
index 26d55a00d47..d5b2a1f948d 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -7,6 +7,10 @@ 
 #endif
 #define __CONFIG_H__ 1
 
+/* Define to 1 if you want to emit DT_DEBUGSZ dynamic tag in the ELF linker by
+   default. */
+#undef DEFAULT_EMIT_DT_DEBUGSZ
+
 /* Define to 1 if you want to emit gnu hash in the ELF linker by default. */
 #undef DEFAULT_EMIT_GNU_HASH
 
diff --git a/ld/configure b/ld/configure
index 33b7de33d1d..d4440f97857 100755
--- a/ld/configure
+++ b/ld/configure
@@ -838,6 +838,7 @@  enable_textrel_check
 enable_separate_code
 enable_error_handling_script
 enable_default_hash_style
+enable_dt_debugsz
 enable_initfini_array
 enable_libctf
 enable_werror
@@ -1513,6 +1514,7 @@  Optional Features:
                           --error-handling-script option
   --enable-default-hash-style={sysv,gnu,both}
                           use this default hash style
+  --disable-dt-debugsz    do not emit DT_DEBUGSZ dynamic tag
   --disable-initfini-array do not use .init_array/.fini_array sections
   --enable-libctf         Handle .ctf type-info sections [default=yes]
   --enable-werror         treat compile warnings as errors
@@ -11412,7 +11414,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11415 "configure"
+#line 11417 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11518,7 +11520,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11521 "configure"
+#line 11523 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15363,6 +15365,27 @@  case "${enable_default_hash_style}" in
   *) ac_default_emit_gnu_hash=0 ;;
 esac
 
+# Check whether --enable-dt-debugsz was given.
+if test "${enable_dt_debugsz+set}" = set; then :
+  enableval=$enable_dt_debugsz; case "${enableval}" in
+ yes|no) ;;
+ *) as_fn_error $? "invalid --disable-dt-debugsz argument" "$LINENO" 5 ;;
+ esac
+else
+  emit_dt_debugsz=yes
+fi
+
+if test $emit_dt_debugsz = yes; then
+  ac_default_emit_dt_debugsz=1
+else
+  ac_default_emit_dt_debugsz=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_EMIT_DT_DEBUGSZ $ac_default_emit_dt_debugsz
+_ACEOF
+
+
 # Check whether --enable-initfini-array was given.
 if test "${enable_initfini_array+set}" = set; then :
   enableval=$enable_initfini_array; case "${enableval}" in
diff --git a/ld/configure.ac b/ld/configure.ac
index 8ea97c43cd4..09ee28474d5 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -243,6 +243,22 @@  case "${enable_default_hash_style}" in
   *) ac_default_emit_gnu_hash=0 ;;
 esac
 
+AC_ARG_ENABLE(dt-debugsz,
+AS_HELP_STRING([--disable-dt-debugsz],
+	       [do not emit DT_DEBUGSZ dynamic tag]),
+[case "${enableval}" in
+ yes|no) ;;
+ *) AC_MSG_ERROR([invalid --disable-dt-debugsz argument]) ;;
+ esac], [emit_dt_debugsz=yes])
+if test $emit_dt_debugsz = yes; then
+  ac_default_emit_dt_debugsz=1
+else
+  ac_default_emit_dt_debugsz=0
+fi
+AC_DEFINE_UNQUOTED([DEFAULT_EMIT_DT_DEBUGSZ],
+  [$ac_default_emit_dt_debugsz],
+  [Define to 1 if you want to emit DT_DEBUGSZ dynamic tag in the ELF linker by default.])
+
 AC_ARG_ENABLE(initfini-array,
 [  --disable-initfini-array do not use .init_array/.fini_array sections],
 [case "${enableval}" in
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index bfaf8130a3e..2e5ef68dc13 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -824,6 +824,10 @@  fragment <<EOF
 	link_info.combreloc = false;
       else if (strcmp (optarg, "nocopyreloc") == 0)
 	link_info.nocopyreloc = true;
+      else if (strcmp (optarg, "dt-debugsz") == 0)
+	link_info.emit_dt_debugsz = true;
+      else if (strcmp (optarg, "nodt-debugsz") == 0)
+	link_info.emit_dt_debugsz = false;
 EOF
 if test -n "$COMMONPAGESIZE"; then
 fragment <<EOF
diff --git a/ld/ld.texi b/ld/ld.texi
index 72b5c373ba1..0e02bcf72c0 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -1258,6 +1258,10 @@  Report unresolved symbol references from regular object files.  This
 is done even if the linker is creating a non-symbolic shared library.
 This option is the inverse of @samp{-z undefs}.
 
+@item dt-debugsz
+@itemx nodt-debugsz
+Emit DT_DEBUGSZ dynamic tag when building executables.
+
 @item dynamic-undefined-weak
 @itemx nodynamic-undefined-weak
 Make undefined weak symbols dynamic when building a dynamic object,
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 02029237e1a..900085f29c7 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -338,6 +338,7 @@  main (int argc, char **argv)
   link_info.textrel_check = DEFAULT_LD_TEXTREL_CHECK;
   link_info.emit_hash = DEFAULT_EMIT_SYSV_HASH;
   link_info.emit_gnu_hash = DEFAULT_EMIT_GNU_HASH;
+  link_info.emit_dt_debugsz = DEFAULT_EMIT_DT_DEBUGSZ;
   link_info.callbacks = &link_callbacks;
   link_info.input_bfds_tail = &link_info.input_bfds;
   /* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init
diff --git a/ld/lexsup.c b/ld/lexsup.c
index c128fe3a96b..5203c302c93 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -2040,6 +2040,8 @@  elf_shlib_list_options (FILE *file)
   fprintf (file, _("\
   -z nocombreloc              Don't merge dynamic relocs into one section\n"));
   fprintf (file, _("\
+  -z dt-debugsz               Emit DT_DEBUGSZ dynamic tag\n"));
+  fprintf (file, _("\
   -z global                   Make symbols in DSO available for subsequently\n\
                                 loaded objects\n"));
   fprintf (file, _("\
@@ -2063,6 +2065,8 @@  elf_shlib_list_options (FILE *file)
   fprintf (file, _("\
   -z nodlopen                 Mark DSO not available to dlopen\n"));
   fprintf (file, _("\
+  -z nodt-debugsz             Don't emit DT_DEBUGSZ dynamic tag\n"));
+  fprintf (file, _("\
   -z nodump                   Mark DSO not available to dldump\n"));
   fprintf (file, _("\
   -z now                      Mark object non-lazy runtime binding\n"));
diff --git a/ld/testsuite/config/default.exp b/ld/testsuite/config/default.exp
index 0795ea81bfb..d2f2c2460b0 100644
--- a/ld/testsuite/config/default.exp
+++ b/ld/testsuite/config/default.exp
@@ -310,6 +310,9 @@  if ![info exists LDFLAGS] then {
     set LDFLAGS {}
 }
 
+# Don't emit DT_DEBUGSZ.
+append LDFLAGS " -z nodt-debugsz"
+
 # Set LD_CLASS to "64bit" for a 64-bit *host* linker.
 if { ![info exists LD_CLASS] } then {
     set REAL_LD [findfile $base_dir/.libs/ld-new .libs/ld-new $LD [transform ld]]
diff --git a/ld/testsuite/ld-elf/dt-debugsz-1.d b/ld/testsuite/ld-elf/dt-debugsz-1.d
new file mode 100644
index 00000000000..e74739dee42
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-debugsz-1.d
@@ -0,0 +1,9 @@ 
+#source: start.s
+#ld: -pie -z dt-debugsz
+#readelf : -dW
+#target: *-*-linux* *-*-gnu* *-*-solaris* arm*-*-uclinuxfdpiceabi
+#xfail: ![check_pie_support]
+
+#...
+ 0x0*6ffffff8 \(DEBUGSZ\) +0x0
+#pass
diff --git a/ld/testsuite/ld-elf/dt-debugsz-2.d b/ld/testsuite/ld-elf/dt-debugsz-2.d
new file mode 100644
index 00000000000..0fac6abbe6e
--- /dev/null
+++ b/ld/testsuite/ld-elf/dt-debugsz-2.d
@@ -0,0 +1,10 @@ 
+#source: start.s
+#ld: -shared -z dt-debugsz
+#readelf : -dW
+#target: *-*-linux* *-*-gnu* *-*-solaris* arm*-*-uclinuxfdpiceabi
+#xfail: ![check_shared_lib_support]
+
+#failif
+#...
+ 0x0*6ffffff8 \(DEBUGSZ\) +0x0
+#...