| // Copyright 2013 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. |
| // |
| // Declares the data structure that will be used by various pieces of the |
| // instrumentation and trace agent's to collect data at runtime. |
| |
| #ifndef SYZYGY_COMMON_INDEXED_FREQUENCY_DATA_H_ |
| #define SYZYGY_COMMON_INDEXED_FREQUENCY_DATA_H_ |
| |
| #include <windows.h> |
| |
| #include "base/strings/string_piece.h" |
| #include "syzygy/common/assertions.h" |
| |
| namespace common { |
| |
| #pragma pack(push, 1) |
| |
| // This data structure is injected into an instrumented image in a read-write |
| // section of its own. It will be initialized by the runtime client library |
| // and is referred to by all of the instrumentation code. |
| struct IndexedFrequencyData { |
| |
| // Describe the kind of data contained in frequency_data; |
| // IndexedFrequencyDataTypeName must be maintained if this is changed. |
| enum DataType { |
| INVALID_DATA_TYPE = 0, |
| BASIC_BLOCK_ENTRY = 1, |
| BRANCH = 2, |
| COVERAGE = 3, |
| JUMP_TABLE = 4, |
| MAX_DATA_TYPE = 5, |
| }; |
| |
| // An identifier denoting the agent with which this frequency data |
| // instrumentation is intended to work. |
| uint32_t agent_id; |
| |
| // The version of the data structure and agent of the toolchain that |
| // instrumented the binary. If this doesn't match the running client |
| // library then the whole process should be aborted. This just a simple |
| // counter which should be updated whenever a non-backwards compatible |
| // change is made to the data structure or its usage. |
| uint32_t version; |
| |
| // This points to an array of length 'num_entries' counter elements. At |
| // link time it is initialized to point to statically allocated array that is |
| // in the .data section of the image (this is done so that if capture is not |
| // enabled the binary can still run without crashing). If a single process- |
| // wide frequency table is needed, the agent may allocate a call-trace buffer |
| // and redirect this pointer to point into it. Alternatively, it may allocate |
| // any thread-specific context it requires and refer to this pointer as a |
| // fall-back measure if tracing is disabled. |
| // |
| // The total size (in bytes) of the buffer pointed to is |
| // num_entries * num_columns * frequency_size. |
| void* frequency_data; |
| |
| // The number of entries in the frequency table. This is required by the |
| // runtime client library so it knows how big an array to allocate. |
| uint32_t num_entries; |
| |
| // The number of columns for each entry. |
| uint32_t num_columns; |
| |
| // The number of bytes used for each element of frequency_data: 1, 4, or 8. |
| uint8_t frequency_size; |
| |
| // Each module only needs to be registered once with the call-trace service. |
| // Our hooks grab various entry points (e.g. TLS initializers and the image |
| // entry points), so the initialization routine may be called repeatedly. We |
| // use this to determine whether or not we should try initializing things. |
| // Upon first entry this is protected by the loader lock and afterwards it |
| // is only read, so synchronization is not an issue. |
| uint8_t initialization_attempted; |
| |
| // The type of data associated with this module. |
| uint8_t data_type; |
| }; |
| COMPILE_ASSERT_IS_POD(IndexedFrequencyData); |
| |
| // Indexed frequency data that is managed as a thread local. Used by the basic |
| // block entry instrumentation and agent, and variants. |
| struct ThreadLocalIndexedFrequencyData { |
| // The indexed frequency data information common for all agents. |
| ::common::IndexedFrequencyData module_data; |
| |
| // The TLS slot associated with this module (if any). This allows for the |
| // frequency trace data to be managed on a per-thread basis, if desired by the |
| // agent. The TLS index is initialized to TLS_OUT_OF_INDEXES by the |
| // instrumenter. |
| DWORD tls_index; |
| |
| // The FS slot associated with this module (if any). This allows for the |
| // frequency trace data to be managed on a per-thread basis, if desired by the |
| // agent. An unused slot is initialized to zero by the instrumenter, otherwise |
| // it is initialized to a slot index between 1 and 4. |
| DWORD fs_slot; |
| }; |
| |
| #pragma pack(pop) |
| |
| // The basic-block coverage agent ID. |
| extern const uint32_t kBasicBlockCoverageAgentId; |
| |
| // The basic-block entry counting agent ID. |
| extern const uint32_t kBasicBlockEntryAgentId; |
| |
| // The jump table counting agent ID. |
| extern const uint32_t kJumpTableCountAgentId; |
| |
| // The basic-block trace agent version. |
| extern const uint32_t kBasicBlockFrequencyDataVersion; |
| |
| // The branch trace agent version. |
| extern const uint32_t kBranchFrequencyDataVersion; |
| |
| // The jump table trace agent version. |
| extern const uint32_t kJumpTableFrequencyDataVersion; |
| |
| // The name of the basic-block ranges stream added to the PDB by |
| // any instrumentation employing basic-block trace data. |
| extern const char kBasicBlockRangesStreamName[]; |
| |
| // A string table mapping from DataType to text representation. |
| // This array must be maintained if enum DataType is changed. |
| extern const char* IndexedFrequencyDataTypeName[]; |
| |
| // Produce a human readable name for the IndexedFrequencyData::DataType. |
| // @param type type to convert in string. |
| // @param result on success, receives the textual representation of @p type. |
| bool IndexedFrequencyDataTypeToString(IndexedFrequencyData::DataType type, |
| std::string* result); |
| |
| // Parse a string to get the IndexedFrequencyData::DataType. |
| // @param str the string to convert. |
| // @param result on success, receives the DataType value of @p str. |
| bool ParseFrequencyDataType(const base::StringPiece& str, |
| IndexedFrequencyData::DataType* type); |
| |
| } // namespace common |
| |
| #endif // SYZYGY_COMMON_INDEXED_FREQUENCY_DATA_H_ |