Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: gdb/python/py-linetable.c

Issue 124383005: GDB 7.6.50 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@upstream
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gdb/python/py-lazy-string.c ('k') | gdb/python/py-newobjfileevent.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Python interface to line tables.
2
3 Copyright (C) 2013 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 "python-internal.h"
22 #include "exceptions.h"
23
24 typedef struct {
25 PyObject_HEAD
26 /* The line table source line. */
27 int line;
28 /* The pc associated with the source line. */
29 CORE_ADDR pc;
30 } linetable_entry_object;
31
32 static PyTypeObject linetable_entry_object_type
33 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_entry_object");
34
35 typedef struct {
36 PyObject_HEAD
37 /* The symtab python object. We store the Python object here as the
38 underlying symtab can become invalid, and we have to run validity
39 checks on it. */
40 PyObject *symtab;
41 } linetable_object;
42
43 static PyTypeObject linetable_object_type
44 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("linetable_object");
45
46 typedef struct {
47 PyObject_HEAD
48 /* The current entry in the line table for the iterator */
49 int current_index;
50 /* Pointer back to the original source line table object. Needed to
51 check if the line table is still valid, and has not been invalidated
52 when an object file has been freed. */
53 PyObject *source;
54 } ltpy_iterator_object;
55
56 static PyTypeObject ltpy_iterator_object_type
57 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("ltpy_iterator_object");
58
59 /* Internal helper function to extract gdb.Symtab from a gdb.Linetable
60 object. */
61
62 static PyObject *
63 get_symtab (PyObject *linetable)
64 {
65 linetable_object *lt = (linetable_object *) linetable;
66
67 return lt->symtab;
68 }
69
70 #define LTPY_REQUIRE_VALID(lt_obj, symtab) \
71 do { \
72 symtab = symtab_object_to_symtab (get_symtab (lt_obj)); \
73 if (symtab == NULL) \
74 { \
75 PyErr_SetString (PyExc_RuntimeError, \
76 _("Symbol Table in line table is invalid."));\
77 return NULL; \
78 } \
79 } while (0)
80
81
82 /* Helper function to create a line table object that wraps a
83 gdb.Symtab object. */
84
85 PyObject *
86 symtab_to_linetable_object (PyObject *symtab)
87 {
88 linetable_object *ltable;
89
90 ltable = PyObject_New (linetable_object, &linetable_object_type);
91 if (ltable != NULL)
92 {
93 ltable->symtab = symtab;
94 Py_INCREF (symtab);
95 }
96 return (PyObject *) ltable;
97 }
98
99 /* Internal helper function to build a line table object from a line
100 and an address. */
101
102 static PyObject *
103 build_linetable_entry (int line, CORE_ADDR address)
104 {
105 linetable_entry_object *obj;
106
107 obj = PyObject_New (linetable_entry_object,
108 &linetable_entry_object_type);
109 if (obj != NULL)
110 {
111 obj->line = line;
112 obj->pc = address;
113 }
114
115 return (PyObject *) obj;
116 }
117
118 /* Internal helper function to build a Python Tuple from a GDB Vector.
119 A line table entry can have multiple PCs for a given source line.
120 Construct a Tuple of all entries for the given source line, LINE
121 from the line table VEC. Construct one line table entry object per
122 address. */
123
124 static PyObject *
125 build_line_table_tuple_from_pcs (int line, VEC (CORE_ADDR) *vec)
126 {
127 int vec_len = 0;
128 PyObject *tuple;
129 CORE_ADDR pc;
130 int i;
131
132 vec_len = VEC_length (CORE_ADDR, vec);
133 if (vec_len < 1)
134 Py_RETURN_NONE;
135
136 tuple = PyTuple_New (vec_len);
137
138 if (tuple == NULL)
139 return NULL;
140
141 for (i = 0; VEC_iterate (CORE_ADDR, vec, i, pc); ++i)
142 {
143 PyObject *obj = build_linetable_entry (line, pc);
144
145 if (obj == NULL)
146 {
147 Py_DECREF (tuple);
148 tuple = NULL;
149 break;
150 }
151 else if (PyTuple_SetItem (tuple, i, obj) != 0)
152 {
153 Py_DECREF (obj);
154 Py_DECREF (tuple);
155 tuple = NULL;
156 break;
157 }
158 }
159
160 return tuple;
161 }
162
163 /* Implementation of gdb.LineTable.line (self) -> Tuple. Returns a
164 tuple of LineTableEntry objects associated with this line from the
165 in the line table. */
166
167 static PyObject *
168 ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
169 {
170 struct symtab *symtab;
171 int py_line;
172 struct linetable_entry *best_entry = NULL;
173 linetable_entry_object *result;
174 VEC (CORE_ADDR) *pcs = NULL;
175 PyObject *tuple;
176 volatile struct gdb_exception except;
177
178 LTPY_REQUIRE_VALID (self, symtab);
179
180 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
181 return NULL;
182
183 TRY_CATCH (except, RETURN_MASK_ALL)
184 {
185 pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
186 }
187 GDB_PY_HANDLE_EXCEPTION (except);
188
189 tuple = build_line_table_tuple_from_pcs (py_line, pcs);
190 VEC_free (CORE_ADDR, pcs);
191
192 return tuple;
193 }
194
195 /* Implementation of gdb.LineTable.has_line (self, line) -> Boolean.
196 Returns a Python Boolean indicating whether a source line has any
197 line table entries corresponding to it. */
198
199 static PyObject *
200 ltpy_has_line (PyObject *self, PyObject *args)
201 {
202 struct symtab *symtab;
203 int py_line;
204 int index;
205
206 LTPY_REQUIRE_VALID (self, symtab);
207
208 if (! PyArg_ParseTuple (args, GDB_PY_LL_ARG, &py_line))
209 return NULL;
210
211 if (LINETABLE (symtab) == NULL)
212 {
213 PyErr_SetString (PyExc_RuntimeError,
214 _("Linetable information not found in symbol table"));
215 return NULL;
216 }
217
218 for (index = 0; index < LINETABLE (symtab)->nitems; index++)
219 {
220 struct linetable_entry *item = &(symtab->linetable->item[index]);
221 if (item->line == py_line)
222 Py_RETURN_TRUE;
223 }
224
225 Py_RETURN_FALSE;
226 }
227
228 /* Implementation of gdb.LineTable.source_lines (self) -> FrozenSet.
229 Returns a Python FrozenSet that contains source line entries in the
230 line table. This function will just return the source lines
231 without corresponding addresses. */
232
233 static PyObject *
234 ltpy_get_all_source_lines (PyObject *self, PyObject *args)
235 {
236 struct symtab *symtab;
237 Py_ssize_t index;
238 PyObject *source_list, *source_dict, *line;
239 struct linetable_entry *item;
240 Py_ssize_t list_size;
241
242 LTPY_REQUIRE_VALID (self, symtab);
243
244 if (LINETABLE (symtab) == NULL)
245 {
246 PyErr_SetString (PyExc_RuntimeError,
247 _("Linetable information not found in symbol table"));
248 return NULL;
249 }
250
251 source_dict = PyDict_New ();
252 if (source_dict == NULL)
253 return NULL;
254
255 for (index = 0; index < LINETABLE (symtab)->nitems; index++)
256 {
257 item = &(LINETABLE (symtab)->item[index]);
258
259 /* 0 is used to signify end of line table information. Do not
260 include in the source set. */
261 if (item->line > 0)
262 {
263 line = gdb_py_object_from_longest (item->line);
264
265 if (line == NULL)
266 {
267 Py_DECREF (source_dict);
268 return NULL;
269 }
270
271 if (PyDict_SetItem (source_dict, line, Py_None) == -1)
272 {
273 Py_DECREF (line);
274 Py_DECREF (source_dict);
275 return NULL;
276 }
277
278 Py_DECREF (line);
279 }
280 }
281
282
283 source_list = PyDict_Keys (source_dict);
284 Py_DECREF (source_dict);
285
286 return source_list;
287 }
288
289 /* Implementation of gdb.Linetable.is_valid (self) -> Boolean.
290 Returns True if this line table object still exists in GDB. */
291
292 static PyObject *
293 ltpy_is_valid (PyObject *self, PyObject *args)
294 {
295 struct symtab *symtab = NULL;
296 linetable_object *obj = (linetable_object *) self;
297
298 symtab = symtab_object_to_symtab (get_symtab (self));
299
300 if (symtab == NULL)
301 Py_RETURN_FALSE;
302
303 Py_RETURN_TRUE;
304 }
305
306 /* Deconstructor for the line table object. Decrement the reference
307 to the symbol table object before calling the default free. */
308
309 static void
310 ltpy_dealloc (PyObject *self)
311 {
312 linetable_object *obj = (linetable_object *) self;
313
314 Py_DECREF (obj->symtab);
315 Py_TYPE (self)->tp_free (self);
316 }
317
318 /* Initialize LineTable, LineTableEntry and LineTableIterator
319 objects. */
320
321 int
322 gdbpy_initialize_linetable (void)
323 {
324 if (PyType_Ready (&linetable_object_type) < 0)
325 return -1;
326 if (PyType_Ready (&linetable_entry_object_type) < 0)
327 return -1;
328 if (PyType_Ready (&ltpy_iterator_object_type) < 0)
329 return -1;
330
331 Py_INCREF (&linetable_object_type);
332 Py_INCREF (&linetable_entry_object_type);
333 Py_INCREF (&ltpy_iterator_object_type);
334
335 if (gdb_pymodule_addobject (gdb_module, "LineTable",
336 (PyObject *) &linetable_object_type) < 0)
337 return -1;
338
339 if (gdb_pymodule_addobject (gdb_module, "LineTableEntry",
340 (PyObject *) &linetable_entry_object_type) < 0)
341 return -1;
342
343 if (gdb_pymodule_addobject (gdb_module, "LineTableIterator",
344 (PyObject *) &ltpy_iterator_object_type) < 0)
345 return -1;
346
347 return 0;
348 }
349
350 /* Linetable entry object get functions. */
351
352 /* Implementation of gdb.LineTableEntry.line (self) -> Long. Returns
353 a long integer associated with the line table entry. */
354
355 static PyObject *
356 ltpy_entry_get_line (PyObject *self, void *closure)
357 {
358 linetable_entry_object *obj = (linetable_entry_object *) self;
359
360 return gdb_py_object_from_longest (obj->line);
361 }
362
363 /* Implementation of gdb.LineTableEntry.pc (self) -> Long. Returns a
364 a long integer associated with the PC of the line table entry. */
365
366 static PyObject *
367 ltpy_entry_get_pc (PyObject *self, void *closure)
368 {
369 linetable_entry_object *obj = (linetable_entry_object *) self;
370
371 return gdb_py_object_from_longest (obj->pc);
372 }
373
374 /* Linetable iterator functions. */
375
376 /* Return a new line table iterator. */
377
378 static PyObject *
379 ltpy_iter (PyObject *self)
380 {
381 ltpy_iterator_object *ltpy_iter_obj;
382 struct symtab *symtab = NULL;
383
384 LTPY_REQUIRE_VALID (self, symtab);
385
386 ltpy_iter_obj = PyObject_New (ltpy_iterator_object,
387 &ltpy_iterator_object_type);
388 if (ltpy_iter_obj == NULL)
389 return NULL;
390
391 ltpy_iter_obj->current_index = 0;
392 ltpy_iter_obj->source = self;
393
394 Py_INCREF (self);
395 return (PyObject *) ltpy_iter_obj;
396 }
397
398 static void
399 ltpy_iterator_dealloc (PyObject *obj)
400 {
401 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) obj;
402
403 Py_DECREF (iter_obj->source);
404 }
405
406 /* Return a reference to the line table iterator. */
407
408 static PyObject *
409 ltpy_iterator (PyObject *self)
410 {
411 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
412 struct symtab *symtab;
413
414 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
415
416 Py_INCREF (self);
417 return self;
418 }
419
420 /* Return the next line table entry in the iteration through the line
421 table data structure. */
422
423 static PyObject *
424 ltpy_iternext (PyObject *self)
425 {
426 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
427 struct symtab *symtab;
428 int index;
429 PyObject *obj;
430 struct linetable_entry *item;
431
432 LTPY_REQUIRE_VALID (iter_obj->source, symtab);
433
434 if (iter_obj->current_index >= LINETABLE (symtab)->nitems)
435 goto stop_iteration;
436
437 item = &(LINETABLE (symtab)->item[iter_obj->current_index]);
438
439 /* Skip over internal entries such as 0. 0 signifies the end of
440 line table data and is not useful to the API user. */
441 while (item->line < 1)
442 {
443 iter_obj->current_index++;
444
445 /* Exit if the internal value is the last item in the line table. */
446 if (iter_obj->current_index >= symtab->linetable->nitems)
447 goto stop_iteration;
448 item = &(symtab->linetable->item[iter_obj->current_index]);
449 }
450
451 obj = build_linetable_entry (item->line, item->pc);
452 iter_obj->current_index++;
453
454 return obj;
455
456 stop_iteration:
457 PyErr_SetNone (PyExc_StopIteration);
458 return NULL;
459 }
460
461 /* Implementation of gdb.LinetableIterator.is_valid (self) -> Boolean.
462 Returns True if this line table iterator object still exists in
463 GDB. */
464
465 static PyObject *
466 ltpy_iter_is_valid (PyObject *self, PyObject *args)
467 {
468 struct symtab *symtab = NULL;
469 ltpy_iterator_object *iter_obj = (ltpy_iterator_object *) self;
470
471 symtab = symtab_object_to_symtab (get_symtab (iter_obj->source));
472
473 if (symtab == NULL)
474 Py_RETURN_FALSE;
475
476 Py_RETURN_TRUE;
477 }
478
479
480
481 static PyMethodDef linetable_object_methods[] = {
482 { "line", ltpy_get_pcs_for_line, METH_VARARGS,
483 "line (lineno) -> Tuple\n\
484 Return executable locations for a given source line." },
485 { "has_line", ltpy_has_line, METH_VARARGS,
486 "has_line (lineno) -> Boolean\n\
487 Return TRUE if this line has executable information, FALSE if not." },
488 { "source_lines", ltpy_get_all_source_lines, METH_NOARGS,
489 "source_lines () -> FrozenSet\n\
490 Return a frozen set of all executable source lines." },
491 { "is_valid", ltpy_is_valid, METH_NOARGS,
492 "is_valid () -> Boolean.\n\
493 Return True if this Linetable is valid, False if not." },
494 {NULL} /* Sentinel */
495 };
496
497 static PyTypeObject linetable_object_type = {
498 PyVarObject_HEAD_INIT (NULL, 0)
499 "gdb.LineTable", /*tp_name*/
500 sizeof (linetable_object), /*tp_basicsize*/
501 0, /*tp_itemsize*/
502 ltpy_dealloc, /*tp_dealloc*/
503 0, /*tp_print*/
504 0, /*tp_getattr*/
505 0, /*tp_setattr*/
506 0, /*tp_compare*/
507 0, /*tp_repr*/
508 0, /*tp_as_number*/
509 0, /*tp_as_sequence*/
510 0, /*tp_as_mapping*/
511 0, /*tp_hash */
512 0, /*tp_call*/
513 0, /*tp_str*/
514 0, /*tp_getattro*/
515 0, /*tp_setattro*/
516 0, /*tp_as_buffer*/
517 Py_TPFLAGS_DEFAULT, /*tp_flags*/
518 "GDB line table object", /* tp_doc */
519 0, /* tp_traverse */
520 0, /* tp_clear */
521 0, /* tp_richcompare */
522 0, /* tp_weaklistoffset */
523 ltpy_iter, /* tp_iter */
524 0, /* tp_iternext */
525 linetable_object_methods, /* tp_methods */
526 0, /* tp_members */
527 0, /* tp_getset */
528 0, /* tp_base */
529 0, /* tp_dict */
530 0, /* tp_descr_get */
531 0, /* tp_descr_set */
532 0, /* tp_dictoffset */
533 0, /* tp_init */
534 0, /* tp_alloc */
535 };
536
537 static PyMethodDef ltpy_iterator_methods[] = {
538 { "is_valid", ltpy_iter_is_valid, METH_NOARGS,
539 "is_valid () -> Boolean.\n\
540 Return True if this Linetable iterator is valid, False if not." },
541 {NULL} /* Sentinel */
542 };
543
544 static PyTypeObject ltpy_iterator_object_type = {
545 PyVarObject_HEAD_INIT (NULL, 0)
546 "gdb.LineTableIterator", /*tp_name*/
547 sizeof (ltpy_iterator_object), /*tp_basicsize*/
548 0, /*tp_itemsize*/
549 ltpy_iterator_dealloc, /*tp_dealloc*/
550 0, /*tp_print*/
551 0, /*tp_getattr*/
552 0, /*tp_setattr*/
553 0, /*tp_compare*/
554 0, /*tp_repr*/
555 0, /*tp_as_number*/
556 0, /*tp_as_sequence*/
557 0, /*tp_as_mapping*/
558 0, /*tp_hash */
559 0, /*tp_call*/
560 0, /*tp_str*/
561 0, /*tp_getattro*/
562 0, /*tp_setattro*/
563 0, /*tp_as_buffer*/
564 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
565 "GDB line table iterator object", /*tp_doc */
566 0, /*tp_traverse */
567 0, /*tp_clear */
568 0, /*tp_richcompare */
569 0, /*tp_weaklistoffset */
570 ltpy_iterator, /*tp_iter */
571 ltpy_iternext, /*tp_iternext */
572 ltpy_iterator_methods /*tp_methods */
573 };
574
575
576 static PyGetSetDef linetable_entry_object_getset[] = {
577 { "line", ltpy_entry_get_line, NULL,
578 "The line number in the source file.", NULL },
579 { "pc", ltpy_entry_get_pc, NULL,
580 "The memory address for this line number.", NULL },
581 { NULL } /* Sentinel */
582 };
583
584 static PyTypeObject linetable_entry_object_type = {
585 PyVarObject_HEAD_INIT (NULL, 0)
586 "gdb.LineTableEntry", /*tp_name*/
587 sizeof (linetable_entry_object), /*tp_basicsize*/
588 0, /*tp_itemsize*/
589 0, /*tp_dealloc*/
590 0, /*tp_print*/
591 0, /*tp_getattr*/
592 0, /*tp_setattr*/
593 0, /*tp_compare*/
594 0, /*tp_repr*/
595 0, /*tp_as_number*/
596 0, /*tp_as_sequence*/
597 0, /*tp_as_mapping*/
598 0, /*tp_hash */
599 0, /*tp_call*/
600 0, /*tp_str*/
601 0, /*tp_getattro*/
602 0, /*tp_setattro*/
603 0, /*tp_as_buffer*/
604 Py_TPFLAGS_DEFAULT, /*tp_flags*/
605 "GDB line table entry object", /* tp_doc */
606 0, /* tp_traverse */
607 0, /* tp_clear */
608 0, /* tp_richcompare */
609 0, /* tp_weaklistoffset */
610 0, /* tp_iter */
611 0, /* tp_iternext */
612 0, /* tp_methods */
613 0, /* tp_members */
614 linetable_entry_object_getset, /* tp_getset */
615 0, /* tp_base */
616 0, /* tp_dict */
617 0, /* tp_descr_get */
618 0, /* tp_descr_set */
619 0, /* tp_dictoffset */
620 0, /* tp_init */
621 0, /* tp_alloc */
622 };
OLDNEW
« no previous file with comments | « gdb/python/py-lazy-string.c ('k') | gdb/python/py-newobjfileevent.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698