# 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?
0x...898 are 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)x
But the branch targets are different for high-half and low-half, otherwise it could simply
movsxd rdx, eax /
cmp rax, rdx /
jnl is the same condition as
jge, so it's jumping on
(int64_t)rax >= INT_MIN, with INT_MIN of course sign-extended to 64-bit.
cmp rax, 0xffffffff80000000 # INT32_MIN jge x_ge_INT32_MIN # else fall-through: x < INT32_MIN ... other code here x_ge_INT32_MIN: cmp rax, 0x7fffffff # INT32_MAX jle x_fits_in_int32_t ... else it doesn't, x > INT32_MAX
0xffffffff80000000 represents a negative signed integer,
(int64_t)INT32_MIN. It's the sign-extension of 32-bit
I don't know what
_M_extract_int() does and you didn't link any libstdc++ source for usage info.
I think 0xffffffff80000000 is the top physical memory address can be used for user mode
0xffffffff80000000 is 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
nullptr dereferences, 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.
User contributions licensed under CC BY-SA 3.0