blob: 3ceb292d90b3f0b08c511f7e4238707da7fb0254 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Find a named variable or parameter within given scopes.
2 Copyright (C) 2005 Red Hat, Inc.
3
4 This program is Open Source software; you can redistribute it and/or
5 modify it under the terms of the Open Software License version 1.0 as
6 published by the Open Source Initiative.
7
8 You should have received a copy of the Open Software License along
9 with this program; if not, you may obtain a copy of the Open Software
10 License version 1.0 from http://www.opensource.org/licenses/osl.php or
11 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
12 3001 King Ranch Road, Ukiah, CA 95482. */
13
14#ifdef HAVE_CONFIG_H
15# include <config.h>
16#endif
17
18#include <stdbool.h>
19#include <string.h>
20#include "libdwP.h"
21#include <dwarf.h>
22
23
24/* Find the containing CU's files. */
25static int
26getfiles (Dwarf_Die *die, Dwarf_Files **files)
27{
28 Dwarf_Die cudie =
29 {
30 .cu = die->cu,
31 .addr = ((char *) die->cu->dbg->sectiondata[IDX_debug_info]->d_buf
32 + 3 * die->cu->offset_size - 4 + 3),
33 };
34 return INTUSE(dwarf_getsrcfiles) (&cudie, files, NULL);
35}
36
37/* Fetch an attribute that should have a constant integer form. */
38static int
39getattr (Dwarf_Die *die, int search_name, Dwarf_Word *value)
40{
41 Dwarf_Attribute attr_mem;
42 return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, search_name,
43 &attr_mem), value);
44}
45
46/* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
47 Ignore the first SKIP_SHADOWS scopes that match the name.
48 If MATCH_FILE is not null, accept only declaration in that source file;
49 if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration
50 at that line and column.
51
52 If successful, fill in *RESULT with the DIE of the variable found,
53 and return N where SCOPES[N] is the scope defining the variable.
54 Return -1 for errors or -2 for no matching variable found. */
55
56int
57dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
58 const char *name, int skip_shadows,
59 const char *match_file, int match_lineno, int match_linecol,
60 Dwarf_Die *result)
61{
62 /* Match against the given file name. */
63 size_t match_file_len = match_file == NULL ? 0 : strlen (match_file);
64 bool lastfile_matches = false;
65 const char *lastfile = NULL;
66 inline bool file_matches (Dwarf_Files *files, size_t idx)
67 {
68 if (idx >= files->nfiles)
69 return false;
70
71 const char *file = files->info[idx].name;
72 if (file != lastfile)
73 {
74 size_t len = strlen (file);
75 lastfile_matches = (len >= match_file_len
76 && !memcmp (match_file, file, match_file_len)
77 && (len == match_file_len
78 || file[len - match_file_len - 1] == '/'));
79 }
80 return lastfile_matches;
81 }
82
83 /* Start with the innermost scope and move out. */
84 for (int out = 0; out < nscopes; ++out)
85 if (INTUSE(dwarf_haschildren) (&scopes[out]))
86 {
87 if (INTUSE(dwarf_child) (&scopes[out], result) != 0)
88 return -1;
89 do
90 {
91 switch (INTUSE(dwarf_tag) (result))
92 {
93 case DW_TAG_variable:
94 case DW_TAG_formal_parameter:
95 break;
96
97 default:
98 continue;
99 }
100
101 /* Only get here for a variable or parameter. Check the name. */
102 Dwarf_Attribute attr_mem;
103 const char *diename = INTUSE(dwarf_formstring)
104 (INTUSE(dwarf_attr_integrate) (result, DW_AT_name, &attr_mem));
105 if (diename != NULL && !strcmp (name, diename))
106 {
107 /* We have a matching name. */
108
109 if (skip_shadows > 0)
110 {
111 /* Punt this scope for the one it shadows. */
112 --skip_shadows;
113 break;
114 }
115
116 if (match_file != NULL)
117 {
118 /* Check its decl_file. */
119
120 Dwarf_Word i;
121 Dwarf_Files *files;
122 if (getattr (result, DW_AT_decl_file, &i) != 0
123 || getfiles (&scopes[out], &files) != 0)
124 break;
125
126 if (!file_matches (files, i))
127 break;
128
129 if (match_lineno > 0
130 && (getattr (result, DW_AT_decl_line, &i) != 0
131 || (int) i != match_lineno))
132 break;
133 if (match_linecol > 0
134 && (getattr (result, DW_AT_decl_column, &i) != 0
135 || (int) i != match_linecol))
136 break;
137 }
138
139 /* We have a winner! */
140 return out;
141 }
142 }
143 while (INTUSE(dwarf_siblingof) (result, result) == 0);
144 }
145
146 return -2;
147}