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/ObjectFile.h"
14 #include "lldb/Target/ExecutionContext.h"
15 #include "lldb/Target/Process.h"
16 #include "lldb/Target/Target.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 //static size_t
22 //ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len)
23 //{
24 //    if (exe_scope == NULL)
25 //        return 0;
26 //
27 //    lldb::AddressType addr_type = eAddressTypeInvalid;
28 //    addr_t addr = LLDB_INVALID_ADDRESS;
29 //
30 //    Process *process = exe_scope->CalculateProcess();
31 //
32 //    if (process && process->IsAlive())
33 //    {
34 //        addr = address.GetLoadAddress(process);
35 //        if (addr != LLDB_INVALID_ADDRESS)
36 //            addr_type = eAddressTypeLoad;
37 //    }
38 //
39 //    if (addr == LLDB_INVALID_ADDRESS)
40 //    {
41 //        addr = address.GetFileAddress();
42 //        if (addr != LLDB_INVALID_ADDRESS)
43 //            addr_type = eAddressTypeFile;
44 //    }
45 //
46 //    if (addr_type == eAddressTypeInvalid)
47 //        return false;
48 //
49 //    Target *target = exe_scope->CalculateTarget();
50 //    if (target)
51 //    {
52 //        Error error;
53 //        ObjectFile *objfile = NULL;
54 //        if (address.GetModule())
55 //            objfile = address.GetModule()->GetObjectFile();
56 //        return target->ReadMemory (addr_type, addr, dst, dst_len, error, objfile);
57 //    }
58 //    return 0;
59 //}
60 
61 static size_t
62 ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len)
63 {
64     if (exe_scope == NULL)
65         return 0;
66 
67     Target *target = exe_scope->CalculateTarget();
68     if (target)
69     {
70         Error error;
71         return target->ReadMemory (address, dst, dst_len, error);
72     }
73     return 0;
74 }
75 
76 static bool
77 GetByteOrderAndAddressSize (ExecutionContextScope *exe_scope, const Address &address, ByteOrder& byte_order, uint32_t& addr_size)
78 {
79     byte_order = eByteOrderInvalid;
80     addr_size = 0;
81     if (exe_scope == NULL)
82         return false;
83 
84     Process *process = exe_scope->CalculateProcess();
85     if (process)
86     {
87         byte_order = process->GetByteOrder();
88         addr_size = process->GetAddressByteSize();
89     }
90 
91     if (byte_order == eByteOrderInvalid || addr_size == 0)
92     {
93         Module *module = address.GetModule();
94         if (module)
95         {
96             byte_order = module->GetArchitecture().GetDefaultEndian();
97             addr_size = module->GetArchitecture().GetAddressByteSize();
98         }
99     }
100     return byte_order != eByteOrderInvalid && addr_size != 0;
101 }
102 
103 static uint64_t
104 ReadUIntMax64 (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, bool &success)
105 {
106     uint64_t uval64 = 0;
107     if (exe_scope == NULL || byte_size > sizeof(uint64_t))
108     {
109         success = false;
110         return 0;
111     }
112     uint64_t buf;
113 
114     success = ReadBytes (exe_scope, address, &buf, byte_size) == byte_size;
115     if (success)
116     {
117         ByteOrder byte_order = eByteOrderInvalid;
118         uint32_t addr_size = 0;
119         if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size))
120         {
121             DataExtractor data (&buf, sizeof(buf), byte_order, addr_size);
122             uint32_t offset = 0;
123             uval64 = data.GetU64(&offset);
124         }
125         else
126             success = false;
127     }
128     return uval64;
129 }
130 
131 static bool
132 ReadAddress (ExecutionContextScope *exe_scope, const Address &address, uint32_t pointer_size, Address &deref_so_addr)
133 {
134     if (exe_scope == NULL)
135         return false;
136 
137 
138     bool success = false;
139     addr_t deref_addr = ReadUIntMax64 (exe_scope, address, pointer_size, success);
140     if (success)
141     {
142         ExecutionContext exe_ctx;
143         exe_scope->CalculateExecutionContext(exe_ctx);
144         // If we have any sections that are loaded, try and resolve using the
145         // section load list
146         if (exe_ctx.target && !exe_ctx.target->GetSectionLoadList().IsEmpty())
147         {
148             if (exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (deref_addr, deref_so_addr))
149                 return true;
150         }
151         else
152         {
153             // If we were not running, yet able to read an integer, we must
154             // have a module
155             Module *module = address.GetModule();
156             assert (module);
157             if (module->ResolveFileAddress(deref_addr, deref_so_addr))
158                 return true;
159         }
160 
161         // We couldn't make "deref_addr" into a section offset value, but we were
162         // able to read the address, so we return a section offset address with
163         // no section and "deref_addr" as the offset (address).
164         deref_so_addr.SetSection(NULL);
165         deref_so_addr.SetOffset(deref_addr);
166         return true;
167     }
168     return false;
169 }
170 
171 static bool
172 DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm)
173 {
174     if (exe_scope == NULL || byte_size == 0)
175         return 0;
176     std::vector<uint8_t> buf(byte_size, 0);
177 
178     if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size())
179     {
180         ByteOrder byte_order = eByteOrderInvalid;
181         uint32_t addr_size = 0;
182         if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size))
183         {
184             DataExtractor data (&buf.front(), buf.size(), byte_order, addr_size);
185 
186             data.Dump (strm,
187                        0,                 // Start offset in "data"
188                        eFormatHex,        // Print as characters
189                        buf.size(),        // Size of item
190                        1,                 // Items count
191                        UINT32_MAX,        // num per line
192                        LLDB_INVALID_ADDRESS,// base address
193                        0,                 // bitfield bit size
194                        0);                // bitfield bit offset
195 
196             return true;
197         }
198     }
199     return false;
200 }
201 
202 
203 static size_t
204 ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm)
205 {
206     if (exe_scope == NULL)
207         return 0;
208     const size_t k_buf_len = 256;
209     char buf[k_buf_len+1];
210     buf[k_buf_len] = '\0'; // NULL terminate
211 
212     // Byte order and adderss size don't matter for C string dumping..
213     DataExtractor data (buf, sizeof(buf), eByteOrderHost, 4);
214     size_t total_len = 0;
215     size_t bytes_read;
216     Address curr_address(address);
217     strm->PutChar ('"');
218     while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0)
219     {
220         size_t len = strlen(buf);
221         if (len == 0)
222             break;
223         if (len > bytes_read)
224             len = bytes_read;
225 
226         data.Dump (strm,
227                    0,                 // Start offset in "data"
228                    eFormatChar,       // Print as characters
229                    1,                 // Size of item (1 byte for a char!)
230                    len,               // How many bytes to print?
231                    UINT32_MAX,        // num per line
232                    LLDB_INVALID_ADDRESS,// base address
233                    0,                 // bitfield bit size
234 
235                    0);                // bitfield bit offset
236 
237         total_len += bytes_read;
238 
239         if (len < k_buf_len)
240             break;
241         curr_address.SetOffset (curr_address.GetOffset() + bytes_read);
242     }
243     strm->PutChar ('"');
244     return total_len;
245 }
246 
247 Address::Address (addr_t address, const SectionList * sections) :
248     m_section (NULL),
249     m_offset (LLDB_INVALID_ADDRESS)
250 {
251     ResolveAddressUsingFileSections(address, sections);
252 }
253 
254 const Address&
255 Address::operator= (const Address& rhs)
256 {
257     if (this != &rhs)
258     {
259         m_section = rhs.m_section;
260         m_offset = rhs.m_offset;
261     }
262     return *this;
263 }
264 
265 bool
266 Address::ResolveAddressUsingFileSections (addr_t addr, const SectionList *sections)
267 {
268     if (sections)
269         m_section = sections->FindSectionContainingFileAddress(addr).get();
270     else
271         m_section = NULL;
272 
273     if (m_section != NULL)
274     {
275         assert( m_section->ContainsFileAddress(addr) );
276         m_offset = addr - m_section->GetFileAddress();
277         return true;    // Successfully transformed addr into a section offset address
278     }
279 
280     m_offset = addr;
281     return false;       // Failed to resolve this address to a section offset value
282 }
283 
284 //bool
285 //Address::ResolveAddressUsingLoadSections (addr_t addr, const SectionList *sections)
286 //{
287 //    if (sections)
288 //        m_section = sections->FindSectionContainingLoadAddress(addr).get();
289 //    else
290 //        m_section = NULL;
291 //
292 //    if (m_section != NULL)
293 //    {
294 //        assert( m_section->ContainsLoadAddress(addr) );
295 //        m_offset = addr - m_section->GetLoadBaseAddress();
296 //        return true;    // Successfully transformed addr into a section offset address
297 //    }
298 //
299 //    m_offset = addr;
300 //    return false;       // Failed to resolve this address to a section offset value
301 //}
302 //
303 Module *
304 Address::GetModule () const
305 {
306     if (m_section)
307         return m_section->GetModule();
308     return NULL;
309 }
310 
311 //addr_t
312 //Address::Address() const
313 //{
314 //  addr_t addr = GetLoadAddress();
315 //  if (addr != LLDB_INVALID_ADDRESS)
316 //      return addr;
317 //  return GetFileAddress();
318 //}
319 //
320 
321 addr_t
322 Address::GetFileAddress () const
323 {
324     if (m_section != NULL)
325     {
326         addr_t sect_file_addr = m_section->GetFileAddress();
327         if (sect_file_addr == LLDB_INVALID_ADDRESS)
328         {
329             // Section isn't resolved, we can't return a valid file address
330             return LLDB_INVALID_ADDRESS;
331         }
332         // We have a valid file range, so we can return the file based
333         // address by adding the file base address to our offset
334         return sect_file_addr + m_offset;
335     }
336     // No section, we just return the offset since it is the value in this case
337     return m_offset;
338 }
339 
340 addr_t
341 Address::GetLoadAddress (Target *target) const
342 {
343     if (m_section == NULL)
344     {
345         // No section, we just return the offset since it is the value in this case
346         return m_offset;
347     }
348 
349     if (target)
350     {
351         addr_t sect_load_addr = m_section->GetLoadBaseAddress (target);
352 
353         if (sect_load_addr != LLDB_INVALID_ADDRESS)
354         {
355             // We have a valid file range, so we can return the file based
356             // address by adding the file base address to our offset
357             return sect_load_addr + m_offset;
358         }
359     }
360     // The section isn't resolved or no process was supplied so we can't
361     // return a valid file address.
362     return LLDB_INVALID_ADDRESS;
363 }
364 
365 bool
366 Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const
367 {
368     // If the section was NULL, only load address is going to work.
369     if (m_section == NULL)
370         style = DumpStyleLoadAddress;
371 
372     Target *target = NULL;
373     Process *process = NULL;
374     if (exe_scope)
375     {
376         target = exe_scope->CalculateTarget();
377         process = exe_scope->CalculateProcess();
378     }
379     // If addr_byte_size is UINT32_MAX, then determine the correct address
380     // byte size for the process or default to the size of addr_t
381     if (addr_size == UINT32_MAX)
382     {
383         if (process)
384             addr_size = process->GetAddressByteSize ();
385         else
386             addr_size = sizeof(addr_t);
387     }
388 
389     Address so_addr;
390     switch (style)
391     {
392     case DumpStyleInvalid:
393         return false;
394 
395     case DumpStyleSectionNameOffset:
396         if (m_section != NULL)
397         {
398             m_section->DumpName(s);
399             s->Printf (" + %llu", m_offset);
400         }
401         else
402         {
403             s->Address(m_offset, addr_size);
404         }
405         break;
406 
407     case DumpStyleSectionPointerOffset:
408         s->Printf("(Section *)%.*p + ", (int)sizeof(void*) * 2, m_section);
409         s->Address(m_offset, addr_size);
410         break;
411 
412     case DumpStyleModuleWithFileAddress:
413         s->Printf("%s[", m_section->GetModule()->GetFileSpec().GetFilename().AsCString());
414         // Fall through
415     case DumpStyleFileAddress:
416         {
417             addr_t file_addr = GetFileAddress();
418             if (file_addr == LLDB_INVALID_ADDRESS)
419             {
420                 if (fallback_style != DumpStyleInvalid)
421                     return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
422                 return false;
423             }
424             s->Address (file_addr, addr_size);
425             if (style == DumpStyleModuleWithFileAddress)
426                 s->PutChar(']');
427         }
428         break;
429 
430     case DumpStyleLoadAddress:
431         {
432             addr_t load_addr = GetLoadAddress (target);
433             if (load_addr == LLDB_INVALID_ADDRESS)
434             {
435                 if (fallback_style != DumpStyleInvalid)
436                     return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
437                 return false;
438             }
439             s->Address (load_addr, addr_size);
440         }
441         break;
442 
443     case DumpStyleResolvedDescription:
444     case DumpStyleResolvedDescriptionNoModule:
445         if (IsSectionOffset())
446         {
447             lldb::AddressType addr_type = eAddressTypeLoad;
448             addr_t addr = GetLoadAddress (target);
449             if (addr == LLDB_INVALID_ADDRESS)
450             {
451                 addr = GetFileAddress();
452                 addr_type = eAddressTypeFile;
453             }
454 
455             uint32_t pointer_size = 4;
456             Module *module = GetModule();
457             if (process)
458                 pointer_size = process->GetAddressByteSize();
459             else if (module)
460                 pointer_size = module->GetArchitecture().GetAddressByteSize();
461 
462             bool showed_info = false;
463             const Section *section = GetSection();
464             if (section)
465             {
466                 SectionType sect_type = section->GetType();
467                 switch (sect_type)
468                 {
469                 case eSectionTypeData:
470                     if (module)
471                     {
472                         ObjectFile *objfile = module->GetObjectFile();
473                         if (objfile)
474                         {
475                             Symtab *symtab = objfile->GetSymtab();
476                             if (symtab)
477                             {
478                                 const addr_t file_Addr = GetFileAddress();
479                                 Symbol *symbol = symtab->FindSymbolContainingFileAddress (file_Addr);
480                                 if (symbol)
481                                 {
482                                     const char *symbol_name = symbol->GetName().AsCString();
483                                     if (symbol_name)
484                                     {
485                                         s->PutCString(symbol_name);
486                                         addr_t delta = file_Addr - symbol->GetAddressRangePtr()->GetBaseAddress().GetFileAddress();
487                                         if (delta)
488                                             s->Printf(" + %llu", delta);
489                                         showed_info = true;
490                                     }
491                                 }
492                             }
493                         }
494                     }
495                     break;
496 
497                 case eSectionTypeDataCString:
498                     // Read the C string from memory and display it
499                     showed_info = true;
500                     ReadCStringFromMemory (exe_scope, *this, s);
501                     break;
502 
503                 case eSectionTypeDataCStringPointers:
504                     {
505                         if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
506                         {
507 #if VERBOSE_OUTPUT
508                             s->PutCString("(char *)");
509                             so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
510                             s->PutCString(": ");
511 #endif
512                             showed_info = true;
513                             ReadCStringFromMemory (exe_scope, so_addr, s);
514                         }
515                     }
516                     break;
517 
518                 case eSectionTypeDataObjCMessageRefs:
519                     {
520                         if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
521                         {
522                             if (target && so_addr.IsSectionOffset())
523                             {
524                                 SymbolContext func_sc;
525                                 target->GetImages().ResolveSymbolContextForAddress (so_addr,
526                                                                                     eSymbolContextEverything,
527                                                                                     func_sc);
528                                 if (func_sc.function || func_sc.symbol)
529                                 {
530                                     showed_info = true;
531 #if VERBOSE_OUTPUT
532                                     s->PutCString ("(objc_msgref *) -> { (func*)");
533                                     so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
534 #else
535                                     s->PutCString ("{ ");
536 #endif
537                                     Address cstr_addr(*this);
538                                     cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size);
539                                     func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false);
540                                     if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr))
541                                     {
542 #if VERBOSE_OUTPUT
543                                         s->PutCString("), (char *)");
544                                         so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
545                                         s->PutCString(" (");
546 #else
547                                         s->PutCString(", ");
548 #endif
549                                         ReadCStringFromMemory (exe_scope, so_addr, s);
550                                     }
551 #if VERBOSE_OUTPUT
552                                     s->PutCString(") }");
553 #else
554                                     s->PutCString(" }");
555 #endif
556                                 }
557                             }
558                         }
559                     }
560                     break;
561 
562                 case eSectionTypeDataObjCCFStrings:
563                     {
564                         Address cfstring_data_addr(*this);
565                         cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() + (2 * pointer_size));
566                         if (ReadAddress (exe_scope, cfstring_data_addr, pointer_size, so_addr))
567                         {
568 #if VERBOSE_OUTPUT
569                             s->PutCString("(CFString *) ");
570                             cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
571                             s->PutCString(" -> @");
572 #else
573                             s->PutChar('@');
574 #endif
575                             if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription))
576                                 showed_info = true;
577                         }
578                     }
579                     break;
580 
581                 case eSectionTypeData4:
582                     // Read the 4 byte data and display it
583                     showed_info = true;
584                     s->PutCString("(uint32_t) ");
585                     DumpUInt (exe_scope, *this, 4, s);
586                     break;
587 
588                 case eSectionTypeData8:
589                     // Read the 8 byte data and display it
590                     showed_info = true;
591                     s->PutCString("(uint64_t) ");
592                     DumpUInt (exe_scope, *this, 8, s);
593                     break;
594 
595                 case eSectionTypeData16:
596                     // Read the 16 byte data and display it
597                     showed_info = true;
598                     s->PutCString("(uint128_t) ");
599                     DumpUInt (exe_scope, *this, 16, s);
600                     break;
601 
602                 case eSectionTypeDataPointers:
603                     // Read the pointer data and display it
604                     {
605                         if (ReadAddress (exe_scope, *this, pointer_size, so_addr))
606                         {
607                             s->PutCString ("(void *)");
608                             so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress);
609 
610                             showed_info = true;
611                             if (so_addr.IsSectionOffset())
612                             {
613                                 SymbolContext pointer_sc;
614                                 if (target)
615                                 {
616                                     target->GetImages().ResolveSymbolContextForAddress (so_addr,
617                                                                                         eSymbolContextEverything,
618                                                                                         pointer_sc);
619                                     if (pointer_sc.function || pointer_sc.symbol)
620                                     {
621                                         s->PutCString(": ");
622                                         pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false);
623                                     }
624                                 }
625                             }
626                         }
627                     }
628                     break;
629 
630                 default:
631                     break;
632                 }
633             }
634 
635             if (!showed_info)
636             {
637                 if (module)
638                 {
639                     SymbolContext sc;
640                     module->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
641                     if (sc.function || sc.symbol)
642                     {
643                         bool show_stop_context = true;
644                         const bool show_module = (style == DumpStyleResolvedDescription);
645                         const bool show_fullpaths = false;
646                         const bool show_inlined_frames = false;
647                         if (sc.function == NULL && sc.symbol != NULL)
648                         {
649                             // If we have just a symbol make sure it is in the right section
650                             if (sc.symbol->GetAddressRangePtr())
651                             {
652                                 if (sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetSection() != GetSection())
653                                 {
654                                     // don't show the module if the symbol is a trampoline symbol
655                                     show_stop_context = false;
656                                 }
657                             }
658                         }
659                         if (show_stop_context)
660                         {
661                             // We have a function or a symbol from the same
662                             // sections as this address.
663                             sc.DumpStopContext (s,
664                                                 exe_scope,
665                                                 *this,
666                                                 show_fullpaths,
667                                                 show_module,
668                                                 show_inlined_frames);
669                         }
670                         else
671                         {
672                             // We found a symbol but it was in a different
673                             // section so it isn't the symbol we should be
674                             // showing, just show the section name + offset
675                             Dump (s, exe_scope, DumpStyleSectionNameOffset);
676                         }
677                     }
678                 }
679             }
680         }
681         else
682         {
683             if (fallback_style != DumpStyleInvalid)
684                 return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
685             return false;
686         }
687         break;
688 
689     case DumpStyleDetailedSymbolContext:
690         if (IsSectionOffset())
691         {
692             Module *module = GetModule();
693             if (module)
694             {
695                 SymbolContext sc;
696                 module->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc);
697                 if (sc.symbol)
698                 {
699                     // If we have just a symbol make sure it is in the same section
700                     // as our address. If it isn't, then we might have just found
701                     // the last symbol that came before the address that we are
702                     // looking up that has nothing to do with our address lookup.
703                     if (sc.symbol->GetAddressRangePtr() && sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetSection() != GetSection())
704                         sc.symbol = NULL;
705                 }
706                 sc.GetDescription(s, eDescriptionLevelBrief, target);
707             }
708         }
709         if (fallback_style != DumpStyleInvalid)
710             return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
711         return false;
712         break;
713     }
714 
715     return true;
716 }
717 
718 //Stream& operator << (Stream& s, const Address& so_addr)
719 //{
720 //    so_addr.Dump(&s, Address::DumpStyleSectionNameOffset);
721 //    return s;
722 //}
723 //
724 void
725 Address::CalculateSymbolContext (SymbolContext *sc)
726 {
727     sc->Clear();
728     // Absolute addresses don't have enough information to reconstruct even their target.
729     if (m_section == NULL)
730         return;
731 
732     if (m_section->GetModule())
733     {
734         sc->module_sp = m_section->GetModule()->GetSP();
735         if (sc->module_sp)
736             sc->module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextEverything, *sc);
737     }
738 }
739 
740 void
741 Address::DumpDebug(Stream *s) const
742 {
743     *s << (void *)this << ": " << "Address";
744     if (m_section != NULL)
745     {
746         *s << ", section = " << (void *)m_section << " (" << m_section->GetName() << "), offset = " << m_offset;
747     }
748     else
749     {
750         *s << ", vm_addr = " << m_offset;
751     }
752     s->EOL();
753 }
754 
755 int
756 Address::CompareFileAddress (const Address& a, const Address& b)
757 {
758     addr_t a_file_addr = a.GetFileAddress();
759     addr_t b_file_addr = b.GetFileAddress();
760     if (a_file_addr < b_file_addr)
761         return -1;
762     if (a_file_addr > b_file_addr)
763         return +1;
764     return 0;
765 }
766 
767 
768 int
769 Address::CompareLoadAddress (const Address& a, const Address& b, Target *target)
770 {
771     assert (target != NULL);
772     addr_t a_load_addr = a.GetLoadAddress (target);
773     addr_t b_load_addr = b.GetLoadAddress (target);
774     if (a_load_addr < b_load_addr)
775         return -1;
776     if (a_load_addr > b_load_addr)
777         return +1;
778     return 0;
779 }
780 
781 int
782 Address::CompareModulePointerAndOffset (const Address& a, const Address& b)
783 {
784     Module *a_module = a.GetModule ();
785     Module *b_module = b.GetModule ();
786     if (a_module < b_module)
787         return -1;
788     if (a_module > b_module)
789         return +1;
790     // Modules are the same, just compare the file address since they should
791     // be unique
792     addr_t a_file_addr = a.GetFileAddress();
793     addr_t b_file_addr = b.GetFileAddress();
794     if (a_file_addr < b_file_addr)
795         return -1;
796     if (a_file_addr > b_file_addr)
797         return +1;
798     return 0;
799 }
800 
801 
802 size_t
803 Address::MemorySize () const
804 {
805     // Noting special for the memory size of a single Address object,
806     // it is just the size of itself.
807     return sizeof(Address);
808 }
809 
810 
811 /// The only comparisons that make sense are the load addresses
812 //bool
813 //lldb::operator< (const Address& lhs, const Address& rhs)
814 //{
815 //    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
816 //    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
817 //
818 //    if (lhs_addr == rhs_addr)
819 //    {
820 //        lhs_addr = lhs.GetFileAddress();
821 //        rhs_addr = rhs.GetFileAddress();
822 //    }
823 //    return lhs_addr < rhs_addr;
824 //}
825 //
826 //bool
827 //lldb::operator<=    (const Address& lhs, const Address& rhs)
828 //{
829 //    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
830 //    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
831 //
832 //    if (lhs_addr == rhs_addr)
833 //    {
834 //        lhs_addr = lhs.GetFileAddress();
835 //        rhs_addr = rhs.GetFileAddress();
836 //    }
837 //    return lhs_addr <= rhs_addr;
838 //}
839 //
840 //bool
841 //lldb::operator> (const Address& lhs, const Address& rhs)
842 //{
843 //    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
844 //    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
845 //
846 //    if (lhs_addr == rhs_addr)
847 //    {
848 //        lhs_addr = lhs.GetFileAddress();
849 //        rhs_addr = rhs.GetFileAddress();
850 //    }
851 //    return lhs_addr > rhs_addr;
852 //}
853 //
854 //bool
855 //lldb::operator>=    (const Address& lhs, const Address& rhs)
856 //{
857 //    lldb::addr_t lhs_addr = lhs.GetLoadAddress();
858 //    lldb::addr_t rhs_addr = rhs.GetLoadAddress();
859 //
860 //    if (lhs_addr == rhs_addr)
861 //    {
862 //        lhs_addr = lhs.GetFileAddress();
863 //        rhs_addr = rhs.GetFileAddress();
864 //    }
865 //    return lhs_addr >= rhs_addr;
866 //}
867 //
868 
869 // The operator == checks for exact equality only (same section, same offset)
870 bool
871 lldb_private::operator== (const Address& a, const Address& rhs)
872 {
873     return  a.GetSection() == rhs.GetSection() &&
874             a.GetOffset()  == rhs.GetOffset();
875 }
876 // The operator != checks for exact inequality only (differing section, or
877 // different offset)
878 bool
879 lldb_private::operator!= (const Address& a, const Address& rhs)
880 {
881     return  a.GetSection() != rhs.GetSection() ||
882             a.GetOffset()  != rhs.GetOffset();
883 }
884 
885 bool
886 Address::IsLinkedAddress () const
887 {
888     return m_section && m_section->GetLinkedSection();
889 }
890 
891 
892 void
893 Address::ResolveLinkedAddress ()
894 {
895     if (m_section)
896     {
897         const Section *linked_section = m_section->GetLinkedSection();
898         if (linked_section)
899         {
900             m_offset += m_section->GetLinkedOffset();
901             m_section = linked_section;
902         }
903     }
904 }
905