1 /*- 2 * Copyright (c) 2010 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include "_libdwarf.h" 28 29 ELFTC_VCSID("$Id: libdwarf_sections.c 2379 2012-01-05 02:08:20Z jkoshy $"); 30 31 #define _SECTION_INIT_SIZE 128 32 33 int 34 _dwarf_section_init(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp, const char *name, 35 int pseudo, Dwarf_Error *error) 36 { 37 Dwarf_P_Section ds; 38 39 assert(dbg != NULL && dsp != NULL && name != NULL); 40 41 if ((ds = calloc(1, sizeof(struct _Dwarf_P_Section))) == NULL) { 42 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 43 return (DW_DLE_MEMORY); 44 } 45 46 if ((ds->ds_name = strdup(name)) == NULL) { 47 free(ds); 48 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 49 return (DW_DLE_MEMORY); 50 } 51 52 if (!pseudo) { 53 ds->ds_cap = _SECTION_INIT_SIZE; 54 if ((ds->ds_data = malloc((size_t) ds->ds_cap)) == NULL) { 55 free(ds->ds_name); 56 free(ds); 57 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 58 return (DW_DLE_MEMORY); 59 } 60 STAILQ_INSERT_TAIL(&dbg->dbgp_seclist, ds, ds_next); 61 dbg->dbgp_seccnt++; 62 } 63 64 *dsp = ds; 65 66 return (DW_DLE_NONE); 67 } 68 69 void 70 _dwarf_section_free(Dwarf_P_Debug dbg, Dwarf_P_Section *dsp) 71 { 72 Dwarf_P_Section ds, tds; 73 74 assert(dbg != NULL && dsp != NULL); 75 76 if (*dsp == NULL) 77 return; 78 79 STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) { 80 if (ds == *dsp) { 81 STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section, 82 ds_next); 83 dbg->dbgp_seccnt--; 84 break; 85 } 86 } 87 ds = *dsp; 88 if (ds->ds_name) 89 free(ds->ds_name); 90 if (ds->ds_data) 91 free(ds->ds_data); 92 free(ds); 93 *dsp = NULL; 94 } 95 96 int 97 _dwarf_pro_callback(Dwarf_P_Debug dbg, char *name, int size, 98 Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link, 99 Dwarf_Unsigned info, Dwarf_Unsigned *symndx, int *error) 100 { 101 int e, ret, isymndx; 102 103 assert(dbg != NULL && name != NULL && symndx != NULL); 104 105 if (dbg->dbgp_func_b) 106 ret = dbg->dbgp_func_b(name, size, type, flags, link, info, 107 symndx, &e); 108 else { 109 ret = dbg->dbgp_func(name, size, type, flags, link, info, 110 &isymndx, &e); 111 *symndx = isymndx; 112 } 113 if (ret < 0) { 114 if (error) 115 *error = e; 116 } 117 118 return (ret); 119 } 120 121 int 122 _dwarf_section_callback(Dwarf_P_Debug dbg, Dwarf_P_Section ds, 123 Dwarf_Unsigned type, Dwarf_Unsigned flags, Dwarf_Unsigned link, 124 Dwarf_Unsigned info, Dwarf_Error *error) 125 { 126 int ret, ndx; 127 128 ndx = _dwarf_pro_callback(dbg, ds->ds_name, (int) ds->ds_size, 129 type, flags, link, info, &ds->ds_symndx, NULL); 130 if (ndx < 0) { 131 ret = DW_DLE_ELF_SECT_ERR; 132 DWARF_SET_ERROR(dbg, error, ret); 133 return (ret); 134 } 135 ds->ds_ndx = ndx; 136 137 return (DW_DLE_NONE); 138 } 139 140 int 141 _dwarf_generate_sections(Dwarf_P_Debug dbg, Dwarf_Error *error) 142 { 143 int ret; 144 145 /* Produce .debug_info section. */ 146 if ((ret = _dwarf_info_gen(dbg, error)) != DW_DLE_NONE) 147 return (ret); 148 149 /* Produce .debug_abbrev section. */ 150 if ((ret = _dwarf_abbrev_gen(dbg, error)) != DW_DLE_NONE) 151 return (ret); 152 153 /* Produce .debug_line section. */ 154 if ((ret = _dwarf_lineno_gen(dbg, error)) != DW_DLE_NONE) 155 return (ret); 156 157 /* Produce .debug_frame section. */ 158 if ((ret = _dwarf_frame_gen(dbg, error)) != DW_DLE_NONE) 159 return (ret); 160 161 /* Produce .debug_aranges section. */ 162 if ((ret = _dwarf_arange_gen(dbg, error)) != DW_DLE_NONE) 163 return (ret); 164 165 /* Produce .debug_macinfo section. */ 166 if ((ret = _dwarf_macinfo_gen(dbg, error)) != DW_DLE_NONE) 167 return (ret); 168 169 /* Produce .debug_pubnames section. */ 170 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_pubnames", dbg->dbgp_pubs, 171 error)) != DW_DLE_NONE) 172 return (ret); 173 174 /* Produce .debug_weaknames section. */ 175 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_weaknames", dbg->dbgp_weaks, 176 error)) != DW_DLE_NONE) 177 return (ret); 178 179 /* Produce .debug_funcnames section. */ 180 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_funcnames", dbg->dbgp_funcs, 181 error)) != DW_DLE_NONE) 182 return (ret); 183 184 /* Produce .debug_typenames section. */ 185 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_typenames", dbg->dbgp_types, 186 error)) != DW_DLE_NONE) 187 return (ret); 188 189 /* Produce .debug_varnames section. */ 190 if ((ret = _dwarf_nametbl_gen(dbg, ".debug_varnames", dbg->dbgp_vars, 191 error)) != DW_DLE_NONE) 192 return (ret); 193 194 /* Produce .debug_str section. */ 195 if ((ret = _dwarf_strtab_gen(dbg, error)) != DW_DLE_NONE) 196 return (ret); 197 198 /* Finally, update and generate all relocation sections. */ 199 if ((ret = _dwarf_reloc_gen(dbg, error)) != DW_DLE_NONE) 200 return (ret); 201 202 /* Set section/relocation iterator to the first element. */ 203 dbg->dbgp_secpos = STAILQ_FIRST(&dbg->dbgp_seclist); 204 dbg->dbgp_drspos = STAILQ_FIRST(&dbg->dbgp_drslist); 205 206 return (DW_DLE_NONE); 207 } 208 209 Dwarf_Section * 210 _dwarf_find_section(Dwarf_Debug dbg, const char *name) 211 { 212 Dwarf_Section *ds; 213 Dwarf_Half i; 214 215 assert(name != NULL); 216 217 for (i = 0; i < dbg->dbg_seccnt; i++) { 218 ds = &dbg->dbg_section[i]; 219 if (ds->ds_name != NULL && !strcmp(ds->ds_name, name)) 220 return (ds); 221 } 222 223 return (NULL); 224 } 225 226 Dwarf_P_Section 227 _dwarf_pro_find_section(Dwarf_P_Debug dbg, const char *name) 228 { 229 Dwarf_P_Section ds; 230 231 assert(dbg != NULL && name != NULL); 232 233 STAILQ_FOREACH(ds, &dbg->dbgp_seclist, ds_next) { 234 if (ds->ds_name != NULL && !strcmp(ds->ds_name ,name)) 235 return (ds); 236 } 237 238 return (NULL); 239 } 240 241 void 242 _dwarf_section_cleanup(Dwarf_P_Debug dbg) 243 { 244 Dwarf_P_Section ds, tds; 245 246 assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); 247 248 STAILQ_FOREACH_SAFE(ds, &dbg->dbgp_seclist, ds_next, tds) { 249 STAILQ_REMOVE(&dbg->dbgp_seclist, ds, _Dwarf_P_Section, 250 ds_next); 251 if (ds->ds_name) 252 free(ds->ds_name); 253 if (ds->ds_data) 254 free(ds->ds_data); 255 free(ds); 256 } 257 dbg->dbgp_seccnt = 0; 258 dbg->dbgp_secpos = 0; 259 } 260