blob: 0831378d9b6d9cd4397f0d7a70ce673e433ff904 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "syzygy/pdb/omap.h"
#include <algorithm>
#include "syzygy/pdb/pdb_util.h"
namespace pdb {
OMAP CreateOmap(ULONG rva, ULONG rvaTo) {
OMAP omap = { rva, rvaTo };
return omap;
}
bool OmapLess(const OMAP& omap1, const OMAP& omap2) {
return omap1.rva < omap2.rva;
}
bool OmapVectorIsValid(const std::vector<OMAP>& omaps) {
for (size_t i = 1; i < omaps.size(); ++i) {
if (!OmapLess(omaps[i - 1], omaps[i]))
return false;
}
return true;
}
core::RelativeAddress TranslateAddressViaOmap(const std::vector<OMAP>& omaps,
core::RelativeAddress address) {
OMAP omap_address = CreateOmap(address.value(), 0);
// Find the first element that is > than omap_address.
std::vector<OMAP>::const_iterator it =
std::upper_bound(omaps.begin(), omaps.end(), omap_address,
OmapLess);
// If we are at the first OMAP entry, the address is before any addresses
// that are OMAPped. Thus, we return the same address.
if (it == omaps.begin())
return address;
// Otherwise, the previous OMAP entry tells us where we lie.
--it;
return core::RelativeAddress(it->rvaTo) +
(address - core::RelativeAddress(it->rva));
}
bool ReadOmapsFromPdbFile(const PdbFile& pdb_file,
std::vector<OMAP>* omap_to,
std::vector<OMAP>* omap_from) {
PdbStream* dbi_stream = pdb_file.GetStream(kDbiStream);
if (dbi_stream == NULL)
return false;
DbiHeader dbi_header = {};
if (!dbi_stream->Read(&dbi_header, 1))
return false;
DbiDbgHeader dbg_header = {};
if (!dbi_stream->Seek(GetDbiDbgHeaderOffset(dbi_header)))
return false;
if (!dbi_stream->Read(&dbg_header, 1))
return false;
// We expect both the OMAP stream IDs to exist.
if (dbg_header.omap_to_src < 0 || dbg_header.omap_from_src < 0)
return false;
// We expect both streams to exist.
PdbStream* omap_to_stream = pdb_file.GetStream(dbg_header.omap_to_src);
PdbStream* omap_from_stream = pdb_file.GetStream(dbg_header.omap_from_src);
if (omap_to_stream == NULL || omap_from_stream == NULL)
return false;
// Read the streams if need be.
if (omap_to != NULL && !omap_to_stream->Read(omap_to))
return false;
if (omap_from != NULL && !omap_from_stream->Read(omap_from))
return false;
return true;
}
bool ReadOmapsFromPdbFile(const base::FilePath& pdb_path,
std::vector<OMAP>* omap_to,
std::vector<OMAP>* omap_from) {
PdbReader pdb_reader;
PdbFile pdb_file;
if (!pdb_reader.Read(pdb_path, &pdb_file))
return false;
return ReadOmapsFromPdbFile(pdb_file, omap_to, omap_from);
}
} // namespace pdb