How to analyze crash in printer driver from dump - callstack

I am trying to find the cause of an access violation using Konica Minolta PCL driver from a memory dump. I will try to provide as much info as needed. Maybe others in similar situations will benefit from this.
The software I am investegating is a combination of unmanaged windows written in Delphi 2007 hosting .net components via COM. Other crash dumps indicate possible connections with errors in setting floating point exceptions http://connect.microsoft.com/VisualStudio/feedback/details/535285/using-events-on-interop-assemblies-causes-system-stackoverflowexception#details, and I am trying to determine if there are any similarities.
A dump is created caused by a second chance exception: KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+36778 in C:\Windows\System32\spool\drivers\w32x86\3\KOAZ8J_O.DLL has caused an access violation exception (0xC0000005) when trying to read from memory location 0x1906ef0c on thread 16.
Loading up Windbg I find this call stack:
0:016> kL
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may be wrong.
253efdcc 22958881 KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36778
253efe1c 2294eff5 KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36819
253efe28 22976dde KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x2cf8d
253efe68 22976e85 KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x54d76
253efe90 7795f731 KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x54e1d
253eff34 7795f632 ntdll!LdrShutdownThread+0xe6
253eff44 75c576f5 ntdll!RtlExitUserThread+0x2a
253eff58 774c03c0 KERNELBASE!FreeLibraryAndExitThread+0x5f
253eff68 5e59367e kernel32!FreeLibraryAndExitThreadStub+0x10
253eff88 774ced6c +0x23367e
253eff94 7799377b kernel32!BaseThreadInitThunk+0xe
253effd4 7799374e ntdll!__RtlUserThreadStart+0x70
253effec 00000000 ntdll!_RtlUserThreadStart+0x1b
I do not have symbols for the printer drivers and by the offset on the last known function name I suspect the offending function is a completely different one.
0:016> r
eax=22920000 ebx=00000001 ecx=1906ef00 edx=22a01000 esi=24e42ff0 edi=229e6598
eip=229587e0 esp=253efdbc ebp=253efdcc iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36778:
229587e0 3944d904 cmp dword ptr [ecx+ebx*8+4],eax ds:0023:1906ef0c=????????
0:016> db ecx+ebx*8+4
1906ef0c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
1906ef1c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
1906ef2c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
1906ef3c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
1906ef4c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
1906ef5c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
1906ef6c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
1906ef7c ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
0:016> uf 229587e0
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3676e:
229587d6 8b450c mov eax,dword ptr [ebp+0Ch]
229587d9 85c0 test eax,eax
229587db 7418 je KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3678d (229587f5)
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36775:
229587dd 8b4f10 mov ecx,dword ptr [edi+10h]
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36778:
229587e0 3944d904 cmp dword ptr [ecx+ebx*8+4],eax
229587e4 740f je KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3678d (229587f5)
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3677e:
229587e6 8b460c mov eax,dword ptr [esi+0Ch]
229587e9 833c9800 cmp dword ptr [eax+ebx*4],0
229587ed 741d je KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x367a4 (2295880c)
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36787:
229587ef 8365fc00 and dword ptr [ebp-4],0
229587f3 eb17 jmp KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x367a4 (2295880c)
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3678d:
229587f5 8b460c mov eax,dword ptr [esi+0Ch]
229587f8 8b0c98 mov ecx,dword ptr [eax+ebx*4]
229587fb 85c9 test ecx,ecx
229587fd 7406 je KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3679d (22958805)
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36797:
229587ff 8b01 mov eax,dword ptr [ecx]
22958801 6a01 push 1
22958803 ff10 call dword ptr [eax]
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3679d:
22958805 8b460c mov eax,dword ptr [esi+0Ch]
22958808 83249800 and dword ptr [eax+ebx*4],0
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x367a4:
2295880c 43 inc ebx
2295880d 3b5e08 cmp ebx,dword ptr [esi+8]
22958810 7cc4 jl KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x3676e (229587d6)
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x367aa:
22958812 837dfc00 cmp dword ptr [ebp-4],0
22958816 7435 je KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x367e5 (2295884d)
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x367b0:
22958818 8d5f1c lea ebx,[edi+1Ch]
2295881b 53 push ebx
2295881c ff1544c19e22 call dword ptr [KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0xca0dc (229ec144)]
22958822 56 push esi
22958823 8d4f14 lea ecx,[edi+14h]
22958826 e80bfcffff call KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x363ce (22958436)
2295882b 53 push ebx
2295882c ff1548c19e22 call dword ptr [KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0xca0e0 (229ec148)]
22958832 ff760c push dword ptr [esi+0Ch]
22958835 ff1530c19e22 call dword ptr [KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0xca0c8 (229ec130)]
2295883b 8b06 mov eax,dword ptr [esi]
2295883d 6a01 push 1
2295883f 8bce mov ecx,esi
22958841 ff10 call dword ptr [eax]
22958843 6a00 push 0
22958845 ff37 push dword ptr [edi]
22958847 ff15c8bf9e22 call dword ptr [KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0xc9f60 (229ebfc8)]
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x367e5:
2295884d 5f pop edi
2295884e 5e pop esi
2295884f 5b pop ebx
22958850 c9 leave
22958851 c20800 ret 8
Is anybody able to spot any obvious errors in this assembly code? Why would it adress this invalid memory location. I am also looking for guidance as how to pinpoint the error further. My goal is to look for a workaround (so this code block is not run) and to supply the author of the driver with as much info as possible.

Got this assessment from Microsoft:
The problem was related to below printer driver which has bad DllMain
implementations.
Image path: C:\Windows\System32\spool\drivers\w32x86\3\KOAZ8J_O.DLL
Image name: KOAZ8J_O.DLL
Timestamp: Mon Nov 02 15:14:30 2009 (4AEE86D6)
CheckSum: 00000000
ImageSize: 000DE000
File version: 4.2.0.6
Product version: 4.2.0.6
File flags: 0 (Mask 3F)
File OS: 4 Unknown Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0000.04b0
ProductName: OpenAPIDrvLib Dynamic Link Library
InternalName: OAPIDrvLib42.dll
OriginalFilename: OAPIDrvLib42.dll
ProductVersion: 4.2.0.6
FileVersion: 4.2.0.6
FileDescription: OpenAPI Driver Library for Ver.4.2
LegalCopyright: Copyright (C) 2009 Konica Minolta Business Technologies, Inc. All rights reserved.
ChildEBP RetAddr
WARNING: Stack unwind information not available. Following frames may
be wrong.
00 2758fdcc 26ed8881
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36778
01 2758fe1c 26eceff5
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x36819
02 2758fe28 26ef6dde
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x2cf8d
03 2758fe68 26ef6e85
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x54d76
04 2758fe90 771af731
KOAZ8J_O!OAPIGetPrinterEncryptionSettingForDriver+0x54e1d
05 2758ff34 771af632 ntdll!LdrShutdownThread+0xe6
06 2758ff44 753b7695 ntdll!RtlExitUserThread+0x2a
07 2758ff58 766f0378 KERNELBASE!FreeLibraryAndExitThread+0x5f
08 2758ff68 51bb367e kernel32!FreeLibraryAndExitThreadStub+0x10
09 2758ff88 766fed6c +0x23367e
0a 2758ff94 771e377b kernel32!BaseThreadInitThunk+0xe
0b 2758ffd4 771e374e ntdll!__RtlUserThreadStart+0x70
0c 2758ffec 00000000 ntdll!_RtlUserThreadStart+0x1b
The loader tried to call entry point method (mostly DllMain) for
cleanup operations. Such module performed complicated tasks and
damaged the memory. We observed the similar issue from other cases on
this printer drivers.
You may try any printer driver or contact the printer driver vendor to
fix the problem.
With the above information, you can discuss with the printer driver
vendor to review their code in DllMain and check for failure
possibilities.
http://msdn.microsoft.com/en-us/library/ms682583(VS.85).aspx

Related

32-bit ADD on Aarch64 assembly

This is my first post here and I'm also kind of new to arm64 assembly, so I'm trying to do some arithmetic, but for example when I try to do an addition it seems to do it in 32-bit.
Here's my code:
.data
msg: .asciz "Value 1: "
msg2: .asciz "Value 2: "
result: .asciz "Result: %d\n"
fmt: .asciz "%d"
.balign 8
value1: .quad 0
.balign 8
value2: .quad 0
.balign 16
lr_value: .quad 0
.text
.global main
main:
adr x0, lr_value
str x30, [x0]
//Display message
adr x0,msg
bl printf
//Input first value
adr x0,fmt
adr x1,value1
bl scanf
//Display second message
adr x0,msg2
bl printf
//Input second value
adr x0,fmt
adr x1,value2
bl scanf
//Load first and second value
adr x1,value1
ldr x1,[x1]
adr x2,value2
ldr x2,[x2]
//Add both values on x1
add x1,x1,x2
//Show result
adr x0,result
bl printf
adr x0,lr_value
ldr x30,[x0]
mov w0,#0
ret
And here's the output:
Value 1: 2147483647
Value 2: 1
Result: -2147483648
What am I doing wrong? I've also tried multiplication and substraction
Edit: Solved it, turns out I had to use %ld instead of %d, thank you Nate Eldredge!

Nanopb + Azure MQTT not working on NodeMCU

I have been trying to encode a string using Nanopb library on NodeMCU and publish it using AzureMQTT.
On testing individually, both Nanopb and Azure work just fine. However, Integration of both in one sketch gives me errors.
void loop(){
uint8_t sMsg[512];
gestures data;
char *msg = "aaaaaaaaaaaaaaaaaaaaaaaaa";
strcpy(data.values,msg);
Serial.println("done with strcpy");
pb_ostream_t buffer = pb_ostream_from_buffer(sMsg, sizeof(sMsg));
if (!(pb_encode(&buffer, gestures_fields, &data))) {
Serial.println(F("Encoding failed"));
Serial.println(PB_GET_ERROR(&buffer));
return;
}
else
{
Serial.println("enterd else");
Serial.println((char*)sMsg);
client.run();
if (client.connected()) {
Serial.println("connected");
String payload = "{\"DeviceId\":\"" + String(DEVICE_ID) + "\", \"data\":" + (char*)sMsg + "}";
Serial.println(payload);
client.sendEvent(payload);
Serial.println("Published message!");
}
}
Serial.println("Done with loop");
}
The Serial output is as below:
entered if
done with strcpy
enterd else
aaaaaaaaaaaaaaaaaaaaaaaaa?z[#t/⸮?⸮⸮⸮?⸮⸮⸮?⸮⸮⸮?⸮+⸮?⸮⸮⸮?$⸮?
Done with loop
If observed, the client.connected() is returning false, hence, the message is not being published.
Also, sometimes, at client.run() there's a stack error:
Fatal exception 28(LoadProhibitedCause):
epc1=0x401016dc, epc2=0x00000000, epc3=0x00000000, excvaddr=0x02786a4c,
depc=0x00000000
Exception (28):
epc1=0x401016dc epc2=0x00000000 epc3=0x00000000 excvaddr=0x02786a4c
depc=0x00000000
ctx: sys
sp: 3ffffcf0 end: 3fffffb0 offset: 01a0
>>>stack>>>
3ffffe90: 3fff0010 3fff242c 00000000 40216af4
3ffffea0: 00000000 005e5dbc 40216b4b 3fff242c
3ffffeb0: 3fff2414 ffffffbc 00000000 ffffffff
3ffffec0: 02786a30 00000000 4020c087 00000026
3ffffed0: ffffffff 00000000 3ffeaf61 00000130
3ffffee0: 4020c0da 3fff2d2c 3ffef1cc 3ffef4cc
3ffffef0: 00000000 00000000 4010195b 3fff2d2c
3fffff00: 000000c0 00000000 00000064 3fff2d94
3fffff10: 4020b4e0 3fff2d2c 3fff2d6c 401070bc
3fffff20: 00000009 4021007c 3ffef848 40234b25
3fffff30: 3fff1f34 3fff1f30 005e5dcb 4010610e
3fffff40: 402164be 3ffee878 3ffee878 40234d6d
3fffff50: 401060f4 00000000 00000000 0000001c
3fffff60: 4021fdb4 3ffeffe8 0000001b 4021fdc1
3fffff70: 3ffef858 3fff0010 027982a2 60000600
3fffff80: 4021fe06 3fffdab0 00000000 3fffdcb0
3fffff90: 3fff0020 3fffdab0 00000000 40208993
3fffffa0: 40000f49 40000f49 3fffdab0 40000f49
<<<stack<<<
Decoding the stacktrace gives:
Exception 28: LoadProhibited: A load referenced a page mapped with an
attribute that does not permit loads
Decoding 22 results
0x401016dc: ppEnqueueRxq at ?? line ?
0x401016dc: ppEnqueueRxq at ?? line ?
0x40216af4: ieee80211_parse_wmeparams at ?? line ?
0x40216b4b: ieee80211_parse_wmeparams at ?? line ?
0x4020c087: pp_attach at ?? line ?
0x4020c0da: pp_attach at ?? line ?
0x4010195b: ppCalFrameTimes at ?? line ?
0x4020b4e0: ppCheckTxIdle at ?? line ?
0x401070bc: pvPortMalloc at
C:\Users\Violet\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/heap.c line 13
0x4021007c: ieee80211_getmgtframe at ?? line ?
0x40234b25: udp_input at
/Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/udp.c line 106
(discriminator 1)
0x4010610e: igmp_timer at
/Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/timers.c line
222
0x402164be: sta_input at ?? line ?
0x40234d6d: udp_bind at
/Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/udp.c line 787
0x401060f4: igmp_timer at
/Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/timers.c line 217
0x4021fdb4: system_get_os_print at ?? line ?
0x4021fdc1: system_pp_recycle_rx_pkt at ?? line ?
0x4021fe06: system_restart_hook at ?? line ?
0x40208993: std::_Function_base::_Base_manager ::_M_manager(std::_Any_data&,
std::_Any_data const&, std::_Manager_operation) at
c:\users\violet\documents\arduinodata\packages\esp8266\tools\xtensa-lx106-
elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional
line 1934
It seems you may be overflowing your stack, i.e. running out of space allocated for local variables. When either of the libraries run alone, there is enough space, but when combined it runs out.
A simple way to fix this would be to change this large variable to static allocation:
uint8_t sMsg[512]; // Allocated on stack area
static uint8_t sMsg[512]; // Allocated separately
What static does is that it reserves a section for the variable for the whole duration of the program, instead of trying to fit it in the small dynamic area of the stack.
It is also possible to increase the stack size. On Arduino ESP8266 SDK, this seems to be done by modifying CONT_STACKSIZE in cores/esp8266/cont.h.

Is 'as' just another way to express a type-annotation?

My understanding of Dart leads me to believe that this 'cast' should not affect run-time semantics, but just wanted to confirm:
(foo as Bar).fee();
(foo as Bar).fi();
(foo as Bar).fo();
Or is it "best practice" to cast once:
final bFoo = (foo as Bar);
bFoo.fee();
bFoo.fi();
bFoo.fo();
This is highly dependent on how the DartVM optimizer handles the case. Using the latest version of Dart I constructed two test functions:
void test1() {
Dynamic bar = makeAFoo();
for (int i = 0; i < 5000; i++) {
(bar as Foo).a();
(bar as Foo).b();
}
}
and
void test2() {
Dynamic bar = makeAFoo();
Foo f = bar as Foo;
for (int i = 0; i < 5000; i++) {
f.a();
f.b();
}
}
Looking at the optimized code for test1 you can see the loop looks like this:
00D09A3C bf813b9d00 mov edi,0x9d3b81 'instance of Class: SubtypeTestCache'
00D09A41 57 push edi
00D09A42 50 push eax
00D09A43 6811003400 push 0x340011
00D09A48 e8d36c83ff call 0x540720 [stub: Subtype1TestCache]
00D09A4D 58 pop eax
00D09A4E 58 pop eax
00D09A4F 5f pop edi
00D09A50 81f911003400 cmp ecx,0x340011
00D09A56 7411 jz 0xd09a69
00D09A58 81f9710f7c00 cmp ecx,0x7c0f71
00D09A5E 0f8437000000 jz 0xd09a9b
00D09A64 e900000000 jmp 0xd09a69
00D09A69 8b1424 mov edx,[esp]
00D09A6C 8b4c2404 mov ecx,[esp+0x4]
00D09A70 6811003400 push 0x340011
00D09A75 50 push eax
00D09A76 68b9229d00 push 0x9d22b9
00D09A7B 51 push ecx
00D09A7C 52 push edx
00D09A7D 6889289d00 push 0x9d2889
00D09A82 b8813b9d00 mov eax,0x9d3b81 'instance of Class: SubtypeTestCache'
00D09A87 50 push eax
00D09A88 b9b0d00b00 mov ecx,0xbd0b0
00D09A8D ba06000000 mov edx,0x6
00D09A92 e8896583ff call 0x540020 [stub: CallToRuntime]
00D09A97 83c418 add esp,0x18
00D09A9A 58 pop eax
00D09A9B 5a pop edx
00D09A9C 59 pop ecx
00D09A9D 50 push eax
00D09A9E a801 test al,0x1
00D09AA0 0f8450010000 jz 0xd09bf6
00D09AA6 0fb74801 movzx_w ecx,[eax+0x1]
00D09AAA 81f922020000 cmp ecx,0x222
00D09AB0 0f8540010000 jnz 0xd09bf6
00D09AB6 b9d1229d00 mov ecx,0x9d22d1 'Function 'a':.'
00D09ABB bae96ccb00 mov edx,0xcb6ce9 Array[1, 1, null]
00D09AC0 e82b6983ff call 0x5403f0 [stub: CallStaticFunction]
00D09AC5 83c404 add esp,0x4
00D09AC8 b911003400 mov ecx,0x340011
00D09ACD ba11003400 mov edx,0x340011
00D09AD2 8b45f4 mov eax,[ebp-0xc]
00D09AD5 51 push ecx
00D09AD6 52 push edx
00D09AD7 3d11003400 cmp eax, 0x340011
00D09ADC 0f849a000000 jz 0xd09b7c
00D09AE2 a801 test al,0x1
00D09AE4 7505 jnz 0xd09aeb
00D09AE6 e95f000000 jmp 0xd09b4a
00D09AEB 0fb74801 movzx_w ecx,[eax+0x1]
00D09AEF 81f922020000 cmp ecx,0x222
00D09AF5 0f8481000000 jz 0xd09b7c
00D09AFB 0fb77801 movzx_w edi,[eax+0x1]
00D09AFF 8b4e07 mov ecx,[esi+0x7]
00D09B02 8b891c100000 mov ecx,[ecx+0x101c]
00D09B08 8b0cb9 mov ecx,[ecx+edi*0x4]
00D09B0B 8b7927 mov edi,[ecx+0x27]
00D09B0E 8b7f03 mov edi,[edi+0x3]
00D09B11 81ff59229d00 cmp edi,0x9d2259
00D09B17 0f845f000000 jz 0xd09b7c
00D09B1D bfd13b9d00 mov edi,0x9d3bd1 'instance of Class: SubtypeTestCache'
00D09B22 57 push edi
00D09B23 50 push eax
00D09B24 6811003400 push 0x340011
00D09B29 e8f26b83ff call 0x540720 [stub: Subtype1TestCache]
00D09B2E 58 pop eax
00D09B2F 58 pop eax
00D09B30 5f pop edi
00D09B31 81f911003400 cmp ecx,0x340011
00D09B37 7411 jz 0xd09b4a
00D09B39 81f9710f7c00 cmp ecx,0x7c0f71
00D09B3F 0f8437000000 jz 0xd09b7c
00D09B45 e900000000 jmp 0xd09b4a
00D09B4A 8b1424 mov edx,[esp]
00D09B4D 8b4c2404 mov ecx,[esp+0x4]
00D09B51 6811003400 push 0x340011
00D09B56 50 push eax
00D09B57 68b9229d00 push 0x9d22b9
00D09B5C 51 push ecx
00D09B5D 52 push edx
00D09B5E 6889289d00 push 0x9d2889
00D09B63 b8d13b9d00 mov eax,0x9d3bd1 'instance of Class: SubtypeTestCache'
00D09B68 50 push eax
00D09B69 b9b0d00b00 mov ecx,0xbd0b0
00D09B6E ba06000000 mov edx,0x6
00D09B73 e8a86483ff call 0x540020 [stub: CallToRuntime]
00D09B78 83c418 add esp,0x18
00D09B7B 58 pop eax
00D09B7C 5a pop edx
00D09B7D 59 pop ecx
00D09B7E 50 push eax
00D09B7F a801 test al,0x1
00D09B81 0f8479000000 jz 0xd09c00
00D09B87 0fb74801 movzx_w ecx,[eax+0x1]
00D09B8B 81f922020000 cmp ecx,0x222
00D09B91 0f8569000000 jnz 0xd09c00
00D09B97 b961239d00 mov ecx,0x9d2361 'Function 'b':.'
00D09B9C bae96ccb00 mov edx,0xcb6ce9 Array[1, 1, null]
00D09BA1 e84a6883ff call 0x5403f0 [stub: CallStaticFunction]
00D09BA6 83c404 add esp,0x4
00D09BA9 8b4df8 mov ecx,[ebp-0x8]
00D09BAC 83c102 add ecx,0x2
00D09BAF 0f8055000000 jo 0xd09c0a
00D09BB5 89cf mov edi,ecx
00D09BB7 8b5df4 mov ebx,[ebp-0xc]
00D09BBA e90efeffff jmp 0xd099cd
And the optimized code for test2 you can see the loop looks like this:
00D09F3D 894df4 mov [ebp-0xc],ecx
00D09F40 81f910270000 cmp ecx,0x2710
00D09F46 0f8d46000000 jnl 0xd09f92
00D09F4C 3b251c414700 cmp esp,[0x47411c]
00D09F52 0f8659000000 jna 0xd09fb1
00D09F58 50 push eax
00D09F59 b9d1229d00 mov ecx,0x9d22d1 'Function 'a':.'
00D09F5E bae96ccb00 mov edx,0xcb6ce9 Array[1, 1, null]
00D09F63 e8886483ff call 0x5403f0 [stub: CallStaticFunction]
00D09F68 83c404 add esp,0x4
00D09F6B 8b45f0 mov eax,[ebp-0x10]
00D09F6E 50 push eax
00D09F6F b961239d00 mov ecx,0x9d2361 'Function 'b':.'
00D09F74 bae96ccb00 mov edx,0xcb6ce9 Array[1, 1, null]
00D09F79 e8726483ff call 0x5403f0 [stub: CallStaticFunction]
00D09F7E 83c404 add esp,0x4
00D09F81 8b4df4 mov ecx,[ebp-0xc]
00D09F84 83c102 add ecx,0x2
00D09F87 0f8048000000 jo 0xd09fd5
00D09F8D 8b45f0 mov eax,[ebp-0x10]
00D09F90 ebab jmp 0xd09f3d
And only one set of calls to SubTypeTestCache (outside the loop for test2) instead of two in test1.
Today, it seems that doing the cast once is faster but pulling the cast out of the loop seems like a simple optimization that the VM may do in the future.
Running (foo as Bar) has two effects:
It tells the editor that foo is a Bar which helps with static type analysis and lets the editor do code completion.
It checks that foo is a Bar (or a subtype of Bar), otherwise it'll throw a CastException.
Look for "Type Cast" in (http://www.dartlang.org/docs/spec/latest/dart-language-specification.pdf).
Updated: I like John's answer, too, but I think I should say one more thing. I overlooked the fact that you were talking about doing the cast once versus three times. Looking at final bFoo = (foo as Bar);, I want to say one more thing about the language semantics.
It's true that Dart Editor, dart2js, and the VM could conceivably infer that foo is of type Bar, which would save additional checks, etc. However, the semantics of the language say something slightly different. "final bFoo" does not have a type annotation. So according to the language spec, bFoo is of type Dynamic.
Hence, when you write "(foo as Bar)" three times, each expression results in a Bar. But when you write bFoo, you have a Dynamic object.
It is not "best practice" to perform three as casts right in a row for the same variable.
An as cast is really a runtime check. I'm just guessing, but if you are trying to reduce warnings from the editor, there is probably a better way to do it.
For example, here's one scenario:
class Foo {
}
class Bar extends Foo {
m1() => print('m1');
}
doStuff(Foo foo) {
foo.m1(); // warning here
}
main() {
var foo = new Bar();
doStuff(foo);
}
The above code runs just fine, but the editor does show a warning. To eliminate the warning, it's better to refactor the code. You could remove the Foo annotation from doStuff, or you could consider moving m1() up to Foo, or you could do double-dispatch.

pacer.sys cause BSOD

I have created a NDIS5 intermediate filter driver named fxwrap.sys,however when i uninstall it. windows causes BSOD.It also seems ndis!ndisOidRequestComplete reads null address from dump file.I want to know whether this problem is caused by fxwrap or other things.
env:windows 7 ultimate 7601
Here is fxwrap!PtRequestComplete function source code:
VOID PtRequestComplete(NDIS_HANDLE ProtocolBindingContext,
PNDIS_REQUEST NdisRequest,
NDIS_STATUS Status)
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;
NdisAcquireSpinLock(&pAdapt->AdaptDataLock);
{
pAdapt->OutstandingRequests = FALSE;
}
NdisReleaseSpinLock(&pAdapt->AdaptDataLock);
switch(NdisRequest->RequestType)
{
case NdisRequestQueryInformation:
{
if(Oid == OID_TCP_TASK_OFFLOAD)
{
Status = NDIS_STATUS_FAILURE;
}
ASSERT(Oid != OID_PNP_QUERY_POWER);
if(Oid == OID_PNP_CAPABILITIES && Status == NDIS_STATUS_SUCCESS)
{
MPQueryPNPCapbilities(pAdapt, &Status);
}
*pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
*pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
NdisMQueryInformationComplete(pAdapt->MiniportHandle, Status);
} break;
case NdisRequestSetInformation:
{
ASSERT( Oid != OID_PNP_SET_POWER);
*pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
*pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
NdisMSetInformationComplete(pAdapt->MiniportHandle, Status);
}break;
default:
ASSERT(0);
break;
}
}
following is dump info:
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1) An attempt was made to access a
pageable (or completely invalid) address at an interrupt request level
(IRQL) that is too high. This is usually caused by drivers using
improper addresses. If kernel debugger is available get stack
backtrace. Arguments: Arg1: 00000000, memory referenced Arg2:
00000002, IRQL Arg3: 00000000, value 0 = read operation, 1 = write
operation Arg4: 8a81bd11, address which referenced memory
Debugging Details:
READ_ADDRESS: GetPointerFromAddress: unable to read from 84788848
Unable to read MiSystemVaType memory at 84767e20 00000000
CURRENT_IRQL: 2
FAULTING_IP: ndis!ndisOidRequestComplete+8a 8a81bd11 803b05
cmp byte ptr [ebx],5
CUSTOMER_CRASH_COUNT: 1
DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT
BUGCHECK_STR: 0xD1
PROCESS_NAME: System
TRAP_FRAME: 8dd07aa0 -- (.trap 0xffffffff8dd07aa0) ErrCode = 00000000
eax=00000200 ebx=00000000 ecx=00000001 edx=00000000 esi=8dd07b4c
edi=a277f5a4 eip=8a81bd11 esp=8dd07b14 ebp=8dd07b34 iopl=0 nv
up ei pl zr na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030
gs=0000 efl=00010246
ndis!ndisOidRequestComplete+0x8a:
8a81bd11 803b05 cmp byte ptr [ebx],5 ds:0023:00000000=??
Resetting default scope
LAST_CONTROL_TRANSFER: from 8a81bd11 to 846605fb
STACK_TEXT:
8dd07aa0 8a81bd11 badb0d00 00000000 8dd07ac0 nt!KiTrap0E+0x2cf
8dd07b34 8a81c8b9 8dd07b4c 8c840008 870c1618
ndis!ndisOidRequestComplete+0x8a
8dd07b68 952b411b 8963b0f0 a277f5a4 00000000
ndis!NdisFOidRequestComplete+0x6a
8dd07b88 8a81c19d 870c1618 8c840008 00000000
pacer!PcFilterRequestComplete+0x5b
8dd07bbc 8a843572 02d07bd4 00000000 89ac60e0
ndis!ndisOidRequestComplete+0x516
8dd07bf4 8a843805 00ac60e0 8c840008 00000000
ndis!ndisMOidRequestCompleteInternal+0xd0
8dd07c18 8a87a765 02ac60e0 00000000 8c840008
ndis!ndisCompleteLegacyRequest+0xdb
8dd07c38 95a831c5 89ac60e0 00000000 89ad20e0
ndis!NdisMSetInformationComplete+0x81
8dd07c54 8a87506f 8a1d48e8 8a1d4908 00000000
fxwrap!PtRequestComplete+0x61
8dd07c70 8a81c05b 876f54c0 8966f0f0 00000000
ndis!ndisCompleteOidRequestToRequest+0x4a
8dd07ca4 8a8704b2 00d07cbc 89ad20e0 8a85a000
ndis!ndisOidRequestComplete+0x3d4
8dd07ce8 8a823221 00ad20e0 8966f190 86a58638
ndis!ndisMDoOidRequest+0x528
8dd07d00 8469ca6b 8966f188 00000000 86a58638
ndis!ndisDoOidRequests+0x4d
8dd07d50 84827fda 00000000 92ed9892 00000000 nt!ExpWorkerThread+0x10d
8dd07d90 846d01f9 8469c95e 00000000 00000000
nt!PspSystemThreadStartup+0x9e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19
STACK_COMMAND: kb
FOLLOWUP_IP: pacer!PcFilterRequestComplete+5b 952b411b 56
push esi
SYMBOL_STACK_INDEX: 3
SYMBOL_NAME: pacer!PcFilterRequestComplete+5b
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: pacer
IMAGE_NAME: pacer.sys
DEBUG_FLR_IMAGE_TIMESTAMP: 4a5bc916
FAILURE_BUCKET_ID: 0xD1_pacer!PcFilterRequestComplete+5b
BUCKET_ID: 0xD1_pacer!PcFilterRequestComplete+5b
Followup: MachineOwner
thanks for any input.
You write that it happens during uninstall. Is it uninstall or driver disable as well? I'll assume it's driver disable, don't see any reason why this should happen on uninstall exclusively. The failure happens in your set OID completion routine. More information is needed in order to analyze, specifically the view of pAdapt and MiniportHandle structs. However, most probable cause is lack of synchronization - for example, in this case it might happen if your driver has already deallocated the pAdapt context and the completion was invoked after that (again, this is just an assumption, need more data to give more certain answer).

Pin Tool unexpected instrumentation result

I've got very unexpected result from Pin Tool, my tool looks for CALL/RET instructions and then log the proper message :
VOID CallBack(VOID * ip, ADDRINT esp)
{
UINT32 *RetAddrPtr = (UINT32 *)esp;
fprintf(log_info,"RET inst #%p ==> Retuen Address #%p.\n", ip, *RetAddrPtr);
}
// Pin calls this function every time a new instruction is encountered
VOID Trace(TRACE trace, VOID *v)
{
ADDRINT insAddress = TRACE_Address(trace);
// Visit every basic block in the trace
for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl))
{
for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins))
{
ADDRINT instAddress = INS_Address(ins);
if( INS_IsCall(ins) )
{
ADDRINT nextInstAddress = (ADDRINT)( (USIZE)instAddress + INS_Size(ins) );
fprintf(log_info,"CALL inst #%p ==> CALL Return Address #%p.\n", instAddress, nextInstAddress);
}
if(INS_IsRet(ins))
{
INS_InsertCall( ins,
IPOINT_BEFORE,
(AFUNPTR)CallBack,
IARG_INST_PTR,
IARG_REG_VALUE,
REG_STACK_PTR,
IARG_END);
}
}
}
}
but the result is very unusual :-/. see this is log result from program entry point:
CALL inst #0101247C ==> CALL Return Address #01012481.
RET inst #01012800 ==> Return Address #01012481.
CALL inst #0101248A ==> CALL Return Address #0101248C.
CALL inst #7C80B73F ==> CALL Return Address #7C80B744.
RET inst #7C80B751 ==> Return Address #0101248C.
CALL inst #010124E3 ==> CALL Return Address #010124E9.
RET inst #77C3538A ==> Return Address #010124E9.
CALL inst #010124F8 ==> CALL Return Address #010124FE.
RET inst #77C1F1E0 ==> Return Address #010124FE.
CALL inst #01012506 ==> CALL Return Address #0101250C.
RET inst #77C1F1A9 ==> Return Address #0101250C.
CALL inst #01012520 ==> CALL Return Address #01012525.
RET inst #010127C4 ==> Return Address #01012525.
CALL inst #01012532 ==> CALL Return Address #01012538.
CALL inst #01012539 ==> CALL Return Address #0101253E.
CALL inst #010127BA ==> CALL Return Address #010127BF.
CALL inst #77C4EE60 ==> CALL Return Address #77C4EE65.
RET inst #77C4ED04 ==> Return Address #77C4EE28. <=========
RET inst #77C4ED97 ==> Return Address #77C4EE3F. <=========
RET inst #77C4EE49 ==> Return Address #77C4EE65.
RET inst #77C4EE68 ==> Return Address #010127BF.
RET inst #010127C1 ==> Return Address #0101253E.
as you can see, there is two RET instruction which doesn't map to any CALL.
after this I opened up program in debugger and saw this :
77C4EE15 > 8BFF MOV EDI,EDI ; kernel32.GetModuleHandleA
77C4EE17 55 PUSH EBP
77C4EE18 8BEC MOV EBP,ESP
77C4EE1A 51 PUSH ECX
77C4EE1B 53 PUSH EBX
77C4EE1C 9B WAIT
77C4EE1D D97D FC FSTCW WORD PTR SS:[EBP-4]
77C4EE20 FF75 FC PUSH DWORD PTR SS:[EBP-4]
77C4EE23 E8 41FEFFFF CALL msvcrt.77C4EC69 <============
77C4EE28 8BD8 MOV EBX,EAX
77C4EE2A 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C]
77C4EE2D F7D0 NOT EAX
77C4EE2F 23D8 AND EBX,EAX
77C4EE31 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
77C4EE34 2345 0C AND EAX,DWORD PTR SS:[EBP+C]
77C4EE37 59 POP ECX ; msvcrt.77C4EE65
77C4EE38 0BD8 OR EBX,EAX
77C4EE3A E8 CBFEFFFF CALL msvcrt.77C4ED0A <==============
77C4EE3F 8945 0C MOV DWORD PTR SS:[EBP+C],EAX
77C4EE42 D96D 0C FLDCW WORD PTR SS:[EBP+C]
77C4EE45 8BC3 MOV EAX,EBX
77C4EE47 5B POP EBX ; msvcrt.77C4EE65
77C4EE48 C9 LEAVE
Pin Tool cannot see this calls ? I think maybe I used a wrong sequence of API call.
and also there is another unexpected result: there is two different CALL instructions within a function with a conditional jmp between CALLs, which means just of those CALL instructions should execute but Pin log both of them!
Pin doesn't instrument ALL the process execution, it starts it a little bit after the real process start and ends a little bit before the real exit.
The call was probably executed when process execution wasn't redirected to Pin yet this is why you see the retn and not the call.
a little piece of code to explain it :
call start_instrumentation
label ret_call_start_ins:
[...]
function start_instrumentation:
_do_stuff_
* now the process is under Pin control *
_do_stuff_under_pin_control_
retn ; the return you see without any associated call

Resources