From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14925 invoked by alias); 2 Jul 2003 00:06:48 -0000 Mailing-List: contact gdb-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sources.redhat.com Received: (qmail 14916 invoked from network); 2 Jul 2003 00:06:47 -0000 Received: from unknown (HELO zenia.home) (12.223.225.216) by sources.redhat.com with SMTP; 2 Jul 2003 00:06:47 -0000 Received: by zenia.home (Postfix, from userid 5433) id 144DE202BC; Tue, 1 Jul 2003 19:06:28 -0500 (EST) To: Andrew Cagney Cc: gdb@sources.redhat.com Subject: Re: IBM S/390 prologue analysis revisited References: <3F00DC8C.5040908@redhat.com> <3F017E6B.90003@redhat.com> From: Jim Blandy Date: Wed, 02 Jul 2003 00:06:00 -0000 In-Reply-To: <3F017E6B.90003@redhat.com> Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-07/txt/msg00029.txt.bz2 Andrew Cagney writes: > > You mean: [just for the record]: new prologue analyzer for S/390 > > http://sources.redhat.com/ml/gdb-patches/2003-04/msg00352.html > > One PS, > > Since this was posted (but you'd declined to commit) I added > trad-frame.[hc]. This provides functionality that overlaps what is > found in the s390 patch (it's slightly more compact). > > > /* A traditional saved regs table, indexed by REGNUM, encoding where > > the value of REGNUM for the previous frame can be found in this > > frame. > > The table is initialized with an identity encoding (ADDR == -1, > > REALREG == REGNUM) indicating that the value of REGNUM in the > > previous frame can be found in register REGNUM (== REALREG) in this > > frame. > > The initial encoding can then be changed: > > Modify ADDR (REALREG >= 0, ADDR != -1) to indicate that the value > > of register REGNUM in the previous frame can be found in memory at > > ADDR in this frame (addr_p, !realreg_p, !value_p). > > Modify REALREG (REALREG >= 0, ADDR == -1) to indicate that the > > value of register REGNUM in the previous frame is found in register > > REALREG in this frame (!addr_p, realreg_p, !value_p). > > Call trad_frame_register_value (REALREG == -1) to indicate that > > the > > value of register REGNUM in the previous frame is found in ADDR > > (!addr_p, !realreg_p, value_p). */ > > Editor note: It's missing the undefined state. I'll add it. I'd say that 'struct trad_frame_saved_reg' and 'struct prologue_value' are inverses of each other. They represent information at different steps in the process: - First you interpret your prologue to get a bunch of prologue values. - Then you use those to compute a set of trad_frame_saved_reg values. - Finally, those are what you'd use to find registers. Let me explain what I mean. The S/390 prologue analyzer creates a table of registers' current values, expressed as simple expressions: - "unknown", - "the constant K", or - "the original value of register R plus the constant K" To build this info, you just "interpret" the prologue, starting at the entry point, using prologue values instead of actual integers. Here's the code for the S/390 "add register" instruction when it appears in a prologue: ... /* AR r1, r2 -- add register */ else if (is_rr (insn, op_ar, &r1, &r2)) pv_add (&gpr[r1], &gpr[r1], &gpr[r2]); ... That is, you just "add" the current values of r1 and r2, and store the "result" in r1. (The "pv_*" functions do addition, subtraction, etc. on prologue values, returning "unknown" whenever the answer can't be expressed in one of the forms above.) When you stop, you've got the information you need to unwind: a description of the machine's resultant state after running the prologue. So, suppose your prologue moves the SP into the FP, and then subtracts 100 from the SP. In that case, the S/390 prologue analyzer will end up with the following "values" in those registers: SP: "the original value of SP plus the constant -100" FP: "the original value of SP plus the constant 0" Given this it's easy to find the original SP, the frame size, and so on. But here's what's cool: suppose your prologue is actually: - save the SP in the FP - move the constant "-100" into register R4 - subtract R4 from SP That extra step, going through register R4, would break a traditional prologue analyzer, even though it's equivalent to the original sequence (as far as SP and FP are concerned), unless you add special code to recognize that maneuver. But the S/390 prologue analyzer handles this just fine, with no special cases, producing a final state of: R4: "the constant -100" SP: "the original value of SP plus the constant -100" FP: "the original value of SP plus the constant 0" So you still get the information you wanted. This is the point where trad_frame_saved_reg comes in: that final state information there is not exactly what you need for register unwinding. To find the original SP, say, you need to search the register set for a register whose current value is "the original value of SP plus the constant Q". In the above case, we could recover the original SP from either the current SP or the current FP. (The FP is a little easier, but if you make sure you can handle either case, then you've got support for FP-less functions, too.) But if you simply make a pass over the entire register set, and record where one can find the original values of registers, then you've produced a complete set of 'struct trad_frame_saved_reg' values in one pass. So as things stand, prologue values and trad_frame_saved_reg structures are inverses of each other: they play different roles. A trad_frame_saved_reg points to one of the values your prologue "interpreter" tracks: a register, stack slot, or whatever.