+// This routine is for DWARF version 5.
+
+template<int size, bool big_endian>
+const unsigned char*
+Sized_dwarf_line_info<size, big_endian>::read_header_tables_v5(
+ const unsigned char* lineptr)
+{
+ size_t len;
+
+ ++this->current_header_index_;
+
+ gold_assert(static_cast<int>(this->directories_.size())
+ == this->current_header_index_);
+ gold_assert(static_cast<int>(this->files_.size())
+ == this->current_header_index_);
+
+ // Read the directory list.
+ unsigned int format_count = *lineptr;
+ lineptr += 1;
+
+ unsigned int *types = new unsigned int[format_count];
+ unsigned int *forms = new unsigned int[format_count];
+
+ for (unsigned int i = 0; i < format_count; i++)
+ {
+ types[i] = read_unsigned_LEB_128(lineptr, &len);
+ lineptr += len;
+ forms[i] = read_unsigned_LEB_128(lineptr, &len);
+ lineptr += len;
+ }
+
+ uint64_t entry_count = read_unsigned_LEB_128(lineptr, &len);
+ lineptr += len;
+ this->directories_.push_back(std::vector<std::string>(0));
+ std::vector<std::string>& dir_list = this->directories_.back();
+
+ for (unsigned int j = 0; j < entry_count; j++)
+ {
+ std::string dirname;
+
+ for (unsigned int i = 0; i < format_count; i++)
+ {
+ if (types[i] == elfcpp::DW_LNCT_path)
+ {
+ if (forms[i] == elfcpp::DW_FORM_string)
+ {
+ dirname = reinterpret_cast<const char*>(lineptr);
+ lineptr += dirname.size() + 1;
+ }
+ else if (forms[i] == elfcpp::DW_FORM_line_strp)
+ {
+ uint64_t offset;
+ if (this->header_.offset_size == 4)
+ offset =
+ elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
+ else
+ offset =
+ elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
+ typename Reloc_map::const_iterator it
+ = this->reloc_map_.find(lineptr - this->buffer_);
+ if (it != reloc_map_.end())
+ {
+ if (this->track_relocs_type_ == elfcpp::SHT_RELA)
+ offset = 0;
+ offset += it->second.second;
+ }
+ lineptr += this->header_.offset_size;
+ dirname = reinterpret_cast<const char*>(this->str_buffer_
+ + offset);
+ }
+ else
+ return lineptr;
+ }
+ else
+ return lineptr;
+ }
+ dir_list.push_back(dirname);
+ }
+
+ delete[] types;
+ delete[] forms;
+
+ // Read the filenames list.
+ format_count = *lineptr;
+ lineptr += 1;
+
+ types = new unsigned int[format_count];
+ forms = new unsigned int[format_count];
+
+ for (unsigned int i = 0; i < format_count; i++)
+ {
+ types[i] = read_unsigned_LEB_128(lineptr, &len);
+ lineptr += len;
+ forms[i] = read_unsigned_LEB_128(lineptr, &len);
+ lineptr += len;
+ }
+
+ entry_count = read_unsigned_LEB_128(lineptr, &len);
+ lineptr += len;
+ this->files_.push_back(
+ std::vector<std::pair<int, std::string> >(0));
+ std::vector<std::pair<int, std::string> >& file_list = this->files_.back();
+
+ for (unsigned int j = 0; j < entry_count; j++)
+ {
+ const char* path = NULL;
+ int dirindex = 0;
+
+ for (unsigned int i = 0; i < format_count; i++)
+ {
+ if (types[i] == elfcpp::DW_LNCT_path)
+ {
+ if (forms[i] == elfcpp::DW_FORM_string)
+ {
+ path = reinterpret_cast<const char*>(lineptr);
+ lineptr += strlen(path) + 1;
+ }
+ else if (forms[i] == elfcpp::DW_FORM_line_strp)
+ {
+ uint64_t offset;
+ if (this->header_.offset_size == 4)
+ offset = elfcpp::Swap_unaligned<32, big_endian>::readval(lineptr);
+ else
+ offset = elfcpp::Swap_unaligned<64, big_endian>::readval(lineptr);
+ typename Reloc_map::const_iterator it
+ = this->reloc_map_.find(lineptr - this->buffer_);
+ if (it != reloc_map_.end())
+ {
+ if (this->track_relocs_type_ == elfcpp::SHT_RELA)
+ offset = 0;
+ offset += it->second.second;
+ }
+ lineptr += this->header_.offset_size;
+ path = reinterpret_cast<const char*>(this->str_buffer_
+ + offset);
+ }
+ else
+ return lineptr;
+ }
+ else if (types[i] == elfcpp::DW_LNCT_directory_index)
+ {
+ if (forms[i] == elfcpp::DW_FORM_udata)
+ {
+ dirindex = read_unsigned_LEB_128(lineptr, &len);
+ lineptr += len;
+ }
+ else
+ return lineptr;
+ }
+ else
+ return lineptr;
+ }
+ gold_debug(DEBUG_LOCATION, "File %3d: %s",
+ static_cast<int>(file_list.size()), path);
+ file_list.push_back(std::make_pair(dirindex, path));
+ }
+
+ delete[] types;
+ delete[] forms;
+
+ return lineptr;
+}
+