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/DataBufferHeap.h"
14 #include "lldb/Core/Log.h"
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/RegularExpression.h"
18 #include "lldb/Core/Section.h"
19 #include "lldb/Core/Timer.h"
20 #include "lldb/Symbol/ObjectFile.h"
21 #include "lldb/Symbol/ObjectContainer.h"
22 #include "lldb/Symbol/SymbolFile.h"
23 #include "lldb/Target/Process.h"
24 #include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 ObjectFileSP
30 ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp, const FileSpec* file, addr_t file_offset, addr_t file_size, DataBufferSP &file_data_sp)
31 {
32     ObjectFileSP object_file_sp;
33 
34     if (module_sp)
35     {
36         Timer scoped_timer (__PRETTY_FUNCTION__,
37                             "ObjectFile::FindPlugin (module = %s/%s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
38                             module_sp->GetFileSpec().GetDirectory().AsCString(),
39                             module_sp->GetFileSpec().GetFilename().AsCString(),
40                             file, (uint64_t) file_offset, (uint64_t) file_size);
41         if (file)
42         {
43             // Memory map the entire file contents
44             if (!file_data_sp && file_size > 0)
45             {
46                 assert (file_offset == 0);
47                 file_data_sp = file->MemoryMapFileContents(file_offset, file_size);
48             }
49 
50             if (!file_data_sp || file_data_sp->GetByteSize() == 0)
51             {
52                 // Check for archive file with format "/path/to/archive.a(object.o)"
53                 char path_with_object[PATH_MAX*2];
54                 module_sp->GetFileSpec().GetPath(path_with_object, sizeof(path_with_object));
55 
56                 FileSpec archive_file;
57                 ConstString archive_object;
58                 if (ObjectFile::SplitArchivePathWithObject (path_with_object, archive_file, archive_object))
59                 {
60                     file_size = archive_file.GetByteSize();
61                     if (file_size > 0)
62                     {
63                         module_sp->SetFileSpecAndObjectName (archive_file, archive_object);
64                         file_data_sp = archive_file.MemoryMapFileContents(file_offset, file_size);
65                     }
66                 }
67             }
68 
69             if (file_data_sp && file_data_sp->GetByteSize() > 0)
70             {
71                 uint32_t idx;
72 
73                 // Check if this is a normal object file by iterating through
74                 // all object file plugin instances.
75                 ObjectFileCreateInstance create_object_file_callback;
76                 for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx)
77                 {
78                     object_file_sp.reset (create_object_file_callback(module_sp, file_data_sp, file, file_offset, file_size));
79                     if (object_file_sp.get())
80                         return object_file_sp;
81                 }
82 
83                 // Check if this is a object container by iterating through
84                 // all object container plugin instances and then trying to get
85                 // an object file from the container.
86                 ObjectContainerCreateInstance create_object_container_callback;
87                 for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx)
88                 {
89                     std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, file_data_sp, file, file_offset, file_size));
90 
91                     if (object_container_ap.get())
92                         object_file_sp = object_container_ap->GetObjectFile(file);
93 
94                     if (object_file_sp.get())
95                         return object_file_sp;
96                 }
97             }
98         }
99     }
100     // We didn't find it, so clear our shared pointer in case it
101     // contains anything and return an empty shared pointer
102     object_file_sp.reset();
103     return object_file_sp;
104 }
105 
106 ObjectFileSP
107 ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp,
108                         const ProcessSP &process_sp,
109                         lldb::addr_t header_addr,
110                         DataBufferSP &file_data_sp)
111 {
112     ObjectFileSP object_file_sp;
113 
114     if (module_sp)
115     {
116         Timer scoped_timer (__PRETTY_FUNCTION__,
117                             "ObjectFile::FindPlugin (module = %s/%s, process = %p, header_addr = 0x%" PRIx64 ")",
118                             module_sp->GetFileSpec().GetDirectory().AsCString(),
119                             module_sp->GetFileSpec().GetFilename().AsCString(),
120                             process_sp.get(), header_addr);
121         uint32_t idx;
122 
123         // Check if this is a normal object file by iterating through
124         // all object file plugin instances.
125         ObjectFileCreateMemoryInstance create_callback;
126         for (idx = 0; (create_callback = PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != NULL; ++idx)
127         {
128             object_file_sp.reset (create_callback(module_sp, file_data_sp, process_sp, header_addr));
129             if (object_file_sp.get())
130                 return object_file_sp;
131         }
132 
133     }
134     // We didn't find it, so clear our shared pointer in case it
135     // contains anything and return an empty shared pointer
136     object_file_sp.reset();
137     return object_file_sp;
138 }
139 
140 ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
141                         const FileSpec *file_spec_ptr,
142                         addr_t file_offset,
143                         addr_t file_size,
144                         DataBufferSP& file_data_sp) :
145     ModuleChild (module_sp),
146     m_file (),  // This file could be different from the original module's file
147     m_type (eTypeInvalid),
148     m_strata (eStrataInvalid),
149     m_offset (file_offset),
150     m_length (file_size),
151     m_data (),
152     m_unwind_table (*this),
153     m_process_wp(),
154     m_memory_addr (LLDB_INVALID_ADDRESS)
155 {
156     if (file_spec_ptr)
157         m_file = *file_spec_ptr;
158     if (file_data_sp)
159         m_data.SetData (file_data_sp, file_offset, file_size);
160     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
161     if (log)
162     {
163         if (m_file)
164         {
165             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8" PRIx64 ", size = %" PRIu64 "\n",
166                          this,
167                          module_sp->GetFileSpec().GetDirectory().AsCString(),
168                          module_sp->GetFileSpec().GetFilename().AsCString(),
169                          m_file.GetDirectory().AsCString(),
170                          m_file.GetFilename().AsCString(),
171                          m_offset,
172                          m_length);
173         }
174         else
175         {
176             log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8" PRIx64 ", size = %" PRIu64 "\n",
177                          this,
178                          module_sp->GetFileSpec().GetDirectory().AsCString(),
179                          module_sp->GetFileSpec().GetFilename().AsCString(),
180                          m_offset,
181                          m_length);
182         }
183     }
184 }
185 
186 
187 ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp,
188                         const ProcessSP &process_sp,
189                         lldb::addr_t header_addr,
190                         DataBufferSP& header_data_sp) :
191     ModuleChild (module_sp),
192     m_file (),
193     m_type (eTypeInvalid),
194     m_strata (eStrataInvalid),
195     m_offset (header_addr),
196     m_length (0),
197     m_data (),
198     m_unwind_table (*this),
199     m_process_wp (process_sp),
200     m_memory_addr (header_addr)
201 {
202     if (header_data_sp)
203         m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
204     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
205     if (log)
206     {
207         log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, process = %p, header_addr = 0x%" PRIx64 "\n",
208                      this,
209                      module_sp->GetFileSpec().GetDirectory().AsCString(),
210                      module_sp->GetFileSpec().GetFilename().AsCString(),
211                      process_sp.get(),
212                      m_offset);
213     }
214 }
215 
216 
217 ObjectFile::~ObjectFile()
218 {
219     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
220     if (log)
221         log->Printf ("%p ObjectFile::~ObjectFile ()\n", this);
222 }
223 
224 bool
225 ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch)
226 {
227     ModuleSP module_sp (GetModule());
228     if (module_sp)
229         return module_sp->SetArchitecture (new_arch);
230     return false;
231 }
232 
233 AddressClass
234 ObjectFile::GetAddressClass (addr_t file_addr)
235 {
236     Symtab *symtab = GetSymtab();
237     if (symtab)
238     {
239         Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);
240         if (symbol)
241         {
242             if (symbol->ValueIsAddress())
243             {
244                 const SectionSP section_sp (symbol->GetAddress().GetSection());
245                 if (section_sp)
246                 {
247                     const SectionType section_type = section_sp->GetType();
248                     switch (section_type)
249                     {
250                     case eSectionTypeInvalid:               return eAddressClassUnknown;
251                     case eSectionTypeCode:                  return eAddressClassCode;
252                     case eSectionTypeContainer:             return eAddressClassUnknown;
253                     case eSectionTypeData:
254                     case eSectionTypeDataCString:
255                     case eSectionTypeDataCStringPointers:
256                     case eSectionTypeDataSymbolAddress:
257                     case eSectionTypeData4:
258                     case eSectionTypeData8:
259                     case eSectionTypeData16:
260                     case eSectionTypeDataPointers:
261                     case eSectionTypeZeroFill:
262                     case eSectionTypeDataObjCMessageRefs:
263                     case eSectionTypeDataObjCCFStrings:
264                         return eAddressClassData;
265                     case eSectionTypeDebug:
266                     case eSectionTypeDWARFDebugAbbrev:
267                     case eSectionTypeDWARFDebugAranges:
268                     case eSectionTypeDWARFDebugFrame:
269                     case eSectionTypeDWARFDebugInfo:
270                     case eSectionTypeDWARFDebugLine:
271                     case eSectionTypeDWARFDebugLoc:
272                     case eSectionTypeDWARFDebugMacInfo:
273                     case eSectionTypeDWARFDebugPubNames:
274                     case eSectionTypeDWARFDebugPubTypes:
275                     case eSectionTypeDWARFDebugRanges:
276                     case eSectionTypeDWARFDebugStr:
277                     case eSectionTypeDWARFAppleNames:
278                     case eSectionTypeDWARFAppleTypes:
279                     case eSectionTypeDWARFAppleNamespaces:
280                     case eSectionTypeDWARFAppleObjC:
281                         return eAddressClassDebug;
282                     case eSectionTypeEHFrame:               return eAddressClassRuntime;
283                     case eSectionTypeOther:                 return eAddressClassUnknown;
284                     }
285                 }
286             }
287 
288             const SymbolType symbol_type = symbol->GetType();
289             switch (symbol_type)
290             {
291             case eSymbolTypeAny:            return eAddressClassUnknown;
292             case eSymbolTypeAbsolute:       return eAddressClassUnknown;
293             case eSymbolTypeCode:           return eAddressClassCode;
294             case eSymbolTypeTrampoline:     return eAddressClassCode;
295             case eSymbolTypeData:           return eAddressClassData;
296             case eSymbolTypeRuntime:        return eAddressClassRuntime;
297             case eSymbolTypeException:      return eAddressClassRuntime;
298             case eSymbolTypeSourceFile:     return eAddressClassDebug;
299             case eSymbolTypeHeaderFile:     return eAddressClassDebug;
300             case eSymbolTypeObjectFile:     return eAddressClassDebug;
301             case eSymbolTypeCommonBlock:    return eAddressClassDebug;
302             case eSymbolTypeBlock:          return eAddressClassDebug;
303             case eSymbolTypeLocal:          return eAddressClassData;
304             case eSymbolTypeParam:          return eAddressClassData;
305             case eSymbolTypeVariable:       return eAddressClassData;
306             case eSymbolTypeVariableType:   return eAddressClassDebug;
307             case eSymbolTypeLineEntry:      return eAddressClassDebug;
308             case eSymbolTypeLineHeader:     return eAddressClassDebug;
309             case eSymbolTypeScopeBegin:     return eAddressClassDebug;
310             case eSymbolTypeScopeEnd:       return eAddressClassDebug;
311             case eSymbolTypeAdditional:     return eAddressClassUnknown;
312             case eSymbolTypeCompiler:       return eAddressClassDebug;
313             case eSymbolTypeInstrumentation:return eAddressClassDebug;
314             case eSymbolTypeUndefined:      return eAddressClassUnknown;
315             case eSymbolTypeObjCClass:      return eAddressClassRuntime;
316             case eSymbolTypeObjCMetaClass:  return eAddressClassRuntime;
317             case eSymbolTypeObjCIVar:       return eAddressClassRuntime;
318             }
319         }
320     }
321     return eAddressClassUnknown;
322 }
323 
324 DataBufferSP
325 ObjectFile::ReadMemory (const ProcessSP &process_sp, lldb::addr_t addr, size_t byte_size)
326 {
327     DataBufferSP data_sp;
328     if (process_sp)
329     {
330         std::auto_ptr<DataBufferHeap> data_ap (new DataBufferHeap (byte_size, 0));
331         Error error;
332         const size_t bytes_read = process_sp->ReadMemory (addr,
333                                                           data_ap->GetBytes(),
334                                                           data_ap->GetByteSize(),
335                                                           error);
336         if (bytes_read == byte_size)
337             data_sp.reset (data_ap.release());
338     }
339     return data_sp;
340 }
341 
342 size_t
343 ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
344 {
345     // The entire file has already been mmap'ed into m_data, so just copy from there
346     // as the back mmap buffer will be shared with shared pointers.
347     return data.SetData (m_data, offset, length);
348 }
349 
350 size_t
351 ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
352 {
353     // The entire file has already been mmap'ed into m_data, so just copy from there
354     return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
355 }
356 
357 
358 size_t
359 ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const
360 {
361     if (IsInMemory())
362     {
363         ProcessSP process_sp (m_process_wp.lock());
364         if (process_sp)
365         {
366             Error error;
367             return process_sp->ReadMemory (section->GetLoadBaseAddress (&process_sp->GetTarget()) + section_offset, dst, dst_len, error);
368         }
369     }
370     else
371     {
372         const uint64_t section_file_size = section->GetFileSize();
373         if (section_offset < section_file_size)
374         {
375             const uint64_t section_bytes_left = section_file_size - section_offset;
376             uint64_t section_dst_len = dst_len;
377             if (section_dst_len > section_bytes_left)
378                 section_dst_len = section_bytes_left;
379             return CopyData (section->GetFileOffset() + section_offset, section_dst_len, dst);
380         }
381         else
382         {
383             if (section->GetType() == eSectionTypeZeroFill)
384             {
385                 const uint64_t section_size = section->GetByteSize();
386                 const uint64_t section_bytes_left = section_size - section_offset;
387                 uint64_t section_dst_len = dst_len;
388                 if (section_dst_len > section_bytes_left)
389                     section_dst_len = section_bytes_left;
390                 bzero(dst, section_dst_len);
391                 return section_dst_len;
392             }
393         }
394     }
395     return 0;
396 }
397 
398 //----------------------------------------------------------------------
399 // Get the section data the file on disk
400 //----------------------------------------------------------------------
401 size_t
402 ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const
403 {
404     if (IsInMemory())
405     {
406         ProcessSP process_sp (m_process_wp.lock());
407         if (process_sp)
408         {
409             DataBufferSP data_sp (ReadMemory (process_sp, section->GetLoadBaseAddress (&process_sp->GetTarget()), section->GetByteSize()));
410             if (data_sp)
411             {
412                 section_data.SetData (data_sp, 0, data_sp->GetByteSize());
413                 section_data.SetByteOrder (process_sp->GetByteOrder());
414                 section_data.SetAddressByteSize (process_sp->GetAddressByteSize());
415                 return section_data.GetByteSize();
416             }
417         }
418     }
419     else
420     {
421         // The object file now contains a full mmap'ed copy of the object file data, so just use this
422         return MemoryMapSectionData (section, section_data);
423     }
424     section_data.Clear();
425     return 0;
426 }
427 
428 size_t
429 ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const
430 {
431     if (IsInMemory())
432     {
433         return ReadSectionData (section, section_data);
434     }
435     else
436     {
437         // The object file now contains a full mmap'ed copy of the object file data, so just use this
438         return GetData(section->GetFileOffset(), section->GetFileSize(), section_data);
439     }
440     section_data.Clear();
441     return 0;
442 }
443 
444 
445 bool
446 ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &archive_file, ConstString &archive_object)
447 {
448     RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$");
449     if (g_object_regex.Execute (path_with_object, 2))
450     {
451         std::string path;
452         std::string obj;
453         if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) &&
454             g_object_regex.GetMatchAtIndex (path_with_object, 2, obj))
455         {
456             archive_file.SetFile (path.c_str(), false);
457             archive_object.SetCString(obj.c_str());
458             return true;
459         }
460     }
461     return false;
462 }
463 
464