blob: 45f8347b13b374430ebb97077633e616c80b23f1 [file] [log] [blame]
Nick Kledzike34182f2013-11-06 21:36:55 +00001//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h ------------===//
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
10
11#include "MachONormalizedFile.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000012#include "lld/Core/Error.h"
13#include "lld/Core/LLVM.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000014#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Casting.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/Host.h"
18#include "llvm/Support/MachO.h"
Rafael Espindola54427cc2014-06-12 17:15:58 +000019#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000020
Rui Ueyama014192db2013-11-15 03:09:26 +000021#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
22#define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
Nick Kledzike34182f2013-11-06 21:36:55 +000023
24namespace lld {
25namespace mach_o {
26namespace normalized {
27
28using llvm::sys::SwapByteOrder;
29
30inline void swapStruct(llvm::MachO::mach_header &mh) {
31 mh.magic = SwapByteOrder(mh.magic);
32 mh.cputype = SwapByteOrder(mh.cputype);
33 mh.cpusubtype = SwapByteOrder(mh.cpusubtype);
34 mh.filetype = SwapByteOrder(mh.filetype);
35 mh.ncmds = SwapByteOrder(mh.ncmds);
36 mh.sizeofcmds = SwapByteOrder(mh.sizeofcmds);
37 mh.flags = SwapByteOrder(mh.flags);
38}
39
40inline void swapStruct(llvm::MachO::load_command &lc) {
41 lc.cmd = SwapByteOrder(lc.cmd);
42 lc.cmdsize = SwapByteOrder(lc.cmdsize);
43}
44
45inline void swapStruct(llvm::MachO::symtab_command &lc) {
46 lc.cmd = SwapByteOrder(lc.cmd);
47 lc.cmdsize = SwapByteOrder(lc.cmdsize);
48 lc.symoff = SwapByteOrder(lc.symoff);
49 lc.nsyms = SwapByteOrder(lc.nsyms);
50 lc.stroff = SwapByteOrder(lc.stroff);
51 lc.strsize = SwapByteOrder(lc.strsize);
52}
53
54inline void swapStruct(llvm::MachO::segment_command_64 &seg) {
55 seg.cmd = SwapByteOrder(seg.cmd);
56 seg.cmdsize = SwapByteOrder(seg.cmdsize);
57 seg.vmaddr = SwapByteOrder(seg.vmaddr);
58 seg.vmsize = SwapByteOrder(seg.vmsize);
59 seg.fileoff = SwapByteOrder(seg.fileoff);
60 seg.filesize = SwapByteOrder(seg.filesize);
61 seg.maxprot = SwapByteOrder(seg.maxprot);
62 seg.initprot = SwapByteOrder(seg.initprot);
63 seg.nsects = SwapByteOrder(seg.nsects);
64 seg.flags = SwapByteOrder(seg.flags);
65}
66
67inline void swapStruct(llvm::MachO::segment_command &seg) {
68 seg.cmd = SwapByteOrder(seg.cmd);
69 seg.cmdsize = SwapByteOrder(seg.cmdsize);
70 seg.vmaddr = SwapByteOrder(seg.vmaddr);
71 seg.vmsize = SwapByteOrder(seg.vmsize);
72 seg.fileoff = SwapByteOrder(seg.fileoff);
73 seg.filesize = SwapByteOrder(seg.filesize);
74 seg.maxprot = SwapByteOrder(seg.maxprot);
75 seg.initprot = SwapByteOrder(seg.initprot);
76 seg.nsects = SwapByteOrder(seg.nsects);
77 seg.flags = SwapByteOrder(seg.flags);
78}
79
80inline void swapStruct(llvm::MachO::section_64 &sect) {
81 sect.addr = SwapByteOrder(sect.addr);
82 sect.size = SwapByteOrder(sect.size);
83 sect.offset = SwapByteOrder(sect.offset);
84 sect.align = SwapByteOrder(sect.align);
85 sect.reloff = SwapByteOrder(sect.reloff);
86 sect.nreloc = SwapByteOrder(sect.nreloc);
87 sect.flags = SwapByteOrder(sect.flags);
88 sect.reserved1 = SwapByteOrder(sect.reserved1);
89 sect.reserved2 = SwapByteOrder(sect.reserved2);
90}
91
92inline void swapStruct(llvm::MachO::section &sect) {
93 sect.addr = SwapByteOrder(sect.addr);
94 sect.size = SwapByteOrder(sect.size);
95 sect.offset = SwapByteOrder(sect.offset);
96 sect.align = SwapByteOrder(sect.align);
97 sect.reloff = SwapByteOrder(sect.reloff);
98 sect.nreloc = SwapByteOrder(sect.nreloc);
99 sect.flags = SwapByteOrder(sect.flags);
100 sect.reserved1 = SwapByteOrder(sect.reserved1);
101 sect.reserved2 = SwapByteOrder(sect.reserved2);
102}
103
104inline void swapStruct(llvm::MachO::dyld_info_command &info) {
105 info.cmd = SwapByteOrder(info.cmd);
106 info.cmdsize = SwapByteOrder(info.cmdsize);
107 info.rebase_off = SwapByteOrder(info.rebase_off);
108 info.rebase_size = SwapByteOrder(info.rebase_size);
109 info.bind_off = SwapByteOrder(info.bind_off);
110 info.bind_size = SwapByteOrder(info.bind_size);
111 info.weak_bind_off = SwapByteOrder(info.weak_bind_off);
112 info.weak_bind_size = SwapByteOrder(info.weak_bind_size);
113 info.lazy_bind_off = SwapByteOrder(info.lazy_bind_off);
114 info.lazy_bind_size = SwapByteOrder(info.lazy_bind_size);
115 info.export_off = SwapByteOrder(info.export_off);
116 info.export_size = SwapByteOrder(info.export_size);
117}
118
119inline void swapStruct(llvm::MachO::dylib_command &d) {
120 d.cmd = SwapByteOrder(d.cmd);
121 d.cmdsize = SwapByteOrder(d.cmdsize);
122 d.dylib.name = SwapByteOrder(d.dylib.name);
123 d.dylib.timestamp = SwapByteOrder(d.dylib.timestamp);
124 d.dylib.current_version = SwapByteOrder(d.dylib.current_version);
125 d.dylib.compatibility_version = SwapByteOrder(d.dylib.compatibility_version);
126}
127
128inline void swapStruct(llvm::MachO::dylinker_command &d) {
129 d.cmd = SwapByteOrder(d.cmd);
130 d.cmdsize = SwapByteOrder(d.cmdsize);
131 d.name = SwapByteOrder(d.name);
132}
133
134inline void swapStruct(llvm::MachO::entry_point_command &e) {
135 e.cmd = SwapByteOrder(e.cmd);
136 e.cmdsize = SwapByteOrder(e.cmdsize);
137 e.entryoff = SwapByteOrder(e.entryoff);
138 e.stacksize = SwapByteOrder(e.stacksize);
139}
140
141inline void swapStruct(llvm::MachO::dysymtab_command &dst) {
142 dst.cmd = SwapByteOrder(dst.cmd);
143 dst.cmdsize = SwapByteOrder(dst.cmdsize);
144 dst.ilocalsym = SwapByteOrder(dst.ilocalsym);
145 dst.nlocalsym = SwapByteOrder(dst.nlocalsym);
146 dst.iextdefsym = SwapByteOrder(dst.iextdefsym);
147 dst.nextdefsym = SwapByteOrder(dst.nextdefsym);
148 dst.iundefsym = SwapByteOrder(dst.iundefsym);
149 dst.nundefsym = SwapByteOrder(dst.nundefsym);
150 dst.tocoff = SwapByteOrder(dst.tocoff);
151 dst.ntoc = SwapByteOrder(dst.ntoc);
152 dst.modtaboff = SwapByteOrder(dst.modtaboff);
153 dst.nmodtab = SwapByteOrder(dst.nmodtab);
154 dst.extrefsymoff = SwapByteOrder(dst.extrefsymoff);
155 dst.nextrefsyms = SwapByteOrder(dst.nextrefsyms);
156 dst.indirectsymoff = SwapByteOrder(dst.indirectsymoff);
157 dst.nindirectsyms = SwapByteOrder(dst.nindirectsyms);
158 dst.extreloff = SwapByteOrder(dst.extreloff);
159 dst.nextrel = SwapByteOrder(dst.nextrel);
160 dst.locreloff = SwapByteOrder(dst.locreloff);
161 dst.nlocrel = SwapByteOrder(dst.nlocrel);
162}
163
164
165inline void swapStruct(llvm::MachO::any_relocation_info &reloc) {
166 reloc.r_word0 = SwapByteOrder(reloc.r_word0);
167 reloc.r_word1 = SwapByteOrder(reloc.r_word1);
168}
169
170inline void swapStruct(llvm::MachO::nlist &sym) {
171 sym.n_strx = SwapByteOrder(sym.n_strx);
172 sym.n_desc = SwapByteOrder(sym.n_desc);
173 sym.n_value = SwapByteOrder(sym.n_value);
174}
175
176inline void swapStruct(llvm::MachO::nlist_64 &sym) {
177 sym.n_strx = SwapByteOrder(sym.n_strx);
178 sym.n_desc = SwapByteOrder(sym.n_desc);
179 sym.n_value = SwapByteOrder(sym.n_value);
180}
181
182
183
184
185inline uint32_t read32(bool swap, uint32_t value) {
186 return (swap ? SwapByteOrder(value) : value);
187}
188
189inline uint64_t read64(bool swap, uint64_t value) {
190 return (swap ? SwapByteOrder(value) : value);
191}
192
193
194
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000195inline uint32_t
196bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
Nick Kledzike34182f2013-11-06 21:36:55 +0000197 uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000198 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +0000199 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
200 return (value >> shift) & mask;
201}
202
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000203inline void
204bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
Nick Kledzike34182f2013-11-06 21:36:55 +0000205 uint8_t firstBit, uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000206 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +0000207 assert((newBits & mask) == newBits);
208 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
209 bits &= ~(mask << shift);
210 bits |= (newBits << shift);
211}
212
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000213inline Relocation
214unpackRelocation(const llvm::MachO::any_relocation_info &r, bool swap,
Nick Kledzike34182f2013-11-06 21:36:55 +0000215 bool isBigEndian) {
216 uint32_t r0 = read32(swap, r.r_word0);
217 uint32_t r1 = read32(swap, r.r_word1);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000218
Nick Kledzike34182f2013-11-06 21:36:55 +0000219 Relocation result;
220 if (r0 & llvm::MachO::R_SCATTERED) {
221 // scattered relocation record always laid out like big endian bit field
222 result.offset = bitFieldExtract(r0, true, 8, 24);
223 result.scattered = true;
224 result.type = (RelocationInfoType)
225 bitFieldExtract(r0, true, 4, 4);
226 result.length = bitFieldExtract(r0, true, 2, 2);
227 result.pcRel = bitFieldExtract(r0, true, 1, 1);
228 result.isExtern = false;
229 result.value = r1;
230 result.symbol = 0;
231 } else {
232 result.offset = r0;
233 result.scattered = false;
234 result.type = (RelocationInfoType)
235 bitFieldExtract(r1, isBigEndian, 28, 4);
236 result.length = bitFieldExtract(r1, isBigEndian, 25, 2);
237 result.pcRel = bitFieldExtract(r1, isBigEndian, 24, 1);
238 result.isExtern = bitFieldExtract(r1, isBigEndian, 27, 1);
239 result.value = 0;
240 result.symbol = bitFieldExtract(r1, isBigEndian, 0, 24);
241 }
242 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000243}
Nick Kledzike34182f2013-11-06 21:36:55 +0000244
245
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000246inline llvm::MachO::any_relocation_info
Nick Kledzike34182f2013-11-06 21:36:55 +0000247packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
248 uint32_t r0 = 0;
249 uint32_t r1 = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000250
Nick Kledzike34182f2013-11-06 21:36:55 +0000251 if (r.scattered) {
252 r1 = r.value;
253 bitFieldSet(r0, true, r.offset, 8, 24);
254 bitFieldSet(r0, true, r.type, 4, 4);
255 bitFieldSet(r0, true, r.length, 2, 2);
256 bitFieldSet(r0, true, r.pcRel, 1, 1);
257 bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
258 } else {
259 r0 = r.offset;
260 bitFieldSet(r1, isBigEndian, r.type, 28, 4);
261 bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
262 bitFieldSet(r1, isBigEndian, r.length, 25, 2);
263 bitFieldSet(r1, isBigEndian, r.pcRel, 24, 1);
264 bitFieldSet(r1, isBigEndian, r.symbol, 0, 24);
265 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000266
Nick Kledzike34182f2013-11-06 21:36:55 +0000267 llvm::MachO::any_relocation_info result;
268 result.r_word0 = swap ? SwapByteOrder(r0) : r0;
269 result.r_word1 = swap ? SwapByteOrder(r1) : r1;
270 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000271}
Nick Kledzike34182f2013-11-06 21:36:55 +0000272
273inline StringRef getString16(const char s[16]) {
274 StringRef x = s;
275 if ( x.size() > 16 )
276 return x.substr(0, 16);
277 else
278 return x;
279}
280
281inline void setString16(StringRef str, char s[16]) {
282 memset(s, 0, 16);
283 memcpy(s, str.begin(), (str.size() > 16) ? 16: str.size());
284}
285
Nick Kledzikec140832014-06-10 01:50:00 +0000286// Implemented in normalizedToAtoms() and used by normalizedFromAtoms() so
287// that the same table can be used to map mach-o sections to and from
288// DefinedAtom::ContentType.
289void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
290 StringRef &segmentName,
291 StringRef &sectionName,
292 SectionType &sectionType,
293 SectionAttr &sectionAttrs);
Nick Kledzike34182f2013-11-06 21:36:55 +0000294
295} // namespace normalized
296} // namespace mach_o
297} // namespace lld
298
Rui Ueyama014192db2013-11-15 03:09:26 +0000299#endif // LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H