+ try {
+ this->validateNonResourceComponents(); // also validates the CodeDirectory
+ if (!(flags & kSecCSDoNotValidateExecutable))
+ this->validateExecutable();
+ if (req)
+ this->validateRequirement(req->requirement(), errSecCSReqFailed);
+ } catch (CSError &err) {
+ if (Universal *fat = this->diskRep()->mainExecutableImage()) // Mach-O
+ if (MachO *mach = fat->architecture()) {
+ err.augment(kSecCFErrorArchitecture, CFTempString(mach->architecture().displayName()));
+ delete mach;
+ }
+ throw;
+ } catch (const MacOSError &err) {
+ // add architecture information if we can get it
+ if (Universal *fat = this->diskRep()->mainExecutableImage())
+ if (MachO *mach = fat->architecture()) {
+ CFTempString arch(mach->architecture().displayName());
+ delete mach;
+ CSError::throwMe(err.error, kSecCFErrorArchitecture, arch);
+ }
+ throw;
+ }
+}
+
+
+//
+// A helper that generates SecStaticCode objects for all but the primary architecture
+// of a fat binary and calls a block on them.
+// If there's only one architecture (or this is an architecture-agnostic code),
+// nothing happens quickly.
+//
+void SecStaticCode::handleOtherArchitectures(void (^handle)(SecStaticCode* other))
+{
+ if (Universal *fat = this->diskRep()->mainExecutableImage()) {
+ Universal::Architectures architectures;
+ fat->architectures(architectures);
+ if (architectures.size() > 1) {
+ DiskRep::Context ctx;
+ size_t activeOffset = fat->archOffset();
+ for (Universal::Architectures::const_iterator arch = architectures.begin(); arch != architectures.end(); ++arch) {
+ ctx.offset = fat->archOffset(*arch);
+ if (ctx.offset != activeOffset) { // inactive architecture; check it
+ SecPointer<SecStaticCode> subcode = new SecStaticCode(DiskRep::bestGuess(this->mainExecutablePath(), &ctx));
+ subcode->detachedSignature(this->mDetachedSig); // carry over explicit (but not implicit) detached signature
+ handle(subcode);
+ }