diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2013-07-25 11:05:35 +0200 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2013-07-25 11:05:35 +0200 |
commit | 10edf47b87e0b15459d8f74357e03c9440e3dcf3 (patch) | |
tree | 67a0affd058a0517e0b8dc52ff274c7ce1271bf5 | |
parent | 744fc6f97f1c32fbab0f2a124bfa053e88fc3697 (diff) | |
download | elfutils-10edf47b87e0b15459d8f74357e03c9440e3dcf3.tar.gz |
Fix run-unstrip-n.sh regression on CentOS-5 ppc.
last patch was a bit more heuristic than needed which was found on RHEL-5 ppc
(32-bit):
FAIL: run-unstrip-n.sh (exit: 1)
================================
--- unstrip.out 2013-07-23 23:23:49.000000000 +0200
+++ - 2013-07-23 23:23:49.434052534 +0200
@@ -4,4 +4,3 @@
0xfdf0000+0x1c0000 edf3dd232e09d01b90683889bd16b9406c52d4de@0xfdf0184 - - libc.so.6
0xffb0000+0x50000 edec437a85026a1cf8cda94003706202733130c1@0xffb0124 - - ld.so.1
0x10000000+0x20000 979b7a26747cc09bd84a42b311b5288c704baea5@0x10000174 . - [exe]
-0xf880000+0x201d4 - /lib/librt.so.1 /usr/lib/debug/lib/librt-2.5.so.debug librt.so.1
Therefore the new code generated this excessive line:
0xf880000+0x201d4 - /lib/librt.so.1 /usr/lib/debug/lib/librt-2.5.so.debug librt.so.1
The first part of debug dump is from DT_DEBUG, second part is from segments:
start=0xf880000 end=0xf8a01d4 l_ld=0xfd6fe20 name=/lib/librt.so.1
start=0xfc60000 end=0xfe031e4 l_ld=0xff9e270 name=/lib/libc.so.6
start=0xfe10000 end=0xfe421dc l_ld=0xfddfd98 name=/lib/libpthread.so.0
start=0xffb0000 end=0xfff0668 l_ld=0xffef9ac name=/lib/ld.so.1
module_start=0x100000 module_end=0x110000 dyn_vaddr=0x100ee4
module_start=0xfd50000 module_end=0xfd80000 dyn_vaddr=0xfd6fe20 /lib/librt.so.1
module_start=0xfdb0000 module_end=0xfdf0000 dyn_vaddr=0xfddfd98 /lib/libpthread.so.0
module_start=0xfdf0000 module_end=0xffb0000 dyn_vaddr=0xff9e270 /lib/libc.so.6
module_start=0xffb0000 module_end=0x10000000 dyn_vaddr=0xffef9ac /lib/ld.so.1
module_start=0x10000000 module_end=0x10020000 dyn_vaddr=0x10010850
When comparing conflicts for (found in segments)
module_start=0xfd50000 module_end=0xfd80000 dyn_vaddr=0xfd6fe20 /lib/librt.so.1
the code found this line conflicts (and discarded it):
start=0xfc60000 end=0xfe031e4 l_ld=0xff9e270 name=/lib/libc.so.6
but it did not discard also conflicting:
start=0xf880000 end=0xf8a01d4 l_ld=0xfd6fe20 name=/lib/librt.so.1
So I have changed/improved the algorithm - L_LD can be IMO compared exactly
but otherwise the ranges should be compared for every module, not just the
first one.
Again I am not much happy from this code, it should be using NT_FILE instead,
but when we keep compatibility with old OSes elfutils should not regress
there.
libdwfl/
2013-07-25 Jan Kratochvil <jan.kratochvil@redhat.com>
* dwfl_segment_report_module.c (dwfl_segment_report_module): Check for
conflicts all the modules, not just the first one. Compare L_LD if it
is equal, not if it is in a module address range.
Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
-rw-r--r-- | libdwfl/ChangeLog | 6 | ||||
-rw-r--r-- | libdwfl/dwfl_segment_report_module.c | 51 |
2 files changed, 36 insertions, 21 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 77faa850..88bdfc67 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,9 @@ +2013-07-25 Jan Kratochvil <jan.kratochvil@redhat.com> + + * dwfl_segment_report_module.c (dwfl_segment_report_module): Check for + conflicts all the modules, not just the first one. Compare L_LD if it + is equal, not if it is in a module address range. + 2013-07-23 Jan Kratochvil <jan.kratochvil@redhat.com> * libdwflP.h (__libdwfl_elf_address_range): Add internal_function. diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index 41487bf0..97f4a1af 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -470,28 +470,37 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, } } - /* Ignore this found module if it would conflict in address space with any - already existing module of DWFL. */ if (r_debug_info != NULL) - for (struct r_debug_info_module *module = r_debug_info->module; - module != NULL; module = module->next) - if ((module_end > module->start && module_start < module->end) - || (module_start <= module->l_ld && module->l_ld < module_end)) - { - if (! module->disk_file_has_build_id && build_id_len > 0) - { - if (module->elf != NULL) - { - elf_end (module->elf); - close (module->fd); - module->elf = NULL; - module->fd = -1; - } - break; - } - else if (module->elf != NULL) - return finish (); - } + { + bool skip_this_module = false; + for (struct r_debug_info_module *module = r_debug_info->module; + module != NULL; module = module->next) + if ((module_end > module->start && module_start < module->end) + || dyn_vaddr == module->l_ld) + { + if (! module->disk_file_has_build_id && build_id_len > 0) + { + /* Module found in segments with build-id is more reliable + than a module found via DT_DEBUG on disk without any + build-id. */ + if (module->elf != NULL) + { + elf_end (module->elf); + close (module->fd); + module->elf = NULL; + module->fd = -1; + } + } + else if (module->elf != NULL) + { + /* Ignore this found module if it would conflict in address + space with any already existing module of DWFL. */ + skip_this_module = true; + } + } + if (skip_this_module) + return finish (); + } /* Our return value now says to skip the segments contained within the module. */ |