GNU Binutils with patches for OS216
修订版 | 76b3c0a5333ab4741e9d4d0c57972c1d14a8cd19 (tree) |
---|---|
时间 | 2015-02-23 16:44:23 |
作者 | Cary Coutant <ccoutant@goog...> |
Commiter | Cary Coutant |
Support compressed debug in dyn objects.
2015-02-09 Cary Coutant <ccoutant@google.com>
gold/
* dwp.cc (Sized_relobj_dwo::do_decompressed_section_contents): Delete.
(Sized_relobj_dwo::setup): Setup map of compressed sections.
(print_version): Update copyright.
* dynobj.cc (Sized_dynobj::base_read_symbols): Set up map of compressed
sections.
* object.cc (Sized_relobj_file::compressed_sections): Delete.
(build_compressed_section_map): Add decompress_if_needed parameter.
Adjust callers.
(Sized_relobj_file::do_find_special_sections): Set compressed sections
map in Object base class.
(Sized_relobj_file::do_decompressed_section_contents): Rename to
Object::decompressed_section_contents.
(Sized_relobj_file::do_discard_decompressed_sections): Rename to
Object::discard_decompressed_sections.
* object.h (Object::compressed_sections_): New data member.
(Object::section_is_compressed): Remove virtual, implement here.
(Object::decompressed_section_contents): Remove virtual.
(Object::do_section_is_compressed): Delete.
(Object::do_decompressed_section_contents): Delete.
(Object::set_compressed_sections): New method.
(Object::compressed_sections): New method.
(Sized_relobj_file::do_section_is_compressed): Delete.
(Sized_relobj_file::do_decompressed_section_contents): Delete.
(Sized_relobj_file::do_discard_decompressed_sections): Delete.
(Sized_relobj_file::compressed_sections): Delete.
@@ -284,14 +284,6 @@ class Sized_relobj_dwo : public Sized_relobj<size, big_endian> | ||
284 | 284 | const unsigned char* |
285 | 285 | do_section_contents(unsigned int, section_size_type*, bool); |
286 | 286 | |
287 | - // Return a view of the uncompressed contents of a section. Set *PLEN | |
288 | - // to the size. Set *IS_NEW to true if the contents need to be deleted | |
289 | - // by the caller. | |
290 | - const unsigned char* | |
291 | - do_decompressed_section_contents(unsigned int shndx, | |
292 | - section_size_type* plen, | |
293 | - bool* is_new); | |
294 | - | |
295 | 287 | // The following virtual functions are abstract in the base classes, |
296 | 288 | // but are not used here. |
297 | 289 |
@@ -781,9 +773,36 @@ template <int size, bool big_endian> | ||
781 | 773 | void |
782 | 774 | Sized_relobj_dwo<size, big_endian>::setup() |
783 | 775 | { |
776 | + const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size; | |
777 | + const off_t shoff = this->elf_file_.shoff(); | |
784 | 778 | const unsigned int shnum = this->elf_file_.shnum(); |
779 | + | |
785 | 780 | this->set_shnum(shnum); |
786 | 781 | this->section_offsets().resize(shnum); |
782 | + | |
783 | + // Read the section headers. | |
784 | + const unsigned char* const pshdrs = this->get_view(shoff, shnum * shdr_size, | |
785 | + true, false); | |
786 | + | |
787 | + // Read the section names. | |
788 | + const unsigned char* pshdrnames = | |
789 | + pshdrs + this->elf_file_.shstrndx() * shdr_size; | |
790 | + typename elfcpp::Shdr<size, big_endian> shdrnames(pshdrnames); | |
791 | + if (shdrnames.get_sh_type() != elfcpp::SHT_STRTAB) | |
792 | + this->error(_("section name section has wrong type: %u"), | |
793 | + static_cast<unsigned int>(shdrnames.get_sh_type())); | |
794 | + section_size_type section_names_size = | |
795 | + convert_to_section_size_type(shdrnames.get_sh_size()); | |
796 | + const unsigned char* namesu = this->get_view(shdrnames.get_sh_offset(), | |
797 | + section_names_size, false, | |
798 | + false); | |
799 | + const char* names = reinterpret_cast<const char*>(namesu); | |
800 | + | |
801 | + Compressed_section_map* compressed_sections = | |
802 | + build_compressed_section_map<size, big_endian>( | |
803 | + pshdrs, this->shnum(), names, section_names_size, this, true); | |
804 | + if (compressed_sections != NULL && !compressed_sections->empty()) | |
805 | + this->set_compressed_sections(compressed_sections); | |
787 | 806 | } |
788 | 807 | |
789 | 808 | // Return a view of the contents of a section. |
@@ -805,43 +824,6 @@ Sized_relobj_dwo<size, big_endian>::do_section_contents( | ||
805 | 824 | return this->get_view(loc.file_offset, *plen, true, cache); |
806 | 825 | } |
807 | 826 | |
808 | -// Return a view of the uncompressed contents of a section. Set *PLEN | |
809 | -// to the size. Set *IS_NEW to true if the contents need to be deleted | |
810 | -// by the caller. | |
811 | - | |
812 | -template <int size, bool big_endian> | |
813 | -const unsigned char* | |
814 | -Sized_relobj_dwo<size, big_endian>::do_decompressed_section_contents( | |
815 | - unsigned int shndx, | |
816 | - section_size_type* plen, | |
817 | - bool* is_new) | |
818 | -{ | |
819 | - section_size_type buffer_size; | |
820 | - const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size, | |
821 | - false); | |
822 | - | |
823 | - std::string sect_name = this->do_section_name(shndx); | |
824 | - if (!is_prefix_of(".zdebug_", sect_name.c_str())) | |
825 | - { | |
826 | - *plen = buffer_size; | |
827 | - *is_new = false; | |
828 | - return buffer; | |
829 | - } | |
830 | - | |
831 | - section_size_type uncompressed_size = get_uncompressed_size(buffer, | |
832 | - buffer_size); | |
833 | - unsigned char* uncompressed_data = new unsigned char[uncompressed_size]; | |
834 | - if (!decompress_input_section(buffer, | |
835 | - buffer_size, | |
836 | - uncompressed_data, | |
837 | - uncompressed_size)) | |
838 | - this->error(_("could not decompress section %s"), | |
839 | - this->section_name(shndx).c_str()); | |
840 | - *plen = uncompressed_size; | |
841 | - *is_new = true; | |
842 | - return uncompressed_data; | |
843 | -} | |
844 | - | |
845 | 827 | // Class Dwo_file. |
846 | 828 | |
847 | 829 | Dwo_file::~Dwo_file() |
@@ -2352,7 +2334,7 @@ print_version() | ||
2352 | 2334 | { |
2353 | 2335 | // This output is intended to follow the GNU standards. |
2354 | 2336 | printf("GNU dwp %s\n", BFD_VERSION_STRING); |
2355 | - printf(_("Copyright (C) 2014-2015 Free Software Foundation, Inc.\n")); | |
2337 | + printf(_("Copyright (C) 2015 Free Software Foundation, Inc.\n")); | |
2356 | 2338 | printf(_("\ |
2357 | 2339 | This program is free software; you may redistribute it under the terms of\n\ |
2358 | 2340 | the GNU General Public License version 3 or (at your option) any later version.\n\ |
@@ -374,6 +374,17 @@ Sized_dynobj<size, big_endian>::base_read_symbols(Read_symbols_data* sd) | ||
374 | 374 | sd->verneed_size = 0; |
375 | 375 | sd->verneed_info = 0; |
376 | 376 | |
377 | + const unsigned char* namesu = sd->section_names->data(); | |
378 | + const char* names = reinterpret_cast<const char*>(namesu); | |
379 | + if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL) | |
380 | + { | |
381 | + Compressed_section_map* compressed_sections = | |
382 | + build_compressed_section_map<size, big_endian>( | |
383 | + pshdrs, this->shnum(), names, sd->section_names_size, this, true); | |
384 | + if (compressed_sections != NULL) | |
385 | + this->set_compressed_sections(compressed_sections); | |
386 | + } | |
387 | + | |
377 | 388 | if (this->dynsym_shndx_ != -1U) |
378 | 389 | { |
379 | 390 | // Get the dynamic symbols. |
@@ -432,8 +432,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file( | ||
432 | 432 | discarded_eh_frame_shndx_(-1U), |
433 | 433 | is_deferred_layout_(false), |
434 | 434 | deferred_layout_(), |
435 | - deferred_layout_relocs_(), | |
436 | - compressed_sections_() | |
435 | + deferred_layout_relocs_() | |
437 | 436 | { |
438 | 437 | this->e_type_ = ehdr.get_e_type(); |
439 | 438 | } |
@@ -675,7 +674,8 @@ build_compressed_section_map( | ||
675 | 674 | unsigned int shnum, |
676 | 675 | const char* names, |
677 | 676 | section_size_type names_size, |
678 | - Sized_relobj_file<size, big_endian>* obj) | |
677 | + Object* obj, | |
678 | + bool decompress_if_needed) | |
679 | 679 | { |
680 | 680 | Compressed_section_map* uncompressed_map = new Compressed_section_map(); |
681 | 681 | const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size; |
@@ -707,7 +707,7 @@ build_compressed_section_map( | ||
707 | 707 | if (uncompressed_size != -1ULL) |
708 | 708 | { |
709 | 709 | unsigned char* uncompressed_data = NULL; |
710 | - if (need_decompressed_section(name)) | |
710 | + if (decompress_if_needed && need_decompressed_section(name)) | |
711 | 711 | { |
712 | 712 | uncompressed_data = new unsigned char[uncompressed_size]; |
713 | 713 | if (decompress_input_section(contents, len, |
@@ -741,9 +741,14 @@ Sized_relobj_file<size, big_endian>::do_find_special_sections( | ||
741 | 741 | this->has_eh_frame_ = true; |
742 | 742 | |
743 | 743 | if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL) |
744 | - this->compressed_sections_ | |
745 | - = build_compressed_section_map(pshdrs, this->shnum(), names, | |
746 | - sd->section_names_size, this); | |
744 | + { | |
745 | + Compressed_section_map* compressed_sections = | |
746 | + build_compressed_section_map<size, big_endian>( | |
747 | + pshdrs, this->shnum(), names, sd->section_names_size, this, true); | |
748 | + if (compressed_sections != NULL) | |
749 | + this->set_compressed_sections(compressed_sections); | |
750 | + } | |
751 | + | |
747 | 752 | return (this->has_eh_frame_ |
748 | 753 | || (!parameters->options().relocatable() |
749 | 754 | && parameters->options().gdb_index() |
@@ -2804,9 +2809,8 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts( | ||
2804 | 2809 | // to the size. Set *IS_NEW to true if the contents need to be freed |
2805 | 2810 | // by the caller. |
2806 | 2811 | |
2807 | -template<int size, bool big_endian> | |
2808 | 2812 | const unsigned char* |
2809 | -Sized_relobj_file<size, big_endian>::do_decompressed_section_contents( | |
2813 | +Object::decompressed_section_contents( | |
2810 | 2814 | unsigned int shndx, |
2811 | 2815 | section_size_type* plen, |
2812 | 2816 | bool* is_new) |
@@ -2860,9 +2864,8 @@ Sized_relobj_file<size, big_endian>::do_decompressed_section_contents( | ||
2860 | 2864 | // Discard any buffers of uncompressed sections. This is done |
2861 | 2865 | // at the end of the Add_symbols task. |
2862 | 2866 | |
2863 | -template<int size, bool big_endian> | |
2864 | 2867 | void |
2865 | -Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections() | |
2868 | +Object::discard_decompressed_sections() | |
2866 | 2869 | { |
2867 | 2870 | if (this->compressed_sections_ == NULL) |
2868 | 2871 | return; |
@@ -314,6 +314,21 @@ class Got_offset_list | ||
314 | 314 | Got_offset_list* got_next_; |
315 | 315 | }; |
316 | 316 | |
317 | +// Type for mapping section index to uncompressed size and contents. | |
318 | + | |
319 | +struct Compressed_section_info | |
320 | +{ | |
321 | + section_size_type size; | |
322 | + const unsigned char* contents; | |
323 | +}; | |
324 | +typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map; | |
325 | + | |
326 | +template<int size, bool big_endian> | |
327 | +Compressed_section_map* | |
328 | +build_compressed_section_map(const unsigned char* pshdrs, unsigned int shnum, | |
329 | + const char* names, section_size_type names_size, | |
330 | + Object* obj, bool decompress_if_needed); | |
331 | + | |
317 | 332 | // Object is an abstract base class which represents either a 32-bit |
318 | 333 | // or a 64-bit input object. This can be a regular object file |
319 | 334 | // (ET_REL) or a shared object (ET_DYN). |
@@ -332,7 +347,8 @@ class Object | ||
332 | 347 | : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U), |
333 | 348 | is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false), |
334 | 349 | has_no_split_stack_(false), no_export_(false), |
335 | - is_in_system_directory_(false), as_needed_(false), xindex_(NULL) | |
350 | + is_in_system_directory_(false), as_needed_(false), xindex_(NULL), | |
351 | + compressed_sections_(NULL) | |
336 | 352 | { |
337 | 353 | if (input_file != NULL) |
338 | 354 | { |
@@ -725,26 +741,34 @@ class Object | ||
725 | 741 | set_no_export(bool value) |
726 | 742 | { this->no_export_ = value; } |
727 | 743 | |
728 | - // Return TRUE if the section is a compressed debug section, and set | |
729 | - // *UNCOMPRESSED_SIZE to the size of the uncompressed data. | |
730 | 744 | bool |
731 | 745 | section_is_compressed(unsigned int shndx, |
732 | 746 | section_size_type* uncompressed_size) const |
733 | - { return this->do_section_is_compressed(shndx, uncompressed_size); } | |
747 | + { | |
748 | + if (this->compressed_sections_ == NULL) | |
749 | + return false; | |
750 | + Compressed_section_map::const_iterator p = | |
751 | + this->compressed_sections_->find(shndx); | |
752 | + if (p != this->compressed_sections_->end()) | |
753 | + { | |
754 | + if (uncompressed_size != NULL) | |
755 | + *uncompressed_size = p->second.size; | |
756 | + return true; | |
757 | + } | |
758 | + return false; | |
759 | + } | |
734 | 760 | |
735 | 761 | // Return a view of the decompressed contents of a section. Set *PLEN |
736 | 762 | // to the size. Set *IS_NEW to true if the contents need to be freed |
737 | 763 | // by the caller. |
738 | 764 | const unsigned char* |
739 | 765 | decompressed_section_contents(unsigned int shndx, section_size_type* plen, |
740 | - bool* is_cached) | |
741 | - { return this->do_decompressed_section_contents(shndx, plen, is_cached); } | |
766 | + bool* is_cached); | |
742 | 767 | |
743 | 768 | // Discard any buffers of decompressed sections. This is done |
744 | 769 | // at the end of the Add_symbols task. |
745 | 770 | void |
746 | - discard_decompressed_sections() | |
747 | - { this->do_discard_decompressed_sections(); } | |
771 | + discard_decompressed_sections(); | |
748 | 772 | |
749 | 773 | // Return the index of the first incremental relocation for symbol SYMNDX. |
750 | 774 | unsigned int |
@@ -923,27 +947,6 @@ class Object | ||
923 | 947 | bool |
924 | 948 | handle_split_stack_section(const char* name); |
925 | 949 | |
926 | - // Return TRUE if the section is a compressed debug section, and set | |
927 | - // *UNCOMPRESSED_SIZE to the size of the uncompressed data. | |
928 | - virtual bool | |
929 | - do_section_is_compressed(unsigned int, section_size_type*) const | |
930 | - { return false; } | |
931 | - | |
932 | - // Return a view of the decompressed contents of a section. Set *PLEN | |
933 | - // to the size. This default implementation simply returns the | |
934 | - // raw section contents and sets *IS_NEW to false to indicate | |
935 | - // that the contents do not need to be freed by the caller. | |
936 | - // This function must be overridden for any types of object files | |
937 | - // that might contain compressed sections. | |
938 | - virtual const unsigned char* | |
939 | - do_decompressed_section_contents(unsigned int shndx, | |
940 | - section_size_type* plen, | |
941 | - bool* is_new) | |
942 | - { | |
943 | - *is_new = false; | |
944 | - return this->do_section_contents(shndx, plen, false); | |
945 | - } | |
946 | - | |
947 | 950 | // Discard any buffers of decompressed sections. This is done |
948 | 951 | // at the end of the Add_symbols task. |
949 | 952 | virtual void |
@@ -962,6 +965,14 @@ class Object | ||
962 | 965 | do_get_incremental_reloc_count(unsigned int) const |
963 | 966 | { gold_unreachable(); } |
964 | 967 | |
968 | + void | |
969 | + set_compressed_sections(Compressed_section_map* compressed_sections) | |
970 | + { this->compressed_sections_ = compressed_sections; } | |
971 | + | |
972 | + Compressed_section_map* | |
973 | + compressed_sections() | |
974 | + { return this->compressed_sections_; } | |
975 | + | |
965 | 976 | private: |
966 | 977 | // This class may not be copied. |
967 | 978 | Object(const Object&); |
@@ -996,6 +1007,9 @@ class Object | ||
996 | 1007 | bool as_needed_ : 1; |
997 | 1008 | // Many sections for objects with more than SHN_LORESERVE sections. |
998 | 1009 | Xindex* xindex_; |
1010 | + // For compressed debug sections, map section index to uncompressed size | |
1011 | + // and contents. | |
1012 | + Compressed_section_map* compressed_sections_; | |
999 | 1013 | }; |
1000 | 1014 | |
1001 | 1015 | // A regular object (ET_REL). This is an abstract base class itself. |
@@ -1862,15 +1876,6 @@ class Reloc_symbol_changes | ||
1862 | 1876 | std::vector<Symbol*> vec_; |
1863 | 1877 | }; |
1864 | 1878 | |
1865 | -// Type for mapping section index to uncompressed size and contents. | |
1866 | - | |
1867 | -struct Compressed_section_info | |
1868 | -{ | |
1869 | - section_size_type size; | |
1870 | - const unsigned char* contents; | |
1871 | -}; | |
1872 | -typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map; | |
1873 | - | |
1874 | 1879 | // Abstract base class for a regular object file, either a real object file |
1875 | 1880 | // or an incremental (unchanged) object. This is size and endian specific. |
1876 | 1881 |
@@ -2453,38 +2458,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian> | ||
2453 | 2458 | set_output_local_symbol_count(unsigned int value) |
2454 | 2459 | { this->output_local_symbol_count_ = value; } |
2455 | 2460 | |
2456 | - // Return TRUE if the section is a compressed debug section, and set | |
2457 | - // *UNCOMPRESSED_SIZE to the size of the uncompressed data. | |
2458 | - bool | |
2459 | - do_section_is_compressed(unsigned int shndx, | |
2460 | - section_size_type* uncompressed_size) const | |
2461 | - { | |
2462 | - if (this->compressed_sections_ == NULL) | |
2463 | - return false; | |
2464 | - Compressed_section_map::const_iterator p = | |
2465 | - this->compressed_sections_->find(shndx); | |
2466 | - if (p != this->compressed_sections_->end()) | |
2467 | - { | |
2468 | - if (uncompressed_size != NULL) | |
2469 | - *uncompressed_size = p->second.size; | |
2470 | - return true; | |
2471 | - } | |
2472 | - return false; | |
2473 | - } | |
2474 | - | |
2475 | - // Return a view of the uncompressed contents of a section. Set *PLEN | |
2476 | - // to the size. Set *IS_NEW to true if the contents need to be deleted | |
2477 | - // by the caller. | |
2478 | - const unsigned char* | |
2479 | - do_decompressed_section_contents(unsigned int shndx, | |
2480 | - section_size_type* plen, | |
2481 | - bool* is_new); | |
2482 | - | |
2483 | - // Discard any buffers of decompressed sections. This is done | |
2484 | - // at the end of the Add_symbols task. | |
2485 | - void | |
2486 | - do_discard_decompressed_sections(); | |
2487 | - | |
2488 | 2461 | private: |
2489 | 2462 | // For convenience. |
2490 | 2463 | typedef Sized_relobj_file<size, big_endian> This; |
@@ -2751,9 +2724,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian> | ||
2751 | 2724 | std::vector<Deferred_layout> deferred_layout_; |
2752 | 2725 | // The list of relocation sections whose layout was deferred. |
2753 | 2726 | std::vector<Deferred_layout> deferred_layout_relocs_; |
2754 | - // For compressed debug sections, map section index to uncompressed size | |
2755 | - // and contents. | |
2756 | - Compressed_section_map* compressed_sections_; | |
2757 | 2727 | }; |
2758 | 2728 | |
2759 | 2729 | // A class to manage the list of all objects. |