X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Fprobe.c;h=3b8882e66ee904d7ad505448bc007ca7cdfd17f4;hb=711833262c7a413b10a32f01153454bc5a53a5a6;hp=4e1b6a03faba169a8233fcf7936a778273464851;hpb=55aa24fb2eb147288fec359a99e960f7136336e8;p=platform%2Fupstream%2Fbinutils.git diff --git a/gdb/probe.c b/gdb/probe.c index 4e1b6a0..3b8882e 100644 --- a/gdb/probe.c +++ b/gdb/probe.c @@ -1,6 +1,6 @@ /* Generic static probe support for GDB. - Copyright (C) 2012 Free Software Foundation, Inc. + Copyright (C) 2012-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -26,13 +26,15 @@ #include "symtab.h" #include "progspace.h" #include "filenames.h" -#include "exceptions.h" #include "linespec.h" #include "gdb_regex.h" #include "frame.h" #include "arch-utils.h" #include +typedef struct bound_probe bound_probe_s; +DEF_VEC_O (bound_probe_s); + /* See definition in probe.h. */ @@ -41,7 +43,7 @@ struct symtabs_and_lines parse_probes (char **argptr, struct linespec_result *canonical) { char *arg_start, *arg_end, *arg; - char *objfile_name = NULL, *provider = NULL, *name, *p; + char *objfile_namestr = NULL, *provider = NULL, *name, *p; struct cleanup *cleanup; struct symtabs_and_lines result; struct objfile *objfile; @@ -56,7 +58,8 @@ parse_probes (char **argptr, struct linespec_result *canonical) cs = *argptr; probe_ops = probe_linespec_to_ops (&cs); - gdb_assert (probe_ops != NULL); + if (probe_ops == NULL) + error (_("'%s' is not a probe linespec"), arg_start); arg = (char *) cs; arg = skip_spaces (arg); @@ -92,7 +95,7 @@ parse_probes (char **argptr, struct linespec_result *canonical) { /* This is `-p objfile:provider:name'. */ *p = '\0'; - objfile_name = arg; + objfile_namestr = arg; provider = hold; name = p + 1; } @@ -102,7 +105,7 @@ parse_probes (char **argptr, struct linespec_result *canonical) error (_("no probe name specified")); if (provider && *provider == '\0') error (_("invalid provider name")); - if (objfile_name && *objfile_name == '\0') + if (objfile_namestr && *objfile_namestr == '\0') error (_("invalid objfile name")); ALL_PSPACES (pspace) @@ -115,12 +118,10 @@ parse_probes (char **argptr, struct linespec_result *canonical) if (!objfile->sf || !objfile->sf->sym_probe_fns) continue; - if (objfile_name - && FILENAME_CMP (objfile->name, objfile_name) != 0 - && FILENAME_CMP (lbasename (objfile->name), objfile_name) != 0) - continue; - - if (objfile->separate_debug_objfile_backlink != NULL) + if (objfile_namestr + && FILENAME_CMP (objfile_name (objfile), objfile_namestr) != 0 + && FILENAME_CMP (lbasename (objfile_name (objfile)), + objfile_namestr) != 0) continue; probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); @@ -146,11 +147,12 @@ parse_probes (char **argptr, struct linespec_result *canonical) init_sal (sal); - sal->pc = probe->address; + sal->pc = get_probe_address (probe, objfile); sal->explicit_pc = 1; sal->section = find_pc_overlay (sal->pc); sal->pspace = pspace; sal->probe = probe; + sal->objfile = objfile; } } @@ -158,7 +160,7 @@ parse_probes (char **argptr, struct linespec_result *canonical) { throw_error (NOT_FOUND_ERROR, _("No probe matching objfile=`%s', provider=`%s', name=`%s'"), - objfile_name ? objfile_name : _(""), + objfile_namestr ? objfile_namestr : _(""), provider ? provider : _(""), name); } @@ -206,10 +208,14 @@ find_probes_in_objfile (struct objfile *objfile, const char *provider, /* See definition in probe.h. */ -struct probe * -find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out) +struct bound_probe +find_probe_by_pc (CORE_ADDR pc) { struct objfile *objfile; + struct bound_probe result; + + result.objfile = NULL; + result.probe = NULL; ALL_OBJFILES (objfile) { @@ -217,82 +223,48 @@ find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out) int ix; struct probe *probe; - if (!objfile->sf || !objfile->sf->sym_probe_fns) + if (!objfile->sf || !objfile->sf->sym_probe_fns + || objfile->sect_index_text == -1) continue; /* If this proves too inefficient, we can replace with a hash. */ probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) - if (probe->address == pc) + if (get_probe_address (probe, objfile) == pc) { - *objfile_out = objfile; - return probe; + result.objfile = objfile; + result.probe = probe; + return result; } } - return NULL; + return result; } -/* A utility structure. A VEC of these is built when handling "info - probes". */ - -struct probe_and_objfile -{ - /* The probe. */ - struct probe *probe; - - /* The probe's objfile. */ - struct objfile *objfile; -}; - -typedef struct probe_and_objfile probe_and_objfile_s; -DEF_VEC_O (probe_and_objfile_s); - -/* A helper function for collect_probes that compiles a regexp and - throws an exception on error. This installs a cleanup to free the - resulting pattern on success. If RX is NULL, this does nothing. */ - -static void -compile_rx_or_error (regex_t *pattern, const char *rx, const char *message) -{ - int code; - - if (!rx) - return; - - code = regcomp (pattern, rx, REG_NOSUB); - if (code == 0) - make_regfree_cleanup (pattern); - else - { - char *err = get_regcomp_error (code, pattern); - - make_cleanup (xfree, err); - error ("%s: %s", message, err); - } -} - /* Make a vector of probes matching OBJNAME, PROVIDER, and PROBE_NAME. If POPS is not NULL, only probes of this certain probe_ops will match. Each argument is a regexp, or NULL, which matches anything. */ -static VEC (probe_and_objfile_s) * +static VEC (bound_probe_s) * collect_probes (char *objname, char *provider, char *probe_name, const struct probe_ops *pops) { struct objfile *objfile; - VEC (probe_and_objfile_s) *result = NULL; + VEC (bound_probe_s) *result = NULL; struct cleanup *cleanup, *cleanup_temps; regex_t obj_pat, prov_pat, probe_pat; - cleanup = make_cleanup (VEC_cleanup (probe_and_objfile_s), &result); + cleanup = make_cleanup (VEC_cleanup (bound_probe_s), &result); cleanup_temps = make_cleanup (null_cleanup, NULL); - compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp")); - compile_rx_or_error (&probe_pat, probe_name, _("Invalid probe regexp")); - compile_rx_or_error (&obj_pat, objname, _("Invalid object file regexp")); + if (provider != NULL) + compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp")); + if (probe_name != NULL) + compile_rx_or_error (&probe_pat, probe_name, _("Invalid probe regexp")); + if (objname != NULL) + compile_rx_or_error (&obj_pat, objname, _("Invalid object file regexp")); ALL_OBJFILES (objfile) { @@ -305,7 +277,7 @@ collect_probes (char *objname, char *provider, char *probe_name, if (objname) { - if (regexec (&obj_pat, objfile->name, 0, NULL, 0) != 0) + if (regexec (&obj_pat, objfile_name (objfile), 0, NULL, 0) != 0) continue; } @@ -313,7 +285,7 @@ collect_probes (char *objname, char *provider, char *probe_name, for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) { - probe_and_objfile_s entry; + struct bound_probe bound; if (pops != NULL && probe->pops != pops) continue; @@ -326,9 +298,9 @@ collect_probes (char *objname, char *provider, char *probe_name, && regexec (&probe_pat, probe->name, 0, NULL, 0) != 0) continue; - entry.probe = probe; - entry.objfile = objfile; - VEC_safe_push (probe_and_objfile_s, result, &entry); + bound.objfile = objfile; + bound.probe = probe; + VEC_safe_push (bound_probe_s, result, &bound); } } @@ -337,36 +309,36 @@ collect_probes (char *objname, char *provider, char *probe_name, return result; } -/* A qsort comparison function for probe_and_objfile_s objects. */ +/* A qsort comparison function for bound_probe_s objects. */ static int -compare_entries (const void *a, const void *b) +compare_probes (const void *a, const void *b) { - const probe_and_objfile_s *ea = a; - const probe_and_objfile_s *eb = b; + const struct bound_probe *pa = (const struct bound_probe *) a; + const struct bound_probe *pb = (const struct bound_probe *) b; int v; - v = strcmp (ea->probe->provider, eb->probe->provider); + v = strcmp (pa->probe->provider, pb->probe->provider); if (v) return v; - v = strcmp (ea->probe->name, eb->probe->name); + v = strcmp (pa->probe->name, pb->probe->name); if (v) return v; - if (ea->probe->address < eb->probe->address) + if (pa->probe->address < pb->probe->address) return -1; - if (ea->probe->address > eb->probe->address) + if (pa->probe->address > pb->probe->address) return 1; - return strcmp (ea->objfile->name, eb->objfile->name); + return strcmp (objfile_name (pa->objfile), objfile_name (pb->objfile)); } /* Helper function that generate entries in the ui_out table being crafted by `info_probes_for_ops'. */ static void -gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes, +gen_ui_out_table_header_info (VEC (bound_probe_s) *probes, const struct probe_ops *p) { /* `headings' refers to the names of the columns when printing `info @@ -395,11 +367,11 @@ gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes, VEC_iterate (info_probe_column_s, headings, ix, column); ++ix) { - probe_and_objfile_s *entry; + struct bound_probe *probe; int jx; size_t size_max = strlen (column->print_name); - for (jx = 0; VEC_iterate (probe_and_objfile_s, probes, jx, entry); ++jx) + for (jx = 0; VEC_iterate (bound_probe_s, probes, jx, probe); ++jx) { /* `probe_fields' refers to the values of each new field that this probe will display. */ @@ -408,12 +380,11 @@ gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes, const char *val; int kx; - if (entry->probe->pops != p) + if (probe->probe->pops != p) continue; c2 = make_cleanup (VEC_cleanup (const_char_ptr), &probe_fields); - p->gen_info_probes_table_values (entry->probe, entry->objfile, - &probe_fields); + p->gen_info_probes_table_values (probe->probe, &probe_fields); gdb_assert (VEC_length (const_char_ptr, probe_fields) == headings_size); @@ -440,10 +411,10 @@ gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes, } /* Helper function to print extra information about a probe and an objfile - represented by ENTRY. */ + represented by PROBE. */ static void -print_ui_out_info (probe_and_objfile_s *entry) +print_ui_out_info (struct probe *probe) { int ix; int j = 0; @@ -454,23 +425,21 @@ print_ui_out_info (probe_and_objfile_s *entry) info_probe_column_s *column; struct cleanup *c; - gdb_assert (entry != NULL); - gdb_assert (entry->probe != NULL); - gdb_assert (entry->probe->pops != NULL); + gdb_assert (probe != NULL); + gdb_assert (probe->pops != NULL); - if (entry->probe->pops->gen_info_probes_table_header == NULL - && entry->probe->pops->gen_info_probes_table_values == NULL) + if (probe->pops->gen_info_probes_table_header == NULL + && probe->pops->gen_info_probes_table_values == NULL) return; - gdb_assert (entry->probe->pops->gen_info_probes_table_header != NULL - && entry->probe->pops->gen_info_probes_table_values != NULL); + gdb_assert (probe->pops->gen_info_probes_table_header != NULL + && probe->pops->gen_info_probes_table_values != NULL); c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings); make_cleanup (VEC_cleanup (const_char_ptr), &values); - entry->probe->pops->gen_info_probes_table_header (&headings); - entry->probe->pops->gen_info_probes_table_values (entry->probe, - entry->objfile, &values); + probe->pops->gen_info_probes_table_header (&headings); + probe->pops->gen_info_probes_table_values (probe, &values); gdb_assert (VEC_length (info_probe_column_s, headings) == VEC_length (const_char_ptr, values)); @@ -516,32 +485,33 @@ get_number_extra_fields (const struct probe_ops *pops) /* See comment in probe.h. */ void -info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) +info_probes_for_ops (const char *arg, int from_tty, + const struct probe_ops *pops) { - char *provider, *probe = NULL, *objname = NULL; + char *provider, *probe_name = NULL, *objname = NULL; struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); - VEC (probe_and_objfile_s) *items; + VEC (bound_probe_s) *probes; int i, any_found; int ui_out_extra_fields = 0; size_t size_addr; size_t size_name = strlen ("Name"); size_t size_objname = strlen ("Object"); size_t size_provider = strlen ("Provider"); - probe_and_objfile_s *entry; + struct bound_probe *probe; struct gdbarch *gdbarch = get_current_arch (); /* Do we have a `provider:probe:objfile' style of linespec? */ - provider = extract_arg (&arg); + provider = extract_arg_const (&arg); if (provider) { make_cleanup (xfree, provider); - probe = extract_arg (&arg); - if (probe) + probe_name = extract_arg_const (&arg); + if (probe_name) { - make_cleanup (xfree, probe); + make_cleanup (xfree, probe_name); - objname = extract_arg (&arg); + objname = extract_arg_const (&arg); if (objname) make_cleanup (xfree, objname); } @@ -567,28 +537,28 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) else ui_out_extra_fields = get_number_extra_fields (pops); - items = collect_probes (objname, provider, probe, pops); - make_cleanup (VEC_cleanup (probe_and_objfile_s), &items); + probes = collect_probes (objname, provider, probe_name, pops); + make_cleanup (VEC_cleanup (probe_p), &probes); make_cleanup_ui_out_table_begin_end (current_uiout, 4 + ui_out_extra_fields, - VEC_length (probe_and_objfile_s, items), + VEC_length (bound_probe_s, probes), "StaticProbes"); - if (!VEC_empty (probe_and_objfile_s, items)) - qsort (VEC_address (probe_and_objfile_s, items), - VEC_length (probe_and_objfile_s, items), - sizeof (probe_and_objfile_s), compare_entries); + if (!VEC_empty (bound_probe_s, probes)) + qsort (VEC_address (bound_probe_s, probes), + VEC_length (bound_probe_s, probes), + sizeof (bound_probe_s), compare_probes); /* What's the size of an address in our architecture? */ size_addr = gdbarch_addr_bit (gdbarch) == 64 ? 18 : 10; /* Determining the maximum size of each field (`provider', `name' and `objname'). */ - for (i = 0; VEC_iterate (probe_and_objfile_s, items, i, entry); ++i) + for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i) { - size_name = max (strlen (entry->probe->name), size_name); - size_provider = max (strlen (entry->probe->provider), size_provider); - size_objname = max (strlen (entry->objfile->name), size_objname); + size_name = max (strlen (probe->probe->name), size_name); + size_provider = max (strlen (probe->probe->provider), size_provider); + size_objname = max (strlen (objfile_name (probe->objfile)), size_objname); } ui_out_table_header (current_uiout, size_provider, ui_left, "provider", @@ -604,26 +574,26 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) /* We have to generate the table header for each new probe type that we will print. */ for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix) - gen_ui_out_table_header_info (items, po); + gen_ui_out_table_header_info (probes, po); } else - gen_ui_out_table_header_info (items, pops); + gen_ui_out_table_header_info (probes, pops); ui_out_table_header (current_uiout, size_objname, ui_left, "object", _("Object")); ui_out_table_body (current_uiout); - for (i = 0; VEC_iterate (probe_and_objfile_s, items, i, entry); ++i) + for (i = 0; VEC_iterate (bound_probe_s, probes, i, probe); ++i) { struct cleanup *inner; inner = make_cleanup_ui_out_tuple_begin_end (current_uiout, "probe"); - ui_out_field_string (current_uiout, "provider", entry->probe->provider); - ui_out_field_string (current_uiout, "name", entry->probe->name); + ui_out_field_string (current_uiout, "provider", probe->probe->provider); + ui_out_field_string (current_uiout, "name", probe->probe->name); ui_out_field_core_addr (current_uiout, "addr", - get_objfile_arch (entry->objfile), - entry->probe->address); + probe->probe->arch, + get_probe_address (probe->probe, probe->objfile)); if (pops == NULL) { @@ -632,19 +602,20 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix) - if (entry->probe->pops == po) - print_ui_out_info (entry); + if (probe->probe->pops == po) + print_ui_out_info (probe->probe); } else - print_ui_out_info (entry); + print_ui_out_info (probe->probe); - ui_out_field_string (current_uiout, "object", entry->objfile->name); + ui_out_field_string (current_uiout, "object", + objfile_name (probe->objfile)); ui_out_text (current_uiout, "\n"); do_cleanups (inner); } - any_found = !VEC_empty (probe_and_objfile_s, items); + any_found = !VEC_empty (bound_probe_s, probes); do_cleanups (cleanup); if (!any_found) @@ -661,27 +632,54 @@ info_probes_command (char *arg, int from_tty) /* See comments in probe.h. */ +CORE_ADDR +get_probe_address (struct probe *probe, struct objfile *objfile) +{ + return probe->pops->get_probe_address (probe, objfile); +} + +/* See comments in probe.h. */ + +unsigned +get_probe_argument_count (struct probe *probe, struct frame_info *frame) +{ + return probe->pops->get_probe_argument_count (probe, frame); +} + +/* See comments in probe.h. */ + +int +can_evaluate_probe_arguments (struct probe *probe) +{ + return probe->pops->can_evaluate_probe_arguments (probe); +} + +/* See comments in probe.h. */ + +struct value * +evaluate_probe_argument (struct probe *probe, unsigned n, + struct frame_info *frame) +{ + return probe->pops->evaluate_probe_argument (probe, n, frame); +} + +/* See comments in probe.h. */ + struct value * probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n) { - struct probe *probe; - struct objfile *objfile; - unsigned n_probes; + struct bound_probe probe; + unsigned n_args; - probe = find_probe_by_pc (get_frame_pc (frame), &objfile); - if (!probe) + probe = find_probe_by_pc (get_frame_pc (frame)); + if (!probe.probe) return NULL; - gdb_assert (objfile->sf && objfile->sf->sym_probe_fns); - n_probes - = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, - probe); - if (n >= n_probes) + n_args = get_probe_argument_count (probe.probe, frame); + if (n >= n_args) return NULL; - return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile, - probe, - n); + return evaluate_probe_argument (probe.probe, n, frame); } /* See comment in probe.h. */