1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-* 
   3  * Copyright (c) 2009 Apple Inc. All rights reserved. 
   5  * @APPLE_LICENSE_HEADER_START@ 
   7  * This file contains Original Code and/or Modifications of Original Code 
   8  * as defined in and that are subject to the Apple Public Source License 
   9  * Version 2.0 (the 'License'). You may not use this file except in 
  10  * compliance with the License. Please obtain a copy of the License at 
  11  * http://www.opensource.apple.com/apsl/ and read it before using this 
  14  * The Original Code and all software distributed under the License are 
  15  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  16  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  17  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  18  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  19  * Please see the License for the specific language governing rights and 
  20  * limitations under the License. 
  22  * @APPLE_LICENSE_HEADER_END@ 
  25 #ifndef __OUTPUT_FILE_H__ 
  26 #define __OUTPUT_FILE_H__ 
  29 #include <sys/types.h> 
  32 #include <sys/sysctl.h> 
  37 #include <mach/mach_time.h> 
  38 #include <mach/vm_statistics.h> 
  39 #include <mach/mach_init.h> 
  40 #include <mach/mach_host.h> 
  42 #include <mach-o/dyld.h> 
  55                                                                 OutputFile(const Options
& opts
); 
  58         // iterates all atoms in initial files 
  59         void                                            write(ld::Internal
&); 
  60         bool                                            findSegment(ld::Internal
& state
, uint64_t addr
, uint64_t* start
, uint64_t* end
, uint32_t* index
); 
  61         void                                            setLazyBindingInfoOffset(uint64_t lpAddress
, uint32_t lpInfoOffset
); 
  62         uint32_t                                        dylibCount(); 
  63         const ld::dylib::File
*          dylibByOrdinal(unsigned int ordinal
); 
  64         uint32_t                                        dylibToOrdinal(const ld::dylib::File
*); 
  65         uint32_t                                        encryptedTextStartOffset()      { return _encryptedTEXTstartOffset
; } 
  66         uint32_t                                        encryptedTextEndOffset()        { return _encryptedTEXTendOffset
; } 
  67         int                                                     compressedOrdinalForAtom(const ld::Atom
* target
); 
  71         bool                                            hasWeakExternalSymbols
; 
  72         bool                                            usesWeakExternalSymbols
; 
  73         bool                                            overridesWeakExternalSymbols
; 
  74         bool                                            _noReExportedDylibs
; 
  75         bool                                            hasThreadLocalVariableDefinitions
; 
  77         ld::Internal::FinalSection
*     headerAndLoadCommandsSection
; 
  78         ld::Internal::FinalSection
*     rebaseSection
; 
  79         ld::Internal::FinalSection
*     bindingSection
; 
  80         ld::Internal::FinalSection
*     weakBindingSection
; 
  81         ld::Internal::FinalSection
*     lazyBindingSection
; 
  82         ld::Internal::FinalSection
*     exportSection
; 
  83         ld::Internal::FinalSection
*     splitSegInfoSection
; 
  84         ld::Internal::FinalSection
*     functionStartsSection
; 
  85         ld::Internal::FinalSection
*     symbolTableSection
; 
  86         ld::Internal::FinalSection
*     stringPoolSection
; 
  87         ld::Internal::FinalSection
*     localRelocationsSection
; 
  88         ld::Internal::FinalSection
*     externalRelocationsSection
; 
  89         ld::Internal::FinalSection
*     sectionRelocationsSection
; 
  90         ld::Internal::FinalSection
*     indirectSymbolTableSection
; 
  93                                                 RebaseInfo(uint8_t t
, uint64_t addr
) : _type(t
), _address(addr
) {} 
  97                 int operator<(const RebaseInfo
& rhs
) const { 
  98                         // sort by type, then address 
  99                         if ( this->_type 
!= rhs
._type 
) 
 100                                 return  (this->_type 
< rhs
._type 
); 
 101                         return  (this->_address 
< rhs
._address 
); 
 106                                                 BindingInfo(uint8_t t
, int ord
, const char* sym
, bool weak_import
, uint64_t addr
, int64_t add
)  
 107                                                         : _type(t
), _flags(weak_import 
? BIND_SYMBOL_FLAGS_WEAK_IMPORT 
: 0 ), _libraryOrdinal(ord
),  
 108                                                                 _symbolName(sym
), _address(addr
), _addend(add
) {} 
 109                                                 BindingInfo(uint8_t t
, const char* sym
, bool non_weak_definition
, uint64_t addr
, int64_t add
)  
 110                                                         : _type(t
), _flags(non_weak_definition 
? BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 
: 0 ),  
 111                                                          _libraryOrdinal(0), _symbolName(sym
), _address(addr
), _addend(add
) {} 
 115                 const char*             _symbolName
; 
 120                 int operator<(const BindingInfo
& rhs
) const { 
 121                         // sort by library, symbol, type, then address 
 122                         if ( this->_libraryOrdinal 
!= rhs
._libraryOrdinal 
) 
 123                                 return  (this->_libraryOrdinal 
< rhs
._libraryOrdinal 
); 
 124                         if ( this->_symbolName 
!= rhs
._symbolName 
) 
 125                                 return ( strcmp(this->_symbolName
, rhs
._symbolName
) < 0 ); 
 126                         if ( this->_type 
!= rhs
._type 
) 
 127                                 return  (this->_type 
< rhs
._type 
); 
 128                         return  (this->_address 
< rhs
._address 
); 
 132         struct SplitSegInfoEntry 
{ 
 133                                                 SplitSegInfoEntry(uint64_t a
, ld::Fixup::Kind k
) : address(a
), kind(k
) {} 
 135                 ld::Fixup::Kind kind
; 
 139         void                                            buildDylibOrdinalMapping(ld::Internal
&); 
 140         bool                                            hasOrdinalForInstallPath(const char* path
, int* ordinal
); 
 141         void                                            addLoadCommands(ld::Internal
& state
); 
 142         void                                            addLinkEdit(ld::Internal
& state
); 
 143         void                                            addPreloadLinkEdit(ld::Internal
& state
); 
 144         void                                            generateLinkEditInfo(ld::Internal
& state
); 
 145         void                                            buildSymbolTable(ld::Internal
& state
); 
 146         void                                            writeOutputFile(ld::Internal
& state
); 
 147         void                                            assignFileOffsets(ld::Internal
& state
); 
 148         void                                            setSectionSizesAndAlignments(ld::Internal
& state
); 
 149         void                                            addSectionRelocs(ld::Internal
& state
, ld::Internal::FinalSection
* sect
,   
 150                                                                                                 const ld::Atom
* atom
, ld::Fixup
* fixupWithTarget
,  
 151                                                                                                 ld::Fixup
* fixupWithMinusTarget
, ld::Fixup
* fixupWithStore
, 
 152                                                                                                 const ld::Atom
* target
, const ld::Atom
* minusTarget
,  
 153                                                                                                 uint64_t targetAddend
, uint64_t minusTargetAddend
); 
 154         void                                            addDyldInfo(ld::Internal
& state
, ld::Internal::FinalSection
* sect
,   
 155                                                                                                 const ld::Atom
* atom
, ld::Fixup
* fixupWithTarget
, 
 156                                                                                                 ld::Fixup
* fixupWithMinusTarget
, ld::Fixup
* fixupWithStore
, 
 157                                                                                                 const ld::Atom
* target
, const ld::Atom
* minusTarget
,  
 158                                                                                                 uint64_t targetAddend
, uint64_t minusTargetAddend
); 
 159         void                                            addClassicRelocs(ld::Internal
& state
, ld::Internal::FinalSection
* sect
,   
 160                                                                                                 const ld::Atom
* atom
, ld::Fixup
* fixupWithTarget
,  
 161                                                                                                 ld::Fixup
* fixupWithMinusTarget
, ld::Fixup
* fixupWithStore
, 
 162                                                                                                 const ld::Atom
* target
, const ld::Atom
* minusTarget
,  
 163                                                                                                 uint64_t targetAddend
, uint64_t minusTargetAddend
); 
 164         bool                                            useExternalSectionReloc(const ld::Atom
* atom
, const ld::Atom
* target
,  
 165                                                                                                                         ld::Fixup
* fixupWithTarget
); 
 166         uint64_t                                        pageAlign(uint64_t addr
); 
 167         uint64_t                                        pageAlign(uint64_t addr
, uint64_t pageSize
); 
 168         void                                            setLoadCommandsPadding(ld::Internal
& state
); 
 169         void                                            assignAtomAddresses(ld::Internal
& state
); 
 170         void                                            addRebaseInfo(const ld::Atom
* atom
, const ld::Fixup
* fixup
, const ld::Atom
* target
); 
 171         void                                            makeRebasingInfo(ld::Internal
& state
); 
 172         void                                            makeBindingInfo(ld::Internal
& state
); 
 173         void                                            updateLINKEDITAddresses(ld::Internal
& state
); 
 174         void                                            applyFixUps(ld::Internal
& state
, uint64_t mhAddress
, const ld::Atom
*  atom
, uint8_t* buffer
); 
 175         uint64_t                                        addressOf(const ld::Internal
& state
, const ld::Fixup
* fixup
, const ld::Atom
** target
); 
 176         bool                                            targetIsThumb(ld::Internal
& state
, const ld::Fixup
* fixup
); 
 177         uint32_t                                        lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress
); 
 178         void                                            copyNoOps(uint8_t* from
, uint8_t* to
); 
 179         bool                                            isPointerToTarget(ld::Fixup::Kind kind
); 
 180         bool                                            isPointerFromTarget(ld::Fixup::Kind kind
); 
 181         bool                                            isPcRelStore(ld::Fixup::Kind kind
); 
 182         bool                                            isStore(ld::Fixup::Kind kind
); 
 183         bool                                            storeAddendOnly(const ld::Atom
* inAtom
, const ld::Atom
* target
, bool pcRel
=false); 
 184         bool                                            setsTarget(ld::Fixup::Kind kind
); 
 185         void                                            addFixupOutInfo(ld::Internal
& state
); 
 186         void                                            makeRelocations(ld::Internal
& state
); 
 187         void                                            makeSectionRelocations(ld::Internal
& state
); 
 188         void                                            makeDyldInfo(ld::Internal
& state
); 
 189         void                                            makeSplitSegInfo(ld::Internal
& state
); 
 190         void                                            writeMapFile(ld::Internal
& state
); 
 191         uint64_t                                        lookBackAddend(ld::Fixup::iterator fit
); 
 192         bool                                            takesNoDiskSpace(const ld::Section
* sect
); 
 193         bool                                            hasZeroForFileOffset(const ld::Section
* sect
); 
 195         void                                            printSectionLayout(ld::Internal
& state
); 
 196         void                                            rangeCheck8(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 197                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 198         void                                            rangeCheck16(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 199                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 200         void                                            rangeCheckBranch32(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 201                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 202         void                                            rangeCheckRIP32(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 203                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 204         void                                            rangeCheckARM12(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 205                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 206         void                                            rangeCheckARMBranch24(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 207                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 208         void                                            rangeCheckThumbBranch22(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 209                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 210         void                                            rangeCheckPPCBranch24(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 211                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 212         void                                            rangeCheckPPCBranch14(int64_t delta
, ld::Internal
& state
, const ld::Atom
* atom
,  
 213                                                                                                                                                                                         const ld::Fixup
* fixup
); 
 214         uint64_t                                        sectionOffsetOf(const ld::Internal
& state
, const ld::Fixup
* fixup
); 
 215         uint64_t                                        tlvTemplateOffsetOf(const ld::Internal
& state
, const ld::Fixup
* fixup
); 
 216         void                                            dumpAtomsBySection(ld::Internal
& state
, bool); 
 217         void                                            synthesizeDebugNotes(ld::Internal
& state
); 
 218         const char*                                     assureFullPath(const char* path
); 
 219         void                                            noteTextReloc(const ld::Atom
* atom
, const ld::Atom
* target
); 
 222         static uint16_t                         get16LE(uint8_t* loc
); 
 223         static void                                     set16LE(uint8_t* loc
, uint16_t value
); 
 224         static uint32_t                         get32LE(uint8_t* loc
); 
 225         static void                                     set32LE(uint8_t* loc
, uint32_t value
); 
 226         static uint64_t                         get64LE(uint8_t* loc
); 
 227         static void                                     set64LE(uint8_t* loc
, uint64_t value
); 
 229         static uint16_t                         get16BE(uint8_t* loc
); 
 230         static void                                     set16BE(uint8_t* loc
, uint16_t value
); 
 231         static uint32_t                         get32BE(uint8_t* loc
); 
 232         static void                                     set32BE(uint8_t* loc
, uint32_t value
); 
 233         static uint64_t                         get64BE(uint8_t* loc
); 
 234         static void                                     set64BE(uint8_t* loc
, uint64_t value
); 
 238         const Options
&                                                  _options
; 
 239         std::map
<const ld::dylib::File
*, int>   _dylibToOrdinal
; 
 240         std::vector
<const ld::dylib::File
*>             _dylibsToLoad
; 
 241         std::vector
<const char*>                                _dylibOrdinalPaths
; 
 242         const bool                                                              _hasDyldInfo
; 
 243         const bool                                                              _hasSymbolTable
; 
 244         const bool                                                              _hasSectionRelocations
; 
 245         const bool                                                              _hasSplitSegInfo
; 
 246         const bool                                                              _hasFunctionStartsInfo
; 
 247                   bool                                                          _hasDynamicSymbolTable
; 
 248                   bool                                                          _hasLocalRelocations
; 
 249                   bool                                                          _hasExternalRelocations
; 
 251         std::map
<uint64_t, uint32_t>                    _lazyPointerAddressToInfoOffset
; 
 252         uint32_t                                                                _encryptedTEXTstartOffset
; 
 253         uint32_t                                                                _encryptedTEXTendOffset
; 
 255         std::vector
<const ld::Atom
*>                    _localAtoms
; 
 256         std::vector
<const ld::Atom
*>                    _exportedAtoms
; 
 257         std::vector
<const ld::Atom
*>                    _importedAtoms
; 
 258         uint32_t                                                                _localSymbolsStartIndex
; 
 259         uint32_t                                                                _localSymbolsCount
; 
 260         uint32_t                                                                _globalSymbolsStartIndex
; 
 261         uint32_t                                                                _globalSymbolsCount
; 
 262         uint32_t                                                                _importSymbolsStartIndex
; 
 263         uint32_t                                                                _importSymbolsCount
; 
 264         std::map
<const ld::Atom
*, uint32_t>             _atomToSymbolIndex
; 
 265         std::vector
<RebaseInfo
>                                 _rebaseInfo
; 
 266         std::vector
<BindingInfo
>                                _bindingInfo
; 
 267         std::vector
<BindingInfo
>                                _lazyBindingInfo
; 
 268         std::vector
<BindingInfo
>                                _weakBindingInfo
; 
 269         std::vector
<SplitSegInfoEntry
>                  _splitSegInfos
; 
 270         class HeaderAndLoadCommandsAbtract
*             _headersAndLoadCommandAtom
; 
 271         class RelocationsAtomAbstract
*                  _sectionsRelocationsAtom
; 
 272         class RelocationsAtomAbstract
*                  _localRelocsAtom
; 
 273         class RelocationsAtomAbstract
*                  _externalRelocsAtom
; 
 274         class ClassicLinkEditAtom
*                              _symbolTableAtom
; 
 275         class ClassicLinkEditAtom
*                              _indirectSymbolTableAtom
; 
 276         class StringPoolAtom
*                                   _stringPoolAtom
; 
 277         class LinkEditAtom
*                                             _rebasingInfoAtom
; 
 278         class LinkEditAtom
*                                             _bindingInfoAtom
; 
 279         class LinkEditAtom
*                                             _lazyBindingInfoAtom
; 
 280         class LinkEditAtom
*                                             _weakBindingInfoAtom
; 
 281         class LinkEditAtom
*                                             _exportInfoAtom
; 
 282         class LinkEditAtom
*                                             _splitSegInfoAtom
; 
 283         class LinkEditAtom
*                                             _functionStartsAtom
; 
 289 #endif // __OUTPUT_FILE_H__