1/*- 2 * Copyright (c) 2009,2011 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 29ELFTC_VCSID("$Id: dwarf_lineno.c 2983 2014-02-09 00:24:31Z kaiwang27 $"); 30 31int 32dwarf_srclines(Dwarf_Die die, Dwarf_Line **linebuf, Dwarf_Signed *linecount, 33 Dwarf_Error *error) 34{ 35 Dwarf_LineInfo li; 36 Dwarf_Debug dbg; 37 Dwarf_Line ln; 38 Dwarf_CU cu; 39 Dwarf_Attribute at; 40 int i; 41 42 dbg = die != NULL ? die->die_dbg : NULL; 43 44 if (die == NULL || linebuf == NULL || linecount == NULL) { 45 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 46 return (DW_DLV_ERROR); 47 } 48 49 if ((at = _dwarf_attr_find(die, DW_AT_stmt_list)) == NULL) { 50 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 51 return (DW_DLV_NO_ENTRY); 52 } 53 54 cu = die->die_cu; 55 if (cu->cu_lineinfo == NULL) { 56 if (_dwarf_lineno_init(die, at->u[0].u64, error) != 57 DW_DLE_NONE) 58 return (DW_DLV_ERROR); 59 } 60 if (cu->cu_lineinfo == NULL) { 61 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 62 return (DW_DLV_NO_ENTRY); 63 } 64 65 li = cu->cu_lineinfo; 66 *linecount = (Dwarf_Signed) li->li_lnlen; 67 68 if (*linecount == 0) { 69 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 70 return (DW_DLV_NO_ENTRY); 71 } 72 73 if (li->li_lnarray != NULL) { 74 *linebuf = li->li_lnarray; 75 return (DW_DLV_OK); 76 } 77 78 if ((li->li_lnarray = malloc(*linecount * sizeof(Dwarf_Line))) == 79 NULL) { 80 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 81 return (DW_DLV_ERROR); 82 } 83 84 for (i = 0, ln = STAILQ_FIRST(&li->li_lnlist); 85 i < *linecount && ln != NULL; i++, ln = STAILQ_NEXT(ln, ln_next)) 86 li->li_lnarray[i] = ln; 87 88 *linebuf = li->li_lnarray; 89 90 return (DW_DLV_OK); 91} 92 93int 94dwarf_srcfiles(Dwarf_Die die, char ***srcfiles, Dwarf_Signed *srccount, 95 Dwarf_Error *error) 96{ 97 Dwarf_LineInfo li; 98 Dwarf_LineFile lf; 99 Dwarf_Debug dbg; 100 Dwarf_CU cu; 101 Dwarf_Attribute at; 102 int i; 103 104 dbg = die != NULL ? die->die_dbg : NULL; 105 106 if (die == NULL || srcfiles == NULL || srccount == NULL) { 107 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT); 108 return (DW_DLV_ERROR); 109 } 110 111 if ((at = _dwarf_attr_find(die, DW_AT_stmt_list)) == NULL) { 112 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 113 return (DW_DLV_NO_ENTRY); 114 } 115 116 cu = die->die_cu; 117 if (cu->cu_lineinfo == NULL) { 118 if (_dwarf_lineno_init(die, at->u[0].u64, error) != 119 DW_DLE_NONE) 120 return (DW_DLV_ERROR); 121 } 122 if (cu->cu_lineinfo == NULL) { 123 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 124 return (DW_DLV_NO_ENTRY); 125 } 126 127 li = cu->cu_lineinfo; 128 *srccount = (Dwarf_Signed) li->li_lflen; 129 130 if (*srccount == 0) { 131 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY); 132 return (DW_DLV_NO_ENTRY); 133 } 134 135 if (li->li_lfnarray != NULL) { 136 *srcfiles = li->li_lfnarray; 137 return (DW_DLV_OK); 138 } 139 140 if ((li->li_lfnarray = malloc(*srccount * sizeof(char *))) == NULL) { 141 DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); 142 return (DW_DLV_ERROR); 143 } 144 145 for (i = 0, lf = STAILQ_FIRST(&li->li_lflist); 146 i < *srccount && lf != NULL; i++, lf = STAILQ_NEXT(lf, lf_next)) { 147 if (lf->lf_fullpath) 148 li->li_lfnarray[i] = lf->lf_fullpath; 149 else 150 li->li_lfnarray[i] = lf->lf_fname; 151 } 152 153 *srcfiles = li->li_lfnarray; 154 155 return (DW_DLV_OK); 156} 157 158int 159dwarf_linebeginstatement(Dwarf_Line ln, Dwarf_Bool *ret_bool, 160 Dwarf_Error *error) 161{ 162 163 if (ln == NULL || ret_bool == NULL) { 164 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 165 return (DW_DLV_ERROR); 166 } 167 168 *ret_bool = ln->ln_stmt; 169 170 return (DW_DLV_OK); 171} 172 173int 174dwarf_lineendsequence(Dwarf_Line ln, Dwarf_Bool *ret_bool, Dwarf_Error *error) 175{ 176 177 if (ln == NULL || ret_bool == NULL) { 178 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 179 return (DW_DLV_ERROR); 180 } 181 182 *ret_bool = ln->ln_endseq; 183 184 return (DW_DLV_OK); 185} 186 187int 188dwarf_lineno(Dwarf_Line ln, Dwarf_Unsigned *ret_lineno, Dwarf_Error *error) 189{ 190 191 if (ln == NULL || ret_lineno == NULL) { 192 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 193 return (DW_DLV_ERROR); 194 } 195 196 *ret_lineno = ln->ln_lineno; 197 198 return (DW_DLV_OK); 199} 200 201int 202dwarf_line_srcfileno(Dwarf_Line ln, Dwarf_Unsigned *ret_fileno, 203 Dwarf_Error *error) 204{ 205 206 if (ln == NULL || ret_fileno == NULL) { 207 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 208 return (DW_DLV_ERROR); 209 } 210 211 *ret_fileno = ln->ln_fileno; 212 213 return (DW_DLV_OK); 214} 215 216int 217dwarf_lineaddr(Dwarf_Line ln, Dwarf_Addr *ret_lineaddr, Dwarf_Error *error) 218{ 219 220 if (ln == NULL || ret_lineaddr == NULL) { 221 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 222 return (DW_DLV_ERROR); 223 } 224 225 *ret_lineaddr = ln->ln_addr; 226 227 return (DW_DLV_OK); 228} 229 230int 231dwarf_lineoff(Dwarf_Line ln, Dwarf_Signed *ret_lineoff, Dwarf_Error *error) 232{ 233 234 if (ln == NULL || ret_lineoff == NULL) { 235 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 236 return (DW_DLV_ERROR); 237 } 238 239 if (ln->ln_column == 0) 240 *ret_lineoff = -1; 241 else 242 *ret_lineoff = (Dwarf_Signed) ln->ln_column; 243 244 return (DW_DLV_OK); 245} 246 247int 248dwarf_linesrc(Dwarf_Line ln, char **ret_linesrc, Dwarf_Error *error) 249{ 250 Dwarf_LineInfo li; 251 Dwarf_LineFile lf; 252 int i; 253 254 if (ln == NULL || ret_linesrc == NULL) { 255 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 256 return (DW_DLV_ERROR); 257 } 258 259 li = ln->ln_li; 260 assert(li != NULL); 261 262 for (i = 1, lf = STAILQ_FIRST(&li->li_lflist); 263 (Dwarf_Unsigned) i < ln->ln_fileno && lf != NULL; 264 i++, lf = STAILQ_NEXT(lf, lf_next)) 265 ; 266 267 if (lf == NULL) { 268 DWARF_SET_ERROR(NULL, error, DW_DLE_LINE_FILE_NUM_BAD); 269 return (DW_DLV_ERROR); 270 } 271 272 if (lf->lf_fullpath) { 273 *ret_linesrc = (char *) lf->lf_fullpath; 274 return (DW_DLV_OK); 275 } 276 277 *ret_linesrc = lf->lf_fname; 278 279 return (DW_DLV_OK); 280} 281 282int 283dwarf_lineblock(Dwarf_Line ln, Dwarf_Bool *ret_bool, Dwarf_Error *error) 284{ 285 286 if (ln == NULL || ret_bool == NULL) { 287 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT); 288 return (DW_DLV_ERROR); 289 } 290 291 *ret_bool = ln->ln_bblock; 292 293 return (DW_DLV_OK); 294} 295