// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_ZUCCHINI_ADDRESS_TRANSLATOR_H_ #define COMPONENTS_ZUCCHINI_ADDRESS_TRANSLATOR_H_ #include <stdint.h> #include <tuple> #include <vector> #include "base/memory/raw_ptr.h" #include "base/memory/raw_ref.h" #include "components/zucchini/algorithm.h" #include "components/zucchini/image_utils.h" namespace zucchini { // There are several ways to reason about addresses in an image: // - Offset: Position relative to start of image. // - VA (Virtual Address): Virtual memory address of a loaded image. This is // subject to relocation by the OS. // - RVA (Relative Virtual Address): VA relative to some base address. This is // the preferred way to specify pointers in an image. // // Zucchini is primarily concerned with offsets and RVAs. Executable images like // PE and ELF are organized into sections. Each section specifies offset and RVA // ranges as: // {Offset start, offset size, RVA start, RVA size}. // This constitutes a basic unit to translate between offsets and RVAs. Note: // |offset size| < |RVA size| is possible. For example, the .bss section can can // have zero-filled statically-allocated data that have no corresponding bytes // on image (to save space). This poses a problem for Zucchini, which stores // addresses as offsets: now we'd have "dangling RVAs" that don't map to // offsets! Some ways to handling this are: // 1. Ignore all dangling RVAs. This simplifies the algorithm, but also means // some reference targets would escape detection and processing. // 2. Create distinct "fake offsets" to accommodate dangling RVAs. Image data // must not be read on these fake offsets, which are only valid as target // addresses for reference matching. // As for |RVA size| < |offset size|, the extra portion just gets ignored. // // Status: Zucchini implements (2) in a simple way: dangling RVAs are mapped to // fake offsets by adding a large value. This value can be chosen as an // exclusive upper bound of all offsets (i.e., image size). This allows them to // be easily detected and processed as a special-case. // TODO(huangs): Investigate option (1), now that the refactored code makes // experimentation easier. // TODO(huangs): Make AddressTranslator smarter: Allocate unused |offset_t| // ranges and create "fake" units to accommodate dangling RVAs. Then // AddressTranslator can be simplified. // Virtual Address relative to some base address (RVA). There's distinction // between "valid RVA" and "existent RVA": // - Valid RVA: An RVA that's reasonably small, i.e., below |kRvaBound|. // - Existent RVA: An RVA that has semantic meaning in an image, and may // translate to an offset in an image or (if a dangling RVA) a fake offset. // All existent RVAs are valid RVAs. rva_t; // Divide by 2 to match |kOffsetBound|. constexpr rva_t kRvaBound = …; constexpr rva_t kInvalidRva = …; // A utility to translate between offsets and RVAs in an image. class AddressTranslator { … }; } // namespace zucchini #endif // COMPONENTS_ZUCCHINI_ADDRESS_TRANSLATOR_H_