• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

Révision1cd475528393f4c4c01be7c654990d578247295f (tree)
l'heure2006-03-14 22:58:41
AuteurDaniel Jacobowitz <drow@fals...>
CommiterDaniel Jacobowitz

Message de Log

Add RAM caching, checksum, and non-sequential register support.

Change Summary

Modification

--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -609,6 +609,7 @@ gdb_sim_sh_h = $(INCLUDE_DIR)/gdb/sim-sh.h
609609 splay_tree_h = $(INCLUDE_DIR)/splay-tree.h
610610 safe_ctype_h = $(INCLUDE_DIR)/safe-ctype.h
611611 hashtab_h = $(INCLUDE_DIR)/hashtab.h
612+filenames_h = $(INCLUDE_DIR)/filenames.h
612613
613614 #
614615 # $BUILD/ headers
@@ -1794,8 +1795,8 @@ auxv.o: auxv.c $(defs_h) $(target_h) $(gdbtypes_h) $(command_h) \
17941795 $(inferior_h) $(valprint_h) $(gdb_assert_h) $(auxv_h) \
17951796 $(elf_common_h)
17961797 available.o: available.c $(defs_h) $(symfile_h) $(target_h) $(available_h) \
1797- $(arch_utils_h) $(gdbtypes_h) \
1798- $(gdb_string) $(gdb_assert) $(gdb_obstack_h)
1798+ $(arch_utils_h) $(gdbtypes_h) $(sha1_h) \
1799+ $(gdb_string) $(gdb_assert) $(gdb_obstack_h) $(gdb_stdint_h)
17991800 avr-tdep.o: avr-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
18001801 $(frame_base_h) $(trad_frame_h) $(gdbcmd_h) $(gdbcore_h) \
18011802 $(inferior_h) $(symfile_h) $(arch_utils_h) $(regcache_h) \
@@ -2410,8 +2411,8 @@ parse.o: parse.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
24102411 $(frame_h) $(expression_h) $(value_h) $(command_h) $(language_h) \
24112412 $(parser_defs_h) $(gdbcmd_h) $(symfile_h) $(inferior_h) \
24122413 $(doublest_h) $(gdb_assert_h) $(block_h)
2413-parse-avail.o: parse-avail.c $(defs_h) $(available_h) \
2414- $(gdb_string) $(gdb_obstack_h)
2414+parse-avail.o: parse-avail.c $(defs_h) $(available_h) $(gdb_assert_h) \
2415+ $(filenames_h) $(gdb_string) $(gdb_obstack_h)
24152416 p-exp.o: p-exp.c $(defs_h) $(gdb_string_h) $(expression_h) $(value_h) \
24162417 $(parser_defs_h) $(language_h) $(p_lang_h) $(bfd_h) $(symfile_h) \
24172418 $(objfiles_h) $(block_h)
--- a/gdb/available.c
+++ b/gdb/available.c
@@ -27,12 +27,14 @@
2727 #include "gdbtypes.h"
2828 #include "symfile.h"
2929 #include "target.h"
30+#include "sha1.h"
3031
3132 #include "available.h"
3233
3334 #include "gdb_assert.h"
3435 #include "gdb_string.h"
3536 #include "gdb_obstack.h"
37+#include "gdb_stdint.h"
3638
3739 /* TODO: Remote target "guess" features from g packet size */
3840
@@ -53,26 +55,184 @@
5355 to initialize a gdbarch, which leads to later failures when we expect
5456 e.g. current_regcache to have been initialized. */
5557
58+
59+
60+/* Support for caching XML objects read from the target.
61+
62+ TODO ITEMS:
63+ - Support caching to disk.
64+ - Support compiled-in feature cache.
65+ - Figure out memory management for feature contents strings.
66+*/
67+
68+
69+/* Saved information about cached XML objects. Each cache entry
70+ corresponds to a file in the cache, or an object fetched from
71+ the target with one particular annex. */
72+
73+struct xml_cache_entry
74+{
75+ const char *annex;
76+ const char *contents;
77+
78+ union
79+ {
80+ /* We use a union to represent the checksum in order to guarantee
81+ sufficient alignment. */
82+ uint32_t words[5];
83+ unsigned char bytes[20];
84+ } sha1sum;
85+
86+ struct xml_cache_entry *next;
87+};
88+
89+/* A list of all the cached objects. */
90+
91+static struct xml_cache_entry *xml_global_cache;
92+
93+/* Look for a feature in the cache with ANNEX and CHECKSUM. If no
94+ entry is found, return NULL. */
95+
96+static const char *
97+find_xml_feature_in_cache (const char *annex, const unsigned char *checksum)
98+{
99+ struct xml_cache_entry *ent;
100+
101+ for (ent = xml_global_cache; ent != NULL; ent = ent->next)
102+ {
103+ if (strcmp (ent->annex, annex) != 0)
104+ continue;
105+ if (memcmp (ent->sha1sum.bytes, checksum, 20) != 0)
106+ continue;
107+
108+ return ent->contents;
109+ }
110+
111+ return NULL;
112+}
113+
114+/* Add CONTENTS, which represents the object named ANNEX, to the
115+ cache if it is not already cached. */
116+
117+static void
118+add_xml_feature_to_cache (const char *annex, const char *contents)
119+{
120+ struct xml_cache_entry new_ent;
121+
122+ /* FIXME: Again, memory allocation? */
123+ new_ent.annex = xstrdup (annex);
124+ new_ent.contents = xstrdup (contents);
125+
126+ sha1_buffer (new_ent.contents, strlen (new_ent.contents),
127+ new_ent.sha1sum.bytes);
128+
129+ /* If this entry is already in the cache, do not add it again. */
130+ if (find_xml_feature_in_cache (annex, new_ent.sha1sum.bytes))
131+ return;
132+
133+ new_ent.next = xml_global_cache;
134+
135+ xml_global_cache = xmalloc (sizeof (struct xml_cache_entry));
136+ memcpy (xml_global_cache, &new_ent, sizeof (struct xml_cache_entry));
137+}
138+
139+/* Convert an ASCII checksum string, CHECKSUM, to a binary blob,
140+ BYTES. Returns 0 for success, or -1 if a bad character is
141+ encountered. CHECKSUM does not need to be NUL terminated. */
142+
143+static int
144+checksum_to_bytes (char *checksum, unsigned char *bytes)
145+{
146+ int i;
147+
148+ for (i = 0; i < 20; i++)
149+ {
150+ int n;
151+ char c1, c2;
152+
153+ c1 = checksum[2 * i];
154+ if (c1 >= '0' && c1 <= '9')
155+ n = c1 - '0';
156+ else if (c1 >= 'a' && c1 <= 'f')
157+ n = c1 - 'a' + 10;
158+ else if (c1 >= 'A' && c1 <= 'F')
159+ n = c1 - 'A' + 10;
160+ else
161+ return -1;
162+
163+ n *= 16;
164+
165+ c2 = checksum[2 * i + 1];
166+ if (c2 >= '0' && c2 <= '9')
167+ n += c2 - '0';
168+ else if (c2 >= 'a' && c2 <= 'f')
169+ n += c2 - 'a' + 10;
170+ else if (c2 >= 'A' && c2 <= 'F')
171+ n += c2 - 'A' + 10;
172+ else
173+ return -1;
174+
175+ bytes[i] = n;
176+ }
177+
178+ return 0;
179+}
180+
181+/* Baton passed to fetch_available_features_from_target. */
182+
183+struct fetch_features_baton
184+{
185+ struct target_ops *ops;
186+
187+ struct fetch_features_checksum
188+ {
189+ const char *annex;
190+ unsigned char checksum[20];
191+ } *checksums;
192+};
193+
56194 /* Read a string representation of available features from the target,
57195 using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
58- malloc allocated and NUL-terminated. If NAME is NULL, the overall
59- feature set is read; otherwise the specified name is read (e.g.
60- resolving xi:include). */
196+ malloc allocated and NUL-terminated. NAME should be a non-NULL
197+ string identifying the XML document we want; the top level document
198+ is "target.xml". Other calls may be performed for the DTD or
199+ for xi:include. */
61200
62201 static char *
63-fetch_available_features_from_target (const char *name, void *ops_)
202+fetch_available_features_from_target (const char *name, void *baton_)
64203 {
65- struct target_ops *ops = ops_;
204+ struct fetch_features_baton *baton = baton_;
66205 char *features_str;
67206 gdb_byte *features_buf;
68207 LONGEST len;
69208
70- struct gdb_feature_set *features;
71- struct gdb_available_feature **slot;
72- int ret;
209+ if (baton->checksums)
210+ {
211+ struct fetch_features_checksum *checksum_ent;
73212
74- len = target_read_whole (ops, TARGET_OBJECT_AVAILABLE_FEATURES,
75- NULL, &features_buf);
213+ for (checksum_ent = baton->checksums;
214+ checksum_ent->annex != NULL;
215+ checksum_ent++)
216+ if (strcmp (checksum_ent->annex, name) == 0)
217+ break;
218+
219+ if (checksum_ent)
220+ {
221+ const char *cached_str;
222+
223+ cached_str = find_xml_feature_in_cache (name,
224+ checksum_ent->checksum);
225+
226+ /* This function always returns something which the caller is
227+ responsible for freeing. So, if we got a match, return a
228+ copy of it. */
229+ if (cached_str)
230+ return xstrdup (cached_str);
231+ }
232+ }
233+
234+ len = target_read_whole (baton->ops, TARGET_OBJECT_AVAILABLE_FEATURES,
235+ name, &features_buf);
76236 if (len <= 0)
77237 return NULL;
78238
@@ -85,6 +245,9 @@ fetch_available_features_from_target (const char *name, void *ops_)
85245 features_str[len] = '\0';
86246 }
87247
248+ if (baton->checksums)
249+ add_xml_feature_to_cache (name, features_str);
250+
88251 return features_str;
89252 }
90253
@@ -92,25 +255,120 @@ fetch_available_features_from_target (const char *name, void *ops_)
92255 to a binary representation. The string representation is fetched using
93256 TARGET_OBJECT_AVAILABLE_FEATURES. */
94257
258+/* TODO: Document \n conventions */
259+
95260 struct gdb_feature_set *
96261 available_features_from_target_object (struct target_ops *ops,
97262 struct obstack *obstack)
98263 {
264+ struct fetch_features_baton baton;
99265 struct gdb_feature_set *features;
100- char *features_str, *cur;
101- gdb_byte *features_buf;
102- LONGEST len;
103- struct gdb_available_feature **slot;
266+ char *features_str, *checksums_str;
104267 int ret;
268+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
269+
270+ /* Initialize the baton. */
271+ baton.ops = ops;
272+ baton.checksums = NULL;
273+
274+ /* Attempt to read checksums from the target. */
275+ checksums_str = fetch_available_features_from_target ("CHECKSUMS", &baton);
276+ if (checksums_str)
277+ {
278+ char *p;
279+ int n_checksums;
280+
281+ make_cleanup (xfree, checksums_str);
282+
283+ /* Allow for one checksum in case there is no trailing newline,
284+ and one to serve as a NULL terminator. */
285+ n_checksums = 2;
286+
287+ /* Allocate one additional checksum per newline. */
288+ for (p = checksums_str; *p; p++)
289+ if (*p == '\n')
290+ n_checksums++;
105291
106- features_str = fetch_available_features_from_target (NULL, ops);
292+ baton.checksums = xmalloc (n_checksums
293+ * sizeof (struct fetch_features_checksum));
294+ make_cleanup (xfree, baton.checksums);
295+
296+ n_checksums = 0;
297+ p = checksums_str;
298+ while (*p)
299+ {
300+ char *field_end;
301+
302+ /* Find the first space on the line, marking the end of the
303+ checksum. */
304+ field_end = p;
305+ while (*field_end && *field_end != '\n'
306+ && *field_end != ' ')
307+ field_end++;
308+
309+ /* Check for a malformed checksum. */
310+ if (*field_end != ' '
311+ || field_end - p != 40
312+ || checksum_to_bytes (p, baton.checksums[n_checksums].checksum))
313+ {
314+ /* Skip this line. */
315+ p = field_end;
316+ while (*p && *p != '\n')
317+ p++;
318+ if (*p == '\n')
319+ p++;
320+ continue;
321+ }
322+
323+ *field_end = '\0';
324+
325+ /* Skip whitespace after the checksum. */
326+ p = field_end + 1;
327+ while (*p == ' ')
328+ p++;
329+
330+ field_end = p;
331+ while (*field_end && *field_end != '\n')
332+ field_end++;
333+
334+ if (field_end == p)
335+ {
336+ /* Malformed line; skip it. */
337+ if (*p == '\n')
338+ p++;
339+ continue;
340+ }
341+
342+ baton.checksums[n_checksums++].annex = p;
343+
344+ /* Advance to the next line, inserting a NUL for the end of
345+ the annex name if necessary. */
346+ if (*field_end)
347+ {
348+ *field_end = '\0';
349+ p = field_end + 1;
350+ }
351+ else
352+ break;
353+ }
354+
355+ baton.checksums[n_checksums].annex = NULL;
356+ }
357+
358+ /* FIXME: Memory management: what happens to features_str? */
359+
360+ features_str = fetch_available_features_from_target ("target.xml", &baton);
361+ if (features_str == NULL)
362+ return NULL;
107363
108364 features = OBSTACK_ZALLOC (obstack, struct gdb_feature_set);
109365 features->obstack = obstack;
110366 ret = available_features_from_xml_string (&features->features, obstack,
111367 features_str,
112368 fetch_available_features_from_target,
113- ops, 0);
369+ &baton, 0);
370+
371+ do_cleanups (back_to);
114372
115373 if (ret < 0)
116374 {
--- a/gdb/available.h
+++ b/gdb/available.h
@@ -83,7 +83,7 @@ struct gdb_available_register
8383 /* The protocol number used by this target to provide this
8484 feature. For instance, the register number used for remote
8585 p/P packets to access this register. */
86- int protocol_number;
86+ long protocol_number;
8787
8888 /* Data private to the architecture associated with this feature.
8989 This is a NUL-terminated string. */
@@ -158,7 +158,6 @@ const char *available_register_name (struct gdbarch *, int);
158158
159159 int available_register_target_regnum (struct gdbarch *, int);
160160
161-
162161 /* Internal routines shared by available.c and parse-avail.c. */
163162
164163 typedef char *(*xml_fetch_another) (const char *, void *);
--- /dev/null
+++ b/gdb/features/feature_to_c.sh
@@ -0,0 +1,37 @@
1+#!/bin/sh
2+
3+input=$1
4+output=$2
5+
6+if test -z "$input" || test -z "$output"; then
7+ echo "Usage: $0 INPUTFILE OUTPUTFILE"
8+ exit 1
9+fi
10+
11+arrayname=xml_feature_`basename $input | sed 's/\..*//g; s/-/_/g'`
12+
13+gawk 'BEGIN { n = 0
14+ print "const char '$arrayname'[] = {"
15+ for (i = 0; i < 255; i++)
16+ _ord_[sprintf("%c", i)] = i
17+} {
18+ split($0, line, "");
19+ printf " "
20+ for (i = 1; i <= length(line); i++) {
21+ c = line[i]
22+ if (c == "'\''") {
23+ printf "'\''\\'\'''\'', "
24+ } else if (c == "\\") {
25+ printf "'\''\\\\'\'', "
26+ } else if (match (c, "[[:print:]]") != 0) {
27+ printf "'\''" c "'\'', "
28+ } else {
29+ printf "'\''\\%03o'\'', ", _ord_[c]
30+ }
31+ if (i % 10 == 0)
32+ printf "\n "
33+ }
34+ printf "'\''\\n'\'', \n"
35+} END {
36+ print " 0 };"
37+}' < $input > $output
--- a/gdb/features/gdb-target.dtd
+++ b/gdb/features/gdb-target.dtd
@@ -30,15 +30,18 @@
3030
3131 <!-- TODO: GDB does not yet support descriptions. -->
3232
33-<!-- Registers do not have an explicit register number field; they
34- are numbered sequentially from the containing feature's base-regnum
35- when the feature is referenced. -->
33+<!-- Registers are not required to have an explicit register number field;
34+ they are numbered sequentially starting at zero. If a register does
35+ have an explicit number, the next register will be assigned the next
36+ sequential number by default. When the feature is referenced, register
37+ numbers are adjusted by the reference's base-regnum. -->
3638 <!-- arch_data; see above -->
3739 <!-- Kill save-restore in favor of a more complete scheme -->
3840 <!ELEMENT reg (description*)>
3941 <!ATTLIST reg
4042 name CDATA #REQUIRED
4143 bitsize CDATA #REQUIRED
44+ regnum CDATA #IMPLIED
4245 readonly (yes | no) 'no'
4346 save-restore (yes | no) 'yes'
4447 type CDATA 'int'
--- a/gdb/parse-avail.c
+++ b/gdb/parse-avail.c
@@ -328,6 +328,7 @@ xml_start_reg (struct xml_feature_parse_data *data,
328328 sizeof (struct gdb_available_register));
329329 memset (reg, 0, sizeof (struct gdb_available_register));
330330
331+ reg->protocol_number = -1;
331332 reg->bitsize = -1;
332333 reg->readonly = -1;
333334 reg->save_restore = -1;
@@ -343,6 +344,12 @@ xml_start_reg (struct xml_feature_parse_data *data,
343344 else if (strcmp (name, "name") == 0)
344345 reg->name = obstrdup (data->obstack, val);
345346
347+ else if (strcmp (name, "regnum") == 0)
348+ {
349+ if (xml_parse_one_integer (val, &reg->protocol_number) < 0)
350+ data->unhandled++;
351+ }
352+
346353 else if (strcmp (name, "bitsize") == 0)
347354 {
348355 if (xml_parse_one_integer (val, &reg->bitsize) < 0)
@@ -457,10 +464,8 @@ xml_start_feature_ref (struct xml_feature_parse_data *data,
457464 }
458465
459466 /* Set register numbers in the new feature. */
460- for (i = new_feature->protocol_number, reg = new_feature->registers;
461- reg != NULL;
462- i++, reg = reg->next)
463- reg->protocol_number = i;
467+ for (reg = new_feature->registers; reg != NULL; reg = reg->next)
468+ reg->protocol_number += new_feature->protocol_number;
464469
465470 new_feature->next = data->target_features;
466471 data->target_features = new_feature;
@@ -682,10 +687,11 @@ xml_feature_end_element (void *data_, const XML_Char *name)
682687 feature->next = data->seen_features;
683688 data->seen_features = feature;
684689
685- /* Reverse the list of registers. */
686690 if (feature->registers)
687691 {
692+ /* Reverse the list of registers. */
688693 struct gdb_available_register *reg1, *reg2, *reg3;
694+ int next;
689695
690696 reg1 = NULL;
691697 reg2 = feature->registers;
@@ -699,6 +705,13 @@ xml_feature_end_element (void *data_, const XML_Char *name)
699705 }
700706
701707 feature->registers = reg1;
708+
709+ next = 0;
710+ for (reg1 = feature->registers; reg1; reg1 = reg1->next)
711+ if (reg1->protocol_number == -1)
712+ reg1->protocol_number = next++;
713+ else
714+ next = reg1->protocol_number + 1;
702715 }
703716
704717 break;
@@ -765,14 +778,15 @@ xml_parser_cleanup (void *parser)
765778 struct xml_feature_parse_data *data;
766779
767780 data = XML_GetUserData (parser);
768- while (data->state)
769- {
770- struct xml_state_stack *prev;
781+ if (data)
782+ while (data->state)
783+ {
784+ struct xml_state_stack *prev;
771785
772- prev = data->state->prev;
773- xfree (data->state);
774- data->state = prev;
775- }
786+ prev = data->state->prev;
787+ xfree (data->state);
788+ data->state = prev;
789+ }
776790
777791 XML_ParserFree (parser);
778792 }
@@ -801,6 +815,7 @@ xml_feature_external_entity (XML_Parser parser,
801815 back_to = make_cleanup (xml_parser_cleanup, entity_parser);
802816
803817 XML_SetElementHandler (entity_parser, NULL, NULL);
818+ XML_SetUserData (entity_parser, NULL);
804819
805820 if (XML_Parse (entity_parser, text, strlen (text), 1) != XML_STATUS_OK)
806821 {