* objdump -d --line-numbers performance question @ 2005-02-26 8:25 Emile Snyder 2005-03-01 11:11 ` Nick Clifton 0 siblings, 1 reply; 3+ messages in thread From: Emile Snyder @ 2005-02-26 8:25 UTC (permalink / raw) To: binutils [-- Attachment #1: Type: text/plain, Size: 1581 bytes --] Hello all, In one project I work on there's some scripts which we use to do debugging that use objdump to get at debugging symbol info to decode backtrace dumps from the program. The application binary is ~50MB when built with debugging info, and when we moved from developing on RedHat 7.3 to RH 9 or later, the objdump time went through the roof. I grabbed a binutils-2.14 tarball, and spent a little time digging. oprofile reports that some huge proportion of the time is spent in the bfd/elf.c:elf_find_function() call, which is being called (with some intermediates) by binutils/objdump.c:show_line(). Looking at elf_find_function() it jumps out that it's doing a linear search through the entire set of symbols every time it's called. But show_line() has access to find_symbol_for_address which does a binary search on a sorted set of symbols. So. The attached patch uses find_symbol_for_address() in show_line(), and then passes down a fake asymbol** list consisting of just the found symbol and a null end marker. So far it always produces identical 'objdump -d --line-numbers' output for me as the stock objdump, but my run time on one representative file has gone from ~2 hours to ~4 minutes. Does this look right? If not, can anyone give me some pointers on the right way to try to optimize things? Thanks, -emile +---------------------------------------------------------------------- this wine is particularly heavy, and is mostly recommended for hand-to-hand combat. -- Eric Idle +---------------------------------------------------------------------- [-- Attachment #2: binutils-2.14.objdumppatch --] [-- Type: text/x-patch, Size: 1027 bytes --] diff -Naur binutils-2.14/binutils/objdump.c binutils-2.14-modified/binutils/objdump.c --- binutils-2.14/binutils/objdump.c 2003-03-31 16:32:47.000000000 -0800 +++ binutils-2.14-modified/binutils/objdump.c 2005-02-25 12:02:43.617595584 -0800 @@ -980,13 +980,22 @@ const char *filename; const char *functionname; unsigned int line; + asymbol *foundsym; + asymbol *mocksyms[2]; + long symplace; if (! with_line_numbers && ! with_source_code) return; - if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, - &functionname, &line)) - return; + foundsym = find_symbol_for_address(abfd, section, + section->vma + addr_offset, + FALSE, &symplace); + mocksyms[0] = foundsym; + mocksyms[1] = NULL; + + if (! bfd_find_nearest_line (abfd, section, mocksyms, addr_offset, &filename, + &functionname, &line)) + return; if (filename != NULL && *filename == '\0') filename = NULL; ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: objdump -d --line-numbers performance question 2005-02-26 8:25 objdump -d --line-numbers performance question Emile Snyder @ 2005-03-01 11:11 ` Nick Clifton 2005-03-02 15:27 ` Emile Snyder 0 siblings, 1 reply; 3+ messages in thread From: Nick Clifton @ 2005-03-01 11:11 UTC (permalink / raw) To: Emile Snyder; +Cc: binutils [-- Attachment #1: Type: text/plain, Size: 1458 bytes --] Hi Emile, > Looking at elf_find_function() it jumps out that it's doing a linear > search through the entire set of symbols every time it's called. But > show_line() has access to find_symbol_for_address which does a binary > search on a sorted set of symbols. > > So. The attached patch uses find_symbol_for_address() in show_line(), > and then passes down a fake asymbol** list consisting of just the found > symbol and a null end marker. So far it always produces identical > 'objdump -d --line-numbers' output for me as the stock objdump, but my > run time on one representative file has gone from ~2 hours to ~4 > minutes. > > Does this look right? If not, can anyone give me some pointers on the > right way to try to optimize things? Actually this looks like a very good idea. I only have two improvements to suggest: 1. Be paranoid. If the call to bfd_find_nearest_line() fails to find the desired information with the abbreviated symbol table then it should be re-called with the full symbol table. 2. Use the latest sources. The 2.15 release is not going to have any new features added to it, so it is best to produce a patch against the latest sources in the binutils CVS repository. To that end, please could you try out the attached patch which is meant to address both of these points. If you can confirm that it does still work (and reduce the search times) then I will commit it to the sources. Cheers Nick [-- Attachment #2: objdump.c.patch --] [-- Type: text/plain, Size: 2837 bytes --] Index: binutils/objdump.c =================================================================== RCS file: /cvs/src/src/binutils/objdump.c,v retrieving revision 1.100 diff -c -3 -p -r1.100 objdump.c *** binutils/objdump.c 23 Feb 2005 12:25:57 -0000 1.100 --- binutils/objdump.c 1 Mar 2005 11:05:40 -0000 *************** skip_to_line (struct print_file_list *p, *** 1026,1042 **** listing. */ static void ! show_line (bfd *abfd, asection *section, bfd_vma addr_offset) { ! const char *filename; ! const char *functionname; ! unsigned int line; if (! with_line_numbers && ! with_source_code) return; ! if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, ! &functionname, &line)) return; if (filename != NULL && *filename == '\0') --- 1026,1065 ---- listing. */ static void ! show_line (bfd *abfd, asection *section, bfd_vma addr_offset, ! struct disassemble_info * info) { ! const char *filename = NULL; ! const char *functionname = NULL; ! unsigned int line = 0; ! asymbol *foundsym; ! long symplace; if (! with_line_numbers && ! with_source_code) return; ! /* bfd_find_nearest_line will perform a linear search of the symbol table ! for a matching address, but we already have a sorted symbol table and ! a binary search function, so try creating a fake symbol table first. */ ! foundsym = find_symbol_for_address (section->vma + addr_offset, ! info, & symplace); ! if (foundsym) ! { ! asymbol *mocksyms[2]; ! ! mocksyms[0] = foundsym; ! mocksyms[1] = NULL; ! ! /* We do not need to check the return code here since if it ! is zero then functionname will not have been initialised. */ ! (void) bfd_find_nearest_line (abfd, section, mocksyms, addr_offset, ! & filename, & functionname, & line); ! } ! ! if ((functionname == NULL || filename == NULL) ! /* Ourt shortcut failed. Try a full search. */ ! && (! bfd_find_nearest_line (abfd, section, syms, addr_offset, ! & filename, & functionname, & line))) return; if (filename != NULL && *filename == '\0') *************** disassemble_bytes (struct disassemble_in *** 1320,1326 **** /* The line number tables will refer to unadjusted section VMAs, so we must undo any VMA modifications when calling show_line. */ ! show_line (aux->abfd, section, addr_offset - adjust_section_vma); if (! prefix_addresses) { --- 1343,1349 ---- /* The line number tables will refer to unadjusted section VMAs, so we must undo any VMA modifications when calling show_line. */ ! show_line (aux->abfd, section, addr_offset - adjust_section_vma, info); if (! prefix_addresses) { ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: objdump -d --line-numbers performance question 2005-03-01 11:11 ` Nick Clifton @ 2005-03-02 15:27 ` Emile Snyder 0 siblings, 0 replies; 3+ messages in thread From: Emile Snyder @ 2005-03-02 15:27 UTC (permalink / raw) To: Nick Clifton; +Cc: binutils Thanks for the feedback. I couldn't get cvs to let me log in for some reason, so I tried this with binutils-050228.tar.bz2 Unfortunately it doesn't work there (although the similar idea -- defaulting to the old linear search of the whole list -- does work on 2.14). I'll keep digging and see if I can figure out what's going in. thanks, -emile On Tue, 2005-03-01 at 03:21, Nick Clifton wrote: > > Does this look right? If not, can anyone give me some pointers on the > > right way to try to optimize things? > > Actually this looks like a very good idea. I only have two improvements > to suggest: > > 1. Be paranoid. If the call to bfd_find_nearest_line() fails to find > the desired information with the abbreviated symbol table then it should > be re-called with the full symbol table. > > 2. Use the latest sources. The 2.15 release is not going to have any > new features added to it, so it is best to produce a patch against the > latest sources in the binutils CVS repository. > > To that end, please could you try out the attached patch which is meant > to address both of these points. If you can confirm that it does still > work (and reduce the search times) then I will commit it to the sources. > > Cheers > Nick > > > > > ______________________________________________________________________ > Index: binutils/objdump.c > =================================================================== > RCS file: /cvs/src/src/binutils/objdump.c,v > retrieving revision 1.100 > diff -c -3 -p -r1.100 objdump.c > *** binutils/objdump.c 23 Feb 2005 12:25:57 -0000 1.100 > --- binutils/objdump.c 1 Mar 2005 11:05:40 -0000 > *************** skip_to_line (struct print_file_list *p, > *** 1026,1042 **** > listing. */ > > static void > ! show_line (bfd *abfd, asection *section, bfd_vma addr_offset) > { > ! const char *filename; > ! const char *functionname; > ! unsigned int line; > > if (! with_line_numbers && ! with_source_code) > return; > > ! if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, > ! &functionname, &line)) > return; > > if (filename != NULL && *filename == '\0') > --- 1026,1065 ---- > listing. */ > > static void > ! show_line (bfd *abfd, asection *section, bfd_vma addr_offset, > ! struct disassemble_info * info) > { > ! const char *filename = NULL; > ! const char *functionname = NULL; > ! unsigned int line = 0; > ! asymbol *foundsym; > ! long symplace; > > if (! with_line_numbers && ! with_source_code) > return; > > ! /* bfd_find_nearest_line will perform a linear search of the symbol table > ! for a matching address, but we already have a sorted symbol table and > ! a binary search function, so try creating a fake symbol table first. */ > ! foundsym = find_symbol_for_address (section->vma + addr_offset, > ! info, & symplace); > ! if (foundsym) > ! { > ! asymbol *mocksyms[2]; > ! > ! mocksyms[0] = foundsym; > ! mocksyms[1] = NULL; > ! > ! /* We do not need to check the return code here since if it > ! is zero then functionname will not have been initialised. */ > ! (void) bfd_find_nearest_line (abfd, section, mocksyms, addr_offset, > ! & filename, & functionname, & line); > ! } > ! > ! if ((functionname == NULL || filename == NULL) > ! /* Ourt shortcut failed. Try a full search. */ > ! && (! bfd_find_nearest_line (abfd, section, syms, addr_offset, > ! & filename, & functionname, & line))) > return; > > if (filename != NULL && *filename == '\0') > *************** disassemble_bytes (struct disassemble_in > *** 1320,1326 **** > /* The line number tables will refer to unadjusted > section VMAs, so we must undo any VMA modifications > when calling show_line. */ > ! show_line (aux->abfd, section, addr_offset - adjust_section_vma); > > if (! prefix_addresses) > { > --- 1343,1349 ---- > /* The line number tables will refer to unadjusted > section VMAs, so we must undo any VMA modifications > when calling show_line. */ > ! show_line (aux->abfd, section, addr_offset - adjust_section_vma, info); > > if (! prefix_addresses) > { +---------------------------------------------------------------------- On two occasions I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question. -- Charles Babbage +---------------------------------------------------------------------- ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2005-03-02 15:27 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2005-02-26 8:25 objdump -d --line-numbers performance question Emile Snyder 2005-03-01 11:11 ` Nick Clifton 2005-03-02 15:27 ` Emile Snyder
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).