public inbox for archer-commits@sourceware.org help / color / mirror / Atom feed
From: sergiodj@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-sergiodj-stap-patches: New auto-sizing algorithms, new comments, etc. Date: Fri, 20 Apr 2012 04:19:00 -0000 [thread overview] Message-ID: <20120420041944.1214.qmail@sourceware.org> (raw) The branch, archer-sergiodj-stap-patches has been updated via ccaaf2154dfffef1ac11055f9bf0b8564ec73181 (commit) from b1f5e35562e1cc1654ccf668b0166b48c9c50f46 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit ccaaf2154dfffef1ac11055f9bf0b8564ec73181 Author: Sergio Durigan Junior <sergiodj@redhat.com> Date: Fri Apr 20 01:19:11 2012 -0300 New auto-sizing algorithms, new comments, etc. ----------------------------------------------------------------------- Summary of changes: gdb/probe.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++------- gdb/probe.h | 66 +++++++++++++-- gdb/stap-probe.c | 28 +++---- 3 files changed, 286 insertions(+), 54 deletions(-) First 500 lines of diff: diff --git a/gdb/probe.c b/gdb/probe.c index 7a5e140..8659d34 100644 --- a/gdb/probe.c +++ b/gdb/probe.c @@ -362,7 +362,113 @@ compare_entries (const void *a, const void *b) return strcmp (ea->objfile->name, eb->objfile->name); } -/* Implementation of the `info probes' command. */ +/* 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_entry) *items, + const struct probe_ops *p) +{ + VEC (const_char_ptr) *fields = NULL; + struct cleanup *c; + const char *f; + int jx; + + gdb_assert (p != NULL); + + if (p->gen_ui_out_table_header == NULL || p->gen_ui_out_fields == NULL) + return; + + c = make_cleanup (VEC_cleanup (const_char_ptr), &fields); + p->gen_ui_out_table_header (&fields); + + for (jx = 0; VEC_iterate (const_char_ptr, fields, jx, f); ++jx) + { + probe_entry *entry; + int ix; + size_t size_max = strlen (f); + + for (ix = 0; VEC_iterate (probe_entry, items, ix, entry); ++ix) + { + VEC (const_char_ptr) *values = NULL; + struct cleanup *c2; + const char *val; + int kx; + + if (entry->probe->pops != p) + continue; + + c2 = make_cleanup (VEC_cleanup (const_char_ptr), &values); + p->gen_ui_out_fields (entry->probe, entry->objfile, &values); + + for (kx = 0; VEC_iterate (const_char_ptr, values, kx, val); ++kx) + { + size_t s; + + /* It is valid to have a NULL value here, which means that the + backend does not have something to write and this particular + field should be skipped. */ + if (val == NULL) + continue; + + s = strlen (val); + + if (s > size_max) + size_max = s; + } + + do_cleanups (c2); + } + + ui_out_table_header (current_uiout, size_max, ui_left, f, f); + } + + do_cleanups (c); +} + +/* Helper function to print extra information about a probe and an objfile + represented by ENTRY. */ + +static void +print_ui_out_info (probe_entry *entry) +{ + const char *val, *field; + int ix; + VEC (const_char_ptr) *values = NULL, *fields = NULL; + struct cleanup *c; + + gdb_assert (entry != NULL && entry->probe != NULL + && entry->probe->pops != NULL); + + if (entry->probe->pops->gen_ui_out_table_header == NULL + || entry->probe->pops->gen_ui_out_fields == NULL) + return; + + c = make_cleanup (VEC_cleanup (const_char_ptr), &fields); + make_cleanup (VEC_cleanup (const_char_ptr), &values); + + entry->probe->pops->gen_ui_out_table_header (&fields); + entry->probe->pops->gen_ui_out_fields (entry->probe, entry->objfile, + &values); + + gdb_assert (VEC_length (const_char_ptr, fields) + == VEC_length (const_char_ptr, values)); + + for (ix = 0; + VEC_iterate (const_char_ptr, fields, ix, field), + VEC_iterate (const_char_ptr, values, ix, val); + ++ix) + { + if (val == NULL) + ui_out_field_skip (current_uiout, field); + else + ui_out_field_string (current_uiout, field, val); + } + + do_cleanups (c); +} + +/* See comment in probe.h. */ void info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) @@ -370,11 +476,16 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) char *provider, *probe = NULL, *objname = NULL; struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); VEC (probe_entry) *items; - int i, any_found, ui_out_extra_fields; + int i, any_found; + int ui_out_extra_fields = 0; int size_addr; + int size_name = strlen ("Name"); + int size_objname = strlen ("Object"); + int size_provider = strlen ("Provider"); probe_entry *entry; struct gdbarch *gdbarch = get_current_arch (); + /* Do we have a `provider:probe:objfile' style of linespec? */ provider = extract_arg (&arg); if (provider) { @@ -391,7 +502,54 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) } } - ui_out_extra_fields = pops != NULL ? pops->ui_out_extra_fields : 0; + if (pops == NULL) + { + const struct probe_ops *po; + int ix; + + /* If the probe_ops is NULL, it means the user has requested a "simple" + `info probes', i.e., she wants to print all information about all + probes. For that, we have to identify how many extra fields we will + need to add in the ui_out table. + + To do that, we iterate over all probe_ops, querying each one about + its extra fields, and incrementing `ui_out_extra_fields' to reflect + that number. */ + + for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix) + { + VEC (const_char_ptr) *fields = NULL; + struct cleanup *c; + + if (po->gen_ui_out_table_header == NULL) + continue; + + c = make_cleanup (VEC_cleanup (const_char_ptr), &fields); + po->gen_ui_out_table_header (&fields); + + ui_out_extra_fields += VEC_length (const_char_ptr, fields); + + do_cleanups (c); + } + } + else + { + if (pops->gen_ui_out_table_header != NULL) + { + VEC (const_char_ptr) *fields = NULL; + struct cleanup *c; + + /* We have a probe_ops, and it exports the function used to + obtains the extra fields. So we just ask the backend about + what are those extra fields, and increment `ui_out_extra_fields' + accordingly. */ + + c = make_cleanup (VEC_cleanup (const_char_ptr), &fields); + pops->gen_ui_out_table_header (&fields); + ui_out_extra_fields = VEC_length (const_char_ptr, fields); + do_cleanups (c); + } + } items = collect_probes (objname, provider, probe, pops); make_cleanup (VEC_cleanup (probe_entry), &items); @@ -404,23 +562,47 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) qsort (VEC_address (probe_entry, items), VEC_length (probe_entry, items), sizeof (probe_entry), compare_entries); + /* What's the size of an address in our architecture? */ size_addr = gdbarch_addr_bit (gdbarch) == 64 ? 18 : 10; -/* FIXME: provider width auto-sizing. */ - ui_out_table_header (current_uiout, 10, ui_left, "provider", _("Provider")); -/* FIXME: name width auto-sizing. */ - ui_out_table_header (current_uiout, 10, ui_left, "name", _("Name")); -/* FIXME: address width auto-sizing. */ + /* Determining the maximum size of each field (`provider', `name' and + `objname'). */ + for (i = 0; VEC_iterate (probe_entry, items, i, entry); ++i) + { + int s_name = strlen (entry->probe->name); + int s_provider = strlen (entry->probe->provider); + int s_objname = strlen (entry->objfile->name); + + if (s_name > size_name) + size_name = s_name; + + if (s_provider > size_provider) + size_provider = s_provider; + + if (s_objname > size_objname) + size_objname = s_objname; + } + + ui_out_table_header (current_uiout, size_provider, ui_left, "provider", + _("Provider")); + ui_out_table_header (current_uiout, size_name, ui_left, "name", _("Name")); ui_out_table_header (current_uiout, size_addr, ui_left, "addr", _("Where")); - if (pops != NULL && pops->gen_ui_out_table_header != NULL) - pops->gen_ui_out_table_header (current_uiout, ui_left); - -#if 0 /* FIXME */ - ui_out_table_header (current_uiout, 10, ui_left, "semaphore", - _("Semaphore")); -#endif -/* FIXME: object width auto-sizing. */ - ui_out_table_header (current_uiout, 30, ui_left, "object", _("Object")); + + if (pops == NULL) + { + const struct probe_ops *po; + int ix; + + /* 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); + } + else + gen_ui_out_table_header_info (items, 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_entry, items, i, entry); ++i) @@ -434,17 +616,20 @@ info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) ui_out_field_core_addr (current_uiout, "addr", get_objfile_arch (entry->objfile), entry->probe->address); - if (pops != NULL && pops->gen_ui_out_fields != NULL) - pops->gen_ui_out_fields (entry->probe, entry->objfile, current_uiout); -#if 0 /* FIXME */ - if (entry->probe->sem_addr == 0) - ui_out_field_skip (current_uiout, "semaphore"); + if (pops == NULL) + { + const struct probe_ops *po; + int ix; + + for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); + ++ix) + if (entry->probe->pops == po) + print_ui_out_info (entry); + } else - ui_out_field_core_addr (current_uiout, "semaphore", - get_objfile_arch (entry->objfile), - entry->probe->sem_addr); -#endif + print_ui_out_info (entry); + ui_out_field_string (current_uiout, "object", entry->objfile->name); ui_out_text (current_uiout, "\n"); @@ -491,11 +676,7 @@ probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n) n); } -/* Return specific PROBE_OPS * matching *LINESPECP and possibly updating - *LINESPECP to skip its "-probe-type " prefix. Return &probe_ops_any if - *LINESPECP matches "-probe ", that is any unspecific probe. Return NULL if - *LINESPECP is not identified as any known probe type, *LINESPECP is not - modified in such case. */ +/* See comment in probe.h. */ const struct probe_ops * probe_linespec_to_ops (const char **linespecp) @@ -510,7 +691,7 @@ probe_linespec_to_ops (const char **linespecp) return NULL; } -/* See comments in probe.h. */ +/* See comment in probe.h. */ int probe_is_linespec_by_keyword (const char **linespecp, const char *const *keywords) @@ -555,7 +736,6 @@ probe_any_get_probes (VEC (probe_p) **probesp, struct objfile *objfile) const struct probe_ops probe_ops_any = { - 0, probe_any_is_linespec, probe_any_get_probes, }; diff --git a/gdb/probe.h b/gdb/probe.h index 4e53098..96be016 100644 --- a/gdb/probe.h +++ b/gdb/probe.h @@ -22,6 +22,8 @@ #include "gdb_vecs.h" +DEF_VEC_P (const_char_ptr); + struct linespec_result; enum ui_align; @@ -29,13 +31,25 @@ enum ui_align; struct probe_ops { - int ui_out_extra_fields; + /* Method responsible for verifying if the linespec provided is a valid + linespec for a probe breakpoint. It should return 1 if it is, or zero + if it is not. It also should update the pointer passed in order to + discard the breakpoint option associated with this linespec. For + example, if the option is `-probe', and the linespec provided is + `-probe abc', the function should return 1 and set the string pointer + to `abc'. */ + + int (*is_linespec) (const char **); + + /* Function that should fill the `VEC (probe_p) **' argument with + known probes from the objfile specified. */ - int (*is_linespec) (const char **linespecp); + void (*get_probes) (VEC (probe_p) **, struct objfile *); - void (*get_probes) (VEC (probe_p) **probesp, struct objfile *objfile); + /* Function used to relocate a probe's addresses according to some + `CORE_ADDR' delta provided. */ - void (*relocate) (struct probe *probe, CORE_ADDR delta); + void (*relocate) (struct probe *, CORE_ADDR); /* Return the number of arguments of this probe. */ @@ -73,21 +87,52 @@ struct probe_ops void (*destroy) (struct probe *); - void (*gen_ui_out_table_header) (struct ui_out *, enum ui_align); + /* Function responsible for providing the extra fields that will be + printed in the `info probes' command. It should fill the + `VEC (const_char_ptr) **' with whatever extra fields it needs. + If the backend doesn't need to print extra fields, it can set this + method to NULL. */ + + void (*gen_ui_out_table_header) (VEC (const_char_ptr) **); + + /* Function that will provide a `VEC (const_char_ptr) **' containing + the values of the extra fields to be printed for the specified probe + and objfile. If the backend implements the `gen_ui_out_table_header', + then it should implement this method as well. The backend should also + guarantee that the order and the number of values in the vector is + exactly the same as the order of the extra fields provided in the + method `gen_ui_out_table_header'. If a certain field is to be skipped + when printing the information, you can push a NULL value in that + position in the vector. */ void (*gen_ui_out_fields) (struct probe *, struct objfile *, - struct ui_out *); + VEC (const_char_ptr) **); }; +/* Definition of a vector of probe_ops. */ + typedef const struct probe_ops *probe_ops_cp; DEF_VEC_P (probe_ops_cp); extern VEC (probe_ops_cp) *all_probe_ops; +/* The probe_ops associated with the generic probe. */ + extern const struct probe_ops probe_ops_any; +/* Helper function that, given KEYWORDS, iterate over it trying to match + each keyword with LINESPECP. If it succeeds, it updates the LINESPECP + pointer and returns 1. Otherwise, nothing is done to LINESPECP and zero + is returned. */ + extern int probe_is_linespec_by_keyword (const char **linespecp, const char *const *keywords); +/* Return specific PROBE_OPS * matching *LINESPECP and possibly updating + *LINESPECP to skip its "-probe-type " prefix. Return &probe_ops_any if + *LINESPECP matches "-probe ", that is any unspecific probe. Return NULL if + *LINESPECP is not identified as any known probe type, *LINESPECP is not + modified in such case. */ + extern const struct probe_ops *probe_linespec_to_ops (const char **linespecp); /* The probe itself. The struct contains generic information about the @@ -137,9 +182,18 @@ extern VEC (probe_p) *find_probes_in_objfile (struct objfile *objfile, const char *provider, const char *name); +/* Generate a `info probes' command output for probe_ops represented by + POPS. It is a helper function that can be used by the probe backends + to print their `info probe TYPE'. */ + extern void info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops); +/* Return the `cmd_list_element' associated with the `info probes' command, + or create a new one if it doesn't exist. Helper function that serves the + purpose of avoiding the case of a backend using the `cmd_list_element' + associated with `info probes', without having it registered yet. */ + extern struct cmd_list_element **info_probes_cmdlist_get (void); /* A convenience function that finds a probe at the PC in FRAME and diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c index 94ca5e0..3acebd5 100644 --- a/gdb/stap-probe.c +++ b/gdb/stap-probe.c @@ -93,6 +93,9 @@ DEF_VEC_O (stap_probe_arg_s); struct stap_probe { + /* Generic information about the probe. This shall be the first element + of this struct, in order to maintain binary compatibility with the + `struct probe' and be able to fully abstract it. */ struct probe p; /* If the probe has a semaphore associated, then this is the value of @@ -1446,36 +1449,31 @@ stap_probe_is_linespec (const char **linespecp) } static void -stap_gen_ui_out_table_header (struct ui_out *uiout, enum ui_align uialign) +stap_gen_ui_out_table_header (VEC (const_char_ptr) **fields) { - struct gdbarch *gdbarch = get_current_arch (); - int size_addr = gdbarch_addr_bit (gdbarch) == 64 ? 18 : 10; - - ui_out_table_header (uiout, size_addr, uialign, "semaphore", - _("Semaphore")); + VEC_safe_push (const_char_ptr, *fields, _("Semaphore")); } static void -stap_gen_ui_out_fields (struct probe *probe_generic, - struct objfile *objfile, struct ui_out *uiout) +stap_gen_ui_out_fields (struct probe *probe_generic, struct objfile *objfile, + VEC (const_char_ptr) **ret) { struct stap_probe *probe = (struct stap_probe *) probe_generic; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + const char *val = NULL; gdb_assert (probe_generic->pops == &stap_probe_ops); - if (probe->sem_addr == 0) - ui_out_field_skip (uiout, "semaphore"); - else - ui_out_field_core_addr (uiout, "semaphore", - get_objfile_arch (objfile), - probe->sem_addr); + if (probe->sem_addr) + val = print_core_address (gdbarch, probe->sem_addr); + + VEC_safe_push (const_char_ptr, *ret, val); } /* SystemTap probe_ops. */ static const struct probe_ops stap_probe_ops = { - 1, /* ui_out_extra_fields */ stap_probe_is_linespec, stap_get_probes, stap_relocate, hooks/post-receive -- Repository for Project Archer.
reply other threads:[~2012-04-20 4:19 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20120420041944.1214.qmail@sourceware.org \ --to=sergiodj@sourceware.org \ --cc=archer-commits@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).