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