| Nick Kledzik | abb6981 | 2012-05-31 22:34:00 +0000 | [diff] [blame] | 1 | //===- lib/ReaderWriter/Native/NativeFileFormat.h -------------------------===// | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                             The LLVM Linker | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
| Nick Kledzik | abb6981 | 2012-05-31 22:34:00 +0000 | [diff] [blame] | 10 | #ifndef LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_ | 
|  | 11 | #define LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_ | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 12 |  | 
| Michael J. Spencer | 9f91f95 | 2012-03-09 05:27:11 +0000 | [diff] [blame] | 13 | #include "llvm/Support/DataTypes.h" | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 14 |  | 
|  | 15 | namespace lld { | 
|  | 16 |  | 
|  | 17 |  | 
|  | 18 | // | 
|  | 19 | // Overview: | 
|  | 20 | // | 
|  | 21 | // The number one design goal of this file format is enable the linker to | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 22 | // read object files into in-memory Atom objects extremely quickly. | 
|  | 23 | // The second design goal is to enable future modifications to the | 
|  | 24 | // Atom attribute model. | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 25 | // | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 26 | // The llvm native object file format is not like traditional object file | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 27 | // formats (e.g. ELF, COFF, mach-o).  There is no symbol table and no | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 28 | // sections.  Instead the file is essentially an array of archived Atoms. | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 29 | // It is *not* serialized Atoms which would require deserialization into | 
|  | 30 | // in memory objects.  Instead it is an array of read-only info about each | 
|  | 31 | // Atom.  The NativeReader bulk creates in-memory Atoms which just have | 
|  | 32 | // an ivar which points to the read-only info for that Atom. No additional | 
|  | 33 | // processing is done to construct the in-memory Atoms. All Atom attribute | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 34 | // getter methods are virtual calls which dig up the info they need from the | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 35 | // ivar data. | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 36 | // | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 37 | // To support the gradual evolution of Atom attributes, the Atom read-only | 
|  | 38 | // data is versioned. The NativeReader chooses which in-memory Atom class | 
|  | 39 | // to use based on the version. What this means is that if new attributes | 
|  | 40 | // are added (or changed) in the Atom model, a new native atom class and | 
|  | 41 | // read-only atom info struct needs to be defined.  Then, all the existing | 
|  | 42 | // native reader atom classes need to be modified to do their best effort | 
|  | 43 | // to map their old style read-only data to the new Atom model.  At some point | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 44 | // some classes to support old versions may be dropped. | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 45 | // | 
|  | 46 | // | 
|  | 47 | // Details: | 
|  | 48 | // | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 49 | // The native object file format consists of a header that specifies the | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 50 | // endianness of the file and the architecture along with a list of "chunks" | 
|  | 51 | // in the file.  A Chunk is simply a tagged range of the file.  There is | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 52 | // one chunk for the array of atom infos.  There is another chunk for the | 
|  | 53 | // string pool, and another for the content pool. | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 54 | // | 
|  | 55 | // It turns out there most atoms have very similar sets of attributes, only | 
|  | 56 | // the name and content attribute vary. To exploit this fact to reduce the file | 
|  | 57 | // size, the atom read-only info contains just the name and content info plus | 
|  | 58 | // a reference to which attribute set it uses.  The attribute sets are stored | 
|  | 59 | // in another chunk. | 
|  | 60 | // | 
|  | 61 |  | 
|  | 62 |  | 
|  | 63 | // | 
|  | 64 | // An entry in the NativeFileHeader that describes one chunk of the file. | 
|  | 65 | // | 
|  | 66 | struct NativeChunk { | 
|  | 67 | uint32_t    signature; | 
|  | 68 | uint32_t    fileOffset; | 
|  | 69 | uint32_t    fileSize; | 
|  | 70 | uint32_t    elementCount; | 
|  | 71 | }; | 
|  | 72 |  | 
|  | 73 |  | 
|  | 74 | // | 
|  | 75 | // The header in a native object file | 
|  | 76 | // | 
|  | 77 | struct NativeFileHeader { | 
|  | 78 | uint8_t     magic[16]; | 
|  | 79 | uint32_t    endian; | 
|  | 80 | uint32_t    architecture; | 
|  | 81 | uint32_t    fileSize; | 
|  | 82 | uint32_t    chunkCount; | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 83 | // NativeChunk chunks[] | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 84 | }; | 
|  | 85 |  | 
|  | 86 | // | 
|  | 87 | // Possible values for NativeChunk.signature field | 
|  | 88 | // | 
|  | 89 | enum NativeChunkSignatures { | 
|  | 90 | NCS_DefinedAtomsV1 = 1, | 
|  | 91 | NCS_AttributesArrayV1 = 2, | 
| Sid Manning | 2a59024 | 2012-10-18 17:16:19 +0000 | [diff] [blame] | 92 | NCS_AbsoluteAttributesV1 = 12, | 
| Nick Kledzik | 23384e8 | 2012-02-07 02:59:54 +0000 | [diff] [blame] | 93 | NCS_UndefinedAtomsV1 = 3, | 
| Nick Kledzik | 6bc04c6 | 2012-02-22 21:56:59 +0000 | [diff] [blame] | 94 | NCS_SharedLibraryAtomsV1 = 4, | 
|  | 95 | NCS_AbsoluteAtomsV1 = 5, | 
|  | 96 | NCS_Strings = 6, | 
|  | 97 | NCS_ReferencesArrayV1 = 7, | 
|  | 98 | NCS_ReferencesArrayV2 = 8, | 
|  | 99 | NCS_TargetsTable = 9, | 
|  | 100 | NCS_AddendsTable = 10, | 
|  | 101 | NCS_Content = 11, | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 102 | }; | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 103 |  | 
|  | 104 | // | 
|  | 105 | // The 16-bytes at the start of a native object file | 
|  | 106 | // | 
|  | 107 | #define NATIVE_FILE_HEADER_MAGIC "llvm nat obj v1 " | 
|  | 108 |  | 
|  | 109 | // | 
|  | 110 | // Possible values for the NativeFileHeader.endian field | 
|  | 111 | // | 
|  | 112 | enum { | 
|  | 113 | NFH_BigEndian     = 0x42696745, | 
|  | 114 | NFH_LittleEndian  = 0x4574696c | 
|  | 115 | }; | 
|  | 116 |  | 
|  | 117 |  | 
|  | 118 | // | 
|  | 119 | // Possible values for the NativeFileHeader.architecture field | 
|  | 120 | // | 
|  | 121 | enum { | 
|  | 122 | NFA_x86     = 1, | 
|  | 123 | NFA_x86_64  = 2, | 
|  | 124 | NFA_armv6   = 3, | 
|  | 125 | NFA_armv7   = 4, | 
|  | 126 | }; | 
|  | 127 |  | 
|  | 128 |  | 
|  | 129 | // | 
|  | 130 | // The NCS_DefinedAtomsV1 chunk contains an array of these structs | 
|  | 131 | // | 
|  | 132 | struct NativeDefinedAtomIvarsV1 { | 
|  | 133 | uint32_t  nameOffset; | 
|  | 134 | uint32_t  attributesOffset; | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 135 | uint32_t  referencesStartIndex; | 
|  | 136 | uint32_t  referencesCount; | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 137 | uint32_t  contentOffset; | 
|  | 138 | uint32_t  contentSize; | 
|  | 139 | }; | 
|  | 140 |  | 
|  | 141 |  | 
|  | 142 | // | 
|  | 143 | // The NCS_AttributesArrayV1 chunk contains an array of these structs | 
|  | 144 | // | 
|  | 145 | struct NativeAtomAttributesV1 { | 
|  | 146 | uint32_t  sectionNameOffset; | 
|  | 147 | uint16_t  align2; | 
|  | 148 | uint16_t  alignModulus; | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 149 | uint8_t   scope; | 
|  | 150 | uint8_t   interposable; | 
|  | 151 | uint8_t   merge; | 
|  | 152 | uint8_t   contentType; | 
| Nick Kledzik | 36293f6 | 2013-01-23 22:32:56 +0000 | [diff] [blame] | 153 | uint8_t   sectionChoiceAndPosition; // high nibble is choice, low is position | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 154 | uint8_t   deadStrip; | 
|  | 155 | uint8_t   permissions; | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 156 | uint8_t   alias; | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 157 | }; | 
|  | 158 |  | 
|  | 159 |  | 
|  | 160 |  | 
| Nick Kledzik | 23384e8 | 2012-02-07 02:59:54 +0000 | [diff] [blame] | 161 | // | 
|  | 162 | // The NCS_UndefinedAtomsV1 chunk contains an array of these structs | 
|  | 163 | // | 
|  | 164 | struct NativeUndefinedAtomIvarsV1 { | 
|  | 165 | uint32_t  nameOffset; | 
|  | 166 | uint32_t  flags; | 
| Rui Ueyama | e5416ec | 2013-09-12 19:14:05 +0000 | [diff] [blame] | 167 | uint32_t  fallbackNameOffset; | 
| Nick Kledzik | 23384e8 | 2012-02-07 02:59:54 +0000 | [diff] [blame] | 168 | }; | 
|  | 169 |  | 
|  | 170 |  | 
| Nick Kledzik | 6bc04c6 | 2012-02-22 21:56:59 +0000 | [diff] [blame] | 171 | // | 
|  | 172 | // The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs | 
|  | 173 | // | 
|  | 174 | struct NativeSharedLibraryAtomIvarsV1 { | 
| Michael J. Spencer | 4355bb9 | 2013-09-26 22:08:43 +0000 | [diff] [blame^] | 175 | uint64_t  size; | 
| Nick Kledzik | 6bc04c6 | 2012-02-22 21:56:59 +0000 | [diff] [blame] | 176 | uint32_t  nameOffset; | 
|  | 177 | uint32_t  loadNameOffset; | 
| Michael J. Spencer | 4355bb9 | 2013-09-26 22:08:43 +0000 | [diff] [blame^] | 178 | uint32_t  type; | 
| Nick Kledzik | 6bc04c6 | 2012-02-22 21:56:59 +0000 | [diff] [blame] | 179 | uint32_t  flags; | 
|  | 180 | }; | 
|  | 181 |  | 
|  | 182 |  | 
|  | 183 |  | 
|  | 184 | // | 
|  | 185 | // The NCS_AbsoluteAtomsV1 chunk contains an array of these structs | 
|  | 186 | // | 
|  | 187 | struct NativeAbsoluteAtomIvarsV1 { | 
|  | 188 | uint32_t  nameOffset; | 
| Sid Manning | 2a59024 | 2012-10-18 17:16:19 +0000 | [diff] [blame] | 189 | uint32_t  attributesOffset; | 
| Nick Kledzik | 6bc04c6 | 2012-02-22 21:56:59 +0000 | [diff] [blame] | 190 | uint32_t  reserved; | 
|  | 191 | uint64_t  value; | 
|  | 192 | }; | 
|  | 193 |  | 
|  | 194 |  | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 195 |  | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 196 | // | 
|  | 197 | // The NCS_ReferencesArrayV1 chunk contains an array of these structs | 
|  | 198 | // | 
|  | 199 | struct NativeReferenceIvarsV1 { | 
| Nick Kledzik | b334be1 | 2012-04-07 01:31:00 +0000 | [diff] [blame] | 200 | enum { | 
|  | 201 | noTarget = 0xFFFF | 
|  | 202 | }; | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 203 | uint16_t  offsetInAtom; | 
|  | 204 | int16_t  kind; | 
|  | 205 | uint16_t  targetIndex; | 
|  | 206 | uint16_t  addendIndex; | 
|  | 207 | }; | 
|  | 208 |  | 
|  | 209 |  | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 210 | // | 
|  | 211 | // The NCS_ReferencesArrayV2 chunk contains an array of these structs | 
|  | 212 | // | 
|  | 213 | struct NativeReferenceIvarsV2 { | 
|  | 214 | uint64_t  offsetInAtom; | 
|  | 215 | int64_t   addend; | 
|  | 216 | int32_t   kind; | 
|  | 217 | uint32_t  targetIndex; | 
|  | 218 | }; | 
|  | 219 |  | 
|  | 220 |  | 
|  | 221 | // | 
|  | 222 | // The NCS_TargetsTable chunk contains an array of uint32_t entries. | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 223 | // The C++ class Reference has a target() method that returns a | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 224 | // pointer to another Atom.  We can't have pointers in object files, | 
|  | 225 | // so instead  NativeReferenceIvarsV1 contains an index to the target. | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 226 | // The index is into this NCS_TargetsTable of uint32_t entries. | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 227 | // The values in this table are the index of the (target) atom in this file. | 
|  | 228 | // For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount. | 
|  | 229 | // For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to | 
|  | 230 | // NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount. | 
|  | 231 | // | 
|  | 232 |  | 
|  | 233 |  | 
|  | 234 | // | 
|  | 235 | // The NCS_AddendsTable chunk contains an array of int64_t entries. | 
|  | 236 | // If we allocated space for addends directly in NativeReferenceIvarsV1 | 
|  | 237 | // it would double the size of that struct.  But since addends are rare, | 
|  | 238 | // we instead just keep a pool of addends and have NativeReferenceIvarsV1 | 
| Michael J. Spencer | 765792d | 2012-04-03 18:40:27 +0000 | [diff] [blame] | 239 | // (if it needs an addend) just store the index (into the pool) of the | 
| Nick Kledzik | 49d6cc8 | 2012-02-15 00:38:09 +0000 | [diff] [blame] | 240 | // addend it needs. | 
|  | 241 | // | 
|  | 242 |  | 
| Nick Kledzik | 55fd6be | 2012-01-16 22:03:44 +0000 | [diff] [blame] | 243 |  | 
|  | 244 |  | 
|  | 245 | } // namespace lld | 
|  | 246 |  | 
| Nick Kledzik | abb6981 | 2012-05-31 22:34:00 +0000 | [diff] [blame] | 247 | #endif // LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_ |