|
From: Ayodele T. <em...@st...> - 2003-10-03 04:47:48
|
> > I am new to Valgrind and am trying to develop a new skin. In trying to > understand how information is managed in Valgrind, I have some confusion > as to how TempRegs are used and how arguments are passed to > instrumentation functions. > > > For example, look at the following code. > > op = newTemp(cb); > uInstr2(cb, MOV, 4, Literal, 0, TempReg, op); > uLiteral(cb, orig_addr); > uInstr1(cb, CCALL, 0, TempReg, op); > uCCall(cb, (Addr) & get_load_address, 1, 1, False); > > What I expect is happening in this code is: > > * uInstr2(...MOV ...) is copying the literal 0 into the TempReg pointed at by op. > > * uLiteral(...) is copying the value of the orig_addr into the TempReg > that is indicated by op > > * uInstr1(...CCALL...) is setting up the argument (register pointed to > by "op") to be sent with the CCALL > > * uCCall(...) is instrumenting the code > > What I expect to happen when the app is running is that the function > "get_load_address" will have as its argument the value that was in > the TempReg pointed at by op which would be the value of "orig_addr". But > that does not appear to be the case. > > I think I am missing something fundamental about how this should work. > If anyone can explain, it would be appreciated. > > Ayo |
|
From: Nicholas N. <nj...@ca...> - 2003-10-08 21:18:36
|
On Thu, 2 Oct 2003, Ayodele Thomas wrote: > > op = newTemp(cb); > > uInstr2(cb, MOV, 4, Literal, 0, TempReg, op); > > uLiteral(cb, orig_addr); > > uInstr1(cb, CCALL, 0, TempReg, op); > > uCCall(cb, (Addr) & get_load_address, 1, 1, False); > > > > What I expect is happening in this code is: > > > > * uInstr2(...MOV ...) is copying the literal 0 into the TempReg pointed at by op. > > > > * uLiteral(...) is copying the value of the orig_addr into the TempReg > > that is indicated by op > > > > * uInstr1(...CCALL...) is setting up the argument (register pointed to > > by "op") to be sent with the CCALL > > > > * uCCall(...) is instrumenting the code It's a little bit confusing, in that the uLiteral() and uCCall() functions add extra information to a UInstr created by the previous line. In the uInstr2() and the uInstr1(), the 0 gets replaced by the subsequent line. It's like this because most of the time all the necessary information is put in by the uInstr<n>() function, but in some cases more is required. Look at the definitions of uInstr1(), uInstr2, uLiteral() and uCCall() for more info (and note that they are actually macro'd abbreviations for functions with longer names). Probably the best way to think about it is in terms of the UInstrs created, which will be: MOVL $orig_addr, t_op CCALL get_load_address(t_op) The --trace-codegen option can be extremely useful; use --trace-codegen=01100 to show the UCode before and after instrumentation. > > What I expect to happen when the app is running is that the function > > "get_load_address" will have as its argument the value that was in > > the TempReg pointed at by op which would be the value of "orig_addr". But > > that does not appear to be the case. One more source of confusion: Valgrind allows you to use the ((regparm(n)) attribute of GCC to pass args in registers, which can be a bit faster than on the stack. The 3rd arg of uCCall() indicates how many args the called function has, the 4th arg indicates how many of those args are passed in registers. (See the GCC info page for more info, under "C extensions", "Function attributes". I assume your function get_load_address() does not have a ((regparm(n))) attribute. What's happening currently is that Valgrind is passing the arg in a register (%eax), but the function is looking at the stack for its arg, and thus getting whatever random value is on the stack at the relevant position. Either change the 4th arg to uCCall() to a 0, or add __attribute__((regparm(1))) to the declaration for get_load_address(). I'd be interested to know what you plan your skin to do. Hope this helps. N |