diff options
author | Omar Sandoval <osandov@fb.com> | 2019-12-11 17:29:44 -0800 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2019-12-18 21:18:59 +0100 |
commit | 2e75c987d591d3af313ee38a31ab677f6f4eb1ff (patch) | |
tree | 7f2bfca702f5dca0ce5e82a34d222273fa1cfb3f /libdwfl | |
parent | 277c2c54f5579523649a29d26966bfed35a159bf (diff) | |
download | elfutils-2e75c987d591d3af313ee38a31ab677f6f4eb1ff.tar.gz |
libdwfl: remove broken coalescing logic in dwfl_report_segment
dwfl_report_segment has some logic that detects when a segment is
contiguous with the previously reported segment, in which case it's
supposed to coalesce them. However, in this case, it actually returns
without updating the segment array at all. As far as I can tell, this
has always been broken. It appears that no one uses the coalescing logic
anyways, as they pass IDENT as NULL. Let's just get rid of the logic and
add a test case.
Signed-off-by: Omar Sandoval <osandov@fb.com>
Diffstat (limited to 'libdwfl')
-rw-r--r-- | libdwfl/ChangeLog | 7 | ||||
-rw-r--r-- | libdwfl/libdwfl.h | 20 | ||||
-rw-r--r-- | libdwfl/libdwflP.h | 7 | ||||
-rw-r--r-- | libdwfl/segment.c | 35 |
4 files changed, 26 insertions, 43 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index b6b427d4..b36a7ca6 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,10 @@ +2019-12-11 Omar Sandoval <osandov@fb.com> + + * libdwflP.h (Dwfl_Module): Remove coalescing state. + Rename lookup_tail_ndx to next_segndx. + * segment.c (dwfl_report_segment): Remove coalescing logic. + * libdwfl.h (dwfl_report_segment): Document that IDENT is ignored. + 2019-12-05 Mark Wielaard <mark@klomp.org> * linux-kernel-modules.c (find_kernel_elf): Also try to find diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index a0c1d357..d5fa06d4 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -111,7 +111,7 @@ extern void dwfl_report_begin (Dwfl *dwfl); /* Report that segment NDX begins at PHDR->p_vaddr + BIAS. If NDX is < 0, the value succeeding the last call's NDX - is used instead (zero on the first call). + is used instead (zero on the first call). IDENT is ignored. If nonzero, the smallest PHDR->p_align value seen sets the effective page size for the address space DWFL describes. @@ -120,21 +120,9 @@ extern void dwfl_report_begin (Dwfl *dwfl); Returns -1 for errors, or NDX (or its assigned replacement) on success. - When NDX is the value succeeding the last call's NDX (or is implicitly - so as above), IDENT is nonnull and matches the value in the last call, - and the PHDR and BIAS values reflect a segment that would be contiguous, - in both memory and file, with the last segment reported, then this - segment may be coalesced internally with preceding segments. When given - an address inside this segment, dwfl_addrsegment may return the NDX of a - preceding contiguous segment. To prevent coalesced segments, always - pass a null pointer for IDENT. - - The values passed are not stored (except to track coalescence). - The only information that can be extracted from DWFL later is the - mapping of an address to a segment index that starts at or below - it. Reporting segments at all is optional. Its only benefit to - the caller is to offer this quick lookup via dwfl_addrsegment, - or use other segment-based calls. */ + Reporting segments at all is optional. Its only benefit to the caller is to + offer this quick lookup via dwfl_addrsegment, or use other segment-based + calls. */ extern int dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias, const void *ident); diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index f631f946..25753de2 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -132,12 +132,7 @@ struct Dwfl GElf_Addr *lookup_addr; /* Start address of segment. */ Dwfl_Module **lookup_module; /* Module associated with segment, or null. */ int *lookup_segndx; /* User segment index, or -1. */ - - /* Cache from last dwfl_report_segment call. */ - const void *lookup_tail_ident; - GElf_Off lookup_tail_vaddr; - GElf_Off lookup_tail_offset; - int lookup_tail_ndx; + int next_segndx; struct Dwfl_User_Core *user_core; }; diff --git a/libdwfl/segment.c b/libdwfl/segment.c index d9599a7f..f6a3e84e 100644 --- a/libdwfl/segment.c +++ b/libdwfl/segment.c @@ -287,11 +287,15 @@ int dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias, const void *ident) { + /* This was previously used for coalescing segments, but it was buggy since + day one. We don't use it anymore. */ + (void)ident; + if (dwfl == NULL) return -1; if (ndx < 0) - ndx = dwfl->lookup_tail_ndx; + ndx = dwfl->next_segndx; if (phdr->p_align > 1 && (dwfl->segment_align <= 1 || phdr->p_align < dwfl->segment_align)) @@ -307,30 +311,19 @@ dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias, GElf_Addr end = __libdwfl_segment_end (dwfl, bias + phdr->p_vaddr + phdr->p_memsz); - /* Coalesce into the last one if contiguous and matching. */ - if (ndx != dwfl->lookup_tail_ndx - || ident == NULL - || ident != dwfl->lookup_tail_ident - || start != dwfl->lookup_tail_vaddr - || phdr->p_offset != dwfl->lookup_tail_offset) - { - /* Normally just appending keeps us sorted. */ + /* Normally just appending keeps us sorted. */ - size_t i = dwfl->lookup_elts; - while (i > 0 && unlikely (start < dwfl->lookup_addr[i - 1])) - --i; + size_t i = dwfl->lookup_elts; + while (i > 0 && unlikely (start < dwfl->lookup_addr[i - 1])) + --i; - if (unlikely (insert (dwfl, i, start, end, ndx))) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } + if (unlikely (insert (dwfl, i, start, end, ndx))) + { + __libdwfl_seterrno (DWFL_E_NOMEM); + return -1; } - dwfl->lookup_tail_ident = ident; - dwfl->lookup_tail_vaddr = end; - dwfl->lookup_tail_offset = end - bias - phdr->p_vaddr + phdr->p_offset; - dwfl->lookup_tail_ndx = ndx + 1; + dwfl->next_segndx = ndx + 1; return ndx; } |