xref: /aosp_15_r20/external/elfutils/libdw/dwarf_entry_breakpoints.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Find entry breakpoint locations for a function.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005-2009 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker 
5*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker    it under the terms of either
7*7304104dSAndroid Build Coastguard Worker 
8*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker        your option) any later version
11*7304104dSAndroid Build Coastguard Worker 
12*7304104dSAndroid Build Coastguard Worker    or
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker        your option) any later version
17*7304104dSAndroid Build Coastguard Worker 
18*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
27*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
28*7304104dSAndroid Build Coastguard Worker 
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
33*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
34*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
35*7304104dSAndroid Build Coastguard Worker 
36*7304104dSAndroid Build Coastguard Worker 
37*7304104dSAndroid Build Coastguard Worker /* Add one breakpoint location to the result vector.  */
38*7304104dSAndroid Build Coastguard Worker static inline int
add_bkpt(Dwarf_Addr pc,Dwarf_Addr ** bkpts,int * pnbkpts)39*7304104dSAndroid Build Coastguard Worker add_bkpt (Dwarf_Addr pc, Dwarf_Addr **bkpts, int *pnbkpts)
40*7304104dSAndroid Build Coastguard Worker {
41*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr *newlist = realloc (*bkpts, ++(*pnbkpts) * sizeof newlist[0]);
42*7304104dSAndroid Build Coastguard Worker   if (newlist == NULL)
43*7304104dSAndroid Build Coastguard Worker     {
44*7304104dSAndroid Build Coastguard Worker       free (*bkpts);
45*7304104dSAndroid Build Coastguard Worker       *bkpts = NULL;
46*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_NOMEM);
47*7304104dSAndroid Build Coastguard Worker       return -1;
48*7304104dSAndroid Build Coastguard Worker     }
49*7304104dSAndroid Build Coastguard Worker   newlist[*pnbkpts - 1] = pc;
50*7304104dSAndroid Build Coastguard Worker   *bkpts = newlist;
51*7304104dSAndroid Build Coastguard Worker   return *pnbkpts;
52*7304104dSAndroid Build Coastguard Worker }
53*7304104dSAndroid Build Coastguard Worker 
54*7304104dSAndroid Build Coastguard Worker /* Fallback result, break at the entrypc/lowpc value.  */
55*7304104dSAndroid Build Coastguard Worker static inline int
entrypc_bkpt(Dwarf_Die * die,Dwarf_Addr ** bkpts,int * pnbkpts)56*7304104dSAndroid Build Coastguard Worker entrypc_bkpt (Dwarf_Die *die, Dwarf_Addr **bkpts, int *pnbkpts)
57*7304104dSAndroid Build Coastguard Worker {
58*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr pc;
59*7304104dSAndroid Build Coastguard Worker   return INTUSE(dwarf_entrypc) (die, &pc) < 0 ? -1 : add_bkpt (pc, bkpts, pnbkpts);
60*7304104dSAndroid Build Coastguard Worker }
61*7304104dSAndroid Build Coastguard Worker 
62*7304104dSAndroid Build Coastguard Worker /* Search a contiguous PC range for prologue-end markers.
63*7304104dSAndroid Build Coastguard Worker    If DWARF, look for proper markers.
64*7304104dSAndroid Build Coastguard Worker    Failing that, if ADHOC, look for the ad hoc convention.  */
65*7304104dSAndroid Build Coastguard Worker static inline int
search_range(Dwarf_Addr low,Dwarf_Addr high,bool dwarf,bool adhoc,Dwarf_Lines * lines,size_t nlines,Dwarf_Addr ** bkpts,int * pnbkpts)66*7304104dSAndroid Build Coastguard Worker search_range (Dwarf_Addr low, Dwarf_Addr high,
67*7304104dSAndroid Build Coastguard Worker 	      bool dwarf, bool adhoc,
68*7304104dSAndroid Build Coastguard Worker               Dwarf_Lines *lines, size_t nlines,
69*7304104dSAndroid Build Coastguard Worker               Dwarf_Addr **bkpts, int *pnbkpts)
70*7304104dSAndroid Build Coastguard Worker {
71*7304104dSAndroid Build Coastguard Worker       size_t l = 0, u = nlines;
72*7304104dSAndroid Build Coastguard Worker       while (l < u)
73*7304104dSAndroid Build Coastguard Worker 	{
74*7304104dSAndroid Build Coastguard Worker 	  size_t idx = (l + u) / 2;
75*7304104dSAndroid Build Coastguard Worker 	  if (lines->info[idx].addr < low)
76*7304104dSAndroid Build Coastguard Worker 	    l = idx + 1;
77*7304104dSAndroid Build Coastguard Worker 	  else if (lines->info[idx].addr > low)
78*7304104dSAndroid Build Coastguard Worker 	    u = idx;
79*7304104dSAndroid Build Coastguard Worker 	  else if (lines->info[idx].end_sequence)
80*7304104dSAndroid Build Coastguard Worker 	    l = idx + 1;
81*7304104dSAndroid Build Coastguard Worker 	  else
82*7304104dSAndroid Build Coastguard Worker 	    {
83*7304104dSAndroid Build Coastguard Worker 	      l = idx;
84*7304104dSAndroid Build Coastguard Worker 	      break;
85*7304104dSAndroid Build Coastguard Worker 	    }
86*7304104dSAndroid Build Coastguard Worker 	}
87*7304104dSAndroid Build Coastguard Worker       if (l < u)
88*7304104dSAndroid Build Coastguard Worker 	{
89*7304104dSAndroid Build Coastguard Worker 	  if (dwarf)
90*7304104dSAndroid Build Coastguard Worker 	    for (size_t i = l; i < u && lines->info[i].addr < high; ++i)
91*7304104dSAndroid Build Coastguard Worker 	      if (lines->info[i].prologue_end
92*7304104dSAndroid Build Coastguard Worker 		  && add_bkpt (lines->info[i].addr, bkpts, pnbkpts) < 0)
93*7304104dSAndroid Build Coastguard Worker 		return -1;
94*7304104dSAndroid Build Coastguard Worker 	  if (adhoc && *pnbkpts == 0)
95*7304104dSAndroid Build Coastguard Worker 	    while (++l < nlines && lines->info[l].addr < high)
96*7304104dSAndroid Build Coastguard Worker 	      if (!lines->info[l].end_sequence)
97*7304104dSAndroid Build Coastguard Worker 		return add_bkpt (lines->info[l].addr, bkpts, pnbkpts);
98*7304104dSAndroid Build Coastguard Worker 	  return *pnbkpts;
99*7304104dSAndroid Build Coastguard Worker 	}
100*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_INVALID_DWARF);
101*7304104dSAndroid Build Coastguard Worker       return -1;
102*7304104dSAndroid Build Coastguard Worker }
103*7304104dSAndroid Build Coastguard Worker 
104*7304104dSAndroid Build Coastguard Worker int
dwarf_entry_breakpoints(Dwarf_Die * die,Dwarf_Addr ** bkpts)105*7304104dSAndroid Build Coastguard Worker dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts)
106*7304104dSAndroid Build Coastguard Worker {
107*7304104dSAndroid Build Coastguard Worker   int nbkpts = 0;
108*7304104dSAndroid Build Coastguard Worker   *bkpts = NULL;
109*7304104dSAndroid Build Coastguard Worker 
110*7304104dSAndroid Build Coastguard Worker   /* Fetch the CU's line records to look for this DIE's addresses.  */
111*7304104dSAndroid Build Coastguard Worker   Dwarf_Die cudie = CUDIE (die->cu);
112*7304104dSAndroid Build Coastguard Worker   Dwarf_Lines *lines;
113*7304104dSAndroid Build Coastguard Worker   size_t nlines;
114*7304104dSAndroid Build Coastguard Worker   if (INTUSE(dwarf_getsrclines) (&cudie, &lines, &nlines) < 0)
115*7304104dSAndroid Build Coastguard Worker     {
116*7304104dSAndroid Build Coastguard Worker       int error = INTUSE (dwarf_errno) ();
117*7304104dSAndroid Build Coastguard Worker       if (error == 0)		/* CU has no DW_AT_stmt_list.  */
118*7304104dSAndroid Build Coastguard Worker 	return entrypc_bkpt (die, bkpts, &nbkpts);
119*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (error);
120*7304104dSAndroid Build Coastguard Worker       return -1;
121*7304104dSAndroid Build Coastguard Worker     }
122*7304104dSAndroid Build Coastguard Worker 
123*7304104dSAndroid Build Coastguard Worker   /* Search each contiguous address range for DWARF prologue_end markers.  */
124*7304104dSAndroid Build Coastguard Worker 
125*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr base;
126*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr begin;
127*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr end;
128*7304104dSAndroid Build Coastguard Worker   ptrdiff_t offset = INTUSE(dwarf_ranges) (die, 0, &base, &begin, &end);
129*7304104dSAndroid Build Coastguard Worker   if (offset < 0)
130*7304104dSAndroid Build Coastguard Worker     return -1;
131*7304104dSAndroid Build Coastguard Worker 
132*7304104dSAndroid Build Coastguard Worker   /* Most often there is a single contiguous PC range for the DIE.  */
133*7304104dSAndroid Build Coastguard Worker   if (offset == 1)
134*7304104dSAndroid Build Coastguard Worker     return search_range (begin, end, true, true, lines, nlines, bkpts, &nbkpts)
135*7304104dSAndroid Build Coastguard Worker         ?: entrypc_bkpt (die, bkpts, &nbkpts);
136*7304104dSAndroid Build Coastguard Worker 
137*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr lowpc = (Dwarf_Addr) -1l;
138*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr highpc = (Dwarf_Addr) -1l;
139*7304104dSAndroid Build Coastguard Worker   while (offset > 0)
140*7304104dSAndroid Build Coastguard Worker     {
141*7304104dSAndroid Build Coastguard Worker       /* We have an address range entry.  */
142*7304104dSAndroid Build Coastguard Worker       if (search_range (begin, end, true, false,
143*7304104dSAndroid Build Coastguard Worker                         lines, nlines, bkpts, &nbkpts) < 0)
144*7304104dSAndroid Build Coastguard Worker 	return -1;
145*7304104dSAndroid Build Coastguard Worker 
146*7304104dSAndroid Build Coastguard Worker       if (begin < lowpc)
147*7304104dSAndroid Build Coastguard Worker 	{
148*7304104dSAndroid Build Coastguard Worker 	  lowpc = begin;
149*7304104dSAndroid Build Coastguard Worker 	  highpc = end;
150*7304104dSAndroid Build Coastguard Worker 	}
151*7304104dSAndroid Build Coastguard Worker 
152*7304104dSAndroid Build Coastguard Worker       offset = INTUSE(dwarf_ranges) (die, offset, &base, &begin, &end);
153*7304104dSAndroid Build Coastguard Worker     }
154*7304104dSAndroid Build Coastguard Worker 
155*7304104dSAndroid Build Coastguard Worker   /* If we didn't find any proper DWARF markers, then look in the
156*7304104dSAndroid Build Coastguard Worker      lowest-addressed range for an ad hoc marker.  Failing that,
157*7304104dSAndroid Build Coastguard Worker      fall back to just using the entrypc value.  */
158*7304104dSAndroid Build Coastguard Worker   return (nbkpts
159*7304104dSAndroid Build Coastguard Worker 	  ?: (lowpc == (Dwarf_Addr) -1l ? 0
160*7304104dSAndroid Build Coastguard Worker 	      : search_range (lowpc, highpc, false, true,
161*7304104dSAndroid Build Coastguard Worker 	                      lines, nlines, bkpts, &nbkpts))
162*7304104dSAndroid Build Coastguard Worker 	  ?: entrypc_bkpt (die, bkpts, &nbkpts));
163*7304104dSAndroid Build Coastguard Worker }
164