1 /* $NetBSD: libdwarf_sections.c,v 1.3 2016/02/20 02:43:42 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2010 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_sections.c,v 1.3 2016/02/20 02:43:42 christos Exp $"); 32 ELFTC_VCSID("Id: libdwarf_sections.c 3041 2014-05-18 15:11:03Z kaiwang27 "); 33 34 #define _SECTION_INIT_SIZE 128 35 36 int 37 _dwarf_section_init(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp, const char *name, 38 int pseudo, Dwarf_Error *error) 39 { 40 Dwarf_P_Section ds; 41 42 assert(dbg != NULL && dsp != NULL && name != NULL); 43 44 if ((ds = calloc(1, sizeof(struct _Dwarf_P_Section))) == NULL) { 45 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 46 return (DW_DLE_MEMORY); 47 } 48 49 if ((ds->ds_name = strdup(name)) == NULL) { 50 free(ds); 51 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 52 return (DW_DLE_MEMORY); 53 } 54 55 if (!pseudo) { 56 ds->ds_cap = _SECTION_INIT_SIZE; 57 if ((ds->ds_data = malloc((size_t) ds->ds_cap)) == NULL) { 58 free(ds->ds_name); 59 free(ds); 60 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 61 return (DW_DLE_MEMORY); 62 } 63 STAILQ_INSERT_TAIL(&dbg->dbgp_seclist, ds, ds_next); 64 dbg->dbgp_seccnt++; 65 } 66 67 *dsp = ds; 68 69 return (DW_DLE_NONE); 70 } 71 72 void 73 _dwarf_section_free(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp) 74 { 75 Dwarf_P_Section ds, tds; 76 77 assert(dbg != NULL && dsp != NULL); 78 79 if (*dsp == NULL) 80 return; 81 82 STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) { 83 if (ds == *dsp) { 84 STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section, 85 ds_next); 86 dbg->dbgp_seccnt--; 87 break; 88 } 89 } 90 ds = *dsp; 91 if (ds->ds_name) 92 free(ds->ds_name); 93 if (ds->ds_data) 94 free(ds->ds_data); 95 free(ds); 96 *dsp = NULL; 97 } 98 99 int 100 _dwarf_pro_callback(Dwarf_P_Debug dbg, char *name, int size, 101 Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link, 102 Dwarf_Unsigned info, Dwarf_Unsigned *symndx, int *error) 103 { 104 int e, ret, isymndx; 105 106 assert(dbg != NULL && name != NULL && symndx != NULL); 107 108 if (dbg->dbgp_func_b) 109 ret = dbg->dbgp_func_b(name, size, type, flags, link, info, 110 symndx, &e); 111 else { 112 ret = dbg->dbgp_func(name, size, type, flags, link, info, 113 &isymndx, &e); 114 *symndx = isymndx; 115 } 116 if (ret < 0) { 117 if (error) 118 *error = e; 119 } 120 121 return (ret); 122 } 123 124 int 125 _dwarf_section_callback(Dwarf_P_Debug dbg, Dwarf_P_Section ds, 126 Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link, 127 Dwarf_Unsigned info, Dwarf_Error *error) 128 { 129 int ret, ndx; 130 131 ndx = _dwarf_pro_callback(dbg, ds->ds_name, (int) ds->ds_size, 132 type, flags, link, info, &ds->ds_symndx, NULL); 133 if (ndx < 0) { 134 ret = DW_DLE_ELF_SECT_ERR; 135 DWARF_SET_ERROR(dbg, error, ret); 136 return (ret); 137 } 138 ds->ds_ndx = ndx; 139 140 return (DW_DLE_NONE); 141 } 142 143 int 144 _dwarf_generate_sections(Dwarf_P_Debug dbg, Dwarf_Error *error) 145 { 146 int ret; 147 148 /* Produce .debug_info section. */ 149 if ((ret = _dwarf_info_gen(dbg, error)) != DW_DLE_NONE) 150 return (ret); 151 152 /* Produce .debug_abbrev section. */ 153 if ((ret = _dwarf_abbrev_gen(dbg, error)) != DW_DLE_NONE) 154 return (ret); 155 156 /* Produce .debug_line section. */ 157 if ((ret = _dwarf_lineno_gen(dbg, error)) != DW_DLE_NONE) 158 return (ret); 159 160 /* Produce .debug_frame section. */ 161 if ((ret = _dwarf_frame_gen(dbg, error)) != DW_DLE_NONE) 162 return (ret); 163 164 /* Produce .debug_aranges section. */ 165 if ((ret = _dwarf_arange_gen(dbg, error)) != DW_DLE_NONE) 166 return (ret); 167 168 /* Produce .debug_macinfo section. */ 169 if ((ret = _dwarf_macinfo_gen(dbg, error)) != DW_DLE_NONE) 170 return (ret); 171 172 /* Produce .debug_pubnames section. */ 173 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_pubnames", dbg->dbgp_pubs, 174 error)) != DW_DLE_NONE) 175 return (ret); 176 177 /* Produce .debug_weaknames section. */ 178 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_weaknames", dbg->dbgp_weaks, 179 error)) != DW_DLE_NONE) 180 return (ret); 181 182 /* Produce .debug_funcnames section. */ 183 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_funcnames", dbg->dbgp_funcs, 184 error)) != DW_DLE_NONE) 185 return (ret); 186 187 /* Produce .debug_typenames section. */ 188 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_typenames", dbg->dbgp_types, 189 error)) != DW_DLE_NONE) 190 return (ret); 191 192 /* Produce .debug_varnames section. */ 193 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_varnames", dbg->dbgp_vars, 194 error)) != DW_DLE_NONE) 195 return (ret); 196 197 /* Produce .debug_str section. */ 198 if ((ret = _dwarf_strtab_gen(dbg, error)) != DW_DLE_NONE) 199 return (ret); 200 201 /* Finally, update and generate all relocation sections. */ 202 if ((ret = _dwarf_reloc_gen(dbg, error)) != DW_DLE_NONE) 203 return (ret); 204 205 /* Set section/relocation iterator to the first element. */ 206 dbg->dbgp_secpos = STAILQ_FIRST(&dbg->dbgp_seclist); 207 dbg->dbgp_drspos = STAILQ_FIRST(&dbg->dbgp_drslist); 208 209 return (DW_DLE_NONE); 210 } 211 212 Dwarf_Section * 213 _dwarf_find_section(Dwarf_Debug dbg, const char *name) 214 { 215 Dwarf_Section *ds; 216 Dwarf_Half i; 217 218 assert(dbg != NULL && name != NULL); 219 220 for (i = 0; i < dbg->dbg_seccnt; i++) { 221 ds = &dbg->dbg_section[i]; 222 if (ds->ds_name != NULL && !strcmp(ds->ds_name, name)) 223 return (ds); 224 } 225 226 return (NULL); 227 } 228 229 Dwarf_Section * 230 _dwarf_find_next_types_section(Dwarf_Debug dbg, Dwarf_Section *ds) 231 { 232 233 assert(dbg != NULL); 234 235 if (ds == NULL) 236 return (_dwarf_find_section(dbg, ".debug_types")); 237 238 assert(ds->ds_name != NULL); 239 240 do { 241 ds++; 242 if (ds->ds_name != NULL && 243 !strcmp(ds->ds_name, ".debug_types")) 244 return (ds); 245 } while (ds->ds_name != NULL); 246 247 return (NULL); 248 } 249 250 Dwarf_P_Section 251 _dwarf_pro_find_section(Dwarf_P_Debug dbg, const char *name) 252 { 253 Dwarf_P_Section ds; 254 255 assert(dbg != NULL && name != NULL); 256 257 STAILQ_FOREACH(ds, &dbg->dbgp_seclist, ds_next) { 258 if (ds->ds_name != NULL && !strcmp(ds->ds_name ,name)) 259 return (ds); 260 } 261 262 return (NULL); 263 } 264 265 void 266 _dwarf_section_cleanup(Dwarf_P_Debug dbg) 267 { 268 Dwarf_P_Section ds, tds; 269 270 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 271 272 STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) { 273 STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section, 274 ds_next); 275 if (ds->ds_name) 276 free(ds->ds_name); 277 if (ds->ds_data) 278 free(ds->ds_data); 279 free(ds); 280 } 281 dbg->dbgp_seccnt = 0; 282 dbg->dbgp_secpos = 0; 283 } 284