+ return false;
+}
+
+template <typename A>
+bool MachOChecker<A>::addressIsRebaseSite(pint_t targetAddr)
+{
+ // look at local relocs
+ const macho_relocation_info<P>* const localRelocsEnd = &fLocalRelocations[fLocalRelocationsCount];
+ for (const macho_relocation_info<P>* reloc = fLocalRelocations; reloc < localRelocsEnd; ++reloc) {
+ pint_t relocAddress = reloc->r_address() + this->relocBase();
+ if ( relocAddress == targetAddr )
+ return true;
+ }
+ // look rebase info
+ if ( fDyldInfo != NULL ) {
+ const uint8_t* p = (uint8_t*)fHeader + fDyldInfo->rebase_off();
+ const uint8_t* end = &p[fDyldInfo->rebase_size()];
+
+ uint8_t type = 0;
+ uint64_t segOffset = 0;
+ uint32_t count;
+ uint32_t skip;
+ int segIndex;
+ pint_t segStartAddr = 0;
+ pint_t addr;
+ bool done = false;
+ while ( !done && (p < end) ) {
+ uint8_t immediate = *p & REBASE_IMMEDIATE_MASK;
+ uint8_t opcode = *p & REBASE_OPCODE_MASK;
+ ++p;
+ switch (opcode) {
+ case REBASE_OPCODE_DONE:
+ done = true;
+ break;
+ case REBASE_OPCODE_SET_TYPE_IMM:
+ type = immediate;
+ break;
+ case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
+ segIndex = immediate;
+ segStartAddr = segStartAddress(segIndex);
+ segOffset = read_uleb128(p, end);
+ break;
+ case REBASE_OPCODE_ADD_ADDR_ULEB:
+ segOffset += read_uleb128(p, end);
+ break;
+ case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
+ segOffset += immediate*sizeof(pint_t);
+ break;
+ case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
+ for (int i=0; i < immediate; ++i) {
+ addr = segStartAddr+segOffset;
+ if ( addr == targetAddr )
+ return true;
+ //printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName);
+ segOffset += sizeof(pint_t);
+ }
+ break;
+ case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
+ count = read_uleb128(p, end);
+ for (uint32_t i=0; i < count; ++i) {
+ addr = segStartAddr+segOffset;
+ if ( addr == targetAddr )
+ return true;
+ //printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName);
+ segOffset += sizeof(pint_t);
+ }
+ break;
+ case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
+ addr = segStartAddr+segOffset;
+ if ( addr == targetAddr )
+ return true;
+ //printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName);
+ segOffset += read_uleb128(p, end) + sizeof(pint_t);
+ break;
+ case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
+ count = read_uleb128(p, end);
+ skip = read_uleb128(p, end);
+ for (uint32_t i=0; i < count; ++i) {
+ addr = segStartAddr+segOffset;
+ if ( addr == targetAddr )
+ return true;
+ //printf("%-7s %-16s 0x%08llX %s\n", segName, sectionName(segIndex, segStartAddr+segOffset), segStartAddr+segOffset, typeName);
+ segOffset += skip + sizeof(pint_t);
+ }
+ break;
+ default:
+ throwf("bad rebase opcode %d", *p);
+ }
+ }
+ }
+ return false;
+}
+
+
+template <typename A>
+bool MachOChecker<A>::addressIsBindingSite(pint_t targetAddr)
+{
+ // look at external relocs
+ const macho_relocation_info<P>* const externRelocsEnd = &fExternalRelocations[fExternalRelocationsCount];
+ for (const macho_relocation_info<P>* reloc = fExternalRelocations; reloc < externRelocsEnd; ++reloc) {
+ pint_t relocAddress = reloc->r_address() + this->relocBase();
+ if ( relocAddress == targetAddr )
+ return true;
+ }
+ // look bind info
+ if ( fDyldInfo != NULL ) {
+ const uint8_t* p = (uint8_t*)fHeader + fDyldInfo->bind_off();
+ const uint8_t* end = &p[fDyldInfo->bind_size()];
+
+ uint8_t type = 0;
+ uint64_t segOffset = 0;
+ uint32_t count;
+ uint32_t skip;
+ uint8_t flags;
+ const char* symbolName = NULL;
+ int libraryOrdinal = 0;
+ int segIndex;
+ int64_t addend = 0;
+ pint_t segStartAddr = 0;
+ pint_t addr;
+ bool done = false;
+ while ( !done && (p < end) ) {
+ uint8_t immediate = *p & BIND_IMMEDIATE_MASK;
+ uint8_t opcode = *p & BIND_OPCODE_MASK;
+ ++p;
+ switch (opcode) {
+ case BIND_OPCODE_DONE:
+ done = true;
+ break;
+ case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
+ libraryOrdinal = immediate;
+ break;
+ case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
+ libraryOrdinal = read_uleb128(p, end);
+ break;
+ case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
+ // the special ordinals are negative numbers
+ if ( immediate == 0 )
+ libraryOrdinal = 0;
+ else {
+ int8_t signExtended = BIND_OPCODE_MASK | immediate;
+ libraryOrdinal = signExtended;
+ }
+ break;
+ case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
+ symbolName = (char*)p;
+ while (*p != '\0')
+ ++p;
+ ++p;
+ break;
+ case BIND_OPCODE_SET_TYPE_IMM:
+ type = immediate;
+ break;
+ case BIND_OPCODE_SET_ADDEND_SLEB:
+ addend = read_sleb128(p, end);
+ break;
+ case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
+ segIndex = immediate;
+ segStartAddr = segStartAddress(segIndex);
+ segOffset = read_uleb128(p, end);
+ break;
+ case BIND_OPCODE_ADD_ADDR_ULEB:
+ segOffset += read_uleb128(p, end);
+ break;
+ case BIND_OPCODE_DO_BIND:
+ if ( (segStartAddr+segOffset) == targetAddr )
+ return true;
+ segOffset += sizeof(pint_t);
+ break;
+ case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
+ if ( (segStartAddr+segOffset) == targetAddr )
+ return true;
+ segOffset += read_uleb128(p, end) + sizeof(pint_t);
+ break;
+ case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
+ if ( (segStartAddr+segOffset) == targetAddr )
+ return true;
+ segOffset += immediate*sizeof(pint_t) + sizeof(pint_t);
+ break;
+ case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
+ count = read_uleb128(p, end);
+ skip = read_uleb128(p, end);
+ for (uint32_t i=0; i < count; ++i) {
+ if ( (segStartAddr+segOffset) == targetAddr )
+ return true;
+ segOffset += skip + sizeof(pint_t);
+ }
+ break;
+ default:
+ throwf("bad bind opcode %d", *p);
+ }
+ }
+ }
+ return false;