1 /* $NetBSD: libdwarf_arange.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2009-2011 Kai Wang 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include "_libdwarf.h" 30 31 __RCSID("$NetBSD: libdwarf_arange.c,v 1.2 2014/03/09 16:58:04 christos Exp $"); 32 ELFTC_VCSID("Id: libdwarf_arange.c 2070 2011-10-27 03:05:32Z jkoshy "); 33 34 void 35 _dwarf_arange_cleanup(Dwarf_Debug dbg) 36 { 37 Dwarf_ArangeSet as, tas; 38 Dwarf_Arange ar, tar; 39 40 STAILQ_FOREACH_SAFE(as, &dbg->dbg_aslist, as_next, tas) { 41 STAILQ_FOREACH_SAFE(ar, &as->as_arlist, ar_next, tar) { 42 STAILQ_REMOVE(&as->as_arlist, ar, _Dwarf_Arange, 43 ar_next); 44 free(ar); 45 } 46 STAILQ_REMOVE(&dbg->dbg_aslist, as, _Dwarf_ArangeSet, as_next); 47 free(as); 48 } 49 50 if (dbg->dbg_arange_array) 51 free(dbg->dbg_arange_array); 52 53 dbg->dbg_arange_array = NULL; 54 dbg->dbg_arange_cnt = 0; 55 } 56 57 int 58 _dwarf_arange_init(Dwarf_Debug dbg, Dwarf_Error *error) 59 { 60 Dwarf_CU cu; 61 Dwarf_ArangeSet as; 62 Dwarf_Arange ar; 63 Dwarf_Section *ds; 64 uint64_t offset, dwarf_size, length, addr, range; 65 int i, ret; 66 67 ret = DW_DLE_NONE; 68 69 if ((ds = _dwarf_find_section(dbg, ".debug_aranges")) == NULL) 70 return (DW_DLE_NONE); 71 72 if (!dbg->dbg_info_loaded) { 73 ret = _dwarf_info_load(dbg, 1, error); 74 if (ret != DW_DLE_NONE) 75 return (ret); 76 } 77 78 offset = 0; 79 while (offset < ds->ds_size) { 80 81 if ((as = malloc(sizeof(struct _Dwarf_ArangeSet))) == NULL) { 82 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 83 return (DW_DLE_MEMORY); 84 } 85 STAILQ_INIT(&as->as_arlist); 86 STAILQ_INSERT_TAIL(&dbg->dbg_aslist, as, as_next); 87 88 /* Read in the table header. */ 89 length = dbg->read(ds->ds_data, &offset, 4); 90 if (length == 0xffffffff) { 91 dwarf_size = 8; 92 length = dbg->read(ds->ds_data, &offset, 8); 93 } else 94 dwarf_size = 4; 95 96 as->as_length = length; 97 as->as_version = dbg->read(ds->ds_data, &offset, 2); 98 if (as->as_version != 2) { 99 DWARF_SET_ERROR(dbg, error, DW_DLE_VERSION_STAMP_ERROR); 100 ret = DW_DLE_VERSION_STAMP_ERROR; 101 goto fail_cleanup; 102 } 103 104 as->as_cu_offset = dbg->read(ds->ds_data, &offset, dwarf_size); 105 STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) { 106 if (cu->cu_offset == as->as_cu_offset) 107 break; 108 } 109 if (cu == NULL) { 110 DWARF_SET_ERROR(dbg, error, DW_DLE_ARANGE_OFFSET_BAD); 111 ret = DW_DLE_ARANGE_OFFSET_BAD; 112 goto fail_cleanup; 113 } 114 as->as_cu = cu; 115 116 as->as_addrsz = dbg->read(ds->ds_data, &offset, 1); 117 as->as_segsz = dbg->read(ds->ds_data, &offset, 1); 118 119 /* Skip the padding bytes. */ 120 offset = roundup(offset, 2 * as->as_addrsz); 121 122 /* Read in address range descriptors. */ 123 while (offset < ds->ds_size) { 124 addr = dbg->read(ds->ds_data, &offset, as->as_addrsz); 125 range = dbg->read(ds->ds_data, &offset, as->as_addrsz); 126 if (addr == 0 && range == 0) 127 break; 128 if ((ar = calloc(1, sizeof(struct _Dwarf_Arange))) == 129 NULL) { 130 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 131 goto fail_cleanup; 132 } 133 ar->ar_as = as; 134 ar->ar_address = addr; 135 ar->ar_range = range; 136 STAILQ_INSERT_TAIL(&as->as_arlist, ar, ar_next); 137 dbg->dbg_arange_cnt++; 138 } 139 } 140 141 /* Build arange array. */ 142 if (dbg->dbg_arange_cnt > 0) { 143 if ((dbg->dbg_arange_array = malloc(dbg->dbg_arange_cnt * 144 sizeof(struct _Dwarf_Arange))) == NULL) { 145 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 146 ret = DW_DLE_MEMORY; 147 goto fail_cleanup; 148 } 149 150 i = 0; 151 STAILQ_FOREACH(as, &dbg->dbg_aslist, as_next) { 152 STAILQ_FOREACH(ar, &as->as_arlist, ar_next) 153 dbg->dbg_arange_array[i++] = ar; 154 } 155 assert((Dwarf_Unsigned)i == dbg->dbg_arange_cnt); 156 } 157 158 return (DW_DLE_NONE); 159 160 fail_cleanup: 161 162 _dwarf_arange_cleanup(dbg); 163 164 return (ret); 165 } 166 167 int 168 _dwarf_arange_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) 169 { 170 Dwarf_P_Section ds; 171 Dwarf_Rel_Section drs; 172 Dwarf_ArangeSet as; 173 Dwarf_Arange ar; 174 uint64_t offset; 175 int ret; 176 177 as = dbg->dbgp_as; 178 assert(as != NULL); 179 if (STAILQ_EMPTY(&as->as_arlist)) 180 return (DW_DLE_NONE); 181 182 as->as_length = 0; 183 as->as_version = 2; 184 as->as_cu_offset = 0; /* We have only one CU. */ 185 as->as_addrsz = dbg->dbg_pointer_size; 186 as->as_segsz = 0; /* XXX */ 187 188 /* Create .debug_arange section. */ 189 if ((ret = _dwarf_section_init(dbg, &ds, ".debug_aranges", 0, error)) != 190 DW_DLE_NONE) 191 goto gen_fail0; 192 193 /* Create relocation section for .debug_aranges */ 194 RCHECK(_dwarf_reloc_section_init(dbg, &drs, ds, error)); 195 196 /* Write section header. */ 197 RCHECK(WRITE_VALUE(as->as_length, 4)); 198 RCHECK(WRITE_VALUE(as->as_version, 2)); 199 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, 4, 200 ds->ds_size, 0, as->as_cu_offset, ".debug_info", error)); 201 RCHECK(WRITE_VALUE(as->as_addrsz, 1)); 202 RCHECK(WRITE_VALUE(as->as_segsz, 1)); 203 204 /* Pad to (2 * address_size) */ 205 offset = roundup(ds->ds_size, 2 * as->as_addrsz); 206 if (offset > ds->ds_size) 207 RCHECK(WRITE_PADDING(0, offset - ds->ds_size)); 208 209 /* Write tuples. */ 210 STAILQ_FOREACH(ar, &as->as_arlist, ar_next) { 211 RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, 212 dwarf_drt_data_reloc, dbg->dbg_pointer_size, ds->ds_size, 213 ar->ar_symndx, ar->ar_address, NULL, error)); 214 if (ar->ar_esymndx > 0) 215 RCHECK(_dwarf_reloc_entry_add_pair(dbg, drs, ds, 216 dbg->dbg_pointer_size, ds->ds_size, ar->ar_symndx, 217 ar->ar_esymndx, ar->ar_address, ar->ar_eoff, error)); 218 else 219 RCHECK(WRITE_VALUE(ar->ar_range, dbg->dbg_pointer_size)); 220 } 221 RCHECK(WRITE_VALUE(0, dbg->dbg_pointer_size)); 222 RCHECK(WRITE_VALUE(0, dbg->dbg_pointer_size)); 223 224 /* Fill in the length field. */ 225 as->as_length = ds->ds_size - 4; 226 offset = 0; 227 dbg->write(ds->ds_data, &offset, as->as_length, 4); 228 229 /* Inform application the creation of .debug_aranges ELF section. */ 230 RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); 231 232 /* Finalize relocation section for .debug_aranges */ 233 RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); 234 235 return (DW_DLE_NONE); 236 237 gen_fail: 238 _dwarf_reloc_section_free(dbg, &drs); 239 240 gen_fail0: 241 _dwarf_section_free(dbg, &ds); 242 243 return (ret); 244 } 245 246 void 247 _dwarf_arange_pro_cleanup(Dwarf_P_Debug dbg) 248 { 249 Dwarf_ArangeSet as; 250 Dwarf_Arange ar, tar; 251 252 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 253 if (dbg->dbgp_as == NULL) 254 return; 255 256 as = dbg->dbgp_as; 257 STAILQ_FOREACH_SAFE(ar, &as->as_arlist, ar_next, tar) { 258 STAILQ_REMOVE(&as->as_arlist, ar, _Dwarf_Arange, ar_next); 259 free(ar); 260 } 261 free(as); 262 dbg->dbgp_as = NULL; 263 } 264