289 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- lib/ReaderWriter/MachO/NormalizedFile.h ----------------------===//
 | |
| //
 | |
| //                             The LLVM Linker
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| ///
 | |
| /// \file These data structures comprise the "normalized" view of
 | |
| /// mach-o object files. The normalized view is an in-memory only data structure
 | |
| /// which is always in native endianness and pointer size. 
 | |
| ///  
 | |
| /// The normalized view easily converts to and from YAML using YAML I/O. 
 | |
| ///
 | |
| /// The normalized view converts to and from binary mach-o object files using
 | |
| /// the writeBinary() and readBinary() functions.
 | |
| ///
 | |
| /// The normalized view converts to and from lld::Atoms using the 
 | |
| /// normalizedToAtoms() and normalizedFromAtoms().
 | |
| ///
 | |
| /// Overall, the conversion paths available look like:
 | |
| ///
 | |
| ///                 +---------------+  
 | |
| ///                 | binary mach-o |  
 | |
| ///                 +---------------+  
 | |
| ///                        ^
 | |
| ///                        |
 | |
| ///                        v
 | |
| ///                  +------------+         +------+ 
 | |
| ///                  | normalized |   <->   | yaml | 
 | |
| ///                  +------------+         +------+ 
 | |
| ///                        ^
 | |
| ///                        |
 | |
| ///                        v
 | |
| ///                    +-------+ 
 | |
| ///                    | Atoms |
 | |
| ///                    +-------+ 
 | |
| /// 
 | |
| 
 | |
| #include "lld/Core/Error.h"
 | |
| #include "lld/Core/LLVM.h"
 | |
| #include "lld/ReaderWriter/MachOLinkingContext.h"
 | |
| 
 | |
| #include "llvm/ADT/SmallString.h"
 | |
| #include "llvm/ADT/StringRef.h"
 | |
| #include "llvm/Support/Allocator.h"
 | |
| #include "llvm/Support/ErrorOr.h"
 | |
| #include "llvm/Support/MachO.h"
 | |
| #include "llvm/Support/YAMLTraits.h"
 | |
| 
 | |
| #ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
 | |
| #define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
 | |
| 
 | |
| using llvm::BumpPtrAllocator;
 | |
| using llvm::yaml::Hex64;
 | |
| using llvm::yaml::Hex32;
 | |
| using llvm::yaml::Hex8;
 | |
| using llvm::yaml::SequenceTraits;
 | |
| using llvm::MachO::HeaderFileType;
 | |
| using llvm::MachO::BindType;
 | |
| using llvm::MachO::RebaseType;
 | |
| using llvm::MachO::NListType;
 | |
| using llvm::MachO::RelocationInfoType;
 | |
| using llvm::MachO::SectionType;
 | |
| using llvm::MachO::LoadCommandType;
 | |
| using llvm::MachO::ExportSymbolKind;
 | |
| 
 | |
| namespace lld {
 | |
| namespace mach_o {
 | |
| namespace normalized {
 | |
| 
 | |
| 
 | |
| /// The real mach-o relocation record is 8-bytes on disk and is
 | |
| /// encoded in one of two different bit-field patterns.  This
 | |
| /// normalized form has the union of all possible fields.
 | |
| struct Relocation {
 | |
|   Relocation() : offset(0), scattered(false), 
 | |
|                  type(llvm::MachO::GENERIC_RELOC_VANILLA), 
 | |
|                  length(0), pcRel(false), isExtern(false), value(0), 
 | |
|                  symbol(0) { }
 | |
| 
 | |
|   Hex32               offset;
 | |
|   bool                scattered;
 | |
|   RelocationInfoType  type;
 | |
|   uint8_t             length;
 | |
|   bool                pcRel;
 | |
|   bool                isExtern;
 | |
|   Hex32               value;
 | |
|   uint32_t            symbol;
 | |
| };
 | |
| 
 | |
| /// A typedef so that YAML I/O can treat this vector as a sequence.
 | |
| typedef std::vector<Relocation> Relocations;
 | |
| 
 | |
| /// A typedef so that YAML I/O can process the raw bytes in a section.
 | |
| typedef std::vector<Hex8> ContentBytes;
 | |
| 
 | |
| /// A typedef so that YAML I/O can treat indirect symbols as a flow sequence.
 | |
| typedef std::vector<uint32_t> IndirectSymbols;
 | |
| 
 | |
| /// A typedef so that YAML I/O can encode/decode section attributes.
 | |
| LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr);
 | |
| 
 | |
| /// Mach-O has a 32-bit and 64-bit section record.  This normalized form
 | |
| /// can support either kind.
 | |
| struct Section {
 | |
|   Section() : type(llvm::MachO::S_REGULAR), 
 | |
|               attributes(0), alignment(0), address(0) { }
 | |
| 
 | |
|   StringRef       segmentName;
 | |
|   StringRef       sectionName;
 | |
|   SectionType     type;
 | |
|   SectionAttr     attributes;
 | |
|   uint32_t        alignment;
 | |
|   Hex64           address;
 | |
|   ArrayRef<uint8_t> content;
 | |
|   Relocations     relocations;
 | |
|   IndirectSymbols indirectSymbols;
 | |
| };
 | |
| 
 | |
| 
 | |
| /// A typedef so that YAML I/O can encode/decode the scope bits of an nlist.
 | |
| LLVM_YAML_STRONG_TYPEDEF(uint8_t, SymbolScope);
 | |
| 
 | |
| /// A typedef so that YAML I/O can encode/decode the desc bits of an nlist.
 | |
| LLVM_YAML_STRONG_TYPEDEF(uint16_t, SymbolDesc);
 | |
| 
 | |
| /// Mach-O has a 32-bit and 64-bit symbol table entry (nlist), and the symbol
 | |
| /// type and scope and mixed in the same n_type field.  This normalized form
 | |
| /// works for any pointer size and separates out the type and scope. 
 | |
| struct Symbol {
 | |
|   Symbol() : type(llvm::MachO::N_UNDF), scope(0), sect(0), desc(0), value(0) { }
 | |
| 
 | |
|   StringRef     name;
 | |
|   NListType     type;
 | |
|   SymbolScope   scope;
 | |
|   uint8_t       sect;
 | |
|   SymbolDesc    desc;
 | |
|   Hex64         value;
 | |
| };
 | |
| 
 | |
| /// A typedef so that YAML I/O can (de/en)code the protection bits of a segment.
 | |
| LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect);
 | |
| 
 | |
| /// Segments are only used in normalized final linked images (not in relocatable
 | |
| /// object files). They specify how a range of the file is loaded.
 | |
| struct Segment {
 | |
|   StringRef     name;
 | |
|   Hex64         address;
 | |
|   Hex64         size;
 | |
|   VMProtect     access;
 | |
| };
 | |
| 
 | |
| /// Only used in normalized final linked images to specify on which dylibs
 | |
| /// it depends.
 | |
| struct DependentDylib {
 | |
|   StringRef       path;
 | |
|   LoadCommandType kind;
 | |
| };
 | |
| 
 | |
| /// A normalized rebasing entry.  Only used in normalized final linked images.
 | |
| struct RebaseLocation {
 | |
|   Hex32         segOffset;
 | |
|   uint8_t       segIndex;
 | |
|   RebaseType    kind;
 | |
| };
 | |
| 
 | |
| /// A normalized binding entry.  Only used in normalized final linked images.
 | |
| struct BindLocation {
 | |
|   Hex32           segOffset;
 | |
|   uint8_t         segIndex;
 | |
|   BindType        kind;
 | |
|   bool            canBeNull;
 | |
|   int             ordinal;
 | |
|   StringRef       symbolName;
 | |
|   Hex64           addend;
 | |
| };
 | |
| 
 | |
| /// A typedef so that YAML I/O can encode/decode export flags.
 | |
| LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportFlags);
 | |
| 
 | |
| /// A normalized export entry.  Only used in normalized final linked images.
 | |
| struct Export {
 | |
|   StringRef         name;
 | |
|   Hex64             offset;
 | |
|   ExportSymbolKind  kind;
 | |
|   ExportFlags       flags;
 | |
|   Hex32             otherOffset;
 | |
|   StringRef         otherName;
 | |
| };
 | |
| 
 | |
| 
 | |
| /// A typedef so that YAML I/O can encode/decode mach_header.flags.
 | |
| LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags);
 | |
| 
 | |
| /// 
 | |
| struct NormalizedFile {
 | |
|   NormalizedFile() : arch(MachOLinkingContext::arch_unknown), 
 | |
|                      fileType(llvm::MachO::MH_OBJECT),
 | |
|                      flags(0), 
 | |
|                      hasUUID(false), 
 | |
|                      os(MachOLinkingContext::OS::unknown) { }
 | |
|   
 | |
|   MachOLinkingContext::Arch   arch;
 | |
|   HeaderFileType              fileType;
 | |
|   FileFlags                   flags;
 | |
|   std::vector<Segment>        segments; // Not used in object files.
 | |
|   std::vector<Section>        sections;
 | |
|   
 | |
|   // Symbols sorted by kind.
 | |
|   std::vector<Symbol>         localSymbols;
 | |
|   std::vector<Symbol>         globalSymbols;
 | |
|   std::vector<Symbol>         undefinedSymbols;
 | |
|   
 | |
|   // Maps to load commands with no LINKEDIT content (final linked images only).
 | |
|   std::vector<DependentDylib> dependentDylibs;
 | |
|   StringRef                   installName;
 | |
|   bool                        hasUUID;
 | |
|   std::vector<StringRef>      rpaths;
 | |
|   Hex64                       entryAddress;
 | |
|   MachOLinkingContext::OS     os;
 | |
|   Hex64                       sourceVersion;
 | |
|   Hex32                       minOSverson;
 | |
|   Hex32                       sdkVersion;
 | |
|     
 | |
|   // Maps to load commands with LINKEDIT content (final linked images only).
 | |
|   std::vector<RebaseLocation> rebasingInfo;
 | |
|   std::vector<BindLocation>   bindingInfo;
 | |
|   std::vector<BindLocation>   weakBindingInfo;
 | |
|   std::vector<BindLocation>   lazyBindingInfo;
 | |
|   std::vector<Export>         exportInfo;
 | |
|   
 | |
|   // TODO:
 | |
|   // code-signature
 | |
|   // split-seg-info
 | |
|   // function-starts
 | |
|   // data-in-code
 | |
|   
 | |
|   // For any allocations in this struct which need to be owned by this struct.
 | |
|   BumpPtrAllocator            ownedAllocations;
 | |
| };
 | |
| 
 | |
| 
 | |
| /// Reads a mach-o file and produces an in-memory normalized view.
 | |
| ErrorOr<std::unique_ptr<NormalizedFile>>
 | |
| readBinary(std::unique_ptr<MemoryBuffer> &mb,
 | |
|            const MachOLinkingContext::Arch arch);
 | |
| 
 | |
| /// Takes in-memory normalized view and writes a mach-o object file.
 | |
| error_code 
 | |
| writeBinary(const NormalizedFile &file, StringRef path);
 | |
| 
 | |
| size_t headerAndLoadCommandsSize(const NormalizedFile &file);
 | |
| 
 | |
| 
 | |
| /// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
 | |
| ErrorOr<std::unique_ptr<NormalizedFile>> 
 | |
| readYaml(std::unique_ptr<MemoryBuffer> &mb);
 | |
| 
 | |
| /// Writes a yaml encoded mach-o files given an in-memory normalized view.
 | |
| error_code 
 | |
| writeYaml(const NormalizedFile &file, raw_ostream &out);
 | |
| 
 | |
| 
 | |
| /// Takes in-memory normalized dylib or object and parses it into lld::File
 | |
| ErrorOr<std::unique_ptr<lld::File>>
 | |
| normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path, 
 | |
|                   bool copyRefs);
 | |
| 
 | |
| /// Takes atoms and generates a normalized macho-o view.
 | |
| ErrorOr<std::unique_ptr<NormalizedFile>> 
 | |
| normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
 | |
| 
 | |
| 
 | |
| } // namespace normalized
 | |
| 
 | |
| /// Class for interfacing mach-o yaml files into generic yaml parsing
 | |
| class MachOYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
 | |
|   bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const;
 | |
| };
 | |
| 
 | |
| 
 | |
| } // namespace mach_o
 | |
| } // namespace lld
 | |
| 
 | |
| #endif // LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
 |