vm: implement B_RANDOMIZED_IMAGE_ADDRESS address specification

On some 64 bit architectures program and library images have to be mapped in
the lower 2 GB of the address space (due to instruction pointer relative
addressing). Address specification B_RANDOMIZED_IMAGE_ADDRESS ensures that
created area satisfies that requirement.
This commit is contained in:
Pawel Dziepak
2013-04-04 20:54:02 +02:00
parent f697412ff8
commit 65ed4fa908
5 changed files with 31 additions and 10 deletions
+1
View File
@@ -81,6 +81,7 @@ typedef struct area_info {
/* B_ANY_KERNEL_BLOCK_ADDRESS 5 */ /* B_ANY_KERNEL_BLOCK_ADDRESS 5 */
#define B_RANDOMIZED_ANY_ADDRESS 6 #define B_RANDOMIZED_ANY_ADDRESS 6
#define B_RANDOMIZED_BASE_ADDRESS 7 #define B_RANDOMIZED_BASE_ADDRESS 7
#define B_RANDOMIZED_IMAGE_ADDRESS 8
/* area protection */ /* area protection */
#define B_READ_AREA 1 #define B_READ_AREA 1
+26 -8
View File
@@ -36,6 +36,7 @@ const addr_t VMUserAddressSpace::kMaxInitialRandomize = 0x20000000000ul;
const addr_t VMUserAddressSpace::kMaxRandomize = 0x800000ul; const addr_t VMUserAddressSpace::kMaxRandomize = 0x800000ul;
const addr_t VMUserAddressSpace::kMaxInitialRandomize = 0x2000000ul; const addr_t VMUserAddressSpace::kMaxInitialRandomize = 0x2000000ul;
#endif #endif
const addr_t VMUserAddressSpace::kImageEndAddress = 0x7ffffffful;
/*! Verifies that an area with the given aligned base and size fits into /*! Verifies that an area with the given aligned base and size fits into
@@ -69,6 +70,15 @@ log2(uint32_t v)
} }
static inline bool
is_randomized(uint32 addressSpec)
{
return addressSpec == B_RANDOMIZED_ANY_ADDRESS
|| addressSpec == B_RANDOMIZED_BASE_ADDRESS
|| addressSpec == B_RANDOMIZED_IMAGE_ADDRESS;
}
VMUserAddressSpace::VMUserAddressSpace(team_id id, addr_t base, size_t size) VMUserAddressSpace::VMUserAddressSpace(team_id id, addr_t base, size_t size)
: :
VMAddressSpace(id, base, size, "address space"), VMAddressSpace(id, base, size, "address space"),
@@ -183,6 +193,11 @@ VMUserAddressSpace::InsertArea(VMArea* _area, size_t size,
searchEnd = fEndAddress; searchEnd = fEndAddress;
break; break;
case B_RANDOMIZED_IMAGE_ADDRESS:
searchBase = (addr_t)addressRestrictions->address;
searchEnd = min_c(fEndAddress, kImageEndAddress);
break;
default: default:
return B_BAD_VALUE; return B_BAD_VALUE;
} }
@@ -561,7 +576,9 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end,
start = ROUNDUP(start, alignment); start = ROUNDUP(start, alignment);
if (addressSpec == B_RANDOMIZED_BASE_ADDRESS) { if (addressSpec == B_RANDOMIZED_BASE_ADDRESS
|| addressSpec == B_RANDOMIZED_IMAGE_ADDRESS) {
originalStart = start; originalStart = start;
start = _RandomizeAddress(start, end - size, alignment, true); start = _RandomizeAddress(start, end - size, alignment, true);
} }
@@ -594,7 +611,7 @@ second_chance:
addr_t nextBase = next == NULL ? end : next->Base(); addr_t nextBase = next == NULL ? end : next->Base();
if (is_valid_spot(start, alignedBase, size, nextBase)) { if (is_valid_spot(start, alignedBase, size, nextBase)) {
if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { if (is_randomized(addressSpec)) {
alignedBase = _RandomizeAddress(alignedBase, alignedBase = _RandomizeAddress(alignedBase,
nextBase - size, alignment); nextBase - size, alignment);
} }
@@ -615,7 +632,7 @@ second_chance:
if (is_valid_spot(last->Base() + (last->Size() - 1), if (is_valid_spot(last->Base() + (last->Size() - 1),
alignedBase, size, next->Base())) { alignedBase, size, next->Base())) {
if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { if (is_randomized(addressSpec)) {
alignedBase = _RandomizeAddress(alignedBase, alignedBase = _RandomizeAddress(alignedBase,
next->Base() - size, alignment); next->Base() - size, alignment);
} }
@@ -637,7 +654,7 @@ second_chance:
if (is_valid_spot(last->Base() + (last->Size() - 1), alignedBase, if (is_valid_spot(last->Base() + (last->Size() - 1), alignedBase,
size, end)) { size, end)) {
if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { if (is_randomized(addressSpec)) {
alignedBase = _RandomizeAddress(alignedBase, end - size, alignedBase = _RandomizeAddress(alignedBase, end - size,
alignment); alignment);
} }
@@ -677,7 +694,7 @@ second_chance:
&& alignedBase == next->Base() && alignedBase == next->Base()
&& next->Size() >= size) { && next->Size() >= size) {
if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { if (is_randomized(addressSpec)) {
alignedBase = _RandomizeAddress(next->Base(), alignedBase = _RandomizeAddress(next->Base(),
next->Size() - size, alignment); next->Size() - size, alignment);
} }
@@ -699,7 +716,7 @@ second_chance:
// reserved area, and the reserved area will be resized // reserved area, and the reserved area will be resized
// to make space // to make space
if (addressSpec == B_RANDOMIZED_ANY_ADDRESS) { if (is_randomized(addressSpec)) {
addr_t alignedNextBase = ROUNDUP(next->Base(), addr_t alignedNextBase = ROUNDUP(next->Base(),
alignment); alignment);
@@ -731,6 +748,7 @@ second_chance:
case B_BASE_ADDRESS: case B_BASE_ADDRESS:
case B_RANDOMIZED_BASE_ADDRESS: case B_RANDOMIZED_BASE_ADDRESS:
case B_RANDOMIZED_IMAGE_ADDRESS:
{ {
// find a hole big enough for a new area beginning with "start" // find a hole big enough for a new area beginning with "start"
if (last == NULL) { if (last == NULL) {
@@ -765,7 +783,7 @@ second_chance:
area->SetBase(start); area->SetBase(start);
else { else {
start = lastEnd + 1; start = lastEnd + 1;
if (addressSpec == B_RANDOMIZED_BASE_ADDRESS) { if (is_randomized(addressSpec)) {
addr_t spaceEnd = end; addr_t spaceEnd = end;
if (next != NULL) if (next != NULL)
spaceEnd = next->Base(); spaceEnd = next->Base();
@@ -781,7 +799,7 @@ second_chance:
// we didn't find a free spot in the requested range, so we'll // we didn't find a free spot in the requested range, so we'll
// try again without any restrictions // try again without any restrictions
if (addressSpec != B_RANDOMIZED_BASE_ADDRESS) { if (!is_randomized(addressSpec)) {
start = fBase; start = fBase;
addressSpec = B_ANY_ADDRESS; addressSpec = B_ANY_ADDRESS;
} else if (originalStart == 0) { } else if (originalStart == 0) {
@@ -67,6 +67,7 @@ private:
private: private:
static const addr_t kMaxRandomize; static const addr_t kMaxRandomize;
static const addr_t kMaxInitialRandomize; static const addr_t kMaxInitialRandomize;
static const addr_t kImageEndAddress;
VMUserAreaList fAreas; VMUserAreaList fAreas;
mutable VMUserArea* fAreaHint; mutable VMUserArea* fAreaHint;
+1
View File
@@ -1226,6 +1226,7 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size,
case B_ANY_KERNEL_BLOCK_ADDRESS: case B_ANY_KERNEL_BLOCK_ADDRESS:
case B_RANDOMIZED_ANY_ADDRESS: case B_RANDOMIZED_ANY_ADDRESS:
case B_RANDOMIZED_BASE_ADDRESS: case B_RANDOMIZED_BASE_ADDRESS:
case B_RANDOMIZED_IMAGE_ADDRESS:
break; break;
default: default:
+2 -2
View File
@@ -173,7 +173,7 @@ get_image_region_load_address(image_t* image, uint32 index, int32 lastDelta,
if (index == 0) { if (index == 0) {
// but only the first segment gets a free ride // but only the first segment gets a free ride
loadAddress = RLD_PROGRAM_BASE; loadAddress = RLD_PROGRAM_BASE;
addressSpecifier = B_RANDOMIZED_BASE_ADDRESS; addressSpecifier = B_RANDOMIZED_IMAGE_ADDRESS;
} else { } else {
loadAddress = image->regions[index].vmstart + lastDelta; loadAddress = image->regions[index].vmstart + lastDelta;
addressSpecifier = B_EXACT_ADDRESS; addressSpecifier = B_EXACT_ADDRESS;
@@ -298,7 +298,7 @@ map_image(int fd, char const* path, image_t* image, bool fixed)
addr_t loadAddress; addr_t loadAddress;
size_t reservedSize = 0; size_t reservedSize = 0;
size_t length = 0; size_t length = 0;
uint32 addressSpecifier = B_RANDOMIZED_ANY_ADDRESS; uint32 addressSpecifier = B_RANDOMIZED_IMAGE_ADDRESS;
for (uint32 i = 0; i < image->num_regions; i++) { for (uint32 i = 0; i < image->num_regions; i++) {
// for BeOS compatibility: if we load an old BeOS executable, we // for BeOS compatibility: if we load an old BeOS executable, we