[07/14] add infcall_mmap and gcc_target_options gdbarch methods

Message ID 1400253995-12333-8-git-send-email-tromey@redhat.com
State Superseded
Headers

Commit Message

Tom Tromey May 16, 2014, 3:26 p.m. UTC
  From: Jan Kratochvil <jan.kratochvil@redhat.com>

The compiler needed two new gdbarch methods.

The infcall_mmap method allocates memory in the inferior.
This is used when inserting the object code.

The gcc_target_options method computes some arch-specific gcc options
to pass to the compiler.  This is used to ensure that gcc generates
object code for the correct architecture.

2014-05-16  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* arch-utils.c (default_infcall_mmap)
	(default_gcc_target_options): New functions.
	* arch-utils.h (default_infcall_mmap, default_gcc_target_options):
	Declare.
	* gdbarch.h: Rebuild.
	* gdbarch.c: Rebuild.
	* gdbarch.sh (infcall_mmap, gcc_target_options): New methods.
---
 gdb/ChangeLog    | 10 ++++++++++
 gdb/arch-utils.c | 13 +++++++++++++
 gdb/arch-utils.h |  4 ++++
 gdb/gdbarch.c    | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdbarch.h    | 18 ++++++++++++++++++
 gdb/gdbarch.sh   | 12 ++++++++++++
 6 files changed, 103 insertions(+)
  

Comments

Yao Qi May 19, 2014, 6:10 a.m. UTC | #1
On 05/16/2014 11:26 PM, Tom Tromey wrote:
> The compiler needed two new gdbarch methods.
> 
> The infcall_mmap method allocates memory in the inferior.
> This is used when inserting the object code.

IMO, "infcall_mmap" is confusing....

> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
> index 9f357b6..6b2bc12 100755
> --- a/gdb/gdbarch.sh
> +++ b/gdb/gdbarch.sh
> @@ -1029,6 +1029,18 @@ m:int:insn_is_jump:CORE_ADDR addr:addr::default_insn_is_jump::0
>  # Return -1 if there is insufficient buffer for a whole entry.
>  # Return 1 if an entry was read into *TYPEP and *VALP.
>  M:int:auxv_parse:gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp:readptr, endptr, typep, valp
> +
> +# Allocate SIZE bytes of PROT protected page aligned memory in inferior.
> +# PROT has rwx bitmask format - bit 2 (value 4) is for readable memory, bit 1
> +# (value 2) is for writable memory and bit 0 (value 1) is for executable memory.
> +# Throw an error if it is not possible.  Returned address is always valid.
> +f:CORE_ADDR:infcall_mmap:CORE_ADDR size, unsigned prot:size, prot::default_infcall_mmap::0
> +

.... looks this hook is to allocate some target memory pages with
certain required permissions.  Probably, we can use "allocate_memory"
or "mmap".

> +# Return string (caller has to use xfree for it) with options for GCC
> +# to produce code for this target, typically "-m64", "-m32" or "-m31".
> +# These options are put before CU's DW_AT_producer compilation options so that
> +# they can override it.  Method may also return NULL.
> +m:char *:gcc_target_options:void:::default_gcc_target_options::0
>  EOF
>  }

I doubt the interface like this is sufficient for other archs, like
arm and mips, which have multiple multilibs, such as -marm/thumb,
-mfloat-abi={hard,softfp}, etc.  This hook in GDB has to take something
into account, such as gdbarch, current frame, the related bfd, etc, in
order to return a correct or compatible options for gcc to compile
source.
  
Jan Kratochvil May 19, 2014, 6:40 a.m. UTC | #2
On Mon, 19 May 2014 08:10:25 +0200, Yao Qi wrote:
> > +# Allocate SIZE bytes of PROT protected page aligned memory in inferior.
> > +# PROT has rwx bitmask format - bit 2 (value 4) is for readable memory, bit 1
> > +# (value 2) is for writable memory and bit 0 (value 1) is for executable memory.
> > +# Throw an error if it is not possible.  Returned address is always valid.
> > +f:CORE_ADDR:infcall_mmap:CORE_ADDR size, unsigned prot:size, prot::default_infcall_mmap::0
> > +
> 
> .... looks this hook is to allocate some target memory pages with
> certain required permissions.  Probably, we can use "allocate_memory"
> or "mmap".

I am then for plain "mmap".  "allocate_memory" suggests me more malloc().


> > +# Return string (caller has to use xfree for it) with options for GCC
> > +# to produce code for this target, typically "-m64", "-m32" or "-m31".
> > +# These options are put before CU's DW_AT_producer compilation options so that
> > +# they can override it.  Method may also return NULL.
> > +m:char *:gcc_target_options:void:::default_gcc_target_options::0
> >  EOF
> >  }
> 
> I doubt the interface like this is sufficient for other archs, like
> arm and mips, which have multiple multilibs, such as -marm/thumb,
> -mfloat-abi={hard,softfp}, etc.  This hook in GDB has to take something
> into account, such as gdbarch, current frame, the related bfd, etc, in
> order to return a correct or compatible options for gcc to compile
> source.

It already already takes 'gdbarch' as its parameter.  If it is not enough some
more parameters can be added.  But IMO those should be added only when this
method gets implemented for arch which needs such parameter.


Thanks,
Jan
  
Jan Kratochvil May 19, 2014, 6:47 a.m. UTC | #3
On Mon, 19 May 2014 08:40:19 +0200, Jan Kratochvil wrote:
> On Mon, 19 May 2014 08:10:25 +0200, Yao Qi wrote:
> > > +# Return string (caller has to use xfree for it) with options for GCC
> > > +# to produce code for this target, typically "-m64", "-m32" or "-m31".
> > > +# These options are put before CU's DW_AT_producer compilation options so that
> > > +# they can override it.  Method may also return NULL.
> > > +m:char *:gcc_target_options:void:::default_gcc_target_options::0
> > >  EOF
> > >  }
> > 
> > I doubt the interface like this is sufficient for other archs, like
> > arm and mips, which have multiple multilibs, such as -marm/thumb,
> > -mfloat-abi={hard,softfp}, etc.  This hook in GDB has to take something
> > into account, such as gdbarch, current frame, the related bfd, etc, in
> > order to return a correct or compatible options for gcc to compile
> > source.
> 
> It already already takes 'gdbarch' as its parameter.  If it is not enough some
> more parameters can be added.  But IMO those should be added only when this
> method gets implemented for arch which needs such parameter.

Oh, you maybe mean that default_gcc_target_options should just error() out as
the default implementation does not work for many existing archs.  And only
tested archs should get implemented their gcc_target_options (even if they
look as the current default_gcc_target_options).

I was considering it but I was expecting 99% of arch will look the same but if
it is not the case the default really can be error().


Jan
  
Yao Qi May 19, 2014, 7:39 a.m. UTC | #4
On 05/19/2014 02:40 PM, Jan Kratochvil wrote:
>> I doubt the interface like this is sufficient for other archs, like
>> > arm and mips, which have multiple multilibs, such as -marm/thumb,
>> > -mfloat-abi={hard,softfp}, etc.  This hook in GDB has to take something
>> > into account, such as gdbarch, current frame, the related bfd, etc, in
>> > order to return a correct or compatible options for gcc to compile
>> > source.
> It already already takes 'gdbarch' as its parameter.  If it is not enough some
> more parameters can be added.  But IMO those should be added only when this
> method gets implemented for arch which needs such parameter.

We can add these parameters when we really need them.  That is fine.
However, I still doubt whether GDB is able to return the correct gcc
options by means of analysing executable only.  Supposing the executable
is compiled with "-march=armv7-a -mthumb -mfloat-abi=hard -mfpu=neon",
GDB should know the code is thumb and float-abi is hard.  How can GDB
tell "-march=armv7-a -mfpu=neon" is used too?  If GDB doesn't know,
what options this hook should return? and is the object code
compiled "on the fly" still compatible to the inferior code and target
runtime?
  
Agovic, Sanimir May 19, 2014, 8:26 a.m. UTC | #5
> On 05/19/2014 02:40 PM, Jan Kratochvil wrote:

> >> I doubt the interface like this is sufficient for other archs, like

> >> > arm and mips, which have multiple multilibs, such as -marm/thumb,

> >> > -mfloat-abi={hard,softfp}, etc.  This hook in GDB has to take something

> >> > into account, such as gdbarch, current frame, the related bfd, etc, in

> >> > order to return a correct or compatible options for gcc to compile

> >> > source.

> > It already already takes 'gdbarch' as its parameter.  If it is not enough some

> > more parameters can be added.  But IMO those should be added only when this

> > method gets implemented for arch which needs such parameter.

> 

> We can add these parameters when we really need them.  That is fine.

> However, I still doubt whether GDB is able to return the correct gcc

> options by means of analysing executable only.  Supposing the executable

> is compiled with "-march=armv7-a -mthumb -mfloat-abi=hard -mfpu=neon",

> GDB should know the code is thumb and float-abi is hard.  How can GDB

> tell "-march=armv7-a -mfpu=neon" is used too?  If GDB doesn't know,

> what options this hook should return? and is the object code

> compiled "on the fly" still compatible to the inferior code and target

> runtime?

> 

This will probably only work for host == target with the default compiler
options. Any other cases are doomed to fail. So your example is one out 
of many.

We may consider picking the cu die for the current $pc and extract the compiler
options from DW_AT_producer[1]. But this requires parsing the necessary bits out
of a string. Adding something like DW_AT_producer_options to dwarf would make
things more straight forward.

[1] DW_AT_producer    : [...] -mtune=generic -march=x86-64 -g

-Sanimir

Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052
  
Jan Kratochvil May 19, 2014, 11:15 a.m. UTC | #6
On Mon, 19 May 2014 10:26:43 +0200, Agovic, Sanimir wrote:
> We may consider picking the cu die for the current $pc and extract the compiler
> options from DW_AT_producer[1]. But this requires parsing the necessary bits out
> of a string. Adding something like DW_AT_producer_options to dwarf would make
> things more straight forward.
> 
> [1] DW_AT_producer    : [...] -mtune=generic -march=x86-64 -g

This is already done in this patchset.  I expect if one uses the compiled
expressions one is probably using -g non-stripped inferior.

This gdbarch gcc_target_options method is there only as some fallback for
stripped / non-g / old gcc / -gno-record-gcc-switches inferiors.


Jan
  

Patch

diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index bff1a10..e2aea7a 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -819,6 +819,19 @@  int default_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr)
   return 0;
 }
 
+CORE_ADDR
+default_infcall_mmap (CORE_ADDR size, unsigned prot)
+{
+  error (_("This target does not support inferior memory allocation by mmap."));
+}
+
+char *
+default_gcc_target_options (struct gdbarch *gdbarch)
+{
+  return xstrprintf ("-m%d%s", gdbarch_ptr_bit (gdbarch),
+		     gdbarch_ptr_bit (gdbarch) == 64 ? " -mcmodel=large" : "");
+}
+
 /* */
 
 /* -Wmissing-prototypes */
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index 46d1573..d4bf353 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -174,4 +174,8 @@  extern int default_return_in_first_hidden_param_p (struct gdbarch *,
 extern int default_insn_is_call (struct gdbarch *, CORE_ADDR);
 extern int default_insn_is_ret (struct gdbarch *, CORE_ADDR);
 extern int default_insn_is_jump (struct gdbarch *, CORE_ADDR);
+
+extern CORE_ADDR default_infcall_mmap (CORE_ADDR size, unsigned prot);
+extern char *default_gcc_target_options (struct gdbarch *gdbarch);
+
 #endif
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 4f82095..b931690 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -319,6 +319,8 @@  struct gdbarch
   gdbarch_insn_is_ret_ftype *insn_is_ret;
   gdbarch_insn_is_jump_ftype *insn_is_jump;
   gdbarch_auxv_parse_ftype *auxv_parse;
+  gdbarch_infcall_mmap_ftype *infcall_mmap;
+  gdbarch_gcc_target_options_ftype *gcc_target_options;
 };
 
 /* Create a new ``struct gdbarch'' based on information provided by
@@ -411,6 +413,8 @@  gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->insn_is_call = default_insn_is_call;
   gdbarch->insn_is_ret = default_insn_is_ret;
   gdbarch->insn_is_jump = default_insn_is_jump;
+  gdbarch->infcall_mmap = default_infcall_mmap;
+  gdbarch->gcc_target_options = default_gcc_target_options;
   /* gdbarch_alloc() */
 
   return gdbarch;
@@ -630,6 +634,8 @@  verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of insn_is_ret, invalid_p == 0 */
   /* Skip verify of insn_is_jump, invalid_p == 0 */
   /* Skip verify of auxv_parse, has predicate.  */
+  /* Skip verify of infcall_mmap, invalid_p == 0 */
+  /* Skip verify of gcc_target_options, invalid_p == 0 */
   buf = ui_file_xstrdup (log, &length);
   make_cleanup (xfree, buf);
   if (length > 0)
@@ -894,6 +900,9 @@  gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: frame_red_zone_size = %s\n",
                       plongest (gdbarch->frame_red_zone_size));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gcc_target_options = <%s>\n",
+                      host_address_to_string (gdbarch->gcc_target_options));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_gcore_bfd_target_p() = %d\n",
                       gdbarch_gcore_bfd_target_p (gdbarch));
   fprintf_unfiltered (file,
@@ -960,6 +969,9 @@  gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: in_solib_return_trampoline = <%s>\n",
                       host_address_to_string (gdbarch->in_solib_return_trampoline));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: infcall_mmap = <%s>\n",
+                      host_address_to_string (gdbarch->infcall_mmap));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_info_proc_p() = %d\n",
                       gdbarch_info_proc_p (gdbarch));
   fprintf_unfiltered (file,
@@ -4406,6 +4418,40 @@  set_gdbarch_auxv_parse (struct gdbarch *gdbarch,
   gdbarch->auxv_parse = auxv_parse;
 }
 
+CORE_ADDR
+gdbarch_infcall_mmap (struct gdbarch *gdbarch, CORE_ADDR size, unsigned prot)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->infcall_mmap != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_infcall_mmap called\n");
+  return gdbarch->infcall_mmap (size, prot);
+}
+
+void
+set_gdbarch_infcall_mmap (struct gdbarch *gdbarch,
+                          gdbarch_infcall_mmap_ftype infcall_mmap)
+{
+  gdbarch->infcall_mmap = infcall_mmap;
+}
+
+char *
+gdbarch_gcc_target_options (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->gcc_target_options != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_gcc_target_options called\n");
+  return gdbarch->gcc_target_options (gdbarch);
+}
+
+void
+set_gdbarch_gcc_target_options (struct gdbarch *gdbarch,
+                                gdbarch_gcc_target_options_ftype gcc_target_options)
+{
+  gdbarch->gcc_target_options = gcc_target_options;
+}
+
 
 /* Keep a registry of per-architecture data-pointers required by GDB
    modules.  */
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index c621091..00fc1ac 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -1316,6 +1316,24 @@  typedef int (gdbarch_auxv_parse_ftype) (struct gdbarch *gdbarch, gdb_byte **read
 extern int gdbarch_auxv_parse (struct gdbarch *gdbarch, gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp);
 extern void set_gdbarch_auxv_parse (struct gdbarch *gdbarch, gdbarch_auxv_parse_ftype *auxv_parse);
 
+/* Allocate SIZE bytes of PROT protected page aligned memory in inferior.
+   PROT has rwx bitmask format - bit 2 (value 4) is for readable memory, bit 1
+   (value 2) is for writable memory and bit 0 (value 1) is for executable memory.
+   Throw an error if it is not possible.  Returned address is always valid. */
+
+typedef CORE_ADDR (gdbarch_infcall_mmap_ftype) (CORE_ADDR size, unsigned prot);
+extern CORE_ADDR gdbarch_infcall_mmap (struct gdbarch *gdbarch, CORE_ADDR size, unsigned prot);
+extern void set_gdbarch_infcall_mmap (struct gdbarch *gdbarch, gdbarch_infcall_mmap_ftype *infcall_mmap);
+
+/* Return string (caller has to use xfree for it) with options for GCC
+   to produce code for this target, typically "-m64", "-m32" or "-m31".
+   These options are put before CU's DW_AT_producer compilation options so that
+   they can override it.  Method may also return NULL. */
+
+typedef char * (gdbarch_gcc_target_options_ftype) (struct gdbarch *gdbarch);
+extern char * gdbarch_gcc_target_options (struct gdbarch *gdbarch);
+extern void set_gdbarch_gcc_target_options (struct gdbarch *gdbarch, gdbarch_gcc_target_options_ftype *gcc_target_options);
+
 /* Definition for an unknown syscall, used basically in error-cases.  */
 #define UNKNOWN_SYSCALL (-1)
 
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 9f357b6..6b2bc12 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1029,6 +1029,18 @@  m:int:insn_is_jump:CORE_ADDR addr:addr::default_insn_is_jump::0
 # Return -1 if there is insufficient buffer for a whole entry.
 # Return 1 if an entry was read into *TYPEP and *VALP.
 M:int:auxv_parse:gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp:readptr, endptr, typep, valp
+
+# Allocate SIZE bytes of PROT protected page aligned memory in inferior.
+# PROT has rwx bitmask format - bit 2 (value 4) is for readable memory, bit 1
+# (value 2) is for writable memory and bit 0 (value 1) is for executable memory.
+# Throw an error if it is not possible.  Returned address is always valid.
+f:CORE_ADDR:infcall_mmap:CORE_ADDR size, unsigned prot:size, prot::default_infcall_mmap::0
+
+# Return string (caller has to use xfree for it) with options for GCC
+# to produce code for this target, typically "-m64", "-m32" or "-m31".
+# These options are put before CU's DW_AT_producer compilation options so that
+# they can override it.  Method may also return NULL.
+m:char *:gcc_target_options:void:::default_gcc_target_options::0
 EOF
 }