Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH/RFC] Parsing auxv entries
@ 2014-02-04 14:42 Mark Kettenis
  2014-02-06 19:03 ` Pedro Alves
  0 siblings, 1 reply; 6+ messages in thread
From: Mark Kettenis @ 2014-02-04 14:42 UTC (permalink / raw)
  To: gdb-patches

The diff below adds a gdbarch method to parse auxv entries.  The
parsing code currently lives in the target_ops vector, and this poses
a problem.  Because default_auxv_parse() implements parsing of the
non-standard auxv entries used by Linux (where the type is stored in a
'long' instead of an 'int'), it doesn't work on 64-bit big-endian
targets that do follow the SVR4 layout.  I've worked around this by
overriding to_auxv_parse in inf_ptrace_trace() for native BSD targets,
but that means the core_ops target is still broken.  And as we build
binaries as PIE by default on OpenBSD now, where auxv parsing is
essential to find out the load address of the executable, reading core
dumps on our 64-bit big-endian platforms is pretty much broken right
now.  And overriding to_auxv_parse for the core_ops target is painful.

I believe gdbarch is the right place for this functionality.  On many
platforms the memory layout of the entries is consistent across the
various sources.  But there may be some issues with running 32-bit
binaries on 64-bit systems in relation to things like /proc/*/auxv.  I
suppose to_auxv_parse was designed to solve such problems, although I
fail to see how the current implementation would work in the scenario
of running 32-bit binarie on a platform where /proc/*/auxv provides
the auxv entries in 64-bit format.

Thoughts?  OK?


2014-02-04  Mark Kettenis  <kettenis@gnu.org>
 
	* gdbarch.sh (parse_auxv): New.
	* gdbarch.h: Regenerated.
	* gdbarch.c: Regenerated.
	* auxv.c (target_auxv_parse): Call gdbarch_parse_auxv if provided.

diff --git a/gdb/auxv.c b/gdb/auxv.c
index dd13237..dcc6345 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -269,8 +269,12 @@ int
 target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
                   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
 {
+  struct gdbarch *gdbarch = target_gdbarch();
   struct target_ops *t;
 
+  if (gdbarch_parse_auxv_p (gdbarch))
+    return gdbarch_parse_auxv (gdbarch, readptr, endptr, typep, valp);
+
   for (t = ops; t != NULL; t = t->beneath)
     if (t->to_auxv_parse != NULL)
       return t->to_auxv_parse (t, readptr, endptr, typep, valp);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 36dff57..88f481e 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1007,6 +1007,12 @@ m:int:insn_is_ret:CORE_ADDR addr:addr::default_insn_is_ret::0
 
 # Return non-zero if the instruction at ADDR is a jump; zero otherwise.
 m:int:insn_is_jump:CORE_ADDR addr:addr::default_insn_is_jump::0
+
+# Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
+# Return 0 if *READPTR is already at the end of the buffer.
+# Return -1 if there is insufficient buffer for a whole entry.
+# Return 1 if an entry was read into *TYPEP and *VALP.
+M:int:parse_auxv:gdb_byte **readptr, gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp:readptr, endptr, typep, valp
 EOF
 }
 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH/RFC] Parsing auxv entries
  2014-02-04 14:42 [PATCH/RFC] Parsing auxv entries Mark Kettenis
@ 2014-02-06 19:03 ` Pedro Alves
  2014-02-06 21:33   ` Mark Kettenis
  0 siblings, 1 reply; 6+ messages in thread
From: Pedro Alves @ 2014-02-06 19:03 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

On 02/04/2014 02:41 PM, Mark Kettenis wrote:
> The diff below adds a gdbarch method to parse auxv entries.  The
> parsing code currently lives in the target_ops vector, and this poses
> a problem.  Because default_auxv_parse() implements parsing of the
> non-standard auxv entries used by Linux (where the type is stored in a
> 'long' instead of an 'int'), it doesn't work on 64-bit big-endian
> targets that do follow the SVR4 layout.  I've worked around this by
> overriding to_auxv_parse in inf_ptrace_trace() for native BSD targets,
> but that means the core_ops target is still broken.  And as we build
> binaries as PIE by default on OpenBSD now, where auxv parsing is
> essential to find out the load address of the executable, reading core
> dumps on our 64-bit big-endian platforms is pretty much broken right
> now.  And overriding to_auxv_parse for the core_ops target is painful.
> 
> I believe gdbarch is the right place for this functionality.  On many
> platforms the memory layout of the entries is consistent across the
> various sources.  

> But there may be some issues with running 32-bit
> binaries on 64-bit systems in relation to things like /proc/*/auxv.  I
> suppose to_auxv_parse was designed to solve such problems, although I
> fail to see how the current implementation would work in the scenario
> of running 32-bit binarie on a platform where /proc/*/auxv provides
> the auxv entries in 64-bit format.

Yeah.  See the Solaris version:

#if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
/* When GDB is built as 64-bit application on Solaris, the auxv data
   is presented in 64-bit format.  We need to provide a custom parser
   to handle that.  */
static int
procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
{

> 
> Thoughts?  OK?

Hmm, thoughts then.

gdbarch does seems the right place, in principle.  Though
things in practice don't look that simple.

Consider for example a 32-bit Solaris gdb, connected to a
64-bit gdbserver.  In that case, the auxv data is presented
to gdbserver in a 64-bit format, and then in turn that's what
gdbserver sends back to GDB in response to TARGET_OBJECT_AUXV.
GDB won't be able to figure out which layout of auxv it's
looking at, unless perhaps it looks at the auxv block
size (ewwwww), or explicitly asks the target/server which
variant it sends.

Not sure what the real proper fix for this would be.  Several
options I see.  There might be more or even better ones.

  #1 - Install a solaris-specific gdbarch parse auxv hook
    that has gdb ask the target which variant of auxv is handed
    to gdb to work with.
  #2 - Hide the fact that the auxv data is presented differently
    depending on the bitness of the superior, by making the target
    do layout translation when returning the TARGET_OBJECT_AUXV
    object (like done with TARGET_OBJECT_SIGNAL_INFO on Linux).
  #3 - Hide the fact that the auxv data is presented differently
    depending on the bitness of the superior, by making the target
    always translate the auxv block to a host and target
    independent format that the core consumes (xml?).

#2 seems tempting; though so does #3, a little.  Dunno, #1 does
too, just a little, perhaps not.

And PowerPC has a similar issue:

 https://sourceware.org/ml/gdb-patches/2009-01/msg00440.html

And that shows that we can't move the auxv parsing to
gdbarch by default on Linux either.  At least, not if we don't
consult the target before the gdbarch hook.  But then, it
sounds like 32-bit gdb against 64-bit gdbserver on ppc might
be similarly broken in some scenarios.  #3 above starts
sounding a little better than #2.

So I swing back -- thought?  :-)

> 
> 
> 2014-02-04  Mark Kettenis  <kettenis@gnu.org>
>  
> 	* gdbarch.sh (parse_auxv): New.
> 	* gdbarch.h: Regenerated.
> 	* gdbarch.c: Regenerated.
> 	* auxv.c (target_auxv_parse): Call gdbarch_parse_auxv if provided.
> 
> diff --git a/gdb/auxv.c b/gdb/auxv.c
> index dd13237..dcc6345 100644
> --- a/gdb/auxv.c
> +++ b/gdb/auxv.c
> @@ -269,8 +269,12 @@ int
>  target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
>                    gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
>  {
> +  struct gdbarch *gdbarch = target_gdbarch();
>    struct target_ops *t;
>  
> +  if (gdbarch_parse_auxv_p (gdbarch))
> +    return gdbarch_parse_auxv (gdbarch, readptr, endptr, typep, valp);

If this proceeds, can you please rename the hook in accordance
to the target method?  That is, gdbarch_auxv_parse rather than
gdbarch_parse_auxv, so that greps have a better chance of
hitting both?

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH/RFC] Parsing auxv entries
  2014-02-06 19:03 ` Pedro Alves
@ 2014-02-06 21:33   ` Mark Kettenis
  2014-02-10 16:51     ` Pedro Alves
  0 siblings, 1 reply; 6+ messages in thread
From: Mark Kettenis @ 2014-02-06 21:33 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

> Date: Thu, 06 Feb 2014 19:03:53 +0000
> From: Pedro Alves <palves@redhat.com>
> 
> On 02/04/2014 02:41 PM, Mark Kettenis wrote:
> > The diff below adds a gdbarch method to parse auxv entries.  The
> > parsing code currently lives in the target_ops vector, and this poses
> > a problem.  Because default_auxv_parse() implements parsing of the
> > non-standard auxv entries used by Linux (where the type is stored in a
> > 'long' instead of an 'int'), it doesn't work on 64-bit big-endian
> > targets that do follow the SVR4 layout.  I've worked around this by
> > overriding to_auxv_parse in inf_ptrace_trace() for native BSD targets,
> > but that means the core_ops target is still broken.  And as we build
> > binaries as PIE by default on OpenBSD now, where auxv parsing is
> > essential to find out the load address of the executable, reading core
> > dumps on our 64-bit big-endian platforms is pretty much broken right
> > now.  And overriding to_auxv_parse for the core_ops target is painful.
> > 
> > I believe gdbarch is the right place for this functionality.  On many
> > platforms the memory layout of the entries is consistent across the
> > various sources.  
> 
> > But there may be some issues with running 32-bit
> > binaries on 64-bit systems in relation to things like /proc/*/auxv.  I
> > suppose to_auxv_parse was designed to solve such problems, although I
> > fail to see how the current implementation would work in the scenario
> > of running 32-bit binarie on a platform where /proc/*/auxv provides
> > the auxv entries in 64-bit format.
> 
> Yeah.  See the Solaris version:
> 
> #if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
> /* When GDB is built as 64-bit application on Solaris, the auxv data
>    is presented in 64-bit format.  We need to provide a custom parser
>    to handle that.  */
> static int
> procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
> 		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
> {
> 
> > 
> > Thoughts?  OK?
> 
> Hmm, thoughts then.
> 
> gdbarch does seems the right place, in principle.  Though
> things in practice don't look that simple.
> 
> Consider for example a 32-bit Solaris gdb, connected to a
> 64-bit gdbserver.  In that case, the auxv data is presented
> to gdbserver in a 64-bit format, and then in turn that's what
> gdbserver sends back to GDB in response to TARGET_OBJECT_AUXV.
> GDB won't be able to figure out which layout of auxv it's
> looking at, unless perhaps it looks at the auxv block
> size (ewwwww), or explicitly asks the target/server which
> variant it sends.
> 
> Not sure what the real proper fix for this would be.  Several
> options I see.  There might be more or even better ones.
> 
>   #1 - Install a solaris-specific gdbarch parse auxv hook
>     that has gdb ask the target which variant of auxv is handed
>     to gdb to work with.
>   #2 - Hide the fact that the auxv data is presented differently
>     depending on the bitness of the superior, by making the target
>     do layout translation when returning the TARGET_OBJECT_AUXV
>     object (like done with TARGET_OBJECT_SIGNAL_INFO on Linux).
>   #3 - Hide the fact that the auxv data is presented differently
>     depending on the bitness of the superior, by making the target
>     always translate the auxv block to a host and target
>     independent format that the core consumes (xml?).
> 
> #2 seems tempting; though so does #3, a little.  Dunno, #1 does
> too, just a little, perhaps not.
> 
> And PowerPC has a similar issue:
> 
>  https://sourceware.org/ml/gdb-patches/2009-01/msg00440.html
> 
> And that shows that we can't move the auxv parsing to
> gdbarch by default on Linux either.  At least, not if we don't
> consult the target before the gdbarch hook.  But then, it
> sounds like 32-bit gdb against 64-bit gdbserver on ppc might
> be similarly broken in some scenarios.  #3 above starts
> sounding a little better than #2.
> 
> So I swing back -- thought?  :-)

Hmm, gdbserver would be aware of whether it is running a 32-bit or
64-bit binary would it?  So having it translate the auxv entries into
native format should work just fine.

Given the contraints, we'll probably have to live with with having
both the target_ops and the gdbarch methods.  I thought about this a
little bit more yesterday and it seems that we want to move to the
situation where we try things in the following order:

1. The target_ops method if it has been set.

2. The gdbarch method if it has been set.

3. default_auxv_parse().

Targets that always see the auxv entries in the "native" format like
OpenBSD would only set the gdbarch method.  Targets that fetch entries
from /proc in a format that doesn't necessary match the bitness of the
binary that's running (Linux, Solaris) would set the target_ops
method.  Solaris would probably need to set the gdbarch method as well
to avoid using default_auxv_parse() which doesn't do the right thing
for SPARC.

My diff currently has the order of 1 and 2 reversed.  But I think I
can just switch those around.

> > 2014-02-04  Mark Kettenis  <kettenis@gnu.org>
> >  
> > 	* gdbarch.sh (parse_auxv): New.
> > 	* gdbarch.h: Regenerated.
> > 	* gdbarch.c: Regenerated.
> > 	* auxv.c (target_auxv_parse): Call gdbarch_parse_auxv if provided.
> > 
> > diff --git a/gdb/auxv.c b/gdb/auxv.c
> > index dd13237..dcc6345 100644
> > --- a/gdb/auxv.c
> > +++ b/gdb/auxv.c
> > @@ -269,8 +269,12 @@ int
> >  target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
> >                    gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
> >  {
> > +  struct gdbarch *gdbarch = target_gdbarch();
> >    struct target_ops *t;
> >  
> > +  if (gdbarch_parse_auxv_p (gdbarch))
> > +    return gdbarch_parse_auxv (gdbarch, readptr, endptr, typep, valp);
> 
> If this proceeds, can you please rename the hook in accordance
> to the target method?  That is, gdbarch_auxv_parse rather than
> gdbarch_parse_auxv, so that greps have a better chance of
> hitting both?

Will do.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH/RFC] Parsing auxv entries
  2014-02-06 21:33   ` Mark Kettenis
@ 2014-02-10 16:51     ` Pedro Alves
  2014-02-27 13:00       ` Mark Kettenis
  0 siblings, 1 reply; 6+ messages in thread
From: Pedro Alves @ 2014-02-10 16:51 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

On 02/06/2014 09:33 PM, Mark Kettenis wrote:
>> Date: Thu, 06 Feb 2014 19:03:53 +0000
>> From: Pedro Alves <palves@redhat.com>
>>
>> On 02/04/2014 02:41 PM, Mark Kettenis wrote:
>>> The diff below adds a gdbarch method to parse auxv entries.  The
>>> parsing code currently lives in the target_ops vector, and this poses
>>> a problem.  Because default_auxv_parse() implements parsing of the
>>> non-standard auxv entries used by Linux (where the type is stored in a
>>> 'long' instead of an 'int'), it doesn't work on 64-bit big-endian
>>> targets that do follow the SVR4 layout.  I've worked around this by
>>> overriding to_auxv_parse in inf_ptrace_trace() for native BSD targets,
>>> but that means the core_ops target is still broken.  And as we build
>>> binaries as PIE by default on OpenBSD now, where auxv parsing is
>>> essential to find out the load address of the executable, reading core
>>> dumps on our 64-bit big-endian platforms is pretty much broken right
>>> now.  And overriding to_auxv_parse for the core_ops target is painful.
>>>
>>> I believe gdbarch is the right place for this functionality.  On many
>>> platforms the memory layout of the entries is consistent across the
>>> various sources.  
>>
>>> But there may be some issues with running 32-bit
>>> binaries on 64-bit systems in relation to things like /proc/*/auxv.  I
>>> suppose to_auxv_parse was designed to solve such problems, although I
>>> fail to see how the current implementation would work in the scenario
>>> of running 32-bit binarie on a platform where /proc/*/auxv provides
>>> the auxv entries in 64-bit format.
>>
>> Yeah.  See the Solaris version:
>>
>> #if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
>> /* When GDB is built as 64-bit application on Solaris, the auxv data
>>    is presented in 64-bit format.  We need to provide a custom parser
>>    to handle that.  */
>> static int
>> procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
>> 		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
>> {
>>
>>>
>>> Thoughts?  OK?
>>
>> Hmm, thoughts then.
>>
>> gdbarch does seems the right place, in principle.  Though
>> things in practice don't look that simple.
>>
>> Consider for example a 32-bit Solaris gdb, connected to a
>> 64-bit gdbserver.  In that case, the auxv data is presented
>> to gdbserver in a 64-bit format, and then in turn that's what
>> gdbserver sends back to GDB in response to TARGET_OBJECT_AUXV.
>> GDB won't be able to figure out which layout of auxv it's
>> looking at, unless perhaps it looks at the auxv block
>> size (ewwwww), or explicitly asks the target/server which
>> variant it sends.
>>
>> Not sure what the real proper fix for this would be.  Several
>> options I see.  There might be more or even better ones.
>>
>>   #1 - Install a solaris-specific gdbarch parse auxv hook
>>     that has gdb ask the target which variant of auxv is handed
>>     to gdb to work with.
>>   #2 - Hide the fact that the auxv data is presented differently
>>     depending on the bitness of the superior, by making the target
>>     do layout translation when returning the TARGET_OBJECT_AUXV
>>     object (like done with TARGET_OBJECT_SIGNAL_INFO on Linux).
>>   #3 - Hide the fact that the auxv data is presented differently
>>     depending on the bitness of the superior, by making the target
>>     always translate the auxv block to a host and target
>>     independent format that the core consumes (xml?).
>>
>> #2 seems tempting; though so does #3, a little.  Dunno, #1 does
>> too, just a little, perhaps not.
>>
>> And PowerPC has a similar issue:
>>
>>  https://sourceware.org/ml/gdb-patches/2009-01/msg00440.html
>>
>> And that shows that we can't move the auxv parsing to
>> gdbarch by default on Linux either.  At least, not if we don't
>> consult the target before the gdbarch hook.  But then, it
>> sounds like 32-bit gdb against 64-bit gdbserver on ppc might
>> be similarly broken in some scenarios.  #3 above starts
>> sounding a little better than #2.
>>
>> So I swing back -- thought?  :-)
> 
> Hmm, gdbserver would be aware of whether it is running a 32-bit or
> 64-bit binary would it?  

One would hope.

> So having it translate the auxv entries into
> native format should work just fine.

Yes, that's #2 above.  I'm now wondering what does the Solaris kernel
put in the NT_AUXV note in cores generated for 32-bit programs running
on a 64-bit kernel.  One would hope that that would end up with
a 32-bit layout...

GDB's gcore does fill in an NT_AUXV, but it does no layout
translation:

procfs.c:procfs_make_note_section
...
  auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
				NULL, &auxv);
  if (auxv_len > 0)
    {
      note_data = elfcore_write_note (obfd, note_data, note_size,
				      "CORE", NT_AUXV, auxv, auxv_len);
      xfree (auxv);
    }


so with a 64-bit gdb, that'll always end up with 64-bit layout...

If the kernel does 64-bit -> 32-bit translation when generating
cores there (I can't imagine otherwise, but who knows), that too
argues for GDB doing that (i.e., translate at TARGET_OBJECT_AUXV
time) on the Solaris port.

> Given the contraints, we'll probably have to live with with having
> both the target_ops and the gdbarch methods.  I thought about this a
> little bit more yesterday and it seems that we want to move to the
> situation where we try things in the following order:
> 
> 1. The target_ops method if it has been set.
> 
> 2. The gdbarch method if it has been set.
> 
> 3. default_auxv_parse().
> 
> Targets that always see the auxv entries in the "native" format like
> OpenBSD would only set the gdbarch method.  Targets that fetch entries
> from /proc in a format that doesn't necessary match the bitness of the
> binary that's running (Linux, Solaris) would set the target_ops
> method.  

The Linux/PPC issue is not that /proc's format doesn't match
the bitness of the binary.  It's that the auxv needs to be
parsed _before_ the core of GDB even knows the target's
architecture, exactly while trying to figure out the
architecture of the program, as Ulrich said:

> However, there are some scenarios where determining the wordsize
> actually matters (e.g. because the exec file cannot be determined).
> In those cases, the attempts in ppc_linux_read_description would be
> somewhat futile ...

I.e., e.g., no binary at all.   A bit of chicken and egg.
But, that issue can in principle be hidden from core GDB, by
making auxv parsing done by the target backend not go through
GDB core auvx parsing at all.

> Solaris would probably need to set the gdbarch method as well
> to avoid using default_auxv_parse() which doesn't do the right thing
> for SPARC.

> 
> My diff currently has the order of 1 and 2 reversed.  But I think I
> can just switch those around.

I believe so.  I'm trying to figure out whether we actually need
auxv parsing on the target vector at all, and setting up direction
for the future.  Seems very much like we don't, though I'm curious
on the Solaris cores issue.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH/RFC] Parsing auxv entries
  2014-02-10 16:51     ` Pedro Alves
@ 2014-02-27 13:00       ` Mark Kettenis
  2014-02-27 13:17         ` Pedro Alves
  0 siblings, 1 reply; 6+ messages in thread
From: Mark Kettenis @ 2014-02-27 13:00 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches

> Date: Mon, 10 Feb 2014 16:50:58 +0000
> From: Pedro Alves <palves@redhat.com>
> 
> On 02/06/2014 09:33 PM, Mark Kettenis wrote:
> >> Date: Thu, 06 Feb 2014 19:03:53 +0000
> >> From: Pedro Alves <palves@redhat.com>
> >>
> >> On 02/04/2014 02:41 PM, Mark Kettenis wrote:
> >>> The diff below adds a gdbarch method to parse auxv entries.  The
> >>> parsing code currently lives in the target_ops vector, and this poses
> >>> a problem.  Because default_auxv_parse() implements parsing of the
> >>> non-standard auxv entries used by Linux (where the type is stored in a
> >>> 'long' instead of an 'int'), it doesn't work on 64-bit big-endian
> >>> targets that do follow the SVR4 layout.  I've worked around this by
> >>> overriding to_auxv_parse in inf_ptrace_trace() for native BSD targets,
> >>> but that means the core_ops target is still broken.  And as we build
> >>> binaries as PIE by default on OpenBSD now, where auxv parsing is
> >>> essential to find out the load address of the executable, reading core
> >>> dumps on our 64-bit big-endian platforms is pretty much broken right
> >>> now.  And overriding to_auxv_parse for the core_ops target is painful.
> >>>
> >>> I believe gdbarch is the right place for this functionality.  On many
> >>> platforms the memory layout of the entries is consistent across the
> >>> various sources.  
> >>
> >>> But there may be some issues with running 32-bit
> >>> binaries on 64-bit systems in relation to things like /proc/*/auxv.  I
> >>> suppose to_auxv_parse was designed to solve such problems, although I
> >>> fail to see how the current implementation would work in the scenario
> >>> of running 32-bit binarie on a platform where /proc/*/auxv provides
> >>> the auxv entries in 64-bit format.
> >>
> >> Yeah.  See the Solaris version:
> >>
> >> #if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
> >> /* When GDB is built as 64-bit application on Solaris, the auxv data
> >>    is presented in 64-bit format.  We need to provide a custom parser
> >>    to handle that.  */
> >> static int
> >> procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
> >> 		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
> >> {
> >>
> >>>
> >>> Thoughts?  OK?
> >>
> >> Hmm, thoughts then.
> >>
> >> gdbarch does seems the right place, in principle.  Though
> >> things in practice don't look that simple.
> >>
> >> Consider for example a 32-bit Solaris gdb, connected to a
> >> 64-bit gdbserver.  In that case, the auxv data is presented
> >> to gdbserver in a 64-bit format, and then in turn that's what
> >> gdbserver sends back to GDB in response to TARGET_OBJECT_AUXV.
> >> GDB won't be able to figure out which layout of auxv it's
> >> looking at, unless perhaps it looks at the auxv block
> >> size (ewwwww), or explicitly asks the target/server which
> >> variant it sends.
> >>
> >> Not sure what the real proper fix for this would be.  Several
> >> options I see.  There might be more or even better ones.
> >>
> >>   #1 - Install a solaris-specific gdbarch parse auxv hook
> >>     that has gdb ask the target which variant of auxv is handed
> >>     to gdb to work with.
> >>   #2 - Hide the fact that the auxv data is presented differently
> >>     depending on the bitness of the superior, by making the target
> >>     do layout translation when returning the TARGET_OBJECT_AUXV
> >>     object (like done with TARGET_OBJECT_SIGNAL_INFO on Linux).
> >>   #3 - Hide the fact that the auxv data is presented differently
> >>     depending on the bitness of the superior, by making the target
> >>     always translate the auxv block to a host and target
> >>     independent format that the core consumes (xml?).
> >>
> >> #2 seems tempting; though so does #3, a little.  Dunno, #1 does
> >> too, just a little, perhaps not.
> >>
> >> And PowerPC has a similar issue:
> >>
> >>  https://sourceware.org/ml/gdb-patches/2009-01/msg00440.html
> >>
> >> And that shows that we can't move the auxv parsing to
> >> gdbarch by default on Linux either.  At least, not if we don't
> >> consult the target before the gdbarch hook.  But then, it
> >> sounds like 32-bit gdb against 64-bit gdbserver on ppc might
> >> be similarly broken in some scenarios.  #3 above starts
> >> sounding a little better than #2.
> >>
> >> So I swing back -- thought?  :-)
> > 
> > Hmm, gdbserver would be aware of whether it is running a 32-bit or
> > 64-bit binary would it?  
> 
> One would hope.
> 
> > So having it translate the auxv entries into
> > native format should work just fine.
> 
> Yes, that's #2 above.  I'm now wondering what does the Solaris kernel
> put in the NT_AUXV note in cores generated for 32-bit programs running
> on a 64-bit kernel.  One would hope that that would end up with
> a 32-bit layout...
> 
> GDB's gcore does fill in an NT_AUXV, but it does no layout
> translation:
> 
> procfs.c:procfs_make_note_section
> ...
>   auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
> 				NULL, &auxv);
>   if (auxv_len > 0)
>     {
>       note_data = elfcore_write_note (obfd, note_data, note_size,
> 				      "CORE", NT_AUXV, auxv, auxv_len);
>       xfree (auxv);
>     }
> 
> 
> so with a 64-bit gdb, that'll always end up with 64-bit layout...
> 
> If the kernel does 64-bit -> 32-bit translation when generating
> cores there (I can't imagine otherwise, but who knows), that too
> argues for GDB doing that (i.e., translate at TARGET_OBJECT_AUXV
> time) on the Solaris port.
> 
> > Given the contraints, we'll probably have to live with with having
> > both the target_ops and the gdbarch methods.  I thought about this a
> > little bit more yesterday and it seems that we want to move to the
> > situation where we try things in the following order:
> > 
> > 1. The target_ops method if it has been set.
> > 
> > 2. The gdbarch method if it has been set.
> > 
> > 3. default_auxv_parse().
> > 
> > Targets that always see the auxv entries in the "native" format like
> > OpenBSD would only set the gdbarch method.  Targets that fetch entries
> > from /proc in a format that doesn't necessary match the bitness of the
> > binary that's running (Linux, Solaris) would set the target_ops
> > method.  
> 
> The Linux/PPC issue is not that /proc's format doesn't match
> the bitness of the binary.  It's that the auxv needs to be
> parsed _before_ the core of GDB even knows the target's
> architecture, exactly while trying to figure out the
> architecture of the program, as Ulrich said:
> 
> > However, there are some scenarios where determining the wordsize
> > actually matters (e.g. because the exec file cannot be determined).
> > In those cases, the attempts in ppc_linux_read_description would be
> > somewhat futile ...
> 
> I.e., e.g., no binary at all.   A bit of chicken and egg.
> But, that issue can in principle be hidden from core GDB, by
> making auxv parsing done by the target backend not go through
> GDB core auvx parsing at all.
> 
> > Solaris would probably need to set the gdbarch method as well
> > to avoid using default_auxv_parse() which doesn't do the right thing
> > for SPARC.
> 
> > 
> > My diff currently has the order of 1 and 2 reversed.  But I think I
> > can just switch those around.
> 
> I believe so.  I'm trying to figure out whether we actually need
> auxv parsing on the target vector at all, and setting up direction
> for the future.  Seems very much like we don't, though I'm curious
> on the Solaris cores issue.

Well, the target delegation reworking made the issue moot, as I can't
change the order anymore.  I think that points out a bit of a problem
with that change, but as it doesn't matter for OpenBSD, I just added
the gdbarch method in front.  Patch as committed can be found here:

  http://sourceware.org/ml/gdb-patches/2014-02/msg00820.html

Somebody who cares anough about Linux on powerpc or Solaris can figure
out if the target stuff is still necessary if they implement the
gdbarch method.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH/RFC] Parsing auxv entries
  2014-02-27 13:00       ` Mark Kettenis
@ 2014-02-27 13:17         ` Pedro Alves
  0 siblings, 0 replies; 6+ messages in thread
From: Pedro Alves @ 2014-02-27 13:17 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

On 02/27/2014 01:00 PM, Mark Kettenis wrote:
>> Date: Mon, 10 Feb 2014 16:50:58 +0000
>> From: Pedro Alves <palves@redhat.com>
>>
>> On 02/06/2014 09:33 PM, Mark Kettenis wrote:
>>>> Date: Thu, 06 Feb 2014 19:03:53 +0000
>>>> From: Pedro Alves <palves@redhat.com>
>>>>
>>>> On 02/04/2014 02:41 PM, Mark Kettenis wrote:
>>>>> The diff below adds a gdbarch method to parse auxv entries.  The
>>>>> parsing code currently lives in the target_ops vector, and this poses
>>>>> a problem.  Because default_auxv_parse() implements parsing of the
>>>>> non-standard auxv entries used by Linux (where the type is stored in a
>>>>> 'long' instead of an 'int'), it doesn't work on 64-bit big-endian
>>>>> targets that do follow the SVR4 layout.  I've worked around this by
>>>>> overriding to_auxv_parse in inf_ptrace_trace() for native BSD targets,
>>>>> but that means the core_ops target is still broken.  And as we build
>>>>> binaries as PIE by default on OpenBSD now, where auxv parsing is
>>>>> essential to find out the load address of the executable, reading core
>>>>> dumps on our 64-bit big-endian platforms is pretty much broken right
>>>>> now.  And overriding to_auxv_parse for the core_ops target is painful.
>>>>>
>>>>> I believe gdbarch is the right place for this functionality.  On many
>>>>> platforms the memory layout of the entries is consistent across the
>>>>> various sources.  
>>>>
>>>>> But there may be some issues with running 32-bit
>>>>> binaries on 64-bit systems in relation to things like /proc/*/auxv.  I
>>>>> suppose to_auxv_parse was designed to solve such problems, although I
>>>>> fail to see how the current implementation would work in the scenario
>>>>> of running 32-bit binarie on a platform where /proc/*/auxv provides
>>>>> the auxv entries in 64-bit format.
>>>>
>>>> Yeah.  See the Solaris version:
>>>>
>>>> #if defined (PR_MODEL_NATIVE) && (PR_MODEL_NATIVE == PR_MODEL_LP64)
>>>> /* When GDB is built as 64-bit application on Solaris, the auxv data
>>>>    is presented in 64-bit format.  We need to provide a custom parser
>>>>    to handle that.  */
>>>> static int
>>>> procfs_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
>>>> 		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
>>>> {
>>>>
>>>>>
>>>>> Thoughts?  OK?
>>>>
>>>> Hmm, thoughts then.
>>>>
>>>> gdbarch does seems the right place, in principle.  Though
>>>> things in practice don't look that simple.
>>>>
>>>> Consider for example a 32-bit Solaris gdb, connected to a
>>>> 64-bit gdbserver.  In that case, the auxv data is presented
>>>> to gdbserver in a 64-bit format, and then in turn that's what
>>>> gdbserver sends back to GDB in response to TARGET_OBJECT_AUXV.
>>>> GDB won't be able to figure out which layout of auxv it's
>>>> looking at, unless perhaps it looks at the auxv block
>>>> size (ewwwww), or explicitly asks the target/server which
>>>> variant it sends.
>>>>
>>>> Not sure what the real proper fix for this would be.  Several
>>>> options I see.  There might be more or even better ones.
>>>>
>>>>   #1 - Install a solaris-specific gdbarch parse auxv hook
>>>>     that has gdb ask the target which variant of auxv is handed
>>>>     to gdb to work with.
>>>>   #2 - Hide the fact that the auxv data is presented differently
>>>>     depending on the bitness of the superior, by making the target
>>>>     do layout translation when returning the TARGET_OBJECT_AUXV
>>>>     object (like done with TARGET_OBJECT_SIGNAL_INFO on Linux).
>>>>   #3 - Hide the fact that the auxv data is presented differently
>>>>     depending on the bitness of the superior, by making the target
>>>>     always translate the auxv block to a host and target
>>>>     independent format that the core consumes (xml?).
>>>>
>>>> #2 seems tempting; though so does #3, a little.  Dunno, #1 does
>>>> too, just a little, perhaps not.
>>>>
>>>> And PowerPC has a similar issue:
>>>>
>>>>  https://sourceware.org/ml/gdb-patches/2009-01/msg00440.html
>>>>
>>>> And that shows that we can't move the auxv parsing to
>>>> gdbarch by default on Linux either.  At least, not if we don't
>>>> consult the target before the gdbarch hook.  But then, it
>>>> sounds like 32-bit gdb against 64-bit gdbserver on ppc might
>>>> be similarly broken in some scenarios.  #3 above starts
>>>> sounding a little better than #2.
>>>>
>>>> So I swing back -- thought?  :-)
>>>
>>> Hmm, gdbserver would be aware of whether it is running a 32-bit or
>>> 64-bit binary would it?  
>>
>> One would hope.
>>
>>> So having it translate the auxv entries into
>>> native format should work just fine.
>>
>> Yes, that's #2 above.  I'm now wondering what does the Solaris kernel
>> put in the NT_AUXV note in cores generated for 32-bit programs running
>> on a 64-bit kernel.  One would hope that that would end up with
>> a 32-bit layout...
>>
>> GDB's gcore does fill in an NT_AUXV, but it does no layout
>> translation:
>>
>> procfs.c:procfs_make_note_section
>> ...
>>   auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
>> 				NULL, &auxv);
>>   if (auxv_len > 0)
>>     {
>>       note_data = elfcore_write_note (obfd, note_data, note_size,
>> 				      "CORE", NT_AUXV, auxv, auxv_len);
>>       xfree (auxv);
>>     }
>>
>>
>> so with a 64-bit gdb, that'll always end up with 64-bit layout...
>>
>> If the kernel does 64-bit -> 32-bit translation when generating
>> cores there (I can't imagine otherwise, but who knows), that too
>> argues for GDB doing that (i.e., translate at TARGET_OBJECT_AUXV
>> time) on the Solaris port.
>>
>>> Given the contraints, we'll probably have to live with with having
>>> both the target_ops and the gdbarch methods.  I thought about this a
>>> little bit more yesterday and it seems that we want to move to the
>>> situation where we try things in the following order:
>>>
>>> 1. The target_ops method if it has been set.
>>>
>>> 2. The gdbarch method if it has been set.
>>>
>>> 3. default_auxv_parse().
>>>
>>> Targets that always see the auxv entries in the "native" format like
>>> OpenBSD would only set the gdbarch method.  Targets that fetch entries
>>> from /proc in a format that doesn't necessary match the bitness of the
>>> binary that's running (Linux, Solaris) would set the target_ops
>>> method.  
>>
>> The Linux/PPC issue is not that /proc's format doesn't match
>> the bitness of the binary.  It's that the auxv needs to be
>> parsed _before_ the core of GDB even knows the target's
>> architecture, exactly while trying to figure out the
>> architecture of the program, as Ulrich said:
>>
>>> However, there are some scenarios where determining the wordsize
>>> actually matters (e.g. because the exec file cannot be determined).
>>> In those cases, the attempts in ppc_linux_read_description would be
>>> somewhat futile ...
>>
>> I.e., e.g., no binary at all.   A bit of chicken and egg.
>> But, that issue can in principle be hidden from core GDB, by
>> making auxv parsing done by the target backend not go through
>> GDB core auvx parsing at all.
>>
>>> Solaris would probably need to set the gdbarch method as well
>>> to avoid using default_auxv_parse() which doesn't do the right thing
>>> for SPARC.
>>
>>>
>>> My diff currently has the order of 1 and 2 reversed.  But I think I
>>> can just switch those around.
>>
>> I believe so.  I'm trying to figure out whether we actually need
>> auxv parsing on the target vector at all, and setting up direction
>> for the future.  Seems very much like we don't, though I'm curious
>> on the Solaris cores issue.
> 
> Well, the target delegation reworking made the issue moot, as I can't
> change the order anymore.  I think that points out a bit of a problem
> with that change, but as it doesn't matter for OpenBSD, I just added
> the gdbarch method in front.

I think we'd just need to make default_auxv_parse _not_ be
the default to_auxv_parse method, and call it at the end of
target_auxv_parse instead.

/* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
   Return 0 if *READPTR is already at the end of the buffer.
   Return -1 if there is insufficient buffer for a whole entry.
   Return 1 if an entry was read into *TYPEP and *VALP.  */
int
target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
                  gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
{
  struct gdbarch *gdbarch = target_gdbarch();

  res = current_target.to_auxv_parse (&current_target, readptr, endptr,
				       typep, valp);
  if (res == ...)
    return res;
  else if (res == not implemented or some such && gdbarch_auxv_parse_p (gdbarch))
    return gdbarch_auxv_parse (gdbarch, readptr, endptr, typep, valp);
  else
    return default_auxv_parse (...);
}

Anyway, something that can be handled later on.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-02-27 13:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-04 14:42 [PATCH/RFC] Parsing auxv entries Mark Kettenis
2014-02-06 19:03 ` Pedro Alves
2014-02-06 21:33   ` Mark Kettenis
2014-02-10 16:51     ` Pedro Alves
2014-02-27 13:00       ` Mark Kettenis
2014-02-27 13:17         ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox