1 //===-- ObjectFile.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 "lldb/lldb-private.h"
11 #include "lldb/lldb-private-log.h"
12 #include "lldb/Core/DataBuffer.h"
13 #include "lldb/Core/Log.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/RegularExpression.h"
17 #include "lldb/Core/Timer.h"
18 #include "lldb/Symbol/ObjectFile.h"
19 #include "lldb/Symbol/ObjectContainer.h"
20 #include "lldb/Symbol/SymbolFile.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 ObjectFileSP
26 ObjectFile::FindPlugin (Module* module, const FileSpec* file, addr_t file_offset, addr_t file_size, DataBufferSP &file_data_sp)
27 {
28     Timer scoped_timer (__PRETTY_FUNCTION__,
29                         "ObjectFile::FindPlugin (module = %s/%s, file = %p, file_offset = 0x%z8.8x, file_size = 0x%z8.8x)",
30                         module->GetFileSpec().GetDirectory().AsCString(),
31                         module->GetFileSpec().GetFilename().AsCString(),
32                         file, file_offset, file_size);
33     ObjectFileSP object_file_sp;
34 
35     if (module != NULL)
36     {
37         if (file)
38         {
39             // Memory map the entire file contents
40             if (!file_data_sp)
41             {
42                 assert (file_offset == 0);
43                 file_data_sp = file->MemoryMapFileContents(file_offset, file_size);
44             }
45 
46             if (!file_data_sp || file_data_sp->GetByteSize() == 0)
47             {
48                 // Check for archive file with format "/path/to/archive.a(object.o)"
49                 char path_with_object[PATH_MAX*2];
50                 module->GetFileSpec().GetPath(path_with_object, sizeof(path_with_object));
51 
52                 RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$");
53                 if (g_object_regex.Execute (path_with_object, 2))
54                 {
55                     FileSpec archive_file;
56                     std::string path;
57                     std::string object;
58                     if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) &&
59                         g_object_regex.GetMatchAtIndex (path_with_object, 2, object))
60                     {
61                         archive_file.SetFile (path.c_str(), false);
62                         file_size = archive_file.GetByteSize();
63                         if (file_size > 0)
64                         {
65                             module->SetFileSpecAndObjectName (archive_file, ConstString(object.c_str()));
66                             file_data_sp = archive_file.MemoryMapFileContents(file_offset, file_size);
67                         }
68                     }
69                 }
70             }
71 
72             if (file_data_sp && file_data_sp->GetByteSize() > 0)
73             {
74                 uint32_t idx;
75 
76                 // Check if this is a normal object file by iterating through
77                 // all object file plugin instances.
78                 ObjectFileCreateInstance create_object_file_callback;
79                 for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
80                 {
81                     object_file_sp.reset (create_object_file_callback(module, file_data_sp, file, file_offset, file_size));
82                     if (object_file_sp.get())
83                         return object_file_sp;
84                 }
85 
86                 // Check if this is a object container by iterating through
87                 // all object container plugin instances and then trying to get
88                 // an object file from the container.
89                 ObjectContainerCreateInstance create_object_container_callback;
90                 for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
91                 {
92                     std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module, file_data_sp, file, file_offset, file_size));
93 
94                     if (object_container_ap.get())
95                         object_file_sp = object_container_ap->GetObjectFile(file);
96 
97                     if (object_file_sp.get())
98                         return object_file_sp;
99                 }
100             }
101         }
102     }
103     // We didn't find it, so clear our shared pointer in case it
104     // contains anything and return an empty shared pointer
105     object_file_sp.reset();
106     return object_file_sp;
107 }
108 
109 ObjectFile::ObjectFile (Module* module,
110                         const FileSpec *file_spec_ptr,
111                         addr_t file_offset,
112                         addr_t file_size,
113                         DataBufferSP& file_data_sp) :
114     ModuleChild (module),
115     m_file (),  // This file could be different from the original module's file
116     m_type (eTypeInvalid),
117     m_strata (eStrataInvalid),
118     m_offset (file_offset),
119     m_length (file_size),
120     m_data (),
121     m_unwind_table (*this)
122 {
123     if (file_spec_ptr)
124         m_file = *file_spec_ptr;
125     if (file_data_sp)
126         m_data.SetData (file_data_sp, file_offset, file_size);
127     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
128     if (log)
129     {
130         if (m_file)
131         {
132             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n",
133                          this,
134                          m_module->GetFileSpec().GetDirectory().AsCString(),
135                          m_module->GetFileSpec().GetFilename().AsCString(),
136                          m_file.GetDirectory().AsCString(),
137                          m_file.GetFilename().AsCString(),
138                          m_offset,
139                          m_length);
140         }
141         else
142         {
143             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n",
144                          this,
145                          m_module->GetFileSpec().GetDirectory().AsCString(),
146                          m_module->GetFileSpec().GetFilename().AsCString(),
147                          m_offset,
148                          m_length);
149         }
150     }
151 }
152 
153 ObjectFile::~ObjectFile()
154 {
155     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
156     if (log)
157     {
158         if (m_file)
159         {
160             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n",
161                          this,
162                          m_module->GetFileSpec().GetDirectory().AsCString(),
163                          m_module->GetFileSpec().GetFilename().AsCString(),
164                          m_file.GetDirectory().AsCString(),
165                          m_file.GetFilename().AsCString(),
166                          m_offset,
167                          m_length);
168         }
169         else
170         {
171             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n",
172                          this,
173                          m_module->GetFileSpec().GetDirectory().AsCString(),
174                          m_module->GetFileSpec().GetFilename().AsCString(),
175                          m_offset,
176                          m_length);
177         }
178     }
179 }
180 
181 bool
182 ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch)
183 {
184     return m_module->SetArchitecture (new_arch);
185 }
186 
187 AddressClass
188 ObjectFile::GetAddressClass (addr_t file_addr)
189 {
190     Symtab *symtab = GetSymtab();
191     if (symtab)
192     {
193         Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);
194         if (symbol)
195         {
196             const AddressRange *range_ptr = symbol->GetAddressRangePtr();
197             if (range_ptr)
198             {
199                 const Section *section = range_ptr->GetBaseAddress().GetSection();
200                 if (section)
201                 {
202                     const SectionType section_type = section->GetType();
203                     switch (section_type)
204                     {
205                     case eSectionTypeInvalid:               return eAddressClassUnknown;
206                     case eSectionTypeCode:                  return eAddressClassCode;
207                     case eSectionTypeContainer:             return eAddressClassUnknown;
208                     case eSectionTypeData:
209                     case eSectionTypeDataCString:
210                     case eSectionTypeDataCStringPointers:
211                     case eSectionTypeDataSymbolAddress:
212                     case eSectionTypeData4:
213                     case eSectionTypeData8:
214                     case eSectionTypeData16:
215                     case eSectionTypeDataPointers:
216                     case eSectionTypeZeroFill:
217                     case eSectionTypeDataObjCMessageRefs:
218                     case eSectionTypeDataObjCCFStrings:
219                         return eAddressClassData;
220                     case eSectionTypeDebug:
221                     case eSectionTypeDWARFDebugAbbrev:
222                     case eSectionTypeDWARFDebugAranges:
223                     case eSectionTypeDWARFDebugFrame:
224                     case eSectionTypeDWARFDebugInfo:
225                     case eSectionTypeDWARFDebugLine:
226                     case eSectionTypeDWARFDebugLoc:
227                     case eSectionTypeDWARFDebugMacInfo:
228                     case eSectionTypeDWARFDebugPubNames:
229                     case eSectionTypeDWARFDebugPubTypes:
230                     case eSectionTypeDWARFDebugRanges:
231                     case eSectionTypeDWARFDebugStr:
232                     case eSectionTypeDWARFAppleNames:
233                     case eSectionTypeDWARFAppleTypes:
234                     case eSectionTypeDWARFAppleNamespaces:
235                     case eSectionTypeDWARFAppleObjC:
236                         return eAddressClassDebug;
237                     case eSectionTypeEHFrame:               return eAddressClassRuntime;
238                     case eSectionTypeOther:                 return eAddressClassUnknown;
239                     }
240                 }
241             }
242 
243             const SymbolType symbol_type = symbol->GetType();
244             switch (symbol_type)
245             {
246             case eSymbolTypeAny:            return eAddressClassUnknown;
247             case eSymbolTypeAbsolute:       return eAddressClassUnknown;
248             case eSymbolTypeCode:           return eAddressClassCode;
249             case eSymbolTypeTrampoline:     return eAddressClassCode;
250             case eSymbolTypeData:           return eAddressClassData;
251             case eSymbolTypeRuntime:        return eAddressClassRuntime;
252             case eSymbolTypeException:      return eAddressClassRuntime;
253             case eSymbolTypeSourceFile:     return eAddressClassDebug;
254             case eSymbolTypeHeaderFile:     return eAddressClassDebug;
255             case eSymbolTypeObjectFile:     return eAddressClassDebug;
256             case eSymbolTypeCommonBlock:    return eAddressClassDebug;
257             case eSymbolTypeBlock:          return eAddressClassDebug;
258             case eSymbolTypeLocal:          return eAddressClassData;
259             case eSymbolTypeParam:          return eAddressClassData;
260             case eSymbolTypeVariable:       return eAddressClassData;
261             case eSymbolTypeVariableType:   return eAddressClassDebug;
262             case eSymbolTypeLineEntry:      return eAddressClassDebug;
263             case eSymbolTypeLineHeader:     return eAddressClassDebug;
264             case eSymbolTypeScopeBegin:     return eAddressClassDebug;
265             case eSymbolTypeScopeEnd:       return eAddressClassDebug;
266             case eSymbolTypeAdditional:     return eAddressClassUnknown;
267             case eSymbolTypeCompiler:       return eAddressClassDebug;
268             case eSymbolTypeInstrumentation:return eAddressClassDebug;
269             case eSymbolTypeUndefined:      return eAddressClassUnknown;
270             case eSymbolTypeObjCClass:      return eAddressClassRuntime;
271             case eSymbolTypeObjCMetaClass:  return eAddressClassRuntime;
272             case eSymbolTypeObjCIVar:       return eAddressClassRuntime;
273             }
274         }
275     }
276     return eAddressClassUnknown;
277 }
278 
279 size_t
280 ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
281 {
282     // The entire file has already been mmap'ed into m_data, so just copy from there
283     // as the back mmap buffer will be shared with shared pointers.
284     return data.SetData (m_data, offset, length);
285 }
286 
287 size_t
288 ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
289 {
290     // The entire file has already been mmap'ed into m_data, so just copy from there
291     return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
292 }
293 
294