LaunchCacheWriter.h [plain text]
#ifndef LaunchCacheWriter_h
#define LaunchCacheWriter_h
#include <stdint.h>
#include <vector>
#include <list>
#include <unordered_map>
#include <map>
#include "LaunchCacheFormat.h"
#include "LaunchCache.h"
#include "MachOParser.h"
#include "shared-cache/DyldSharedCache.h"
namespace dyld3 {
namespace launch_cache {
class ContentBuffer {
private:
std::vector<uint8_t> _data;
public:
std::vector<uint8_t>& bytes() { return _data; }
unsigned long size() const { return _data.size(); }
void reserve(unsigned long l) { _data.reserve(l); }
const uint8_t* start() const { return &_data[0]; }
const uint8_t* end() const { return &_data[_data.size()]; }
void append_uleb128(uint64_t value) {
uint8_t byte;
do {
byte = value & 0x7F;
value &= ~0x7F;
if ( value != 0 )
byte |= 0x80;
_data.push_back(byte);
value = value >> 7;
} while( byte >= 0x80 );
}
void append_byte(uint8_t byte) {
_data.push_back(byte);
}
void append_uint32(uint32_t value) {
for (int i=0; i < 4; ++i) {
_data.push_back(value & 0xFF);
value = (value >> 8);
}
}
void append_uint64(uint64_t value) {
for (int i=0; i < 8; ++i) {
_data.push_back(value & 0xFF);
value = (value >> 8);
}
}
void append_buffer(const ContentBuffer& value) {
_data.insert(_data.end(), value.start(), value.end());
}
static unsigned int uleb128_size(uint64_t value) {
uint32_t result = 0;
do {
value = value >> 7;
++result;
} while ( value != 0 );
return result;
}
void pad_to_size(unsigned int alignment) {
while ( (_data.size() % alignment) != 0 )
_data.push_back(0);
}
};
class ImageGroupWriter
{
public:
ImageGroupWriter(uint32_t groupNum, bool pages16KB, bool is64, bool dylibsExpectedOnDisk, bool mtimeAndInodeAreValid);
enum class FixupType { rebase, pointerBind, pointerLazyBind, bindText, bindTextRel, rebaseText, bindImportJmpRel, ignore };
struct FixUp {
uint32_t segIndex;
uint64_t segOffset;
FixupType type;
TargetSymbolValue target;
};
uint32_t size() const;
void finalizeTo(Diagnostics& diag, const std::vector<const BinaryImageGroupData*>&, binary_format::ImageGroup* buffer) const;
uint32_t maxLoadCount(Diagnostics& diag, const std::vector<const BinaryImageGroupData*>&, binary_format::ImageGroup* buffer) const;
bool isInvalid(uint32_t imageIndex) const;
void setImageCount(uint32_t);
void setImageInvalid(uint32_t imageIndex);
void setImagePath(uint32_t imageIndex, const char* path);
void setImageUUID(uint32_t imageIndex, const uuid_t uuid);
void setImageHasObjC(uint32_t imageIndex, bool value);
void setImageIsBundle(uint32_t imageIndex, bool value);
void setImageHasWeakDefs(uint32_t imageIndex, bool value);
void setImageMayHavePlusLoads(uint32_t imageIndex, bool value);
void setImageNeverUnload(uint32_t imageIndex, bool);
void setImageMustBeThisDir(uint32_t imageIndex, bool value);
void setImageIsPlatformBinary(uint32_t imageIndex, bool value);
void setImageOverridableDylib(uint32_t imageIndex, bool value);
void setImageIsEncrypted(uint32_t imageIndex, bool value);
void setImageMaxLoadCount(uint32_t imageIndex, uint32_t count);
void setImageFairPlayRange(uint32_t imageIndex, uint32_t offset, uint32_t size);
void setImageInitializerOffsets(uint32_t imageIndex, const std::vector<uint32_t>& offsets);
void setImageDOFOffsets(uint32_t imageIndex, const std::vector<uint32_t>& offsets);
void setImageInitBefore(uint32_t imageIndex, const std::vector<binary_format::ImageRef>&);
void setImageSliceOffset(uint32_t imageIndex, uint64_t fileOffset);
void setImageFileMtimeAndInode(uint32_t imageIndex, uint64_t mTime, uint64_t inode);
void setImageCdHash(uint32_t imageIndex, uint8_t cdHash[20]);
void setImageCodeSignatureLocation(uint32_t imageIndex, uint32_t fileOffset, uint32_t size);
void setImageDependentsCount(uint32_t imageIndex, uint32_t count);
void setImageDependent(uint32_t imageIndex, uint32_t depIndex, binary_format::ImageRef dependent);
void setImageSegments(uint32_t imageIndex, MachOParser& imageParser, uint64_t cacheUnslideBaseAddress);
void setImageFixups(Diagnostics& diag, uint32_t imageIndex, std::vector<FixUp>& fixups, bool hasTextRelocs);
void addImageAliasPath(uint32_t imageIndex, const char* anAlias);
void setImagePatchLocations(uint32_t imageIndex, uint32_t funcOffset, const std::unordered_set<uint32_t>& patchLocations);
void setGroupCacheOverrides(const std::vector<binary_format::DyldCacheOverride>& cacheOverrides);
void addImageIsOverride(binary_format::ImageRef replacer, binary_format::ImageRef replacee);
uint32_t addIndirectGroupNum(uint32_t groupNum);
uint32_t addString(const char* str);
void alignStringPool();
uint32_t imageDependentsCount(uint32_t imageIndex) const;
binary_format::ImageRef imageDependent(uint32_t imageIndex, uint32_t depIndex) const;
private:
struct InitializerInfo {
std::vector<uint32_t> offsetsInImage;
std::vector<binary_format::ImageRef> initBeforeImages;
};
uint32_t imageCount() const;
binary_format::Image& imageByIndex(uint32_t);
const binary_format::Image& imageByIndex(uint32_t) const;
std::vector<uint8_t> makeFixupOpcodes(const FixUp* start, const FixUp* end, uint32_t pageStartSegmentOffset, std::map<uint32_t, TargetSymbolValue>&);
void makeDataFixupMapAndOrdinalTable(std::vector<uint8_t>& fixupMap, std::vector<TargetSymbolValue>& ordinalTable);
void computeInitializerOrdering(uint32_t imageIndex);
uint32_t addUniqueInitList(const std::vector<binary_format::ImageRef>& initBefore);
void layoutBinary(binary_format::ImageGroup* grp) const;
const bool _isDiskImage;
const bool _is64;
const uint16_t _groupNum;
const uint32_t _pageSize;
bool _dylibsExpectedOnDisk;
bool _imageFileInfoIsCdHash;
std::vector<binary_format::CachedImage> _images;
std::vector<binary_format::DiskImage> _diskImages;
std::vector<binary_format::AliasEntry> _aliases;
std::vector<uint64_t> _segmentPool;
std::vector<binary_format::ImageRef> _dependentsPool;
std::vector<uint32_t> _initializerOffsets;
std::vector<binary_format::ImageRef> _initializerBeforeLists;
std::vector<uint32_t> _dofOffsets;
std::vector<TargetSymbolValue> _targetsPool;
ContentBuffer _fixupsPool;
std::vector<binary_format::PatchTable> _patchPool;
std::vector<binary_format::PatchOffset> _patchLocationPool;
std::vector<binary_format::DyldCacheOverride>_dyldCacheSymbolOverridePool;
std::vector<binary_format::ImageRefOverride> _imageOverridePool;
std::vector<uint32_t> _indirectGroupNumPool;
std::unordered_map<uint32_t, uint32_t> _indirectGroupNumPoolExisting;
std::vector<char> _stringPool;
std::unordered_map<std::string, uint32_t> _stringPoolExisting;
};
} }
#endif // LaunchCacheWriter_h