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.8llx, file_size = 0x%8.8llx)",
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%llx)",
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.8llx, size = %llu\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.8llx, size = %llu\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%llx\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     {
222         ModuleSP module_sp (GetModule());
223         if (m_file)
224         {
225             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n",
226                          this,
227                          module_sp->GetFileSpec().GetDirectory().AsCString(),
228                          module_sp->GetFileSpec().GetFilename().AsCString(),
229                          m_file.GetDirectory().AsCString(),
230                          m_file.GetFilename().AsCString(),
231                          m_offset,
232                          m_length);
233         }
234         else
235         {
236             log->Printf ("%p ObjectFile::~ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n",
237                          this,
238                          module_sp->GetFileSpec().GetDirectory().AsCString(),
239                          module_sp->GetFileSpec().GetFilename().AsCString(),
240                          m_offset,
241                          m_length);
242         }
243     }
244 }
245 
246 bool
247 ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch)
248 {
249     ModuleSP module_sp (GetModule());
250     if (module_sp)
251         return module_sp->SetArchitecture (new_arch);
252     return false;
253 }
254 
255 AddressClass
256 ObjectFile::GetAddressClass (addr_t file_addr)
257 {
258     Symtab *symtab = GetSymtab();
259     if (symtab)
260     {
261         Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);
262         if (symbol)
263         {
264             if (symbol->ValueIsAddress())
265             {
266                 const SectionSP section_sp (symbol->GetAddress().GetSection());
267                 if (section_sp)
268                 {
269                     const SectionType section_type = section_sp->GetType();
270                     switch (section_type)
271                     {
272                     case eSectionTypeInvalid:               return eAddressClassUnknown;
273                     case eSectionTypeCode:                  return eAddressClassCode;
274                     case eSectionTypeContainer:             return eAddressClassUnknown;
275                     case eSectionTypeData:
276                     case eSectionTypeDataCString:
277                     case eSectionTypeDataCStringPointers:
278                     case eSectionTypeDataSymbolAddress:
279                     case eSectionTypeData4:
280                     case eSectionTypeData8:
281                     case eSectionTypeData16:
282                     case eSectionTypeDataPointers:
283                     case eSectionTypeZeroFill:
284                     case eSectionTypeDataObjCMessageRefs:
285                     case eSectionTypeDataObjCCFStrings:
286                         return eAddressClassData;
287                     case eSectionTypeDebug:
288                     case eSectionTypeDWARFDebugAbbrev:
289                     case eSectionTypeDWARFDebugAranges:
290                     case eSectionTypeDWARFDebugFrame:
291                     case eSectionTypeDWARFDebugInfo:
292                     case eSectionTypeDWARFDebugLine:
293                     case eSectionTypeDWARFDebugLoc:
294                     case eSectionTypeDWARFDebugMacInfo:
295                     case eSectionTypeDWARFDebugPubNames:
296                     case eSectionTypeDWARFDebugPubTypes:
297                     case eSectionTypeDWARFDebugRanges:
298                     case eSectionTypeDWARFDebugStr:
299                     case eSectionTypeDWARFAppleNames:
300                     case eSectionTypeDWARFAppleTypes:
301                     case eSectionTypeDWARFAppleNamespaces:
302                     case eSectionTypeDWARFAppleObjC:
303                         return eAddressClassDebug;
304                     case eSectionTypeEHFrame:               return eAddressClassRuntime;
305                     case eSectionTypeOther:                 return eAddressClassUnknown;
306                     }
307                 }
308             }
309 
310             const SymbolType symbol_type = symbol->GetType();
311             switch (symbol_type)
312             {
313             case eSymbolTypeAny:            return eAddressClassUnknown;
314             case eSymbolTypeAbsolute:       return eAddressClassUnknown;
315             case eSymbolTypeCode:           return eAddressClassCode;
316             case eSymbolTypeTrampoline:     return eAddressClassCode;
317             case eSymbolTypeData:           return eAddressClassData;
318             case eSymbolTypeRuntime:        return eAddressClassRuntime;
319             case eSymbolTypeException:      return eAddressClassRuntime;
320             case eSymbolTypeSourceFile:     return eAddressClassDebug;
321             case eSymbolTypeHeaderFile:     return eAddressClassDebug;
322             case eSymbolTypeObjectFile:     return eAddressClassDebug;
323             case eSymbolTypeCommonBlock:    return eAddressClassDebug;
324             case eSymbolTypeBlock:          return eAddressClassDebug;
325             case eSymbolTypeLocal:          return eAddressClassData;
326             case eSymbolTypeParam:          return eAddressClassData;
327             case eSymbolTypeVariable:       return eAddressClassData;
328             case eSymbolTypeVariableType:   return eAddressClassDebug;
329             case eSymbolTypeLineEntry:      return eAddressClassDebug;
330             case eSymbolTypeLineHeader:     return eAddressClassDebug;
331             case eSymbolTypeScopeBegin:     return eAddressClassDebug;
332             case eSymbolTypeScopeEnd:       return eAddressClassDebug;
333             case eSymbolTypeAdditional:     return eAddressClassUnknown;
334             case eSymbolTypeCompiler:       return eAddressClassDebug;
335             case eSymbolTypeInstrumentation:return eAddressClassDebug;
336             case eSymbolTypeUndefined:      return eAddressClassUnknown;
337             case eSymbolTypeObjCClass:      return eAddressClassRuntime;
338             case eSymbolTypeObjCMetaClass:  return eAddressClassRuntime;
339             case eSymbolTypeObjCIVar:       return eAddressClassRuntime;
340             }
341         }
342     }
343     return eAddressClassUnknown;
344 }
345 
346 DataBufferSP
347 ObjectFile::ReadMemory (const ProcessSP &process_sp, lldb::addr_t addr, size_t byte_size)
348 {
349     DataBufferSP data_sp;
350     if (process_sp)
351     {
352         std::auto_ptr<DataBufferHeap> data_ap (new DataBufferHeap (byte_size, 0));
353         Error error;
354         const size_t bytes_read = process_sp->ReadMemory (addr,
355                                                           data_ap->GetBytes(),
356                                                           data_ap->GetByteSize(),
357                                                           error);
358         if (bytes_read == byte_size)
359             data_sp.reset (data_ap.release());
360     }
361     return data_sp;
362 }
363 
364 size_t
365 ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const
366 {
367     // The entire file has already been mmap'ed into m_data, so just copy from there
368     // as the back mmap buffer will be shared with shared pointers.
369     return data.SetData (m_data, offset, length);
370 }
371 
372 size_t
373 ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
374 {
375     // The entire file has already been mmap'ed into m_data, so just copy from there
376     return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder());
377 }
378 
379 
380 size_t
381 ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const
382 {
383     if (IsInMemory())
384     {
385         ProcessSP process_sp (m_process_wp.lock());
386         if (process_sp)
387         {
388             Error error;
389             return process_sp->ReadMemory (section->GetLoadBaseAddress (&process_sp->GetTarget()) + section_offset, dst, dst_len, error);
390         }
391     }
392     else
393     {
394         const uint64_t section_file_size = section->GetFileSize();
395         if (section_offset < section_file_size)
396         {
397             const uint64_t section_bytes_left = section_file_size - section_offset;
398             uint64_t section_dst_len = dst_len;
399             if (section_dst_len > section_bytes_left)
400                 section_dst_len = section_bytes_left;
401             return CopyData (section->GetFileOffset() + section_offset, section_dst_len, dst);
402         }
403     }
404     return 0;
405 }
406 
407 //----------------------------------------------------------------------
408 // Get the section data the file on disk
409 //----------------------------------------------------------------------
410 size_t
411 ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const
412 {
413     if (IsInMemory())
414     {
415         ProcessSP process_sp (m_process_wp.lock());
416         if (process_sp)
417         {
418             DataBufferSP data_sp (ReadMemory (process_sp, section->GetLoadBaseAddress (&process_sp->GetTarget()), section->GetByteSize()));
419             if (data_sp)
420             {
421                 section_data.SetData (data_sp, 0, data_sp->GetByteSize());
422                 section_data.SetByteOrder (process_sp->GetByteOrder());
423                 section_data.SetAddressByteSize (process_sp->GetAddressByteSize());
424                 return section_data.GetByteSize();
425             }
426         }
427     }
428     else
429     {
430         // The object file now contains a full mmap'ed copy of the object file data, so just use this
431         return MemoryMapSectionData (section, section_data);
432     }
433     section_data.Clear();
434     return 0;
435 }
436 
437 size_t
438 ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const
439 {
440     if (IsInMemory())
441     {
442         return ReadSectionData (section, section_data);
443     }
444     else
445     {
446         // The object file now contains a full mmap'ed copy of the object file data, so just use this
447         return GetData(section->GetFileOffset(), section->GetFileSize(), section_data);
448     }
449     section_data.Clear();
450     return 0;
451 }
452 
453 
454 bool
455 ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &archive_file, ConstString &archive_object)
456 {
457     RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$");
458     if (g_object_regex.Execute (path_with_object, 2))
459     {
460         std::string path;
461         std::string obj;
462         if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) &&
463             g_object_regex.GetMatchAtIndex (path_with_object, 2, obj))
464         {
465             archive_file.SetFile (path.c_str(), false);
466             archive_object.SetCString(obj.c_str());
467             return true;
468         }
469     }
470     return false;
471 }
472 
473