Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!ucbvax!hplabs!hpfcso!jmn From: jmn@hpfcso.HP.COM (John Newman) Newsgroups: comp.sys.hp Subject: Re: HP-UX s800 xdb question Message-ID: <7370014@hpfcso.HP.COM> Date: 13 Oct 89 20:47:12 GMT References: <1728@zen.co.uk> Organization: Hewlett-Packard, Fort Collins, CO, USA Lines: 111 Greetings: > xdb(1) takes a *long* time single-stepping the return of a large > structure. Here is the example program I sent to our Customer Response > Centre (instructions start in main's comment block): > > ... > foo() > { > struct big a; /* uninitialised, but who cares? */ > ... > return a; > } > > My question is simply: why does this happen? Here we have an example of what it means to debug on a RISC machine :-) The single statement return a; when viewed in disassembly mode (using xdb's "td" command), looks like this: 0x0000085c foo +0004 LDO -1076(30),1 0x00000860 foo +0008 OR 28,0,31 0x00000864 foo +000c LDO 1028(1),19 0x00000868 foo +0010 LDWS,MA 4(0,1),20 0x0000086c foo +0014 COMBF,<= 19,1,foo+0010 0x00000870 foo +0018 STWS,MA 20,4(0,31) For those of us who don't speak PA-RISC fluently, it translates to something like this (I've taken some liberties here for the sake of clarity): R1 <- address_of('a') R31 <- contents(R28) # R28 is pre-set return-value pointer R19 <- address_of('a') + sizeof('a') loop: R20 <- memory[contents(R1)], R1 += 4 memory[contents(R31)] <- R20, R31 += 4 if (R1 <= R19) goto loop goto contents(R2) # R2 contains return address The structure is being copied to the caller's stack-frame one word (4 bytes) at a time. This means that the 3 instruction loop gets executed 256 times. When in single-step mode, there is a considerable amount of context-switching overhead, and the debugger actually single-steps at the *instruction* level. So for this one C statement, the debugger is actually single-stepping the process thru approx. 770 instructions, one at a time, with control passing back and forth between the debugger and the child for each instruction executed. This takes enough time as to be noticible to the user. Being a RISC machine, there is no "blockmove" instruction, so I guess you could call this an architectural limitation (feature). > And is there a tweak I can apply *now* to get rid of it? ;-) If you must single-stepping thru a return statment that returns a large structure, no there isn't. As a workaround, there's a couple of things you could do: 1. Upon reaching the return statement, use the "bu" command to set an uplevel breakpoint (which wil be at the 1st instruction following the return), and continue ("c") to it. This takes the debugger out of single-step mode, and all 770 instructions execute at full speed, all at once. -or- 2. Return a pointer to the structure, rather than the entire structure. This means the return statement effectively compiles into 2 (two) instructions, which are stepped thru quickly and easily. BTW, Frank, we have seen the SR you filed concerning this, to be appearing in a Software Status Bulletin (SSB) near you soon. Unfortunately, because of the process overhead inherent in using single-step mode, and because such a large amount of data must be moved with this sort of return statement, there really isn't a "fix" possible (not on a RISC architecture, anyway). > [By the way, why are the "Procedures:" and "Files:" counts presented on > xdb entry both one too large under 3.1? (They were the *same number* > under 3.01, so at least that got fixed :-).) Are they counting > the startup module that gets linked in? Whyever (sp!) they are too large, > is it documented? Just curious.] When debuggable programs are linked, there is an extra object file that is added: on the s800, it's named /usr/lib/xdbend.o. This file contains a single subroutine _end_(), which is used for controlled returns from command-line procedure calls, and a data buffer __buffer[], which is used for storing character data in the user's address space when a string assigment, or a cmd-line procedure call with string arguments, is made. Inclusion of this file (which is itself debuggable) increases both the "Procedures:" and "Files:" counts both by 1. I don't think this is clearly documented anywhere. I believe it should be, and will endeavor to make it so. > Frank Wales, Systems Manager > Zengrange Ltd. John Newman Hewlett-Packard, Colorado Language Lab Symbolic Debuggers jmn%hpfcrt@hplabs.HP.COM CMA: All opinions expressed are strictly my own.