llvm.org GIT mirror llvm / 2173e18
Use llvm/Object/MachO.h in macho-dumper. Drop the old macho parser. For Mach-O there were 2 implementations for parsing object files. A standalone llvm/Object/MachOObject.h and llvm/Object/MachO.h which implements the generic interface in llvm/Object/ObjectFile.h. This patch adds the missing features to MachO.h, moves macho-dump to use MachO.h and removes ObjectFile.h. In addition to making sure that check-all is clean, I checked that the new version produces exactly the same output in all Mach-O files in a llvm+clang build directory (including executables and shared libraries). To test the performance, I ran macho-dump over all the files in a llvm+clang build directory again, but this time redirecting the output to /dev/null. Both the old and new versions take about 4.6 seconds (2.5 user) to finish. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180624 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 7 years ago
9 changed file(s) with 374 addition(s) and 1003 deletion(s). Raw diff Collapse all Expand all
+0
-77
include/llvm/ADT/InMemoryStruct.h less more
None //===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_ADT_INMEMORYSTRUCT_H
10 #define LLVM_ADT_INMEMORYSTRUCT_H
11
12 #include
13
14 namespace llvm {
15
16 /// \brief Helper object for abstracting access to an in-memory structure which
17 /// may require some kind of temporary storage.
18 ///
19 /// This class is designed to be used for accessing file data structures which
20 /// in the common case can be accessed from a direct pointer to a memory mapped
21 /// object, but which in some cases may require indirect access to a temporary
22 /// structure (which, for example, may have undergone endianness translation).
23 template
24 class InMemoryStruct {
25 typedef T value_type;
26 typedef value_type &reference;
27 typedef value_type *pointer;
28 typedef const value_type &const_reference;
29 typedef const value_type *const_pointer;
30
31 /// \brief The smart pointer target.
32 value_type *Target;
33
34 /// \brief A temporary object which can be used as a target of the smart
35 /// pointer.
36 value_type Contents;
37
38 private:
39
40 public:
41 InMemoryStruct() : Target(0) {}
42 InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {}
43 InMemoryStruct(pointer Value) : Target(Value) {}
44 InMemoryStruct(const InMemoryStruct &Value) { *this = Value; }
45
46 void operator=(const InMemoryStruct &Value) {
47 if (Value.Target != &Value.Contents) {
48 Target = Value.Target;
49 } else {
50 Target = &Contents;
51 Contents = Value.Contents;
52 }
53 }
54
55 const_reference operator*() const {
56 assert(Target && "Cannot dereference null pointer");
57 return *Target;
58 }
59 reference operator*() {
60 assert(Target && "Cannot dereference null pointer");
61 return *Target;
62 }
63
64 const_pointer operator->() const {
65 return Target;
66 }
67 pointer operator->() {
68 return Target;
69 }
70
71 operator bool() const { return Target != 0; }
72 };
73
74 }
75
76 #endif
105105
106106 virtual StringRef getLoadName() const;
107107
108 relocation_iterator getSectionRelBegin(unsigned Index) const;
109 relocation_iterator getSectionRelEnd(unsigned Index) const;
110
108111 // In a MachO file, sections have a segment name. This is used in the .o
109112 // files. They have a single segment, but this field specifies which segment
110113 // a section should be put in in the final object.
133136 // MachO specific structures.
134137 macho::Section getSection(DataRefImpl DRI) const;
135138 macho::Section64 getSection64(DataRefImpl DRI) const;
139 macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const;
140 macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const;
136141 macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const;
137142 macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const;
143
138144 macho::LinkeditDataLoadCommand
139145 getLinkeditDataLoadCommand(const LoadCommandInfo &L) const;
146 macho::SegmentLoadCommand
147 getSegmentLoadCommand(const LoadCommandInfo &L) const;
148 macho::Segment64LoadCommand
149 getSegment64LoadCommand(const LoadCommandInfo &L) const;
150 macho::LinkerOptionsLoadCommand
151 getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const;
152
140153 macho::RelocationEntry getRelocation(DataRefImpl Rel) const;
141154 macho::Header getHeader() const;
155 macho::Header64Ext getHeader64Ext() const;
156 macho::IndirectSymbolTableEntry
157 getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC,
158 unsigned Index) const;
159 macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset,
160 unsigned Index) const;
142161 macho::SymtabLoadCommand getSymtabLoadCommand() const;
162 macho::DysymtabLoadCommand getDysymtabLoadCommand() const;
143163
164 StringRef getStringTableData() const;
144165 bool is64Bit() const;
145166 void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const;
146167
152173 typedef SmallVector SectionList;
153174 SectionList Sections;
154175 const char *SymtabLoadCmd;
176 const char *DysymtabLoadCmd;
155177 };
156178
157179 }
+0
-212
include/llvm/Object/MachOObject.h less more
None //===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_OBJECT_MACHOOBJECT_H
10 #define LLVM_OBJECT_MACHOOBJECT_H
11
12 #include "llvm/ADT/InMemoryStruct.h"
13 #include "llvm/ADT/OwningPtr.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Object/MachOFormat.h"
16 #include
17
18 namespace llvm {
19
20 class MemoryBuffer;
21 class raw_ostream;
22
23 namespace object {
24
25 /// \brief Wrapper object for manipulating Mach-O object files.
26 ///
27 /// This class is designed to implement a full-featured, efficient, portable,
28 /// and robust Mach-O interface to Mach-O object files. It does not attempt to
29 /// smooth over rough edges in the Mach-O format or generalize access to object
30 /// independent features.
31 ///
32 /// The class is designed around accessing the Mach-O object which is expected
33 /// to be fully loaded into memory.
34 ///
35 /// This class is *not* suitable for concurrent use. For efficient operation,
36 /// the class uses APIs which rely on the ability to cache the results of
37 /// certain calls in internal objects which are not safe for concurrent
38 /// access. This allows the API to be zero-copy on the common paths.
39 //
40 // FIXME: It would be cool if we supported a "paged" MemoryBuffer
41 // implementation. This would allow us to implement a more sensible version of
42 // MemoryObject which can work like a MemoryBuffer, but be more efficient for
43 // objects which are in the current address space.
44 class MachOObject {
45 public:
46 struct LoadCommandInfo {
47 /// The load command information.
48 macho::LoadCommand Command;
49
50 /// The offset to the start of the load command in memory.
51 uint64_t Offset;
52 };
53
54 private:
55 OwningPtr Buffer;
56
57 /// Whether the object is little endian.
58 bool IsLittleEndian;
59 /// Whether the object is 64-bit.
60 bool Is64Bit;
61 /// Whether the object is swapped endianness from the host.
62 bool IsSwappedEndian;
63 /// Whether the string table has been registered.
64 bool HasStringTable;
65
66 /// The cached information on the load commands.
67 LoadCommandInfo *LoadCommands;
68 mutable unsigned NumLoadedCommands;
69
70 /// The cached copy of the header.
71 macho::Header Header;
72 macho::Header64Ext Header64Ext;
73
74 /// Cache string table information.
75 StringRef StringTable;
76
77 private:
78 MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit);
79
80 public:
81 ~MachOObject();
82
83 /// \brief Load a Mach-O object from a MemoryBuffer object.
84 ///
85 /// \param Buffer - The buffer to load the object from. This routine takes
86 /// exclusive ownership of the buffer (which is passed to the returned object
87 /// on success).
88 /// \param ErrorStr [out] - If given, will be set to a user readable error
89 /// message on failure.
90 /// \returns The loaded object, or null on error.
91 static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer,
92 std::string *ErrorStr = 0);
93
94 /// @name File Information
95 /// @{
96
97 bool isLittleEndian() const { return IsLittleEndian; }
98 bool isSwappedEndian() const { return IsSwappedEndian; }
99 bool is64Bit() const { return Is64Bit; }
100
101 unsigned getHeaderSize() const {
102 return Is64Bit ? macho::Header64Size : macho::Header32Size;
103 }
104
105 StringRef getData(size_t Offset, size_t Size) const;
106
107 /// @}
108 /// @name String Table Data
109 /// @{
110
111 StringRef getStringTableData() const {
112 assert(HasStringTable && "String table has not been registered!");
113 return StringTable;
114 }
115
116 StringRef getStringAtIndex(unsigned Index) const {
117 size_t End = getStringTableData().find('\0', Index);
118 return getStringTableData().slice(Index, End);
119 }
120
121 void RegisterStringTable(macho::SymtabLoadCommand &SLC);
122
123 /// @}
124 /// @name Object Header Access
125 /// @{
126
127 const macho::Header &getHeader() const { return Header; }
128 const macho::Header64Ext &getHeader64Ext() const {
129 assert(is64Bit() && "Invalid access!");
130 return Header64Ext;
131 }
132
133 /// @}
134 /// @name Object Structure Access
135 /// @{
136
137 // TODO: Would be useful to have an iterator based version
138 // of this.
139 /// \brief Retrieve the information for the given load command.
140 const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const;
141
142 void ReadSegmentLoadCommand(
143 const LoadCommandInfo &LCI,
144 InMemoryStruct &Res) const;
145 void ReadSegment64LoadCommand(
146 const LoadCommandInfo &LCI,
147 InMemoryStruct &Res) const;
148 void ReadSymtabLoadCommand(
149 const LoadCommandInfo &LCI,
150 InMemoryStruct &Res) const;
151 void ReadDysymtabLoadCommand(
152 const LoadCommandInfo &LCI,
153 InMemoryStruct &Res) const;
154 void ReadLinkeditDataLoadCommand(
155 const LoadCommandInfo &LCI,
156 InMemoryStruct &Res) const;
157 void ReadLinkerOptionsLoadCommand(
158 const LoadCommandInfo &LCI,
159 InMemoryStruct &Res) const;
160 void ReadIndirectSymbolTableEntry(
161 const macho::DysymtabLoadCommand &DLC,
162 unsigned Index,
163 InMemoryStruct &Res) const;
164 void ReadSection(
165 const LoadCommandInfo &LCI,
166 unsigned Index,
167 InMemoryStruct &Res) const;
168 void ReadSection64(
169 const LoadCommandInfo &LCI,
170 unsigned Index,
171 InMemoryStruct &Res) const;
172 void ReadRelocationEntry(
173 uint64_t RelocationTableOffset, unsigned Index,
174 InMemoryStruct &Res) const;
175 void ReadSymbolTableEntry(
176 uint64_t SymbolTableOffset, unsigned Index,
177 InMemoryStruct &Res) const;
178 void ReadSymbol64TableEntry(
179 uint64_t SymbolTableOffset, unsigned Index,
180 InMemoryStruct &Res) const;
181 void ReadDataInCodeTableEntry(
182 uint64_t TableOffset, unsigned Index,
183 InMemoryStruct &Res) const;
184 void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const;
185
186 /// @}
187
188 /// @name Object Dump Facilities
189 /// @{
190 /// dump - Support for debugging, callable in GDB: V->dump()
191 //
192 void dump() const;
193 void dumpHeader() const;
194
195 /// print - Implement operator<< on Value.
196 ///
197 void print(raw_ostream &O) const;
198 void printHeader(raw_ostream &O) const;
199
200 /// @}
201 };
202
203 inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) {
204 V.print(OS);
205 return OS;
206 }
207
208 } // end namespace object
209 } // end namespace llvm
210
211 #endif
1515
1616 #include "RuntimeDyldImpl.h"
1717 #include "llvm/ADT/IndexedMap.h"
18 #include "llvm/Object/MachOObject.h"
18 #include "llvm/Object/MachO.h"
1919 #include "llvm/Support/Format.h"
2020
2121 using namespace llvm;
33 COFFObjectFile.cpp
44 ELFObjectFile.cpp
55 Error.cpp
6 MachOObject.cpp
76 MachOObjectFile.cpp
87 Object.cpp
98 ObjectFile.cpp
+0
-422
lib/Object/MachOObject.cpp less more
None //===- MachOObject.cpp - Mach-O Object File Wrapper -----------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Object/MachOObject.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/DataExtractor.h"
13 #include "llvm/Support/Debug.h"
14 #include "llvm/Support/Host.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/Support/SwapByteOrder.h"
17 #include "llvm/Support/raw_ostream.h"
18
19 using namespace llvm;
20 using namespace llvm::object;
21
22 /* Translation Utilities */
23
24 template
25 static void SwapValue(T &Value) {
26 Value = sys::SwapByteOrder(Value);
27 }
28
29 template
30 static void SwapStruct(T &Value);
31
32 template
33 static void ReadInMemoryStruct(const MachOObject &MOO,
34 StringRef Buffer, uint64_t Base,
35 InMemoryStruct &Res) {
36 typedef T struct_type;
37 uint64_t Size = sizeof(struct_type);
38
39 // Check that the buffer contains the expected data.
40 if (Base + Size > Buffer.size()) {
41 Res = 0;
42 return;
43 }
44
45 // Check whether we can return a direct pointer.
46 struct_type *Ptr = reinterpret_cast(
47 const_cast(Buffer.data() + Base));
48 if (!MOO.isSwappedEndian()) {
49 Res = Ptr;
50 return;
51 }
52
53 // Otherwise, copy the struct and translate the values.
54 Res = *Ptr;
55 SwapStruct(*Res);
56 }
57
58 /* *** */
59
60 MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_,
61 bool Is64Bit_)
62 : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_),
63 IsSwappedEndian(IsLittleEndian != sys::IsLittleEndianHost),
64 HasStringTable(false), LoadCommands(0), NumLoadedCommands(0) {
65 // Load the common header.
66 memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header));
67 if (IsSwappedEndian) {
68 SwapValue(Header.Magic);
69 SwapValue(Header.CPUType);
70 SwapValue(Header.CPUSubtype);
71 SwapValue(Header.FileType);
72 SwapValue(Header.NumLoadCommands);
73 SwapValue(Header.SizeOfLoadCommands);
74 SwapValue(Header.Flags);
75 }
76
77 if (is64Bit()) {
78 memcpy(&Header64Ext, Buffer->getBuffer().data() + sizeof(Header),
79 sizeof(Header64Ext));
80 if (IsSwappedEndian) {
81 SwapValue(Header64Ext.Reserved);
82 }
83 }
84
85 // Create the load command array if sane.
86 if (getHeader().NumLoadCommands < (1 << 20))
87 LoadCommands = new LoadCommandInfo[getHeader().NumLoadCommands];
88 }
89
90 MachOObject::~MachOObject() {
91 delete [] LoadCommands;
92 }
93
94 MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer,
95 std::string *ErrorStr) {
96 // First, check the magic value and initialize the basic object info.
97 bool IsLittleEndian = false, Is64Bit = false;
98 StringRef Magic = Buffer->getBuffer().slice(0, 4);
99 if (Magic == "\xFE\xED\xFA\xCE") {
100 } else if (Magic == "\xCE\xFA\xED\xFE") {
101 IsLittleEndian = true;
102 } else if (Magic == "\xFE\xED\xFA\xCF") {
103 Is64Bit = true;
104 } else if (Magic == "\xCF\xFA\xED\xFE") {
105 IsLittleEndian = true;
106 Is64Bit = true;
107 } else {
108 if (ErrorStr) *ErrorStr = "not a Mach object file (invalid magic)";
109 return 0;
110 }
111
112 // Ensure that the at least the full header is present.
113 unsigned HeaderSize = Is64Bit ? macho::Header64Size : macho::Header32Size;
114 if (Buffer->getBufferSize() < HeaderSize) {
115 if (ErrorStr) *ErrorStr = "not a Mach object file (invalid header)";
116 return 0;
117 }
118
119 OwningPtr Object(new MachOObject(Buffer, IsLittleEndian,
120 Is64Bit));
121
122 // Check for bogus number of load commands.
123 if (Object->getHeader().NumLoadCommands >= (1 << 20)) {
124 if (ErrorStr) *ErrorStr = "not a Mach object file (unreasonable header)";
125 return 0;
126 }
127
128 if (ErrorStr) *ErrorStr = "";
129 return Object.take();
130 }
131
132 StringRef MachOObject::getData(size_t Offset, size_t Size) const {
133 return Buffer->getBuffer().substr(Offset,Size);
134 }
135
136 void MachOObject::RegisterStringTable(macho::SymtabLoadCommand &SLC) {
137 HasStringTable = true;
138 StringTable = Buffer->getBuffer().substr(SLC.StringTableOffset,
139 SLC.StringTableSize);
140 }
141
142 const MachOObject::LoadCommandInfo &
143 MachOObject::getLoadCommandInfo(unsigned Index) const {
144 assert(Index < getHeader().NumLoadCommands && "Invalid index!");
145
146 // Load the command, if necessary.
147 if (Index >= NumLoadedCommands) {
148 uint64_t Offset;
149 if (Index == 0) {
150 Offset = getHeaderSize();
151 } else {
152 const LoadCommandInfo &Prev = getLoadCommandInfo(Index - 1);
153 Offset = Prev.Offset + Prev.Command.Size;
154 }
155
156 LoadCommandInfo &Info = LoadCommands[Index];
157 memcpy(&Info.Command, Buffer->getBuffer().data() + Offset,
158 sizeof(macho::LoadCommand));
159 if (IsSwappedEndian) {
160 SwapValue(Info.Command.Type);
161 SwapValue(Info.Command.Size);
162 }
163 Info.Offset = Offset;
164 NumLoadedCommands = Index + 1;
165 }
166
167 return LoadCommands[Index];
168 }
169
170 template<>
171 void SwapStruct(macho::SegmentLoadCommand &Value) {
172 SwapValue(Value.Type);
173 SwapValue(Value.Size);
174 SwapValue(Value.VMAddress);
175 SwapValue(Value.VMSize);
176 SwapValue(Value.FileOffset);
177 SwapValue(Value.FileSize);
178 SwapValue(Value.MaxVMProtection);
179 SwapValue(Value.InitialVMProtection);
180 SwapValue(Value.NumSections);
181 SwapValue(Value.Flags);
182 }
183 void MachOObject::ReadSegmentLoadCommand(const LoadCommandInfo &LCI,
184 InMemoryStruct &Res) const {
185 ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
186 }
187
188 template<>
189 void SwapStruct(macho::Segment64LoadCommand &Value) {
190 SwapValue(Value.Type);
191 SwapValue(Value.Size);
192 SwapValue(Value.VMAddress);
193 SwapValue(Value.VMSize);
194 SwapValue(Value.FileOffset);
195 SwapValue(Value.FileSize);
196 SwapValue(Value.MaxVMProtection);
197 SwapValue(Value.InitialVMProtection);
198 SwapValue(Value.NumSections);
199 SwapValue(Value.Flags);
200 }
201 void MachOObject::ReadSegment64LoadCommand(const LoadCommandInfo &LCI,
202 InMemoryStruct &Res) const {
203 ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
204 }
205
206 template<>
207 void SwapStruct(macho::SymtabLoadCommand &Value) {
208 SwapValue(Value.Type);
209 SwapValue(Value.Size);
210 SwapValue(Value.SymbolTableOffset);
211 SwapValue(Value.NumSymbolTableEntries);
212 SwapValue(Value.StringTableOffset);
213 SwapValue(Value.StringTableSize);
214 }
215 void MachOObject::ReadSymtabLoadCommand(const LoadCommandInfo &LCI,
216 InMemoryStruct &Res) const {
217 ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
218 }
219
220 template<>
221 void SwapStruct(macho::DysymtabLoadCommand &Value) {
222 SwapValue(Value.Type);
223 SwapValue(Value.Size);
224 SwapValue(Value.LocalSymbolsIndex);
225 SwapValue(Value.NumLocalSymbols);
226 SwapValue(Value.ExternalSymbolsIndex);
227 SwapValue(Value.NumExternalSymbols);
228 SwapValue(Value.UndefinedSymbolsIndex);
229 SwapValue(Value.NumUndefinedSymbols);
230 SwapValue(Value.TOCOffset);
231 SwapValue(Value.NumTOCEntries);
232 SwapValue(Value.ModuleTableOffset);
233 SwapValue(Value.NumModuleTableEntries);
234 SwapValue(Value.ReferenceSymbolTableOffset);
235 SwapValue(Value.NumReferencedSymbolTableEntries);
236 SwapValue(Value.IndirectSymbolTableOffset);
237 SwapValue(Value.NumIndirectSymbolTableEntries);
238 SwapValue(Value.ExternalRelocationTableOffset);
239 SwapValue(Value.NumExternalRelocationTableEntries);
240 SwapValue(Value.LocalRelocationTableOffset);
241 SwapValue(Value.NumLocalRelocationTableEntries);
242 }
243 void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI,
244 InMemoryStruct &Res) const {
245 ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
246 }
247
248 template<>
249 void SwapStruct(macho::LinkeditDataLoadCommand &Value) {
250 SwapValue(Value.Type);
251 SwapValue(Value.Size);
252 SwapValue(Value.DataOffset);
253 SwapValue(Value.DataSize);
254 }
255 void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI,
256 InMemoryStruct &Res) const {
257 ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
258 }
259
260 template<>
261 void SwapStruct(macho::LinkerOptionsLoadCommand &Value) {
262 SwapValue(Value.Type);
263 SwapValue(Value.Size);
264 SwapValue(Value.Count);
265 }
266 void MachOObject::ReadLinkerOptionsLoadCommand(const LoadCommandInfo &LCI,
267 InMemoryStruct &Res) const {
268 ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res);
269 }
270
271 template<>
272 void SwapStruct(macho::IndirectSymbolTableEntry &Value) {
273 SwapValue(Value.Index);
274 }
275 void
276 MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC,
277 unsigned Index,
278 InMemoryStruct &Res) const {
279 uint64_t Offset = (DLC.IndirectSymbolTableOffset +
280 Index * sizeof(macho::IndirectSymbolTableEntry));
281 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
282 }
283
284
285 template<>
286 void SwapStruct(macho::Section &Value) {
287 SwapValue(Value.Address);
288 SwapValue(Value.Size);
289 SwapValue(Value.Offset);
290 SwapValue(Value.Align);
291 SwapValue(Value.RelocationTableOffset);
292 SwapValue(Value.NumRelocationTableEntries);
293 SwapValue(Value.Flags);
294 SwapValue(Value.Reserved1);
295 SwapValue(Value.Reserved2);
296 }
297 void MachOObject::ReadSection(const LoadCommandInfo &LCI,
298 unsigned Index,
299 InMemoryStruct &Res) const {
300 assert(LCI.Command.Type == macho::LCT_Segment &&
301 "Unexpected load command info!");
302 uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) +
303 Index * sizeof(macho::Section));
304 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
305 }
306
307 template<>
308 void SwapStruct(macho::Section64 &Value) {
309 SwapValue(Value.Address);
310 SwapValue(Value.Size);
311 SwapValue(Value.Offset);
312 SwapValue(Value.Align);
313 SwapValue(Value.RelocationTableOffset);
314 SwapValue(Value.NumRelocationTableEntries);
315 SwapValue(Value.Flags);
316 SwapValue(Value.Reserved1);
317 SwapValue(Value.Reserved2);
318 SwapValue(Value.Reserved3);
319 }
320 void MachOObject::ReadSection64(const LoadCommandInfo &LCI,
321 unsigned Index,
322 InMemoryStruct &Res) const {
323 assert(LCI.Command.Type == macho::LCT_Segment64 &&
324 "Unexpected load command info!");
325 uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) +
326 Index * sizeof(macho::Section64));
327 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
328 }
329
330 template<>
331 void SwapStruct(macho::RelocationEntry &Value) {
332 SwapValue(Value.Word0);
333 SwapValue(Value.Word1);
334 }
335 void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset,
336 unsigned Index,
337 InMemoryStruct &Res) const {
338 uint64_t Offset = (RelocationTableOffset +
339 Index * sizeof(macho::RelocationEntry));
340 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
341 }
342
343 template<>
344 void SwapStruct(macho::SymbolTableEntry &Value) {
345 SwapValue(Value.StringIndex);
346 SwapValue(Value.Flags);
347 SwapValue(Value.Value);
348 }
349 void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset,
350 unsigned Index,
351 InMemoryStruct &Res) const {
352 uint64_t Offset = (SymbolTableOffset +
353 Index * sizeof(macho::SymbolTableEntry));
354 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
355 }
356
357 template<>
358 void SwapStruct(macho::Symbol64TableEntry &Value) {
359 SwapValue(Value.StringIndex);
360 SwapValue(Value.Flags);
361 SwapValue(Value.Value);
362 }
363 void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset,
364 unsigned Index,
365 InMemoryStruct &Res) const {
366 uint64_t Offset = (SymbolTableOffset +
367 Index * sizeof(macho::Symbol64TableEntry));
368 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
369 }
370
371 template<>
372 void SwapStruct(macho::DataInCodeTableEntry &Value) {
373 SwapValue(Value.Offset);
374 SwapValue(Value.Length);
375 SwapValue(Value.Kind);
376 }
377 void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset,
378 unsigned Index,
379 InMemoryStruct &Res) const {
380 uint64_t Offset = (TableOffset +
381 Index * sizeof(macho::DataInCodeTableEntry));
382 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
383 }
384
385 void MachOObject::ReadULEB128s(uint64_t Index,
386 SmallVectorImpl &Out) const {
387 DataExtractor extractor(Buffer->getBuffer(), true, 0);
388
389 uint32_t offset = Index;
390 uint64_t data = 0;
391 while (uint64_t delta = extractor.getULEB128(&offset)) {
392 data += delta;
393 Out.push_back(data);
394 }
395 }
396
397 /* ** */
398 // Object Dumping Facilities
399 void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; }
400 void MachOObject::dumpHeader() const { printHeader(dbgs()); dbgs() << '\n'; }
401
402 void MachOObject::printHeader(raw_ostream &O) const {
403 O << "('cputype', " << Header.CPUType << ")\n";
404 O << "('cpusubtype', " << Header.CPUSubtype << ")\n";
405 O << "('filetype', " << Header.FileType << ")\n";
406 O << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
407 O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
408 O << "('flag', " << Header.Flags << ")\n";
409
410 // Print extended header if 64-bit.
411 if (is64Bit())
412 O << "('reserved', " << Header64Ext.Reserved << ")\n";
413 }
414
415 void MachOObject::print(raw_ostream &O) const {
416 O << "Header:\n";
417 printHeader(O);
418 O << "Load Commands:\n";
419
420 O << "Buffer:\n";
421 }
119119 }
120120
121121 template<>
122 void SwapStruct(macho::Header64Ext &E) {
123 SwapValue(E.Reserved);
124 }
125
126 template<>
122127 void SwapStruct(macho::SymtabLoadCommand &C) {
123128 SwapValue(C.Type);
124129 SwapValue(C.Size);
126131 SwapValue(C.NumSymbolTableEntries);
127132 SwapValue(C.StringTableOffset);
128133 SwapValue(C.StringTableSize);
134 }
135
136 template<>
137 void SwapStruct(macho::DysymtabLoadCommand &C) {
138 SwapValue(C.Type);
139 SwapValue(C.Size);
140 SwapValue(C.LocalSymbolsIndex);
141 SwapValue(C.NumLocalSymbols);
142 SwapValue(C.ExternalSymbolsIndex);
143 SwapValue(C.NumExternalSymbols);
144 SwapValue(C.UndefinedSymbolsIndex);
145 SwapValue(C.NumUndefinedSymbols);
146 SwapValue(C.TOCOffset);
147 SwapValue(C.NumTOCEntries);
148 SwapValue(C.ModuleTableOffset);
149 SwapValue(C.NumModuleTableEntries);
150 SwapValue(C.ReferenceSymbolTableOffset);
151 SwapValue(C.NumReferencedSymbolTableEntries);
152 SwapValue(C.IndirectSymbolTableOffset);
153 SwapValue(C.NumIndirectSymbolTableEntries);
154 SwapValue(C.ExternalRelocationTableOffset);
155 SwapValue(C.NumExternalRelocationTableEntries);
156 SwapValue(C.LocalRelocationTableOffset);
157 SwapValue(C.NumLocalRelocationTableEntries);
129158 }
130159
131160 template<>
164193 SwapValue(C.Flags);
165194 }
166195
196 template<>
197 void SwapStruct(macho::IndirectSymbolTableEntry &C) {
198 SwapValue(C.Index);
199 }
200
201 template<>
202 void SwapStruct(macho::LinkerOptionsLoadCommand &C) {
203 SwapValue(C.Type);
204 SwapValue(C.Size);
205 SwapValue(C.Count);
206 }
207
208 template<>
209 void SwapStruct(macho::DataInCodeTableEntry &C) {
210 SwapValue(C.Offset);
211 SwapValue(C.Length);
212 SwapValue(C.Kind);
213 }
214
167215 template
168216 T getStruct(const MachOObjectFile *O, const char *P) {
169217 T Cmd;
173221 return Cmd;
174222 }
175223
176 static macho::SegmentLoadCommand
177 getSegmentLoadCommand(const MachOObjectFile *O,
178 const MachOObjectFile::LoadCommandInfo &L) {
179 return getStruct(O, L.Ptr);
180 }
181
182 static macho::Segment64LoadCommand
183 getSegment64LoadCommand(const MachOObjectFile *O,
184 const MachOObjectFile::LoadCommandInfo &L) {
185 return getStruct(O, L.Ptr);
186 }
187
188224 static uint32_t
189225 getSegmentLoadCommandNumSections(const MachOObjectFile *O,
190226 const MachOObjectFile::LoadCommandInfo &L) {
191227 if (O->is64Bit()) {
192 macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L);
228 macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L);
193229 return S.NumSections;
194230 }
195 macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L);
231 macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L);
196232 return S.NumSections;
197233 }
198234
199 static const SectionBase *
200 getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
201 unsigned Sec) {
235 static const char *
236 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L,
237 unsigned Sec) {
202238 uintptr_t CommandAddr = reinterpret_cast(L.Ptr);
203239
204240 bool Is64 = O->is64Bit();
208244 sizeof(macho::Section);
209245
210246 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
211 return reinterpret_castSectionBase*>(SectionAddr);
247 return reinterpret_castchar*>(SectionAddr);
212248 }
213249
214250 static const char *getPtr(const MachOObjectFile *O, size_t Offset) {
376412 bool IsLittleEndian, bool Is64bits,
377413 error_code &ec)
378414 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
379 SymtabLoadCmd(NULL) {
415 SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL) {
380416 uint32_t LoadCommandCount = this->getHeader().NumLoadCommands;
381417 macho::LoadCommandType SegmentLoadType = is64Bit() ?
382418 macho::LCT_Segment64 : macho::LCT_Segment;
386422 if (Load.C.Type == macho::LCT_Symtab) {
387423 assert(!SymtabLoadCmd && "Multiple symbol tables");
388424 SymtabLoadCmd = Load.Ptr;
389 }
390
391 if (Load.C.Type == SegmentLoadType) {
425 } else if (Load.C.Type == macho::LCT_Dysymtab) {
426 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables");
427 DysymtabLoadCmd = Load.Ptr;
428 } else if (Load.C.Type == SegmentLoadType) {
392429 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
393430 for (unsigned J = 0; J < NumSections; ++J) {
394 const SectionBase *Sec = getSectionBase(this, Load, J);
395 Sections.push_back(reinterpret_cast(Sec));
431 const char *Sec = getSectionPtr(this, Load, J);
432 Sections.push_back(Sec);
396433 }
397434 }
398435
415452
416453 error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
417454 StringRef &Res) const {
418 macho::SymtabLoadCommand S = getSymtabLoadCommand();
419 const char *StringTable = getPtr(this, S.StringTableOffset);
455 StringRef StringTable = getStringTableData();
420456 SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb);
421 const char *Start = &StringTable[Entry.StringIndex];
457 const char *Start = &StringTable.data()[Entry.StringIndex];
422458 Res = StringRef(Start);
423459 return object_error::success;
424460 }
12701306 report_fatal_error("get_load_name() unimplemented in MachOObjectFile");
12711307 }
12721308
1309 relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const {
1310 DataRefImpl DRI;
1311 DRI.d.a = Index;
1312 return getSectionRelBegin(DRI);
1313 }
1314
1315 relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const {
1316 DataRefImpl DRI;
1317 DRI.d.a = Index;
1318 return getSectionRelEnd(DRI);
1319 }
1320
12731321 StringRef
12741322 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
12751323 ArrayRef Raw = getSectionRawFinalSegmentName(Sec);
13741422 return getStruct(this, Sections[DRI.d.a]);
13751423 }
13761424
1425 macho::Section MachOObjectFile::getSection(const LoadCommandInfo &L,
1426 unsigned Index) const {
1427 const char *Sec = getSectionPtr(this, L, Index);
1428 return getStruct(this, Sec);
1429 }
1430
1431 macho::Section64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
1432 unsigned Index) const {
1433 const char *Sec = getSectionPtr(this, L, Index);
1434 return getStruct(this, Sec);
1435 }
1436
13771437 macho::SymbolTableEntry
13781438 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
13791439 const char *P = reinterpret_cast(DRI.p);
13911451 return getStruct(this, L.Ptr);
13921452 }
13931453
1454 macho::SegmentLoadCommand
1455 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
1456 return getStruct(this, L.Ptr);
1457 }
1458
1459 macho::Segment64LoadCommand
1460 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
1461 return getStruct(this, L.Ptr);
1462 }
1463
1464 macho::LinkerOptionsLoadCommand
1465 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {
1466 return getStruct(this, L.Ptr);
1467 }
1468
13941469 macho::RelocationEntry
13951470 MachOObjectFile::getRelocation(DataRefImpl Rel) const {
13961471 const char *P = reinterpret_cast(Rel.p);
14011476 return getStruct(this, getPtr(this, 0));
14021477 }
14031478
1404 macho::SymtabLoadCommand
1405 MachOObjectFile::getSymtabLoadCommand() const {
1479 macho::Header64Ext MachOObjectFile::getHeader64Ext() const {
1480 return
1481 getStruct(this, getPtr(this, sizeof(macho::Header)));
1482 }
1483
1484 macho::IndirectSymbolTableEntry MachOObjectFile::getIndirectSymbolTableEntry(
1485 const macho::DysymtabLoadCommand &DLC,
1486 unsigned Index) const {
1487 uint64_t Offset = DLC.IndirectSymbolTableOffset +
1488 Index * sizeof(macho::IndirectSymbolTableEntry);
1489 return getStruct(this, getPtr(this, Offset));
1490 }
1491
1492 macho::DataInCodeTableEntry
1493 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
1494 unsigned Index) const {
1495 uint64_t Offset = DataOffset + Index * sizeof(macho::DataInCodeTableEntry);
1496 return getStruct(this, getPtr(this, Offset));
1497 }
1498
1499 macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const {
14061500 return getStruct(this, SymtabLoadCmd);
1501 }
1502
1503 macho::DysymtabLoadCommand MachOObjectFile::getDysymtabLoadCommand() const {
1504 return getStruct(this, DysymtabLoadCmd);
1505 }
1506
1507 StringRef MachOObjectFile::getStringTableData() const {
1508 macho::SymtabLoadCommand S = getSymtabLoadCommand();
1509 return getData().substr(S.StringTableOffset, S.StringTableSize);
14071510 }
14081511
14091512 bool MachOObjectFile::is64Bit() const {
1616 #include "llvm/ExecutionEngine/ObjectBuffer.h"
1717 #include "llvm/ExecutionEngine/ObjectImage.h"
1818 #include "llvm/ExecutionEngine/RuntimeDyld.h"
19 #include "llvm/Object/MachOObject.h"
19 #include "llvm/Object/MachO.h"
2020 #include "llvm/Support/CommandLine.h"
2121 #include "llvm/Support/ManagedStatic.h"
2222 #include "llvm/Support/Memory.h"
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 #include "llvm/Object/MachOObject.h"
13 #include "llvm/Object/MachO.h"
1414 #include "llvm/ADT/StringExtras.h"
1515 #include "llvm/ADT/Twine.h"
16 #include "llvm/Support/Casting.h"
1617 #include "llvm/Support/CommandLine.h"
1718 #include "llvm/Support/Format.h"
1819 #include "llvm/Support/ManagedStatic.h"
6566 outs() << " ('flags', " << Flags << ")\n";
6667 }
6768
68 static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name,
69 static int DumpSectionData(const MachOObjectFile &Obj, unsigned Index,
70 StringRef Name,
6971 StringRef SegmentName, uint64_t Address,
7072 uint64_t Size, uint32_t Offset,
7173 uint32_t Align, uint32_t RelocationTableOffset,
9193 outs() << " ),\n";
9294
9395 // Dump the relocation entries.
94 int Res = 0;
9596 outs() << " ('_relocations', [\n";
96 for (unsigned i = 0; i != NumRelocationTableEntries; ++i) {
97 InMemoryStruct RE;
98 Obj.ReadRelocationEntry(RelocationTableOffset, i, RE);
99 if (!RE) {
100 Res = Error("unable to read relocation table entry '" + Twine(i) + "'");
101 break;
102 }
103
104 outs() << " # Relocation " << i << "\n";
105 outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n";
106 outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n";
97 unsigned RelNum = 0;
98 error_code EC;
99 for (relocation_iterator I = Obj.getSectionRelBegin(Index),
100 E = Obj.getSectionRelEnd(Index); I != E; I.increment(EC), ++RelNum) {
101 macho::RelocationEntry RE = Obj.getRelocation(I->getRawDataRefImpl());
102 outs() << " # Relocation " << RelNum << "\n";
103 outs() << " (('word-0', " << format("0x%x", RE.Word0) << "),\n";
104 outs() << " ('word-1', " << format("0x%x", RE.Word1) << ")),\n";
107105 }
108106 outs() << " ])\n";
109107
110108 // Dump the section data, if requested.
111109 if (ShowSectionData) {
112110 outs() << " ('_section_data', '";
113 StringRef Data = Obj.getData(Offset, Size);
111 StringRef Data = Obj.getData().substr(Offset, Size);
114112 for (unsigned i = 0; i != Data.size(); ++i) {
115113 if (i && (i % 4) == 0)
116114 outs() << ' ';
120118 outs() << "')\n";
121119 }
122120
123 return Res;
124 }
125
126 static int DumpSegmentCommand(MachOObject &Obj,
127 const MachOObject::LoadCommandInfo &LCI) {
128 InMemoryStruct SLC;
129 Obj.ReadSegmentLoadCommand(LCI, SLC);
130 if (!SLC)
131 return Error("unable to read segment load command");
132
133 DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress,
134 SLC->VMSize, SLC->FileOffset, SLC->FileSize,
135 SLC->MaxVMProtection, SLC->InitialVMProtection,
136 SLC->NumSections, SLC->Flags);
121 return 0;
122 }
123
124 static int DumpSegmentCommand(const MachOObjectFile &Obj,
125 const MachOObjectFile::LoadCommandInfo &LCI) {
126 macho::SegmentLoadCommand SLC = Obj.getSegmentLoadCommand(LCI);
127
128 DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress,
129 SLC.VMSize, SLC.FileOffset, SLC.FileSize,
130 SLC.MaxVMProtection, SLC.InitialVMProtection,
131 SLC.NumSections, SLC.Flags);
137132
138133 // Dump the sections.
139 int Res = 0;
140134 outs() << " ('sections', [\n";
141 for (unsigned i = 0; i != SLC->NumSections; ++i) {
142 InMemoryStruct Sect;
143 Obj.ReadSection(LCI, i, Sect);
144 if (!SLC) {
145 Res = Error("unable to read section '" + Twine(i) + "'");
146 break;
147 }
148
149 if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16),
150 StringRef(Sect->SegmentName, 16), Sect->Address,
151 Sect->Size, Sect->Offset, Sect->Align,
152 Sect->RelocationTableOffset,
153 Sect->NumRelocationTableEntries, Sect->Flags,
154 Sect->Reserved1, Sect->Reserved2)))
155 break;
156 }
157 outs() << " ])\n";
158
159 return Res;
160 }
161
162 static int DumpSegment64Command(MachOObject &Obj,
163 const MachOObject::LoadCommandInfo &LCI) {
164 InMemoryStruct SLC;
165 Obj.ReadSegment64LoadCommand(LCI, SLC);
166 if (!SLC)
167 return Error("unable to read segment load command");
168
169 DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress,
170 SLC->VMSize, SLC->FileOffset, SLC->FileSize,
171 SLC->MaxVMProtection, SLC->InitialVMProtection,
172 SLC->NumSections, SLC->Flags);
135 for (unsigned i = 0; i != SLC.NumSections; ++i) {
136 macho::Section Sect = Obj.getSection(LCI, i);
137 DumpSectionData(Obj, i, StringRef(Sect.Name, 16),
138 StringRef(Sect.SegmentName, 16), Sect.Address,
139 Sect.Size, Sect.Offset, Sect.Align,
140 Sect.RelocationTableOffset,
141 Sect.NumRelocationTableEntries, Sect.Flags,
142 Sect.Reserved1, Sect.Reserved2);
143 }
144 outs() << " ])\n";
145
146 return 0;
147 }
148
149 static int DumpSegment64Command(const MachOObjectFile &Obj,
150 const MachOObjectFile::LoadCommandInfo &LCI) {
151 macho::Segment64LoadCommand SLC = Obj.getSegment64LoadCommand(LCI);
152 DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress,
153 SLC.VMSize, SLC.FileOffset, SLC.FileSize,
154 SLC.MaxVMProtection, SLC.InitialVMProtection,
155 SLC.NumSections, SLC.Flags);
173156
174157 // Dump the sections.
175 int Res = 0;
176158 outs() << " ('sections', [\n";
177 for (unsigned i = 0; i != SLC->NumSections; ++i) {
178 InMemoryStruct Sect;
179 Obj.ReadSection64(LCI, i, Sect);
180 if (!SLC) {
181 Res = Error("unable to read section '" + Twine(i) + "'");
182 break;
183 }
184
185 if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16),
186 StringRef(Sect->SegmentName, 16), Sect->Address,
187 Sect->Size, Sect->Offset, Sect->Align,
188 Sect->RelocationTableOffset,
189 Sect->NumRelocationTableEntries, Sect->Flags,
190 Sect->Reserved1, Sect->Reserved2,
191 Sect->Reserved3)))
192 break;
193 }
194 outs() << " ])\n";
195
196 return Res;
197 }
198
199 static void DumpSymbolTableEntryData(MachOObject &Obj,
159 for (unsigned i = 0; i != SLC.NumSections; ++i) {
160 macho::Section64 Sect = Obj.getSection64(LCI, i);
161
162 DumpSectionData(Obj, i, StringRef(Sect.Name, 16),
163 StringRef(Sect.SegmentName, 16), Sect.Address,
164 Sect.Size, Sect.Offset, Sect.Align,
165 Sect.RelocationTableOffset,
166 Sect.NumRelocationTableEntries, Sect.Flags,
167 Sect.Reserved1, Sect.Reserved2,
168 Sect.Reserved3);
169 }
170 outs() << " ])\n";
171
172 return 0;
173 }
174
175 static void DumpSymbolTableEntryData(const MachOObjectFile &Obj,
200176 unsigned Index, uint32_t StringIndex,
201177 uint8_t Type, uint8_t SectionIndex,
202 uint16_t Flags, uint64_t Value) {
178 uint16_t Flags, uint64_t Value,
179 StringRef StringTable) {
180 const char *Name = &StringTable.data()[StringIndex];
203181 outs() << " # Symbol " << Index << "\n";
204182 outs() << " (('n_strx', " << StringIndex << ")\n";
205183 outs() << " ('n_type', " << format("0x%x", Type) << ")\n";
206184 outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n";
207185 outs() << " ('n_desc', " << Flags << ")\n";
208186 outs() << " ('n_value', " << Value << ")\n";
209 outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n";
187 outs() << " ('_string', '" << Name << "')\n";
210188 outs() << " ),\n";
211189 }
212190
213 static int DumpSymtabCommand(MachOObject &Obj,
214 const MachOObject::LoadCommandInfo &LCI) {
215 InMemoryStruct SLC;
216 Obj.ReadSymtabLoadCommand(LCI, SLC);
217 if (!SLC)
218 return Error("unable to read segment load command");
219
220 outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n";
221 outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n";
222 outs() << " ('stroff', " << SLC->StringTableOffset << ")\n";
223 outs() << " ('strsize', " << SLC->StringTableSize << ")\n";
224
225 // Cache the string table data.
226 Obj.RegisterStringTable(*SLC);
191 static int DumpSymtabCommand(const MachOObjectFile &Obj) {
192 macho::SymtabLoadCommand SLC = Obj.getSymtabLoadCommand();
193
194 outs() << " ('symoff', " << SLC.SymbolTableOffset << ")\n";
195 outs() << " ('nsyms', " << SLC.NumSymbolTableEntries << ")\n";
196 outs() << " ('stroff', " << SLC.StringTableOffset << ")\n";
197 outs() << " ('strsize', " << SLC.StringTableSize << ")\n";
227198
228199 // Dump the string data.
229200 outs() << " ('_string_data', '";
230 outs().write_escaped(Obj.getStringTableData(),
201 StringRef StringTable = Obj.getStringTableData();
202 outs().write_escaped(StringTable,
231203 /*UseHexEscapes=*/true) << "')\n";
232204
233205 // Dump the symbol table.
234 int Res = 0;
235206 outs() << " ('_symbols', [\n";
236 for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) {
207 error_code EC;
208 unsigned SymNum = 0;
209 for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E;
210 I.increment(EC), ++SymNum) {
211 DataRefImpl DRI = I->getRawDataRefImpl();
237212 if (Obj.is64Bit()) {
238 InMemoryStruct STE;
239 Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE);
240 if (!STE) {
241 Res = Error("unable to read symbol: '" + Twine(i) + "'");
242 break;
243 }
244
245 DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type,
246 STE->SectionIndex, STE->Flags, STE->Value);
213 macho::Symbol64TableEntry STE = Obj.getSymbol64TableEntry(DRI);
214 DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type,
215 STE.SectionIndex, STE.Flags, STE.Value,
216 StringTable);
247217 } else {
248 InMemoryStruct STE;
249 Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE);
250 if (!SLC) {
251 Res = Error("unable to read symbol: '" + Twine(i) + "'");
252 break;
253 }
254
255 DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type,
256 STE->SectionIndex, STE->Flags, STE->Value);
218 macho::SymbolTableEntry STE = Obj.getSymbolTableEntry(DRI);
219 DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type,
220 STE.SectionIndex, STE.Flags, STE.Value,
221 StringTable);
257222 }
258223 }
259224 outs() << " ])\n";
260225
261 return Res;
262 }
263
264 static int DumpDysymtabCommand(MachOObject &Obj,
265 const MachOObject::LoadCommandInfo &LCI) {
266 InMemoryStruct DLC;
267 Obj.ReadDysymtabLoadCommand(LCI, DLC);
268 if (!DLC)
269 return Error("unable to read segment load command");
270
271 outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n";
272 outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n";
273 outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n";
274 outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n";
275 outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n";
276 outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n";
277 outs() << " ('tocoff', " << DLC->TOCOffset << ")\n";
278 outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n";
279 outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n";
280 outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n";
281 outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n";
226 return 0;
227 }
228
229 static int DumpDysymtabCommand(const MachOObjectFile &Obj) {
230 macho::DysymtabLoadCommand DLC = Obj.getDysymtabLoadCommand();
231
232 outs() << " ('ilocalsym', " << DLC.LocalSymbolsIndex << ")\n";
233 outs() << " ('nlocalsym', " << DLC.NumLocalSymbols << ")\n";
234 outs() << " ('iextdefsym', " << DLC.ExternalSymbolsIndex << ")\n";
235 outs() << " ('nextdefsym', " << DLC.NumExternalSymbols << ")\n";
236 outs() << " ('iundefsym', " << DLC.UndefinedSymbolsIndex << ")\n";
237 outs() << " ('nundefsym', " << DLC.NumUndefinedSymbols << ")\n";
238 outs() << " ('tocoff', " << DLC.TOCOffset << ")\n";
239 outs() << " ('ntoc', " << DLC.NumTOCEntries << ")\n";
240 outs() << " ('modtaboff', " << DLC.ModuleTableOffset << ")\n";
241 outs() << " ('nmodtab', " << DLC.NumModuleTableEntries << ")\n";
242 outs() << " ('extrefsymoff', " << DLC.ReferenceSymbolTableOffset << ")\n";
282243 outs() << " ('nextrefsyms', "
283 << DLC->NumReferencedSymbolTableEntries << ")\n";
284 outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n";
244 << DLC.NumReferencedSymbolTableEntries << ")\n";
245 outs() << " ('indirectsymoff', " << DLC.IndirectSymbolTableOffset << ")\n";
285246 outs() << " ('nindirectsyms', "
286 << DLC->NumIndirectSymbolTableEntries << ")\n";
287 outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n";
288 outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n";
289 outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n";
290 outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n";
247 << DLC.NumIndirectSymbolTableEntries << ")\n";
248 outs() << " ('extreloff', " << DLC.ExternalRelocationTableOffset << ")\n";
249 outs() << " ('nextrel', " << DLC.NumExternalRelocationTableEntries << ")\n";
250 outs() << " ('locreloff', " << DLC.LocalRelocationTableOffset << ")\n";
251 outs() << " ('nlocrel', " << DLC.NumLocalRelocationTableEntries << ")\n";
291252
292253 // Dump the indirect symbol table.
293 int Res = 0;
294254 outs() << " ('_indirect_symbols', [\n";
295 for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) {
296 InMemoryStruct ISTE;
297 Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE);
298 if (!ISTE) {
299 Res = Error("unable to read segment load command");
300 break;
301 }
302
255 for (unsigned i = 0; i != DLC.NumIndirectSymbolTableEntries; ++i) {
256 macho::IndirectSymbolTableEntry ISTE =
257 Obj.getIndirectSymbolTableEntry(DLC, i);
303258 outs() << " # Indirect Symbol " << i << "\n";
304259 outs() << " (('symbol_index', "
305 << format("0x%x", ISTE->Index) << "),),\n";
306 }
307 outs() << " ])\n";
308
309 return Res;
310 }
311
312 static int DumpLinkeditDataCommand(MachOObject &Obj,
313 const MachOObject::LoadCommandInfo &LCI) {
314 InMemoryStruct LLC;
315 Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
316 if (!LLC)
317 return Error("unable to read segment load command");
318
319 outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
320 << " ('datasize', " << LLC->DataSize << ")\n"
260 << format("0x%x", ISTE.Index) << "),),\n";
261 }
262 outs() << " ])\n";
263
264 return 0;
265 }
266
267 static int
268 DumpLinkeditDataCommand(const MachOObjectFile &Obj,
269 const MachOObjectFile::LoadCommandInfo &LCI) {
270 macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI);
271 outs() << " ('dataoff', " << LLC.DataOffset << ")\n"
272 << " ('datasize', " << LLC.DataSize << ")\n"
321273 << " ('_addresses', [\n";
322274
323275 SmallVector Addresses;
324 Obj.ReadULEB128s(LLC->DataOffset, Addresses);
276 Obj.ReadULEB128s(LLC.DataOffset, Addresses);
325277 for (unsigned i = 0, e = Addresses.size(); i != e; ++i)
326278 outs() << " # Address " << i << '\n'
327279 << " ('address', " << format("0x%x", Addresses[i]) << "),\n";
331283 return 0;
332284 }
333285
334 static int DumpDataInCodeDataCommand(MachOObject &Obj,
335 const MachOObject::LoadCommandInfo &LCI) {
336 InMemoryStruct LLC;
337 Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
338 if (!LLC)
339 return Error("unable to read data-in-code load command");
340
341 outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
342 << " ('datasize', " << LLC->DataSize << ")\n"
286 static int
287 DumpDataInCodeDataCommand(const MachOObjectFile &Obj,
288 const MachOObjectFile::LoadCommandInfo &LCI) {
289 macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI);
290 outs() << " ('dataoff', " << LLC.DataOffset << ")\n"
291 << " ('datasize', " << LLC.DataSize << ")\n"
343292 << " ('_data_regions', [\n";
344293
345
346 unsigned NumRegions = LLC->DataSize / 8;
294 unsigned NumRegions = LLC.DataSize / 8;
347295 for (unsigned i = 0; i < NumRegions; ++i) {
348 InMemoryStruct DICE;
349 Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE);
350 if (!DICE)
351 return Error("unable to read DataInCodeTableEntry");
296 macho::DataInCodeTableEntry DICE =
297 Obj.getDataInCodeTableEntry(LLC.DataOffset, i);
352298 outs() << " # DICE " << i << "\n"
353 << " ('offset', " << DICE->Offset << ")\n"
354 << " ('length', " << DICE->Length << ")\n"
355 << " ('kind', " << DICE->Kind << ")\n";
299 << " ('offset', " << DICE.Offset << ")\n"
300 << " ('length', " << DICE.Length << ")\n"
301 << " ('kind', " << DICE.Kind << ")\n";
356302 }
357303
358304 outs() <<" ])\n";
360306 return 0;
361307 }
362308
363 static int DumpLinkerOptionsCommand(MachOObject &Obj,
364 const MachOObject::LoadCommandInfo &LCI) {
365 InMemoryStruct LOLC;
366 Obj.ReadLinkerOptionsLoadCommand(LCI, LOLC);
367 if (!LOLC)
368 return Error("unable to read linker options load command");
369
370 outs() << " ('count', " << LOLC->Count << ")\n"
371 << " ('_strings', [\n";
372
373 uint64_t DataSize = LOLC->Size - sizeof(macho::LinkerOptionsLoadCommand);
374 StringRef Data = Obj.getData(
375 LCI.Offset + sizeof(macho::LinkerOptionsLoadCommand), DataSize);
376 for (unsigned i = 0; i != LOLC->Count; ++i) {
377 std::pair Split = Data.split('\0');
378 outs() << "\t\"";
379 outs().write_escaped(Split.first);
380 outs() << "\",\n";
381 Data = Split.second;
382 }
383 outs() <<" ])\n";
384
385 return 0;
386 }
387
388
389 static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
390 const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index);
391 int Res = 0;
392
393 outs() << " # Load Command " << Index << "\n"
394 << " (('command', " << LCI.Command.Type << ")\n"
395 << " ('size', " << LCI.Command.Size << ")\n";
396 switch (LCI.Command.Type) {
309 static int
310 DumpLinkerOptionsCommand(const MachOObjectFile &Obj,
311 const MachOObjectFile::LoadCommandInfo &LCI) {
312 macho::LinkerOptionsLoadCommand LOLC = Obj.getLinkerOptionsLoadCommand(LCI);
313 outs() << " ('count', " << LOLC.Count << ")\n"
314 << " ('_strings', [\n";
315
316 uint64_t DataSize = LOLC.Size - sizeof(macho::LinkerOptionsLoadCommand);
317 const char *P = LCI.Ptr + sizeof(macho::LinkerOptionsLoadCommand);
318 StringRef Data(P, DataSize);
319 for (unsigned i = 0; i != LOLC.Count; ++i) {
320 std::pair Split = Data.split('\0');
321 outs() << "\t\"";
322 outs().write_escaped(Split.first);
323 outs() << "\",\n";
324 Data = Split.second;
325 }
326 outs() <<" ])\n";
327
328 return 0;
329 }
330
331 static int DumpLoadCommand(const MachOObjectFile &Obj,
332 MachOObjectFile::LoadCommandInfo &LCI) {
333 switch (LCI.C.Type) {
397334 case macho::LCT_Segment:
398 Res = DumpSegmentCommand(Obj, LCI);
399 break;
335 return DumpSegmentCommand(Obj, LCI);
400336 case macho::LCT_Segment64:
401 Res = DumpSegment64Command(Obj, LCI);
402 break;
337 return DumpSegment64Command(Obj, LCI);
403338 case macho::LCT_Symtab:
404 Res = DumpSymtabCommand(Obj, LCI);
405 break;
339 return DumpSymtabCommand(Obj);
406340 case macho::LCT_Dysymtab:
407 Res = DumpDysymtabCommand(Obj, LCI);
408 break;
341 return DumpDysymtabCommand(Obj);
409342 case macho::LCT_CodeSignature:
410343 case macho::LCT_SegmentSplitInfo:
411344 case macho::LCT_FunctionStarts:
412 Res = DumpLinkeditDataCommand(Obj, LCI);
413 break;
345 return DumpLinkeditDataCommand(Obj, LCI);
414346 case macho::LCT_DataInCode:
415 Res = DumpDataInCodeDataCommand(Obj, LCI);
416 break;
347 return DumpDataInCodeDataCommand(Obj, LCI);
417348 case macho::LCT_LinkerOptions:
418 Res = DumpLinkerOptionsCommand(Obj, LCI);
419 break;
349 return DumpLinkerOptionsCommand(Obj, LCI);
420350 default:
421 Warning("unknown load command: " + Twine(LCI.Command.Type));
422 break;
423 }
351 Warning("unknown load command: " + Twine(LCI.C.Type));
352 return 0;
353 }
354 }
355
356
357 static int DumpLoadCommand(const MachOObjectFile &Obj, unsigned Index,
358 MachOObjectFile::LoadCommandInfo &LCI) {
359 outs() << " # Load Command " << Index << "\n"
360 << " (('command', " << LCI.C.Type << ")\n"
361 << " ('size', " << LCI.C.Size << ")\n";
362 int Res = DumpLoadCommand(Obj, LCI);
424363 outs() << " ),\n";
425
426364 return Res;
365 }
366
367 static void printHeader(const MachOObjectFile *Obj,
368 const macho::Header &Header) {
369 outs() << "('cputype', " << Header.CPUType << ")\n";
370 outs() << "('cpusubtype', " << Header.CPUSubtype << ")\n";
371 outs() << "('filetype', " << Header.FileType << ")\n";
372 outs() << "('num_load_commands', " << Header.NumLoadCommands << ")\n";
373 outs() << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n";
374 outs() << "('flag', " << Header.Flags << ")\n";
375
376 // Print extended header if 64-bit.
377 if (Obj->is64Bit()) {
378 macho::Header64Ext Header64Ext = Obj->getHeader64Ext();
379 outs() << "('reserved', " << Header64Ext.Reserved << ")\n";
380 }
427381 }
428382
429383 int main(int argc, char **argv) {
432386
433387 cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n");
434388
435 // Load the input file.
436 std::string ErrorStr;
437 OwningPtr InputBuffer;
438 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer))
439 return Error("unable to read input: '" + ec.message() + "'");
440
441 // Construct the Mach-O wrapper object.
442 OwningPtr InputObject(
443 MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr));
389 OwningPtr Binary;
390 if (error_code EC = createBinary(InputFile, Binary))
391 return Error("unable to read input: '" + EC.message() + "'");
392
393 const MachOObjectFile *InputObject = dyn_cast(Binary.get());
444394 if (!InputObject)
445 return Error("unable to load object: '" + ErrorStr + "'");
395 return Error("Not a MachO object");
446396
447397 // Print the header
448 InputObject->printHeader(outs());
398 macho::Header Header = InputObject->getHeader();
399 printHeader(InputObject, Header);
449400
450401 // Print the load commands.
451402 int Res = 0;
403 MachOObjectFile::LoadCommandInfo Command =
404 InputObject->getFirstLoadCommandInfo();
452405 outs() << "('load_commands', [\n";
453 for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i)
454 if ((Res = DumpLoadCommand(*InputObject, i)))
406 for (unsigned i = 0; ; ++i) {
407 if (DumpLoadCommand(*InputObject, i, Command))
455408 break;
409
410 if (i == Header.NumLoadCommands - 1)
411 break;
412 Command = InputObject->getNextLoadCommandInfo(Command);
413 }
456414 outs() << "])\n";
457415
458416 return Res;