Commit | Line | Data |
---|---|---|
424163ea DJ |
1 | /* Target description support for GDB. |
2 | ||
6aba47ca | 3 | Copyright (C) 2006, 2007 Free Software Foundation, Inc. |
424163ea DJ |
4 | |
5 | Contributed by CodeSourcery. | |
6 | ||
7 | This file is part of GDB. | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2 of the License, or | |
12 | (at your option) any later version. | |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with this program; if not, write to the Free Software | |
21 | Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
22 | Boston, MA 02110-1301, USA. */ | |
23 | ||
24 | #include "defs.h" | |
25 | #include "arch-utils.h" | |
23181151 | 26 | #include "gdbcmd.h" |
424163ea DJ |
27 | #include "target.h" |
28 | #include "target-descriptions.h" | |
29709017 | 29 | #include "vec.h" |
23181151 | 30 | #include "xml-tdesc.h" |
424163ea DJ |
31 | |
32 | #include "gdb_assert.h" | |
33 | ||
34 | /* Types. */ | |
35 | ||
29709017 DJ |
36 | typedef struct property |
37 | { | |
23181151 DJ |
38 | char *key; |
39 | char *value; | |
29709017 DJ |
40 | } property_s; |
41 | DEF_VEC_O(property_s); | |
42 | ||
424163ea DJ |
43 | struct target_desc |
44 | { | |
23181151 DJ |
45 | /* The architecture reported by the target, if any. */ |
46 | const struct bfd_arch_info *arch; | |
47 | ||
29709017 DJ |
48 | /* Any architecture-specific properties specified by the target. */ |
49 | VEC(property_s) *properties; | |
424163ea DJ |
50 | }; |
51 | ||
52 | /* Global state. These variables are associated with the current | |
53 | target; if GDB adds support for multiple simultaneous targets, then | |
54 | these variables should become target-specific data. */ | |
55 | ||
56 | /* A flag indicating that a description has already been fetched from | |
57 | the current target, so it should not be queried again. */ | |
58 | ||
59 | static int target_desc_fetched; | |
60 | ||
61 | /* The description fetched from the current target, or NULL if the | |
62 | current target did not supply any description. Only valid when | |
63 | target_desc_fetched is set. Only the description initialization | |
64 | code should access this; normally, the description should be | |
65 | accessed through the gdbarch object. */ | |
66 | ||
67 | static const struct target_desc *current_target_desc; | |
68 | ||
23181151 DJ |
69 | /* Other global variables. */ |
70 | ||
71 | /* The filename to read a target description from. */ | |
72 | ||
73 | static char *target_description_filename; | |
74 | ||
424163ea DJ |
75 | /* Fetch the current target's description, and switch the current |
76 | architecture to one which incorporates that description. */ | |
77 | ||
78 | void | |
79 | target_find_description (void) | |
80 | { | |
81 | /* If we've already fetched a description from the target, don't do | |
82 | it again. This allows a target to fetch the description early, | |
83 | during its to_open or to_create_inferior, if it needs extra | |
84 | information about the target to initialize. */ | |
85 | if (target_desc_fetched) | |
86 | return; | |
87 | ||
88 | /* The current architecture should not have any target description | |
89 | specified. It should have been cleared, e.g. when we | |
90 | disconnected from the previous target. */ | |
91 | gdb_assert (gdbarch_target_desc (current_gdbarch) == NULL); | |
92 | ||
23181151 DJ |
93 | /* First try to fetch an XML description from the user-specified |
94 | file. */ | |
95 | current_target_desc = NULL; | |
96 | if (target_description_filename != NULL | |
97 | && *target_description_filename != '\0') | |
98 | current_target_desc | |
99 | = file_read_description_xml (target_description_filename); | |
100 | ||
101 | /* Next try to read the description from the current target using | |
102 | target objects. */ | |
103 | if (current_target_desc == NULL) | |
104 | current_target_desc = target_read_description_xml (¤t_target); | |
105 | ||
106 | /* If that failed try a target-specific hook. */ | |
107 | if (current_target_desc == NULL) | |
108 | current_target_desc = target_read_description (¤t_target); | |
424163ea DJ |
109 | |
110 | /* If a non-NULL description was returned, then update the current | |
111 | architecture. */ | |
112 | if (current_target_desc) | |
113 | { | |
114 | struct gdbarch_info info; | |
115 | ||
116 | gdbarch_info_init (&info); | |
117 | info.target_desc = current_target_desc; | |
118 | if (!gdbarch_update_p (info)) | |
119 | warning (_("Could not use target-supplied description")); | |
120 | } | |
121 | ||
122 | /* Now that we know this description is usable, record that we | |
123 | fetched it. */ | |
124 | target_desc_fetched = 1; | |
125 | } | |
126 | ||
127 | /* Discard any description fetched from the current target, and switch | |
128 | the current architecture to one with no target description. */ | |
129 | ||
130 | void | |
131 | target_clear_description (void) | |
132 | { | |
133 | struct gdbarch_info info; | |
134 | ||
135 | if (!target_desc_fetched) | |
136 | return; | |
137 | ||
138 | target_desc_fetched = 0; | |
139 | current_target_desc = NULL; | |
140 | ||
141 | gdbarch_info_init (&info); | |
142 | if (!gdbarch_update_p (info)) | |
143 | internal_error (__FILE__, __LINE__, | |
144 | _("Could not remove target-supplied description")); | |
145 | } | |
146 | ||
147 | /* Return the global current target description. This should only be | |
148 | used by gdbarch initialization code; most access should be through | |
149 | an existing gdbarch. */ | |
150 | ||
151 | const struct target_desc * | |
152 | target_current_description (void) | |
153 | { | |
154 | if (target_desc_fetched) | |
155 | return current_target_desc; | |
156 | ||
157 | return NULL; | |
158 | } | |
23181151 DJ |
159 | \f |
160 | ||
161 | /* Direct accessors for feature sets. */ | |
424163ea | 162 | |
29709017 DJ |
163 | /* Return the string value of a property named KEY, or NULL if the |
164 | property was not specified. */ | |
165 | ||
166 | const char * | |
167 | tdesc_property (const struct target_desc *target_desc, const char *key) | |
168 | { | |
169 | struct property *prop; | |
170 | int ix; | |
171 | ||
172 | for (ix = 0; VEC_iterate (property_s, target_desc->properties, ix, prop); | |
173 | ix++) | |
174 | if (strcmp (prop->key, key) == 0) | |
175 | return prop->value; | |
176 | ||
177 | return NULL; | |
178 | } | |
179 | ||
23181151 DJ |
180 | /* Return the BFD architecture associated with this target |
181 | description, or NULL if no architecture was specified. */ | |
182 | ||
183 | const struct bfd_arch_info * | |
184 | tdesc_architecture (const struct target_desc *target_desc) | |
185 | { | |
186 | return target_desc->arch; | |
187 | } | |
188 | \f | |
189 | ||
424163ea DJ |
190 | /* Methods for constructing a target description. */ |
191 | ||
192 | struct target_desc * | |
193 | allocate_target_description (void) | |
194 | { | |
195 | return XZALLOC (struct target_desc); | |
196 | } | |
29709017 | 197 | |
23181151 DJ |
198 | static void |
199 | free_target_description (void *arg) | |
200 | { | |
201 | struct target_desc *target_desc = arg; | |
202 | struct property *prop; | |
203 | int ix; | |
204 | ||
205 | for (ix = 0; | |
206 | VEC_iterate (property_s, target_desc->properties, ix, prop); | |
207 | ix++) | |
208 | { | |
209 | xfree (prop->key); | |
210 | xfree (prop->value); | |
211 | } | |
212 | VEC_free (property_s, target_desc->properties); | |
213 | ||
214 | xfree (target_desc); | |
215 | } | |
216 | ||
217 | struct cleanup * | |
218 | make_cleanup_free_target_description (struct target_desc *target_desc) | |
219 | { | |
220 | return make_cleanup (free_target_description, target_desc); | |
221 | } | |
222 | ||
29709017 DJ |
223 | void |
224 | set_tdesc_property (struct target_desc *target_desc, | |
225 | const char *key, const char *value) | |
226 | { | |
227 | struct property *prop, new_prop; | |
228 | int ix; | |
229 | ||
230 | gdb_assert (key != NULL && value != NULL); | |
231 | ||
232 | for (ix = 0; VEC_iterate (property_s, target_desc->properties, ix, prop); | |
233 | ix++) | |
234 | if (strcmp (prop->key, key) == 0) | |
235 | internal_error (__FILE__, __LINE__, | |
236 | _("Attempted to add duplicate property \"%s\""), key); | |
237 | ||
23181151 DJ |
238 | new_prop.key = xstrdup (key); |
239 | new_prop.value = xstrdup (value); | |
29709017 DJ |
240 | VEC_safe_push (property_s, target_desc->properties, &new_prop); |
241 | } | |
23181151 DJ |
242 | |
243 | void | |
244 | set_tdesc_architecture (struct target_desc *target_desc, | |
245 | const struct bfd_arch_info *arch) | |
246 | { | |
247 | target_desc->arch = arch; | |
248 | } | |
249 | \f | |
250 | ||
251 | static struct cmd_list_element *tdesc_set_cmdlist, *tdesc_show_cmdlist; | |
252 | static struct cmd_list_element *tdesc_unset_cmdlist; | |
253 | ||
254 | /* Helper functions for the CLI commands. */ | |
255 | ||
256 | static void | |
257 | set_tdesc_cmd (char *args, int from_tty) | |
258 | { | |
259 | help_list (tdesc_set_cmdlist, "set tdesc ", -1, gdb_stdout); | |
260 | } | |
261 | ||
262 | static void | |
263 | show_tdesc_cmd (char *args, int from_tty) | |
264 | { | |
265 | cmd_show_list (tdesc_show_cmdlist, from_tty, ""); | |
266 | } | |
267 | ||
268 | static void | |
269 | unset_tdesc_cmd (char *args, int from_tty) | |
270 | { | |
271 | help_list (tdesc_unset_cmdlist, "unset tdesc ", -1, gdb_stdout); | |
272 | } | |
273 | ||
274 | static void | |
275 | set_tdesc_filename_cmd (char *args, int from_tty, | |
276 | struct cmd_list_element *c) | |
277 | { | |
278 | target_clear_description (); | |
279 | target_find_description (); | |
280 | } | |
281 | ||
282 | static void | |
283 | show_tdesc_filename_cmd (struct ui_file *file, int from_tty, | |
284 | struct cmd_list_element *c, | |
285 | const char *value) | |
286 | { | |
287 | if (value != NULL && *value != '\0') | |
288 | printf_filtered (_("\ | |
289 | The target description will be read from \"%s\".\n"), | |
290 | value); | |
291 | else | |
292 | printf_filtered (_("\ | |
293 | The target description will be read from the target.\n")); | |
294 | } | |
295 | ||
296 | static void | |
297 | unset_tdesc_filename_cmd (char *args, int from_tty) | |
298 | { | |
299 | xfree (target_description_filename); | |
300 | target_description_filename = NULL; | |
301 | target_clear_description (); | |
302 | target_find_description (); | |
303 | } | |
304 | ||
305 | void | |
306 | _initialize_target_descriptions (void) | |
307 | { | |
308 | add_prefix_cmd ("tdesc", class_maintenance, set_tdesc_cmd, _("\ | |
309 | Set target description specific variables."), | |
310 | &tdesc_set_cmdlist, "set tdesc ", | |
311 | 0 /* allow-unknown */, &setlist); | |
312 | add_prefix_cmd ("tdesc", class_maintenance, show_tdesc_cmd, _("\ | |
313 | Show target description specific variables."), | |
314 | &tdesc_show_cmdlist, "show tdesc ", | |
315 | 0 /* allow-unknown */, &showlist); | |
316 | add_prefix_cmd ("tdesc", class_maintenance, unset_tdesc_cmd, _("\ | |
317 | Unset target description specific variables."), | |
318 | &tdesc_unset_cmdlist, "unset tdesc ", | |
319 | 0 /* allow-unknown */, &unsetlist); | |
320 | ||
321 | add_setshow_filename_cmd ("filename", class_obscure, | |
322 | &target_description_filename, | |
323 | _("\ | |
324 | Set the file to read for an XML target description"), _("\ | |
325 | Show the file to read for an XML target description"), _("\ | |
326 | When set, GDB will read the target description from a local\n\ | |
327 | file instead of querying the remote target."), | |
328 | set_tdesc_filename_cmd, | |
329 | show_tdesc_filename_cmd, | |
330 | &tdesc_set_cmdlist, &tdesc_show_cmdlist); | |
331 | ||
332 | add_cmd ("filename", class_obscure, unset_tdesc_filename_cmd, _("\ | |
333 | Unset the file to read for an XML target description. When unset,\n\ | |
334 | GDB will read the description from the target."), | |
335 | &tdesc_unset_cmdlist); | |
336 | } |