简体   繁体   中英

Extracting value from an MPX bounds register into a general purpose register

Intel's Memory Protection Extensions provide four new 128-bit bounds registers, BND0 to BND3 , each storing a pair of 64-bit lower bound (LB) and upper bound (UB) values of a buffer.

How can I extract the lower bound's 64-bit value (ie %BND0[0-63] into a 64-bit general purpose register (ie %RAX )?

The problem as I understand it is that Intel's instruction set doesn't provide a way to directly do this. I've consulted Intel's MPX Enabling Guide (see download at bottom of this link ) and found that there is a BNDMOV b/m, b instruction that will store lower bounds and upper bounds in a bounds register to memory or another register . However it appears that the another register must be a bounds register itself because it's not possible to fit the 128-bit bounds register into a 64-bit general purpose register.

Additionally, as far as I can tell, there is no way to get just the lower bounds out of a bounds register by using a half-width sibling register (ie %EAX contains the value of the lower half of %RAX ). Likewise, there is no addressing %BND#.LB , even though fig. 14 on pg. 50 of the MPX Enabling Guide shows a debugger watching those values.

This is an experimental solution, I don't have a CPU with MPX support at hand.
My work is purely theoretical, I can't tell if it will fail miserably due to some quibble on a real hardware.


As Igor said in is complete answer there is no instruction to read a bnd register without passing through memory.
That's the end of the story.

As Mattew expressed his concern about spilling the value of the bnd register I though of an indirect way to read the bnd register.

The bottom of the line being that due to their nature the MPX let a programmer perform a dichotomic search on the value of a bnd register.

I'll use bndcl as reference throughout this answer. The dual, bndcu , with the considerations about the one complement format, is similar.

The instruction bndcl generates an exception #BR if the value of the register lower bound LB is higher than the address A tested.
What is required is to translate the conditions A < LB and A ≥ LB into a numeric value in a register or a flag.
Basically, if available and accessible, the bndstatus register's field EC (Error Condition) is what we are looking for: it is 1 if bndcl failed, 0 otherwise.
Alternatively one can handle the #BR exception (or any exception the OS reifies as bndcl generates only #BF and #UD) by setting a variable/register to 1. If said register is reset before executing bndcl then it will reflect the result of the check.
Care must be taken as the rip points to the offending bndcl instruction.

Long story short, one need something like

 bndcl:
    A < LB ⇒ ECX = 1 
    A ≥ LB ⇒ ECX = 0 

With these prerequisites we can perform a binary search on the values of the lower bound.
There is one small caveat: we can't test for equality, only for greater than or equal .
This means: 1) we perform a fixed number of comparisons (slightly greater than 64) and 2) we need an extra final step to determine the exact address.

To understand point 2) just consider searching the values 14 and 15 in an array from 0 to 15 inclusive:

       15                          14

Pivot    Step   Cmp         Pivot    Step   Cmp
 8        4      ≥           8        4      ≥
 12       2      ≥           12       2      ≥
 14       1      ≥           14       1      ≥ (Can't stop here)
 15       0      ≥           15       0      ≥

My CPU doesn't support the MPX, so I'll assume the existence of a macro bndclex that perform the check of bndcl and set ecx as said above.

;Get the bnd0 lower bound without storing it into memory
;It uses a dichotomy search

get_bnd0_lb: 
 mov rax, 4000_0000_0000_0000h  ;Half-range
 lea rbx, [rax*2]               ;Address to check


_check:

 ;D O   T H E   B O U N D    C H E C K 

 bndclex _bnd0, rbx

 ;ecx = 01 if rbx < bnd0.lb
 ;ecx = 00 if rbx >= bnd0.lb

 ;S E T   T H E   C F 

 not ecx
 shr ecx, 1                     ;CF = 0   IF rbx < bnd0.lb
                                ;     1   IF rbx >= bnd0.lb

 ;A D D / S U B   T H E   H A L F   R A N G E 

 sbb rcx, rcx           ;rcx =  0 IF rbx < bnd0.lb
                                ;      -1 IF rbx >= bnd0.lb

 sub rbx, rcx                   ;rbx = rbx     IF rbx < bnd0.lb
                                ;      rbx +1  IF rbx >= bnd0.lb

 xor rcx, rax                   ;rcx = rax     IF rbx < bnd0.lb
                                ;      NOT rax IF rbx >= bnd0.lb

 add rbx, rcx                   ;rbx = rbx + rax      IF rbx < bnd0.lb
                                ;      rbx + NOT rax + 1 
                                ;    = rbx + (-rax)   IF rbx >= bnd0.lb

 shr rax, 1                     ;Halve half-range
jnz _check

 ;C H  E C K    T H E   E X A C T   A D D R E S S

 bndclex _bnd0, rbx

 ;ecx = 01 if rbx < bnd0.lb
 ;ecx = 00 if rbx >= bnd0.lb

 lea rax, [rbx + rcx]

 ret 

The algorithm works by setting the initial pivot P 0 to the half of the 64-bit address range and the initial S 0 step equal to 1/4 of the address range.
Then at each step it moves the pivot to P i+1 = P i ± S i and halves the step S i+1 = S i / 2.

This algorithm leaks the number of zeros in the lower bound of the bnd register as the number of exceptions generated but doesn't store the value in memory.
One could generate synthetic #BR exceptions to workaround that.


The implementation of the bndclex macro - or better its elimination - is left to the OP as that strongly depends on the environment.
Mine was as simple as

%macro bndclex 2

 xor ecx, ecx           ;RCX = 0
 lea r8, [rcx+1]        ;r8 = 0

 cmp %2, QWORD [REL %1 %+ .lb]            
 cmovb rcx, r8          ;RCX = 1 if %2 < lower bound

%endmacro

Apparently you can't. It seems you're supposed to use memory (with BNDMOV or BNDSTX ) if you need the value of a bound register. BND0.LB is probably just the debugger notation and not an actual register.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM