//===--- swift-reflection-test.cpp - Reflection testing application -------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // This is a host-side tool to dump remote reflection sections in swift // binaries. //===----------------------------------------------------------------------===// #include "swift/ABI/MetadataValues.h" #include "swift/Basic/Demangle.h" #include "swift/Basic/LLVMInitialize.h" #include "swift/Reflection/ReflectionContext.h" #include "swift/Reflection/TypeRef.h" #include "llvm/Object/Archive.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ELF.h" #include "llvm/Support/CommandLine.h" #include #include #include #include using llvm::dyn_cast; using llvm::StringRef; using llvm::ArrayRef; using namespace llvm::object; using namespace swift; using namespace reflection; using namespace Demangle; enum class ActionType { None, DumpReflectionSections, DumpHeapInstance }; namespace options { static llvm::cl::opt Action(llvm::cl::desc("Mode:"), llvm::cl::values( clEnumValN(ActionType::DumpReflectionSections, "dump-reflection-sections", "Dump the field reflection section"), clEnumValN(ActionType::DumpHeapInstance, "dump-heap-instance", "Dump the field layout for a heap instance by running " "a Swift executable"), clEnumValEnd)); static llvm::cl::opt BinaryFilename("binary-filename", llvm::cl::desc("Filename of the binary file"), llvm::cl::Required); static llvm::cl::opt Architecture("arch", llvm::cl::desc("Architecture to inspect in the binary"), llvm::cl::Required); } // end namespace options static void guardError(std::error_code error) { if (!error) return; std::cerr << "swift-reflection-test error: " << error.message() << "\n"; exit(EXIT_FAILURE); } static llvm::object::SectionRef getSectionRef(const ObjectFile *objectFile, ArrayRef anySectionNames) { for (auto section : objectFile->sections()) { StringRef sectionName; section.getName(sectionName); for (auto desiredName : anySectionNames) { if (sectionName.equals(desiredName)) { return section; } } } return llvm::object::SectionRef(); } static llvm::object::SectionRef getSectionRef(const Binary *binaryFile, StringRef arch, ArrayRef anySectionNames) { if (auto objectFile = dyn_cast(binaryFile)) return getSectionRef(objectFile, anySectionNames); if (auto machoUniversal = dyn_cast(binaryFile)) { const auto objectOrError = machoUniversal->getObjectForArch(arch); guardError(objectOrError.getError()); return getSectionRef(objectOrError.get().get(), anySectionNames); } return SectionRef(); } static int doDumpReflectionSections(std::string BinaryFilename, StringRef arch) { auto binaryOrError = llvm::object::createBinary(BinaryFilename); guardError(binaryOrError.getError()); const auto binary = binaryOrError.get().getBinary(); auto FieldSectionRef = getSectionRef(binary, arch, { "__swift3_fieldmd", ".swift3_fieldmd" }); if (FieldSectionRef.getObject() == nullptr) { std::cerr << BinaryFilename; std::cerr << " doesn't have a field reflection section!\n"; return EXIT_FAILURE; } auto AssociatedTypeSectionRef = getSectionRef(binary, arch, { "__swift3_assocty", ".swift3_assocty" }); if (AssociatedTypeSectionRef.getObject() == nullptr) { std::cerr << BinaryFilename; std::cerr << " doesn't have an associated type reflection section!\n"; return EXIT_FAILURE; } auto ReflectionStringsSectionRef = getSectionRef(binary, arch, { "__swift3_reflstr", ".swift3_reflstr" }); if (ReflectionStringsSectionRef.getObject() == nullptr) { std::cerr << BinaryFilename; std::cerr << " doesn't have an associated reflection strings section!\n"; return EXIT_FAILURE; } auto TypeRefSectionRef = getSectionRef(binary, arch, { "__swift3_typeref", ".swift3_typeref" }); if (TypeRefSectionRef.getObject() == nullptr) { std::cerr << BinaryFilename; std::cerr << " doesn't have an associated typeref section!\n"; return EXIT_FAILURE; } StringRef FieldSectionContents; FieldSectionRef.getContents(FieldSectionContents); const FieldSection fieldSection { reinterpret_cast(FieldSectionContents.begin()), reinterpret_cast(FieldSectionContents.end()) }; StringRef AssociatedTypeSectionContents; AssociatedTypeSectionRef.getContents(AssociatedTypeSectionContents); const AssociatedTypeSection associatedTypeSection { reinterpret_cast(AssociatedTypeSectionContents.begin()), reinterpret_cast(AssociatedTypeSectionContents.end()) }; StringRef ReflectionStringsSectionContents; ReflectionStringsSectionRef.getContents(ReflectionStringsSectionContents); const GenericSection ReflectionStringsSection { reinterpret_cast(ReflectionStringsSectionContents.begin()), reinterpret_cast(ReflectionStringsSectionContents.end()) }; StringRef TypeRefSectionContents; AssociatedTypeSectionRef.getContents(TypeRefSectionContents); const GenericSection TypeRefSection { reinterpret_cast(TypeRefSectionContents.begin()), reinterpret_cast(TypeRefSectionContents.end()) }; InProcessMemoryReader Reader; ReflectionContext>> RC(Reader); RC.addReflectionInfo({ BinaryFilename, fieldSection, associatedTypeSection, ReflectionStringsSection, TypeRefSection, }); RC.dumpAllSections(std::cout); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { llvm::cl::ParseCommandLineOptions(argc, argv, "Swift Reflection Dump\n"); return doDumpReflectionSections(options::BinaryFilename, options::Architecture); }