summaryrefslogtreecommitdiff
path: root/libdwfl
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2019-12-11 17:29:44 -0800
committerMark Wielaard <mark@klomp.org>2019-12-18 21:18:59 +0100
commit2e75c987d591d3af313ee38a31ab677f6f4eb1ff (patch)
tree7f2bfca702f5dca0ce5e82a34d222273fa1cfb3f /libdwfl
parent277c2c54f5579523649a29d26966bfed35a159bf (diff)
downloadelfutils-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/ChangeLog7
-rw-r--r--libdwfl/libdwfl.h20
-rw-r--r--libdwfl/libdwflP.h7
-rw-r--r--libdwfl/segment.c35
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;
}