I am leaning to the view that the MPX feature is an attempt to make C into a safe language. It would be fairer to say “a safer language” for I have seen no claim that MPX was fool-proof.
For the memory safe languages it is assumed that calls across independently compiled units have seen the same function prototypes and declarations of global variables. A loader could enforce this with a little help from the compiler but I don’t know of any attempt to do this. (The loader might demand a secure hash of types of external symbols.)
Figure 16-4 real page 377 of Intel’s manual (q.v.) is a strange diagram describing a structure that given the memory address of the memory address of X is converted to the address of a bound pair that is supposed to bound X. Section 16.4.3 explains the diagram. A pessimistic interpretation of this structure would lead you to think that for every byte of storage devoted to data including pointers, 4 bytes of “Bound Table Entries” are required. It is not nearly that bad because 1MB spans of data memory storing no pointers cost nothing and 1KB spans without pointers cost only virtual memory. There are further economies in the cache. Still such a structure for a modern language such as Scheme, Lisp, OCaml, are likely to need five times as much real data memory.
The problem, as I see it, is that there is no standardized dope vector. The convention is for code to call other code using C conventions, despite the input language to the compiler. Various compilers have their private conventions for messages between independently compiled modules. One argument is whether all index ranges start at 0. Another is how big the range should be. (PL/I had a 16 bit limit early on. That was too small.) I wrote much assembler code to call and be called by compiled code. It was easy. With a suspicious loader, honest assembler code and a bug-free compiler, that would have been memory safe.