- gold_assert(this->lock_count_ > 0);
- File_read::View* pv = this->find_or_make_view(start, size, NULL);
- pv->lock();
- return new File_view(*this, pv, pv->data() + (start - pv->start()));
+ unsigned char discard[File_read::page_size];
+ iovec iov[File_read::max_readv_entries * 2];
+ size_t iov_index = 0;
+
+ off_t first_offset = rm[start].file_offset;
+ off_t last_offset = first_offset;
+ ssize_t want = 0;
+ for (size_t i = 0; i < count; ++i)
+ {
+ const Read_multiple_entry& i_entry(rm[start + i]);
+
+ if (i_entry.file_offset > last_offset)
+ {
+ size_t skip = i_entry.file_offset - last_offset;
+ gold_assert(skip <= sizeof discard);
+
+ iov[iov_index].iov_base = discard;
+ iov[iov_index].iov_len = skip;
+ ++iov_index;
+
+ want += skip;
+ }
+
+ iov[iov_index].iov_base = i_entry.buffer;
+ iov[iov_index].iov_len = i_entry.size;
+ ++iov_index;
+
+ want += i_entry.size;
+
+ last_offset = i_entry.file_offset + i_entry.size;
+ }
+
+ this->reopen_descriptor();
+
+ gold_assert(iov_index < sizeof iov / sizeof iov[0]);
+
+ if (::lseek(this->descriptor_, base + first_offset, SEEK_SET) < 0)
+ gold_fatal(_("%s: lseek failed: %s"),
+ this->filename().c_str(), strerror(errno));
+
+ ssize_t got = ::readv(this->descriptor_, iov, iov_index);
+
+ if (got < 0)
+ gold_fatal(_("%s: readv failed: %s"),
+ this->filename().c_str(), strerror(errno));
+ if (got != want)
+ gold_fatal(_("%s: file too short: read only %zd of %zd bytes at %lld"),
+ this->filename().c_str(),
+ got, want, static_cast<long long>(base + first_offset));