Branch data Line data Source code
1 : : /* Find source location for PC address in module. 2 : : Copyright (C) 2005, 2008, 2014 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : 5 : : This file is free software; you can redistribute it and/or modify 6 : : it under the terms of either 7 : : 8 : : * the GNU Lesser General Public License as published by the Free 9 : : Software Foundation; either version 3 of the License, or (at 10 : : your option) any later version 11 : : 12 : : or 13 : : 14 : : * the GNU General Public License as published by the Free 15 : : Software Foundation; either version 2 of the License, or (at 16 : : your option) any later version 17 : : 18 : : or both in parallel, as here. 19 : : 20 : : elfutils is distributed in the hope that it will be useful, but 21 : : WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 : : General Public License for more details. 24 : : 25 : : You should have received copies of the GNU General Public License and 26 : : the GNU Lesser General Public License along with this program. If 27 : : not, see <http://www.gnu.org/licenses/>. */ 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include "libdwflP.h" 34 : : #include "libdwP.h" 35 : : 36 : : Dwfl_Line * 37 : 268 : dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr) 38 : : { 39 : 268 : Dwarf_Addr bias; 40 [ + + ]: 268 : if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL) 41 : : return NULL; 42 : : 43 : 198 : struct dwfl_cu *cu; 44 : 198 : Dwfl_Error error = __libdwfl_addrcu (mod, addr, &cu); 45 [ + + ]: 198 : if (likely (error == DWFL_E_NOERROR)) 46 : 192 : error = __libdwfl_cu_getsrclines (cu); 47 [ + + ]: 198 : if (likely (error == DWFL_E_NOERROR)) 48 : : { 49 : 192 : Dwarf_Lines *lines = cu->die.cu->lines; 50 : 192 : size_t nlines = lines->nlines; 51 [ + + ]: 192 : if (nlines > 0) 52 : : { 53 : : /* This is guaranteed for us by libdw read_srclines. */ 54 [ - + ]: 190 : assert(lines->info[nlines - 1].end_sequence); 55 : : 56 : : /* Now we look at the module-relative address. */ 57 : 190 : addr -= bias; 58 : : 59 : : /* The lines are sorted by address, so we can use binary search. */ 60 : 190 : size_t l = 0, u = nlines - 1; 61 [ + + ]: 1044 : while (l < u) 62 : : { 63 : 664 : size_t idx = u - (u - l) / 2; 64 : 664 : Dwarf_Line *line = &lines->info[idx]; 65 [ + + ]: 664 : if (addr < line->addr) 66 : 356 : u = idx - 1; 67 : : else 68 : : l = idx; 69 : : } 70 : : 71 : : /* The last line which is less than or equal to addr is what 72 : : we want, unless it is the end_sequence which is after the 73 : : current line sequence. */ 74 : 190 : Dwarf_Line *line = &lines->info[l]; 75 [ + - + - ]: 190 : if (! line->end_sequence && line->addr <= addr) 76 : 190 : return &cu->lines->idx[l]; 77 : : } 78 : : 79 : : error = DWFL_E_ADDR_OUTOFRANGE; 80 : : } 81 : : 82 : 8 : __libdwfl_seterrno (error); 83 : 8 : return NULL; 84 : : } 85 : : INTDEF (dwfl_module_getsrc)