diff options
author | Marcin Kościelnicki <koriakin@0x04.net> | 2015-10-05 16:57:12 +0200 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2015-10-28 16:46:07 -0700 |
commit | 6f97897dbef256a80fb08c561b7f447aacf4bdf1 (patch) | |
tree | 614791546ab3e0a3b2ca1f2bb8f37b9354caa019 /gold | |
parent | 8d9743bd43d7c3123bfee2287e879dde0ac9bba4 (diff) | |
download | gdb-6f97897dbef256a80fb08c561b7f447aacf4bdf1.zip gdb-6f97897dbef256a80fb08c561b7f447aacf4bdf1.tar.gz gdb-6f97897dbef256a80fb08c561b7f447aacf4bdf1.tar.bz2 |
Add 64-bit archive support.
gold/
* archive.cc (Archive::sym64name): New const.
(Archive::setup): Add support for SYM64 armap.
(Archive::read_armap): Likewise.
(Archive::interpret_header): Likewise.
(Archive::const_iterator::read_next_header): Likewise.
* archive.h (Archive::sym64name): New const.
(Archive::read_armap): Add mapsize template parameter.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 10 | ||||
-rw-r--r-- | gold/archive.cc | 30 | ||||
-rw-r--r-- | gold/archive.h | 4 |
3 files changed, 38 insertions, 6 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index e4558a8..0957c53 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,15 @@ 2015-10-28 Marcin Kościelnicki <koriakin@0x04.net> + * archive.cc (Archive::sym64name): New const. + (Archive::setup): Add support for SYM64 armap. + (Archive::read_armap): Likewise. + (Archive::interpret_header): Likewise. + (Archive::const_iterator::read_next_header): Likewise. + * archive.h (Archive::sym64name): New const. + (Archive::read_armap): Add mapsize template parameter. + +2015-10-28 Marcin Kościelnicki <koriakin@0x04.net> + * dynobj.cc (Dynobj::create_elf_hash_table): Create hash table with target-specific entry size. (Dynobj::sized_create_elf_hash_table): Add size template parameter. diff --git a/gold/archive.cc b/gold/archive.cc index cc69c40..9c001c2 100644 --- a/gold/archive.cc +++ b/gold/archive.cc @@ -193,6 +193,8 @@ const char Archive::armagt[sarmag] = const char Archive::arfmag[2] = { '`', '\n' }; +const char Archive::sym64name[7] = { '/', 'S', 'Y', 'M', '6', '4', '/' }; + Archive::Archive(const std::string& name, Input_file* input_file, bool is_thin_archive, Dirsearch* dirpath, Task* task) : Library_base(task), name_(name), input_file_(input_file), armap_(), @@ -225,7 +227,12 @@ Archive::setup() off_t off = sarmag; if (armap_name.empty()) { - this->read_armap(sarmag + sizeof(Archive_header), armap_size); + this->read_armap<32>(sarmag + sizeof(Archive_header), armap_size); + off = sarmag + sizeof(Archive_header) + armap_size; + } + else if (armap_name == "/SYM64/") + { + this->read_armap<64>(sarmag + sizeof(Archive_header), armap_size); off = sarmag + sizeof(Archive_header) + armap_size; } else if (!this->input_file_->options().whole_archive()) @@ -277,6 +284,7 @@ Archive::unlock_nested_archives() // Read the archive symbol map. +template<int mapsize> void Archive::read_armap(off_t start, section_size_type size) { @@ -290,8 +298,10 @@ Archive::read_armap(off_t start, section_size_type size) const unsigned char* p = this->get_view(start, size, true, false); // Numbers in the armap are always big-endian. - const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p); - unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword); + typedef typename elfcpp::Elf_types<mapsize>::Elf_Addr Entry_type; + const Entry_type* pword = reinterpret_cast<const Entry_type*>(p); + unsigned long nsyms = convert_types<unsigned long, Entry_type>( + elfcpp::Swap<mapsize, true>::readval(pword)); ++pword; // Note that the addition is in units of sizeof(elfcpp::Elf_Word). @@ -303,10 +313,11 @@ Archive::read_armap(off_t start, section_size_type size) this->armap_.resize(nsyms); section_offset_type name_offset = 0; - for (unsigned int i = 0; i < nsyms; ++i) + for (unsigned long i = 0; i < nsyms; ++i) { this->armap_[i].name_offset = name_offset; - this->armap_[i].file_offset = elfcpp::Swap<32, true>::readval(pword); + this->armap_[i].file_offset = convert_types<off_t, Entry_type>( + elfcpp::Swap<mapsize, true>::readval(pword)); name_offset += strlen(pnames + name_offset) + 1; ++pword; if (this->armap_[i].file_offset != last_seen_offset) @@ -394,6 +405,11 @@ Archive::interpret_header(const Archive_header* hdr, off_t off, if (!pname->empty()) pname->clear(); } + else if (memcmp(hdr->ar_name, sym64name, sizeof sym64name) == 0) + { + // This is the symbol table, 64-bit version. + pname->assign(sym64name, sizeof sym64name); + } else if (hdr->ar_name[1] == '/') { // This is the extended name table. @@ -544,7 +560,9 @@ Archive::const_iterator::read_next_header() this->header_.off = this->off_; // Skip special members. - if (!this->header_.name.empty() && this->header_.name != "/") + if (!this->header_.name.empty() + && this->header_.name != "/" + && this->header_.name != "/SYM64/") return; this->off_ += sizeof(Archive_header) + this->header_.size; diff --git a/gold/archive.h b/gold/archive.h index 18cd899..66e4b2c 100644 --- a/gold/archive.h +++ b/gold/archive.h @@ -175,6 +175,9 @@ class Archive : public Library_base // The string expected at the end of an archive member header. static const char arfmag[2]; + // Name of 64-bit symbol table member. + static const char sym64name[7]; + // The name of the object. This is the name used on the command // line; e.g., if "-lgcc" is on the command line, this will be // "gcc". @@ -290,6 +293,7 @@ class Archive : public Library_base { return this->input_file_->file().get_view(0, start, size, aligned, cache); } // Read the archive symbol map. + template<int mapsize> void read_armap(off_t start, section_size_type size); |