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