From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9803 invoked by alias); 27 Feb 2014 13:17:27 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 9793 invoked by uid 89); 27 Feb 2014 13:17:27 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 27 Feb 2014 13:17:25 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s1RDHNVQ022627 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 27 Feb 2014 08:17:24 -0500 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s1RDHLkS014988; Thu, 27 Feb 2014 08:17:22 -0500 Message-ID: <530F3AE1.8010104@redhat.com> Date: Thu, 27 Feb 2014 13:17:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130625 Thunderbird/17.0.7 MIME-Version: 1.0 To: Mark Kettenis CC: gdb-patches@sourceware.org Subject: Re: [PATCH/RFC] Parsing auxv entries References: <201402041441.s14Efx91011969@glazunov.sibelius.xs4all.nl> <52F3DC99.8070209@redhat.com> <201402062133.s16LXBT7005594@glazunov.sibelius.xs4all.nl> <52F90372.3040207@redhat.com> <201402271300.s1RD0YhN021204@glazunov.sibelius.xs4all.nl> In-Reply-To: <201402271300.s1RD0YhN021204@glazunov.sibelius.xs4all.nl> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-SW-Source: 2014-02/txt/msg00823.txt.bz2 On 02/27/2014 01:00 PM, Mark Kettenis wrote: >> Date: Mon, 10 Feb 2014 16:50:58 +0000 >> From: Pedro Alves >> >> On 02/06/2014 09:33 PM, Mark Kettenis wrote: >>>> Date: Thu, 06 Feb 2014 19:03:53 +0000 >>>> From: Pedro Alves >>>> >>>> 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 (¤t_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 (¤t_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