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