X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=libdwfl%2Fargp-std.c;h=42b7e78380047ae67560eb77d7ad8ed9b621ae67;hb=a286dd013ef8d46edf013efc0908822a59d8ac81;hp=2ef4555ccb04635ac62a7ba498741e2b7c117e06;hpb=18a667176dd196f7bc3a9cdf1cbd87d4c7b31c7f;p=platform%2Fupstream%2Felfutils.git diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c index 2ef4555..42b7e78 100644 --- a/libdwfl/argp-std.c +++ b/libdwfl/argp-std.c @@ -1,5 +1,5 @@ /* Standard argp argument parsers for tools using libdwfl. - Copyright (C) 2005-2010 Red Hat, Inc. + Copyright (C) 2005-2010, 2012 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -90,6 +90,16 @@ static const Dwfl_Callbacks kernel_callbacks = .section_address = INTUSE(dwfl_linux_kernel_module_section_address), }; +/* Structure held at state->HOOK. */ +struct parse_opt +{ + Dwfl *dwfl; + /* The -e|--executable parameter. */ + const char *e; + /* The --core parameter. */ + const char *core; +}; + static error_t parse_opt (int key, char *arg, struct argp_state *state) { @@ -111,152 +121,145 @@ parse_opt (int key, char *arg, struct argp_state *state) switch (key) { + case ARGP_KEY_INIT: + { + assert (state->hook == NULL); + struct parse_opt *opt = calloc (1, sizeof (*opt)); + if (opt == NULL) + failure (NULL, DWFL_E_ERRNO, "calloc"); + state->hook = opt; + } + break; + case OPT_DEBUGINFO: debuginfo_path = arg; break; case 'e': { - Dwfl *dwfl = state->hook; + struct parse_opt *opt = state->hook; + Dwfl *dwfl = opt->dwfl; if (dwfl == NULL) { dwfl = INTUSE(dwfl_begin) (&offline_callbacks); if (dwfl == NULL) return fail (dwfl, -1, arg); - state->hook = dwfl; + opt->dwfl = dwfl; /* Start at zero so if there is just one -e foo.so, the DSO is shown without address bias. */ dwfl->offline_next_address = 0; } - if (dwfl->callbacks == &offline_callbacks) - { - if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL) - return fail (dwfl, -1, arg); - state->hook = dwfl; - } - else + if (dwfl->callbacks != &offline_callbacks) { toomany: argp_error (state, "%s", _("only one of -e, -p, -k, -K, or --core allowed")); return EINVAL; } + opt->e = arg; } break; case 'p': - if (state->hook == NULL) - { - Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks); - int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg)); - if (result != 0) - return fail (dwfl, result, arg); - state->hook = dwfl; - } - else - goto toomany; + { + struct parse_opt *opt = state->hook; + if (opt->dwfl == NULL) + { + Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks); + int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg)); + if (result != 0) + return fail (dwfl, result, arg); + + /* Non-fatal to not be able to attach to process, ignore error. */ + INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false); + + opt->dwfl = dwfl; + } + else + goto toomany; + } break; case 'M': - if (state->hook == NULL) - { - FILE *f = fopen (arg, "r"); - if (f == NULL) - nofile: - { - int code = errno; - argp_failure (state, EXIT_FAILURE, code, - "cannot open '%s'", arg); - return code; - } - Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks); - int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f); - fclose (f); - if (result != 0) - return fail (dwfl, result, arg); - state->hook = dwfl; - } - else - goto toomany; + { + struct parse_opt *opt = state->hook; + if (opt->dwfl == NULL) + { + FILE *f = fopen (arg, "r"); + if (f == NULL) + { + int code = errno; + argp_failure (state, EXIT_FAILURE, code, + "cannot open '%s'", arg); + return code; + } + Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks); + int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f); + fclose (f); + if (result != 0) + return fail (dwfl, result, arg); + opt->dwfl = dwfl; + } + else + goto toomany; + } break; case OPT_COREFILE: { - Dwfl *dwfl = state->hook; + struct parse_opt *opt = state->hook; + Dwfl *dwfl = opt->dwfl; if (dwfl == NULL) - state->hook = dwfl = INTUSE(dwfl_begin) (&offline_callbacks); + opt->dwfl = dwfl = INTUSE(dwfl_begin) (&offline_callbacks); /* Permit -e and --core together. */ else if (dwfl->callbacks != &offline_callbacks) goto toomany; - - int fd = open64 (arg, O_RDONLY); - if (fd < 0) - goto nofile; - - Elf *core; - Dwfl_Error error = __libdw_open_file (&fd, &core, true, false); - if (error != DWFL_E_NOERROR) - { - argp_failure (state, EXIT_FAILURE, 0, - _("cannot read ELF core file: %s"), - INTUSE(dwfl_errmsg) (error)); - return error == DWFL_E_ERRNO ? errno : EIO; - } - - int result = INTUSE(dwfl_core_file_report) (dwfl, core); - if (result < 0) - { - elf_end (core); - close (fd); - return fail (dwfl, result, arg); - } - - /* From now we leak FD and CORE. */ - - if (result == 0) - { - argp_failure (state, EXIT_FAILURE, 0, - _("No modules recognized in core file")); - return ENOENT; - } + opt->core = arg; } break; case 'k': - if (state->hook == NULL) - { - Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks); - int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl); - if (result != 0) - return fail (dwfl, result, _("cannot load kernel symbols")); - result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl); - if (result != 0) - /* Non-fatal to have no modules since we do have the kernel. */ - failure (dwfl, result, _("cannot find kernel modules")); - state->hook = dwfl; - } - else - goto toomany; + { + struct parse_opt *opt = state->hook; + if (opt->dwfl == NULL) + { + Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks); + int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl); + if (result != 0) + return fail (dwfl, result, _("cannot load kernel symbols")); + result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl); + if (result != 0) + /* Non-fatal to have no modules since we do have the kernel. */ + failure (dwfl, result, _("cannot find kernel modules")); + opt->dwfl = dwfl; + } + else + goto toomany; + } break; case 'K': - if (state->hook == NULL) - { - Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks); - int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg, - NULL); - if (result != 0) - return fail (dwfl, result, _("cannot find kernel or modules")); - state->hook = dwfl; - } - else - goto toomany; + { + struct parse_opt *opt = state->hook; + if (opt->dwfl == NULL) + { + Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks); + int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg, + NULL); + if (result != 0) + return fail (dwfl, result, _("cannot find kernel or modules")); + opt->dwfl = dwfl; + } + else + goto toomany; + } break; case ARGP_KEY_SUCCESS: { - Dwfl *dwfl = state->hook; + struct parse_opt *opt = state->hook; + Dwfl *dwfl = opt->dwfl; if (dwfl == NULL) { @@ -265,7 +268,54 @@ parse_opt (int key, char *arg, struct argp_state *state) dwfl = INTUSE(dwfl_begin) (&offline_callbacks); if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL) return fail (dwfl, -1, arg); - state->hook = dwfl; + opt->dwfl = dwfl; + } + + if (opt->core) + { + int fd = open64 (opt->core, O_RDONLY); + if (fd < 0) + { + int code = errno; + argp_failure (state, EXIT_FAILURE, code, + "cannot open '%s'", opt->core); + return code; + } + + Elf *core; + Dwfl_Error error = __libdw_open_file (&fd, &core, true, false); + if (error != DWFL_E_NOERROR) + { + argp_failure (state, EXIT_FAILURE, 0, + _("cannot read ELF core file: %s"), + INTUSE(dwfl_errmsg) (error)); + return error == DWFL_E_ERRNO ? errno : EIO; + } + + int result = INTUSE(dwfl_core_file_report) (dwfl, core, opt->e); + if (result < 0) + { + elf_end (core); + close (fd); + return fail (dwfl, result, opt->core); + } + + /* Non-fatal to not be able to attach to core, ignore error. */ + INTUSE(dwfl_core_file_attach) (dwfl, core); + + /* From now we leak FD and CORE. */ + + if (result == 0) + { + argp_failure (state, EXIT_FAILURE, 0, + _("No modules recognized in core file")); + return ENOENT; + } + } + else if (opt->e) + { + if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL) + return fail (dwfl, -1, opt->e); } /* One of the three flavors has done dwfl_begin and some reporting @@ -274,12 +324,22 @@ parse_opt (int key, char *arg, struct argp_state *state) int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL); assert (result == 0); + + /* Update the input all along, so a parent parser can see it. + As we free OPT the update below will be no longer active. */ + *(Dwfl **) state->input = dwfl; + free (opt); + state->hook = NULL; } break; case ARGP_KEY_ERROR: - dwfl_end (state->hook); - state->hook = NULL; + { + struct parse_opt *opt = state->hook; + dwfl_end (opt->dwfl); + free (opt); + state->hook = NULL; + } break; default: @@ -287,7 +347,10 @@ parse_opt (int key, char *arg, struct argp_state *state) } /* Update the input all along, so a parent parser can see it. */ - *(Dwfl **) state->input = state->hook; + struct parse_opt *opt = state->hook; + if (opt) + *(Dwfl **) state->input = opt->dwfl; + return 0; } @@ -299,15 +362,3 @@ dwfl_standard_argp (void) { return &libdwfl_argp; } - -#ifdef _MUDFLAP -/* In the absence of a mudflap wrapper for argp_parse, or a libc compiled - with -fmudflap, we'll see spurious errors for using the struct argp_state - on argp_parse's stack. */ - -void __attribute__ ((constructor)) -__libdwfl_argp_mudflap_options (void) -{ - __mf_set_options ("-heur-stack-bound"); -} -#endif