1da0c48c4Sopenharmony_ci/* Iterate through the debug line table. 2da0c48c4Sopenharmony_ci Copyright (C) 2018 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 30da0c48c4Sopenharmony_ci# include <config.h> 31da0c48c4Sopenharmony_ci#endif 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci#include <libdwP.h> 34da0c48c4Sopenharmony_ci 35da0c48c4Sopenharmony_ci 36da0c48c4Sopenharmony_ciint 37da0c48c4Sopenharmony_cidwarf_next_lines (Dwarf *dbg, Dwarf_Off off, 38da0c48c4Sopenharmony_ci Dwarf_Off *next_off, Dwarf_CU **cu, 39da0c48c4Sopenharmony_ci Dwarf_Files **srcfiles, size_t *nfiles, 40da0c48c4Sopenharmony_ci Dwarf_Lines **srclines, size_t *nlines) 41da0c48c4Sopenharmony_ci{ 42da0c48c4Sopenharmony_ci /* Ignore existing errors. */ 43da0c48c4Sopenharmony_ci if (dbg == NULL) 44da0c48c4Sopenharmony_ci return -1; 45da0c48c4Sopenharmony_ci 46da0c48c4Sopenharmony_ci Elf_Data *lines = dbg->sectiondata[IDX_debug_line]; 47da0c48c4Sopenharmony_ci if (lines == NULL) 48da0c48c4Sopenharmony_ci { 49da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_NO_DEBUG_LINE); 50da0c48c4Sopenharmony_ci return -1; 51da0c48c4Sopenharmony_ci } 52da0c48c4Sopenharmony_ci 53da0c48c4Sopenharmony_ci if (off == (Dwarf_Off) -1 54da0c48c4Sopenharmony_ci || lines->d_size < 4 55da0c48c4Sopenharmony_ci || off >= lines->d_size) 56da0c48c4Sopenharmony_ci { 57da0c48c4Sopenharmony_ci *next_off = (Dwarf_Off) -1; 58da0c48c4Sopenharmony_ci return 1; 59da0c48c4Sopenharmony_ci } 60da0c48c4Sopenharmony_ci 61da0c48c4Sopenharmony_ci /* Read enough of the header to know where the next table is and 62da0c48c4Sopenharmony_ci whether we need to lookup the CU (version < 5). */ 63da0c48c4Sopenharmony_ci const unsigned char *linep = lines->d_buf + off; 64da0c48c4Sopenharmony_ci const unsigned char *lineendp = lines->d_buf + lines->d_size; 65da0c48c4Sopenharmony_ci 66da0c48c4Sopenharmony_ci if ((size_t) (lineendp - linep) < 4) 67da0c48c4Sopenharmony_ci { 68da0c48c4Sopenharmony_ci invalid_data: 69da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE); 70da0c48c4Sopenharmony_ci return -1; 71da0c48c4Sopenharmony_ci } 72da0c48c4Sopenharmony_ci 73da0c48c4Sopenharmony_ci *next_off = off + 4; 74da0c48c4Sopenharmony_ci Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); 75da0c48c4Sopenharmony_ci if (unit_length == DWARF3_LENGTH_64_BIT) 76da0c48c4Sopenharmony_ci { 77da0c48c4Sopenharmony_ci if ((size_t) (lineendp - linep) < 8) 78da0c48c4Sopenharmony_ci goto invalid_data; 79da0c48c4Sopenharmony_ci unit_length = read_8ubyte_unaligned_inc (dbg, linep); 80da0c48c4Sopenharmony_ci *next_off += 8; 81da0c48c4Sopenharmony_ci } 82da0c48c4Sopenharmony_ci 83da0c48c4Sopenharmony_ci if (unit_length > (size_t) (lineendp - linep)) 84da0c48c4Sopenharmony_ci goto invalid_data; 85da0c48c4Sopenharmony_ci 86da0c48c4Sopenharmony_ci *next_off += unit_length; 87da0c48c4Sopenharmony_ci lineendp = linep + unit_length; 88da0c48c4Sopenharmony_ci 89da0c48c4Sopenharmony_ci if ((size_t) (lineendp - linep) < 2) 90da0c48c4Sopenharmony_ci goto invalid_data; 91da0c48c4Sopenharmony_ci uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); 92da0c48c4Sopenharmony_ci 93da0c48c4Sopenharmony_ci Dwarf_Die cudie; 94da0c48c4Sopenharmony_ci if (version < 5) 95da0c48c4Sopenharmony_ci { 96da0c48c4Sopenharmony_ci /* We need to find the matching CU to get the comp_dir. Use the 97da0c48c4Sopenharmony_ci given CU as hint where to start searching. Normally it will 98da0c48c4Sopenharmony_ci be the next CU that has a statement list. */ 99da0c48c4Sopenharmony_ci Dwarf_CU *given_cu = *cu; 100da0c48c4Sopenharmony_ci Dwarf_CU *next_cu = given_cu; 101da0c48c4Sopenharmony_ci bool found = false; 102da0c48c4Sopenharmony_ci while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL, 103da0c48c4Sopenharmony_ci &cudie, NULL) == 0) 104da0c48c4Sopenharmony_ci { 105da0c48c4Sopenharmony_ci if (dwarf_hasattr (&cudie, DW_AT_stmt_list)) 106da0c48c4Sopenharmony_ci { 107da0c48c4Sopenharmony_ci Dwarf_Attribute attr; 108da0c48c4Sopenharmony_ci Dwarf_Word stmt_off; 109da0c48c4Sopenharmony_ci if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr), 110da0c48c4Sopenharmony_ci &stmt_off) == 0 111da0c48c4Sopenharmony_ci && stmt_off == off) 112da0c48c4Sopenharmony_ci { 113da0c48c4Sopenharmony_ci found = true; 114da0c48c4Sopenharmony_ci break; 115da0c48c4Sopenharmony_ci } 116da0c48c4Sopenharmony_ci } 117da0c48c4Sopenharmony_ci else if (off == 0 118da0c48c4Sopenharmony_ci && (next_cu->unit_type == DW_UT_split_compile 119da0c48c4Sopenharmony_ci || next_cu->unit_type == DW_UT_split_type)) 120da0c48c4Sopenharmony_ci { 121da0c48c4Sopenharmony_ci /* For split units (in .dwo files) there is only one table 122da0c48c4Sopenharmony_ci at offset zero (containing just the files, no lines). */ 123da0c48c4Sopenharmony_ci found = true; 124da0c48c4Sopenharmony_ci break; 125da0c48c4Sopenharmony_ci } 126da0c48c4Sopenharmony_ci } 127da0c48c4Sopenharmony_ci 128da0c48c4Sopenharmony_ci if (!found && given_cu != NULL) 129da0c48c4Sopenharmony_ci { 130da0c48c4Sopenharmony_ci /* The CUs might be in a different order from the line 131da0c48c4Sopenharmony_ci tables. Need to do a linear search (but stop at the given 132da0c48c4Sopenharmony_ci CU, since we already searched those. */ 133da0c48c4Sopenharmony_ci next_cu = NULL; 134da0c48c4Sopenharmony_ci while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL, 135da0c48c4Sopenharmony_ci &cudie, NULL) == 0 136da0c48c4Sopenharmony_ci && next_cu != given_cu) 137da0c48c4Sopenharmony_ci { 138da0c48c4Sopenharmony_ci Dwarf_Attribute attr; 139da0c48c4Sopenharmony_ci Dwarf_Word stmt_off; 140da0c48c4Sopenharmony_ci if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr), 141da0c48c4Sopenharmony_ci &stmt_off) == 0 142da0c48c4Sopenharmony_ci && stmt_off == off) 143da0c48c4Sopenharmony_ci { 144da0c48c4Sopenharmony_ci found = true; 145da0c48c4Sopenharmony_ci break; 146da0c48c4Sopenharmony_ci } 147da0c48c4Sopenharmony_ci } 148da0c48c4Sopenharmony_ci } 149da0c48c4Sopenharmony_ci 150da0c48c4Sopenharmony_ci if (found) 151da0c48c4Sopenharmony_ci *cu = next_cu; 152da0c48c4Sopenharmony_ci else 153da0c48c4Sopenharmony_ci *cu = NULL; 154da0c48c4Sopenharmony_ci } 155da0c48c4Sopenharmony_ci else 156da0c48c4Sopenharmony_ci *cu = NULL; 157da0c48c4Sopenharmony_ci 158da0c48c4Sopenharmony_ci const char *comp_dir; 159da0c48c4Sopenharmony_ci unsigned address_size; 160da0c48c4Sopenharmony_ci if (*cu != NULL) 161da0c48c4Sopenharmony_ci { 162da0c48c4Sopenharmony_ci comp_dir = __libdw_getcompdir (&cudie); 163da0c48c4Sopenharmony_ci address_size = (*cu)->address_size; 164da0c48c4Sopenharmony_ci } 165da0c48c4Sopenharmony_ci else 166da0c48c4Sopenharmony_ci { 167da0c48c4Sopenharmony_ci comp_dir = NULL; 168da0c48c4Sopenharmony_ci 169da0c48c4Sopenharmony_ci size_t esize; 170da0c48c4Sopenharmony_ci char *ident = elf_getident (dbg->elf, &esize); 171da0c48c4Sopenharmony_ci if (ident == NULL || esize < EI_NIDENT) 172da0c48c4Sopenharmony_ci goto invalid_data; 173da0c48c4Sopenharmony_ci address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 174da0c48c4Sopenharmony_ci } 175da0c48c4Sopenharmony_ci 176da0c48c4Sopenharmony_ci if (__libdw_getsrclines (dbg, off, comp_dir, address_size, 177da0c48c4Sopenharmony_ci srclines, srcfiles) != 0) 178da0c48c4Sopenharmony_ci return -1; 179da0c48c4Sopenharmony_ci 180da0c48c4Sopenharmony_ci if (nlines != NULL) 181da0c48c4Sopenharmony_ci { 182da0c48c4Sopenharmony_ci if (srclines != NULL && *srclines != NULL) 183da0c48c4Sopenharmony_ci *nlines = (*srclines)->nlines; 184da0c48c4Sopenharmony_ci else 185da0c48c4Sopenharmony_ci *nlines = 0; 186da0c48c4Sopenharmony_ci } 187da0c48c4Sopenharmony_ci 188da0c48c4Sopenharmony_ci if (nfiles != NULL) 189da0c48c4Sopenharmony_ci { 190da0c48c4Sopenharmony_ci if (srcfiles != NULL && *srcfiles != NULL) 191da0c48c4Sopenharmony_ci *nfiles = (*srcfiles)->nfiles; 192da0c48c4Sopenharmony_ci else 193da0c48c4Sopenharmony_ci *nfiles = 0; 194da0c48c4Sopenharmony_ci } 195da0c48c4Sopenharmony_ci 196da0c48c4Sopenharmony_ci return 0; 197da0c48c4Sopenharmony_ci} 198