How to catch array index(es) on custom variant - delphi

I'm reading about TCustomVariantType and would like to know if there's a way to override the behaviour when a variable of the custom variant type gets called with one or more array indexes. If I do a quick debug with the debug DCU's on a[1] where a is a variant, I see _VarArrayGet gets called, but it funnels to a call to SafeArrayPtrOfIndex or SafeArrayGetElement, without a way to provide an alternative. I see older versions used to have a VariantManager, but this is deprecated. Is there a way to replace the _VarArrayGet pointer?

How is the system wired up so that a[x] ends up as a call to VarArrayGet(a,[x])?
The compiler in modern versions of Delphi has built in knowledge of variants and hard-wires the call to VarArrayGet. Look at the code the x86 compiler emits:
d := V[0];
is translated into:
004234D7 6A00 push $00
004234D9 6A01 push $01
004234DB 6858AF4200 push $0042af58
004234E0 8D45C8 lea eax,[ebp-$38]
004234E3 50 push eax
004234E4 E81BD8FFFF call #VarArrayGet
004234E9 83C410 add esp,$10
004234EC 8D45C8 lea eax,[ebp-$38]
004234EF E864B8FFFF call #VarToReal
004234F4 DD1D68AF4200 fstp qword ptr [$0042af68]
004234FA 9B wait
There is simply no extension point available to you.
Your best option if you wish to change the behaviour is to use a runtime code detour.

Related

Beaglebone Black JTag segger

I'm working on bare metal Programming on the Beaglebone Black with a Segger J-link under Ubuntu linux with the arm-none-eabi toolchain.
So now i get every time the error No source aviailable for "0x...."
When I pause the bone I get following in the Disassembly:
b6e93ce1: inc %ebx
b6e93ce2: fdivl -0x4922eb40(%esi)
b6e93ce8: call 0xdfa019f7
b6e93ced: add %ch,%bl
b6e93cef: mov $0x50,%dh
b6e93cf1: add $0xdd,%al
b6e93cf3: mov $0xa4,%dh
b6e93cf5: or %ebp,%ebx
b6e93cf7: mov $0xcc,%dh
b6e93cf9: inc %eax
b6e93cfa: fnsave -0x4922bf2c(%esi)
b6e93d00: add %al,(%eax)
b6e93d02: add %al,(%eax)
b6e93d04: add %al,(%eax)
b6e93d06: add %al,(%eax)
b6e93d08: js 0xb6e93d4c
b6e93d0a: fnsave -0x4922bb54(%esi)
b6e93d10: xor $0x42,%al
b6e93d12: fnsave -0x4922cfc0(%esi)
b6e93d18: mov $0x42,%ah
b6e93d1a: fnsave -0x4922cf98(%esi)
b6e93d20: cmp $0x31,%al
b6e93d22: fnsave -0x4922b92c(%esi)
b6e93d28: xorb $0xdd,(%edx)
b6e93d2b: mov $0xe0,%dh
b6e93d2d: xor %ebx,%ebp
b6e93d2f: mov $0xf0,%dh
When I start debugging the programm the J-Link restarts the bone correct but then the linux starts and not my Programm.
You may have several problems here, but the most severe is that you are using a version of gdb targeted for Intel processors: ebx, esi and friends are Intel 32 bits registers.
You have to use arm-none-eabi-gdb, not the gdb that comes with Ubuntu.
An easy way to avoid confusion is to explicitly use arm-none-eabi-gcc, arm-none-eabi-as, arm-none-eabi-ld and friends in your scripts and make files.
J-Links comes with a gdb-server software that acts as an intermediary between GDB and the JTAG hardware. Once the gdb-server is running, you can start a debugging session, assuming you are using a version of GDB debugger that matches your target processor.
This is obviously not your case, since your disassembled code looks pretty much like x86 assembly language code. This makes me think you are using a GDB executable compiled for an x86 target. You therefore really do need to get a version of GDB compiled for use with ARM targets.
You will find a version suitable to your needs in the bin directory of a Linaro toolchain, either for Windows or Linux. Its name will be arm-none-eabi-gdb.exe (Windows) or arm-none-eabi-gdb (Linux).

qemu memory operations

I intend to use Qemu to generate a memory trace for the execution of a x86 guest operating system.
According to tcg wiki page, Qemu uses a handful of helpers to generate load/stores to the target(guest) memory.
This list of instructions is tcg_gen_qemu_ld8s/u, tcg_gen_qemu_ld16s/u, tcg_gen_qemu_ld32s/u, tcg_gen_qemu_ld64. (We have a similar set for store instructions).
I am trapping all calls to the above functions in the target-i386/translate.c file
However, I am still missing load/stores of certain instructions like
cmp ecx, [r12+0x4]
mov r10b, [r13+0x0]
mov byte [rax+0xf0000], 0x0
mov byte [rax+rdx], 0x0
Questions :
Can someone please point to other load/store points (direct or indirect) that I am missing ??
Does qemu provide a single entry point function for accesses to guest memory (like guest_read()) which can be instrumented for tracing all loads from the guest memory ???
Can somebody please point to a good documentation where I can understand how qemu maintains the state of the guest memory ??
Sorry friends for the misleading instructions in the previous mail.
cmp ecx, [r12+0x4]
mov r10b, [r13+0x0]
mov byte [rax+0xf0000], 0x0
mov byte [rax+rdx], 0x0
It seems all the above instructions are getting covered with the tcg_gen_ld/st helpers.
But now I have stumbled upon another problem :
I initially thought that all the interactions with the guest memory happen through the helper instructions in the translate.c file.
However, I found that the helper functions for some instructions like cmpxcgh8b and cmpxchg16b are actually accessing guest memory.
So, does it mean there are more than one entry points for reading guest memory.
Can some one please explain how are the ldq and stq instructions translated to access the guest memory ??
The other functions that load data are called cpu_ld*_data and cpu_st*_data, or cpu_ld*_data_ra and cpu_st*_data_ra. The _ra version have an additional argument, which is the address of the caller in the generated code. It is used to compute the address of the faulting instruction in case the load or store generates a page fault.
For example, grepping for cmpxchg8b gives
target/i386/mem_helper.c:void helper_cmpxchg8b(CPUX86State *env, target_ulong a0)
and inside that function:
uintptr_t ra = GETPC();
...
oldv = cpu_ldq_data_ra(env, a0, ra);
newv = (cmpv == oldv ? newv : oldv);
/* always do the store */
cpu_stq_data_ra(env, a0, newv, ra);

Debugging code in Delphi XE

I am a long time Delphi dev and in the past I use a third party tool for logging and debugging while developing (called Smart Inspect) however now that I've upgraded to Delphi XE I want to try and use the IDE for debugging.
My question is, given a function like
procedure MyFunction;
var
str : string;
begin
str := 'Foo';
//Debug, show value of str?
str := AnotherFunction(str);
//Debug, show value of str?
end;
how can I debug and get the value of str, without doing stupid things like
showmessage(str);
if there is a video somewhere (or article) then I am more than happy to read.
Is there a way to watch/output the value of variables.
If you want to use the IDE Debugger only, then do the following:
put a breakpoint somewhere
right click on the breakpointr circle and choose "Breakpoint Properties ..."
press "Advanced" button to show more options
uncheck "Break" checkbox
then use "Log message" and "Eval expression" edit boxes to enter trace values
Such messages will be send to "Event Log" debugger pane. Right click on the pane and choose "Properties". There you can filter ("Messages") / hilight ("Colors") the trace messages as you whish.
Well, Delphi XE comes with CodeSite logging, but I get the feeling you're talking about the debugger itself.
If you place a breakpoint in a routine, it will break to the debugger when it hits it. From there, you've got a Local Variables pane and a Watches pane along the left side of the IDE. Local Variables will show the value of all locals, and Watches lets you set up expressions whose value it will keep track of.
You can also get something similar to a watch, but with more detailed information (especially for structured types such as objects) by using Inspect (Alt-F5). Also, the Evaluate/Modify (Ctrl-F7) will allow you to type in expressions and evaluate them. It's not quite as detailed as Inspect, but it gives you a lot more flexibility.
If you familiarize yourself with these tools, you'll find debugging much easier.
1) You can use OutputDebugString Function to output string to debug window
2) You can use CodeSite Express. I recommend video from CodeRage 5 as a starting point for using CodeSite
Other answers are all correct.
My personal favorite technique (same as the answer by da-soft) is to create a breakpoint, that logs a message to the event log, containing a value that I want logged, and does not actually "break" (that is, execution continues without you hitting the Run icon). Then every time that line of code is reached, I get my message, and my values in the log. Since I can go back and read the history, as well as see the current values, I find this more useful than merely using the debugger watch window.
But since Delphi XE includes CodeSite, you can go far beyond what expression evaluation in breakpoints does for you. Code Site however requires that you modify your code to add some logging. But it's much better than a message box.
You can also use OutputDebugString(PChar(s)) to output any string to the debugger. Since this can contain whatever you want, it's a very nice way to debug but not show stuff to the end user.
In many of my applications, I have a special trace buffer, which is circular (that is, it keeps only the last 500 or so lines). When ever I see a problem, not only do I get a stack traceback, I also save that in-memory trace log, so I have some history on what was going on just before my problem.
You can also check out the Log 4 Delphi project.
I prefer debugger hints. After breaking to the debugger move your mouse to the "str" anywhere in your code and you will see its current value. Also you can highlight some statement by a mouse and evaluate it. For example highlight "AnotherFunction(str)" and place your mouse over it.
Nothing wrong with any of the other answers but I just wanted to add these useful functions.
procedure DebugString ( const s : string ) ; overload ;
begin
{$IFDEF DEBUG}
OutputDebugString ( PChar ( s ) ) ;
{$ENDIF}
end ;
procedure DebugString ( const s : string ; args : array of const ) ; overload ;
begin
{$IFDEF DEBUG}
OutputDebugString ( PChar ( Format ( s , args ) ) ) ;
{$ENDIF}
end ;

Calling Delphi DLL crashes VB6 exe with "Run-time error '-2147418113 (8000ffff)' Method '~' of object '~' failed", but only on some machines!

I have searched for hours but could not find anything similar.
The crash has two flavors; one is with "Run-time error '-2147418113 (8000ffff)' Method '~' of object '~' failed" and the second flavor is a total crash where Windows asks if I want to report this to Microsoft. In the second case I chose to debug once and it showed "Unhandled exception in App.exe (OLEAUT32.DLL): 0xC0000005: Access violation."
The Disassembly screen showed the yellow pointer at top line of:
>> 771148A4 mov ecx, dword ptr [esi]
771148A6 add ecx, 15h
771148A9 and ecx, 0FFFFFFF0h
771148AC push ecx
771148AD push esi
...
The problem occurs when calling a particular essential function in a third-party Delphi DLL, but I cannot declare outright that the DLL is buggy because this happens only in the program executables I compile. This same dll is used in hundreds of other customers and (at least for now) I am the only one running into this problem. The same source code compiled in the customer's PC, or the 3rd party supplier's office works fine.
So the problem boils down to this: VB6 with SP6 produces different binary exe files from the exact same source code. The one compiled on my pc works fine in my pc, and a clean virtual pc I installed to check this, but does not work anywhere it should; and the one compiled in the customer or the 3rd party supplier works fine everywhere except my pc.
It is unlike the problem Boost describes (see this link) since both the IDE and the compiled application behave in the same manner on all machines. They either work fine or break terribly.
Public mXApp As XObjects.XApplication
Public Sub Main
On Error Resume Next
Set mXApp = New XObjects.XApplication
If Err.Number = 0 Then
MsgBox "Found: " & mXApp.Version & vbCrLf & mXApp.GetAppPath
Else
MsgBox "XApp DLL not found. " & Err.Number & ": " & Err.Description
End If
Err.Clear
End Sub
Public Sub Login(Byval uid As String, Byval pwd As String, Byval companyNr as Long)
Dim ok as Boolean
ok = mXApp.Login(uid, pwd, companyNr)' >> CRASH! Program never gets to the next line.'
If ok Then
MsgBox "Login success"
Else
MsgBox "Login fails"
End If
End Sub
Note that after the mXApp object is created, two function calls are done -namely Version and GetAppPath- without any problem. The crash occurs in the Login call. VB IDE Object browser displays the definitions of the three functions as:
Function Version() As String
Function GetAppPath() As String
Function Login(UserName As String, Password As String, FirmNr As Long) As Boolean
Does anyone have any solutions or (equally usefully) ways that I can make the supplier reproduce this problem in their own machines?
Well, it's hard to say for sure without being able to see the Delphi side of it, but when you get problems like this in DLL calls, there are two standard things to check first.
First, make sure the DLL function and the import header for it in the VB program are using the same calling convention. If VB is putting the paramters in one place and the Delphi DLL is looking for them somewhere else, you get undefined behavior.
Second, make sure you're using the same string type on both sides. If this is COM, your string type should be the COM BSTR type, known as WideString in Delphi. Not sure what VB calls it. If you're passing the DLL a different string type than it's expecting to receive, it'll get corrupt data.
Double-check these two things and see if that doesn't fix it.
Problem Solved! Mason was quite right when telling me to double-check:
...make sure the DLL function and the
import header for it in the VB program
are using the same calling convention.
If VB is putting the paramters in one
place and the Delphi DLL is looking
for them somewhere else, you get
undefined behavior.
The DLL on my pc and the one in the customer were slightly different builds all along. And I had assumed that they had exactly the same interface. But wait before thinking I was careless; I did not just assume this, I had compiled two different executables after registering both versions of the DLL long before posting my question here.
When I thought I had tried the second dll, I was mistaken. I had registered the dll version 1.1 on my pc. The Object Viewer showed the declarations in the question. I compiled the executable and tested. And then without exiting the IDE, I registered the dll version 1.2 and compiled again assuming that the VB compiler would read the dll interface during compilation. Well this assumption was wrong. It turns out that the IDE had to be restarted.
Problem was solved after the supplier of the dll told me there was an optional new parameter, but they did not mention it earlier assuming this would not be problem since it was optional.
Below is the difference that caused the crashes:
Function Login(UserName As String, Password As String, FirmNr As Long, [PeriodNr As Long]) As Boolean
Make sure you're loading the right DLL. Process Explorer from SysInternals will show you the DLLs being used by any app (configure it to show DLLs in the lower pane). Maybe you're loading a different version of the DLL, unknowingly.
You can run it directly here:
http://live.sysinternals.com/ click on procexp.exe

When is space allocated for local variables?

Example
function Test: Boolean;
var
a, b, c: Integer;
begin
...
end;
When a program containing such code is executed, are a, b, and c allocated each time Test is called, or are they allocated only once somewhere in the initialization phase of the execution? I ask this because such an information is not available in the debugger.
Local variables are created in the stack, after the call to the function. They are removed by the called function by default when the function returns.
Here is a more exact version.
Local variables are allocated:
Usually on the stack;
In registers if the optimizer can use it: for instance, a simple method with just a loop and a var i: integer declared as local variable will likely allocate i as a CPU register, for better speed.
How is stack allocated?
On both x86 and x64 scheme, the compiler has the same process:
It first computes all the space needed, at compile time;
It generates code to reserve this space on the stack (e.g. a MOV EBP,ESP; SUB ESP,16);
It generates code to initialize reference-counted variables allocated on the stack (e.g. string) - other kind of variables (like integer) have no default value, and can be any random content which is on the stack;
It generates an hidden try..finally block if there are some reference-counted variables;
It generates the code for the internal of the function/method;
Now here the finally part of the function/method: it generates code to free all reference-counted variables;
It generates code to release the space on the stack (e.g. an MOV ESP,EBP);
It generates code to return to the caller function.
Most of the time, a "stack frame" (pointed by register EBP) is created: it is used to access directly all the variables allocated on the stack.
There is a specific handling of the result variable of a function: sometimes, it is a CPU/FPU register, sometimes, it is a variable initialized by the caller, and passed as an additional parameter.
On x64, it is a bit more complicated, since exceptions are not handled the same, and all registers need to have some space allocated on the stack, if there is an inner call.
On Mac OS, there are some alignment issues.
All this stack allocation / initialization process is the reason why for some small functions/methods, declaring them inline will make the code faster to execute: all this stack handling is sometimes slow, if the process within the function is very simple.
For more details, see the official Delphi documentation.

Resources