ObjectContainerUniversalMachO.cpp revision 24943d2ee8bfaa7cf5893e4709143924157a5c1e
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 17using namespace lldb; 18using namespace lldb_private; 19 20 21void 22ObjectContainerUniversalMachO::Initialize() 23{ 24 PluginManager::RegisterPlugin (GetPluginNameStatic(), 25 GetPluginDescriptionStatic(), 26 CreateInstance); 27} 28 29void 30ObjectContainerUniversalMachO::Terminate() 31{ 32 PluginManager::UnregisterPlugin (CreateInstance); 33} 34 35 36const char * 37ObjectContainerUniversalMachO::GetPluginNameStatic() 38{ 39 return "object-container.mach-o"; 40} 41 42const char * 43ObjectContainerUniversalMachO::GetPluginDescriptionStatic() 44{ 45 return "Universal mach-o object container reader."; 46} 47 48 49ObjectContainer * 50ObjectContainerUniversalMachO::CreateInstance 51( 52 Module* module, 53 DataBufferSP& dataSP, 54 const FileSpec *file, 55 addr_t offset, 56 addr_t length 57) 58{ 59 if (ObjectContainerUniversalMachO::MagicBytesMatch(dataSP)) 60 { 61 std::auto_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module, dataSP, file, offset, length)); 62 if (container_ap->ParseHeader()) 63 { 64 return container_ap.release(); 65 } 66 } 67 return NULL; 68} 69 70 71 72bool 73ObjectContainerUniversalMachO::MagicBytesMatch (DataBufferSP& dataSP) 74{ 75 DataExtractor data(dataSP, eByteOrderHost, 4); 76 uint32_t offset = 0; 77 uint32_t magic = data.GetU32(&offset); 78 return magic == FAT_MAGIC || magic == FAT_CIGAM; 79} 80 81ObjectContainerUniversalMachO::ObjectContainerUniversalMachO 82( 83 Module* module, 84 DataBufferSP& dataSP, 85 const FileSpec *file, 86 addr_t offset, 87 addr_t length 88) : 89 ObjectContainer (module, file, offset, length, dataSP), 90 m_header(), 91 m_fat_archs() 92{ 93 memset(&m_header, 0, sizeof(m_header)); 94} 95 96 97ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() 98{ 99} 100 101bool 102ObjectContainerUniversalMachO::ParseHeader () 103{ 104 // Store the file offset for this universal file as we could have a universal .o file 105 // in a BSD archive, or be contained in another kind of object. 106 uint32_t offset = 0; 107 // Universal mach-o files always have their headers in big endian. 108 m_data.SetByteOrder (eByteOrderBig); 109 m_header.magic = m_data.GetU32(&offset); 110 111 if (m_header.magic == FAT_MAGIC) 112 { 113 m_data.SetAddressByteSize(4); 114 115 m_header.nfat_arch = m_data.GetU32(&offset); 116 117 const size_t nfat_arch_size = sizeof(fat_arch_t) * m_header.nfat_arch; 118 // See if the current data we have is enough for all of the fat headers? 119 if (!m_data.ValidOffsetForDataOfSize(offset, nfat_arch_size)) 120 { 121 // The fat headers are larger than the number of bytes we have been 122 // given when this class was constructed. We will read the exact number 123 // of bytes that we need. 124 DataBufferSP data_sp(m_file.ReadFileContents(m_offset, nfat_arch_size + sizeof(fat_header_t))); 125 m_data.SetData (data_sp); 126 } 127 128 // Now we should have enough data for all of the fat headers, so lets index 129 // them so we know how many architectures that this univeral binary contains. 130 uint32_t arch_idx = 0; 131 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) 132 { 133 if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch_t))) 134 { 135 fat_arch_t arch; 136 if (m_data.GetU32(&offset, &arch, sizeof(fat_arch_t)/sizeof(uint32_t))) 137 { 138 m_fat_archs.push_back(arch); 139 } 140 } 141 } 142 // Now that we have indexed the universal headers, we no longer need any cached data. 143 m_data.Clear(); 144 145 return true; 146 } 147 else 148 { 149 memset(&m_header, 0, sizeof(m_header)); 150 } 151 152 return false; 153} 154 155void 156ObjectContainerUniversalMachO::Dump (Stream *s) const 157{ 158 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 159 s->Indent(); 160 const size_t num_archs = GetNumArchitectures(); 161 const size_t num_objects = GetNumObjects(); 162 s->Printf("ObjectContainerUniversalMachO, num_archs = %u, num_objects = %u", num_archs, num_objects); 163 uint32_t i; 164 ArchSpec arch; 165 s->IndentMore(); 166 for (i=0; i<num_archs; i++) 167 { 168 s->Indent(); 169 GetArchitectureAtIndex(i, arch); 170 s->Printf("arch[%u] = %s\n", arch.AsCString()); 171 } 172 for (i=0; i<num_objects; i++) 173 { 174 s->Indent(); 175 s->Printf("object[%u] = %s\n", GetObjectNameAtIndex (i)); 176 } 177 s->IndentLess(); 178 s->EOL(); 179} 180 181size_t 182ObjectContainerUniversalMachO::GetNumArchitectures () const 183{ 184 return m_header.nfat_arch; 185} 186 187bool 188ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const 189{ 190 if (idx < m_header.nfat_arch) 191 { 192 arch.SetArch(m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype); 193 return true; 194 } 195 return false; 196} 197 198ObjectFile * 199ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file) 200{ 201 uint32_t arch_idx = 0; 202 const ArchSpec arch = m_module->GetArchitecture(); 203 ArchSpec curr_arch; 204 for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) 205 { 206 if (GetArchitectureAtIndex (arch_idx, curr_arch)) 207 { 208 if (arch == curr_arch) 209 { 210 return ObjectFile::FindPlugin (m_module, file, m_offset + m_fat_archs[arch_idx].offset, m_fat_archs[arch_idx].size); 211 } 212 } 213 } 214 return NULL; 215} 216 217 218//------------------------------------------------------------------ 219// PluginInterface protocol 220//------------------------------------------------------------------ 221const char * 222ObjectContainerUniversalMachO::GetPluginName() 223{ 224 return "ObjectContainerUniversalMachO"; 225} 226 227const char * 228ObjectContainerUniversalMachO::GetShortPluginName() 229{ 230 return GetPluginNameStatic(); 231} 232 233uint32_t 234ObjectContainerUniversalMachO::GetPluginVersion() 235{ 236 return 1; 237} 238 239void 240ObjectContainerUniversalMachO::GetPluginCommandHelp (const char *command, Stream *strm) 241{ 242} 243 244Error 245ObjectContainerUniversalMachO::ExecutePluginCommand (Args &command, Stream *strm) 246{ 247 Error error; 248 error.SetErrorString("No plug-in command are currently supported."); 249 return error; 250} 251 252Log * 253ObjectContainerUniversalMachO::EnablePluginLogging (Stream *strm, Args &command) 254{ 255 return NULL; 256} 257 258 259 260