1 // Setup routines for creating fully populated DWFLs. Used in pass 2 and 3.
2 // Copyright (C) 2009-2018 Red Hat, Inc.
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
10 #include "setupdwfl.h"
12 #include "dwarf_wrappers.h"
29 #include <sys/times.h>
31 #include <sys/types.h>
35 #include <sys/utsname.h>
39 // XXX: also consider adding $HOME/.debug/ for perf build-id-cache
40 static const char *debuginfo_path_arr
= "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug:build";
41 static const char *debuginfo_env_arr
= getenv("SYSTEMTAP_DEBUGINFO_PATH");
42 static char *debuginfo_path
= (char *)(debuginfo_env_arr
?: debuginfo_path_arr
);
44 // NB: kernel_build_tree doesn't enter into this, as it's for
45 // kernel-side modules only.
46 // XXX: also consider adding $HOME/.debug/ for perf build-id-cache
47 static const char *debuginfo_usr_path_arr
= "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug";
48 static char *debuginfo_usr_path
= (char *)(debuginfo_env_arr
49 ?: debuginfo_usr_path_arr
);
51 // A pointer to the current systemtap session for use only by a few
52 // dwfl calls. DO NOT rely on this, as it is cleared after use.
54 static systemtap_session
* current_session_for_find_debuginfo
;
56 static const Dwfl_Callbacks kernel_callbacks
=
58 dwfl_linux_kernel_find_elf
,
59 internal_find_debuginfo
,
60 dwfl_offline_section_address
,
61 (char **) & debuginfo_path
64 static const Dwfl_Callbacks user_callbacks
=
67 internal_find_debuginfo
,
68 NULL
, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN.
69 dwfl_offline_section_address, */
70 (char **) & debuginfo_usr_path
75 // Setup in setup_dwfl_kernel(), for use in setup_dwfl_report_kernel_p().
76 // Either offline_search_modname or offline_search_names is
77 // used. When offline_search_modname is not NULL then
78 // offline_search_names is ignored.
79 static const char *offline_search_modname
;
80 static set
<string
> offline_search_names
;
81 static unsigned offline_modules_found
;
83 // Whether or not we are done reporting kernel modules in
84 // set_dwfl_report_kernel_p().
85 static bool setup_dwfl_done
;
87 // Determines whether or not we will make setup_dwfl_report_kernel_p
88 // report true for all module dependencies. This is necessary for
89 // correctly resolving some dwarf constructs that relocate against
90 // symbols in vmlinux and/or other modules they depend on. See PR10678.
91 static const bool setup_all_deps
= true;
93 // Where to find the kernel (and the Modules.dep file). Setup in
94 // setup_dwfl_kernel(), used by dwfl_linux_kernel_report_offline() and
96 static string elfutils_kernel_path
;
98 static bool is_comma_dash(const char c
) { return (c
== ',' || c
== '-'); }
100 // The path to the abrt-action-install-debuginfo-to-abrt-cache program.
101 static const string abrt_path
=
102 (access ("/usr/bin/abrt-action-install-debuginfo-to-abrt-cache", X_OK
) == 0
103 ? "/usr/bin/abrt-action-install-debuginfo-to-abrt-cache"
104 : (access ("/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache", X_OK
) == 0
105 ? "/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache"
108 // The module name is the basename (without the extension) of the module path,
109 // with ',' and '-' replaced by '_'. This is a (more or less safe) heuristic:
110 // the actual name by which the module is known once inside the kernel is not
111 // derived from the path, but from the .gnu.linkonce.this_module section of the
112 // KO. In practice, modules in /lib/modules/ respect this convention, and we
113 // require it as well for out-of-tree kernel modules.
115 modname_from_path(const string
&path
)
117 size_t slash
= path
.rfind('/');
118 if (slash
== string::npos
)
120 string name
= path
.substr(slash
+ 1);
122 // First look for .ko extension variants like ".ko" or ".ko.xz"
123 // If that fails, look for any ".*" extension at all.
124 size_t extension
= name
.rfind(".ko");
125 if (extension
== string::npos
)
126 extension
= name
.rfind('.');
127 if (extension
== string::npos
)
130 name
.erase(extension
);
131 replace_if(name
.begin(), name
.end(), is_comma_dash
, '_');
135 static bool offline_search_names_find(const string
&modpath
) {
136 if (offline_search_names
.find(modpath
) != offline_search_names
.end()) return 1;
137 string modname
= modname_from_path (modpath
);
138 return offline_search_names
.find(modname
) != offline_search_names
.end();
141 // Try to parse modules.dep file,
142 // Simple format: module path (either full or relative), colon,
143 // (possibly empty) space delimited list of module (path)
153 if (elfutils_kernel_path
[0] == '/')
155 kernel_path
= elfutils_kernel_path
;
160 if (current_session_for_find_debuginfo
)
161 sysroot
= current_session_for_find_debuginfo
->sysroot
;
162 kernel_path
= sysroot
+ "/lib/modules/" + elfutils_kernel_path
;
164 modulesdep
= kernel_path
+ "/modules.dep";
165 in
.open(modulesdep
.c_str());
169 while (getline (in
, l
))
171 size_t off
= l
.find (':');
172 if (off
!= string::npos
)
174 string modpath
, modname
;
175 modpath
= l
.substr (0, off
);
176 modname
= modname_from_path (modpath
);
179 if (modpath
[0] != '/') modpath
= kernel_path
+ "/" + modpath
;
182 if (offline_search_modname
!= NULL
)
184 if (dwflpp::name_has_wildcard (offline_search_modname
))
186 dep_needed
= !fnmatch (offline_search_modname
,
187 modname
.c_str (), 0);
189 offline_search_names
.insert (modpath
);
193 dep_needed
= ! strcmp(modname
.c_str (),
194 offline_search_modname
);
196 offline_search_names
.insert (modpath
);
199 else if (offline_search_names
.find(modpath
) != offline_search_names
.end())
203 set
<string
>::iterator it
= offline_search_names
.begin();
204 while (it
!= offline_search_names
.end())
207 modname
= modname_from_path(modpath
);
211 offline_search_names
.erase(it
);
212 offline_search_names
.insert(modpath
);
222 string depstring
= l
.substr (off
+ 1);
223 if (depstring
.size () > 0)
225 stringstream
ss (depstring
);
227 while (ss
>> deppath
)
228 offline_search_names
.insert (deppath
);
234 // We always want kernel (needed in list so size checks match).
235 // Everything needed now stored in offline_search_names.
236 offline_search_names
.insert ("kernel");
237 offline_search_modname
= NULL
;
240 // Set up our offline search for kernel modules. We don't want the
241 // offline search iteration to do a complete search of the kernel
242 // build tree, since that's wasteful, so create a predicate that
243 // filters and stops reporting as soon as we got everything.
245 setup_dwfl_report_kernel_p(const char* modname
, const char* filename
)
247 assert_no_interrupts();
252 assert (current_session_for_find_debuginfo
);
253 if (current_session_for_find_debuginfo
->verbose
> 4)
254 clog
<< _F("checking pattern '%s' vs. module '%s' file '%s'\n",
255 offline_search_modname
?: "",
259 // elfutils sends us NULL filenames sometimes if it can't find dwarf
260 if (filename
== NULL
)
263 // Check kernel first since it is often the only thing needed,
264 // then we never have to parse and setup the module deps map.
265 // It will be reported as the very first thing.
266 if (setup_all_deps
&& ! strcmp (modname
, "kernel"))
268 if ((offline_search_modname
!= NULL
269 && ! strcmp (offline_search_modname
, "kernel"))
270 || (offline_search_names
.size() == 1
271 && *offline_search_names
.begin() == "kernel"))
272 setup_dwfl_done
= true;
276 offline_modules_found
++;
280 // If offline_search_modname is setup use it (either as regexp or
281 // explicit module/kernel name) and ignore offline_search_names.
282 // Otherwise use offline_search_names exclusively.
283 if (offline_search_modname
!= NULL
)
285 if (dwflpp::name_has_wildcard (offline_search_modname
))
287 // XXX: see also dwflpp::module_name_matches()
288 int match_p
= !fnmatch(offline_search_modname
, modname
, 0);
289 // In the wildcard case, we don't short-circuit (return -1)
290 // analogously to dwflpp::module_name_final_match().
292 offline_modules_found
++;
296 { /* non-wildcard mode, reject mismatching module names */
297 if (strcmp(modname
, offline_search_modname
))
301 // Done, only one name needed and found it.
302 offline_modules_found
++;
303 setup_dwfl_done
= true;
309 { /* find all in set mode, reject mismatching module names */
310 if (!offline_search_names_find(filename
))
314 offline_modules_found
++;
315 if (offline_search_names
.size() == offline_modules_found
)
316 setup_dwfl_done
= true;
322 static char * path_insert_sysroot(string sysroot
, string path
)
327 path
.replace(0, 1, sysroot
);
329 pos
= path
.find(":/", pos
);
330 if (pos
== string::npos
)
332 path
.replace(pos
, 2, ":" + sysroot
);
335 path_new
= new char[path
.size()+1];
336 strcpy (path_new
, path
.c_str());
340 void debuginfo_path_insert_sysroot(string sysroot
)
342 // FIXME: This is a short-term fix, until we expect sysroot paths to
343 // always end with a '/' (and never be empty).
345 // The path_insert_sysroot() function assumes that sysroot has a '/'
346 // on the end. Make sure that is true.
347 if (! sysroot
.empty() && *(sysroot
.end() - 1) != '/')
348 sysroot
.append(1, '/');
349 debuginfo_path
= path_insert_sysroot(sysroot
, debuginfo_path
);
350 debuginfo_usr_path
= path_insert_sysroot(sysroot
, debuginfo_usr_path
);
354 setup_dwfl_kernel (unsigned *modules_found
, systemtap_session
&s
)
356 Dwfl
*dwfl
= dwfl_begin (&kernel_callbacks
);
357 DWFL_ASSERT ("dwfl_begin", dwfl
);
358 dwfl_report_begin (dwfl
);
360 // We have a problem with -r REVISION vs -r BUILDDIR here. If
361 // we're running against a fedora/rhel style kernel-debuginfo
362 // tree, s.kernel_build_tree is not the place where the unstripped
363 // vmlinux will be installed. Rather, it's over yonder at
364 // /usr/lib/debug/lib/modules/$REVISION/. It seems that there is
365 // no way to set the dwfl_callback.debuginfo_path and always
366 // passs the plain kernel_release here. So instead we have to
367 // hard-code this magic here.
368 string lib_path
= s
.sysroot
+ "/lib/modules/" + s
.kernel_release
+ "/build";
369 if (s
.kernel_build_tree
== lib_path
)
372 // If we have sysroot set does not make sense to pass
373 // short release to dwfl, it won't take a sysroot into
374 // account. Let's construct full path in such case.
375 elfutils_kernel_path
= string(s
.sysroot
+ "/lib/modules/" + s
.kernel_release
);
377 elfutils_kernel_path
= s
.kernel_release
;
380 elfutils_kernel_path
= s
.kernel_build_tree
;
381 offline_modules_found
= 0;
383 // First try to report full path modules.
384 set
<string
>::iterator it
= offline_search_names
.begin();
386 while (it
!= offline_search_names
.end())
390 const char *cname
= (*it
).c_str();
391 Dwfl_Module
*mod
= dwfl_report_offline (dwfl
, cname
, cname
, -1);
393 offline_modules_found
++;
395 else if ((*it
) == "kernel")
400 // We always need this, even when offline_search_modname is NULL
401 // and offline_search_names is empty because we still might want
402 // the kernel vmlinux reported.
403 setup_dwfl_done
= false;
404 int rc
= dwfl_linux_kernel_report_offline (dwfl
,
405 elfutils_kernel_path
.c_str(),
406 &setup_dwfl_report_kernel_p
);
408 (void) rc
; /* Ignore since the predicate probably returned -1 at some point,
409 And libdwfl interprets that as "whole query failed" rather than
410 "found it already, stop looking". */
412 // NB: the result of an _offline call is the assignment of
413 // virtualized addresses to relocatable objects such as
414 // modules. These have to be converted to real addresses at
415 // run time. See the dwarf_derived_probe ctor and its caller.
417 // If no modules were found, and we are probing the kernel,
418 // attempt to download the kernel debuginfo.
421 // Get the kernel build ID. We still need to call this even if we
422 // already have the kernel debuginfo installed as it adds the
423 // build ID to the script hash.
424 string hex
= get_kernel_build_id(s
);
425 if (offline_modules_found
== 0 && s
.download_dbinfo
!= 0 && !hex
.empty())
427 rc
= download_kernel_debuginfo(s
, hex
);
431 return setup_dwfl_kernel (modules_found
, s
);
436 DWFL_ASSERT ("dwfl_report_end", dwfl_report_end(dwfl
, NULL
, NULL
));
437 *modules_found
= offline_modules_found
;
443 setup_dwfl_kernel(const std::string
&name
,
445 systemtap_session
&s
)
447 current_session_for_find_debuginfo
= &s
;
448 const char *modname
= name
.c_str();
449 set
<string
> names
; // Default to empty
451 /* Support full path kernel modules, these cannot be regular
452 expressions, so just put them in the search set. */
453 if (name
[0] == '/' || ! dwflpp::name_has_wildcard (modname
))
459 offline_search_modname
= modname
;
460 offline_search_names
= names
;
462 return setup_dwfl_kernel(found
, s
);
466 setup_dwfl_kernel(const std::set
<std::string
> &names
,
468 systemtap_session
&s
)
470 current_session_for_find_debuginfo
= &s
;
472 offline_search_modname
= NULL
;
473 offline_search_names
= names
;
474 return setup_dwfl_kernel(found
, s
);
478 setup_dwfl_user(const std::string
&name
)
480 Dwfl
*dwfl
= dwfl_begin (&user_callbacks
);
481 DWFL_ASSERT("dwfl_begin", dwfl
);
482 dwfl_report_begin (dwfl
);
484 // XXX: should support buildid-based naming
485 const char *cname
= name
.c_str();
486 Dwfl_Module
*mod
= dwfl_report_offline (dwfl
, cname
, cname
, -1);
487 DWFL_ASSERT ("dwfl_report_end", dwfl_report_end(dwfl
, NULL
, NULL
));
498 setup_dwfl_user(std::vector
<std::string
>::const_iterator
&begin
,
499 const std::vector
<std::string
>::const_iterator
&end
,
500 bool all_needed
, systemtap_session
&s
)
502 current_session_for_find_debuginfo
= &s
;
503 // See if we have this dwfl already cached
504 set
<string
> modset(begin
, end
);
506 Dwfl
*dwfl
= dwfl_begin (&user_callbacks
);
507 DWFL_ASSERT("dwfl_begin", dwfl
);
508 dwfl_report_begin (dwfl
);
509 Dwfl_Module
*mod
= NULL
;
510 // XXX: should support buildid-based naming
511 while (begin
!= end
&& dwfl
!= NULL
)
513 const char *cname
= (*begin
).c_str();
514 mod
= dwfl_report_offline (dwfl
, cname
, cname
, -1);
515 if (! mod
&& all_needed
)
523 /* Extract the build id and add it to the session variable
524 * so it will be added to the script hash */
527 const unsigned char *bits
;
530 clog
<< _("Extracting build ID.") << endl
;
531 int bits_length
= dwfl_module_build_id(mod
, &bits
, &vaddr
);
533 /* Convert the binary bits to a hex string */
534 string hex
= hex_dump(bits
, bits_length
);
536 //Store the build ID in the session
537 s
.build_ids
.push_back(hex
);
541 DWFL_ASSERT ("dwfl_report_end", dwfl_report_end(dwfl
, NULL
, NULL
));
547 is_user_module(const std::string
&m
)
549 return m
[0] == '/' && m
.rfind(".ko", m
.length() - 1) != m
.length() - 3;
553 internal_find_debuginfo (Dwfl_Module
*mod
,
554 void **userdata
__attribute__ ((unused
)),
555 const char *modname
__attribute__ ((unused
)),
556 GElf_Addr base
__attribute__ ((unused
)),
557 const char *file_name
,
558 const char *debuglink_file
,
559 GElf_Word debuglink_crc
,
560 char **debuginfo_file_name
)
566 /* To Keep track of whether the abrt successfully installed the debuginfo */
567 static int install_dbinfo_failed
= 0;
569 /* Make sure the current session variable is not null */
570 if(current_session_for_find_debuginfo
== NULL
)
571 goto call_dwfl_standard_find_debuginfo
;
573 /* Check to see if download-debuginfo=0 was set */
574 if(!current_session_for_find_debuginfo
->download_dbinfo
|| abrt_path
.empty())
575 goto call_dwfl_standard_find_debuginfo
;
577 /* Check that we haven't already run this */
578 if (install_dbinfo_failed
< 0)
580 if(current_session_for_find_debuginfo
->verbose
> 1)
581 current_session_for_find_debuginfo
->print_warning(_F("We already tried running '%s'", abrt_path
.c_str()));
582 goto call_dwfl_standard_find_debuginfo
;
585 /* Extract the build ID */
586 const unsigned char *bits
;
588 if(current_session_for_find_debuginfo
->verbose
> 2)
589 clog
<< _("Extracting build ID.") << endl
;
590 bits_length
= dwfl_module_build_id(mod
, &bits
, &vaddr
);
592 /* Convert the binary bits to a hex string */
593 hex
= hex_dump(bits
, bits_length
);
595 /* Search for the debuginfo with the build ID */
596 if(current_session_for_find_debuginfo
->verbose
> 2)
597 clog
<< _F("Searching for debuginfo with build ID: '%s'.", hex
.c_str()) << endl
;
600 int fd
= dwfl_build_id_find_debuginfo(mod
,
603 debuginfo_file_name
);
608 /* The above failed, so call abrt-action-install-debuginfo-to-abrt-cache
609 to download and install the debuginfo */
610 if(current_session_for_find_debuginfo
->verbose
> 1)
611 clog
<< _F("Downloading and installing debuginfo with build ID: '%s' using %s.",
612 hex
.c_str(), abrt_path
.c_str()) << endl
;
614 struct tms tms_before
;
615 times (& tms_before
);
616 struct timeval tv_before
;
617 struct tms tms_after
;
618 unsigned _sc_clk_tck
;
619 struct timeval tv_after
;
620 gettimeofday (&tv_before
, NULL
);
622 if(execute_abrt_action_install_debuginfo_to_abrt_cache (hex
) < 0)
624 install_dbinfo_failed
= -1;
625 current_session_for_find_debuginfo
->print_warning(_F("%s failed.", abrt_path
.c_str()));
626 goto call_dwfl_standard_find_debuginfo
;
629 _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
631 gettimeofday (&tv_after
, NULL
);
632 if(current_session_for_find_debuginfo
->verbose
> 1)
633 clog
<< _("Download completed in ")
634 << ((tms_after
.tms_cutime
+ tms_after
.tms_utime
635 - tms_before
.tms_cutime
- tms_before
.tms_utime
) * 1000 / (_sc_clk_tck
)) << "usr/"
636 << ((tms_after
.tms_cstime
+ tms_after
.tms_stime
637 - tms_before
.tms_cstime
- tms_before
.tms_stime
) * 1000 / (_sc_clk_tck
)) << "sys/"
638 << ((tv_after
.tv_sec
- tv_before
.tv_sec
) * 1000 +
639 ((long)tv_after
.tv_usec
- (long)tv_before
.tv_usec
) / 1000) << "real ms"<< endl
;
641 call_dwfl_standard_find_debuginfo
:
643 /* Call the original dwfl_standard_find_debuginfo */
644 return dwfl_standard_find_debuginfo(mod
, userdata
, modname
, base
,
645 file_name
, debuglink_file
,
646 debuglink_crc
, debuginfo_file_name
);
651 execute_abrt_action_install_debuginfo_to_abrt_cache (string hex
)
653 /* Be sure that abrt exists */
654 if (abrt_path
.empty())
657 int timeout
= current_session_for_find_debuginfo
->download_dbinfo
;;
659 cmd
.push_back ("/bin/sh");
660 cmd
.push_back ("-c");
662 /* NOTE: abrt does not currently work with asking for confirmation
663 * in version abrt-2.0.3-1.fc15.x86_64, Bugzilla: BZ726192 */
664 if(current_session_for_find_debuginfo
->download_dbinfo
== -1)
666 cmd
.push_back ("echo " + hex
+ " | " + abrt_path
+ " --ids=-");
668 current_session_for_find_debuginfo
->print_warning(_("Due to bug in abrt, it may continue downloading anyway without asking for confirmation."));
671 cmd
.push_back ("echo " + hex
+ " | " + abrt_path
+ " -y --ids=-");
673 /* NOTE: abrt does not allow canceling the download process at the moment
674 * in version abrt-2.0.3-1.fc15.x86_64, Bugzilla: BZ730107 */
675 if(timeout
!= INT_MAX
)
676 current_session_for_find_debuginfo
->print_warning(_("Due to a bug in abrt, it may continue downloading after stopping stap if download times out."));
679 if(current_session_for_find_debuginfo
->verbose
> 1 || current_session_for_find_debuginfo
->download_dbinfo
== -1)
680 /* Execute abrt-action-install-debuginfo-to-abrt-cache,
681 * showing output from abrt */
682 pid
= stap_spawn(current_session_for_find_debuginfo
->verbose
, cmd
, NULL
);
685 /* Execute abrt-action-install-debuginfo-to-abrt-cache,
686 * without showing output from abrt */
687 posix_spawn_file_actions_t fa
;
688 if (posix_spawn_file_actions_init(&fa
) != 0)
690 if(posix_spawn_file_actions_addopen(&fa
, 1, "/dev/null", O_WRONLY
, 0) != 0)
692 posix_spawn_file_actions_destroy(&fa
);
695 pid
= stap_spawn(current_session_for_find_debuginfo
->verbose
, cmd
, &fa
);
696 posix_spawn_file_actions_destroy(&fa
);
699 /* Check to see if either the program successfully completed, or if it timed out. */
703 while(timer
< timeout
)
706 rc
= waitpid(pid
, &rstatus
, WNOHANG
);
709 if (rc
> 0 && WIFEXITED(rstatus
))
711 assert_no_interrupts();
718 current_session_for_find_debuginfo
->print_warning(_("Aborted downloading debuginfo: timed out."));
722 /* Successfully finished downloading! */
723 #if 0 // Should not print this until BZ733690 is fixed as abrt could fail to download
724 // and it would still print success.
725 if(current_session_for_find_debuginfo
->verbose
> 1 || current_session_for_find_debuginfo
->download_dbinfo
== -1)
726 clog
<< _("Download Completed Successfully!") << endl
;
728 if(current_session_for_find_debuginfo
->verbose
> 1 || current_session_for_find_debuginfo
->download_dbinfo
== -1)
729 clog
<< _("ABRT finished attempting to download debuginfo.") << endl
;
734 /* Get the kernel build ID */
736 get_kernel_build_id(systemtap_session
&s
)
741 // Try to find BuildID from vmlinux.id
742 string kernel_buildID_path
= s
.kernel_build_tree
+ "/vmlinux.id";
744 clog
<< _F("Attempting to extract kernel debuginfo build ID from %s", kernel_buildID_path
.c_str()) << endl
;
745 ifstream buildIDfile
;
746 buildIDfile
.open(kernel_buildID_path
.c_str());
747 if(buildIDfile
.is_open())
749 getline(buildIDfile
, hex
);
750 if(buildIDfile
.good())
757 // Try to find BuildID from the notes file if the above didn't work and we are
758 // building a native module
759 if(found
== false && s
.native_build
)
762 clog
<< _("Attempting to extract kernel debuginfo build ID from /sys/kernel/notes") << endl
;
764 const char *notesfile
= "/sys/kernel/notes";
765 int fd
= open64 (notesfile
, O_RDONLY
);
769 assert (sizeof (Elf32_Nhdr
) == sizeof (GElf_Nhdr
));
770 assert (sizeof (Elf64_Nhdr
) == sizeof (GElf_Nhdr
));
775 unsigned char data
[8192];
778 ssize_t n
= read (fd
, buf
.data
, sizeof buf
);
784 unsigned char *p
= buf
.data
;
785 while (p
< &buf
.data
[n
])
787 /* No translation required since we are reading the native kernel. */
788 GElf_Nhdr
*nhdr
= (GElf_Nhdr
*) p
;
790 unsigned char *name
= p
;
791 p
+= (nhdr
->n_namesz
+ 3) & -4U;
792 unsigned char *bits
= p
;
793 p
+= (nhdr
->n_descsz
+ 3) & -4U;
795 if (p
<= &buf
.data
[n
]
796 && nhdr
->n_type
== NT_GNU_BUILD_ID
797 && nhdr
->n_namesz
== sizeof "GNU"
798 && !memcmp (name
, "GNU", sizeof "GNU"))
801 hex
= hex_dump(bits
, nhdr
->n_descsz
);
814 /* Find the kernel build ID and attempt to download the matching debuginfo */
815 int download_kernel_debuginfo (systemtap_session
&s
, string hex
)
817 // NOTE: At some point we want to base the
818 // already_tried_downloading_kernel_debuginfo flag on the build ID rather
819 // than just the stap process.
821 // Don't try this again if we already did.
822 static int already_tried_downloading_kernel_debuginfo
= 0;
823 if(already_tried_downloading_kernel_debuginfo
)
826 // Attempt to download the debuginfo
828 clog
<< _F("Success! Extracted kernel debuginfo build ID: %s", hex
.c_str()) << endl
;
829 int rc
= execute_abrt_action_install_debuginfo_to_abrt_cache(hex
);
830 already_tried_downloading_kernel_debuginfo
= 1;