aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2018-04-16 10:25:35 +0200
committerMark Wielaard <mark@klomp.org>2018-04-16 10:25:35 +0200
commit40b1f188a3b3194c7f62db9760d81f07db229b33 (patch)
tree760b3ccef3c045871760408ab0a9d72b294ad75b /src
parenteaccd7870874d8a9821e298ceaabf492490b3fa7 (diff)
downloadelfutils-40b1f188a3b3194c7f62db9760d81f07db229b33.tar.gz
readelf: Fix advance_pc to use op_addr_advance, not just op_advance.
Found by John Mellor-Crummey. The reason this bug wasn't found earlier is because gcc fixes minimum_instr_len and max_ops_per_instr to 1 for all architectures (in theory max_ops_per_instr could be overridden, but I didn't find any architecture that does). And op_index always seems zero (it looks like it is really only for special VLWI architectures). So in all cases I saw it means that: op_addr_advance = minimum_instr_len * ((op_index + op_advance) / max_ops_per_instr) = 1 * ((0 + op_advance) / 1) = op_advance Completely masking the bug. The libdw dwarf_getsrclines.c implementation does get this right. Because it doesn't care about the data representation and so does the calculation directly. Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog5
-rw-r--r--src/readelf.c2
2 files changed, 6 insertions, 1 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 068c87b9..2d525e6d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2018-04-16 Mark Wielaard <mark@klomp.org>
+
+ * readelf.c (print_debug_line_section). In advance_pc, advance
+ using op_addr_advance, not op_advance.
+
2018-04-14 Mark Wielaard <mark@klomp.org>
* readelf.c (attr_callback): Only show errors when not silent.
diff --git a/src/readelf.c b/src/readelf.c
index 8c0ef6ca..45fc8265 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -6971,7 +6971,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
{
op_addr_advance = minimum_instr_len * ((op_index + op_advance)
/ max_ops_per_instr);
- address += op_advance;
+ address += op_addr_advance;
show_op_index = (op_index > 0 ||
(op_index + op_advance) % max_ops_per_instr > 0);
op_index = (op_index + op_advance) % max_ops_per_instr;