]>
git.saurik.com Git - apple/ld64.git/blob - src/ld/code-sign-blobs/superblob.h
2 // SuperBlob - a typed bag of Blobs
18 // A SuperBlob is a Blob that contains multiple sub-Blobs of varying type.
19 // The SuperBlob is contiguous and contains a directory of its sub-blobs.
20 // A Maker is included.
22 // SuperBlobCore lets you define your own SuperBlob type. To just use a generic
23 // SuperBlob, use SuperBlob<> below.
25 template <class _BlobType
, uint32_t _magic
, class _Type
>
26 class SuperBlobCore
: public Blob
<_BlobType
, _magic
> {
28 class Maker
; friend class Maker
;
32 // echoes from parent BlobCore (the C++ type system is too restrictive here)
33 typedef BlobCore::Offset Offset
;
34 template <class BlobType
> BlobType
*at(Offset offset
) { return BlobCore::at
<BlobType
>(offset
); }
35 template <class BlobType
> const BlobType
*at(Offset offset
) const { return BlobCore::at
<BlobType
>(offset
); }
37 void setup(size_t size
, unsigned cnt
)
38 { this->initialize(size
); this->mCount
= cnt
; }
41 Endian
<Type
> type
; // type of sub-Blob
42 Endian
<Offset
> offset
; // starting offset
45 bool validateBlob(size_t maxSize
= 0) const;
47 unsigned count() const { return mCount
; }
49 // access by index number
50 Type
type(unsigned n
) const { assert(n
< mCount
); return mIndex
[n
].type
; }
51 const BlobCore
*blob(unsigned n
) const { assert(n
< mCount
); Offset off
=mIndex
[n
].offset
; return off
? at
<const BlobCore
>(off
) : NULL
; }
53 template <class BlobType
>
54 const BlobType
*blob(unsigned n
) const { return BlobType::specific(blob(n
)); }
56 // access by index type (assumes unique types)
57 const BlobCore
*find(Type type
) const;
58 template <class BlobType
>
59 const BlobType
*find(Type t
) const { return BlobType::specific(find(t
)); }
62 Endian
<uint32_t> mCount
; // number of sub-Blobs following
63 Index mIndex
[0]; // <count> IndexSlot structures
64 // followed by sub-Blobs, packed and ordered in an undefined way
68 template <class _BlobType
, uint32_t _magic
, class _Type
>
69 inline bool SuperBlobCore
<_BlobType
, _magic
, _Type
>::validateBlob(size_t maxSize
/* = 0 */) const
71 unsigned cnt
= mCount
;
72 size_t ixLimit
= sizeof(SuperBlobCore
) + cnt
* sizeof(Index
); // end of index vector
73 if (!BlobCore::validateBlob(_magic
, ixLimit
, maxSize
))
76 for (const Index
*ix
= mIndex
+ cnt
- 1; ix
>= mIndex
; ix
--) {
77 Offset offset
= ix
->offset
;
79 continue; // offset==0 means unused entry
80 if (offset
< ixLimit
// offset not too small
81 || offset
+ sizeof(BlobCore
) > this->length() // fits Blob header (including length field)
82 || offset
+ at
<const BlobCore
>(offset
)->length() > this->length()) // fits entire blob
90 // A generic SuperBlob ready for use. You still need to specify a magic number.
92 template <uint32_t _magic
, class _Type
= uint32_t>
93 class SuperBlob
: public SuperBlobCore
<SuperBlob
<_magic
, _Type
>, _magic
, _Type
> {
97 template <class _BlobType
, uint32_t _magic
, class _Type
>
98 const BlobCore
*SuperBlobCore
<_BlobType
, _magic
, _Type
>::find(Type t
) const
100 for (unsigned slot
= 0; slot
< mCount
; slot
++) {
101 if (mIndex
[slot
].type
== t
) {
102 uint32_t off
= mIndex
[slot
].offset
;
106 return at
<const BlobCore
>(off
);
109 return NULL
; // not found
114 // A SuperBlob::Maker simply assembles multiple Blobs into a single, indexed
115 // super-blob. Just add() sub-Blobs by type and call build() to get
116 // the result, malloc'ed. A Maker is not reusable.
117 // Maker can repeatedly make SuperBlobs from the same (cached) inputs.
118 // It can also tell you how big its output will be, given established contents
119 // plus (optional) additional sizes of blobs yet to come.
121 template <class _BlobType
, uint32_t _magic
, class _Type
>
122 class SuperBlobCore
<_BlobType
, _magic
, _Type
>::Maker
{
126 Maker(const Maker
&src
)
128 for (typename
BlobMap::iterator it
= mPieces
.begin(); it
!= mPieces
.end(); ++it
)
129 mPieces
.insert(make_pair(it
->first
, it
->second
->clone()));
134 for (typename
BlobMap::iterator it
= mPieces
.begin(); it
!= mPieces
.end(); ++it
)
138 void add(Type type
, BlobCore
*blob
); // takes ownership of blob
139 void add(const _BlobType
*blobs
); // copies all blobs
140 void add(const Maker
&maker
); // ditto
142 size_t size(size_t size1
= 0, ...) const; // size with optional additional blob sizes
143 _BlobType
*make() const; // create (malloc) and return SuperBlob
144 _BlobType
*operator () () const { return make(); }
147 typedef std::map
<Type
, BlobCore
*> BlobMap
;
153 // Add a Blob to a SuperBlob::Maker.
154 // This takes ownership of the blob, which must have been malloc'ed.
155 // Any previous value set for this Type will be freed immediately.
157 template <class _BlobType
, uint32_t _magic
, class _Type
>
158 void SuperBlobCore
<_BlobType
, _magic
, _Type
>::Maker::add(Type type
, BlobCore
*blob
)
160 pair
<typename
BlobMap::iterator
, bool> r
= mPieces
.insert(make_pair(type
, blob
));
161 if (!r
.second
) { // already there
162 //secdebug("superblob", "Maker %p replaces type=%d", this, type);
163 ::free(r
.first
->second
);
164 r
.first
->second
= blob
;
168 template <class _BlobType
, uint32_t _magic
, class _Type
>
169 void SuperBlobCore
<_BlobType
, _magic
, _Type
>::Maker::add(const _BlobType
*blobs
)
171 for (uint32_t ix
= 0; ix
< blobs
->mCount
; ix
++)
172 this->add(blobs
->mIndex
[ix
].type
, blobs
->blob(ix
)->clone());
175 template <class _BlobType
, uint32_t _magic
, class _Type
>
176 void SuperBlobCore
<_BlobType
, _magic
, _Type
>::Maker::add(const Maker
&maker
)
178 for (typename
BlobMap::const_iterator it
= maker
.mPieces
.begin(); it
!= maker
.mPieces
.end(); ++it
)
179 this->add(it
->first
, it
->second
->clone());
184 // Calculate the size the new SuperBlob would have, given the contents of the Maker
185 // so far, plus additional blobs with the sizes given.
187 template <class _BlobType
, uint32_t _magic
, class _Type
>
188 size_t SuperBlobCore
<_BlobType
, _magic
, _Type
>::Maker::size(size_t size1
, ...) const
190 // count established blobs
191 unsigned count
= mPieces
.size();
193 for (typename
BlobMap::const_iterator it
= mPieces
.begin(); it
!= mPieces
.end(); ++it
) {
194 if ( it
->second
!= NULL
)
195 total
+= (it
->second
->length() + 3) & (-4); // 4-byte align each element
198 // add preview blob sizes to calculation (if any)
201 va_start(args
, size1
);
205 size1
= va_arg(args
, size_t);
210 return sizeof(SuperBlobCore
) + count
* sizeof(Index
) + total
;
215 // Finish SuperBlob construction and return the new, malloc'ed, SuperBlob.
216 // This can be done repeatedly.
218 template <class _BlobType
, uint32_t _magic
, class _Type
>
219 _BlobType
*SuperBlobCore
<_BlobType
, _magic
, _Type
>::Maker::make() const
221 Offset pc
= sizeof(SuperBlobCore
) + mPieces
.size() * sizeof(Index
);
222 Offset total
= size();
223 _BlobType
*result
= (_BlobType
*)calloc(1, total
);
226 result
->setup(total
, mPieces
.size());
228 for (typename
BlobMap::const_iterator it
= mPieces
.begin(); it
!= mPieces
.end(); ++it
) {
229 result
->mIndex
[n
].type
= it
->first
;
230 BlobCore
* b
= it
->second
;
232 result
->mIndex
[n
].offset
= pc
;
233 memcpy(result
->template at
<unsigned char>(pc
), b
, b
->length());
234 pc
+= ((b
->length() + 3) & (-4)); // 4-byte align each element
237 result
->mIndex
[n
].offset
= 0;
241 //secdebug("superblob", "Maker %p assembles %ld blob(s) into %p (size=%d)",
242 // this, mPieces.size(), result, total);
249 #endif //_H_SUPERBLOB