blob: ae47329034b440f50d2f00fb46b9ed9763fc4bfd [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"
Rui Ueyamae088a0f2015-02-27 04:21:40 +000012#include "lld/Core/Endian.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000013#include "lld/Core/Error.h"
14#include "lld/Core/LLVM.h"
Nick Kledzike34182f2013-11-06 21:36:55 +000015#include "llvm/ADT/StringRef.h"
16#include "llvm/Support/Casting.h"
17#include "llvm/Support/ErrorHandling.h"
18#include "llvm/Support/Host.h"
19#include "llvm/Support/MachO.h"
Rafael Espindola54427cc2014-06-12 17:15:58 +000020#include <system_error>
Nick Kledzike34182f2013-11-06 21:36:55 +000021
Rui Ueyama014192db2013-11-15 03:09:26 +000022#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
23#define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
Nick Kledzike34182f2013-11-06 21:36:55 +000024
25namespace lld {
26namespace mach_o {
27namespace normalized {
28
Artyom Skrobov9b3f6472014-06-14 12:14:25 +000029using llvm::sys::getSwappedBytes;
Nick Kledzike34182f2013-11-06 21:36:55 +000030
Tim Northover40d3ad32014-10-27 22:48:35 +000031template<typename T>
32static inline uint16_t read16(const T *loc, bool isBig) {
33 assert((uint64_t)loc % llvm::alignOf<T>() == 0 &&
34 "invalid pointer alignment");
Rui Ueyamae088a0f2015-02-27 04:21:40 +000035 return isBig ? read16be(loc) : read16le(loc);
Nick Kledzikde0860a2014-07-02 23:52:22 +000036}
Nick Kledzike34182f2013-11-06 21:36:55 +000037
Tim Northover40d3ad32014-10-27 22:48:35 +000038template<typename T>
39static inline uint32_t read32(const T *loc, bool isBig) {
40 assert((uint64_t)loc % llvm::alignOf<T>() == 0 &&
41 "invalid pointer alignment");
Rui Ueyamae088a0f2015-02-27 04:21:40 +000042 return isBig ? read32be(loc) : read32le(loc);
Nick Kledzike34182f2013-11-06 21:36:55 +000043}
44
Tim Northover40d3ad32014-10-27 22:48:35 +000045template<typename T>
46static inline uint64_t read64(const T *loc, bool isBig) {
47 assert((uint64_t)loc % llvm::alignOf<T>() == 0 &&
48 "invalid pointer alignment");
Rui Ueyamae088a0f2015-02-27 04:21:40 +000049 return isBig ? read64be(loc) : read64le(loc);
Nick Kledzike34182f2013-11-06 21:36:55 +000050}
51
Tim Northover40d3ad32014-10-27 22:48:35 +000052inline void write16(uint8_t *loc, uint16_t value, bool isBig) {
53 if (isBig)
Rui Ueyamae088a0f2015-02-27 04:21:40 +000054 write16be(loc, value);
Tim Northover40d3ad32014-10-27 22:48:35 +000055 else
Rui Ueyamae088a0f2015-02-27 04:21:40 +000056 write16le(loc, value);
Nick Kledzik2458bec2014-07-16 19:49:02 +000057}
Nick Kledzike34182f2013-11-06 21:36:55 +000058
Tim Northover40d3ad32014-10-27 22:48:35 +000059inline void write32(uint8_t *loc, uint32_t value, bool isBig) {
60 if (isBig)
Rui Ueyamae088a0f2015-02-27 04:21:40 +000061 write32be(loc, value);
Tim Northover40d3ad32014-10-27 22:48:35 +000062 else
Rui Ueyamae088a0f2015-02-27 04:21:40 +000063 write32le(loc, value);
Nick Kledzik2458bec2014-07-16 19:49:02 +000064}
65
Tim Northover40d3ad32014-10-27 22:48:35 +000066inline void write64(uint8_t *loc, uint64_t value, bool isBig) {
67 if (isBig)
Rui Ueyamae088a0f2015-02-27 04:21:40 +000068 write64be(loc, value);
Tim Northover40d3ad32014-10-27 22:48:35 +000069 else
Rui Ueyamae088a0f2015-02-27 04:21:40 +000070 write64le(loc, value);
Nick Kledzik2458bec2014-07-16 19:49:02 +000071}
Nick Kledzike34182f2013-11-06 21:36:55 +000072
Shankar Easwaran3d8de472014-01-27 03:09:26 +000073inline uint32_t
74bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
Nick Kledzike34182f2013-11-06 21:36:55 +000075 uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +000076 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +000077 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
78 return (value >> shift) & mask;
79}
80
Shankar Easwaran3d8de472014-01-27 03:09:26 +000081inline void
82bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
Nick Kledzike34182f2013-11-06 21:36:55 +000083 uint8_t firstBit, uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +000084 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +000085 assert((newBits & mask) == newBits);
86 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
87 bits &= ~(mask << shift);
88 bits |= (newBits << shift);
89}
90
Tim Northover40d3ad32014-10-27 22:48:35 +000091inline Relocation unpackRelocation(const llvm::MachO::any_relocation_info &r,
92 bool isBigEndian) {
93 uint32_t r0 = read32(&r.r_word0, isBigEndian);
94 uint32_t r1 = read32(&r.r_word1, isBigEndian);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000095
Nick Kledzike34182f2013-11-06 21:36:55 +000096 Relocation result;
97 if (r0 & llvm::MachO::R_SCATTERED) {
98 // scattered relocation record always laid out like big endian bit field
99 result.offset = bitFieldExtract(r0, true, 8, 24);
100 result.scattered = true;
101 result.type = (RelocationInfoType)
102 bitFieldExtract(r0, true, 4, 4);
103 result.length = bitFieldExtract(r0, true, 2, 2);
104 result.pcRel = bitFieldExtract(r0, true, 1, 1);
105 result.isExtern = false;
106 result.value = r1;
107 result.symbol = 0;
108 } else {
109 result.offset = r0;
110 result.scattered = false;
111 result.type = (RelocationInfoType)
112 bitFieldExtract(r1, isBigEndian, 28, 4);
113 result.length = bitFieldExtract(r1, isBigEndian, 25, 2);
114 result.pcRel = bitFieldExtract(r1, isBigEndian, 24, 1);
115 result.isExtern = bitFieldExtract(r1, isBigEndian, 27, 1);
116 result.value = 0;
117 result.symbol = bitFieldExtract(r1, isBigEndian, 0, 24);
118 }
119 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000120}
Nick Kledzike34182f2013-11-06 21:36:55 +0000121
122
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000123inline llvm::MachO::any_relocation_info
Nick Kledzike34182f2013-11-06 21:36:55 +0000124packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
125 uint32_t r0 = 0;
126 uint32_t r1 = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000127
Nick Kledzike34182f2013-11-06 21:36:55 +0000128 if (r.scattered) {
129 r1 = r.value;
130 bitFieldSet(r0, true, r.offset, 8, 24);
131 bitFieldSet(r0, true, r.type, 4, 4);
132 bitFieldSet(r0, true, r.length, 2, 2);
133 bitFieldSet(r0, true, r.pcRel, 1, 1);
134 bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
135 } else {
136 r0 = r.offset;
137 bitFieldSet(r1, isBigEndian, r.type, 28, 4);
138 bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
139 bitFieldSet(r1, isBigEndian, r.length, 25, 2);
140 bitFieldSet(r1, isBigEndian, r.pcRel, 24, 1);
141 bitFieldSet(r1, isBigEndian, r.symbol, 0, 24);
142 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000143
Nick Kledzike34182f2013-11-06 21:36:55 +0000144 llvm::MachO::any_relocation_info result;
Artyom Skrobov9b3f6472014-06-14 12:14:25 +0000145 result.r_word0 = swap ? getSwappedBytes(r0) : r0;
146 result.r_word1 = swap ? getSwappedBytes(r1) : r1;
Nick Kledzike34182f2013-11-06 21:36:55 +0000147 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000148}
Nick Kledzike34182f2013-11-06 21:36:55 +0000149
150inline StringRef getString16(const char s[16]) {
151 StringRef x = s;
152 if ( x.size() > 16 )
153 return x.substr(0, 16);
154 else
155 return x;
156}
157
158inline void setString16(StringRef str, char s[16]) {
159 memset(s, 0, 16);
160 memcpy(s, str.begin(), (str.size() > 16) ? 16: str.size());
161}
162
Nick Kledzikec140832014-06-10 01:50:00 +0000163// Implemented in normalizedToAtoms() and used by normalizedFromAtoms() so
164// that the same table can be used to map mach-o sections to and from
165// DefinedAtom::ContentType.
166void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
167 StringRef &segmentName,
168 StringRef &sectionName,
169 SectionType &sectionType,
170 SectionAttr &sectionAttrs);
Nick Kledzike34182f2013-11-06 21:36:55 +0000171
172} // namespace normalized
173} // namespace mach_o
174} // namespace lld
175
Rui Ueyama014192db2013-11-15 03:09:26 +0000176#endif // LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H