1 //===-- ObjectContainerUniversalMachO.cpp -----------------------*- 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 #include "ObjectContainerUniversalMachO.h" 11 #include "lldb/Core/Stream.h" 12 #include "lldb/Core/ArchSpec.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/PluginManager.h" 15 #include "lldb/Symbol/ObjectFile.h" 16 #include "lldb/Target/Target.h" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 using namespace llvm::MachO; 21 22 void 23 ObjectContainerUniversalMachO::Initialize() 24 { 25 PluginManager::RegisterPlugin (GetPluginNameStatic(), 26 GetPluginDescriptionStatic(), 27 CreateInstance); 28 } 29 30 void 31 ObjectContainerUniversalMachO::Terminate() 32 { 33 PluginManager::UnregisterPlugin (CreateInstance); 34 } 35 36 37 const char * 38 ObjectContainerUniversalMachO::GetPluginNameStatic() 39 { 40 return "object-container.mach-o"; 41 } 42 43 const char * 44 ObjectContainerUniversalMachO::GetPluginDescriptionStatic() 45 { 46 return "Universal mach-o object container reader."; 47 } 48 49 50 ObjectContainer * 51 ObjectContainerUniversalMachO::CreateInstance 52 ( 53 const lldb::ModuleSP &module_sp, 54 DataBufferSP& data_sp, 55 const FileSpec *file, 56 addr_t offset, 57 addr_t length 58 ) 59 { 60 DataExtractor data; 61 data.SetData (data_sp, offset, length); 62 if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) 63 { 64 std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module_sp, data_sp, file, offset, length)); 65 if (container_ap->ParseHeader()) 66 { 67 return container_ap.release(); 68 } 69 } 70 return NULL; 71 } 72 73 74 75 bool 76 ObjectContainerUniversalMachO::MagicBytesMatch (const DataExtractor &data) 77 { 78 uint32_t offset = 0; 79 uint32_t magic = data.GetU32(&offset); 80 return magic == UniversalMagic || magic == UniversalMagicSwapped; 81 } 82 83 ObjectContainerUniversalMachO::ObjectContainerUniversalMachO 84 ( 85 const lldb::ModuleSP &module_sp, 86 DataBufferSP& dataSP, 87 const FileSpec *file, 88 addr_t offset, 89 addr_t length 90 ) : 91 ObjectContainer (module_sp, file, offset, length, dataSP), 92 m_header(), 93 m_fat_archs() 94 { 95 memset(&m_header, 0, sizeof(m_header)); 96 } 97 98 99 ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() 100 { 101 } 102 103 bool 104 ObjectContainerUniversalMachO::ParseHeader () 105 { 106 // Store the file offset for this universal file as we could have a universal .o file 107 // in a BSD archive, or be contained in another kind of object. 108 uint32_t offset = 0; 109 // Universal mach-o files always have their headers in big endian. 110 m_data.SetByteOrder (eByteOrderBig); 111 m_header.magic = m_data.GetU32(&offset); 112 113 if (m_header.magic == UniversalMagic) 114 { 115 m_data.SetAddressByteSize(4); 116 117 m_header.nfat_arch = m_data.GetU32(&offset); 118 119 // Now we should have enough data for all of the fat headers, so lets index 120 // them so we know how many architectures that this universal binary contains. 121 uint32_t arch_idx = 0; 122 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) 123 { 124 if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch))) 125 { 126 fat_arch arch; 127 if (m_data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t))) 128 { 129 m_fat_archs.push_back(arch); 130 } 131 } 132 } 133 return true; 134 } 135 else 136 { 137 memset(&m_header, 0, sizeof(m_header)); 138 } 139 140 return false; 141 } 142 143 void 144 ObjectContainerUniversalMachO::Dump (Stream *s) const 145 { 146 s->Printf("%p: ", this); 147 s->Indent(); 148 const size_t num_archs = GetNumArchitectures(); 149 const size_t num_objects = GetNumObjects(); 150 s->Printf("ObjectContainerUniversalMachO, num_archs = %lu, num_objects = %lu", num_archs, num_objects); 151 uint32_t i; 152 ArchSpec arch; 153 s->IndentMore(); 154 for (i=0; i<num_archs; i++) 155 { 156 s->Indent(); 157 GetArchitectureAtIndex(i, arch); 158 s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName()); 159 } 160 for (i=0; i<num_objects; i++) 161 { 162 s->Indent(); 163 s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex (i)); 164 } 165 s->IndentLess(); 166 s->EOL(); 167 } 168 169 size_t 170 ObjectContainerUniversalMachO::GetNumArchitectures () const 171 { 172 return m_header.nfat_arch; 173 } 174 175 bool 176 ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const 177 { 178 if (idx < m_header.nfat_arch) 179 { 180 arch.SetArchitecture (eArchTypeMachO, m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype); 181 return true; 182 } 183 return false; 184 } 185 186 ObjectFileSP 187 ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file) 188 { 189 uint32_t arch_idx = 0; 190 ArchSpec arch; 191 // If the module hasn't specified an architecture yet, set it to the default 192 // architecture: 193 ModuleSP module_sp (GetModule()); 194 if (module_sp) 195 { 196 if (!module_sp->GetArchitecture().IsValid()) 197 { 198 arch = Target::GetDefaultArchitecture (); 199 if (!arch.IsValid()) 200 arch.SetTriple (LLDB_ARCH_DEFAULT); 201 } 202 else 203 arch = module_sp->GetArchitecture(); 204 205 ArchSpec curr_arch; 206 // First, try to find an exact match for the Arch of the Target. 207 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) 208 { 209 if (GetArchitectureAtIndex (arch_idx, curr_arch)) 210 { 211 if (arch.IsExactMatch(curr_arch)) 212 { 213 return ObjectFile::FindPlugin (module_sp, 214 file, 215 m_offset + m_fat_archs[arch_idx].offset, 216 m_fat_archs[arch_idx].size, 217 m_data.GetSharedDataBuffer()); 218 } 219 } 220 } 221 222 // Failing an exact match, try to find a compatible Arch of the Target. 223 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) 224 { 225 if (GetArchitectureAtIndex (arch_idx, curr_arch)) 226 { 227 if (arch.IsCompatibleMatch(curr_arch)) 228 { 229 return ObjectFile::FindPlugin (module_sp, 230 file, 231 m_offset + m_fat_archs[arch_idx].offset, 232 m_fat_archs[arch_idx].size, 233 m_data.GetSharedDataBuffer()); 234 } 235 } 236 } 237 238 } 239 return ObjectFileSP(); 240 } 241 242 243 //------------------------------------------------------------------ 244 // PluginInterface protocol 245 //------------------------------------------------------------------ 246 const char * 247 ObjectContainerUniversalMachO::GetPluginName() 248 { 249 return "ObjectContainerUniversalMachO"; 250 } 251 252 const char * 253 ObjectContainerUniversalMachO::GetShortPluginName() 254 { 255 return GetPluginNameStatic(); 256 } 257 258 uint32_t 259 ObjectContainerUniversalMachO::GetPluginVersion() 260 { 261 return 1; 262 } 263 264 265