Set dynamic tag VMA and size from dynamic section when possible
[external/binutils.git] / gdb / tid-parse.c
1 /* TID parsing for GDB, the GNU debugger.
2
3    Copyright (C) 2015-2016 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "tid-parse.h"
22 #include "inferior.h"
23 #include "gdbthread.h"
24 #include <ctype.h>
25
26 /* See tid-parse.h.  */
27
28 void ATTRIBUTE_NORETURN
29 invalid_thread_id_error (const char *string)
30 {
31   error (_("Invalid thread ID: %s"), string);
32 }
33
34 /* Wrapper for get_number_trailer that throws an error if we get back
35    a negative number.  We'll see a negative value if the number is
36    stored in a negative convenience variable (e.g., $minus_one = -1).
37    STRING is the parser string to be used in the error message if we
38    do get back a negative number.  */
39
40 static int
41 get_positive_number_trailer (const char **pp, int trailer, const char *string)
42 {
43   int num;
44
45   num = get_number_trailer (pp, trailer);
46   if (num < 0)
47     error (_("negative value: %s"), string);
48   return num;
49 }
50
51 /* See tid-parse.h.  */
52
53 struct thread_info *
54 parse_thread_id (const char *tidstr, const char **end)
55 {
56   const char *number = tidstr;
57   const char *dot, *p1;
58   struct thread_info *tp;
59   struct inferior *inf;
60   int thr_num;
61   int explicit_inf_id = 0;
62
63   dot = strchr (number, '.');
64
65   if (dot != NULL)
66     {
67       /* Parse number to the left of the dot.  */
68       int inf_num;
69
70       p1 = number;
71       inf_num = get_positive_number_trailer (&p1, '.', number);
72       if (inf_num == 0)
73         invalid_thread_id_error (number);
74
75       inf = find_inferior_id (inf_num);
76       if (inf == NULL)
77         error (_("No inferior number '%d'"), inf_num);
78
79       explicit_inf_id = 1;
80       p1 = dot + 1;
81     }
82   else
83     {
84       inf = current_inferior ();
85
86       p1 = number;
87     }
88
89   thr_num = get_positive_number_trailer (&p1, 0, number);
90   if (thr_num == 0)
91     invalid_thread_id_error (number);
92
93   ALL_THREADS (tp)
94     {
95       if (ptid_get_pid (tp->ptid) == inf->pid
96           && tp->per_inf_num == thr_num)
97         break;
98     }
99
100   if (tp == NULL)
101     {
102       if (show_inferior_qualified_tids () || explicit_inf_id)
103         error (_("Unknown thread %d.%d."), inf->num, thr_num);
104       else
105         error (_("Unknown thread %d."), thr_num);
106     }
107
108   if (end != NULL)
109     *end = p1;
110
111   return tp;
112 }
113
114 /* See tid-parse.h.  */
115
116 void
117 tid_range_parser_init (struct tid_range_parser *parser, const char *tidlist,
118                        int default_inferior)
119 {
120   parser->state = TID_RANGE_STATE_INFERIOR;
121   parser->string = tidlist;
122   parser->inf_num = 0;
123   parser->qualified = 0;
124   parser->default_inferior = default_inferior;
125 }
126
127 /* See tid-parse.h.  */
128
129 int
130 tid_range_parser_finished (struct tid_range_parser *parser)
131 {
132   switch (parser->state)
133     {
134     case TID_RANGE_STATE_INFERIOR:
135       return *parser->string == '\0';
136     case TID_RANGE_STATE_THREAD_RANGE:
137     case TID_RANGE_STATE_STAR_RANGE:
138       return parser->range_parser.finished;
139     }
140
141   gdb_assert_not_reached (_("unhandled state"));
142 }
143
144 /* See tid-parse.h.  */
145
146 const char *
147 tid_range_parser_string (struct tid_range_parser *parser)
148 {
149   switch (parser->state)
150     {
151     case TID_RANGE_STATE_INFERIOR:
152       return parser->string;
153     case TID_RANGE_STATE_THREAD_RANGE:
154     case TID_RANGE_STATE_STAR_RANGE:
155       return parser->range_parser.string;
156     }
157
158   gdb_assert_not_reached (_("unhandled state"));
159 }
160
161 /* See tid-parse.h.  */
162
163 void
164 tid_range_parser_skip (struct tid_range_parser *parser)
165 {
166   gdb_assert ((parser->state == TID_RANGE_STATE_THREAD_RANGE
167                || parser->state == TID_RANGE_STATE_STAR_RANGE)
168               && parser->range_parser.in_range);
169
170   tid_range_parser_init (parser, parser->range_parser.end_ptr,
171                          parser->default_inferior);
172 }
173
174 /* See tid-parse.h.  */
175
176 int
177 tid_range_parser_qualified (struct tid_range_parser *parser)
178 {
179   return parser->qualified;
180 }
181
182 /* Helper for tid_range_parser_get_tid and
183    tid_range_parser_get_tid_range.  Return the next range if THR_END
184    is non-NULL, return a single thread ID otherwise.  */
185
186 static int
187 get_tid_or_range (struct tid_range_parser *parser, int *inf_num,
188                   int *thr_start, int *thr_end)
189 {
190   if (parser->state == TID_RANGE_STATE_INFERIOR)
191     {
192       const char *p;
193       const char *space;
194
195       space = skip_to_space (parser->string);
196
197       p = parser->string;
198       while (p < space && *p != '.')
199         p++;
200       if (p < space)
201         {
202           const char *dot = p;
203
204           /* Parse number to the left of the dot.  */
205           p = parser->string;
206           parser->inf_num
207             = get_positive_number_trailer (&p, '.', parser->string);
208           if (parser->inf_num == 0)
209             return 0;
210
211           parser->qualified = 1;
212           p = dot + 1;
213
214           if (isspace (*p))
215             return 0;
216         }
217       else
218         {
219           parser->inf_num = parser->default_inferior;
220           parser->qualified = 0;
221           p = parser->string;
222         }
223
224       init_number_or_range (&parser->range_parser, p);
225       if (p[0] == '*' && (p[1] == '\0' || isspace (p[1])))
226         {
227           /* Setup the number range parser to return numbers in the
228              whole [1,INT_MAX] range.  */
229           number_range_setup_range (&parser->range_parser, 1, INT_MAX,
230                                     skip_spaces_const (p + 1));
231           parser->state = TID_RANGE_STATE_STAR_RANGE;
232         }
233       else
234         parser->state = TID_RANGE_STATE_THREAD_RANGE;
235     }
236
237   *inf_num = parser->inf_num;
238   *thr_start = get_number_or_range (&parser->range_parser);
239   if (*thr_start < 0)
240     error (_("negative value: %s"), parser->string);
241   if (*thr_start == 0)
242     {
243       parser->state = TID_RANGE_STATE_INFERIOR;
244       return 0;
245     }
246
247   /* If we successfully parsed a thread number or finished parsing a
248      thread range, switch back to assuming the next TID is
249      inferior-qualified.  */
250   if (parser->range_parser.end_ptr == NULL
251       || parser->range_parser.string == parser->range_parser.end_ptr)
252     {
253       parser->state = TID_RANGE_STATE_INFERIOR;
254       parser->string = parser->range_parser.string;
255
256       if (thr_end != NULL)
257         *thr_end = *thr_start;
258     }
259
260   /* If we're midway through a range, and the caller wants the end
261      value, return it and skip to the end of the range.  */
262   if (thr_end != NULL
263       && (parser->state == TID_RANGE_STATE_THREAD_RANGE
264           || parser->state == TID_RANGE_STATE_STAR_RANGE))
265     {
266       *thr_end = parser->range_parser.end_value;
267       tid_range_parser_skip (parser);
268     }
269
270   return (*inf_num != 0 && *thr_start != 0);
271 }
272
273 /* See tid-parse.h.  */
274
275 int
276 tid_range_parser_get_tid_range (struct tid_range_parser *parser, int *inf_num,
277                                 int *thr_start, int *thr_end)
278 {
279   gdb_assert (inf_num != NULL && thr_start != NULL && thr_end != NULL);
280
281   return get_tid_or_range (parser, inf_num, thr_start, thr_end);
282 }
283
284 /* See tid-parse.h.  */
285
286 int
287 tid_range_parser_get_tid (struct tid_range_parser *parser,
288                           int *inf_num, int *thr_num)
289 {
290   gdb_assert (inf_num != NULL && thr_num != NULL);
291
292   return get_tid_or_range (parser, inf_num, thr_num, NULL);
293 }
294
295 /* See tid-parse.h.  */
296
297 int
298 tid_range_parser_star_range (struct tid_range_parser *parser)
299 {
300   return parser->state == TID_RANGE_STATE_STAR_RANGE;
301 }
302
303 /* See gdbthread.h.  */
304
305 int
306 tid_is_in_list (const char *list, int default_inferior,
307                 int inf_num, int thr_num)
308 {
309   struct tid_range_parser parser;
310
311   if (list == NULL || *list == '\0')
312     return 1;
313
314   tid_range_parser_init (&parser, list, default_inferior);
315   while (!tid_range_parser_finished (&parser))
316     {
317       int tmp_inf, tmp_thr_start, tmp_thr_end;
318
319       if (!tid_range_parser_get_tid_range (&parser, &tmp_inf,
320                                            &tmp_thr_start, &tmp_thr_end))
321         invalid_thread_id_error (parser.string);
322       if (tmp_inf == inf_num
323           && tmp_thr_start <= thr_num && thr_num <= tmp_thr_end)
324         return 1;
325     }
326   return 0;
327 }