Address.cpp revision 269024
1//===-- Address.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/Core/Address.h"
11#include "lldb/Core/Module.h"
12#include "lldb/Core/Section.h"
13#include "lldb/Symbol/Block.h"
14#include "lldb/Symbol/ObjectFile.h"
15#include "lldb/Symbol/Variable.h"
16#include "lldb/Symbol/VariableList.h"
17#include "lldb/Target/ExecutionContext.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/SectionLoadList.h"
20#include "lldb/Target/Target.h"
21#include "lldb/Symbol/SymbolVendor.h"
22
23#include "llvm/ADT/Triple.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28static size_t
29ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len)
30{
31    if (exe_scope == NULL)
32        return 0;
33
34    TargetSP target_sp (exe_scope->CalculateTarget());
35    if (target_sp)
36    {
37        Error error;
38        bool prefer_file_cache = false;
39        return target_sp->ReadMemory (address, prefer_file_cache, dst, dst_len, error);
40    }
41    return 0;
42}
43
44static bool
45GetByteOrderAndAddressSize (ExecutionContextScope *exe_scope, const Address &address, ByteOrder& byte_order, uint32_t& addr_size)
46{
47    byte_order = eByteOrderInvalid;
48    addr_size = 0;
49    if (exe_scope == NULL)
50        return false;
51
52    TargetSP target_sp (exe_scope->CalculateTarget());
53    if (target_sp)
54    {
55        byte_order = target_sp->GetArchitecture().GetByteOrder();
56        addr_size = target_sp->GetArchitecture().GetAddressByteSize();
57    }
58
59    if (byte_order == eByteOrderInvalid || addr_size == 0)
60    {
61        ModuleSP module_sp (address.GetModule());
62        if (module_sp)
63        {
64            byte_order = module_sp->GetArchitecture().GetByteOrder();
65            addr_size = module_sp->GetArchitecture().GetAddressByteSize();
66        }
67    }
68    return byte_order != eByteOrderInvalid && addr_size != 0;
69}
70
71static uint64_t
72ReadUIntMax64 (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, bool &success)
73{
74    uint64_t uval64 = 0;
75    if (exe_scope == NULL || byte_size > sizeof(uint64_t))
76    {
77        success = false;
78        return 0;
79    }
80    uint64_t buf = 0;
81
82    success = ReadBytes (exe_scope, address, &buf, byte_size) == byte_size;
83    if (success)
84    {
85        ByteOrder byte_order = eByteOrderInvalid;
86        uint32_t addr_size = 0;
87        if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size))
88        {
89            DataExtractor data (&buf, sizeof(buf), byte_order, addr_size);
90            lldb::offset_t offset = 0;
91            uval64 = data.GetU64(&offset);
92        }
93        else
94            success = false;
95    }
96    return uval64;
97}
98
99static bool
100ReadAddress (ExecutionContextScope *exe_scope, const Address &address, uint32_t pointer_size, Address &deref_so_addr)
101{
102    if (exe_scope == NULL)
103        return false;
104
105
106    bool success = false;
107    addr_t deref_addr = ReadUIntMax64 (exe_scope, address, pointer_size, success);
108    if (success)
109    {
110        ExecutionContext exe_ctx;
111        exe_scope->CalculateExecutionContext(exe_ctx);
112        // If we have any sections that are loaded, try and resolve using the
113        // section load list
114        Target *target = exe_ctx.GetTargetPtr();
115        if (target && !target->GetSectionLoadList().IsEmpty())
116        {
117            if (target->GetSectionLoadList().ResolveLoadAddress (deref_addr, deref_so_addr))
118                return true;
119        }
120        else
121        {
122            // If we were not running, yet able to read an integer, we must
123            // have a module
124            ModuleSP module_sp (address.GetModule());
125
126            assert (module_sp);
127            if (module_sp->ResolveFileAddress(deref_addr, deref_so_addr))
128                return true;
129        }
130
131        // We couldn't make "deref_addr" into a section offset value, but we were
132        // able to read the address, so we return a section offset address with
133        // no section and "deref_addr" as the offset (address).
134        deref_so_addr.SetRawAddress(deref_addr);
135        return true;
136    }
137    return false;
138}
139
140static bool
141DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm)
142{
143    if (exe_scope == NULL || byte_size == 0)
144        return 0;
145    std::vector<uint8_t> buf(byte_size, 0);
146
147    if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size())
148    {
149        ByteOrder byte_order = eByteOrderInvalid;
150        uint32_t addr_size = 0;
151        if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size))
152        {
153            DataExtractor data (&buf.front(), buf.size(), byte_order, addr_size);
154
155            data.Dump (strm,
156                       0,                 // Start offset in "data"
157                       eFormatHex,        // Print as characters
158                       buf.size(),        // Size of item
159                       1,                 // Items count
160                       UINT32_MAX,        // num per line
161                       LLDB_INVALID_ADDRESS,// base address
162                       0,                 // bitfield bit size
163                       0);                // bitfield bit offset
164
165            return true;
166        }
167    }
168    return false;
169}
170
171
172static size_t
173ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm)
174{
175    if (exe_scope == NULL)
176        return 0;
177    const size_t k_buf_len = 256;
178    char buf[k_buf_len+1];
179    buf[k_buf_len] = '\0'; // NULL terminate
180
181    // Byte order and address size don't matter for C string dumping..
182    DataExtractor data (buf, sizeof(buf), lldb::endian::InlHostByteOrder(), 4);
183    size_t total_len = 0;
184    size_t bytes_read;
185    Address curr_address(address);
186    strm->PutChar ('"');
187    while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0)
188    {
189        size_t len = strlen(buf);
190        if (len == 0)
191            break;
192        if (len > bytes_read)
193            len = bytes_read;
194
195        data.Dump (strm,
196                   0,                 // Start offset in "data"
197                   eFormatChar,       // Print as characters
198                   1,                 // Size of item (1 byte for a char!)
199                   len,               // How many bytes to print?
200                   UINT32_MAX,        // num per line
201                   LLDB_INVALID_ADDRESS,// base address
202                   0,                 // bitfield bit size
203
204                   0);                // bitfield bit offset
205
206        total_len += bytes_read;
207
208        if (len < k_buf_len)
209            break;
210        curr_address.SetOffset (curr_address.GetOffset() + bytes_read);
211    }
212    strm->PutChar ('"');
213    return total_len;
214}
215
216Address::Address (lldb::addr_t abs_addr) :
217    m_section_wp (),
218    m_offset (abs_addr)
219{
220}
221
222Address::Address (addr_t address, const SectionList *section_list) :
223    m_section_wp (),
224    m_offset (LLDB_INVALID_ADDRESS)
225{
226    ResolveAddressUsingFileSections(address, section_list);
227}
228
229const Address&
230Address::operator= (const Address& rhs)
231{
232    if (this != &rhs)
233    {
234        m_section_wp = rhs.m_section_wp;
235        m_offset = rhs.m_offset.load();
236    }
237    return *this;
238}
239
240bool
241Address::ResolveAddressUsingFileSections (addr_t file_addr, const SectionList *section_list)
242{
243    if (section_list)
244    {
245        SectionSP section_sp (section_list->FindSectionContainingFileAddress(file_addr));
246        m_section_wp = section_sp;
247        if (section_sp)
248        {
249            assert( section_sp->ContainsFileAddress(file_addr) );
250            m_offset = file_addr - section_sp->GetFileAddress();
251            return true;    // Successfully transformed addr into a section offset address
252        }
253    }
254    m_offset = file_addr;
255    return false;       // Failed to resolve this address to a section offset value
256}
257
258ModuleSP
259Address::GetModule () const
260{
261    lldb::ModuleSP module_sp;
262    SectionSP section_sp (GetSection());
263    if (section_sp)
264        module_sp = section_sp->GetModule();
265    return module_sp;
266}
267
268addr_t
269Address::GetFileAddress () const
270{
271    SectionSP section_sp (GetSection());
272    if (section_sp)
273    {
274        addr_t sect_file_addr = section_sp->GetFileAddress();
275        if (sect_file_addr == LLDB_INVALID_ADDRESS)
276        {
277            // Section isn't resolved, we can't return a valid file address
278            return LLDB_INVALID_ADDRESS;
279        }
280        // We have a valid file range, so we can return the file based
281        // address by adding the file base address to our offset
282        return sect_file_addr + m_offset;
283    }
284    else if (SectionWasDeletedPrivate())
285    {
286        // Used to have a valid section but it got deleted so the
287        // offset doesn't mean anything without the section
288        return LLDB_INVALID_ADDRESS;
289    }
290    // No section, we just return the offset since it is the value in this case
291    return m_offset;
292}
293
294addr_t
295Address::GetLoadAddress (Target *target) const
296{
297    SectionSP section_sp (GetSection());
298    if (section_sp)
299    {
300        if (target)
301        {
302            addr_t sect_load_addr = section_sp->GetLoadBaseAddress (target);
303
304            if (sect_load_addr != LLDB_INVALID_ADDRESS)
305            {
306                // We have a valid file range, so we can return the file based
307                // address by adding the file base address to our offset
308                return sect_load_addr + m_offset;
309            }
310        }
311    }
312    else if (SectionWasDeletedPrivate())
313    {
314        // Used to have a valid section but it got deleted so the
315        // offset doesn't mean anything without the section
316        return LLDB_INVALID_ADDRESS;
317    }
318    else
319    {
320        // We don't have a section so the offset is the load address
321        return m_offset;
322    }
323    // The section isn't resolved or an invalid target was passed in
324    // so we can't return a valid load address.
325    return LLDB_INVALID_ADDRESS;
326}
327
328addr_t
329Address::GetCallableLoadAddress (Target *target, bool is_indirect) const
330{
331    addr_t code_addr = LLDB_INVALID_ADDRESS;
332
333    if (is_indirect && target)
334    {
335        ProcessSP processSP = target->GetProcessSP();
336        Error error;
337        if (processSP.get())
338        {
339            code_addr = processSP->ResolveIndirectFunction(this, error);
340            if (!error.Success())
341                code_addr = LLDB_INVALID_ADDRESS;
342        }
343    }
344    else
345    {
346        code_addr = GetLoadAddress (target);
347    }
348
349    if (code_addr == LLDB_INVALID_ADDRESS)
350        return code_addr;
351
352    if (target)
353        return target->GetCallableLoadAddress (code_addr, GetAddressClass());
354    return code_addr;
355}
356
357bool
358Address::SetCallableLoadAddress (lldb::addr_t load_addr, Target *target)
359{
360    if (SetLoadAddress (load_addr, target))
361    {
362        if (target)
363            m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass());
364        return true;
365    }
366    return false;
367}
368
369addr_t
370Address::GetOpcodeLoadAddress (Target *target) const
371{
372    addr_t code_addr = GetLoadAddress (target);
373    if (code_addr != LLDB_INVALID_ADDRESS)
374        code_addr = target->GetOpcodeLoadAddress (code_addr, GetAddressClass());
375    return code_addr;
376}
377
378bool
379Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target)
380{
381    if (SetLoadAddress (load_addr, target))
382    {
383        if (target)
384            m_offset = target->GetOpcodeLoadAddress (m_offset, GetAddressClass());
385        return true;
386    }
387    return false;
388}
389
390bool
391Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const
392{
393    // If the section was NULL, only load address is going to work unless we are
394    // trying to deref a pointer
395    SectionSP section_sp (GetSection());
396    if (!section_sp && style != DumpStyleResolvedPointerDescription)
397        style = DumpStyleLoadAddress;
398
399    ExecutionContext exe_ctx (exe_scope);
400    Target *target = exe_ctx.GetTargetPtr();
401    // If addr_byte_size is UINT32_MAX, then determine the correct address
402    // byte size for the process or default to the size of addr_t
403    if (addr_size == UINT32_MAX)
404    {
405        if (target)
406            addr_size = target->GetArchitecture().GetAddressByteSize ();
407        else
408            addr_size = sizeof(addr_t);
409    }
410
411    Address so_addr;
412    switch (style)
413    {
414    case DumpStyleInvalid:
415        return false;
416
417    case DumpStyleSectionNameOffset:
418        if (section_sp)
419        {
420            section_sp->DumpName(s);
421            s->Printf (" + %" PRIu64, m_offset.load());
422        }
423        else
424        {
425            s->Address(m_offset, addr_size);
426        }
427        break;
428
429    case DumpStyleSectionPointerOffset:
430        s->Printf("(Section *)%p + ", section_sp.get());
431        s->Address(m_offset, addr_size);
432        break;
433
434    case DumpStyleModuleWithFileAddress:
435        if (section_sp)
436            s->Printf("%s[", section_sp->GetModule()->GetFileSpec().GetFilename().AsCString());
437        // Fall through
438    case DumpStyleFileAddress:
439        {
440            addr_t file_addr = GetFileAddress();
441            if (file_addr == LLDB_INVALID_ADDRESS)
442            {
443                if (fallback_style != DumpStyleInvalid)
444                    return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
445                return false;
446            }
447            s->Address (file_addr, addr_size);
448            if (style == DumpStyleModuleWithFileAddress && section_sp)
449                s->PutChar(']');
450        }
451        break;
452
453    case DumpStyleLoadAddress:
454        {
455            addr_t load_addr = GetLoadAddress (target);
456            if (load_addr == LLDB_INVALID_ADDRESS)
457            {
458                if (fallback_style != DumpStyleInvalid)
459                    return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
460                return false;
461            }
462            s->Address (load_addr, addr_size);
463        }
464        break;
465
466    case DumpStyleResolvedDescription:
467    case DumpStyleResolvedDescriptionNoModule:
468        if (IsSectionOffset())
469        {
470            uint32_t pointer_size = 4;
471            ModuleSP module_sp (GetModule());
472            if (target)
473                pointer_size = target->GetArchitecture().GetAddressByteSize();
474            else if (module_sp)
475                pointer_size = module_sp->GetArchitecture().GetAddressByteSize();
476
477            bool showed_info = false;
478            if (section_sp)
479            {
480                SectionType sect_type = section_sp->GetType();
481                switch (sect_type)
482                {
483                case eSectionTypeData:
484                    if (module_sp)
485                    {
486                        SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
487                        if (sym_vendor)
488                        {
489                            Symtab *symtab = sym_vendor->GetSymtab();
490                            if (symtab)
491                            {
492                                const addr_t file_Addr = GetFileAddress();
493                                Symbol *symbol = symtab->FindSymbolContainingFileAddress (file_Addr);
494                                if (symbol)
495                                {
496                                    const char *symbol_name = symbol->GetName().AsCString();
497                                    if (symbol_name)
498                                    {
499                                        s->PutCString(symbol_name);
500                                        addr_t delta = file_Addr - symbol->GetAddress().GetFileAddress();
501                                        if (delta)
502                                            s->Printf(" + %" PRIu64, delta);
503                                        showed_info = true;
504                                    }
505                                }
506                            }
507                        }
508                    }
509                    break;
510
511                case eSectionTypeDataCString:
512                    // Read the C string from memory and display it
513                    showed_info = true;
514                    ReadCStringFromMemory (exe_scope, *this, s);
515                    break;
516
517                case eSectionTypeDataCStringPointers:
518                    {
519                        if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
520                        {
521#if VERBOSE_OUTPUT
522                            s->PutCString("(char *)");
523                            so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
524                            s->PutCString(": ");
525#endif
526                            showed_info = true;
527                            ReadCStringFromMemory (exe_scope, so_addr, s);
528                        }
529                    }
530                    break;
531
532                case eSectionTypeDataObjCMessageRefs:
533                    {
534                        if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
535                        {
536                            if (target && so_addr.IsSectionOffset())
537                            {
538                                SymbolContext func_sc;
539                                target->GetImages().ResolveSymbolContextForAddress (so_addr,
540                                                                                             eSymbolContextEverything,
541                                                                                             func_sc);
542                                if (func_sc.function || func_sc.symbol)
543                                {
544                                    showed_info = true;
545#if VERBOSE_OUTPUT
546                                    s->PutCString ("(objc_msgref *) -> { (func*)");
547                                    so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
548#else
549                                    s->PutCString ("{ ");
550#endif
551                                    Address cstr_addr(*this);
552                                    cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size);
553                                    func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false);
554                                    if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr))
555                                    {
556#if VERBOSE_OUTPUT
557                                        s->PutCString("), (char *)");
558                                        so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
559                                        s->PutCString(" (");
560#else
561                                        s->PutCString(", ");
562#endif
563                                        ReadCStringFromMemory (exe_scope, so_addr, s);
564                                    }
565#if VERBOSE_OUTPUT
566                                    s->PutCString(") }");
567#else
568                                    s->PutCString(" }");
569#endif
570                                }
571                            }
572                        }
573                    }
574                    break;
575
576                case eSectionTypeDataObjCCFStrings:
577                    {
578                        Address cfstring_data_addr(*this);
579                        cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() + (2 * pointer_size));
580                        if (ReadAddress (exe_scope, cfstring_data_addr, pointer_size, so_addr))
581                        {
582#if VERBOSE_OUTPUT
583                            s->PutCString("(CFString *) ");
584                            cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
585                            s->PutCString(" -> @");
586#else
587                            s->PutChar('@');
588#endif
589                            if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription))
590                                showed_info = true;
591                        }
592                    }
593                    break;
594
595                case eSectionTypeData4:
596                    // Read the 4 byte data and display it
597                    showed_info = true;
598                    s->PutCString("(uint32_t) ");
599                    DumpUInt (exe_scope, *this, 4, s);
600                    break;
601
602                case eSectionTypeData8:
603                    // Read the 8 byte data and display it
604                    showed_info = true;
605                    s->PutCString("(uint64_t) ");
606                    DumpUInt (exe_scope, *this, 8, s);
607                    break;
608
609                case eSectionTypeData16:
610                    // Read the 16 byte data and display it
611                    showed_info = true;
612                    s->PutCString("(uint128_t) ");
613                    DumpUInt (exe_scope, *this, 16, s);
614                    break;
615
616                case eSectionTypeDataPointers:
617                    // Read the pointer data and display it
618                    {
619                        if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
620                        {
621                            s->PutCString ("(void *)");
622                            so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
623
624                            showed_info = true;
625                            if (so_addr.IsSectionOffset())
626                            {
627                                SymbolContext pointer_sc;
628                                if (target)
629                                {
630                                    target->GetImages().ResolveSymbolContextForAddress (so_addr,
631                                                                                                 eSymbolContextEverything,
632                                                                                                 pointer_sc);
633                                    if (pointer_sc.function || pointer_sc.symbol)
634                                    {
635                                        s->PutCString(": ");
636                                        pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false);
637                                    }
638                                }
639                            }
640                        }
641                    }
642                    break;
643
644                default:
645                    break;
646                }
647            }
648
649            if (!showed_info)
650            {
651                if (module_sp)
652                {
653                    SymbolContext sc;
654                    module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
655                    if (sc.function || sc.symbol)
656                    {
657                        bool show_stop_context = true;
658                        const bool show_module = (style == DumpStyleResolvedDescription);
659                        const bool show_fullpaths = false;
660                        const bool show_inlined_frames = true;
661                        if (sc.function == NULL && sc.symbol != NULL)
662                        {
663                            // If we have just a symbol make sure it is in the right section
664                            if (sc.symbol->ValueIsAddress())
665                            {
666                                if (sc.symbol->GetAddress().GetSection() != GetSection())
667                                {
668                                    // don't show the module if the symbol is a trampoline symbol
669                                    show_stop_context = false;
670                                }
671                            }
672                        }
673                        if (show_stop_context)
674                        {
675                            // We have a function or a symbol from the same
676                            // sections as this address.
677                            sc.DumpStopContext (s,
678                                                exe_scope,
679                                                *this,
680                                                show_fullpaths,
681                                                show_module,
682                                                show_inlined_frames);
683                        }
684                        else
685                        {
686                            // We found a symbol but it was in a different
687                            // section so it isn't the symbol we should be
688                            // showing, just show the section name + offset
689                            Dump (s, exe_scope, DumpStyleSectionNameOffset);
690                        }
691                    }
692                }
693            }
694        }
695        else
696        {
697            if (fallback_style != DumpStyleInvalid)
698                return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
699            return false;
700        }
701        break;
702
703    case DumpStyleDetailedSymbolContext:
704        if (IsSectionOffset())
705        {
706            ModuleSP module_sp (GetModule());
707            if (module_sp)
708            {
709                SymbolContext sc;
710                module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
711                if (sc.symbol)
712                {
713                    // If we have just a symbol make sure it is in the same section
714                    // as our address. If it isn't, then we might have just found
715                    // the last symbol that came before the address that we are
716                    // looking up that has nothing to do with our address lookup.
717                    if (sc.symbol->ValueIsAddress() && sc.symbol->GetAddress().GetSection() != GetSection())
718                        sc.symbol = NULL;
719                }
720                sc.GetDescription(s, eDescriptionLevelBrief, target);
721
722                if (sc.block)
723                {
724                    bool can_create = true;
725                    bool get_parent_variables = true;
726                    bool stop_if_block_is_inlined_function = false;
727                    VariableList variable_list;
728                    sc.block->AppendVariables (can_create,
729                                               get_parent_variables,
730                                               stop_if_block_is_inlined_function,
731                                               &variable_list);
732
733                    const size_t num_variables = variable_list.GetSize();
734                    for (size_t var_idx = 0; var_idx < num_variables; ++var_idx)
735                    {
736                        Variable *var = variable_list.GetVariableAtIndex (var_idx).get();
737                        if (var && var->LocationIsValidForAddress (*this))
738                        {
739                            s->Indent();
740                            s->Printf ("   Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\", type= \"%s\", location =",
741                                       var->GetID(),
742                                       var->GetName().GetCString(),
743                                       var->GetType()->GetName().GetCString());
744                            var->DumpLocationForAddress(s, *this);
745                            s->PutCString(", decl = ");
746                            var->GetDeclaration().DumpStopContext(s, false);
747                            s->EOL();
748                        }
749                    }
750                }
751            }
752        }
753        else
754        {
755            if (fallback_style != DumpStyleInvalid)
756                return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
757            return false;
758        }
759        break;
760    case DumpStyleResolvedPointerDescription:
761        {
762            Process *process = exe_ctx.GetProcessPtr();
763            if (process)
764            {
765                addr_t load_addr = GetLoadAddress (target);
766                if (load_addr != LLDB_INVALID_ADDRESS)
767                {
768                    Error memory_error;
769                    addr_t dereferenced_load_addr = process->ReadPointerFromMemory(load_addr, memory_error);
770                    if (dereferenced_load_addr != LLDB_INVALID_ADDRESS)
771                    {
772                        Address dereferenced_addr;
773                        if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr, target))
774                        {
775                            StreamString strm;
776                            if (dereferenced_addr.Dump (&strm, exe_scope, DumpStyleResolvedDescription, DumpStyleInvalid, addr_size))
777                            {
778                                s->Address (dereferenced_load_addr, addr_size, " -> ", " ");
779                                s->Write(strm.GetData(), strm.GetSize());
780                                return true;
781                            }
782                        }
783                    }
784                }
785            }
786            if (fallback_style != DumpStyleInvalid)
787                return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
788            return false;
789        }
790        break;
791    }
792
793    return true;
794}
795
796bool
797Address::SectionWasDeleted() const
798{
799    if (GetSection())
800        return false;
801    return SectionWasDeletedPrivate();
802}
803
804bool
805Address::SectionWasDeletedPrivate() const
806{
807    lldb::SectionWP empty_section_wp;
808
809    // If either call to "std::weak_ptr::owner_before(...) value returns true, this
810    // indicates that m_section_wp once contained (possibly still does) a reference
811    // to a valid shared pointer. This helps us know if we had a valid reference to
812    // a section which is now invalid because the module it was in was unloaded/deleted,
813    // or if the address doesn't have a valid reference to a section.
814    return empty_section_wp.owner_before(m_section_wp) || m_section_wp.owner_before(empty_section_wp);
815}
816
817uint32_t
818Address::CalculateSymbolContext (SymbolContext *sc, uint32_t resolve_scope) const
819{
820    sc->Clear(false);
821    // Absolute addresses don't have enough information to reconstruct even their target.
822
823    SectionSP section_sp (GetSection());
824    if (section_sp)
825    {
826        ModuleSP module_sp (section_sp->GetModule());
827        if (module_sp)
828        {
829            sc->module_sp = module_sp;
830            if (sc->module_sp)
831                return sc->module_sp->ResolveSymbolContextForAddress (*this, resolve_scope, *sc);
832        }
833    }
834    return 0;
835}
836
837ModuleSP
838Address::CalculateSymbolContextModule () const
839{
840    SectionSP section_sp (GetSection());
841    if (section_sp)
842        return section_sp->GetModule();
843    return ModuleSP();
844}
845
846CompileUnit *
847Address::CalculateSymbolContextCompileUnit () const
848{
849    SectionSP section_sp (GetSection());
850    if (section_sp)
851    {
852        SymbolContext sc;
853        sc.module_sp = section_sp->GetModule();
854        if (sc.module_sp)
855        {
856            sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextCompUnit, sc);
857            return sc.comp_unit;
858        }
859    }
860    return NULL;
861}
862
863Function *
864Address::CalculateSymbolContextFunction () const
865{
866    SectionSP section_sp (GetSection());
867    if (section_sp)
868    {
869        SymbolContext sc;
870        sc.module_sp = section_sp->GetModule();
871        if (sc.module_sp)
872        {
873            sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextFunction, sc);
874            return sc.function;
875        }
876    }
877    return NULL;
878}
879
880Block *
881Address::CalculateSymbolContextBlock () const
882{
883    SectionSP section_sp (GetSection());
884    if (section_sp)
885    {
886        SymbolContext sc;
887        sc.module_sp = section_sp->GetModule();
888        if (sc.module_sp)
889        {
890            sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextBlock, sc);
891            return sc.block;
892        }
893    }
894    return NULL;
895}
896
897Symbol *
898Address::CalculateSymbolContextSymbol () const
899{
900    SectionSP section_sp (GetSection());
901    if (section_sp)
902    {
903        SymbolContext sc;
904        sc.module_sp = section_sp->GetModule();
905        if (sc.module_sp)
906        {
907            sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextSymbol, sc);
908            return sc.symbol;
909        }
910    }
911    return NULL;
912}
913
914bool
915Address::CalculateSymbolContextLineEntry (LineEntry &line_entry) const
916{
917    SectionSP section_sp (GetSection());
918    if (section_sp)
919    {
920        SymbolContext sc;
921        sc.module_sp = section_sp->GetModule();
922        if (sc.module_sp)
923        {
924            sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextLineEntry, sc);
925            if (sc.line_entry.IsValid())
926            {
927                line_entry = sc.line_entry;
928                return true;
929            }
930        }
931    }
932    line_entry.Clear();
933    return false;
934}
935
936int
937Address::CompareFileAddress (const Address& a, const Address& b)
938{
939    addr_t a_file_addr = a.GetFileAddress();
940    addr_t b_file_addr = b.GetFileAddress();
941    if (a_file_addr < b_file_addr)
942        return -1;
943    if (a_file_addr > b_file_addr)
944        return +1;
945    return 0;
946}
947
948
949int
950Address::CompareLoadAddress (const Address& a, const Address& b, Target *target)
951{
952    assert (target != NULL);
953    addr_t a_load_addr = a.GetLoadAddress (target);
954    addr_t b_load_addr = b.GetLoadAddress (target);
955    if (a_load_addr < b_load_addr)
956        return -1;
957    if (a_load_addr > b_load_addr)
958        return +1;
959    return 0;
960}
961
962int
963Address::CompareModulePointerAndOffset (const Address& a, const Address& b)
964{
965    ModuleSP a_module_sp (a.GetModule());
966    ModuleSP b_module_sp (b.GetModule());
967    Module *a_module = a_module_sp.get();
968    Module *b_module = b_module_sp.get();
969    if (a_module < b_module)
970        return -1;
971    if (a_module > b_module)
972        return +1;
973    // Modules are the same, just compare the file address since they should
974    // be unique
975    addr_t a_file_addr = a.GetFileAddress();
976    addr_t b_file_addr = b.GetFileAddress();
977    if (a_file_addr < b_file_addr)
978        return -1;
979    if (a_file_addr > b_file_addr)
980        return +1;
981    return 0;
982}
983
984
985size_t
986Address::MemorySize () const
987{
988    // Noting special for the memory size of a single Address object,
989    // it is just the size of itself.
990    return sizeof(Address);
991}
992
993
994//----------------------------------------------------------------------
995// NOTE: Be careful using this operator. It can correctly compare two
996// addresses from the same Module correctly. It can't compare two
997// addresses from different modules in any meaningful way, but it will
998// compare the module pointers.
999//
1000// To sum things up:
1001// - works great for addresses within the same module
1002// - it works for addresses across multiple modules, but don't expect the
1003//   address results to make much sense
1004//
1005// This basically lets Address objects be used in ordered collection
1006// classes.
1007//----------------------------------------------------------------------
1008
1009bool
1010lldb_private::operator< (const Address& lhs, const Address& rhs)
1011{
1012    ModuleSP lhs_module_sp (lhs.GetModule());
1013    ModuleSP rhs_module_sp (rhs.GetModule());
1014    Module *lhs_module = lhs_module_sp.get();
1015    Module *rhs_module = rhs_module_sp.get();
1016    if (lhs_module == rhs_module)
1017    {
1018        // Addresses are in the same module, just compare the file addresses
1019        return lhs.GetFileAddress() < rhs.GetFileAddress();
1020    }
1021    else
1022    {
1023        // The addresses are from different modules, just use the module
1024        // pointer value to get consistent ordering
1025        return lhs_module < rhs_module;
1026    }
1027}
1028
1029bool
1030lldb_private::operator> (const Address& lhs, const Address& rhs)
1031{
1032    ModuleSP lhs_module_sp (lhs.GetModule());
1033    ModuleSP rhs_module_sp (rhs.GetModule());
1034    Module *lhs_module = lhs_module_sp.get();
1035    Module *rhs_module = rhs_module_sp.get();
1036    if (lhs_module == rhs_module)
1037    {
1038        // Addresses are in the same module, just compare the file addresses
1039        return lhs.GetFileAddress() > rhs.GetFileAddress();
1040    }
1041    else
1042    {
1043        // The addresses are from different modules, just use the module
1044        // pointer value to get consistent ordering
1045        return lhs_module > rhs_module;
1046    }
1047}
1048
1049
1050// The operator == checks for exact equality only (same section, same offset)
1051bool
1052lldb_private::operator== (const Address& a, const Address& rhs)
1053{
1054    return  a.GetOffset()  == rhs.GetOffset() &&
1055            a.GetSection() == rhs.GetSection();
1056}
1057// The operator != checks for exact inequality only (differing section, or
1058// different offset)
1059bool
1060lldb_private::operator!= (const Address& a, const Address& rhs)
1061{
1062    return  a.GetOffset()  != rhs.GetOffset() ||
1063            a.GetSection() != rhs.GetSection();
1064}
1065
1066AddressClass
1067Address::GetAddressClass () const
1068{
1069    ModuleSP module_sp (GetModule());
1070    if (module_sp)
1071    {
1072        ObjectFile *obj_file = module_sp->GetObjectFile();
1073        if (obj_file)
1074        {
1075            // Give the symbol vendor a chance to add to the unified section list.
1076            module_sp->GetSymbolVendor();
1077            return obj_file->GetAddressClass (GetFileAddress());
1078        }
1079    }
1080    return eAddressClassUnknown;
1081}
1082
1083bool
1084Address::SetLoadAddress (lldb::addr_t load_addr, Target *target)
1085{
1086    if (target && target->GetSectionLoadList().ResolveLoadAddress(load_addr, *this))
1087        return true;
1088    m_section_wp.reset();
1089    m_offset = load_addr;
1090    return false;
1091}
1092
1093