blob: 8f2ed52c73809cf278599f2d5eb4cd258cb58a9c [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"
12
13#include "lld/Core/Error.h"
14#include "lld/Core/LLVM.h"
15
16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/Casting.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/Host.h"
20#include "llvm/Support/MachO.h"
21#include "llvm/Support/system_error.h"
22
23#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_UILS_H_
24#define LLD_READER_WRITER_MACHO_NORMALIZED_UILS_H_
25
26namespace lld {
27namespace mach_o {
28namespace normalized {
29
30using llvm::sys::SwapByteOrder;
31
32inline void swapStruct(llvm::MachO::mach_header &mh) {
33 mh.magic = SwapByteOrder(mh.magic);
34 mh.cputype = SwapByteOrder(mh.cputype);
35 mh.cpusubtype = SwapByteOrder(mh.cpusubtype);
36 mh.filetype = SwapByteOrder(mh.filetype);
37 mh.ncmds = SwapByteOrder(mh.ncmds);
38 mh.sizeofcmds = SwapByteOrder(mh.sizeofcmds);
39 mh.flags = SwapByteOrder(mh.flags);
40}
41
42inline void swapStruct(llvm::MachO::load_command &lc) {
43 lc.cmd = SwapByteOrder(lc.cmd);
44 lc.cmdsize = SwapByteOrder(lc.cmdsize);
45}
46
47inline void swapStruct(llvm::MachO::symtab_command &lc) {
48 lc.cmd = SwapByteOrder(lc.cmd);
49 lc.cmdsize = SwapByteOrder(lc.cmdsize);
50 lc.symoff = SwapByteOrder(lc.symoff);
51 lc.nsyms = SwapByteOrder(lc.nsyms);
52 lc.stroff = SwapByteOrder(lc.stroff);
53 lc.strsize = SwapByteOrder(lc.strsize);
54}
55
56inline void swapStruct(llvm::MachO::segment_command_64 &seg) {
57 seg.cmd = SwapByteOrder(seg.cmd);
58 seg.cmdsize = SwapByteOrder(seg.cmdsize);
59 seg.vmaddr = SwapByteOrder(seg.vmaddr);
60 seg.vmsize = SwapByteOrder(seg.vmsize);
61 seg.fileoff = SwapByteOrder(seg.fileoff);
62 seg.filesize = SwapByteOrder(seg.filesize);
63 seg.maxprot = SwapByteOrder(seg.maxprot);
64 seg.initprot = SwapByteOrder(seg.initprot);
65 seg.nsects = SwapByteOrder(seg.nsects);
66 seg.flags = SwapByteOrder(seg.flags);
67}
68
69inline void swapStruct(llvm::MachO::segment_command &seg) {
70 seg.cmd = SwapByteOrder(seg.cmd);
71 seg.cmdsize = SwapByteOrder(seg.cmdsize);
72 seg.vmaddr = SwapByteOrder(seg.vmaddr);
73 seg.vmsize = SwapByteOrder(seg.vmsize);
74 seg.fileoff = SwapByteOrder(seg.fileoff);
75 seg.filesize = SwapByteOrder(seg.filesize);
76 seg.maxprot = SwapByteOrder(seg.maxprot);
77 seg.initprot = SwapByteOrder(seg.initprot);
78 seg.nsects = SwapByteOrder(seg.nsects);
79 seg.flags = SwapByteOrder(seg.flags);
80}
81
82inline void swapStruct(llvm::MachO::section_64 &sect) {
83 sect.addr = SwapByteOrder(sect.addr);
84 sect.size = SwapByteOrder(sect.size);
85 sect.offset = SwapByteOrder(sect.offset);
86 sect.align = SwapByteOrder(sect.align);
87 sect.reloff = SwapByteOrder(sect.reloff);
88 sect.nreloc = SwapByteOrder(sect.nreloc);
89 sect.flags = SwapByteOrder(sect.flags);
90 sect.reserved1 = SwapByteOrder(sect.reserved1);
91 sect.reserved2 = SwapByteOrder(sect.reserved2);
92}
93
94inline void swapStruct(llvm::MachO::section &sect) {
95 sect.addr = SwapByteOrder(sect.addr);
96 sect.size = SwapByteOrder(sect.size);
97 sect.offset = SwapByteOrder(sect.offset);
98 sect.align = SwapByteOrder(sect.align);
99 sect.reloff = SwapByteOrder(sect.reloff);
100 sect.nreloc = SwapByteOrder(sect.nreloc);
101 sect.flags = SwapByteOrder(sect.flags);
102 sect.reserved1 = SwapByteOrder(sect.reserved1);
103 sect.reserved2 = SwapByteOrder(sect.reserved2);
104}
105
106inline void swapStruct(llvm::MachO::dyld_info_command &info) {
107 info.cmd = SwapByteOrder(info.cmd);
108 info.cmdsize = SwapByteOrder(info.cmdsize);
109 info.rebase_off = SwapByteOrder(info.rebase_off);
110 info.rebase_size = SwapByteOrder(info.rebase_size);
111 info.bind_off = SwapByteOrder(info.bind_off);
112 info.bind_size = SwapByteOrder(info.bind_size);
113 info.weak_bind_off = SwapByteOrder(info.weak_bind_off);
114 info.weak_bind_size = SwapByteOrder(info.weak_bind_size);
115 info.lazy_bind_off = SwapByteOrder(info.lazy_bind_off);
116 info.lazy_bind_size = SwapByteOrder(info.lazy_bind_size);
117 info.export_off = SwapByteOrder(info.export_off);
118 info.export_size = SwapByteOrder(info.export_size);
119}
120
121inline void swapStruct(llvm::MachO::dylib_command &d) {
122 d.cmd = SwapByteOrder(d.cmd);
123 d.cmdsize = SwapByteOrder(d.cmdsize);
124 d.dylib.name = SwapByteOrder(d.dylib.name);
125 d.dylib.timestamp = SwapByteOrder(d.dylib.timestamp);
126 d.dylib.current_version = SwapByteOrder(d.dylib.current_version);
127 d.dylib.compatibility_version = SwapByteOrder(d.dylib.compatibility_version);
128}
129
130inline void swapStruct(llvm::MachO::dylinker_command &d) {
131 d.cmd = SwapByteOrder(d.cmd);
132 d.cmdsize = SwapByteOrder(d.cmdsize);
133 d.name = SwapByteOrder(d.name);
134}
135
136inline void swapStruct(llvm::MachO::entry_point_command &e) {
137 e.cmd = SwapByteOrder(e.cmd);
138 e.cmdsize = SwapByteOrder(e.cmdsize);
139 e.entryoff = SwapByteOrder(e.entryoff);
140 e.stacksize = SwapByteOrder(e.stacksize);
141}
142
143inline void swapStruct(llvm::MachO::dysymtab_command &dst) {
144 dst.cmd = SwapByteOrder(dst.cmd);
145 dst.cmdsize = SwapByteOrder(dst.cmdsize);
146 dst.ilocalsym = SwapByteOrder(dst.ilocalsym);
147 dst.nlocalsym = SwapByteOrder(dst.nlocalsym);
148 dst.iextdefsym = SwapByteOrder(dst.iextdefsym);
149 dst.nextdefsym = SwapByteOrder(dst.nextdefsym);
150 dst.iundefsym = SwapByteOrder(dst.iundefsym);
151 dst.nundefsym = SwapByteOrder(dst.nundefsym);
152 dst.tocoff = SwapByteOrder(dst.tocoff);
153 dst.ntoc = SwapByteOrder(dst.ntoc);
154 dst.modtaboff = SwapByteOrder(dst.modtaboff);
155 dst.nmodtab = SwapByteOrder(dst.nmodtab);
156 dst.extrefsymoff = SwapByteOrder(dst.extrefsymoff);
157 dst.nextrefsyms = SwapByteOrder(dst.nextrefsyms);
158 dst.indirectsymoff = SwapByteOrder(dst.indirectsymoff);
159 dst.nindirectsyms = SwapByteOrder(dst.nindirectsyms);
160 dst.extreloff = SwapByteOrder(dst.extreloff);
161 dst.nextrel = SwapByteOrder(dst.nextrel);
162 dst.locreloff = SwapByteOrder(dst.locreloff);
163 dst.nlocrel = SwapByteOrder(dst.nlocrel);
164}
165
166
167inline void swapStruct(llvm::MachO::any_relocation_info &reloc) {
168 reloc.r_word0 = SwapByteOrder(reloc.r_word0);
169 reloc.r_word1 = SwapByteOrder(reloc.r_word1);
170}
171
172inline void swapStruct(llvm::MachO::nlist &sym) {
173 sym.n_strx = SwapByteOrder(sym.n_strx);
174 sym.n_desc = SwapByteOrder(sym.n_desc);
175 sym.n_value = SwapByteOrder(sym.n_value);
176}
177
178inline void swapStruct(llvm::MachO::nlist_64 &sym) {
179 sym.n_strx = SwapByteOrder(sym.n_strx);
180 sym.n_desc = SwapByteOrder(sym.n_desc);
181 sym.n_value = SwapByteOrder(sym.n_value);
182}
183
184
185
186
187inline uint32_t read32(bool swap, uint32_t value) {
188 return (swap ? SwapByteOrder(value) : value);
189}
190
191inline uint64_t read64(bool swap, uint64_t value) {
192 return (swap ? SwapByteOrder(value) : value);
193}
194
195
196
197inline uint32_t
198bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
199 uint8_t bitCount) {
200 const uint32_t mask = ((1<<bitCount)-1);
201 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
202 return (value >> shift) & mask;
203}
204
205inline void
206bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
207 uint8_t firstBit, uint8_t bitCount) {
208 const uint32_t mask = ((1<<bitCount)-1);
209 assert((newBits & mask) == newBits);
210 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
211 bits &= ~(mask << shift);
212 bits |= (newBits << shift);
213}
214
215inline Relocation
216unpackRelocation(const llvm::MachO::any_relocation_info &r, bool swap,
217 bool isBigEndian) {
218 uint32_t r0 = read32(swap, r.r_word0);
219 uint32_t r1 = read32(swap, r.r_word1);
220
221 Relocation result;
222 if (r0 & llvm::MachO::R_SCATTERED) {
223 // scattered relocation record always laid out like big endian bit field
224 result.offset = bitFieldExtract(r0, true, 8, 24);
225 result.scattered = true;
226 result.type = (RelocationInfoType)
227 bitFieldExtract(r0, true, 4, 4);
228 result.length = bitFieldExtract(r0, true, 2, 2);
229 result.pcRel = bitFieldExtract(r0, true, 1, 1);
230 result.isExtern = false;
231 result.value = r1;
232 result.symbol = 0;
233 } else {
234 result.offset = r0;
235 result.scattered = false;
236 result.type = (RelocationInfoType)
237 bitFieldExtract(r1, isBigEndian, 28, 4);
238 result.length = bitFieldExtract(r1, isBigEndian, 25, 2);
239 result.pcRel = bitFieldExtract(r1, isBigEndian, 24, 1);
240 result.isExtern = bitFieldExtract(r1, isBigEndian, 27, 1);
241 result.value = 0;
242 result.symbol = bitFieldExtract(r1, isBigEndian, 0, 24);
243 }
244 return result;
245}
246
247
248inline llvm::MachO::any_relocation_info
249packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
250 uint32_t r0 = 0;
251 uint32_t r1 = 0;
252
253 if (r.scattered) {
254 r1 = r.value;
255 bitFieldSet(r0, true, r.offset, 8, 24);
256 bitFieldSet(r0, true, r.type, 4, 4);
257 bitFieldSet(r0, true, r.length, 2, 2);
258 bitFieldSet(r0, true, r.pcRel, 1, 1);
259 bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
260 } else {
261 r0 = r.offset;
262 bitFieldSet(r1, isBigEndian, r.type, 28, 4);
263 bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
264 bitFieldSet(r1, isBigEndian, r.length, 25, 2);
265 bitFieldSet(r1, isBigEndian, r.pcRel, 24, 1);
266 bitFieldSet(r1, isBigEndian, r.symbol, 0, 24);
267 }
268
269 llvm::MachO::any_relocation_info result;
270 result.r_word0 = swap ? SwapByteOrder(r0) : r0;
271 result.r_word1 = swap ? SwapByteOrder(r1) : r1;
272 return result;
273}
274
275inline StringRef getString16(const char s[16]) {
276 StringRef x = s;
277 if ( x.size() > 16 )
278 return x.substr(0, 16);
279 else
280 return x;
281}
282
283inline void setString16(StringRef str, char s[16]) {
284 memset(s, 0, 16);
285 memcpy(s, str.begin(), (str.size() > 16) ? 16: str.size());
286}
287
288
289} // namespace normalized
290} // namespace mach_o
291} // namespace lld
292
293#endif // LLD_READER_WRITER_MACHO_NORMALIZED_UILS_H_