2 * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 // dyldcache - access layer to the DYLD Shared Library Cache file
30 #include <security_utilities/unix++.h>
31 #include <security_utilities/memutils.h>
32 #include <security_utilities/macho++.h>
33 #include <security_utilities/endian.h>
34 #include "dyld_cache_format.h"
38 // One (architecture of the) Shared Library Cache.
39 // We mmap the file rather than reading a copy, since its format is rather scattered, and we're not
40 // interested in the vast majority of it.
41 // This is a read-only view of the cache file. It will not allow modifications, though it may
42 // tell you where in the file they should go.
44 class DYLDCache
: public UnixPlusPlus::AutoFileDesc
{
46 DYLDCache(const std::string
&path
);
49 std::string
magic() const { return mHeader
->magic
; }
50 uint64_t baseAddress() const { return flip(mHeader
->dyldBaseAddress
); }
51 Architecture
architecture() const { return mArch
->architecture(); }
52 size_t mapSize() const { return mSigStart
; } // size of all the mappings
53 size_t signatureLength() const { return mSigLength
; } // size of all the mappings
54 size_t totalSize() const { return mLength
; } // size of entire file (>= mapSize(), we hope)
56 template <class Int
> Int
flip(Int x
) const { return mFlip
? Security::flip(x
) : x
; }
59 static std::string
pathFor(const Architecture
&arch
); // file path for given architecture
60 static bool validate(UnixPlusPlus::FileDesc
&fd
); // does this look like a shared library cache?
63 template <class SubStruct
>
66 Item(const DYLDCache
&c
, uint32_t off
)
67 : cache(c
), mStruct(c
.at
<SubStruct
>(off
)) { }
68 const DYLDCache
&cache
;
71 const SubStruct
*mStruct
;
72 template <class Int
> Int
flip(Int x
) const { return cache
.flip(x
); }
77 // A contiguous mapping established by the cache builder
79 struct Mapping
: public Item
<shared_file_mapping_np
> {
80 mach_vm_address_t
address() const { return flip(mStruct
->sfm_address
); }
81 mach_vm_size_t
size() const { return flip(mStruct
->sfm_size
); }
82 mach_vm_address_t
limit() const { return address() + size(); }
83 mach_vm_offset_t
offset() const { return flip(mStruct
->sfm_file_offset
); }
84 vm_prot_t
maxProt() const { return flip(mStruct
->sfm_max_prot
); }
85 vm_prot_t
initProt() const { return flip(mStruct
->sfm_init_prot
); }
87 bool contains(uint64_t address
) const
88 { return address
>= this->address() && address
< this->limit(); }
90 Mapping(const DYLDCache
&c
, uint32_t off
) : Item
<shared_file_mapping_np
>(c
, off
) { }
93 uint32_t mappingCount() const { return flip(mHeader
->mappingCount
); }
94 Mapping
mapping(unsigned ix
) const;
96 Mapping
findMap(uint64_t address
) const;
97 uint64_t mapAddress(uint64_t address
) const;
101 // One original binary ("image") as embedded in the cache.
103 struct Image
: public Item
<dyld_cache_image_info
> {
104 Image(const DYLDCache
&c
, uint32_t off
) : Item
<dyld_cache_image_info
>(c
, off
) { }
106 uint64_t address() const { return flip(mStruct
->address
); }
107 uint64_t modTime() const { return flip(mStruct
->modTime
); }
108 uint64_t inode() const { return flip(mStruct
->inode
); }
109 uint32_t pad() const { return flip(mStruct
->pad
); }
110 std::string
path() const { return cache
.at
<char>(flip(mStruct
->pathFileOffset
)); }
113 uint32_t imageCount() const { return flip(mHeader
->imagesCount
); }
114 Image
image(unsigned ix
) const;
118 const T
*at(uint32_t offset
) const
120 size_t end
= offset
+ sizeof(T
);
121 if (offset
> end
|| end
> mLength
)
122 UnixError::throwMe(ENOEXEC
);
123 return LowLevelMemoryUtilities::increment
<const T
>(mBase
, offset
);
128 // A private table correlating cache "magic strings" to information we need about the cache
129 // (This should be in the cache files themselves)
132 cpu_type_t cpu
; // main architecture
133 cpu_subtype_t sub
; // subarchitecture
134 char magic
[16]; // cache file magic string
135 char filename
[10]; // conventional file name (off cacheFileBase)
136 uint16_t order
; // byte order marker
138 std::string
path() const
139 { return std::string(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
) + filename
; }
141 Architecture
architecture() const { return Architecture(cpu
, sub
); }
143 static const ArchType architectures
[];
144 static const ArchType defaultArchitecture
;
146 static const ArchType
*matchArchitecture(const dyld_cache_header
&header
);
152 const dyld_cache_header
*mHeader
; // cache file header (NOT byte order corrected)
153 const ArchType
*mArch
; // ArchType entry that describes this file
154 bool mFlip
; // need to flip all integers?
155 size_t mSigStart
; // end of all file mappings (start of signature)
156 size_t mSigLength
; // indicated length of signature
160 #endif //_H_DYLDCACHE