From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1808 invoked by alias); 25 May 2002 00:24:15 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 1800 invoked from network); 25 May 2002 00:24:13 -0000 Received: from unknown (HELO zwingli.cygnus.com) (208.245.165.35) by sources.redhat.com with SMTP; 25 May 2002 00:24:13 -0000 Received: by zwingli.cygnus.com (Postfix, from userid 442) id 787075EA11; Fri, 24 May 2002 19:24:12 -0500 (EST) To: Michael Snyder Cc: gdb-patches@sources.redhat.com Subject: Re: Does anybody remember... References: <3CEEC758.2B52BB2A@redhat.com> From: Jim Blandy Date: Sat, 25 May 2002 10:54:00 -0000 In-Reply-To: <3CEEC758.2B52BB2A@redhat.com> Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2002-05/txt/msg00910.txt.bz2 Michael Snyder writes: > Does anybody remember a Harvard Architecture issue, wherein you did > something > like take the address of a function, which caused gdb to scrunch the > address > down into the target-pointer format and then re-expand it into the > unified-address > format, with possible loss of information in the process? > > I think Jim Blandy did something to prevent this from happening, > but it seems to have crept back in again. Here's what I think you're referring to, from values.c. The comment only talks about non-Harvard architectures, but `descriptors' are also used often in Harvard architectures to keep data and function pointers the same size even when the code space is much larger than the data space. /* Extract a value as a C pointer. Does not deallocate the value. Note that val's type may not actually be a pointer; value_as_long handles all the cases. */ CORE_ADDR value_as_address (struct value *val) { /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure whether we want this to be true eventually. */ #if 0 /* ADDR_BITS_REMOVE is wrong if we are being called for a non-address (e.g. argument to "signal", "info break", etc.), or for pointers to char, in which the low bits *are* significant. */ return ADDR_BITS_REMOVE (value_as_long (val)); #else /* There are several targets (IA-64, PowerPC, and others) which don't represent pointers to functions as simply the address of the function's entry point. For example, on the IA-64, a function pointer points to a two-word descriptor, generated by the linker, which contains the function's entry point, and the value the IA-64 "global pointer" register should have --- to support position-independent code. The linker generates descriptors only for those functions whose addresses are taken. On such targets, it's difficult for GDB to convert an arbitrary function address into a function pointer; it has to either find an existing descriptor for that function, or call malloc and build its own. On some targets, it is impossible for GDB to build a descriptor at all: the descriptor must contain a jump instruction; data memory cannot be executed; and code memory cannot be modified. Upon entry to this function, if VAL is a value of type `function' (that is, TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC), then VALUE_ADDRESS (val) is the address of the function. This is what you'll get if you evaluate an expression like `main'. The call to COERCE_ARRAY below actually does all the usual unary conversions, which includes converting values of type `function' to `pointer to function'. This is the challenging conversion discussed above. Then, `unpack_long' will convert that pointer back into an address. So, suppose the user types `disassemble foo' on an architecture with a strange function pointer representation, on which GDB cannot build its own descriptors, and suppose further that `foo' has no linker-built descriptor. The address->pointer conversion will signal an error and prevent the command from running, even though the next step would have been to convert the pointer directly back into the same address. The following shortcut avoids this whole mess. If VAL is a function, just return its address directly. */ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_METHOD) return VALUE_ADDRESS (val); COERCE_ARRAY (val);