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"
11*762f7135SGreg Clayton #include "lldb/lldb-private-log.h"
12*762f7135SGreg Clayton #include "lldb/Core/Log.h"
1330fdc8d8SChris Lattner #include "lldb/Core/Module.h"
1430fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h"
1530fdc8d8SChris Lattner #include "lldb/Core/RegularExpression.h"
1630fdc8d8SChris Lattner #include "lldb/Core/Timer.h"
1730fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h"
1830fdc8d8SChris Lattner #include "lldb/Symbol/ObjectContainer.h"
1930fdc8d8SChris Lattner #include "lldb/Symbol/SymbolFile.h"
2030fdc8d8SChris Lattner 
2130fdc8d8SChris Lattner using namespace lldb;
2230fdc8d8SChris Lattner using namespace lldb_private;
2330fdc8d8SChris Lattner 
24*762f7135SGreg Clayton ObjectFileSP
25*762f7135SGreg Clayton ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset, addr_t file_size)
2630fdc8d8SChris Lattner {
2730fdc8d8SChris Lattner     Timer scoped_timer (__PRETTY_FUNCTION__,
2830fdc8d8SChris Lattner                         "ObjectFile::FindPlugin (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
2930fdc8d8SChris Lattner                         module->GetFileSpec().GetDirectory().AsCString(),
3030fdc8d8SChris Lattner                         module->GetFileSpec().GetFilename().AsCString(),
3130fdc8d8SChris Lattner                         file, file_offset, file_size);
32*762f7135SGreg Clayton     ObjectFileSP object_file_sp;
3330fdc8d8SChris Lattner 
3430fdc8d8SChris Lattner     if (module != NULL)
3530fdc8d8SChris Lattner     {
3630fdc8d8SChris Lattner         if (file)
3730fdc8d8SChris Lattner         {
3830fdc8d8SChris Lattner             if (file_size == 0)
3930fdc8d8SChris Lattner                 file_size = file->GetByteSize();
4030fdc8d8SChris Lattner 
4130fdc8d8SChris Lattner             if (file_size == 0)
4230fdc8d8SChris Lattner             {
4330fdc8d8SChris Lattner                 // Check for archive file with format "/path/to/archive.a(object.o)"
4430fdc8d8SChris Lattner                 char path_with_object[PATH_MAX*2];
4530fdc8d8SChris Lattner                 module->GetFileSpec().GetPath(path_with_object, sizeof(path_with_object));
4630fdc8d8SChris Lattner 
4730fdc8d8SChris Lattner                 RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$");
4830fdc8d8SChris Lattner                 if (g_object_regex.Execute (path_with_object, 2))
4930fdc8d8SChris Lattner                 {
5030fdc8d8SChris Lattner                     FileSpec archive_file;
5130fdc8d8SChris Lattner                     std::string path;
5230fdc8d8SChris Lattner                     std::string object;
5330fdc8d8SChris Lattner                     if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) &&
5430fdc8d8SChris Lattner                         g_object_regex.GetMatchAtIndex (path_with_object, 2, object))
5530fdc8d8SChris Lattner                     {
56274060b6SGreg Clayton                         archive_file.SetFile (path.c_str(), false);
5730fdc8d8SChris Lattner                         file_size = archive_file.GetByteSize();
5830fdc8d8SChris Lattner                         if (file_size > 0)
5930fdc8d8SChris Lattner                             module->SetFileSpecAndObjectName (archive_file, ConstString(object.c_str()));
6030fdc8d8SChris Lattner                     }
6130fdc8d8SChris Lattner                 }
6230fdc8d8SChris Lattner             }
6330fdc8d8SChris Lattner 
6476c381b6SJohnny Chen             // No need to delegate further if (file_offset, file_size) exceeds the total file size.
6576c381b6SJohnny Chen             // This is the base case.
668b82f087SGreg Clayton //            if (file_offset + file_size > file->GetByteSize())
678b82f087SGreg Clayton //                return NULL;
6876c381b6SJohnny Chen 
6930fdc8d8SChris Lattner             DataBufferSP file_header_data_sp(file->ReadFileContents(file_offset, 512));
7030fdc8d8SChris Lattner             uint32_t idx;
7130fdc8d8SChris Lattner 
7230fdc8d8SChris Lattner             // Check if this is a normal object file by iterating through
7330fdc8d8SChris Lattner             // all object file plugin instances.
7430fdc8d8SChris Lattner             ObjectFileCreateInstance create_object_file_callback;
7530fdc8d8SChris Lattner             for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
7630fdc8d8SChris Lattner             {
77*762f7135SGreg Clayton                 object_file_sp.reset (create_object_file_callback(module, file_header_data_sp, file, file_offset, file_size));
78*762f7135SGreg Clayton                 if (object_file_sp.get())
79*762f7135SGreg Clayton                     return object_file_sp;
8030fdc8d8SChris Lattner             }
8130fdc8d8SChris Lattner 
8230fdc8d8SChris Lattner             // Check if this is a object container by iterating through
8330fdc8d8SChris Lattner             // all object container plugin instances and then trying to get
8430fdc8d8SChris Lattner             // an object file from the container.
8530fdc8d8SChris Lattner             ObjectContainerCreateInstance create_object_container_callback;
8630fdc8d8SChris Lattner             for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
8730fdc8d8SChris Lattner             {
8830fdc8d8SChris Lattner                 std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module, file_header_data_sp, file, file_offset, file_size));
8930fdc8d8SChris Lattner 
9030fdc8d8SChris Lattner                 if (object_container_ap.get())
91*762f7135SGreg Clayton                     object_file_sp = object_container_ap->GetObjectFile(file);
9230fdc8d8SChris Lattner 
93*762f7135SGreg Clayton                 if (object_file_sp.get())
94*762f7135SGreg Clayton                     return object_file_sp;
9530fdc8d8SChris Lattner             }
9630fdc8d8SChris Lattner         }
9730fdc8d8SChris Lattner     }
98*762f7135SGreg Clayton     // We didn't find it, so clear our shared pointer in case it
99*762f7135SGreg Clayton     // contains anything and return an empty shared pointer
100*762f7135SGreg Clayton     object_file_sp.reset();
101*762f7135SGreg Clayton     return object_file_sp;
102*762f7135SGreg Clayton }
103*762f7135SGreg Clayton 
104*762f7135SGreg Clayton ObjectFile::ObjectFile (Module* module,
105*762f7135SGreg Clayton                         const FileSpec *file_spec_ptr,
106*762f7135SGreg Clayton                         addr_t offset,
107*762f7135SGreg Clayton                         addr_t length,
108*762f7135SGreg Clayton                         DataBufferSP& headerDataSP) :
109*762f7135SGreg Clayton     ModuleChild (module),
110*762f7135SGreg Clayton     m_file (),  // This file could be different from the original module's file
111*762f7135SGreg Clayton     m_type (eTypeInvalid),
112*762f7135SGreg Clayton     m_strata (eStrataInvalid),
113*762f7135SGreg Clayton     m_offset (offset),
114*762f7135SGreg Clayton     m_length (length),
115*762f7135SGreg Clayton     m_data (headerDataSP, endian::InlHostByteOrder(), 4),
116*762f7135SGreg Clayton     m_unwind_table (*this)
117*762f7135SGreg Clayton {
118*762f7135SGreg Clayton     if (file_spec_ptr)
119*762f7135SGreg Clayton         m_file = *file_spec_ptr;
120*762f7135SGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
121*762f7135SGreg Clayton     if (log)
122*762f7135SGreg Clayton     {
123*762f7135SGreg Clayton         if (m_file)
124*762f7135SGreg Clayton         {
125*762f7135SGreg Clayton             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n",
126*762f7135SGreg Clayton                          this,
127*762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
128*762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
129*762f7135SGreg Clayton                          m_file.GetDirectory().AsCString(),
130*762f7135SGreg Clayton                          m_file.GetFilename().AsCString(),
131*762f7135SGreg Clayton                          m_offset,
132*762f7135SGreg Clayton                          m_length);
133*762f7135SGreg Clayton         }
134*762f7135SGreg Clayton         else
135*762f7135SGreg Clayton         {
136*762f7135SGreg Clayton             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n",
137*762f7135SGreg Clayton                          this,
138*762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
139*762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
140*762f7135SGreg Clayton                          m_offset,
141*762f7135SGreg Clayton                          m_length);
142*762f7135SGreg Clayton         }
143*762f7135SGreg Clayton     }
144*762f7135SGreg Clayton }
145*762f7135SGreg Clayton 
146*762f7135SGreg Clayton ObjectFile::~ObjectFile()
147*762f7135SGreg Clayton {
148*762f7135SGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
149*762f7135SGreg Clayton     if (log)
150*762f7135SGreg Clayton     {
151*762f7135SGreg Clayton         if (m_file)
152*762f7135SGreg Clayton         {
153*762f7135SGreg Clayton             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n",
154*762f7135SGreg Clayton                          this,
155*762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
156*762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
157*762f7135SGreg Clayton                          m_file.GetDirectory().AsCString(),
158*762f7135SGreg Clayton                          m_file.GetFilename().AsCString(),
159*762f7135SGreg Clayton                          m_offset,
160*762f7135SGreg Clayton                          m_length);
161*762f7135SGreg Clayton         }
162*762f7135SGreg Clayton         else
163*762f7135SGreg Clayton         {
164*762f7135SGreg Clayton             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n",
165*762f7135SGreg Clayton                          this,
166*762f7135SGreg Clayton                          m_module->GetFileSpec().GetDirectory().AsCString(),
167*762f7135SGreg Clayton                          m_module->GetFileSpec().GetFilename().AsCString(),
168*762f7135SGreg Clayton                          m_offset,
169*762f7135SGreg Clayton                          m_length);
170*762f7135SGreg Clayton         }
171*762f7135SGreg Clayton     }
17230fdc8d8SChris Lattner }
1735aee162fSJim Ingham 
1745aee162fSJim Ingham bool
1755aee162fSJim Ingham ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch)
1765aee162fSJim Ingham {
1775aee162fSJim Ingham     return m_module->SetArchitecture (new_arch);
1785aee162fSJim Ingham }
1795aee162fSJim Ingham 
180e0d378b3SGreg Clayton AddressClass
181*762f7135SGreg Clayton ObjectFile::GetAddressClass (addr_t file_addr)
182ded470d3SGreg Clayton {
183ded470d3SGreg Clayton     Symtab *symtab = GetSymtab();
184ded470d3SGreg Clayton     if (symtab)
185ded470d3SGreg Clayton     {
186ded470d3SGreg Clayton         Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);
187ded470d3SGreg Clayton         if (symbol)
188ded470d3SGreg Clayton         {
189ded470d3SGreg Clayton             const AddressRange *range_ptr = symbol->GetAddressRangePtr();
190ded470d3SGreg Clayton             if (range_ptr)
191ded470d3SGreg Clayton             {
192ded470d3SGreg Clayton                 const Section *section = range_ptr->GetBaseAddress().GetSection();
193ded470d3SGreg Clayton                 if (section)
194ded470d3SGreg Clayton                 {
195e0d378b3SGreg Clayton                     const SectionType section_type = section->GetType();
196ded470d3SGreg Clayton                     switch (section_type)
197ded470d3SGreg Clayton                     {
198ded470d3SGreg Clayton                     case eSectionTypeInvalid:               return eAddressClassUnknown;
199ded470d3SGreg Clayton                     case eSectionTypeCode:                  return eAddressClassCode;
200ded470d3SGreg Clayton                     case eSectionTypeContainer:             return eAddressClassUnknown;
201ded470d3SGreg Clayton                     case eSectionTypeData:                  return eAddressClassData;
202e0d378b3SGreg Clayton                     case eSectionTypeDataCString:           return eAddressClassData;
203ded470d3SGreg Clayton                     case eSectionTypeDataCStringPointers:   return eAddressClassData;
204ded470d3SGreg Clayton                     case eSectionTypeDataSymbolAddress:     return eAddressClassData;
205ded470d3SGreg Clayton                     case eSectionTypeData4:                 return eAddressClassData;
206ded470d3SGreg Clayton                     case eSectionTypeData8:                 return eAddressClassData;
207ded470d3SGreg Clayton                     case eSectionTypeData16:                return eAddressClassData;
208ded470d3SGreg Clayton                     case eSectionTypeDataPointers:          return eAddressClassData;
209ded470d3SGreg Clayton                     case eSectionTypeZeroFill:              return eAddressClassData;
210e0d378b3SGreg Clayton                     case eSectionTypeDataObjCMessageRefs:   return eAddressClassData;
211e0d378b3SGreg Clayton                     case eSectionTypeDataObjCCFStrings:     return eAddressClassData;
212ded470d3SGreg Clayton                     case eSectionTypeDebug:                 return eAddressClassDebug;
213ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugAbbrev:      return eAddressClassDebug;
214ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugAranges:     return eAddressClassDebug;
215ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugFrame:       return eAddressClassDebug;
216ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugInfo:        return eAddressClassDebug;
217ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugLine:        return eAddressClassDebug;
218ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugLoc:         return eAddressClassDebug;
219ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugMacInfo:     return eAddressClassDebug;
220ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugPubNames:    return eAddressClassDebug;
221ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugPubTypes:    return eAddressClassDebug;
222ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugRanges:      return eAddressClassDebug;
223ded470d3SGreg Clayton                     case eSectionTypeDWARFDebugStr:         return eAddressClassDebug;
224f9eec20bSGreg Clayton                     case eSectionTypeDWARFDebugNames:       return eAddressClassDebug;
225f9eec20bSGreg Clayton                     case eSectionTypeDWARFDebugTypes:       return eAddressClassDebug;
226ded470d3SGreg Clayton                     case eSectionTypeEHFrame:               return eAddressClassRuntime;
227ded470d3SGreg Clayton                     case eSectionTypeOther:                 return eAddressClassUnknown;
228ded470d3SGreg Clayton                     }
229ded470d3SGreg Clayton                 }
230ded470d3SGreg Clayton             }
231ded470d3SGreg Clayton 
232e0d378b3SGreg Clayton             const SymbolType symbol_type = symbol->GetType();
233ded470d3SGreg Clayton             switch (symbol_type)
234ded470d3SGreg Clayton             {
235ded470d3SGreg Clayton             case eSymbolTypeAny:            return eAddressClassUnknown;
236ded470d3SGreg Clayton             case eSymbolTypeAbsolute:       return eAddressClassUnknown;
237ded470d3SGreg Clayton             case eSymbolTypeExtern:         return eAddressClassUnknown;
238ded470d3SGreg Clayton             case eSymbolTypeCode:           return eAddressClassCode;
239ded470d3SGreg Clayton             case eSymbolTypeTrampoline:     return eAddressClassCode;
240ded470d3SGreg Clayton             case eSymbolTypeData:           return eAddressClassData;
241ded470d3SGreg Clayton             case eSymbolTypeRuntime:        return eAddressClassRuntime;
242ded470d3SGreg Clayton             case eSymbolTypeException:      return eAddressClassRuntime;
243ded470d3SGreg Clayton             case eSymbolTypeSourceFile:     return eAddressClassDebug;
244ded470d3SGreg Clayton             case eSymbolTypeHeaderFile:     return eAddressClassDebug;
245ded470d3SGreg Clayton             case eSymbolTypeObjectFile:     return eAddressClassDebug;
246ded470d3SGreg Clayton             case eSymbolTypeCommonBlock:    return eAddressClassDebug;
247ded470d3SGreg Clayton             case eSymbolTypeBlock:          return eAddressClassDebug;
248ded470d3SGreg Clayton             case eSymbolTypeLocal:          return eAddressClassData;
249ded470d3SGreg Clayton             case eSymbolTypeParam:          return eAddressClassData;
250ded470d3SGreg Clayton             case eSymbolTypeVariable:       return eAddressClassData;
251ded470d3SGreg Clayton             case eSymbolTypeVariableType:   return eAddressClassDebug;
252ded470d3SGreg Clayton             case eSymbolTypeLineEntry:      return eAddressClassDebug;
253ded470d3SGreg Clayton             case eSymbolTypeLineHeader:     return eAddressClassDebug;
254ded470d3SGreg Clayton             case eSymbolTypeScopeBegin:     return eAddressClassDebug;
255ded470d3SGreg Clayton             case eSymbolTypeScopeEnd:       return eAddressClassDebug;
256ded470d3SGreg Clayton             case eSymbolTypeAdditional:     return eAddressClassUnknown;
257ded470d3SGreg Clayton             case eSymbolTypeCompiler:       return eAddressClassDebug;
258ded470d3SGreg Clayton             case eSymbolTypeInstrumentation:return eAddressClassDebug;
259ded470d3SGreg Clayton             case eSymbolTypeUndefined:      return eAddressClassUnknown;
260ded470d3SGreg Clayton             }
261ded470d3SGreg Clayton         }
262ded470d3SGreg Clayton     }
263ded470d3SGreg Clayton     return eAddressClassUnknown;
264ded470d3SGreg Clayton }
265ded470d3SGreg Clayton 
266*762f7135SGreg Clayton ObjectFileSP
267*762f7135SGreg Clayton ObjectFile::GetSP ()
268*762f7135SGreg Clayton {
269*762f7135SGreg Clayton     // This object contains an instrusive ref count base class so we can
270*762f7135SGreg Clayton     // easily make a shared pointer to this object
271*762f7135SGreg Clayton     return ObjectFileSP (this);
272*762f7135SGreg Clayton }
273*762f7135SGreg Clayton 
274ded470d3SGreg Clayton 
275