blob: fcc1879ddc6b4bb8c5e167439a12f4ce55a57f56 [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
Artyom Skrobovf8874b02014-06-14 13:26:14 +000028using llvm::sys::swapByteOrder;
Artyom Skrobov9b3f6472014-06-14 12:14:25 +000029using llvm::sys::getSwappedBytes;
Nick Kledzike34182f2013-11-06 21:36:55 +000030
31inline void swapStruct(llvm::MachO::mach_header &mh) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +000032 swapByteOrder(mh.magic);
33 swapByteOrder(mh.cputype);
34 swapByteOrder(mh.cpusubtype);
35 swapByteOrder(mh.filetype);
36 swapByteOrder(mh.ncmds);
37 swapByteOrder(mh.sizeofcmds);
38 swapByteOrder(mh.flags);
Nick Kledzike34182f2013-11-06 21:36:55 +000039}
40
41inline void swapStruct(llvm::MachO::load_command &lc) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +000042 swapByteOrder(lc.cmd);
43 swapByteOrder(lc.cmdsize);
Nick Kledzike34182f2013-11-06 21:36:55 +000044}
45
46inline void swapStruct(llvm::MachO::symtab_command &lc) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +000047 swapByteOrder(lc.cmd);
48 swapByteOrder(lc.cmdsize);
49 swapByteOrder(lc.symoff);
50 swapByteOrder(lc.nsyms);
51 swapByteOrder(lc.stroff);
52 swapByteOrder(lc.strsize);
Nick Kledzike34182f2013-11-06 21:36:55 +000053}
54
55inline void swapStruct(llvm::MachO::segment_command_64 &seg) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +000056 swapByteOrder(seg.cmd);
57 swapByteOrder(seg.cmdsize);
58 swapByteOrder(seg.vmaddr);
59 swapByteOrder(seg.vmsize);
60 swapByteOrder(seg.fileoff);
61 swapByteOrder(seg.filesize);
62 swapByteOrder(seg.maxprot);
63 swapByteOrder(seg.initprot);
64 swapByteOrder(seg.nsects);
65 swapByteOrder(seg.flags);
Nick Kledzike34182f2013-11-06 21:36:55 +000066}
67
68inline void swapStruct(llvm::MachO::segment_command &seg) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +000069 swapByteOrder(seg.cmd);
70 swapByteOrder(seg.cmdsize);
71 swapByteOrder(seg.vmaddr);
72 swapByteOrder(seg.vmsize);
73 swapByteOrder(seg.fileoff);
74 swapByteOrder(seg.filesize);
75 swapByteOrder(seg.maxprot);
76 swapByteOrder(seg.initprot);
77 swapByteOrder(seg.nsects);
78 swapByteOrder(seg.flags);
Nick Kledzike34182f2013-11-06 21:36:55 +000079}
80
81inline void swapStruct(llvm::MachO::section_64 &sect) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +000082 swapByteOrder(sect.addr);
83 swapByteOrder(sect.size);
84 swapByteOrder(sect.offset);
85 swapByteOrder(sect.align);
86 swapByteOrder(sect.reloff);
87 swapByteOrder(sect.nreloc);
88 swapByteOrder(sect.flags);
89 swapByteOrder(sect.reserved1);
90 swapByteOrder(sect.reserved2);
Nick Kledzike34182f2013-11-06 21:36:55 +000091}
92
93inline void swapStruct(llvm::MachO::section &sect) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +000094 swapByteOrder(sect.addr);
95 swapByteOrder(sect.size);
96 swapByteOrder(sect.offset);
97 swapByteOrder(sect.align);
98 swapByteOrder(sect.reloff);
99 swapByteOrder(sect.nreloc);
100 swapByteOrder(sect.flags);
101 swapByteOrder(sect.reserved1);
102 swapByteOrder(sect.reserved2);
Nick Kledzike34182f2013-11-06 21:36:55 +0000103}
104
105inline void swapStruct(llvm::MachO::dyld_info_command &info) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000106 swapByteOrder(info.cmd);
107 swapByteOrder(info.cmdsize);
108 swapByteOrder(info.rebase_off);
109 swapByteOrder(info.rebase_size);
110 swapByteOrder(info.bind_off);
111 swapByteOrder(info.bind_size);
112 swapByteOrder(info.weak_bind_off);
113 swapByteOrder(info.weak_bind_size);
114 swapByteOrder(info.lazy_bind_off);
115 swapByteOrder(info.lazy_bind_size);
116 swapByteOrder(info.export_off);
117 swapByteOrder(info.export_size);
Nick Kledzike34182f2013-11-06 21:36:55 +0000118}
119
120inline void swapStruct(llvm::MachO::dylib_command &d) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000121 swapByteOrder(d.cmd);
122 swapByteOrder(d.cmdsize);
123 swapByteOrder(d.dylib.name);
124 swapByteOrder(d.dylib.timestamp);
125 swapByteOrder(d.dylib.current_version);
126 swapByteOrder(d.dylib.compatibility_version);
Nick Kledzike34182f2013-11-06 21:36:55 +0000127}
128
129inline void swapStruct(llvm::MachO::dylinker_command &d) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000130 swapByteOrder(d.cmd);
131 swapByteOrder(d.cmdsize);
132 swapByteOrder(d.name);
Nick Kledzike34182f2013-11-06 21:36:55 +0000133}
134
135inline void swapStruct(llvm::MachO::entry_point_command &e) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000136 swapByteOrder(e.cmd);
137 swapByteOrder(e.cmdsize);
138 swapByteOrder(e.entryoff);
139 swapByteOrder(e.stacksize);
Nick Kledzike34182f2013-11-06 21:36:55 +0000140}
141
142inline void swapStruct(llvm::MachO::dysymtab_command &dst) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000143 swapByteOrder(dst.cmd);
144 swapByteOrder(dst.cmdsize);
145 swapByteOrder(dst.ilocalsym);
146 swapByteOrder(dst.nlocalsym);
147 swapByteOrder(dst.iextdefsym);
148 swapByteOrder(dst.nextdefsym);
149 swapByteOrder(dst.iundefsym);
150 swapByteOrder(dst.nundefsym);
151 swapByteOrder(dst.tocoff);
152 swapByteOrder(dst.ntoc);
153 swapByteOrder(dst.modtaboff);
154 swapByteOrder(dst.nmodtab);
155 swapByteOrder(dst.extrefsymoff);
156 swapByteOrder(dst.nextrefsyms);
157 swapByteOrder(dst.indirectsymoff);
158 swapByteOrder(dst.nindirectsyms);
159 swapByteOrder(dst.extreloff);
160 swapByteOrder(dst.nextrel);
161 swapByteOrder(dst.locreloff);
162 swapByteOrder(dst.nlocrel);
Nick Kledzike34182f2013-11-06 21:36:55 +0000163}
164
165
166inline void swapStruct(llvm::MachO::any_relocation_info &reloc) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000167 swapByteOrder(reloc.r_word0);
168 swapByteOrder(reloc.r_word1);
Nick Kledzike34182f2013-11-06 21:36:55 +0000169}
170
171inline void swapStruct(llvm::MachO::nlist &sym) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000172 swapByteOrder(sym.n_strx);
173 swapByteOrder(sym.n_desc);
174 swapByteOrder(sym.n_value);
Nick Kledzike34182f2013-11-06 21:36:55 +0000175}
176
177inline void swapStruct(llvm::MachO::nlist_64 &sym) {
Artyom Skrobovf8874b02014-06-14 13:26:14 +0000178 swapByteOrder(sym.n_strx);
179 swapByteOrder(sym.n_desc);
180 swapByteOrder(sym.n_value);
Nick Kledzike34182f2013-11-06 21:36:55 +0000181}
182
183
184
Nick Kledzikde0860a2014-07-02 23:52:22 +0000185inline uint16_t read16(bool swap, uint16_t value) {
186 return (swap ? getSwappedBytes(value) : value);
187}
Nick Kledzike34182f2013-11-06 21:36:55 +0000188
189inline uint32_t read32(bool swap, uint32_t value) {
Artyom Skrobov9b3f6472014-06-14 12:14:25 +0000190 return (swap ? getSwappedBytes(value) : value);
Nick Kledzike34182f2013-11-06 21:36:55 +0000191}
192
193inline uint64_t read64(bool swap, uint64_t value) {
Artyom Skrobov9b3f6472014-06-14 12:14:25 +0000194 return (swap ? getSwappedBytes(value) : value);
Nick Kledzike34182f2013-11-06 21:36:55 +0000195}
196
Nick Kledzik2458bec2014-07-16 19:49:02 +0000197inline void write16(int16_t &loc, bool swap, int16_t value) {
198 loc = (swap ? getSwappedBytes(value) : value);
199}
Nick Kledzike34182f2013-11-06 21:36:55 +0000200
Nick Kledzik2458bec2014-07-16 19:49:02 +0000201inline void write32(int32_t &loc, bool swap, int32_t value) {
202 loc = (swap ? getSwappedBytes(value) : value);
203}
204
205inline void write64(uint64_t &loc, bool swap, uint64_t value) {
206 loc = (swap ? getSwappedBytes(value) : value);
207}
Nick Kledzike34182f2013-11-06 21:36:55 +0000208
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000209inline uint32_t
210bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
Nick Kledzike34182f2013-11-06 21:36:55 +0000211 uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000212 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +0000213 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
214 return (value >> shift) & mask;
215}
216
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000217inline void
218bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
Nick Kledzike34182f2013-11-06 21:36:55 +0000219 uint8_t firstBit, uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000220 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +0000221 assert((newBits & mask) == newBits);
222 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
223 bits &= ~(mask << shift);
224 bits |= (newBits << shift);
225}
226
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000227inline Relocation
228unpackRelocation(const llvm::MachO::any_relocation_info &r, bool swap,
Nick Kledzike34182f2013-11-06 21:36:55 +0000229 bool isBigEndian) {
230 uint32_t r0 = read32(swap, r.r_word0);
231 uint32_t r1 = read32(swap, r.r_word1);
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000232
Nick Kledzike34182f2013-11-06 21:36:55 +0000233 Relocation result;
234 if (r0 & llvm::MachO::R_SCATTERED) {
235 // scattered relocation record always laid out like big endian bit field
236 result.offset = bitFieldExtract(r0, true, 8, 24);
237 result.scattered = true;
238 result.type = (RelocationInfoType)
239 bitFieldExtract(r0, true, 4, 4);
240 result.length = bitFieldExtract(r0, true, 2, 2);
241 result.pcRel = bitFieldExtract(r0, true, 1, 1);
242 result.isExtern = false;
243 result.value = r1;
244 result.symbol = 0;
245 } else {
246 result.offset = r0;
247 result.scattered = false;
248 result.type = (RelocationInfoType)
249 bitFieldExtract(r1, isBigEndian, 28, 4);
250 result.length = bitFieldExtract(r1, isBigEndian, 25, 2);
251 result.pcRel = bitFieldExtract(r1, isBigEndian, 24, 1);
252 result.isExtern = bitFieldExtract(r1, isBigEndian, 27, 1);
253 result.value = 0;
254 result.symbol = bitFieldExtract(r1, isBigEndian, 0, 24);
255 }
256 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000257}
Nick Kledzike34182f2013-11-06 21:36:55 +0000258
259
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000260inline llvm::MachO::any_relocation_info
Nick Kledzike34182f2013-11-06 21:36:55 +0000261packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
262 uint32_t r0 = 0;
263 uint32_t r1 = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000264
Nick Kledzike34182f2013-11-06 21:36:55 +0000265 if (r.scattered) {
266 r1 = r.value;
267 bitFieldSet(r0, true, r.offset, 8, 24);
268 bitFieldSet(r0, true, r.type, 4, 4);
269 bitFieldSet(r0, true, r.length, 2, 2);
270 bitFieldSet(r0, true, r.pcRel, 1, 1);
271 bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
272 } else {
273 r0 = r.offset;
274 bitFieldSet(r1, isBigEndian, r.type, 28, 4);
275 bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
276 bitFieldSet(r1, isBigEndian, r.length, 25, 2);
277 bitFieldSet(r1, isBigEndian, r.pcRel, 24, 1);
278 bitFieldSet(r1, isBigEndian, r.symbol, 0, 24);
279 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000280
Nick Kledzike34182f2013-11-06 21:36:55 +0000281 llvm::MachO::any_relocation_info result;
Artyom Skrobov9b3f6472014-06-14 12:14:25 +0000282 result.r_word0 = swap ? getSwappedBytes(r0) : r0;
283 result.r_word1 = swap ? getSwappedBytes(r1) : r1;
Nick Kledzike34182f2013-11-06 21:36:55 +0000284 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000285}
Nick Kledzike34182f2013-11-06 21:36:55 +0000286
287inline StringRef getString16(const char s[16]) {
288 StringRef x = s;
289 if ( x.size() > 16 )
290 return x.substr(0, 16);
291 else
292 return x;
293}
294
295inline void setString16(StringRef str, char s[16]) {
296 memset(s, 0, 16);
297 memcpy(s, str.begin(), (str.size() > 16) ? 16: str.size());
298}
299
Nick Kledzikec140832014-06-10 01:50:00 +0000300// Implemented in normalizedToAtoms() and used by normalizedFromAtoms() so
301// that the same table can be used to map mach-o sections to and from
302// DefinedAtom::ContentType.
303void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
304 StringRef &segmentName,
305 StringRef &sectionName,
306 SectionType &sectionType,
307 SectionAttr &sectionAttrs);
Nick Kledzike34182f2013-11-06 21:36:55 +0000308
309} // namespace normalized
310} // namespace mach_o
311} // namespace lld
312
Rui Ueyama014192db2013-11-15 03:09:26 +0000313#endif // LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H