1 /* Find CU for given offset. 2 Copyright (C) 2003, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 2003. 4 5 This program is Open Source software; you can redistribute it and/or 6 modify it under the terms of the Open Software License version 1.0 as 7 published by the Open Source Initiative. 8 9 You should have received a copy of the Open Software License along 10 with this program; if not, you may obtain a copy of the Open Software 11 License version 1.0 from http://www.opensource.org/licenses/osl.php or 12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 13 3001 King Ranch Road, Ukiah, CA 95482. */ 14 15 #ifdef HAVE_CONFIG_H 16 # include <config.h> 17 #endif 18 19 #include <assert.h> 20 #include <search.h> 21 #include "libdwP.h" 22 23 24 static int 25 findcu_cb (const void *arg1, const void *arg2) 26 { 27 struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1; 28 struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2; 29 30 /* Find out which of the two arguments is the search value. It has 31 end offset 0. */ 32 if (cu1->end == 0) 33 { 34 if (cu1->start < cu2->start) 35 return -1; 36 if (cu1->start >= cu2->end) 37 return 1; 38 } 39 else 40 { 41 if (cu2->start < cu1->start) 42 return 1; 43 if (cu2->start >= cu1->end) 44 return -1; 45 } 46 47 return 0; 48 } 49 50 51 struct Dwarf_CU * 52 __libdw_findcu (dbg, start) 53 Dwarf *dbg; 54 Dwarf_Off start; 55 { 56 /* Maybe we already know that CU. */ 57 struct Dwarf_CU fake = { .start = start, .end = 0 }; 58 struct Dwarf_CU **found = tfind (&fake, &dbg->cu_tree, findcu_cb); 59 if (found != NULL) 60 return *found; 61 62 if (start < dbg->next_cu_offset) 63 { 64 __libdw_seterrno (DWARF_E_INVALID_DWARF); 65 return NULL; 66 } 67 68 /* No. Then read more CUs. */ 69 while (1) 70 { 71 Dwarf_Off oldoff = dbg->next_cu_offset; 72 uint8_t address_size; 73 uint8_t offset_size; 74 Dwarf_Off abbrev_offset; 75 76 if (dwarf_nextcu (dbg, oldoff, &dbg->next_cu_offset, NULL, 77 &abbrev_offset, &address_size, &offset_size) != 0) 78 /* No more entries. */ 79 return NULL; 80 81 /* Create an entry for this CU. */ 82 struct Dwarf_CU *newp = libdw_typed_alloc (dbg, struct Dwarf_CU); 83 84 newp->dbg = dbg; 85 newp->start = oldoff; 86 newp->end = dbg->next_cu_offset; 87 newp->address_size = address_size; 88 newp->offset_size = offset_size; 89 Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41); 90 newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset; 91 newp->lines = NULL; 92 newp->locs = NULL; 93 94 /* Add the new entry to the search tree. */ 95 if (tsearch (newp, &dbg->cu_tree, findcu_cb) == NULL) 96 { 97 /* Something went wrong. Unfo the operation. */ 98 dbg->next_cu_offset = oldoff; 99 __libdw_seterrno (DWARF_E_NOMEM); 100 return NULL; 101 } 102 103 /* Is this the one we are looking for? */ 104 if (start < dbg->next_cu_offset) 105 // XXX Match exact offset. 106 return newp; 107 } 108 /* NOTREACHED */ 109 } 110