1 /* Return list address ranges. 2 Copyright (C) 2000, 2001, 2002, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) redhat.com>, 2000. 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 <stdlib.h> 20 21 #include <libdwP.h> 22 23 24 struct arangelist 25 { 26 Dwarf_Arange arange; 27 struct arangelist *next; 28 }; 29 30 31 int 32 dwarf_getaranges (dbg, aranges, naranges) 33 Dwarf *dbg; 34 Dwarf_Aranges **aranges; 35 size_t *naranges; 36 { 37 if (dbg == NULL) 38 return -1; 39 40 if (dbg->aranges != NULL) 41 { 42 *aranges = dbg->aranges; 43 if (naranges != NULL) 44 *naranges = dbg->aranges->naranges; 45 return 0; 46 } 47 48 if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL) 49 return -1; 50 51 struct arangelist *arangelist = NULL; 52 unsigned int narangelist = 0; 53 54 const char *readp 55 = (const char *) dbg->sectiondata[IDX_debug_aranges]->d_buf; 56 const char *readendp = readp + dbg->sectiondata[IDX_debug_aranges]->d_size; 57 58 while (readp < readendp) 59 { 60 const char *hdrstart = readp; 61 62 /* Each entry starts with a header: 63 64 1. A 4-byte or 12-byte length containing the length of the 65 set of entries for this compilation unit, not including the 66 length field itself. [...] 67 68 2. A 2-byte version identifier containing the value 2 for 69 DWARF Version 2.1. 70 71 3. A 4-byte or 8-byte offset into the .debug_info section. [...] 72 73 4. A 1-byte unsigned integer containing the size in bytes of 74 an address (or the offset portion of an address for segmented 75 addressing) on the target system. 76 77 5. A 1-byte unsigned integer containing the size in bytes of 78 a segment descriptor on the target system. */ 79 Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp); 80 unsigned int length_bytes = 4; 81 if (length == 0xffffffff) 82 { 83 length = read_8ubyte_unaligned_inc (dbg, readp); 84 length_bytes = 8; 85 } 86 87 unsigned int version = read_2ubyte_unaligned_inc (dbg, readp); 88 if (version != 2) 89 { 90 invalid: 91 __libdw_seterrno (DWARF_E_INVALID_DWARF); 92 return -1; 93 } 94 95 Dwarf_Word offset; 96 if (length_bytes == 4) 97 offset = read_4ubyte_unaligned_inc (dbg, readp); 98 else 99 offset = read_8ubyte_unaligned_inc (dbg, readp); 100 101 unsigned int address_size = *readp++; 102 if (address_size != 4 && address_size != 8) 103 goto invalid; 104 105 /* Ignore the segment size value. */ 106 // XXX Really? 107 (void) *readp++; 108 109 /* Round the address to the next multiple of 2*address_size. */ 110 readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size))) 111 % (2 * address_size)); 112 113 //arange_info->offset = offset; 114 115 while (1) 116 { 117 Dwarf_Word range_address; 118 Dwarf_Word range_length; 119 120 if (address_size == 4) 121 { 122 range_address = read_4ubyte_unaligned_inc (dbg, readp); 123 range_length = read_4ubyte_unaligned_inc (dbg, readp); 124 } 125 else 126 { 127 range_address = read_8ubyte_unaligned_inc (dbg, readp); 128 range_length = read_8ubyte_unaligned_inc (dbg, readp); 129 } 130 131 /* Two zero values mark the end. */ 132 if (range_address == 0 && range_length == 0) 133 break; 134 135 struct arangelist *new_arange = 136 (struct arangelist *) alloca (sizeof (struct arangelist)); 137 138 new_arange->arange.addr = range_address; 139 new_arange->arange.length = range_length; 140 141 /* We store the actual CU DIE offset, not the CU header offset. */ 142 const char *cu_header = (dbg->sectiondata[IDX_debug_info]->d_buf 143 + offset); 144 unsigned int offset_size; 145 if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff) 146 offset_size = 8; 147 else 148 offset_size = 4; 149 new_arange->arange.offset = offset + 3 * offset_size - 4 + 3; 150 151 new_arange->next = arangelist; 152 arangelist = new_arange; 153 ++narangelist; 154 } 155 } 156 157 if (narangelist == 0) 158 { 159 if (naranges != NULL) 160 *naranges = 0; 161 *aranges = NULL; 162 return 0; 163 } 164 165 /* Allocate the array for the result. */ 166 if (naranges != NULL) 167 *naranges = narangelist; 168 *aranges = libdw_alloc (dbg, Dwarf_Aranges, 169 sizeof (Dwarf_Aranges) 170 + narangelist * sizeof (Dwarf_Arange), 1); 171 172 (*aranges)->dbg = dbg; 173 (*aranges)->naranges = narangelist; 174 175 while (narangelist-- > 0) 176 { 177 (*aranges)->info[narangelist] = arangelist->arange; 178 arangelist = arangelist->next; 179 } 180 181 dbg->aranges = *aranges; 182 183 return 0; 184 } 185