blob: a5cba0aeda839fed2328628fb6ec6a7eb65670b8 [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 Skrobov9b3f6472014-06-14 12:14:25 +000028using llvm::sys::getSwappedBytes;
Nick Kledzike34182f2013-11-06 21:36:55 +000029
Nick Kledzikde0860a2014-07-02 23:52:22 +000030inline uint16_t read16(bool swap, uint16_t value) {
31 return (swap ? getSwappedBytes(value) : value);
32}
Nick Kledzike34182f2013-11-06 21:36:55 +000033
34inline uint32_t read32(bool swap, uint32_t value) {
Artyom Skrobov9b3f6472014-06-14 12:14:25 +000035 return (swap ? getSwappedBytes(value) : value);
Nick Kledzike34182f2013-11-06 21:36:55 +000036}
37
38inline uint64_t read64(bool swap, uint64_t value) {
Artyom Skrobov9b3f6472014-06-14 12:14:25 +000039 return (swap ? getSwappedBytes(value) : value);
Nick Kledzike34182f2013-11-06 21:36:55 +000040}
41
Nick Kledzik2458bec2014-07-16 19:49:02 +000042inline void write16(int16_t &loc, bool swap, int16_t value) {
43 loc = (swap ? getSwappedBytes(value) : value);
44}
Nick Kledzike34182f2013-11-06 21:36:55 +000045
Nick Kledzik2458bec2014-07-16 19:49:02 +000046inline void write32(int32_t &loc, bool swap, int32_t value) {
47 loc = (swap ? getSwappedBytes(value) : value);
48}
49
50inline void write64(uint64_t &loc, bool swap, uint64_t value) {
51 loc = (swap ? getSwappedBytes(value) : value);
52}
Nick Kledzike34182f2013-11-06 21:36:55 +000053
Shankar Easwaran3d8de472014-01-27 03:09:26 +000054inline uint32_t
55bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
Nick Kledzike34182f2013-11-06 21:36:55 +000056 uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +000057 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +000058 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
59 return (value >> shift) & mask;
60}
61
Shankar Easwaran3d8de472014-01-27 03:09:26 +000062inline void
63bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
Nick Kledzike34182f2013-11-06 21:36:55 +000064 uint8_t firstBit, uint8_t bitCount) {
Shankar Easwaran3d8de472014-01-27 03:09:26 +000065 const uint32_t mask = ((1<<bitCount)-1);
Nick Kledzike34182f2013-11-06 21:36:55 +000066 assert((newBits & mask) == newBits);
67 const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
68 bits &= ~(mask << shift);
69 bits |= (newBits << shift);
70}
71
Shankar Easwaran3d8de472014-01-27 03:09:26 +000072inline Relocation
73unpackRelocation(const llvm::MachO::any_relocation_info &r, bool swap,
Nick Kledzike34182f2013-11-06 21:36:55 +000074 bool isBigEndian) {
75 uint32_t r0 = read32(swap, r.r_word0);
76 uint32_t r1 = read32(swap, r.r_word1);
Shankar Easwaran3d8de472014-01-27 03:09:26 +000077
Nick Kledzike34182f2013-11-06 21:36:55 +000078 Relocation result;
79 if (r0 & llvm::MachO::R_SCATTERED) {
80 // scattered relocation record always laid out like big endian bit field
81 result.offset = bitFieldExtract(r0, true, 8, 24);
82 result.scattered = true;
83 result.type = (RelocationInfoType)
84 bitFieldExtract(r0, true, 4, 4);
85 result.length = bitFieldExtract(r0, true, 2, 2);
86 result.pcRel = bitFieldExtract(r0, true, 1, 1);
87 result.isExtern = false;
88 result.value = r1;
89 result.symbol = 0;
90 } else {
91 result.offset = r0;
92 result.scattered = false;
93 result.type = (RelocationInfoType)
94 bitFieldExtract(r1, isBigEndian, 28, 4);
95 result.length = bitFieldExtract(r1, isBigEndian, 25, 2);
96 result.pcRel = bitFieldExtract(r1, isBigEndian, 24, 1);
97 result.isExtern = bitFieldExtract(r1, isBigEndian, 27, 1);
98 result.value = 0;
99 result.symbol = bitFieldExtract(r1, isBigEndian, 0, 24);
100 }
101 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000102}
Nick Kledzike34182f2013-11-06 21:36:55 +0000103
104
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000105inline llvm::MachO::any_relocation_info
Nick Kledzike34182f2013-11-06 21:36:55 +0000106packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
107 uint32_t r0 = 0;
108 uint32_t r1 = 0;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000109
Nick Kledzike34182f2013-11-06 21:36:55 +0000110 if (r.scattered) {
111 r1 = r.value;
112 bitFieldSet(r0, true, r.offset, 8, 24);
113 bitFieldSet(r0, true, r.type, 4, 4);
114 bitFieldSet(r0, true, r.length, 2, 2);
115 bitFieldSet(r0, true, r.pcRel, 1, 1);
116 bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
117 } else {
118 r0 = r.offset;
119 bitFieldSet(r1, isBigEndian, r.type, 28, 4);
120 bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
121 bitFieldSet(r1, isBigEndian, r.length, 25, 2);
122 bitFieldSet(r1, isBigEndian, r.pcRel, 24, 1);
123 bitFieldSet(r1, isBigEndian, r.symbol, 0, 24);
124 }
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000125
Nick Kledzike34182f2013-11-06 21:36:55 +0000126 llvm::MachO::any_relocation_info result;
Artyom Skrobov9b3f6472014-06-14 12:14:25 +0000127 result.r_word0 = swap ? getSwappedBytes(r0) : r0;
128 result.r_word1 = swap ? getSwappedBytes(r1) : r1;
Nick Kledzike34182f2013-11-06 21:36:55 +0000129 return result;
Shankar Easwaran3d8de472014-01-27 03:09:26 +0000130}
Nick Kledzike34182f2013-11-06 21:36:55 +0000131
132inline StringRef getString16(const char s[16]) {
133 StringRef x = s;
134 if ( x.size() > 16 )
135 return x.substr(0, 16);
136 else
137 return x;
138}
139
140inline void setString16(StringRef str, char s[16]) {
141 memset(s, 0, 16);
142 memcpy(s, str.begin(), (str.size() > 16) ? 16: str.size());
143}
144
Nick Kledzikec140832014-06-10 01:50:00 +0000145// Implemented in normalizedToAtoms() and used by normalizedFromAtoms() so
146// that the same table can be used to map mach-o sections to and from
147// DefinedAtom::ContentType.
148void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
149 StringRef &segmentName,
150 StringRef &sectionName,
151 SectionType &sectionType,
152 SectionAttr &sectionAttrs);
Nick Kledzike34182f2013-11-06 21:36:55 +0000153
154} // namespace normalized
155} // namespace mach_o
156} // namespace lld
157
Rui Ueyama014192db2013-11-15 03:09:26 +0000158#endif // LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H