Loading...
--- dyld/dyld-1340/cache_builder/ASLRTracker.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
-*
-* Copyright (c) 2017 Apple Inc. All rights reserved.
-*
-* @APPLE_LICENSE_HEADER_START@
-*
-* This file contains Original Code and/or Modifications of Original Code
-* as defined in and that are subject to the Apple Public Source License
-* Version 2.0 (the 'License'). You may not use this file except in
-* compliance with the License. Please obtain a copy of the License at
-* http://www.opensource.apple.com/apsl/ and read it before using this
-* file.
-*
-* The Original Code and all software distributed under the License are
-* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-* Please see the License for the specific language governing rights and
-* limitations under the License.
-*
-* @APPLE_LICENSE_HEADER_END@
-*/
-
-#ifndef ASLRTracker_hpp
-#define ASLRTracker_hpp
-
-#include "Types.h"
-
-#include <assert.h>
-#include <unordered_map>
-#include <vector>
-
-namespace cache_builder
-{
-
-class ASLR_Tracker
-{
-public:
- ASLR_Tracker() = default;
- ~ASLR_Tracker() = default;
-
- ASLR_Tracker(const ASLR_Tracker&) = delete;
- ASLR_Tracker& operator=(const ASLR_Tracker& other) = delete;
- ASLR_Tracker(ASLR_Tracker&&) = default;
- ASLR_Tracker& operator=(ASLR_Tracker&& other) = default;
-
- void setDataRegion(const void* rwRegionStart, size_t rwRegionSize);
- void add(void* loc, uint8_t level = (uint8_t)~0);
- void setRebaseTarget32(void*p, uint32_t targetVMAddr);
- void setRebaseTarget64(void*p, uint64_t targetVMAddr);
- void remove(void* p);
- bool has(void* loc, uint8_t* level = nullptr) const;
-
- bool hasRebaseTarget32(void* p, uint32_t* vmAddr) const;
- bool hasRebaseTarget64(void* p, uint64_t* vmAddr) const;
-
- void forEachFixup(void (^callback)(void* loc, bool& stop));
-
-#if BUILDING_APP_CACHE_UTIL
- // Get all the out of band rebase targets. Used for the kernel collection builder
- // to emit the classic relocations
- std::vector<void*> getRebaseTargets() const;
-
- bool hasHigh8(void* p, uint8_t* highByte) const;
- bool hasAuthData(void* p, uint16_t* diversity, bool* hasAddrDiv, uint8_t* key) const;
- void setHigh8(void* p, uint8_t high8);
- void setAuthData(void* p, uint16_t diversity, bool hasAddrDiv, uint8_t key);
-#endif
-
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
- void disable() { _enabled = false; };
- void clearRebaseTargetsMaps();
-#endif
-
-private:
-
- enum {
-#if BUILDING_APP_CACHE_UTIL
- // The x86_64 kernel collection needs 1-byte aligned fixups
- kMinimumFixupAlignment = 1
-#else
- // Shared cache fixups must be at least 4-byte aligned
- kMinimumFixupAlignment = 4
-#endif
- };
-
- uint8_t* _regionStart = nullptr;
- uint8_t* _regionEnd = nullptr;
- std::vector<bool> _bitmap;
-
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
- // Only the cache builder needs to disable ASLR, not the kernel linker
- bool _enabled = true;
-#endif
-
-#if BUILDING_APP_CACHE_UTIL
- struct AuthData {
- uint16_t diversity;
- bool addrDiv;
- uint8_t key;
- };
-
- std::unordered_map<void*, uint8_t> _high8Map;
- std::unordered_map<void*, AuthData> _authDataMap;
-
- // For kernel collections to work out which other collection a given
- // fixup is relative to
- std::vector<uint8_t> _cacheLevels;
-#endif
-
- std::unordered_map<void*, uint32_t> _rebaseTarget32;
- std::unordered_map<void*, uint64_t> _rebaseTarget64;
-};
-
-// Shared cache pointer values are packed so that we don't have to store too much data in
-// maps on the ASLRTracker. We don't pack in chain "next" bits, as we don't have enough bits to do so,
-// but we can pack in all the other information
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-struct Fixup
-{
- class Cache32
- {
- public:
- static CacheVMAddress getCacheVMAddressFromLocation(CacheVMAddress cacheBaseAddress,
- const void* fixupLocation)
- {
- const Cache32* value = (Cache32*)fixupLocation;
- return cacheBaseAddress + VMOffset((uint64_t)value->cacheVMOffset);
- }
-
- static void setLocation(CacheVMAddress cacheBaseAddress, void* fixupLocation,
- CacheVMAddress targetAddress)
- {
- // First zero the location (not needed on 32-bit but do for consistency with 64-bit code)
- *(uint32_t*)fixupLocation = 0;
-
- // Then set the value
- Cache32* value = (Cache32*)fixupLocation;
- VMOffset offset = targetAddress - cacheBaseAddress;
- value->cacheVMOffset = (uint32_t)offset.rawValue();
- assert(value->cacheVMOffset == offset.rawValue());
- }
-
- static void updateLocationToCacheVMAddress(CacheVMAddress cacheBaseAddress, void* fixupLocation,
- CacheVMAddress targetAddress)
- {
- Cache32* value = (Cache32*)fixupLocation;
- VMOffset offset = targetAddress - cacheBaseAddress;
- value->cacheVMOffset = (uint32_t)offset.rawValue();
- assert(value->cacheVMOffset == offset.rawValue());
- }
-
- // This is a bit of a hack. We don't know for sure that this value is null if its all zeroes
- // as technically its a 0 offset from the cache base address. But there's no good reason
- // for anyone to point to the cache header. Anyone using this is probably doing something
- // like parsing objc, which has no legitimate reason to be pointing to the cache header
- static bool isNull(const void* fixupLocation)
- {
- const Cache32* value = (Cache32*)fixupLocation;
- return value->cacheVMOffset == 0;
- }
-
- private:
- // This could really be a cacheVMAddress, but for consistency with 64-bit, lets use an offset
- uint32_t cacheVMOffset;
- };
- static_assert(sizeof(Cache32) == sizeof(uint32_t));
-
- class Cache64
- {
- public:
- static CacheVMAddress getCacheVMAddressFromLocation(CacheVMAddress cacheBaseAddress,
- const void* fixupLocation)
- {
- const Cache64* value = (Cache64*)fixupLocation;
- if ( value->regular.isAuthenticated )
- return cacheBaseAddress + VMOffset(value->auth.cacheVMOffset);
- else
- return cacheBaseAddress + VMOffset(value->regular.cacheVMOffset);
- }
-
- static void updateLocationToCacheVMAddress(CacheVMAddress cacheBaseAddress, void* fixupLocation,
- CacheVMAddress targetAddress)
- {
- Cache64* value = (Cache64*)fixupLocation;
- if ( value->regular.isAuthenticated ) {
- VMOffset offset = targetAddress - cacheBaseAddress;
- value->auth.cacheVMOffset = offset.rawValue();
- assert(value->auth.cacheVMOffset == offset.rawValue());
- } else {
- VMOffset offset = targetAddress - cacheBaseAddress;
- value->regular.cacheVMOffset = offset.rawValue();
- assert(value->regular.cacheVMOffset == offset.rawValue());
- }
- }
-
- static void setLocation(CacheVMAddress cacheBaseAddress, void* fixupLocation,
- CacheVMAddress targetAddress, uint8_t high8,
- uint16_t authDiversity, bool hasAddrDiv, uint8_t authKey,
- bool isAuth)
- {
- VMOffset offset = targetAddress - cacheBaseAddress;
-
- // First zero the location
- *(uint64_t*)fixupLocation = 0;
-
- // Then set the value
- Cache64* value = (Cache64*)fixupLocation;
- if ( isAuth ) {
- value->auth.cacheVMOffset = offset.rawValue();
- value->auth.authDiversity = authDiversity;
- value->auth.authKey = authKey;
- value->auth.hasAddrDiv = hasAddrDiv ? 1 : 0;
- value->auth.isAuthenticated = 1;
-
- assert(value->auth.cacheVMOffset == offset.rawValue());
- } else {
- value->regular.cacheVMOffset = offset.rawValue();
- value->regular.high8 = high8;
- value->regular.unused = 0;
- value->regular.isAuthenticated = 0;
-
- assert(value->regular.cacheVMOffset == offset.rawValue());
- }
- }
-
- static uint8_t getHigh8(const void* fixupLocation)
- {
- const Cache64* value = (Cache64*)fixupLocation;
- if ( value->auth.isAuthenticated )
- return 0;
-
- return value->regular.high8;
- }
-
- static bool hasAuthData(void* fixupLocation, uint16_t& diversity, bool& hasAddrDiv, uint8_t& key)
- {
- const Cache64* value = (Cache64*)fixupLocation;
- if ( !value->auth.isAuthenticated )
- return false;
-
- diversity = value->auth.authDiversity;
- hasAddrDiv = value->auth.hasAddrDiv;
- key = value->auth.authKey;
- return true;
- }
-
- // This is a bit of a hack. We don't know for sure that this value is null if its all zeroes
- // as technically its a 0 offset from the cache base address. But there's no good reason
- // for anyone to point to the cache header. Anyone using this is probably doing something
- // like parsing objc, which has no legitimate reason to be pointing to the cache header
- static bool isNull(const void* fixupLocation)
- {
- const Cache64* value = (Cache64*)fixupLocation;
- if ( value->regular.isAuthenticated ) {
- return value->auth.cacheVMOffset == 0;
- } else {
- return value->regular.cacheVMOffset == 0;
- }
- }
-
- private:
- struct Auth {
- uint64_t cacheVMOffset : 44;
- uint64_t authDiversity : 16;
- uint64_t authKey : 2;
- uint64_t hasAddrDiv : 1;
- uint64_t isAuthenticated : 1; // == 1
- };
- struct Regular {
- uint64_t cacheVMOffset : 44;
- uint64_t high8 : 8;
- uint64_t unused : 11;
- uint64_t isAuthenticated : 1; // == 0
- };
-
- union {
- Auth auth;
- Regular regular;
- };
- };
- static_assert(sizeof(Cache64) == sizeof(uint64_t));
-};
-#endif // BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-
-} // namespace cache_builder
-
-#endif /* ASLRTracker_hpp */