Home | History | Annotate | Line # | Download | only in libunwind
AddressSpace.hpp revision 1.9
      1  1.1     joerg //===------------------------- AddressSpace.hpp ---------------------------===//
      2  1.1     joerg //
      3  1.1     joerg //                     The LLVM Compiler Infrastructure
      4  1.1     joerg //
      5  1.1     joerg // This file is dual licensed under the MIT and the University of Illinois Open
      6  1.1     joerg // Source Licenses. See LICENSE.TXT for details.
      7  1.1     joerg //
      8  1.1     joerg //
      9  1.1     joerg // Abstracts accessing local vs remote address spaces.
     10  1.1     joerg //
     11  1.1     joerg //===----------------------------------------------------------------------===//
     12  1.1     joerg 
     13  1.1     joerg #ifndef __ADDRESSSPACE_HPP__
     14  1.1     joerg #define __ADDRESSSPACE_HPP__
     15  1.1     joerg 
     16  1.1     joerg #include <sys/rbtree.h>
     17  1.1     joerg #include <cassert>
     18  1.1     joerg #include <cstddef>
     19  1.1     joerg #include <cstdint>
     20  1.1     joerg #include <cstdlib>
     21  1.1     joerg #include <cstring>
     22  1.1     joerg #include <dlfcn.h>
     23  1.1     joerg #include <elf.h>
     24  1.1     joerg #include <link.h>
     25  1.1     joerg #include <pthread.h>
     26  1.1     joerg 
     27  1.1     joerg #include "dwarf2.h"
     28  1.1     joerg 
     29  1.1     joerg namespace _Unwind {
     30  1.1     joerg 
     31  1.1     joerg static int rangeCmp(void *, const void *, const void *);
     32  1.1     joerg static int rangeCmpKey(void *, const void *, const void *);
     33  1.1     joerg static int dsoTableCmp(void *, const void *, const void *);
     34  1.1     joerg static int dsoTableCmpKey(void *, const void *, const void *);
     35  1.1     joerg static int phdr_callback(struct dl_phdr_info *, size_t, void *);
     36  1.1     joerg 
     37  1.1     joerg struct unw_proc_info_t {
     38  1.1     joerg   uintptr_t data_base;       // Base address for data-relative relocations
     39  1.1     joerg   uintptr_t start_ip;        // Start address of function
     40  1.1     joerg   uintptr_t end_ip;          // First address after end of function
     41  1.1     joerg   uintptr_t lsda;            // Address of Language Specific Data Area
     42  1.1     joerg   uintptr_t handler;         // Personality routine
     43  1.1     joerg   uintptr_t extra_args;      // Extra stack space for frameless routines
     44  1.1     joerg   uintptr_t unwind_info;     // Address of DWARF unwind info
     45  1.1     joerg };
     46  1.1     joerg 
     47  1.1     joerg /// LocalAddressSpace is used as a template parameter to UnwindCursor when
     48  1.1     joerg /// unwinding a thread in the same process.  The wrappers compile away,
     49  1.1     joerg /// making local unwinds fast.
     50  1.1     joerg class LocalAddressSpace {
     51  1.1     joerg public:
     52  1.1     joerg   typedef uintptr_t pint_t;
     53  1.1     joerg   typedef intptr_t sint_t;
     54  1.1     joerg 
     55  1.1     joerg   typedef void (*findPCRange_t)(LocalAddressSpace &, pint_t, pint_t &pcStart,
     56  1.1     joerg                                 pint_t &pcEnd);
     57  1.1     joerg 
     58  1.1     joerg   LocalAddressSpace(findPCRange_t findPCRange_)
     59  1.1     joerg       : findPCRange(findPCRange_), needsReload(true) {
     60  1.1     joerg     static const rb_tree_ops_t segmentTreeOps = {
     61  1.1     joerg       rangeCmp, rangeCmpKey, offsetof(Range, range_link), NULL
     62  1.1     joerg     };
     63  1.1     joerg     static const rb_tree_ops_t dsoTreeOps = {
     64  1.1     joerg       dsoTableCmp, dsoTableCmpKey, offsetof(Range, dso_link), NULL
     65  1.1     joerg     };
     66  1.1     joerg     rb_tree_init(&segmentTree, &segmentTreeOps);
     67  1.1     joerg     rb_tree_init(&dsoTree, &dsoTreeOps);
     68  1.1     joerg     pthread_rwlock_init(&fdeTreeLock, NULL);
     69  1.1     joerg   }
     70  1.1     joerg 
     71  1.4     joerg   uint8_t get8(pint_t addr) {
     72  1.4     joerg     uint8_t val;
     73  1.4     joerg     memcpy(&val, (void *)addr, sizeof(val));
     74  1.4     joerg     return val;
     75  1.4     joerg   }
     76  1.1     joerg 
     77  1.4     joerg   uint16_t get16(pint_t addr) {
     78  1.4     joerg     uint16_t val;
     79  1.4     joerg     memcpy(&val, (void *)addr, sizeof(val));
     80  1.4     joerg     return val;
     81  1.4     joerg   }
     82  1.1     joerg 
     83  1.4     joerg   uint32_t get32(pint_t addr) {
     84  1.4     joerg     uint32_t val;
     85  1.4     joerg     memcpy(&val, (void *)addr, sizeof(val));
     86  1.4     joerg     return val;
     87  1.4     joerg   }
     88  1.1     joerg 
     89  1.4     joerg   uint64_t get64(pint_t addr) {
     90  1.4     joerg     uint64_t val;
     91  1.4     joerg     memcpy(&val, (void *)addr, sizeof(val));
     92  1.4     joerg     return val;
     93  1.4     joerg   }
     94  1.1     joerg 
     95  1.1     joerg   uintptr_t getP(pint_t addr) {
     96  1.1     joerg     if (sizeof(uintptr_t) == sizeof(uint32_t))
     97  1.1     joerg       return get32(addr);
     98  1.1     joerg     else
     99  1.1     joerg       return get64(addr);
    100  1.1     joerg   }
    101  1.1     joerg 
    102  1.1     joerg   uint64_t getULEB128(pint_t &addr, pint_t end) {
    103  1.1     joerg     uint64_t result = 0;
    104  1.1     joerg     uint8_t byte;
    105  1.1     joerg     int bit = 0;
    106  1.1     joerg     do {
    107  1.1     joerg       uint64_t b;
    108  1.1     joerg 
    109  1.1     joerg       assert(addr != end);
    110  1.1     joerg 
    111  1.1     joerg       byte = get8(addr++);
    112  1.1     joerg       b = byte & 0x7f;
    113  1.1     joerg 
    114  1.1     joerg       assert(bit < 64);
    115  1.1     joerg       assert(b << bit >> bit == b);
    116  1.1     joerg 
    117  1.1     joerg       result |= b << bit;
    118  1.1     joerg       bit += 7;
    119  1.1     joerg     } while (byte >= 0x80);
    120  1.1     joerg     return result;
    121  1.1     joerg   }
    122  1.1     joerg 
    123  1.1     joerg   int64_t getSLEB128(pint_t &addr, pint_t end) {
    124  1.1     joerg     uint64_t result = 0;
    125  1.1     joerg     uint8_t byte;
    126  1.1     joerg     int bit = 0;
    127  1.1     joerg     do {
    128  1.1     joerg       uint64_t b;
    129  1.1     joerg 
    130  1.1     joerg       assert(addr != end);
    131  1.1     joerg 
    132  1.1     joerg       byte = get8(addr++);
    133  1.1     joerg       b = byte & 0x7f;
    134  1.1     joerg 
    135  1.1     joerg       assert(bit < 64);
    136  1.1     joerg       assert(b << bit >> bit == b);
    137  1.1     joerg 
    138  1.1     joerg       result |= b << bit;
    139  1.1     joerg       bit += 7;
    140  1.1     joerg     } while (byte >= 0x80);
    141  1.1     joerg     // sign extend negative numbers
    142  1.1     joerg     if ((byte & 0x40) != 0)
    143  1.9  christos       result |= (~0ULL) << bit;
    144  1.1     joerg     return result;
    145  1.1     joerg   }
    146  1.1     joerg 
    147  1.1     joerg   pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
    148  1.1     joerg                      const unw_proc_info_t *ctx) {
    149  1.1     joerg     pint_t startAddr = addr;
    150  1.1     joerg     const uint8_t *p = (uint8_t *)addr;
    151  1.1     joerg     pint_t result;
    152  1.1     joerg 
    153  1.1     joerg     if (encoding == DW_EH_PE_omit)
    154  1.1     joerg       return 0;
    155  1.1     joerg     if (encoding == DW_EH_PE_aligned) {
    156  1.1     joerg       addr = (addr + sizeof(pint_t) - 1) & sizeof(pint_t);
    157  1.1     joerg       return getP(addr);
    158  1.1     joerg     }
    159  1.1     joerg 
    160  1.1     joerg     // first get value
    161  1.1     joerg     switch (encoding & 0x0F) {
    162  1.1     joerg     case DW_EH_PE_ptr:
    163  1.1     joerg       result = getP(addr);
    164  1.1     joerg       p += sizeof(pint_t);
    165  1.1     joerg       addr = (pint_t)p;
    166  1.1     joerg       break;
    167  1.1     joerg     case DW_EH_PE_uleb128:
    168  1.1     joerg       result = getULEB128(addr, end);
    169  1.1     joerg       break;
    170  1.1     joerg     case DW_EH_PE_udata2:
    171  1.1     joerg       result = get16(addr);
    172  1.1     joerg       p += 2;
    173  1.1     joerg       addr = (pint_t)p;
    174  1.1     joerg       break;
    175  1.1     joerg     case DW_EH_PE_udata4:
    176  1.1     joerg       result = get32(addr);
    177  1.1     joerg       p += 4;
    178  1.1     joerg       addr = (pint_t)p;
    179  1.1     joerg       break;
    180  1.1     joerg     case DW_EH_PE_udata8:
    181  1.1     joerg       result = get64(addr);
    182  1.1     joerg       p += 8;
    183  1.1     joerg       addr = (pint_t)p;
    184  1.1     joerg       break;
    185  1.1     joerg     case DW_EH_PE_sleb128:
    186  1.1     joerg       result = getSLEB128(addr, end);
    187  1.1     joerg       break;
    188  1.1     joerg     case DW_EH_PE_sdata2:
    189  1.1     joerg       result = (int16_t)get16(addr);
    190  1.1     joerg       p += 2;
    191  1.1     joerg       addr = (pint_t)p;
    192  1.1     joerg       break;
    193  1.1     joerg     case DW_EH_PE_sdata4:
    194  1.1     joerg       result = (int32_t)get32(addr);
    195  1.1     joerg       p += 4;
    196  1.1     joerg       addr = (pint_t)p;
    197  1.1     joerg       break;
    198  1.1     joerg     case DW_EH_PE_sdata8:
    199  1.1     joerg       result = get64(addr);
    200  1.1     joerg       p += 8;
    201  1.1     joerg       addr = (pint_t)p;
    202  1.1     joerg       break;
    203  1.1     joerg     case DW_EH_PE_omit:
    204  1.1     joerg       result = 0;
    205  1.1     joerg       break;
    206  1.1     joerg     default:
    207  1.1     joerg       assert(0 && "unknown pointer encoding");
    208  1.1     joerg     }
    209  1.1     joerg 
    210  1.1     joerg     // then add relative offset
    211  1.1     joerg     switch (encoding & 0x70) {
    212  1.1     joerg     case DW_EH_PE_absptr:
    213  1.1     joerg       // do nothing
    214  1.1     joerg       break;
    215  1.1     joerg     case DW_EH_PE_pcrel:
    216  1.1     joerg       result += startAddr;
    217  1.1     joerg       break;
    218  1.1     joerg     case DW_EH_PE_textrel:
    219  1.1     joerg       assert(0 && "DW_EH_PE_textrel pointer encoding not supported");
    220  1.1     joerg       break;
    221  1.1     joerg     case DW_EH_PE_datarel:
    222  1.1     joerg       assert(ctx != NULL && "DW_EH_PE_datarel without context");
    223  1.1     joerg       if (ctx)
    224  1.1     joerg         result += ctx->data_base;
    225  1.1     joerg       break;
    226  1.1     joerg     case DW_EH_PE_funcrel:
    227  1.1     joerg       assert(ctx != NULL && "DW_EH_PE_funcrel without context");
    228  1.1     joerg       if (ctx)
    229  1.1     joerg         result += ctx->start_ip;
    230  1.1     joerg       break;
    231  1.1     joerg     case DW_EH_PE_aligned:
    232  1.1     joerg       __builtin_unreachable();
    233  1.1     joerg     default:
    234  1.1     joerg       assert(0 && "unknown pointer encoding");
    235  1.1     joerg       break;
    236  1.1     joerg     }
    237  1.1     joerg 
    238  1.1     joerg     if (encoding & DW_EH_PE_indirect)
    239  1.1     joerg       result = getP(result);
    240  1.1     joerg 
    241  1.1     joerg     return result;
    242  1.1     joerg   }
    243  1.1     joerg 
    244  1.1     joerg   bool findFDE(pint_t pc, pint_t &fdeStart, pint_t &data_base) {
    245  1.1     joerg     Range *n;
    246  1.1     joerg     for (;;) {
    247  1.1     joerg       pthread_rwlock_rdlock(&fdeTreeLock);
    248  1.1     joerg       n = (Range *)rb_tree_find_node(&segmentTree, &pc);
    249  1.1     joerg       pthread_rwlock_unlock(&fdeTreeLock);
    250  1.1     joerg       if (n != NULL)
    251  1.1     joerg         break;
    252  1.1     joerg       if (!needsReload)
    253  1.1     joerg         break;
    254  1.1     joerg       lazyReload();
    255  1.1     joerg     }
    256  1.1     joerg     if (n == NULL)
    257  1.1     joerg       return false;
    258  1.1     joerg     if (n->hdr_start == 0) {
    259  1.1     joerg       fdeStart = n->hdr_base;
    260  1.3     joerg       data_base = n->data_base;
    261  1.1     joerg       return true;
    262  1.1     joerg     }
    263  1.1     joerg 
    264  1.1     joerg     pint_t base = n->hdr_base;
    265  1.1     joerg     pint_t first = n->hdr_start;
    266  1.8     joerg     for (pint_t len = n->hdr_entries; len > 1; ) {
    267  1.8     joerg       pint_t next = first + (len / 2) * 8;
    268  1.1     joerg       pint_t nextPC = base + (int32_t)get32(next);
    269  1.1     joerg       if (nextPC == pc) {
    270  1.1     joerg         first = next;
    271  1.1     joerg         break;
    272  1.1     joerg       }
    273  1.1     joerg       if (nextPC < pc) {
    274  1.1     joerg         first = next;
    275  1.8     joerg         len -= (len / 2);
    276  1.8     joerg       } else {
    277  1.8     joerg         len /= 2;
    278  1.8     joerg       }
    279  1.1     joerg     }
    280  1.1     joerg     fdeStart = base + (int32_t)get32(first + 4);
    281  1.3     joerg     data_base = n->data_base;
    282  1.1     joerg     return true;
    283  1.1     joerg   }
    284  1.1     joerg 
    285  1.1     joerg   bool addFDE(pint_t pcStart, pint_t pcEnd, pint_t fde) {
    286  1.1     joerg     pthread_rwlock_wrlock(&fdeTreeLock);
    287  1.1     joerg     Range *n = (Range *)malloc(sizeof(*n));
    288  1.1     joerg     n->hdr_base = fde;
    289  1.1     joerg     n->hdr_start = 0;
    290  1.1     joerg     n->hdr_entries = 0;
    291  1.1     joerg     n->first_pc = pcStart;
    292  1.1     joerg     n->last_pc = pcEnd;
    293  1.1     joerg     n->data_base = 0;
    294  1.1     joerg     n->ehframe_base = 0;
    295  1.6     joerg     if (static_cast<Range *>(rb_tree_insert_node(&segmentTree, n)) == n) {
    296  1.1     joerg       pthread_rwlock_unlock(&fdeTreeLock);
    297  1.1     joerg       return true;
    298  1.1     joerg     }
    299  1.1     joerg     free(n);
    300  1.1     joerg     pthread_rwlock_unlock(&fdeTreeLock);
    301  1.1     joerg     return false;
    302  1.1     joerg   }
    303  1.1     joerg 
    304  1.1     joerg   bool removeFDE(pint_t pcStart, pint_t pcEnd, pint_t fde) {
    305  1.1     joerg     pthread_rwlock_wrlock(&fdeTreeLock);
    306  1.6     joerg     Range *n = static_cast<Range *>(rb_tree_find_node(&segmentTree, &pcStart));
    307  1.1     joerg     if (n == NULL) {
    308  1.1     joerg       pthread_rwlock_unlock(&fdeTreeLock);
    309  1.1     joerg       return false;
    310  1.1     joerg     }
    311  1.1     joerg     assert(n->first_pc == pcStart);
    312  1.1     joerg     assert(n->last_pc == pcEnd);
    313  1.1     joerg     assert(n->hdr_base == fde);
    314  1.1     joerg     assert(n->hdr_start == 0);
    315  1.1     joerg     assert(n->hdr_entries == 0);
    316  1.1     joerg     assert(n->data_base == 0);
    317  1.1     joerg     assert(n->ehframe_base == 0);
    318  1.1     joerg     rb_tree_remove_node(&segmentTree, n);
    319  1.1     joerg     free(n);
    320  1.1     joerg     pthread_rwlock_unlock(&fdeTreeLock);
    321  1.1     joerg     return true;
    322  1.1     joerg   }
    323  1.1     joerg 
    324  1.1     joerg   void removeDSO(pint_t ehFrameBase) {
    325  1.1     joerg     pthread_rwlock_wrlock(&fdeTreeLock);
    326  1.1     joerg     Range *n;
    327  1.1     joerg     n = (Range *)rb_tree_find_node(&dsoTree, &ehFrameBase);
    328  1.1     joerg     if (n == NULL) {
    329  1.1     joerg       pthread_rwlock_unlock(&fdeTreeLock);
    330  1.1     joerg       return;
    331  1.1     joerg     }
    332  1.1     joerg     rb_tree_remove_node(&dsoTree, n);
    333  1.1     joerg     rb_tree_remove_node(&segmentTree, n);
    334  1.1     joerg     free(n);
    335  1.1     joerg     pthread_rwlock_unlock(&fdeTreeLock);
    336  1.1     joerg   }
    337  1.1     joerg 
    338  1.1     joerg   void setLazyReload() {
    339  1.1     joerg     pthread_rwlock_wrlock(&fdeTreeLock);
    340  1.1     joerg     needsReload = true;
    341  1.1     joerg     pthread_rwlock_unlock(&fdeTreeLock);
    342  1.1     joerg   }
    343  1.1     joerg 
    344  1.1     joerg private:
    345  1.1     joerg   findPCRange_t findPCRange;
    346  1.1     joerg   bool needsReload;
    347  1.1     joerg   pthread_rwlock_t fdeTreeLock;
    348  1.1     joerg   rb_tree_t segmentTree;
    349  1.1     joerg   rb_tree_t dsoTree;
    350  1.1     joerg 
    351  1.1     joerg   friend int phdr_callback(struct dl_phdr_info *, size_t, void *);
    352  1.1     joerg   friend int rangeCmp(void *, const void *, const void *);
    353  1.1     joerg   friend int rangeCmpKey(void *, const void *, const void *);
    354  1.1     joerg   friend int dsoTableCmp(void *, const void *, const void *);
    355  1.1     joerg   friend int dsoTableCmpKey(void *, const void *, const void *);
    356  1.1     joerg 
    357  1.1     joerg   void updateRange();
    358  1.1     joerg 
    359  1.1     joerg   struct Range {
    360  1.1     joerg     rb_node_t range_link;
    361  1.1     joerg     rb_node_t dso_link;
    362  1.1     joerg     pint_t hdr_base; // Pointer to FDE if hdr_start == 0
    363  1.1     joerg     pint_t hdr_start;
    364  1.1     joerg     pint_t hdr_entries;
    365  1.1     joerg     pint_t first_pc;
    366  1.1     joerg     pint_t last_pc;
    367  1.1     joerg     pint_t data_base;
    368  1.1     joerg     pint_t ehframe_base;
    369  1.1     joerg   };
    370  1.1     joerg 
    371  1.1     joerg   void lazyReload() {
    372  1.1     joerg     pthread_rwlock_wrlock(&fdeTreeLock);
    373  1.1     joerg     dl_iterate_phdr(phdr_callback, this);
    374  1.1     joerg     needsReload = false;
    375  1.1     joerg     pthread_rwlock_unlock(&fdeTreeLock);
    376  1.1     joerg   }
    377  1.1     joerg 
    378  1.1     joerg   void addDSO(pint_t header, pint_t data_base) {
    379  1.1     joerg     if (header == 0)
    380  1.1     joerg       return;
    381  1.1     joerg     if (get8(header) != 1)
    382  1.1     joerg       return;
    383  1.1     joerg     if (get8(header + 3) != (DW_EH_PE_datarel | DW_EH_PE_sdata4))
    384  1.1     joerg       return;
    385  1.1     joerg     pint_t end = header + 4;
    386  1.1     joerg     pint_t ehframe_base = getEncodedP(end, 0, get8(header + 1), NULL);
    387  1.1     joerg     pint_t entries = getEncodedP(end, 0, get8(header + 2), NULL);
    388  1.1     joerg     pint_t start = (end + 3) & ~pint_t(3);
    389  1.1     joerg     if (entries == 0)
    390  1.1     joerg       return;
    391  1.1     joerg     Range *n = (Range *)malloc(sizeof(*n));
    392  1.1     joerg     n->hdr_base = header;
    393  1.1     joerg     n->hdr_start = start;
    394  1.1     joerg     n->hdr_entries = entries;
    395  1.1     joerg     n->first_pc = header + (int32_t)get32(n->hdr_start);
    396  1.1     joerg     pint_t tmp;
    397  1.1     joerg     (*findPCRange)(
    398  1.1     joerg         *this, header + (int32_t)get32(n->hdr_start + (entries - 1) * 8 + 4),
    399  1.1     joerg         tmp, n->last_pc);
    400  1.1     joerg     n->data_base = data_base;
    401  1.1     joerg     n->ehframe_base = ehframe_base;
    402  1.1     joerg 
    403  1.7     joerg     if (static_cast<Range *>(rb_tree_insert_node(&segmentTree, n)) != n) {
    404  1.1     joerg       free(n);
    405  1.1     joerg       return;
    406  1.1     joerg     }
    407  1.1     joerg     rb_tree_insert_node(&dsoTree, n);
    408  1.1     joerg   }
    409  1.1     joerg };
    410  1.1     joerg 
    411  1.1     joerg static int phdr_callback(struct dl_phdr_info *info, size_t size, void *data_) {
    412  1.1     joerg   LocalAddressSpace *data = (LocalAddressSpace *)data_;
    413  1.1     joerg   size_t eh_frame = 0, data_base = 0;
    414  1.1     joerg   const Elf_Phdr *hdr = info->dlpi_phdr;
    415  1.1     joerg   const Elf_Phdr *last_hdr = hdr + info->dlpi_phnum;
    416  1.1     joerg   const Elf_Dyn *dyn;
    417  1.1     joerg 
    418  1.1     joerg   for (; hdr != last_hdr; ++hdr) {
    419  1.1     joerg     switch (hdr->p_type) {
    420  1.1     joerg     case PT_GNU_EH_FRAME:
    421  1.1     joerg       eh_frame = info->dlpi_addr + hdr->p_vaddr;
    422  1.1     joerg       break;
    423  1.1     joerg     case PT_DYNAMIC:
    424  1.1     joerg       dyn = (const Elf_Dyn *)(info->dlpi_addr + hdr->p_vaddr);
    425  1.1     joerg       while (dyn->d_tag != DT_NULL) {
    426  1.1     joerg         if (dyn->d_tag == DT_PLTGOT) {
    427  1.1     joerg           data_base = info->dlpi_addr + dyn->d_un.d_ptr;
    428  1.1     joerg           break;
    429  1.1     joerg         }
    430  1.1     joerg         ++dyn;
    431  1.1     joerg       }
    432  1.1     joerg     }
    433  1.1     joerg   }
    434  1.1     joerg 
    435  1.1     joerg   if (eh_frame)
    436  1.1     joerg     data->addDSO(eh_frame, data_base);
    437  1.1     joerg 
    438  1.1     joerg   return 0;
    439  1.1     joerg }
    440  1.1     joerg 
    441  1.1     joerg static int rangeCmp(void *context, const void *n1_, const void *n2_) {
    442  1.2     joerg   const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_;
    443  1.2     joerg   const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_;
    444  1.1     joerg 
    445  1.1     joerg   if (n1->first_pc < n2->first_pc)
    446  1.1     joerg     return -1;
    447  1.1     joerg   if (n1->first_pc > n2->first_pc)
    448  1.1     joerg     return 1;
    449  1.1     joerg   assert(n1->last_pc == n2->last_pc);
    450  1.1     joerg   return 0;
    451  1.1     joerg }
    452  1.1     joerg 
    453  1.1     joerg static int rangeCmpKey(void *context, const void *n_, const void *pc_) {
    454  1.2     joerg   const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_;
    455  1.2     joerg   const LocalAddressSpace::pint_t *pc = (const LocalAddressSpace::pint_t *)pc_;
    456  1.1     joerg   if (n->last_pc < *pc)
    457  1.1     joerg     return -1;
    458  1.1     joerg   if (n->first_pc > *pc)
    459  1.1     joerg     return 1;
    460  1.1     joerg   return 0;
    461  1.1     joerg }
    462  1.1     joerg 
    463  1.1     joerg static int dsoTableCmp(void *context, const void *n1_, const void *n2_) {
    464  1.2     joerg   const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_;
    465  1.2     joerg   const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_;
    466  1.1     joerg 
    467  1.1     joerg   if (n1->ehframe_base < n2->ehframe_base)
    468  1.1     joerg     return -1;
    469  1.1     joerg   if (n1->ehframe_base > n2->ehframe_base)
    470  1.1     joerg     return 1;
    471  1.1     joerg   return 0;
    472  1.1     joerg }
    473  1.1     joerg 
    474  1.1     joerg static int dsoTableCmpKey(void *context, const void *n_, const void *ptr_) {
    475  1.2     joerg   const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_;
    476  1.2     joerg   const LocalAddressSpace::pint_t *ptr = (const LocalAddressSpace::pint_t *)ptr_;
    477  1.1     joerg   if (n->ehframe_base < *ptr)
    478  1.1     joerg     return -1;
    479  1.1     joerg   if (n->ehframe_base > *ptr)
    480  1.1     joerg     return 1;
    481  1.1     joerg   return 0;
    482  1.1     joerg }
    483  1.1     joerg 
    484  1.1     joerg } // namespace _Unwind
    485  1.1     joerg 
    486  1.1     joerg #endif // __ADDRESSSPACE_HPP__
    487