+}
+
+
+void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer)
+{
+ const bool log = false;
+ if ( (_options.outputKind() != Options::kObjectFile) || state.someObjectFileHasDwarf ) {
+ uint8_t digest[CC_MD5_DIGEST_LENGTH];
+ uint32_t stabsStringsOffsetStart;
+ uint32_t tabsStringsOffsetEnd;
+ uint32_t stabsOffsetStart;
+ uint32_t stabsOffsetEnd;
+ if ( _symbolTableAtom->hasStabs(stabsStringsOffsetStart, tabsStringsOffsetEnd, stabsOffsetStart, stabsOffsetEnd) ) {
+ // find two areas of file that are stabs info and should not contribute to checksum
+ uint64_t stringPoolFileOffset = 0;
+ uint64_t symbolTableFileOffset = 0;
+ for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
+ ld::Internal::FinalSection* sect = *sit;
+ if ( sect->type() == ld::Section::typeLinkEdit ) {
+ if ( strcmp(sect->sectionName(), "__string_pool") == 0 )
+ stringPoolFileOffset = sect->fileOffset;
+ else if ( strcmp(sect->sectionName(), "__symbol_table") == 0 )
+ symbolTableFileOffset = sect->fileOffset;
+ }
+ }
+ uint64_t firstStabNlistFileOffset = symbolTableFileOffset + stabsOffsetStart;
+ uint64_t lastStabNlistFileOffset = symbolTableFileOffset + stabsOffsetEnd;
+ uint64_t firstStabStringFileOffset = stringPoolFileOffset + stabsStringsOffsetStart;
+ uint64_t lastStabStringFileOffset = stringPoolFileOffset + tabsStringsOffsetEnd;
+ if ( log ) fprintf(stderr, "firstStabNlistFileOffset=0x%08llX\n", firstStabNlistFileOffset);
+ if ( log ) fprintf(stderr, "lastStabNlistFileOffset=0x%08llX\n", lastStabNlistFileOffset);
+ if ( log ) fprintf(stderr, "firstStabStringFileOffset=0x%08llX\n", firstStabStringFileOffset);
+ if ( log ) fprintf(stderr, "lastStabStringFileOffset=0x%08llX\n", lastStabStringFileOffset);
+ assert(firstStabNlistFileOffset <= firstStabStringFileOffset);
+
+ CC_MD5_CTX md5state;
+ CC_MD5_Init(&md5state);
+ // checksum everything up to first stabs nlist
+ if ( log ) fprintf(stderr, "checksum 0x%08X -> 0x%08llX\n", 0, firstStabNlistFileOffset);
+ CC_MD5_Update(&md5state, &wholeBuffer[0], firstStabNlistFileOffset);
+ // checkusm everything after last stabs nlist and up to first stabs string
+ if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", lastStabNlistFileOffset, firstStabStringFileOffset);
+ CC_MD5_Update(&md5state, &wholeBuffer[lastStabNlistFileOffset], firstStabStringFileOffset-lastStabNlistFileOffset);
+ // checksum everything after last stabs string to end of file
+ if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", lastStabStringFileOffset, _fileSize);
+ CC_MD5_Update(&md5state, &wholeBuffer[lastStabStringFileOffset], _fileSize-lastStabStringFileOffset);
+ CC_MD5_Final(digest, &md5state);
+ if ( log ) fprintf(stderr, "uuid=%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", digest[0], digest[1], digest[2],
+ digest[3], digest[4], digest[5], digest[6], digest[7]);
+ }
+ else {
+ CC_MD5(wholeBuffer, _fileSize, digest);
+ }
+ // <rdar://problem/6723729> LC_UUID uuids should conform to RFC 4122 UUID version 4 & UUID version 5 formats
+ digest[6] = ( digest[6] & 0x0F ) | ( 3 << 4 );
+ digest[8] = ( digest[8] & 0x3F ) | 0x80;
+ // update buffer with new UUID
+ _headersAndLoadCommandAtom->setUUID(digest);
+ _headersAndLoadCommandAtom->recopyUUIDCommand();
+ }
+}