+error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
+ Res = PE32Header;
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getDataDirectory(uint32_t Index,
+ const data_directory *&Res) const {
+ // Error if if there's no data directory or the index is out of range.
+ if (!DataDirectory || Index > PE32Header->NumberOfRvaAndSize)
+ return object_error::parse_failed;
+ Res = &DataDirectory[Index];
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getSection(int32_t Index,
+ const coff_section *&Result) const {
+ // Check for special index values.
+ if (Index == COFF::IMAGE_SYM_UNDEFINED ||
+ Index == COFF::IMAGE_SYM_ABSOLUTE ||
+ Index == COFF::IMAGE_SYM_DEBUG)
+ Result = NULL;
+ else if (Index > 0 && Index <= COFFHeader->NumberOfSections)
+ // We already verified the section table data, so no need to check again.
+ Result = SectionTable + (Index - 1);
+ else
+ return object_error::parse_failed;
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getString(uint32_t Offset,
+ StringRef &Result) const {
+ if (StringTableSize <= 4)
+ // Tried to get a string from an empty string table.
+ return object_error::parse_failed;
+ if (Offset >= StringTableSize)
+ return object_error::unexpected_eof;
+ Result = StringRef(StringTable + Offset);
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getSymbol(uint32_t Index,
+ const coff_symbol *&Result) const {
+ if (Index < COFFHeader->NumberOfSymbols)
+ Result = SymbolTable + Index;
+ else
+ return object_error::parse_failed;
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol,
+ StringRef &Res) const {
+ // Check for string table entry. First 4 bytes are 0.
+ if (Symbol->Name.Offset.Zeroes == 0) {
+ uint32_t Offset = Symbol->Name.Offset.Offset;
+ if (error_code EC = getString(Offset, Res))
+ return EC;
+ return object_error::success;
+ }
+
+ if (Symbol->Name.ShortName[7] == 0)
+ // Null terminated, let ::strlen figure out the length.
+ Res = StringRef(Symbol->Name.ShortName);
+ else
+ // Not null terminated, use all 8 bytes.
+ Res = StringRef(Symbol->Name.ShortName, 8);
+ return object_error::success;
+}
+
+ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData(
+ const coff_symbol *Symbol) const {
+ const uint8_t *Aux = NULL;
+
+ if (Symbol->NumberOfAuxSymbols > 0) {
+ // AUX data comes immediately after the symbol in COFF
+ Aux = reinterpret_cast<const uint8_t *>(Symbol + 1);
+# ifndef NDEBUG
+ // Verify that the Aux symbol points to a valid entry in the symbol table.
+ uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base());
+ if (Offset < COFFHeader->PointerToSymbolTable
+ || Offset >= COFFHeader->PointerToSymbolTable
+ + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
+ report_fatal_error("Aux Symbol data was outside of symbol table.");
+
+ assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
+ == 0 && "Aux Symbol data did not point to the beginning of a symbol");
+# endif
+ }
+ return ArrayRef<uint8_t>(Aux,
+ Symbol->NumberOfAuxSymbols * sizeof(coff_symbol));
+}
+
+error_code COFFObjectFile::getSectionName(const coff_section *Sec,
+ StringRef &Res) const {
+ StringRef Name;
+ if (Sec->Name[7] == 0)
+ // Null terminated, let ::strlen figure out the length.
+ Name = Sec->Name;
+ else
+ // Not null terminated, use all 8 bytes.
+ Name = StringRef(Sec->Name, 8);
+
+ // Check for string table entry. First byte is '/'.
+ if (Name[0] == '/') {
+ uint32_t Offset;
+ if (Name.substr(1).getAsInteger(10, Offset))
+ return object_error::parse_failed;
+ if (error_code EC = getString(Offset, Name))
+ return EC;
+ }
+
+ Res = Name;
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getSectionContents(const coff_section *Sec,
+ ArrayRef<uint8_t> &Res) const {
+ // The only thing that we need to verify is that the contents is contained
+ // within the file bounds. We don't need to make sure it doesn't cover other
+ // data, as there's nothing that says that is not allowed.
+ uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
+ uintptr_t ConEnd = ConStart + Sec->SizeOfRawData;
+ if (ConEnd > uintptr_t(Data->getBufferEnd()))
+ return object_error::parse_failed;
+ Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart),
+ Sec->SizeOfRawData);
+ return object_error::success;
+}
+
+const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
+ return reinterpret_cast<const coff_relocation*>(Rel.p);
+}
+
+error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
+ RelocationRef &Res) const {
+ Rel.p = reinterpret_cast<uintptr_t>(
+ reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
+ Res = RelocationRef(Rel, this);
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
+ uint64_t &Res) const {
+ report_fatal_error("getRelocationAddress not implemented in COFFObjectFile");
+}
+
+error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel,
+ uint64_t &Res) const {
+ Res = toRel(Rel)->VirtualAddress;
+ return object_error::success;
+}
+
+symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
+ const coff_relocation* R = toRel(Rel);
+ DataRefImpl Ref;
+ Ref.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
+ return symbol_iterator(SymbolRef(Ref, this));
+}
+
+error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
+ uint64_t &Res) const {
+ const coff_relocation* R = toRel(Rel);
+ Res = R->Type;
+ return object_error::success;
+}
+
+const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const {
+ return toSec(It->getRawDataRefImpl());
+}
+
+const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const {
+ return toSymb(It->getRawDataRefImpl());
+}
+
+const coff_relocation *COFFObjectFile::getCOFFRelocation(
+ relocation_iterator &It) const {
+ return toRel(It->getRawDataRefImpl());
+}
+
+#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
+ case COFF::enum: Res = #enum; break;
+
+error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const {
+ const coff_relocation *Reloc = toRel(Rel);
+ StringRef Res;
+ switch (COFFHeader->Machine) {
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ switch (Reloc->Type) {
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
+ default:
+ Res = "Unknown";
+ }
+ break;
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ switch (Reloc->Type) {
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
+ LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
+ default:
+ Res = "Unknown";
+ }
+ break;
+ default:
+ Res = "Unknown";
+ }
+ Result.append(Res.begin(), Res.end());
+ return object_error::success;
+}
+
+#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
+
+error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
+ SmallVectorImpl<char> &Result) const {
+ const coff_relocation *Reloc = toRel(Rel);
+ const coff_symbol *Symb = 0;
+ if (error_code EC = getSymbol(Reloc->SymbolTableIndex, Symb)) return EC;
+ DataRefImpl Sym;
+ Sym.p = reinterpret_cast<uintptr_t>(Symb);
+ StringRef SymName;
+ if (error_code EC = getSymbolName(Sym, SymName)) return EC;
+ Result.append(SymName.begin(), SymName.end());
+ return object_error::success;
+}
+
+error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData,
+ LibraryRef &Result) const {
+ report_fatal_error("getLibraryNext not implemented in COFFObjectFile");
+}
+
+error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData,
+ StringRef &Result) const {
+ report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
+}
+
+bool ImportDirectoryEntryRef::
+operator==(const ImportDirectoryEntryRef &Other) const {
+ return ImportTable == Other.ImportTable && Index == Other.Index;
+}