I was analysing a complete memory dump and I applied Windbg uf command to see what a function does
0: kd> uf profsvc!CUserProfileService::_RegisterGPNotification
This is the part of the output. I wonder why the address in parentheses is different than the address of profsvc!CUserProfileService::_RegisterGPNotification+0x44 which should be
000007fe fb149276
but is
000007fe fb155019.
When I try to unassembled the address 000007fe fb155019 with u it points to
profsvc!CUserProfileService::_RegisterGPNotification+0x44:
I’m really puzzled, any help deeply appreciated.
OUTPUT from WinDBG
….
profsvc!CUserProfileService::_RegisterGPNotification+0x2e:
000007fe`fb14925e ba01000000 mov edx,1
000007fe`fb149263 488bc8 mov rcx,rax
000007fe`fb149266 ff157c410200 call qword ptr [profsvc!_imp_RegisterGPNotification (000007fe`fb16d3e8)]
000007fe`fb14926c 85c0 test eax,eax
000007fe`fb14926e 0f84a5bd0000 je profsvc!CUserProfileService::_RegisterGPNotification+0x44 (**000007fe`fb155019**)
profsvc!CUserProfileService::_RegisterGPNotification+0x40:
000007fe`fb149274 33db xor ebx,ebx
000007fe`fb149276 eb00 jmp profsvc!CUserProfileService::_RegisterGPNotification+0x66 (000007fe`fb149278) Branch
profsvc!CUserProfileService::_RegisterGPNotification+0x66:
000007fe`fb149278 488b0d31b00200 mov rcx,qword ptr [profsvc!WPP_GLOBAL_Control (000007fe`fb1742b0)]
000007fe`fb14927f 488d052ab00200 lea rax,[profsvc!WPP_GLOBAL_Control (000007fe`fb1742b0)]
000007fe`fb149286 483bc8 cmp rcx,rax
000007fe`fb149289 740a je profsvc!CUserProfileService::_RegisterGPNotification+0x94 (000007fe`fb149295) Branch
0: kd> u 000007fe`fb155019
profsvc!CUserProfileService::_RegisterGPNotification+0x44:
000007fe`fb155019 ?? ???
^ Memory access error in 'u 000007fe`fb155019'
This is due to optimization, see the following MSDN article:
https://msdn.microsoft.com/en-us/library/windows/hardware/ff541382(v=vs.85).aspx
Related
I'm trying to find the address of the API HeapAlloc in Windbg using the following syntax u Kernel32!HeapAllocStub but windbg cannot resolve that. I have reloded the symbols and the error persist, for the Other api this method is working fine.
Can you point me what I'm doing wrong ?
Thanks in advance
why are you looking for HeapAllocStub ?
do you have any reason that it should exist ?
and in latest windows kernel32.dll does not have any implementation
most of the functions are implemented in kernelbase.dll
almost most of the heap functions are forwarded to ntdll.dll
HeapAlloc is implemented in ntdll as RtlAllocateHeap
windbg has a very powerful wild card Search
you can use a command like x *!*Heap*All*
which would look for any function that has the regex Heap.*All.*
in all the loaded Modules
kernel32 imports the function HeapAlloc as can be seen below
0:000> x *k*32*!*heap*all*
00007ffe`44eefb94 KERNEL32!`WerpHeapAlloc'::`1'::fin$0 (void)
00007ffe`44ea6330 KERNEL32!BasepJobObjectHeapAlloc (BasepJobObjectHeapAlloc)
00007ffe`44f023f8 KERNEL32!_imp_HeapAlloc = <no type information>
00007ffe`44f023e8 KERNEL32!_imp_HeapReAlloc = <no type information>
00007ffe`44eef90c KERNEL32!WerpHeapAlloc (void * __cdecl WerpHeapAlloc(struct _WER_HEAP_MAIN_HEADER *,unsigned __int64))
and the imported function is implemented in ntdll.dll
0:000> dps KERNEL32!_imp_HeapAlloc l1
00007ffe`44f023f8 00007ffe`460fa9a0 ntdll!RtlAllocateHeap
0:000> dps KERNEL32!_imp_HeapReAlloc l1
00007ffe`44f023e8 00007ffe`460f3640 ntdll!RtlReAllocateHeap
0:000>
0:000> u poi(KERNEL32!_imp_HeapAlloc) l5
ntdll!RtlAllocateHeap:
00007ffe`460fa9a0 48895c2408 mov qword ptr [rsp+8],rbx
00007ffe`460fa9a5 4889742410 mov qword ptr [rsp+10h],rsi
00007ffe`460fa9aa 57 push rdi
00007ffe`460fa9ab 4883ec30 sub rsp,30h
00007ffe`460fa9af 498bf8 mov rdi,r8
0:000>
How can i access the exception chain (SEH) using masm64?
Using masm32, I get the first exception looking into fs:[0]
But when I checked in Windbg if fs:[0] still pointed at the first exception in x64, I figured that it wasn't.
I'd like to set an exception in x64 the same way I did in x86. Is it feasible (maybe looking at gs register)?
If this is coding related then you use
ml64seh PROC FRAME:ExceptionFilter
this adds your exception handler to .PDATA section RUNTIME_FUNCTION
if this is how to find this exception handler in windbg when the exception has been raised
use !exchain command
or if you want to find it before executing a specific function use .fnent command
a sample for x64 seh and finding it in windbg is as follows
;assemble and link with
;ml64 /Zi ml64seh.asm /link /debug /entry:ml64seh /subsystem:console
.data
safeplace DWORD ?
.code
ExceptionFilter PROC
jmp Handler
ExceptionFilter ENDP
PUBLIC ml64seh
ml64seh PROC FRAME:ExceptionFilter
.ENDPROLOG
mov rax, 0
mov [rax], rax ;access violation
jmp exit
Handler::
lea rax, safeplace
mov [r8+078h], rax ; replacing rax in exception handler so access is possible
mov rax, 0
ret
Exit:
ret
ml64seh ENDP
END
run without stopping in windbg
:\>cdb -g ml64seh.exe
(2aa0.3024): Access violation - code c0000005 (first chance)
ml64seh!ml64seh+0x7:
00007ff7`0e3b1029 488900 mov qword ptr [rax],rax ds:00000000`00000000=????????????????
0:000>
it crashed and broke now locating exception handlers
0:000> .fnent .
Debugger function entry 0000020b`e36c47a8 for:
(00007ff7`0e3b1022) ml64seh!ml64seh+0x7 | (00007ff7`0e3b32b0) ml64seh!$xdatasym
BeginAddress = 00000000`00001022
EndAddress = 00000000`00001042
UnwindInfoAddress = 00000000`000032b0
Unwind info at 00007ff7`0e3b32b0, c bytes
version 1, flags 3, prolog 0, codes 0
handler routine: ml64seh!ILT+0(ExceptionFilter) (00007ff7`0e3b1005), data 0 <<<<<<<<<
0:000> !exchain
3 stack frames, scanning for handlers...
Frame 0x00: ml64seh!ml64seh+0x7 (00007ff7`0e3b1029)
ehandler ml64seh!ILT+0(ExceptionFilter) (00007ff7`0e3b1005) <<<<<<<<<<<<
Frame 0x02: ntdll!RtlUserThreadStart+0x21 (00007ffe`213c26a1)
ehandler ntdll!_C_specific_handler (00007ffe`213fc720)
0:000>
lets see if we go to the handler and return back to re access the faulting place
0:000> bp .
0:000> bp 00007ff7`0e3b1005
0:000> bl
0 e 00007ff7`0e3b1029 0001 (0001) 0:**** ml64seh!ml64seh+0x7
1 e 00007ff7`0e3b1005 0001 (0001) 0:**** ml64seh!ILT+0(ExceptionFilter)
0:000> g
Breakpoint 1 hit
ml64seh!ILT+0(ExceptionFilter):
00007ff7`0e3b1005 e916000000 jmp ml64seh!ExceptionFilter (00007ff7`0e3b1020)
0:000> g
Breakpoint 0 hit
ml64seh!ml64seh+0x7: is accessible now
00007ff7`0e3b1029 488900 mov qword ptr [rax],rax ds:00007ff7`0e3b4000=0000000000000000
0:000>
btw you can use dumpbin or linker to spit out all the unwindinfos in a specific binary using -unwindinfo switch
:\>dumpbin /unwindinfo ml64seh.exe
Microsoft (R) COFF/PE Dumper Version 14.29.30146.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file ml64seh.exe
File Type: EXECUTABLE IMAGE
Function Table (1)
Begin End Info Function Name
00000000 00001022 00001042 000032B0 ml64seh
Unwind version: 1
Unwind flags: EHANDLER UHANDLER
Size of prologue: 0x00
Count of codes: 0
Handler: 00001005 #ILT+0(ExceptionFilter)
The String type is Swift has a property named isEmpty that indicates whether a string has no characters.
I'd like to know if there's any difference between using isEmpty and checking the equality to an empty string literal. In other words, is myString.isEmpty any better than myString == ""?
I did some research and came across the following recommendations:
String struct reference at Apple developer documentation (as well as the Swift Language Guide) recommends using isEmpty instead of checking the string's length:
To check whether a string is empty, use its isEmpty property instead of comparing the length of one of the views to 0. Unlike with isEmpty, calculating a view’s count property requires iterating through the elements of the string.
Answer to a slightly different question from 2015 on StackOverflow by Rob Napier states the following:
The empty string is the only empty string, so there should be no cases where string.isEmpty() does not return the same value as string == "". They may do so in different amounts of time and memory, of course. Whether they use different amounts of time and memory is an implementation detail not described, but isEmpty is the preferred way to check in Swift (as documented).
Some blog posts also recommend using isEmpty especially instead of checking if the string's length is 0.
None of these sources however say anything against comparing with an empty literal.
It seems totally reasonable to avoid constructions like myString.count == 0 because of obvious performance and readability drawbacks. I also get the fact that myString.isEmpty is more readable than myString == "".
Still, I'm curious whether the comparison with an empty string literal is bad. Does it really have any memory or performance implications? Perhaps the Swift compiler is so smart these days that it will produce the same binary code for myString.isEmpty and myString == ""? My gut feeling is that the difference should be negligible or even non-existent but I don't have proofs.
I realize it's not really a practical question though, however I'll be grateful if someone could share some insights how these two alternatives work on a lower level and whether there are any differences. Thank you all in advance.
As a note, isEmpty is the preferred/recommended method to check the emptiness of a collection, as all Collection types guarantee that isEmpty returns in O(1) (or at least this holds for the standard library collections). The equality operator make no such guarantees, thus if you're only interested about the collection having or not having elements (e.g. to launch a processing operation), then isEmpty is definitively the way to go.
Now, to see what's happening under the hood when using isEmpty vs when comparing to an empty string, we can use the generated assembly.
func testEmpty(_ str: String) -> Bool { str.isEmpty }
results in the following assembly code:
_$s3CL29testEmptyySbSSF:
0000000100002c70 push rbp
0000000100002c71 mov rbp, rsp
0000000100002c74 mov rax, rsi
0000000100002c77 shr rax, 0x38
0000000100002c7b and eax, 0xf
0000000100002c7e movabs rcx, 0xffffffffffff
0000000100002c88 and rcx, rdi
0000000100002c8b bt rsi, 0x3d
0000000100002c90 cmovae rax, rcx
0000000100002c94 test rax, rax
0000000100002c97 sete al
0000000100002c9a pop rbp
0000000100002c9b ret
while
func testEqual(_ str: String) -> Bool { str == "" }
generates this:
_$s3CL29testEqualySbSSF:
0000000100002cd0 push rbp
0000000100002cd1 mov rbp, rsp
0000000100002cd4 movabs rcx, 0xe000000000000000
0000000100002cde test rdi, rdi
0000000100002ce1 jne 0x100002cec
0000000100002ce3 cmp rsi, rcx
0000000100002ce6 jne 0x100002cec
0000000100002ce8 mov al, 0x1
0000000100002cea pop rbp
0000000100002ceb ret
0000000100002cec xor edx, edx ; XREF=_$s3CL29testEqualySbSSF+17, _$s3CL29testEqualySbSSF+22
0000000100002cee xor r8d, r8d
0000000100002cf1 pop rbp
0000000100002cf2 jmp imp___stubs__$ss27_stringCompareWithSmolCheck__9expectingSbs11_StringGutsV_ADs01_G16ComparisonResultOtF
; endp
Both assemblies are generated in the Release mode, with all optimizations enabled. Seems that for the isEmpty call the compiler is able to take some shortcuts since it knows about the internal String structure.
But we can take that away by making our functions generic:
func testEmpty<S: StringProtocol>(_ str: S) -> Bool { str.isEmpty }
produces
_$s3CL29testEmptyySbxSyRzlF:
0000000100002bd0 push rbp
0000000100002bd1 mov rbp, rsp
0000000100002bd4 push r13
0000000100002bd6 push rax
0000000100002bd7 mov rax, rsi
0000000100002bda mov rcx, qword [ds:rdx+8]
0000000100002bde mov rsi, qword [ds:rcx+8]
0000000100002be2 mov r13, rdi
0000000100002be5 mov rdi, rax
0000000100002be8 call imp___stubs__$sSl7isEmptySbvgTj
0000000100002bed add rsp, 0x8
0000000100002bf1 pop r13
0000000100002bf3 pop rbp
0000000100002bf4 ret
; endp
, while
func testEqual<S: StringProtocol>(_ str: S) -> Bool { str == "" }
produces
_$s3CL29testEqualySbxSyRzlF:
0000000100002c00 push rbp
0000000100002c01 mov rbp, rsp
0000000100002c04 push r14
0000000100002c06 push r13
0000000100002c08 push rbx
0000000100002c09 sub rsp, 0x18
0000000100002c0d mov r14, rdx
0000000100002c10 mov r13, rsi
0000000100002c13 mov rbx, rdi
0000000100002c16 mov qword [ss:rbp+var_28], 0x0
0000000100002c1e movabs rax, 0xe000000000000000
0000000100002c28 mov qword [ss:rbp+var_20], rax
0000000100002c2c call _$sS2SSysWl
0000000100002c31 mov rcx, qword [ds:imp___got__$sSSN]
0000000100002c38 lea rsi, qword [ss:rbp+var_28]
0000000100002c3c mov rdi, rbx
0000000100002c3f mov rdx, r13
0000000100002c42 mov r8, r14
0000000100002c45 mov r9, rax
0000000100002c48 call imp___stubs__$sSysE2eeoiySbx_qd__tSyRd__lFZ
0000000100002c4d add rsp, 0x18
0000000100002c51 pop rbx
0000000100002c52 pop r13
0000000100002c54 pop r14
0000000100002c56 pop rbp
0000000100002c57 ret
; endp
Similar results, the isEmpty code results is less assembly code, which makes it faster.
My Windows 10 laptop has been BSODing recently, almost daily, around the time I am not using it (this is a work PC, so the issue happens from like 10pm to 6am). The crash dumps all look the same:
IRQL_NOT_LESS_OR_EQUAL (a)
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 a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 0000000000002d30, memory referenced
Arg2: 00000000000000ff, IRQL
Arg3: 00000000000000e8, bitfield :
bit 0 : value 0 = read operation, 1 = write operation
bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: fffff8011be4e0ff, address which referenced memory
...
DEFAULT_BUCKET_ID: WIN8_DRIVER_FAULT
BUGCHECK_STR: AV
PROCESS_NAME: System
...
LAST_CONTROL_TRANSFER: from fffff8011bf6bba9 to fffff8011bf59dc0
STACK_TEXT:
fffff801`1dc625c8 fffff801`1bf6bba9 : 00000000`0000000a 00000000`00002d30 00000000`000000ff 00000000`000000e8 : nt!KeBugCheckEx
fffff801`1dc625d0 fffff801`1bf6855a : 0000006b`b0e5bb5a fffff801`1dc62940 00000000`00000002 fffff801`1bf3aecc : nt!KiBugCheckDispatch+0x69
fffff801`1dc62710 fffff801`1be4e0ff : 00000000`00000000 fffff801`1bfed7b6 ffffe001`9510d010 ffffe001`97fc14f0 : nt!KiPageFault+0x51a
fffff801`1dc628a0 fffff801`1be4d31b : 00000000`00000000 00000000`00000002 00000000`00000000 00000000`00000000 : nt!PpmIdleExecuteTransition+0xc2f
fffff801`1dc62b00 fffff801`1bf5d24c : 00000000`00000000 fffff801`1c126180 fffff801`1c19c740 ffffe001`9355c080 : nt!PoIdle+0x33b
fffff801`1dc62c60 00000000`00000000 : fffff801`1dc63000 fffff801`1dc5d000 00000000`00000000 00000000`00000000 : nt!KiIdleLoop+0x2c
0: kd> .trap fffff801`1dc62710
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000000 rbx=0000000000000000 rcx=0000000000000012
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff8011be4e0ff rsp=fffff8011dc628a0 rbp=0000000000000000
r8=0000000000000000 r9=0000000000000000 r10=0000000000000000
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up di ng nz na po nc
nt!PpmIdleExecuteTransition+0xc2f:
fffff801`1be4e0ff 0fb686302d0000 movzx eax,byte ptr [rsi+2D30h] ds:00000000`00002d30=??
And if I am not mistaken, I should look into why RSI was set to 0 before the fault happened. And the "u" command shows a "call qword ptr [rbp+198h]" instruction may have preceded the fault.
0: kd> ub rip L13
nt!PpmIdleExecuteTransition+0xbe3:
fffff801`1be4e0b3 4032ff xor dil,dil
fffff801`1be4e0b6 0fb686302d0000 movzx eax,byte ptr [rsi+2D30h]
fffff801`1be4e0bd a801 test al,1
fffff801`1be4e0bf 740f je nt!PpmIdleExecuteTransition+0xc00 (fffff801`1be4e0d0)
fffff801`1be4e0c1 a808 test al,8
fffff801`1be4e0c3 750b jne nt!PpmIdleExecuteTransition+0xc00 (fffff801`1be4e0d0)
fffff801`1be4e0c5 33c0 xor eax,eax
fffff801`1be4e0c7 b948000000 mov ecx,48h
fffff801`1be4e0cc 33d2 xor edx,edx
fffff801`1be4e0ce 0f30 wrmsr
fffff801`1be4e0d0 488b8518030000 mov rax,qword ptr [rbp+318h]
fffff801`1be4e0d7 458bc4 mov r8d,r12d
fffff801`1be4e0da 448b8d0c030000 mov r9d,dword ptr [rbp+30Ch]
fffff801`1be4e0e1 8b54244c mov edx,dword ptr [rsp+4Ch]
fffff801`1be4e0e5 488b8c2480000000 mov rcx,qword ptr [rsp+80h]
fffff801`1be4e0ed 4889442420 mov qword ptr [rsp+20h],rax
fffff801`1be4e0f2 ff9598010000 call qword ptr [rbp+198h]
fffff801`1be4e0f8 448be0 mov r12d,eax
fffff801`1be4e0fb 89442444 mov dword ptr [rsp+44h],eax
0: kd> u rip
nt!PpmIdleExecuteTransition+0xc2f:
fffff801`1be4e0ff 0fb686302d0000 movzx eax,byte ptr [rsi+2D30h]
fffff801`1be4e106 a801 test al,1
fffff801`1be4e108 7418 je nt!PpmIdleExecuteTransition+0xc52 (fffff801`1be4e122)
fffff801`1be4e10a a808 test al,8
fffff801`1be4e10c 7514 jne nt!PpmIdleExecuteTransition+0xc52 (fffff801`1be4e122)
fffff801`1be4e10e 41b801000000 mov r8d,1
fffff801`1be4e114 33d2 xor edx,edx
fffff801`1be4e116 418bc0 mov eax,r8d
Appreciate your guidance as to how to debug this BSOD further. My troubleshooting direction may be false, in which case I am all ears for your insights. Thanks in advance!
%include "init.inc"
[org 0x0]
[bits 16]
jmp 0x07C0:start_boot
start_boot:
mov ax, cs
mov ds, ax
mov es, ax
load_setup:
mov ax, SETUP_SEG
mov es, ax
xor bx, bx
mov ah, 2 ; copy data to es:bx from disk.
mov al, 1 ; read a sector.
mov ch, 0 ; cylinder 0
mov cl, 2 ; read data since sector 2.
mov dh, 0 ; Head = 0
mov dl, 0 ; Drive = 0
int 0x13 ; BIOS call.
jc load_setup
lea si, [msg_load_setup]
call print
jmp $
print:
print_beg:
mov ax, 0xB800
mov es, ax
xor di, di
print_msg:
mov al, byte [si]
mov byte [es:di], al
or al, al
jz print_end
inc di
mov byte [es:di], BG_TEXT_COLOR
inc di
inc si
jmp print_msg
print_end:
ret
msg_load_setup db "Loading setup.bin was completed." , 0
times 510-($-$$) db 0
dw 0xAA55
I want to load setup.bin to memory address zero. So, I input 0 value to es register (SETUP_SEG = 0). bx, too. But it didn't work. then, I have a question about this issue. My test is below.
SETUP_SEG's value
0x0000 : fail
0x0010 : success
0x0020 : fail
0x0030 : fail
0x0040 : fail
0x0050 : success
I can't understand why this situation was happened. All test was carried out on VMware. Does anyone have an idea ?
I'm not sure if this is your problem, but your trying to load setup.bin in the Real Mode IVT (Interrupt Vector Table). The IVT contains the location of each interrupt, so I'm assuming that your boatloader is overwriting them when it loads setup.bin into memory! Interrupts can be sneaky and tricky, since they can be called even if you didn't call them. Any interrupt vector you overwrote will likely cause undefined behavior when called, which will cause some problems.
I suggest setting SETUP_SEG to a higher number like 0x2000 or 0x3000, but the lowest you could safely go is 0x07E0. The Osdev Wiki and Wikipedia have some helpful information on conventional memory and memory mapping.
I hope this helps!