Mercurial > hg > CbC > CbC_llvm
comparison lib/Object/MachOUniversal.cpp @ 0:95c75e76d11b LLVM3.4
LLVM 3.4
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 12 Dec 2013 13:56:28 +0900 |
parents | |
children | 54457678186b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:95c75e76d11b |
---|---|
1 //===- MachOUniversal.cpp - Mach-O universal binary -------------*- C++ -*-===// | |
2 // | |
3 // The LLVM Compiler Infrastructure | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // This file defines the MachOUniversalBinary class. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 | |
14 #include "llvm/Object/MachOUniversal.h" | |
15 | |
16 #include "llvm/Object/MachO.h" | |
17 #include "llvm/Object/ObjectFile.h" | |
18 #include "llvm/Support/Casting.h" | |
19 #include "llvm/Support/Host.h" | |
20 #include "llvm/Support/MemoryBuffer.h" | |
21 | |
22 using namespace llvm; | |
23 using namespace object; | |
24 | |
25 template<typename T> | |
26 static void SwapValue(T &Value) { | |
27 Value = sys::SwapByteOrder(Value); | |
28 } | |
29 | |
30 template<typename T> | |
31 static void SwapStruct(T &Value); | |
32 | |
33 template<> | |
34 void SwapStruct(MachO::fat_header &H) { | |
35 SwapValue(H.magic); | |
36 SwapValue(H.nfat_arch); | |
37 } | |
38 | |
39 template<> | |
40 void SwapStruct(MachO::fat_arch &H) { | |
41 SwapValue(H.cputype); | |
42 SwapValue(H.cpusubtype); | |
43 SwapValue(H.offset); | |
44 SwapValue(H.size); | |
45 SwapValue(H.align); | |
46 } | |
47 | |
48 template<typename T> | |
49 static T getUniversalBinaryStruct(const char *Ptr) { | |
50 T Res; | |
51 memcpy(&Res, Ptr, sizeof(T)); | |
52 // Universal binary headers have big-endian byte order. | |
53 if (sys::IsLittleEndianHost) | |
54 SwapStruct(Res); | |
55 return Res; | |
56 } | |
57 | |
58 MachOUniversalBinary::ObjectForArch::ObjectForArch( | |
59 const MachOUniversalBinary *Parent, uint32_t Index) | |
60 : Parent(Parent), Index(Index) { | |
61 if (Parent == 0 || Index > Parent->getNumberOfObjects()) { | |
62 clear(); | |
63 } else { | |
64 // Parse object header. | |
65 StringRef ParentData = Parent->getData(); | |
66 const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) + | |
67 Index * sizeof(MachO::fat_arch); | |
68 Header = getUniversalBinaryStruct<MachO::fat_arch>(HeaderPos); | |
69 if (ParentData.size() < Header.offset + Header.size) { | |
70 clear(); | |
71 } | |
72 } | |
73 } | |
74 | |
75 error_code MachOUniversalBinary::ObjectForArch::getAsObjectFile( | |
76 OwningPtr<ObjectFile> &Result) const { | |
77 if (Parent) { | |
78 StringRef ParentData = Parent->getData(); | |
79 StringRef ObjectData = ParentData.substr(Header.offset, Header.size); | |
80 std::string ObjectName = | |
81 Parent->getFileName().str() + ":" + | |
82 Triple::getArchTypeName(MachOObjectFile::getArch(Header.cputype)); | |
83 MemoryBuffer *ObjBuffer = MemoryBuffer::getMemBuffer( | |
84 ObjectData, ObjectName, false); | |
85 if (ObjectFile *Obj = ObjectFile::createMachOObjectFile(ObjBuffer)) { | |
86 Result.reset(Obj); | |
87 return object_error::success; | |
88 } | |
89 } | |
90 return object_error::parse_failed; | |
91 } | |
92 | |
93 void MachOUniversalBinary::anchor() { } | |
94 | |
95 MachOUniversalBinary::MachOUniversalBinary(MemoryBuffer *Source, | |
96 error_code &ec) | |
97 : Binary(Binary::ID_MachOUniversalBinary, Source), | |
98 NumberOfObjects(0) { | |
99 if (Source->getBufferSize() < sizeof(MachO::fat_header)) { | |
100 ec = object_error::invalid_file_type; | |
101 return; | |
102 } | |
103 // Check for magic value and sufficient header size. | |
104 StringRef Buf = getData(); | |
105 MachO::fat_header H= getUniversalBinaryStruct<MachO::fat_header>(Buf.begin()); | |
106 NumberOfObjects = H.nfat_arch; | |
107 uint32_t MinSize = sizeof(MachO::fat_header) + | |
108 sizeof(MachO::fat_arch) * NumberOfObjects; | |
109 if (H.magic != MachO::FAT_MAGIC || Buf.size() < MinSize) { | |
110 ec = object_error::parse_failed; | |
111 return; | |
112 } | |
113 ec = object_error::success; | |
114 } | |
115 | |
116 static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) { | |
117 switch (Arch) { | |
118 case Triple::x86: CTM = MachO::CPU_TYPE_I386; return true; | |
119 case Triple::x86_64: CTM = MachO::CPU_TYPE_X86_64; return true; | |
120 case Triple::arm: CTM = MachO::CPU_TYPE_ARM; return true; | |
121 case Triple::sparc: CTM = MachO::CPU_TYPE_SPARC; return true; | |
122 case Triple::ppc: CTM = MachO::CPU_TYPE_POWERPC; return true; | |
123 case Triple::ppc64: CTM = MachO::CPU_TYPE_POWERPC64; return true; | |
124 default: return false; | |
125 } | |
126 } | |
127 | |
128 error_code | |
129 MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch, | |
130 OwningPtr<ObjectFile> &Result) const { | |
131 MachO::CPUType CTM; | |
132 if (!getCTMForArch(Arch, CTM)) | |
133 return object_error::arch_not_found; | |
134 for (object_iterator I = begin_objects(), E = end_objects(); I != E; ++I) { | |
135 if (I->getCPUType() == static_cast<uint32_t>(CTM)) | |
136 return I->getAsObjectFile(Result); | |
137 } | |
138 return object_error::arch_not_found; | |
139 } |