# 0x00007f33caf5a85f: cmp rax, 0xffffffff80000000
# 0x00007f33caf5a865: jnl 0x7f33caf5a898
...
target_of_jnl:
# 0x00007f33caf5a898: cmp rax, 0x7fffffff
# 0x00007f33caf5a89e: jle 0x7f33caf5a8c8
The above code snip is part of an execution flow of function _M_extract_int() in libstdc++.
I don't understand the meaning of the two compares. I think 0xffffffff80000000 is the top physical memory address can be used for user mode. But how about 0x7fffffff? What are they checking?
Note that
0x...865and0x...898are not contiguous, even though they're shown in the question as part of one contiguous block with no blank line. One is the branch target of the other.It appears to be checking for a value that can fit in a 32-bit 2's complement integer, i.e. between INT32_MIN and INT32_MAX (inclusive). Like
x == (int32_t)xBut the branch targets are different for high-half and low-half, otherwise it could simply
movsxd rdx, eax/cmp rax, rdx/je.jnlis the same condition asjge, so it's jumping on(int64_t)rax >= INT_MIN, with INT_MIN of course sign-extended to 64-bit.Note that
0xffffffff80000000represents a negative signed integer,(int64_t)INT32_MIN. It's the sign-extension of 32-bit0x80000000.I don't know what
_M_extract_int()does and you didn't link any libstdc++ source for usage info.No,
0xffffffff80000000is in the high half of virtual address space, and thus not already too high. See Address canonical form and pointer arithmetic for a diagram of x86-64 48-bit canonical virtual address-space.Linux (and I think all mainstream x86-64 OSes) reserve the entire top half for the kernel's use, with user-space able to allocate / map pages in the low half. i.e. user-space can use the entire low 47 bits of virtual address space. (Maybe not the very bottom, e.g. Linux stops processes from mapping the low 64k by default, so
nullptrdereferences, even with an offset, will still fault. MacOS reserves the entire low 4GiB.)With 5-level page tables (Intel's PML5 extension), user-space can use the low 56 bits of the 57-bit virtual address space.
Either way, this is a similar thing to what this code is looking for, but with 48 or 57-bit values that are correctly sign-extended to 64-bit, not 32.
nope. libstdc++ is used in user-space only, so the only addresses it will ever see are virtual.