| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Calls to the gettext _() macro in hotpaths cause many runtime lookups
of the same translation strings. This patch introduces macro __()
which caches the result of _() at each call site where __() is used.
When a cached translation string is used as the format string for
fprintf, the compiler might raise a -Wformat-nonliteral warning.
To avoid this, the -Wformat-nonliteral warning is suppressed using _Pragma
around affected fprintf calls, using IGNORE_FMT_NONLITERAL_BEGIN and
_END wrappers.
To avoid suppressing -Wformat-nonliteral across every printf-style
function using _(), __() and IGNORE_FMT_NONLITERAL_* are mostly used
within hotpath loops where caching makes a signficant difference.
Runtime improvements of up to 13% faster have been observed with this patch
applied.
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
| |
Improve __libdw_dieabbrev performance by removing abbrev_lock. This
lock protects the Dwarf_Die abbrev member due to lazy loading.
Instead, eagerly load abbrev during Dwarf_Die initialization so that
the member is readonly and requires no locking.
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Implement concurrent execution of print_debug_* functions during handling
of -w, --debug-dump using libthread.a.
A new `-C, --concurrency=NUM` command line option controls the maximum
number of threads that may be used. This value defaults to the number of CPUs.
Job output is buffered and printed in the order that jobs were added to
the queue. This helps preserve the existing order of stdout output.
* src/readelf.c (default_concurrency): Function estimating the
maximum number of threads.
(parse_opt): Handle -C, --concurrency=NUM.
(do_job): Entry point function for threads.
(schedule_job): If thread safety is enabled, add job to the
job queue. Otherwise just run the job from the main thread.
(print_debug): Pass print_debug_* function pointers and
args to schedule_job. Also call run_jobs if thread safety
is enabled.
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Safely handle stdout output during concurrent calls to print_debug_*
functions.
For any print_debug_* function and any function that could be called
from print_debug_* which also prints to stdout: add a FILE * argument
and replace all printf, puts, putchar with fprintf. All printing
to stdout will now be written to this FILE instead.
The FILE * is an interface to a per-thread dynamically-sized buffer.
libthread.a manages the allocation, printing and deallocation of
these buffers.
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add new internal static library libthread.a that provides infrastructure
for eu-* tools to run functions concurrently using pthreads.
threadlib.c manages per-job threads as well as per-job buffers for stdout
output. Output for each job is printed to stdout in the order that the
jobs were added to the job queue. This helps preserve the order of
output when parallelization is added to an eu-* tool.
threadlib.h declares functions add_job and run_jobs. Jobs are added to
a threadlib.c internal job queue using add_job. run_jobs concurrently
executes jobs in parallel.
eu-readelf now links against libthread.a when elfutils is configured
with --enable-thread-safety.
* src/Makefile.am: libthread.a is compiled and and linked with
readelf when USE_LOCKS is defined.
* src/threadlib.c: New file. Manages job creation, concurrent
execution and output handling.
* src/threadlib.h: New file. Declares functions add_job and
run_jobs.
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
| |
DEFAULT_INCLUDES includes -I. which is needed for compiling the
testcases with -DMAIN_CHECK=1.
This fixes make check after commit 76bd5f6bea9b "config: Adjust
AM_CPPFLAGS for srcdir and .. path includes"
* libdw/Makefile.am (CHECK_DEF_FLAGS): Add DEFAULT_INCLUDES.
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When building with clang and libc++ some standard headers might try
including <stack> even when no source file requests such include
directly. When building with srcdir == builddir this might clash in
the src dir since we then build a stack binary there and the src dir
also has srcfiles.cxx which might include some standard c++ headers.
Work around this by removing -I.. from AM_CPPFLAGS and replacing it
with -I(abs_top_builddir) where the <config.h> file can be found. And
use -iquote for srcdir so it doesn't get included in the search path
for the system <header> includes (only for "header" includes).
Note that DEFAULT_INCLUDES might add . and srcdir back. So
DEFAULT_INCLUDES is disabled explicitly in src/Makefile.am (where the
stack binary is build). We could also use the nostdinc automake option
to completely suppress that, but that needs more auditing of various
installed vs not-installed header files.
* config/eu.am (AM_CPPFLAGS): Use -iquote for $(srcdir) and
replace -I.. with -I$(abs_top_builddir).
* libdw/libdwP.h: Include "libdw.h" and "dwarf.h" instead of
the system headers <libdw.h> and <dwarf.h>.
https://sourceware.org/bugzilla/show_bug.cgi?id=33103
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
dwfl_module_getsym returns the name of a symbol as found in the
corresponding (symbol) string section. Make sure all names are
correctly zero terminated by making sure the last valid index in a
section/segment Elf_Data contains a zero character.
* libdwfl/dwfl_module_getdwarf.c (validate_strdata): New
function taking Elf_Data and restricting d_size to last zero
char.
(translate_offs): Call validate_strdata.
(find_symtab): Likewise for both symstrdata and aux_symstrdata.
https://sourceware.org/bugzilla/show_bug.cgi?id=33099
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
| |
__libdw_fde_by_offset is marked as an extern internal function in
libdw/cfi.h (a not public header file). But it is (now) only used in
libdw/fde.c, called from __libdw_find_fde. It was originally used for
dwarf_cfi_validate_fde, but that function was deleted and never made
public. So simplify things and make it static in libdw/fde.c.
* libdw/cfi.h (__libdw_fde_by_offset): Remove.
* libdw/fde.c (__libdw_fde_by_offset): Make static.
|
|
|
|
|
|
|
|
|
| |
If some section doesn't match between the stripped and unstripped file
we invent a new one. Make sure to also update the shnum value.
* src/unstrip.c (copy_elided_sections): Update unstripped_shnum.
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some "illegal" instructions can be up to 24 chars (192 bits), We'll
print this as 0x<48 hex chars>. So make sure the mnebuf is 50 chars
(no terminating zero is needed).
This shows up with _FORTIFY_SOURCE which would immediate terminate on
such "illegal" instructions. Without we just use a few extra bytes on
the stack (which aren't used afterwards, without any issue, even
though it is technically UB).
* libcpu/riscv_disasm.c (riscv_disasm): Extend char mnebuf
array to 50.
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
eu_tfind is used to facilitate lazy loading throughout libdw.
If a result is not found via eu_tfind, work is done to load
the result and cache it in an eu_search_tree.
Some calls to eu_tfind allow for TOCTOU bugs. Multiple threads
might race to call eu_tfind on some result that hasn't yet been
cached. Multiple threads may then attempt to load the result
which might cause an unnecessary amount of memory to be allocated.
Additionally this memory may not get released when the associated
libdw data structure is freed.
Fix this by adding additional locking to ensure that only one
thread performs lazy loading.
One approach used in this patch is to preserve calls to eu_tfind
without additional locking, but when the result isn't found then
a lock is then used to synchronize access to the lazy loading code.
An extra eu_tfind call has been added at the start of these critical
section to synchronize verification that lazy loading should proceed.
Another approach used is to simply synchronize entire calls to
functions where lazy loading via eu_tfind might occur (__libdw_find_fde
and __libdw_intern_expression). In this case, new _nolock variants of
the eu_t* functions are used to avoid unnecessary double locking.
lib/
* eu-search.c: Add eu_tsearch_nolock, eu_tfind_nolock and
eu_tdelete_nolock functions.
* eu-search.h: Ditto.
libdw/
* cfi.h (struct Dwarf_CFI_s): Declare new mutex.
* dwarf_begin_elf.c (valid_p): Initialize all locks for fake CUs.
* dwarf_cfi_addrframe.c (dwarf_cfi_addrframe): Place lock around
__libdw_find_fde.
* dwarf_end.c (cu_free): Deallocate all locks unconditionally,
whether or not the CU is fake.
* dwarf_frame_cfa.c (dwarf_frame_cfa): Place lock around
__libdw_intern_expression.
* dwarf_frame_register.c (dwarf_frame_register): Ditto.
* dwarf_getcfi.c (dwarf_getcfi): Initialize cfi lock.
* dwarf_getlocation.c (is_constant_offset): Synchronize access
to lazy loading section.
(getlocation): Place lock around __libdw_intern_expression.
* dwarf_getmacros.c (cache_op_table): Synchronize access to lazy
loading section.
* frame-cache.c (__libdw_destroy_frame_cache): Free Dwarf_CFI
mutex.
* libdwP.h (struct Dwarf): Update macro_lock comment.
(struct Dwarf_CU): Declare new mutex.
libdw_findcu.c (__libdw_intern_next_unit): Initialize
intern_lock.
(__libdw_findcu): Adjust locking so that the first eu_tfind
can be done without extra lock overhead.
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
| |
Whenever possible, resolve all symlinks as if the sysroot path were a
chroot environment. This prevents potential interactions with files from
the host filesystem.
Signed-off-by: Michal Sekletar <[email protected]>
|
|
|
|
|
|
|
|
|
|
| |
If there is only section zero that shouldn't count. Then we would
still try to work on an empty set of sections and give an obscure
error later.
* src/unstrip.c (copy_elided_sections): Check stripped_shnum <= 1.
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
| |
When an explicit type of long double is specified in the ELF
GNU_Power_ABI_FP attribute, elflint and friends were erroring out:
section [36] '.gnu.attributes': offset 15: unrecognized GNU_Power_ABI_FP attribute value 9
Add the different long double tags to fp_kinds so that these values
are correctly recognised and printed.
Signed-off-by: A. Wilcox <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
handle_dynamic_symtab can attempt to read symbol and version data from
file offset of 0 or address of 0 if the associated DT_ tags aren't found.
Fix this by only reading symbol and version data when non-zero file
offsets/addresses have been found.
https://sourceware.org/bugzilla/show_bug.cgi?id=32864
Suggested-by: Constantine Bytensky <[email protected]>
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The testsuite relies on there being no files in the test directory
after the test finishes. A test will fail if the test dir cannot be
removed. But the test dir isn't really random, it uses the pid of the
shell script that executes the test. On some of the buildbots that
execute a lot of tests it can happen that the pid number wraps around
and a pid of a previous pid is reused. To prevent that happening
generate a real random number (8 bytes) using od /dev/urandom and
xargs (to trim away spaces left by od).
* tests/test-subr.sh: Define test_name and random_number and use
those to define test_dir.
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
| |
This reverts commit deca125665a76cf024bd063ff4f477cb675ad41e.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Missing a few pieces, but worth sharing as an RFC. My idea is to
ensure better test coverage for eu-stack and then
eu-stacktrace+libdwfl_stacktrace by running against a live process
with known content, stopped at a known location, and aggressively
scrubbing output that's known to vary from testrun to testrun.
This is a very basic preview of how that might look. If the approach
is sound, I hope to make it more sophisticated/reliable.
Unanswered questions:
- Scrub more data (e.g. libc symvers) from a more known program.
Scrub stack frame numbers to account for a case where extra frames
appear / are missing at the bottom of the stack?
- Something better than sed for the scrubbing?
- An equivalent eu-stacktrace test will require privileged perf_events
access for profiling data and therefore likely to be skipped by
default. How feasible is it to be enabled on the buildbots, though?
* tests/run-stack-live-test.sh: New test with wild and fuzzy
testrun_compare variant that scrubs inherently unpredictable parts of
the data. Needs to scrub even more.
* tests/Makefile.am (TESTS): Add run-stack-live-test.sh.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
asm/perf_regs.h is an arch-specific linux include, not present on
architectures like hppa and m68k that lack perf_events support.
Only one place we need to fix; others already guard the include by
architecture, or use architecture-independent headers (e.g.
linux/perf_events.h).
* backends/libebl_PERF_FLAGS.h: Only include asm/perf_regs.h on
architectures where we use it.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
| |
We want to test the program against the just build libelf.so not the
system installed one. So add an RPATH to ../libelf.
* libdw/Makefile.am (CHECK_DEF_FLAGS): Add -Wl,-rpath,../libelf.
https://sourceware.org/bugzilla/show_bug.cgi?id=32929
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
| |
* src/unstrip.c (copy_elided_sections): Check elf_getdata result
for symtab and strtab sections.
Suggested-by: Anton Moryakov <[email protected]>
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
handle_core_item calls gelf_getehdr for each item without checking if
the call succeeds. It should always succeed because process_elf_file
already checked gelf_getehdr returned a valid Ehdr before passing it
to handle_notes. Just pass the Ehdr down a couple more function calls.
* readelf.c (handle_core_item): Take const Gelf_Ehdr and use it.
(handle_core_items): Take const Gelf_Ehdr and pass it to
handle_core_item.
(handle_core_note): Take const Gelf_Ehdr and pass it to
handle_core_items.
(handle_notes_data): Pass ehdr to handle_core_note.
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
| |
When elf_getahdr returns NULL we shouldn't even try to handle the ar
header, but immediately go to the next entry.
* src/ar.c (do_oper_extract): If elf_getahdr goto next.
(do_oper_delete): Likewise.
(do_oper_insert): Likewise.
Suggested-by: Anton Moryakov <[email protected]>
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
| |
Set version to 0.193.
Update NEWS, elftuils.spec.in and lib/printversion.c.
Regenerate po/*.po files.
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
| |
Signed-off-by: Aaron Merey <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Remove the code from src/stacktrace.c that is now covered by
libdwfl_stacktrace/dwflst_perf_frame.c and
dwflst_perf_sample_getframes.
* src/stacktrace.c (show_memory_reads): Remove this verbose option as
the relevant code is inside libdwfl_stacktrace now.
(struct __sample_arg): Remove, handled by
libdwfl_stacktrace/dwflst_perf_frame.c.
(sample_next_thread): Ditto.
(sample_getthread): Ditto.
(copy_word_64): Ditto.
(copy_word_32): Ditto.
(elf_memory_read): Ditto.
(sample_memory_read): Ditto.
(sample_set_initial_registers): Ditto.
(sample_detach): Ditto.
(sample_thread_callbacks): Ditto.
(sysprof_find_dwfl): Now also return the Elf* so that it can be
passed to dwflst_perf_sample_getframes. Don't create sample_arg. Do
record sp in sui->last_sp. Don't dwfl_attach_state,
dwflst_perf_sample_getframes handles that now.
(sysprof_unwind_cb): Adapt to sysprof_find_dwfl changes,
now invoke dwflst_perf_sample_getframes instead of
dwfl_getthread_frames.
(parse_opt): Remove show_memory_reads.
(main): Remove show_memory_reads.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a new interface for unwinding that doesn't require the Dwfl to
be attached to a live process (via ptrace) or via corefile. Instead,
data from a perf_events stack sample is provided along with an Elf
struct used to identify the architecture. Based on code from
eu-stacktrace.
* libdwfl_stacktrace/libdwfl_stacktrace.h (dwflst_perf_sample_getframes):
New function.
* libdwfl_stacktrace/dwflst_perf_frame.c
(struct __libdwfl_stacktrace_perf_sample_info): New struct, based on
src/stacktrace.c struct sample_arg.
(sample_next_thread): New function, based on src/stacktrace.c.
(sample_getthread): Ditto.
(copy_word_64): New macro, based on src/stacktrace.c.
(copy_word_32): Ditto.
(copy_word): Ditto.
(elf_memory_read): New function, based on src/stacktrace.c.
(sample_memory_read): Ditto.
(sample_set_initial_registers): Ditto.
(sample_detach): Ditto.
(sample_thread_callbacks): New struct, set of callbacks based on
src/stacktrace.c sample_thread_callbacks.
(dwflst_perf_sample_getframes): New function, based on parts of
src/stacktrace.c sysprof_find_dwfl. If the Dwfl is not attached,
attaches it with sample_thread_callbacks and
__libdwfl_stacktrace_perf_sample_info. Populates the
__libdwfl_stacktrace_perf_sample_info with data from the stack
sample and calls dwfl_getthread_frames to unwind it using the
sample_thread_callbacks.
* libdw/libdw.map (ELFUTILS_0.193_EXPERIMENTAL): Add
dwflst_perf_sample_getframes.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Initial minimal change to ensure dwflst_tracker_find_pid is
tested. For now, we keep the additional dwfltab implementation in
stacktrace.c, since it's being used to track statistics.
In future follow-ups, it will be good to switch to storing
eu-stacktrace statistics e.g. in dwfl->process->callbacks_arg. This
requires some additional design to keep the statistics from being lost
when a pid is reused and the corresponding processtracker table entry
is replaced.
* src/stacktrace.c (sysprof_init_dwfl): New function.
(sysprof_find_dwfl): Rename the existing sysprof_init_dwfl.
Also use dwflst_tracker_find_pid with callback.
(sysprof_unwind_cb): Rename the existing sysprof_init_dwfl.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
New function that retrieves the Dwfl for a particular PID, or,
if the Dwfl is absent, creates it via a provided callback
and adds it to the table later, when the PID is confirmed
via dwfl_attach_state.
* libdwfl_stacktrace/libdwfl_stacktrace.h (dwflst_tracker_find_pid):
New function.
* libdwfl_stacktrace/dwfl_process_tracker.c (dwflst_tracker_find_pid):
New function; find a Dwfl in the dwfltab or create one using the
provided callback. The newly created Dwfl will be added to the
dwfltab automatically when its pid is confirmed by a call to
dwfl_attach_state.
* libdw/libdw.map: Add dwflst_tracker_find_pid.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Dwflst_Process_Tracker also includes a dynamicsizehash cache which
maps process ids to Dwfl * (or rather, dwflst_tracker_dwfl_info *
allowing the table entry to be replaced). Dwfls created from
the tracker are automatically added to it, and removed on dwfl_end().
* libdwfl_stacktrace/libdwfl_stacktraceP.h (dwflst_tracker_dwfl_info):
New typedef, provides indirection to allow a dwfltab entry to be
invalidated.
(struct Dwflst_Process_Tracker): add dwfltab.
(__libdwfl_stacktrace_add_dwfl_to_tracker): New function.
(__libdwfl_stacktrace_remove_dwfl_from_tracker): New function.
* libdwfl_stacktrace/dwflst_process_tracker.c
(dwflst_tracker_begin): Init dwfltab.
(__libdwfl_stacktrace_add_dwfl_to_tracker): New function; add dwfl
to dwfltab.
(__libdwfl_stacktrace_remove_dwfl_from_tracker): New function;
invalidate dwfl entry, since dynamicsizehash doesn't support
outright deletion.
(dwflst_tracker_end): Clean up dwfltab. Lock and iterate the table
to free tracker->dwfltab.table items.
* libdwfl_stacktrace/dwflst_tracker_dwfltab.c: New file, instantiates
lib/dynamicsizehash_concurrent.c to store dwfltracker_dwfl_info
structs.
* libdwfl_stacktrace/dwflst_tracker_dwfltab.h: New file, ditto.
* libdwfl_stacktrace/Makefile.am
(libdwfl_stacktrace_a_SOURCES): Add dwflst_tracker_dwfltab.c.
(noinst_HEADERS): Add dwflst_tracker_dwfltab.h.
* libdwfl/dwfl_frame.c (dwfl_attach_state):
Call __libdwfl_stacktrace_add_dwfl_to_tracker.
* libdwfl/dwfl_end.c (dwfl_end): Add INTDEF.
Call __libdwfl_stacktrace_remove_dwfl_from_tracker.
* libdwfl/libdwflP.h (INTDECLs): Add dwfl_end.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
| |
* src/Makefile.am (AM_CPPFLAGS): Include headers from
../libdwfl_stacktrace.
* src/stacktrace.c (tracker): New global variable.
(sample_callbacks): Use dwflst_tracker_linux_proc_find_elf for
caching.
(sysprof_init_dwfl): Use dwflst_tracker_dwfl_begin.
(main): Initialize and clean up tracker.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Dwflst_Process_Tracker includes a dynamicsizehash cache which maps
file paths to Elf * (or rather, dwflst_tracker_elf_info * storing fd
and Elf *). We provide a dwflst_tracker_linux_proc_find_elf callback
which checks the cache for an already-loaded Elf * and, if missing,
populates the cache with the fd returned by dwfl_linux_proc_find_elf.
Later, open_elf updates the cache with the Elf * for that fd. The
commented asserts in dwflst_tracker_cache_elf still catch some cases
where a redundant Elf * is being created without checking the cache.
Since the Elf * outlasts the Dwfl that created it, we use the
(convenient, already-existing) reference count field in Elf * to
retain the data in the table. Then dwfl_end calling elf_end will
decrement the refcount cleanly, and dwflst_tracker_end will issue
another elf_end call.
* libdwfl_stacktrace/libdwfl_stacktrace.h
(dwflst_tracker_find_cached_elf): New function.
(dwflst_tracker_cache_elf): New function.
(dwflst_module_gettracker): New function, gives external users
a way to access Dwflst_Process_Tracker given a Dwfl_Module.
(dwflst_tracker_linux_proc_find_elf): New function, serves as a
cached version of the dwfl_linux_proc_find_elf callback.
* libdwfl_stacktrace/libdwfl_stacktraceP.h (dwflst_tracker_elf_info):
New struct typedef.
(struct Dwflst_Process_Tracker): Add dynamicsizehash table of
dwflst_tracker_elf_info structs + associated rwlock.
(INTDECLs): Add INTDECL for dwflst_tracker_find_cached_elf,
dwflst_tracker_cache_elf, dwflst_module_gettracker.
* libdwfl_stacktrace/dwflst_tracker_elftab.c: New file, instantiates
lib/dynamicsizehash_concurrent.c to store dwflst_tracker_elf_info
structs.
* libdwfl_stacktrace/dwflst_tracker_elftab.h: New file, ditto.
* libdwfl_stacktrace/libdwfl_stacktrace_next_prime.c: New file.
* libdwfl_stacktrace/dwflst_process_tracker.c (dwflst_tracker_begin):
Init elftab.
(dwflst_tracker_end): Clean up elftab. Lock and iterate the hash to
free tracker->elftab.table items.
* libdwfl_stacktrace/dwflst_tracker_find_elf.c: New file, implements a
find_elf callback that wraps dwfl_linux_proc_find_elf with
additional caching logic, and an API to access the
Dwflst_Process_Tracker Elf cache when implementing a custom find_elf
callback.
* libdwfl_stacktrace/Makefile.am (libdwfl_stacktrace_a_SOURCES): Add
dwflst_tracker_find_elf.c, dwflst_tracker_elftab.c,
libdwfl_stacktrace_next_prime.c.
(noinst_HEADERS): Add dwflst_tracker_elftab.h.
* libdw/libdw.map: Add dwflst_tracker_find_cached_elf,
dwflst_tracker_cache_elf,
dwflst_module_gettracker,
dwflst_tracker_linux_proc_find_elf.
* libdwfl/Makefile.am (AM_CPPFLAGS): Include headers from
../libdwfl_stacktrace.
* libdwfl/dwfl_module_getdwarf.c (open_elf): Cache file->elf in
Dwflst_Process_Tracker. Must be done here as
dwfl_linux_proc_find_elf opens an fd but does not yet create the
Elf *.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
New data structure to coordinate caching Elf data among multiple Dwfl
structs attached to different processes. Meant to reduce the overhead
for profilers that use elfutils for unwinding.
The caching is well-justified, as the prior approach (e.g. in
eu-stacktrace, sysprof-live-unwinder) of creating a separate Dwfl per
process was wildly redundant, opening ~hundreds of file descriptors
just for each common library such as libc.so and leaking the data.
Initial patch just introduces the struct, to be filled in by the rest
of the patch series.
* libdwfl_stacktrace/libdwfl_stacktrace.h
(Dwflst_Process_Tracker): New struct.
(dwflst_tracker_begin): New function.
(dwflst_tracker_dwfl_begin): New function.
(dwflst_tracker_end): New function.
* libdw/libdw.map: Add new functions.
* libdwfl_stacktrace/libdwfl_stacktraceP.h
(struct Dwflst_Process_Tracker): New struct.
* libdwfl/libdwflP.h (Dwflst_Process_Tracker): Typedef forward decl.
(struct Dwfl): Add 'tracker' field.
* libdwfl_stacktrace/Makefile.am (libdwfl_stacktrace_a_SOURCES):
Add dwflst_process_tracker.c.
* libdwfl_stacktrace/dwflst_process_tracker.c: New file.
(dwflst_tracker_begin): Initialize the tracker.
(dwflst_tracker_dwfl_begin): Initialize Dwfl * with specified tracker.
(dwflst_tracker_end): Deallocate the tracker.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
dwflst_perf_sample_preferred_regs_mask
Subsequent patches in the series introduce a new library for
tracking/caching Elf structs across multiple processes and wrapping
the libebl perf register handling (since libebl is a private
interface).
In this patch, add the library and an interface to access the set of
registers that libdwfl needs to allow proper unwinding of stack sample
data. (Unwinding with a smaller set of registers can be attempted,
but will yield a truncated call chain in most cases.)
(Accessing the set of registers feels like an implementation detail,
but the profiler invoking perf_event_open and elfutils unwinding code
need to agree on the exact set of registers being requested. So it's
best for the profiler to ask elfutils for this detail.)
* libdwfl_stacktrace/Makefile.am: New file.
* libdwfl_stacktrace/libdwfl_stacktrace.h: New file, library for
tracking/caching Elf structs and unwinding across multiple
processes.
* libdwfl_stacktrace/libdwfl_stacktraceP.h: New file.
* libdwfl_stacktrace/dwflst_perf_frame.c: New file.
(dwflst_perf_sample_preferred_regs_mask): New function.
* libdw/libdw.map: Add dwflst_perf_sample_preferred_regs_mask.
* NEWS: Add NEWS item about libdwfl_stacktrace.
* configure.ac: Add libdwfl_stacktrace/Makefile.
* Makefile.am (SUBDIRS): Add libdwfl_stacktrace.
* libdw/Makefile.am (libdw_so_LIBS): Add libdwfl_stacktrace.
(libdwfl_stacktrace_objects): Add libdwfl_stacktrace.manifest.
(libdw_a_LIBADD): Add libdwfl_stacktrace_objects.
* config/elfutils.spec.in (%files devel): Add libdwfl_stacktrace.h.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Dummy commit to show how the sample_set_initial_registers callback in
eu-stacktrace would use the proper libebl
ebl_set_initial_registers_sample function (if it were public).
* src/Makefile.am (stacktrace_LDADD): Add libebl.
* src/stacktrace.c (sample_registers_cb): New function,
though identical to pid_thread_state_registers_cb.
(sample_set_initial_registers): (XXX Invoke
ebl_set_initial_registers_sample instead of containing
platform-specific code directly. This is now commented out.
Patch12 in the series replaces with code in
libdwfl_stacktrace/dwflst_perf_frame.c.)
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Renaming pid_set_initial_registers to
__libdwfl_set_initial_registers_thread and adding to libdwflP.h.
This callback was private to one file, but now we need to access it
from the perf_events sampling code as well.
* libdwfl/libdwflP.h (__libdwfl_set_initial_registers_thread): New function.
* libdwfl/linux-pid-attach.c (__libdwfl_set_initial_registers_thread):
Renamed from pid_thread_state_registers_cb.
(pid_set_initial_registers): Pass the newly renamed callback.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
First patch of a series that reworks eu-stacktrace functionality
into a library interface for other profiling tools.
* * *
As it happens, Linux perf_events and DWARF can prescribe completely
different layouts for the register file, requiring non-obvious code
for translation. This makes sense to put in libebl if we want
profilers to handle perf sample data with elfutils.
Start with the x86_64/i386 implementation taken from eu-stacktrace. The
code has been generalized to accept other perf register masks besides
the 'preferred' one.
* backends/Makefile.am (i386_SRCS): Add i386_initreg_sample.c.
(x86_64_SRCS): Add x86_64_initreg_sample.c.
(noinst_HEADERS): Add libebl_PERF_FLAGS.h,
linux-perf-regs.c, x86_initreg_sample.c.
* backends/libebl_PERF_FLAGS.h: New file.
* backends/linux-perf-regs.c: New file.
(perf_sample_find_reg): Index into a perf register array whose
contents are described by regs_mask. The target index is the index
of the register in the enum defined by
linux arch/N/include/uapi/asm/perf_regs.h on arch N.
* backends/x86_initreg_sample.c: New file, implements a generalized
version of the eu-stacktrace register shuffling for x86-64/i386.
* backends/x86_64_initreg_sample.c: New file, specializes
x86_initreg_sample.c for x86-64.
* backends/i386_initreg_sample.c: New file, specializes
i386_initreg_sample.c for i386.
* backends/x86_64_init.c (x86_64_init): Add initialization for
set_initial_registers_sample, perf_frame_regs_mask,
sample_base_addr, sample_pc.
* backends/i386_init.c (i386_init): Add initialization for
set_initial_registers_sample, perf_frame_regs_mask,
sample_base_addr, sample_pc.
* libebl/Makefile.am (libebl_a_SOURCES): Add eblinitreg_sample.c.
* libebl/ebl-hooks.h (set_initial_registers_sample): New hook.
(sample_base_addr): Ditto.
(sample_pc): Ditto.
* libebl/eblinitreg_sample.c: New file, implements ebl interface to
set_initial_registers_sample, sample_base_addr, sample_pc
backend hooks.
* libebl/libebl.h (ebl_set_initial_registers_sample): New function.
(ebl_perf_frame_regs_mask): New function.
(ebl_sample_base_addr): New function.
(ebl_sample_pc): New function.
* libebl/libeblP.h (struct ebl): Add perf_frame_regs_mask field
giving the preferred register mask.
Signed-off-by: Serhei Makarov <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
DW_LANG_Nim and DW_LNAME_Nim were added to the DWARF languages.
While adding them, and the default lower bounds, I noticed DW_LANG_V
and DW_LANG_Algol68 where missing in srclang_to_language an internal
helper function.
Testing through the public api is not that easy since you need a
Dwarf_Die with the right attributes. So this patch adds a way to
compile an individual source file with an optional main function that
can directly access the internal/static functions.
Note that it is almost generic. But even though using .SECONDEXPANSION
I couldn't figure out how to create the equivalent of a rule starting
with %_check$(EXEEXT) target. So for now the rule has to repeated for
every new _check TEST. And there needs to be a line to tell make dist
to not expect the fake source: nodist_src_check_SOURCES = src_check.c
The new test pointed out that there were a few more bugs with
DW_LANG_Dylan and DW_LNAME_Mojo. Also fix those.
* libdw/dwarf.h: Add DW_LANG_Nim and DW_LNAME_Nim.
* libdw/Makefile.am: Add check_PROGRAMS and TESTS for
dwarf_srclang_check.
* libdw/dwarf_default_lower_bound.c
(dwarf_default_lower_bound): Add DW_LANG_Nim.
(dwarf_language_lower_bound): Add DW_LNAME_Nim.
* libdw/dwarf_srclang.c (srclang_to_language): Handle
DW_LANG_Dylan, DW_LANG_V, DW_LANG_Algol68 and DW_LANG_Nim.
(language_to_srclang): Fix DW_LNAME_Mojo. Add DW_LNAME_Nim.
(test_lang): New function guarded by MAIN_CHECK.
(main): Likewise.
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Files that include both <config.h> and "system.h" might include
config.h twice. Prevent that by adding a guard check in system.h
before including config.h.
* lib/crc32.c: Use #ifdef HAVE_CONFIG_H instead of #if.
* lib/error.h: Check HAVE_CONFIG_H before including config.h.
* lib/system.h: Check both HAVE_CONFIG_H and whether
EU_CONFIG_H is defined before including config.h.
Suggested-by: Dmitry V. Levin <[email protected]>
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
| |
* configure.ac: Use AC_CHECK_HEADERS instead of
AC_COMPILE_IFELSE.
Suggested-by: Dmitry V. Levin <[email protected]>
Signed-off-by: Mark Wielaard <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When printing section headers, also include a key to what each flag
is at the end of the section header output.
* src/readelf.c (print_flag_info): New function.
(print_shdr): Call print_flag_info.
* tests/run-copyadd-sections.sh: Fix .extra grep by escaping \.
* tests/run-large-elf-file.sh: Likewise.
* tests/test-copymany-subr.sh: Likewise.
* tests/run-readelf-z.sh: Add Key to Flags to expected output.
* tests/run-retain.sh: Likewise.
* tests/run-strip-remove-keep.sh: Likewise.
https://sourceware.org/bugzilla/show_bug.cgi?id=29571
Signed-off-by: Samuel Zeter <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
| |
Use MHD_OPTION_SOCK_ADDR to bind the http listen socket to a single address.
The address should be an IPv4 or IPv6 address configured on the system:
--listen-address=127.0.0.1
--listen-address=::1
--listen-address='LOCAL_IPv4|IPv6_ADDRESS'
As debuginfod does not include any security features, a listen on the
localhost address is sufficient for a HTTP/HTTPS reverse-proxy setup.
Signed-off-by: Michael Trapp <[email protected]>
|