[PATCH 2/3] libdwfl: Search for the last matching address in lines
Josh Stone
jistone at redhat.com
Fri Dec 12 01:23:36 UTC 2014
Now that libdw's srclines use a stable sort, we can reliably choose the
*last* matching line record for a given address, which should be the
innermost where inlines are concerned.
Signed-off-by: Josh Stone <jistone at redhat.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/dwfl_module_getsrc.c | 51 +++++++++++++++++++++++---------------------
2 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index b882f2049ca0..7b0ea15f013f 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2014-12-11 Josh Stone <jistone at redhat.com>
+
+ * dwfl_module_getsrc.c (dwfl_module_getsrc): Return the *last* line
+ record <= addr, rather than returning immediately on matches.
+
2014-12-07 Mark Wielaard <mjw at redhat.com>
* relocate.c (relocate_section): Sanity check section overlap against
diff --git a/libdwfl/dwfl_module_getsrc.c b/libdwfl/dwfl_module_getsrc.c
index cf8dc0fc2d0a..41cf9753313e 100644
--- a/libdwfl/dwfl_module_getsrc.c
+++ b/libdwfl/dwfl_module_getsrc.c
@@ -1,5 +1,5 @@
/* Find source location for PC address in module.
- Copyright (C) 2005, 2008 Red Hat, Inc.
+ Copyright (C) 2005, 2008, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -42,32 +42,35 @@ dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr)
error = __libdwfl_cu_getsrclines (cu);
if (likely (error == DWFL_E_NOERROR))
{
- /* Now we look at the module-relative address. */
- addr -= bias;
-
- /* The lines are sorted by address, so we can use binary search. */
- size_t l = 0, u = cu->die.cu->lines->nlines;
- while (l < u)
+ Dwarf_Lines *lines = cu->die.cu->lines;
+ size_t nlines = lines->nlines;
+ if (nlines > 0)
{
- size_t idx = (l + u) / 2;
- if (addr < cu->die.cu->lines->info[idx].addr)
- u = idx;
- else if (addr > cu->die.cu->lines->info[idx].addr)
- l = idx + 1;
- else
- return &cu->lines->idx[idx];
- }
+ /* This is guaranteed for us by libdw read_srclines. */
+ assert(lines->info[nlines - 1].end_sequence);
- if (cu->die.cu->lines->nlines > 0)
- assert (cu->die.cu->lines->info
- [cu->die.cu->lines->nlines - 1].end_sequence);
+ /* Now we look at the module-relative address. */
+ addr -= bias;
- /* If none were equal, the closest one below is what we want.
- We never want the last one, because it's the end-sequence
- marker with an address at the high bound of the CU's code. */
- if (u > 0 && u < cu->die.cu->lines->nlines
- && addr > cu->die.cu->lines->info[u - 1].addr)
- return &cu->lines->idx[u - 1];
+ /* The lines are sorted by address, so we can use binary search. */
+ size_t l = 0, u = nlines - 1;
+ while (l < u)
+ {
+ size_t idx = u - (u - l) / 2;
+ Dwarf_Line *line = &lines->info[idx];
+ if (addr < line->addr)
+ u = idx - 1;
+ else if (addr >= line->addr)
+ l = idx;
+ }
+
+ /* The last line which is less than or equal to addr is what we want,
+ except with an end_sequence which can only be strictly equal. */
+ Dwarf_Line *line = &lines->info[l];
+ if (line->addr == addr
+ || (! line->end_sequence && line->addr < addr))
+ return &cu->lines->idx[l];
+ }
error = DWFL_E_ADDR_OUTOFRANGE;
}
--
2.1.0
More information about the elfutils-devel
mailing list