blob: 8525c5f8652304f5f548a2fded5278d34cb8bc29 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/sys/fuzzing/framework/target/module.h"
#include <lib/syslog/cpp/macros.h>
#include "src/sys/fuzzing/common/module.h"
namespace fuzzing {
namespace {
constexpr uint64_t kFnv64Prime = 1099511628211ULL;
constexpr uint64_t kFnv64OffsetBasis = 14695981039346656037ULL;
} // namespace
Identifier Module::Identify(const uintptr_t* pcs, size_t num_pcs) {
// Make a position independent table from the PCs.
auto pc_table = std::make_unique<ModulePC[]>(num_pcs);
for (size_t i = 0; i < num_pcs; ++i) {
pc_table[i].pc = pcs[i * 2] - pcs[0];
pc_table[i].flags = pcs[i * 2 + 1];
}
// Double hash using both FNV1 and FNV1a to reduce the likelihood of collisions. We could use a
// cryptographic hash here, but that introduces unwanted dependencies, and this is good enough.
// The algorithms are taken from http://www.isthe.com/chongo/tech/comp/fnv/index.html
Identifier id = {kFnv64OffsetBasis, kFnv64OffsetBasis};
auto* u8 = reinterpret_cast<uint8_t*>(pc_table.get());
size_t size = num_pcs * sizeof(ModulePC);
while (size-- > 0) {
// FNV1
id[0] *= kFnv64Prime;
id[0] ^= *u8;
// FNV1a
id[1] ^= *u8++;
id[1] *= kFnv64Prime;
}
return id;
}
Module::Module(uint8_t* counters, const uintptr_t* pcs, size_t num_pcs) {
FX_CHECK(counters && pcs && num_pcs);
counters_.Mirror(counters, num_pcs);
id_ = Module::Identify(pcs, num_pcs);
}
Module& Module::operator=(Module&& other) noexcept {
id_ = other.id_;
counters_ = std::move(other.counters_);
return *this;
}
} // namespace fuzzing