130fdc8d8SChris Lattner //===-- ObjectFile.cpp ------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner #include "lldb/lldb-private.h"
11762f7135SGreg Clayton #include "lldb/lldb-private-log.h"
12*44435ed0SGreg Clayton #include "lldb/Core/DataBuffer.h"
13762f7135SGreg Clayton #include "lldb/Core/Log.h"
1430fdc8d8SChris Lattner #include "lldb/Core/Module.h"
1530fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h"
1630fdc8d8SChris Lattner #include "lldb/Core/RegularExpression.h"
1730fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
1830fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h"
1930fdc8d8SChris Lattner #include "lldb/Symbol/ObjectContainer.h"
2030fdc8d8SChris Lattner #include "lldb/Symbol/SymbolFile.h"
2130fdc8d8SChris Lattner 
2230fdc8d8SChris Lattner using namespace lldb;
2330fdc8d8SChris Lattner using namespace lldb_private;
2430fdc8d8SChris Lattner 
25762f7135SGreg Clayton ObjectFileSP
26*44435ed0SGreg Clayton ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset, addr_t file_size, DataBufferSP &file_data_sp)
2730fdc8d8SChris Lattner {
2830fdc8d8SChris Lattner     Timer scoped_timer (__PRETTY_FUNCTION__,
2930fdc8d8SChris Lattner                         "ObjectFile::FindPlugin (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
3030fdc8d8SChris Lattner                         module->GetFileSpec().GetDirectory().AsCString(),
3130fdc8d8SChris Lattner                         module->GetFileSpec().GetFilename().AsCString(),
3230fdc8d8SChris Lattner                         file, file_offset, file_size);
33762f7135SGreg Clayton     ObjectFileSP object_file_sp;
3430fdc8d8SChris Lattner 
3530fdc8d8SChris Lattner     if (module != NULL)
3630fdc8d8SChris Lattner     {
3730fdc8d8SChris Lattner         if (file)
3830fdc8d8SChris Lattner         {
39*44435ed0SGreg Clayton             // Memory map the entire file contents
40*44435ed0SGreg Clayton             if (!file_data_sp)
41*44435ed0SGreg Clayton             {
42*44435ed0SGreg Clayton                 assert (file_offset == 0);
43*44435ed0SGreg Clayton                 file_data_sp = file->MemoryMapFileContents(file_offset, file_size);
44*44435ed0SGreg Clayton             }
4530fdc8d8SChris Lattner 
46*44435ed0SGreg Clayton             if (!file_data_sp || file_data_sp->GetByteSize() == 0)
4730fdc8d8SChris Lattner             {
4830fdc8d8SChris Lattner                 // Check for archive file with format "/path/to/archive.a(object.o)"
4930fdc8d8SChris Lattner                 char path_with_object[PATH_MAX*2];
5030fdc8d8SChris Lattner                 module->GetFileSpec().GetPath(path_with_object, sizeof(path_with_object));
5130fdc8d8SChris Lattner 
5230fdc8d8SChris Lattner                 RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$");
5330fdc8d8SChris Lattner                 if (g_object_regex.Execute (path_with_object, 2))
5430fdc8d8SChris Lattner                 {
5530fdc8d8SChris Lattner                     FileSpec archive_file;
5630fdc8d8SChris Lattner                     std::string path;
5730fdc8d8SChris Lattner                     std::string object;
5830fdc8d8SChris Lattner                     if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) &&
5930fdc8d8SChris Lattner                         g_object_regex.GetMatchAtIndex (path_with_object, 2, object))
6030fdc8d8SChris Lattner                     {
61274060b6SGreg Clayton                         archive_file.SetFile (path.c_str(), false);
6230fdc8d8SChris Lattner                         file_size = archive_file.GetByteSize();
6330fdc8d8SChris Lattner                         if (file_size > 0)
64*44435ed0SGreg Clayton                         {
6530fdc8d8SChris Lattner                             module->SetFileSpecAndObjectName (archive_file, ConstString(object.c_str()));
66*44435ed0SGreg Clayton                             file_data_sp = archive_file.MemoryMapFileContents(file_offset, file_size);
67*44435ed0SGreg Clayton                         }
6830fdc8d8SChris Lattner                     }
6930fdc8d8SChris Lattner                 }
7030fdc8d8SChris Lattner             }
7130fdc8d8SChris Lattner 
72*44435ed0SGreg Clayton             if (file_data_sp && file_data_sp->GetByteSize() > 0)
73*44435ed0SGreg Clayton             {
7430fdc8d8SChris Lattner                 uint32_t idx;
7530fdc8d8SChris Lattner 
7630fdc8d8SChris Lattner                 // Check if this is a normal object file by iterating through
7730fdc8d8SChris Lattner                 // all object file plugin instances.
7830fdc8d8SChris Lattner                 ObjectFileCreateInstance create_object_file_callback;
7930fdc8d8SChris Lattner                 for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
8030fdc8d8SChris Lattner                 {
81*44435ed0SGreg Clayton                     object_file_sp.reset (create_object_file_callback(module, file_data_sp, file, file_offset, file_size));
82762f7135SGreg Clayton                     if (object_file_sp.get())
83762f7135SGreg Clayton                         return object_file_sp;
8430fdc8d8SChris Lattner                 }
8530fdc8d8SChris Lattner 
8630fdc8d8SChris Lattner                 // Check if this is a object container by iterating through
8730fdc8d8SChris Lattner                 // all object container plugin instances and then trying to get
8830fdc8d8SChris Lattner                 // an object file from the container.
8930fdc8d8SChris Lattner                 ObjectContainerCreateInstance create_object_container_callback;
9030fdc8d8SChris Lattner                 for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
9130fdc8d8SChris Lattner                 {
92*44435ed0SGreg Clayton                     std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module, file_data_sp, file, file_offset, file_size));
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner                     if (object_container_ap.get())
95762f7135SGreg Clayton                         object_file_sp = object_container_ap->GetObjectFile(file);
9630fdc8d8SChris Lattner 
97762f7135SGreg Clayton                     if (object_file_sp.get())
98762f7135SGreg Clayton                         return object_file_sp;
9930fdc8d8SChris Lattner                 }
10030fdc8d8SChris Lattner             }
10130fdc8d8SChris Lattner         }
102*44435ed0SGreg Clayton     }
103762f7135SGreg Clayton     // We didn't find it, so clear our shared pointer in case it
104762f7135SGreg Clayton     // contains anything and return an empty shared pointer
105762f7135SGreg Clayton     object_file_sp.reset();
106762f7135SGreg Clayton     return object_file_sp;
107762f7135SGreg Clayton }
108762f7135SGreg Clayton 
109762f7135SGreg Clayton ObjectFile::ObjectFile (Module* module,
110762f7135SGreg Clayton                         const FileSpec *file_spec_ptr,
111*44435ed0SGreg Clayton                         addr_t file_offset,
112*44435ed0SGreg Clayton                         addr_t file_size,
113*44435ed0SGreg Clayton                         DataBufferSP& file_data_sp) :
114762f7135SGreg Clayton     ModuleChild (module),
115762f7135SGreg Clayton     m_file (),  // This file could be different from the original module's file
116762f7135SGreg Clayton     m_type (eTypeInvalid),
117762f7135SGreg Clayton     m_strata (eStrataInvalid),
118*44435ed0SGreg Clayton     m_offset (file_offset),
119*44435ed0SGreg Clayton     m_length (file_size),
120*44435ed0SGreg Clayton     m_data (),
121762f7135SGreg Clayton     m_unwind_table (*this)
122762f7135SGreg Clayton {
123762f7135SGreg Clayton     if (file_spec_ptr)
124762f7135SGreg Clayton         m_file = *file_spec_ptr;
125*44435ed0SGreg Clayton     if (file_data_sp)
126*44435ed0SGreg Clayton         m_data.SetData (file_data_sp, file_offset, file_size);
127762f7135SGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
128762f7135SGreg Clayton     if (log)
129762f7135SGreg Clayton     {
130762f7135SGreg Clayton         if (m_file)
131762f7135SGreg Clayton         {
132762f7135SGreg Clayton             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n",
133762f7135SGreg Clayton                          this,
134762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
135762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
136762f7135SGreg Clayton                          m_file.GetDirectory().AsCString(),
137762f7135SGreg Clayton                          m_file.GetFilename().AsCString(),
138762f7135SGreg Clayton                          m_offset,
139762f7135SGreg Clayton                          m_length);
140762f7135SGreg Clayton         }
141762f7135SGreg Clayton         else
142762f7135SGreg Clayton         {
143762f7135SGreg Clayton             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n",
144762f7135SGreg Clayton                          this,
145762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
146762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
147762f7135SGreg Clayton                          m_offset,
148762f7135SGreg Clayton                          m_length);
149762f7135SGreg Clayton         }
150762f7135SGreg Clayton     }
151762f7135SGreg Clayton }
152762f7135SGreg Clayton 
153762f7135SGreg Clayton ObjectFile::~ObjectFile()
154762f7135SGreg Clayton {
155762f7135SGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
156762f7135SGreg Clayton     if (log)
157762f7135SGreg Clayton     {
158762f7135SGreg Clayton         if (m_file)
159762f7135SGreg Clayton         {
160762f7135SGreg Clayton             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n",
161762f7135SGreg Clayton                          this,
162762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
163762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
164762f7135SGreg Clayton                          m_file.GetDirectory().AsCString(),
165762f7135SGreg Clayton                          m_file.GetFilename().AsCString(),
166762f7135SGreg Clayton                          m_offset,
167762f7135SGreg Clayton                          m_length);
168762f7135SGreg Clayton         }
169762f7135SGreg Clayton         else
170762f7135SGreg Clayton         {
171762f7135SGreg Clayton             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n",
172762f7135SGreg Clayton                          this,
173762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
174762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
175762f7135SGreg Clayton                          m_offset,
176762f7135SGreg Clayton                          m_length);
177762f7135SGreg Clayton         }
178762f7135SGreg Clayton     }
17930fdc8d8SChris Lattner }
1805aee162fSJim Ingham 
1815aee162fSJim Ingham bool
1825aee162fSJim Ingham ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch)
1835aee162fSJim Ingham {
1845aee162fSJim Ingham     return m_module->SetArchitecture (new_arch);
1855aee162fSJim Ingham }
1865aee162fSJim Ingham 
187e0d378b3SGreg Clayton AddressClass
188762f7135SGreg Clayton ObjectFile::GetAddressClass (addr_t file_addr)
189ded470d3SGreg Clayton {
190ded470d3SGreg Clayton     Symtab *symtab = GetSymtab();
191ded470d3SGreg Clayton     if (symtab)
192ded470d3SGreg Clayton     {
193ded470d3SGreg Clayton         Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);
194ded470d3SGreg Clayton         if (symbol)
195ded470d3SGreg Clayton         {
196ded470d3SGreg Clayton             const AddressRange *range_ptr = symbol->GetAddressRangePtr();
197ded470d3SGreg Clayton             if (range_ptr)
198ded470d3SGreg Clayton             {
199ded470d3SGreg Clayton                 const Section *section = range_ptr->GetBaseAddress().GetSection();
200ded470d3SGreg Clayton                 if (section)
201ded470d3SGreg Clayton                 {
202e0d378b3SGreg Clayton                     const SectionType section_type = section->GetType();
203ded470d3SGreg Clayton                     switch (section_type)
204ded470d3SGreg Clayton                     {
205ded470d3SGreg Clayton                     case eSectionTypeInvalid:               return eAddressClassUnknown;
206ded470d3SGreg Clayton                     case eSectionTypeCode:                  return eAddressClassCode;
207ded470d3SGreg Clayton                     case eSectionTypeContainer:             return eAddressClassUnknown;
2085009f9d5SGreg Clayton                     case eSectionTypeData:
2095009f9d5SGreg Clayton                     case eSectionTypeDataCString:
2105009f9d5SGreg Clayton                     case eSectionTypeDataCStringPointers:
2115009f9d5SGreg Clayton                     case eSectionTypeDataSymbolAddress:
2125009f9d5SGreg Clayton                     case eSectionTypeData4:
2135009f9d5SGreg Clayton                     case eSectionTypeData8:
2145009f9d5SGreg Clayton                     case eSectionTypeData16:
2155009f9d5SGreg Clayton                     case eSectionTypeDataPointers:
2165009f9d5SGreg Clayton                     case eSectionTypeZeroFill:
2175009f9d5SGreg Clayton                     case eSectionTypeDataObjCMessageRefs:
2185009f9d5SGreg Clayton                     case eSectionTypeDataObjCCFStrings:
2195009f9d5SGreg Clayton                         return eAddressClassData;
2205009f9d5SGreg Clayton                     case eSectionTypeDebug:
2215009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugAbbrev:
2225009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugAranges:
2235009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugFrame:
2245009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugInfo:
2255009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugLine:
2265009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugLoc:
2275009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugMacInfo:
2285009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugPubNames:
2295009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugPubTypes:
2305009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugRanges:
2315009f9d5SGreg Clayton                     case eSectionTypeDWARFDebugStr:
2325009f9d5SGreg Clayton                     case eSectionTypeDWARFAppleNames:
2335009f9d5SGreg Clayton                     case eSectionTypeDWARFAppleTypes:
2345009f9d5SGreg Clayton                     case eSectionTypeDWARFAppleNamespaces:
2355009f9d5SGreg Clayton                     case eSectionTypeDWARFAppleObjC:
2365009f9d5SGreg Clayton                         return eAddressClassDebug;
237ded470d3SGreg Clayton                     case eSectionTypeEHFrame:               return eAddressClassRuntime;
238ded470d3SGreg Clayton                     case eSectionTypeOther:                 return eAddressClassUnknown;
239ded470d3SGreg Clayton                     }
240ded470d3SGreg Clayton                 }
241ded470d3SGreg Clayton             }
242ded470d3SGreg Clayton 
243e0d378b3SGreg Clayton             const SymbolType symbol_type = symbol->GetType();
244ded470d3SGreg Clayton             switch (symbol_type)
245ded470d3SGreg Clayton             {
246ded470d3SGreg Clayton             case eSymbolTypeAny:            return eAddressClassUnknown;
247ded470d3SGreg Clayton             case eSymbolTypeAbsolute:       return eAddressClassUnknown;
248ded470d3SGreg Clayton             case eSymbolTypeCode:           return eAddressClassCode;
249ded470d3SGreg Clayton             case eSymbolTypeTrampoline:     return eAddressClassCode;
250ded470d3SGreg Clayton             case eSymbolTypeData:           return eAddressClassData;
251ded470d3SGreg Clayton             case eSymbolTypeRuntime:        return eAddressClassRuntime;
252ded470d3SGreg Clayton             case eSymbolTypeException:      return eAddressClassRuntime;
253ded470d3SGreg Clayton             case eSymbolTypeSourceFile:     return eAddressClassDebug;
254ded470d3SGreg Clayton             case eSymbolTypeHeaderFile:     return eAddressClassDebug;
255ded470d3SGreg Clayton             case eSymbolTypeObjectFile:     return eAddressClassDebug;
256ded470d3SGreg Clayton             case eSymbolTypeCommonBlock:    return eAddressClassDebug;
257ded470d3SGreg Clayton             case eSymbolTypeBlock:          return eAddressClassDebug;
258ded470d3SGreg Clayton             case eSymbolTypeLocal:          return eAddressClassData;
259ded470d3SGreg Clayton             case eSymbolTypeParam:          return eAddressClassData;
260ded470d3SGreg Clayton             case eSymbolTypeVariable:       return eAddressClassData;
261ded470d3SGreg Clayton             case eSymbolTypeVariableType:   return eAddressClassDebug;
262ded470d3SGreg Clayton             case eSymbolTypeLineEntry:      return eAddressClassDebug;
263ded470d3SGreg Clayton             case eSymbolTypeLineHeader:     return eAddressClassDebug;
264ded470d3SGreg Clayton             case eSymbolTypeScopeBegin:     return eAddressClassDebug;
265ded470d3SGreg Clayton             case eSymbolTypeScopeEnd:       return eAddressClassDebug;
266ded470d3SGreg Clayton             case eSymbolTypeAdditional:     return eAddressClassUnknown;
267ded470d3SGreg Clayton             case eSymbolTypeCompiler:       return eAddressClassDebug;
268ded470d3SGreg Clayton             case eSymbolTypeInstrumentation:return eAddressClassDebug;
269ded470d3SGreg Clayton             case eSymbolTypeUndefined:      return eAddressClassUnknown;
270456809c1SGreg Clayton             case eSymbolTypeObjCClass:      return eAddressClassRuntime;
271456809c1SGreg Clayton             case eSymbolTypeObjCMetaClass:  return eAddressClassRuntime;
272456809c1SGreg Clayton             case eSymbolTypeObjCIVar:       return eAddressClassRuntime;
273ded470d3SGreg Clayton             }
274ded470d3SGreg Clayton         }
275ded470d3SGreg Clayton     }
276ded470d3SGreg Clayton     return eAddressClassUnknown;
277ded470d3SGreg Clayton }
278ded470d3SGreg Clayton 
279762f7135SGreg Clayton ObjectFileSP
280762f7135SGreg Clayton ObjectFile::GetSP ()
281762f7135SGreg Clayton {
282762f7135SGreg Clayton     // This object contains an instrusive ref count base class so we can
283762f7135SGreg Clayton     // easily make a shared pointer to this object
284762f7135SGreg Clayton     return ObjectFileSP (this);
285762f7135SGreg Clayton }
286762f7135SGreg Clayton 
287*44435ed0SGreg Clayton size_t
288*44435ed0SGreg Clayton ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
289*44435ed0SGreg Clayton {
290*44435ed0SGreg Clayton     // The entire file has already been mmap'ed into m_data, so just copy from there
291*44435ed0SGreg Clayton     // as the back mmap buffer will be shared with shared pointers.
292*44435ed0SGreg Clayton     return data.SetData (m_data, offset, length);
293*44435ed0SGreg Clayton }
294*44435ed0SGreg Clayton 
295*44435ed0SGreg Clayton size_t
296*44435ed0SGreg Clayton ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
297*44435ed0SGreg Clayton {
298*44435ed0SGreg Clayton     // The entire file has already been mmap'ed into m_data, so just copy from there
299*44435ed0SGreg Clayton     return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
300*44435ed0SGreg Clayton }
301ded470d3SGreg Clayton 
302