Branch data Line data Source code
1 : : /* Find source location for PC address in module.
2 : : Copyright (C) 2005, 2008 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 : : #include "libdwflP.h"
30 : : #include "../libdw/libdwP.h"
31 : :
32 : : Dwfl_Line *
33 : 101 : dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr)
34 : : {
35 : : Dwarf_Addr bias;
36 [ + + ]: 101 : if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL)
37 : : return NULL;
38 : :
39 : : struct dwfl_cu *cu;
40 : 44 : Dwfl_Error error = __libdwfl_addrcu (mod, addr, &cu);
41 [ + + ]: 44 : if (likely (error == DWFL_E_NOERROR))
42 : 36 : error = __libdwfl_cu_getsrclines (cu);
43 [ + + ]: 44 : if (likely (error == DWFL_E_NOERROR))
44 : : {
45 : : /* Now we look at the module-relative address. */
46 : 36 : addr -= bias;
47 : :
48 : : /* The lines are sorted by address, so we can use binary search. */
49 : 36 : size_t l = 0, u = cu->die.cu->lines->nlines;
50 [ + + ]: 95 : while (l < u)
51 : : {
52 : 79 : size_t idx = (l + u) / 2;
53 [ + + ]: 79 : if (addr < cu->die.cu->lines->info[idx].addr)
54 : : u = idx;
55 [ + + ]: 42 : else if (addr > cu->die.cu->lines->info[idx].addr)
56 : 22 : l = idx + 1;
57 : : else
58 : 79 : return &cu->lines->idx[idx];
59 : : }
60 : :
61 [ + - ]: 16 : if (cu->die.cu->lines->nlines > 0)
62 [ - + ]: 16 : assert (cu->die.cu->lines->info
63 : : [cu->die.cu->lines->nlines - 1].end_sequence);
64 : :
65 : : /* If none were equal, the closest one below is what we want.
66 : : We never want the last one, because it's the end-sequence
67 : : marker with an address at the high bound of the CU's code. */
68 [ + - ][ + - ]: 16 : if (u > 0 && u < cu->die.cu->lines->nlines
69 [ + - ]: 16 : && addr > cu->die.cu->lines->info[u - 1].addr)
70 : 16 : return &cu->lines->idx[u - 1];
71 : :
72 : : error = DWFL_E_ADDR_OUTOFRANGE;
73 : : }
74 : :
75 : 101 : __libdwfl_seterrno (error);
76 : : return NULL;
77 : : }
78 : : INTDEF (dwfl_module_getsrc)
|