-relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
- const coff_section *sec = toSec(Sec);
- DataRefImpl ret;
- if (sec->NumberOfRelocations == 0)
- ret.p = 0;
- else
- ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations);
-
- return relocation_iterator(RelocationRef(ret, this));
+relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const {
+ const coff_section *Sec = toSec(Ref);
+ DataRefImpl Ret;
+ if (Sec->NumberOfRelocations == 0) {
+ Ret.p = 0;
+ } else {
+ auto begin = reinterpret_cast<const coff_relocation*>(
+ base() + Sec->PointerToRelocations);
+ if (Sec->hasExtendedRelocations()) {
+ // Skip the first relocation entry repurposed to store the number of
+ // relocations.
+ begin++;
+ }
+ Ret.p = reinterpret_cast<uintptr_t>(begin);
+ }
+ return relocation_iterator(RelocationRef(Ret, this));
+}
+
+static uint32_t getNumberOfRelocations(const coff_section *Sec,
+ const uint8_t *base) {
+ // The field for the number of relocations in COFF section table is only
+ // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to
+ // NumberOfRelocations field, and the actual relocation count is stored in the
+ // VirtualAddress field in the first relocation entry.
+ if (Sec->hasExtendedRelocations()) {
+ auto *FirstReloc = reinterpret_cast<const coff_relocation*>(
+ base + Sec->PointerToRelocations);
+ return FirstReloc->VirtualAddress;
+ }
+ return Sec->NumberOfRelocations;