Coverage for /Syzygy/block_graph/block_graph.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
95.7%1341400.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // A block graph is an abstract graph of blocks, each of which has an ID, a
  16    :  // type, a size and a few other properties. Each block represents either code or
  17    :  // data, and blocks can reference one another through references of various
  18    :  // types.
  19    :  //
  20    :  // The BlockGraph also stores minimum knowledge of sections (names and
  21    :  // characteristics), and each block belongs to at most one section. In this
  22    :  // sense, a BlockGraph acts as top-level division of blocks.
  23    :  
  24    :  #ifndef SYZYGY_BLOCK_GRAPH_BLOCK_GRAPH_H_
  25    :  #define SYZYGY_BLOCK_GRAPH_BLOCK_GRAPH_H_
  26    :  
  27    :  #include <hash_map>
  28    :  #include <map>
  29    :  #include <set>
  30    :  #include <string>
  31    :  #include <vector>
  32    :  
  33    :  #include "base/basictypes.h"
  34    :  #include "base/file_util.h"
  35    :  #include "base/strings/string_piece.h"
  36    :  #include "syzygy/common/align.h"
  37    :  #include "syzygy/core/address.h"
  38    :  #include "syzygy/core/address_space.h"
  39    :  #include "syzygy/core/string_table.h"
  40    :  
  41    :  namespace block_graph {
  42    :  
  43    :  // Forward declaration.
  44    :  class BlockGraphSerializer;
  45    :  
  46    :  // NOTE: When adding attributes be sure to update any uses of them in
  47    :  //       block_graph.cc, for example in MergeIntersectingBlocks.
  48    :  #define BLOCK_ATTRIBUTE_ENUM(F) \
  49    :      /* Set for functions declared non-returning. */ \
  50    :      F(NON_RETURN_FUNCTION) \
  51    :      /* Set for blocks that are inferred by the decomposer. */ \
  52    :      F(GAP_BLOCK) \
  53    :      /* Set for blocks that are parsed by the PEFileParser. These */ \
  54    :      /* blocks are unmovable, indivisible, etc, and have to be treated */ \
  55    :      /* specially. */ \
  56    :      F(PE_PARSED) \
  57    :      /* Set for blocks that are created from section contribution */ \
  58    :      /* information or directly from COFF sections. */ \
  59    :      F(SECTION_CONTRIB) \
  60    :      /* This is used to indicate that a block consists purely of padding */ \
  61    :      /* data. */ \
  62    :      F(PADDING_BLOCK) \
  63    :      /* Indicates blocks that contain inline assembly. */ \
  64    :      F(HAS_INLINE_ASSEMBLY) \
  65    :      /* Indicates that the block was built by a compiler whose precise */ \
  66    :      /* behaviour and semantics we are unfamiliar with. */ \
  67    :      F(BUILT_BY_UNSUPPORTED_COMPILER) \
  68    :      /* Indicates that the block has been built by the Syzygy toolchain, and */ \
  69    :      /* thus is inherently safe for basic-block decomposition without having */ \
  70    :      /* to perform the myriad of safety checks we do otherwise. */ \
  71    :      F(BUILT_BY_SYZYGY) \
  72    :      /* Deprecated: used by old decomposer. */ \
  73    :      F(RESERVED_ATTRIBUTE1) \
  74    :      /* Deprecated: used by old decomposer. */ \
  75    :      F(RESERVED_ATTRIBUTE2) \
  76    :      /* This is set for functions that have exception handling enabled. */ \
  77    :      /* Without delving far deeper into the specifics, it is unsafe to basic */ \
  78    :      /* block decompose these blocks. */ \
  79    :      F(HAS_EXCEPTION_HANDLING) \
  80    :      /* Deprecated: used by old decomposer. */ \
  81    :      F(RESERVED_ATTRIBUTE3) \
  82    :      /* This is set for blocks that have a thunk symbol pointing to them. */ \
  83    :      /* Typically thunk blocks are compiler or linker-generated, such as */ \
  84    :      /* e.g. import thunks, delay load import thunks, etc. */ \
  85    :      F(THUNK) \
  86    :      /* This is set for blocks that have been parsed as COFF groups. The */ \
  87    :      /* contents of these blocks are semantically indivisible. */ \
  88    :      F(COFF_GROUP) \
  89    :      /* COFF headers block; not set for PE. */ \
  90    :      F(COFF_HEADERS) \
  91    :      /* COFF symbol table. */ \
  92    :      F(COFF_SYMBOL_TABLE) \
  93    :      /* COFF string table. */ \
  94    :      F(COFF_STRING_TABLE) \
  95    :      /* COFF relocation table; these should be ignored when dealing with */ \
  96    :      /* block graphs, as all the information is represented as references. */ \
  97    :      F(COFF_RELOC_DATA) \
  98    :      /* COFF BSS (unmapped) block; has size but no data. */ \
  99    :      F(COFF_BSS) \
 100    :      /* Contains unsupported instructions. */ \
 101    :      F(UNSUPPORTED_INSTRUCTIONS) \
 102    :      /* This always needs to be set to the next available attribute bit. */ \
 103    :      F(BLOCK_ATTRIBUTES_MAX)
 104    :  
 105    :  // The BlockGraph is a top-level container for Blocks.
 106    :  class BlockGraph {
 107    :   public:
 108    :    typedef core::RelativeAddress RelativeAddress;
 109    :  
 110    :    typedef size_t SectionId;
 111    :    typedef size_t BlockId;
 112    :    typedef size_t Size;
 113    :    typedef ptrdiff_t Offset;
 114    :    typedef uint32 BlockAttributes;
 115    :    typedef uint32 LabelAttributes;
 116    :  
 117    :    // The BlockGraph maintains a list of sections, and each block belongs
 118    :    // to one of them. This is the set of information we keep regarding them.
 119    :    struct Section;
 120    :    // The section map contains all sections, indexed by id.
 121    :    typedef std::map<SectionId, Section> SectionMap;
 122    :  
 123    :    static const SectionId kInvalidSectionId;
 124    :  
 125    :    // The types of image formats that we can currently represent in a
 126    :    // BlockGraph.
 127    :    enum ImageFormat {
 128    :      UNKNOWN_IMAGE_FORMAT,
 129    :      PE_IMAGE,
 130    :      COFF_IMAGE,
 131    :  
 132    :      // This must always be the last entry, and kImageFormat must be kept in
 133    :      // sync with this enum.
 134    :      IMAGE_FORMAT_MAX
 135    :    };
 136    :  
 137    :    static const char* ImageFormatToString(ImageFormat format);
 138    :  
 139    :    // Assign distinct bit IDs to each attribute constant.
 140    :    enum BlockAttributeIdEnum {
 141    :  #define DECLARE_ENUM_BIT(name) name##_BIT,
 142    :      BLOCK_ATTRIBUTE_ENUM(DECLARE_ENUM_BIT)
 143    :  #undef DECLARE_ENUM_BIT
 144    :    };
 145    :  
 146    :    enum BlockAttributeEnum {
 147    :  #define DECLARE_ENUM(name) name = (1 << name##_BIT),
 148    :      BLOCK_ATTRIBUTE_ENUM(DECLARE_ENUM)
 149    :  #undef DECLARE_ENUM
 150    :    };
 151    :  
 152    :    // Returns a string containing the names of the supplied attributes.
 153    :    static std::string BlockAttributesToString(BlockAttributes attrs);
 154    :  
 155    :    enum BlockType {
 156    :      CODE_BLOCK,
 157    :      DATA_BLOCK,
 158    :  
 159    :      // NOTE: This must always be last, and kBlockType must be kept in sync
 160    :      // with this enum.
 161    :      BLOCK_TYPE_MAX
 162    :    };
 163    :  
 164    :    static const char* BlockTypeToString(BlockType type);
 165    :  
 166    :    // Label attributes. Attributes of the form _END_LABEL type actually
 167    :    // point to the first byte past the range they delineate. To make the
 168    :    // semantics of moving labels easier, we shift these labels left by one and
 169    :    // make them follow the last byte of the delineated range.
 170    :    enum LabelAttributesEnum {
 171    :      // The label points to an entry-point in a code block.
 172    :      CODE_LABEL = (1 << 0),
 173    :  
 174    :      // Mark the start and end of the debuggable portion of a code block.
 175    :      DEBUG_START_LABEL = (1 << 1),
 176    :      DEBUG_END_LABEL = (1 << 2),
 177    :  
 178    :      // Mark the start and end of an embedded scope in a code block.
 179    :      SCOPE_START_LABEL = (1 << 3),
 180    :      SCOPE_END_LABEL = (1 << 4),
 181    :  
 182    :      // Marks the location of a (virtual table?) call.
 183    :      CALL_SITE_LABEL = (1 << 5),
 184    :  
 185    :      // The label points to the start of a jump table. The length is inferred
 186    :      // by the location of the next label, or the end of the block. This will
 187    :      // also have DATA_LABEL set.
 188    :      JUMP_TABLE_LABEL = (1 << 6),
 189    :      // The label points to the start of a case table. The length is inferred
 190    :      // by the location of the next label, or the end of the block. This will
 191    :      // also have DATA_LABEL set.
 192    :      CASE_TABLE_LABEL = (1 << 7),
 193    :      // The label originated from a data symbol. The length is inferred by the
 194    :      // location of the next label, or the end of the block. The type of data
 195    :      // is unknown.
 196    :      DATA_LABEL = (1 << 8),
 197    :  
 198    :      // Used to mark a label that was derived from a public symbol. These are
 199    :      // usually actually pointing to code and global data symbols, but we can't
 200    :      // always tell (there may be public symbols pointing to data in a code
 201    :      // block).
 202    :      PUBLIC_SYMBOL_LABEL = (1 << 9),
 203    :  
 204    :      // This always needs to be the most significant bit.
 205    :      LABEL_ATTRIBUTES_MAX = (1 << 10),
 206    :    };
 207    :  
 208    :    static std::string LabelAttributesToString(LabelAttributes label_attributes);
 209    :  
 210    :    enum ReferenceType {
 211    :      // Common reference types.
 212    :      PC_RELATIVE_REF,
 213    :      ABSOLUTE_REF,
 214    :      RELATIVE_REF,
 215    :      FILE_OFFSET_REF,
 216    :  
 217    :      // Object-file reference types.
 218    :      SECTION_REF,
 219    :      SECTION_OFFSET_REF,
 220    :  
 221    :      // Relocation reference types.
 222    :      // TODO(chrisha): Do we need a separate bit, and different ABS and REL
 223    :      //     reference types for COFF files?
 224    :      RELOC_REF_BIT = 1u << 3,
 225    :      RELOC_PC_RELATIVE_REF = PC_RELATIVE_REF | RELOC_REF_BIT,
 226    :      RELOC_ABSOLUTE_REF = ABSOLUTE_REF | RELOC_REF_BIT,
 227    :      RELOC_RELATIVE_REF = RELATIVE_REF | RELOC_REF_BIT,
 228    :      RELOC_SECTION_REF = SECTION_REF | RELOC_REF_BIT,
 229    :      RELOC_SECTION_OFFSET_REF = SECTION_OFFSET_REF | RELOC_REF_BIT,
 230    :  
 231    :      // Must be last!
 232    :      REFERENCE_TYPE_MAX,
 233    :    };
 234    :  
 235    :    // Forward declarations.
 236    :    class AddressSpace;
 237    :    class Block;
 238    :    class Label;
 239    :    class Reference;
 240    :  
 241    :    // The block map contains all blocks, indexed by id.
 242    :    typedef std::map<BlockId, Block> BlockMap;
 243    :  
 244    :    BlockGraph();
 245    :    ~BlockGraph();
 246    :  
 247    :    // Adds a section with the given name.
 248    :    //
 249    :    // @param name The section name.
 250    :    // @param characteristics The section characteristics.
 251    :    // @returns the newly created section.
 252    :    Section* AddSection(const base::StringPiece& name, uint32 characteristics);
 253    :  
 254    :    // Finds a section with the given name, returning NULL if no such section
 255    :    // exists.
 256    :    //
 257    :    // @param name The section name.
 258    :    // @returns the section if one is found, NULL otherwise.
 259    :    Section* FindSection(const base::StringPiece& name);
 260    :    const Section* FindSection(const base::StringPiece& name) const;
 261    :  
 262    :    // Find or adds section with the given name.
 263    :    //
 264    :    // If a section with the given name already exists, updates its
 265    :    // characteristics and returns it. Otherwise, creates a new section and
 266    :    // returns it. If multiple sections exist with the given name, the first
 267    :    // one encountered is returned.
 268    :    //
 269    :    // TODO(chrisha): The semantics of this function are a little odd. It would
 270    :    //     make more sense for it to return only if a section with matching name
 271    :    //     AND characteristics is found, otherwise to create a new one.
 272    :    //
 273    :    // @param name The section name.
 274    :    // @param characteristics The section characteristics.
 275    :    // @returns the new or found section.
 276    :    Section* FindOrAddSection(const base::StringPiece& name,
 277    :                              uint32 characteristics);
 278    :  
 279    :    // Removes the given section from the BlockGraph.
 280    :    //
 281    :    // The section must belong to this block graph. Be aware that this can leave
 282    :    // Blocks with dangling section_ids.
 283    :    //
 284    :    // @param section The section to remove.
 285    :    // @returns true on success, false otherwise.
 286    :    bool RemoveSection(Section* section);
 287    :  
 288    :    // Removes the section with the given id from the BlockGraph.
 289    :    //
 290    :    // @param id The id of the section to remove.
 291    :    // @returns true on success, false otherwise.
 292    :    bool RemoveSectionById(SectionId id);
 293    :  
 294    :    // Add @p block of type @p type and @p size and
 295    :    // return the new block.
 296    :    // @returns the new block.
 297    :    Block* AddBlock(BlockType type, Size size, const base::StringPiece& name);
 298    :  
 299    :    // Deletes the given block from the BlockGraph. The block must belong to this
 300    :    // block graph, and have no references or referrers. Returns true on success,
 301    :    // false otherwise. On failure, the BlockGraph has not been changed.
 302    :    bool RemoveBlock(Block* block);
 303    :  
 304    :    // Deletes the block with the given @p id from the block graph. The block id
 305    :    // must be valid, and the block must have no references or referrers. Returns
 306    :    // true on success, false otherwise. On failure, the BlockGraph has not been
 307    :    // changed.
 308    :    bool RemoveBlockById(BlockId id);
 309    :  
 310    :    // Accessors.
 311  E :    const SectionMap& sections() const { return sections_; }
 312  E :    SectionMap& sections_mutable() { return sections_; }
 313  E :    const BlockMap& blocks() const { return blocks_; }
 314  E :    BlockMap& blocks_mutable() { return blocks_; }
 315    :  
 316    :    // @{
 317    :    // Retrieve the section with the given id.
 318    :    //
 319    :    // @param id The id of the section to retrieve.
 320    :    // @returns the section in question or NULL if no such section.
 321    :    Section* GetSectionById(SectionId id);
 322    :    const Section* GetSectionById(SectionId id) const;
 323    :    // @}
 324    :  
 325    :    // @{
 326    :    // Retrieve the block with id.
 327    :    // @returns the block in question or NULL if no such block.
 328    :    Block* GetBlockById(BlockId id);
 329    :    const Block* GetBlockById(BlockId id) const;
 330    :    // @}
 331    :  
 332    :    // Get the string table.
 333    :    // @returns the string table of this BlockGraph.
 334  E :    core::StringTable& string_table() { return string_table_; }
 335    :  
 336    :    // Sets the image format.
 337    :    // @param image_format The format of the image.
 338  E :    void set_image_format(ImageFormat image_format) {
 339  E :      image_format_ = image_format;
 340  E :    }
 341    :    // @returns the image format.
 342  E :    ImageFormat image_format() const { return image_format_; }
 343    :  
 344    :   private:
 345    :    // Give BlockGraphSerializer access to our innards for serialization.
 346    :    friend BlockGraphSerializer;
 347    :  
 348    :    // Removes a block by the iterator to it. The iterator must be valid.
 349    :    bool RemoveBlockByIterator(BlockMap::iterator it);
 350    :  
 351    :    // All sections we contain.
 352    :    SectionMap sections_;
 353    :  
 354    :    // Our section ID allocator.
 355    :    SectionId next_section_id_;
 356    :  
 357    :    // All blocks we contain.
 358    :    BlockMap blocks_;
 359    :  
 360    :    // Our block ID allocator.
 361    :    BlockId next_block_id_;
 362    :  
 363    :    // A string table used to intern strings.
 364    :    core::StringTable string_table_;
 365    :  
 366    :    // The format of the image represented by this block graph. Defaults to
 367    :    // UNKNOWN_IMAGE_FORMAT. Usually initialized by the appropriate decomposer.
 368    :    ImageFormat image_format_;
 369    :  
 370    :    DISALLOW_COPY_AND_ASSIGN(BlockGraph);
 371    :  };
 372    :  
 373    :  // The BlockGraph maintains a list of sections, and each block belongs
 374    :  // to one of them. This is the set of information we keep regarding them.
 375    :  struct BlockGraph::Section {
 376    :    // Default constructor. Required for serialization.
 377  E :    Section() : id_(kInvalidSectionId), characteristics_(0) {
 378  E :    }
 379    :  
 380    :    // Full constructor.
 381    :    //
 382    :    // @param id The section id. This must not be kInvalidSectionId.
 383    :    // @param name The name of the section. Must not be empty or NULL.
 384    :    // @param characteristics The characteristics of the section.
 385  E :    Section(SectionId id, const base::StringPiece& name, uint32 characteristics)
 386    :        : id_(id), name_(), characteristics_(characteristics) {
 387  E :      DCHECK_NE(kInvalidSectionId, id);
 388  E :      DCHECK(name != NULL);
 389  E :      name.CopyToString(&name_);
 390  E :      DCHECK(!name_.empty());
 391  E :    }
 392    :  
 393    :    // Get the id of this section.
 394    :    //
 395    :    // @returns the id of the section.
 396  E :    SectionId id() const { return id_; }
 397    :  
 398    :    // Get the name of this section.
 399    :    //
 400    :    // @returns the section name.
 401  E :    const std::string& name() const { return name_; }
 402    :  
 403    :    // Sets the name for this section.
 404    :    //
 405    :    // @param name The name of the section. If NULL or empty, this will fail.
 406    :    // @returns true if the name is set, false otherwise.
 407    :    bool set_name(const base::StringPiece& name);
 408    :  
 409    :    // Get the characteristics of this section.
 410    :    //
 411    :    // @returns the section characteristics.
 412  E :    uint32 characteristics() const { return characteristics_; }
 413    :  
 414    :    // Sets the characteristics for this section.
 415    :    //
 416    :    // @param characteristics The new characteristics to set.
 417  E :    void set_characteristics(uint32 characteristics) {
 418  E :      characteristics_ = characteristics;
 419  E :    }
 420    :  
 421    :    // Sets a one or more additional characteristics for this section.
 422    :    //
 423    :    // @param characteristic The new characteristic(s) to set for this section.
 424  E :    void set_characteristic(uint32 characteristic) {
 425  E :      characteristics_ |= characteristic;
 426  E :    }
 427    :  
 428    :    // Clears one or more characteristics for this section.
 429    :    //
 430    :    // @param characteristic The characteristic(s) to clear for this section.
 431  E :    void clear_characteristic(uint32 characteristic) {
 432  E :      characteristics_ &= ~characteristic;
 433  E :    }
 434    :  
 435    :    // @name Serialization functions.
 436    :    // @{
 437    :    bool Save(core::OutArchive* out_archive) const;
 438    :    bool Load(core::InArchive* in_archive);
 439    :    // @}
 440    :  
 441    :    // A simple comparison operator for serialization tests.
 442  E :    bool operator==(const Section& other) const {
 443    :      return id_ == other.id_ && name_ == other.name_ &&
 444  E :          characteristics_ == other.characteristics_;
 445  E :    }
 446    :  
 447    :    // A not-equal comparison operator.
 448  E :    bool operator!=(const Section& other) const {
 449  E :      return !operator==(other);
 450  E :    }
 451    :  
 452    :   private:
 453    :    // The id of the section. This has no particular meaning other than as a way
 454    :    // to identify sections uniquely.
 455    :    SectionId id_;
 456    :    // The name of the section. This will be truncated to a max of 8 characters
 457    :    // on output.
 458    :    std::string name_;
 459    :    // The section characteristics, a bitmask of IMAGE_SCN_* values.
 460    :    uint32 characteristics_;
 461    :  };
 462    :  
 463    :  // A label denotes the beginning (or end) of a sub-region within a (code)
 464    :  // block. In particular, a code label represents an instruction boundary
 465    :  // at which disassembly can begin and a data label represents the beginning
 466    :  // of embedded data.
 467    :  class BlockGraph::Label {
 468    :   public:
 469    :    // Default constructor.
 470  E :    Label() : attributes_(0) {
 471  E :    }
 472    :  
 473    :    // Full constructor.
 474  E :    Label(const base::StringPiece& name, LabelAttributes attributes)
 475    :        : name_(name.begin(), name.end()), attributes_(attributes) {
 476  E :    }
 477    :  
 478    :    // Copy construction.
 479  E :    Label(const Label& other)
 480    :        : name_(other.name_), attributes_(other.attributes_) {
 481  E :    }
 482    :  
 483    :    // @name Accessors.
 484    :    // @{
 485  E :    const std::string& name() const { return name_; }
 486    :    // @}
 487    :  
 488    :    // A helper function for logging and debugging.
 489    :    std::string ToString() const;
 490    :  
 491    :    // Equality comparator for unittesting.
 492  E :    bool operator==(const Label& other) const {
 493  E :      return name_ == other.name_ && attributes_ == other.attributes_;
 494  E :    }
 495    :  
 496    :    // The label attributes are a bitmask. You can set them wholesale,
 497    :    // or set and clear them individually by bitmasking.
 498  E :    LabelAttributes attributes() const { return attributes_; }
 499  E :    void set_attributes(LabelAttributes attributes) { attributes_ = attributes; }
 500    :  
 501    :    // Set or clear one or more attributes.
 502  E :    void set_attribute(LabelAttributes attribute) { attributes_ |= attribute; }
 503  E :    void clear_attribute(LabelAttributes attribute) { attributes_ &= ~attribute; }
 504    :  
 505    :    // Determines if all or any of the given attributes are set.
 506  E :    bool has_attributes(LabelAttributes attributes) const {
 507  E :      return (attributes_ & attributes) == attributes;
 508  E :    }
 509  E :    bool has_any_attributes(LabelAttributes attributes) const {
 510  E :      return (attributes_ & attributes) != 0;
 511  E :    }
 512    :  
 513    :    // @returns true if this label is valid, false otherwise.
 514    :    bool IsValid() const;
 515    :  
 516    :    // Tests a set of label attributes for validity.
 517    :    // @param attributes the attributes to test.
 518    :    // @returns true if the provided attributes are valid, false otherwise.
 519    :    static bool AreValidAttributes(LabelAttributes attributes);
 520    :  
 521    :   private:
 522    :    // The name by which this label is known.
 523    :    std::string name_;
 524    :  
 525    :    // The disposition of the bytes found at this label.
 526    :    LabelAttributes attributes_;
 527    :  };
 528    :  
 529    :  // A block represents a block of either code or data.
 530    :  //
 531    :  // Since blocks may be split and up and glued together in arbitrary ways, each
 532    :  // block maintains an address-space over its data, associating ranges of block
 533    :  // data to ranges of bytes in the original image. This effectively encodes OMAP
 534    :  // data, allowing the PDB file to be updated.
 535    :  //
 536    :  // Each block also stores references to other blocks in the graph, their
 537    :  // relative location within the block and their type and size.
 538    :  //
 539    :  // Each block has a set of attributes, including a size, a name and a
 540    :  // "current" address. Most of those attributes are mutable, and are set in the
 541    :  // process of creating and manipulating images and graph address spaces.
 542    :  class BlockGraph::Block {
 543    :   public:
 544    :    // Set of the blocks that have a reference to this block.
 545    :    // This is keyed on block and source offset (not destination offset),
 546    :    // to allow one to easily locate and remove the backreferences on change or
 547    :    // deletion.
 548    :    typedef std::pair<Block*, Offset> Referrer;
 549    :    typedef std::set<Referrer> ReferrerSet;
 550    :  
 551    :    // Map of references that this block makes to other blocks.
 552    :    typedef std::map<Offset, Reference> ReferenceMap;
 553    :  
 554    :    // Represents a range of data in this block.
 555    :    typedef core::AddressRange<Offset, Size> DataRange;
 556    :  
 557    :    // Represents a range of data in the original image.
 558    :    typedef core::AddressRange<RelativeAddress, Size> SourceRange;
 559    :  
 560    :    // A map between bytes in this block and bytes in the original image.
 561    :    typedef core::AddressRangeMap<DataRange, SourceRange> SourceRanges;
 562    :  
 563    :    // The flags that can be passed to the TransferReferrers function.
 564    :    enum TransferReferrersFlags {
 565    :      kSkipInternalReferences = (1 << 0),
 566    :      kTransferInternalReferences = (1 << 1)
 567    :    };
 568    :  
 569    :    // Typed labels associated with various offsets in the block. Some of these
 570    :    // labels (of type CODE_LABEL) represent code start points for disassembly
 571    :    // while others (of type DATA_LABEL) represent the start of embedded data
 572    :    // within the block. Note that, while possible, it is NOT guaranteed that
 573    :    // all basic blocks are marked with a label. Basic block decomposition should
 574    :    // disassemble from the code labels to discover all basic blocks.
 575    :    typedef std::map<Offset, Label> LabelMap;
 576    :  
 577    :    ~Block();
 578    :  
 579    :    // Accessors.
 580  E :    BlockId id() const { return id_; }
 581  E :    BlockType type() const { return type_; }
 582  E :    void set_type(BlockType type) { type_ = type; }
 583    :  
 584  E :    Size size() const { return size_; }
 585    :  
 586    :    // Set the total size of the block. Note that allocated data_size_ must
 587    :    // always be less than or equal to the total size.
 588  E :    void set_size(Size size) {
 589  E :      DCHECK_LE(data_size_, size);
 590  E :      size_ = size;
 591  E :    }
 592    :  
 593  E :    const std::string& name() const {
 594  E :      DCHECK(name_ != NULL);
 595  E :      return *name_;
 596  E :    }
 597    :    void set_name(const base::StringPiece& name);
 598    :  
 599    :    const std::string& compiland_name() const;
 600    :    void set_compiland_name(const base::StringPiece& name);
 601    :  
 602    :    // Gets the alignment of the block. Note that the alignment is applied to
 603    :    // the byte at the alignment offset.
 604    :    // @returns The current alignment of the block.
 605  E :    Size alignment() const { return alignment_; }
 606    :    // Sets the alignment that applies to the block when building the layout.
 607    :    // By default, the first byte of the block will be aligned, but that can
 608    :    // be overridden by setting the alignment offset.
 609    :    // @param alignment The new alignment. The alignment should be a power of two.
 610    :    // The value of zero is invalid, use 1 to signal no alignment requirements.
 611  E :    void set_alignment(Size alignment) {
 612    :      // Ensure that alignment is a non-zero power of two.
 613  E :      DCHECK(common::IsPowerOfTwo(alignment));
 614  E :      alignment_ = alignment;
 615  E :    }
 616    :  
 617    :    // Gets the offset the alignment is applied to.
 618    :    // @returns The offset that will be aligned.
 619  E :    Offset alignment_offset() const { return alignment_offset_; }
 620    :    // Sets the offset the alignment refers to. The layout builder makes sure the
 621    :    // byte at this position is aligned. By default this value is zero which
 622    :    // means that the first byte of the block should be aligned.
 623    :    // @param alignment_offset The new offset of the alignment.
 624  E :    void set_alignment_offset(Offset alignment_offset) {
 625  E :      alignment_offset_ = alignment_offset;
 626  E :    }
 627    :  
 628    :    // Returns the minimum amount of padding bytes that are inserted before the
 629    :    // block when building the layout.
 630    :    // @returns The minimum amount of padding.
 631  E :    Size padding_before() const { return padding_before_; }
 632    :    // Sets the minium amount of padding bytes before the block when building the
 633    :    // layout.
 634    :    // @param padding_before At least this amount of bytes are inserted before
 635    :    //     the block when building the layout.
 636  E :    void set_padding_before(Size padding_before) {
 637  E :      padding_before_ = padding_before;
 638  E :    }
 639    :  
 640    :    // The address of the block is set any time the block is assigned
 641    :    // an address in an address space.
 642  E :    RelativeAddress addr() const { return addr_; }
 643  E :    void set_addr(RelativeAddress addr) { addr_ = addr; }
 644    :  
 645    :    // The section ID for the block. These IDs are wrt to the SectionMap in the
 646    :    // parent BlockGraph.
 647  E :    SectionId section() const { return section_; }
 648  E :    void set_section(SectionId section) { section_ = section; }
 649    :  
 650    :    // The block attributes are a bitmask. You can set them wholesale,
 651    :    // or set and clear them individually by bitmasking.
 652  E :    BlockAttributes attributes() const { return attributes_; }
 653  E :    void set_attributes(BlockAttributes attributes) { attributes_ = attributes; }
 654    :  
 655    :    // Set or clear one or more attributes.
 656  E :    void set_attribute(BlockAttributes attribute) { attributes_ |= attribute; }
 657  E :    void clear_attribute(BlockAttributes attribute) {
 658  E :      attributes_ &= ~attribute;
 659  E :    }
 660    :  
 661    :    // This is true iff data_ is in the ownership of the block.
 662    :    // Iff true, the block will delete [] data_ on destruction or when
 663    :    // data is overwritten.
 664  E :    bool owns_data() const { return owns_data_; }
 665    :  
 666    :    // Makes room for the given amount of data at the given offset. This is
 667    :    // special in that it will patch up any labels, source ranges and referrers
 668    :    // that land beyond the newly created data, shifting them to the right by
 669    :    // @p size. If the data for this block is actually allocated it will also
 670    :    // patch up the allocated data by zeroing the newly allocate range of data,
 671    :    // and shifting the tail by @p size. If the new data is strictly implicit
 672    :    // (offset > data_size), then the allocated data is not affected in any way
 673    :    // unless @p always_allocate_data is true.
 674    :    //
 675    :    // @param offset the offset at which to insert the new data.
 676    :    // @param size the size of the new data to be inserted.
 677    :    // @param always_allocate_data if true, then data_size will be grown if
 678    :    //     necessary to ensure that the newly created data can be written.
 679    :    // @pre 0 <= offset <= size()
 680    :    void InsertData(Offset offset, Size size, bool always_allocate_data);
 681    :  
 682    :    // Removes the data in the given range. This will refuse to remove labels,
 683    :    // references and referrers that land in the range, and will fail if any
 684    :    // exist. It will also shift any labels, references and referrers that land
 685    :    // beyond the end of the removed range. Source ranges will also be fixed. If
 686    :    // the removed range lies within the initialized data then the data will also
 687    :    // be truncated/shifted as necessary.
 688    :    //
 689    :    // @param offset the offset at which to remove data.
 690    :    // @param size the size of the data to remove, in bytes.
 691    :    // @returns true on success, false otherwise.
 692    :    // @pre 0 <= offset <= size
 693    :    bool RemoveData(Offset offset, Size size);
 694    :  
 695    :    // Performs an inline resize of data in a BlockGraph. If the data is shrinking
 696    :    // this equates to a RemoveData operation. If it is growing it equates to an
 697    :    // InsertData operation.
 698    :    //
 699    :    // @param offset the offset of the data to resize.
 700    :    // @param current_size the current size of the data to resize.
 701    :    // @param new_size the desired size of the data.
 702    :    // @param always_allocate_data if true, then data_size will be grown if
 703    :    //     necessary to ensure that the resized data can be written.
 704    :    // @returns true on success, false otherwise.
 705    :    // @pre 0 <= offset <= size
 706    :    bool InsertOrRemoveData(Offset offset, Size current_size, Size new_size,
 707    :                            bool always_allocate_data);
 708    :  
 709    :    // Set the data the block refers to.
 710    :    // @param data NULL or the data this block refers to.
 711    :    //     The underlying data must outlive this block.
 712    :    // @param data_size the size of data, or zero if data == NULL.
 713    :    // @pre data_size <= size().
 714    :    void SetData(const uint8* data, size_t data_size);
 715    :  
 716    :    // Allocates and returns a new data buffer of the given size. The returned
 717    :    // data will have been initialized to zero.
 718    :    // @pre data_size > 0.
 719    :    // @pre data_size <= size().
 720    :    uint8* AllocateData(size_t data_size);
 721    :  
 722    :    // Makes a copy of data, returns a pointer to the copy.
 723    :    // @pre data_size <= size().
 724    :    uint8* CopyData(size_t data_size, const void* data);
 725    :  
 726    :    // Resizes data to new_size by truncating or zero-extending the current data.
 727    :    // @pre new_size <= size().
 728    :    const uint8* ResizeData(size_t new_size);
 729    :  
 730    :    // Returns a mutable copy of the block's data. If the block doesn't own
 731    :    // the data on entry, it'll be copied and the copy returned to the caller.
 732    :    uint8* GetMutableData();
 733    :  
 734    :    // The data bytes the block refers to.
 735  E :    const uint8* data() const { return data_; }
 736    :  
 737    :    // The data size may be smaller than the block size (see size()),
 738    :    // when the block e.g. refers to data that's all or part
 739    :    // zero-initialized by the linker/loader.
 740  E :    size_t data_size() const { return data_size_; }
 741    :  
 742  E :    const ReferenceMap& references() const { return references_; }
 743  E :    const ReferrerSet& referrers() const { return referrers_; }
 744  E :    const SourceRanges& source_ranges() const { return source_ranges_; }
 745  E :    SourceRanges& source_ranges() { return source_ranges_; }
 746  E :    const LabelMap& labels() const { return labels_; }
 747    :  
 748    :    // Returns true if there are any other blocks holding a reference to this one.
 749    :    bool HasExternalReferrers() const;
 750    :  
 751    :    // Set the reference at @p offset to @p ref.
 752    :    // If there's a pre-existing reference at @p offset, this overrides it.
 753    :    // @param offset offset of the reference into this block.
 754    :    // @param ref the reference to add.
 755    :    // @returns true iff this inserts a new reference.
 756    :    bool SetReference(Offset offset, const Reference& ref);
 757    :  
 758    :    // Retrieve the reference at @p offset if one exists.
 759    :    // @param reference on success returns the reference @p offset.
 760    :    // @returns true iff there was a reference at @p offset.
 761    :    bool GetReference(Offset offset, Reference* reference) const;
 762    :  
 763    :    // Remove the reference at @p offset.
 764    :    // @returns true iff there was a reference at @p offset.
 765    :    bool RemoveReference(Offset offset);
 766    :  
 767    :    // Remove all references from this block. This is handy when removing a block
 768    :    // from the block graph.
 769    :    bool RemoveAllReferences();
 770    :  
 771    :    // Set a label to @p offset.
 772    :    // A label in code marks the location of the start of an instruction -
 773    :    // e.g. a location where disassembly can usefully commence. Labels
 774    :    // appear to be inserted by the VS tool chain where e.g. a switch
 775    :    // statement is implemented with a jump table, to note the location
 776    :    // of the jump destinations.
 777    :    // @param offset the offset of the label to set.
 778    :    // @param name the name of the label.
 779    :    // @param attributes the attributes of the label.
 780    :    // @returns true iff a new label is inserted.
 781    :    // @note that only one label can exist at each offset, and the first
 782    :    //     label set at any offset will stay there.
 783    :    // @{
 784    :    bool SetLabel(Offset offset, const Label& label);
 785    :    bool SetLabel(Offset offset,
 786    :                  const base::StringPiece& name,
 787  E :                  LabelAttributes attributes) {
 788  E :      return SetLabel(offset, Label(name, attributes));
 789  E :    }
 790    :    // @}
 791    :  
 792    :    // Gets the label at the given @p offset.
 793    :    // @param offset the offset of the label to get.
 794    :    // @param label the string to receive the label.
 795    :    // @returns true if the label exists, false otherwise.
 796    :    bool GetLabel(Offset offset, Label* label) const;
 797    :  
 798    :    // Removes the label at the given @p offset.
 799    :    // @param offset the offset of the label to remove.
 800    :    // @returns true if the label existed and was removed, false it it did not
 801    :    //     exist.
 802    :    bool RemoveLabel(Offset offset);
 803    :  
 804    :    // Returns true iff the block has a label at @p offset.
 805    :    // @param offset the offset of the label to search for.
 806    :    bool HasLabel(Offset offset) const;
 807    :  
 808    :    // Change all references to this block to refer to @p new_block instead,
 809    :    // while offsetting each reference by @p offset.
 810    :    // @param offset The offset that we should apply to each reference.
 811    :    // @param new_block The block the reference should point to.
 812    :    // @param flags The flags that control some parameters of this function.
 813    :    // @note this fails if any of the transferred references end up with offsets
 814    :    //     less than zero, or greater than new_block->size().
 815    :    // @returns true iff all references were transferred successfully.
 816    :    bool TransferReferrers(Offset offset,
 817    :                           Block* new_block,
 818    :                           TransferReferrersFlags flags);
 819    :  
 820    :    // Returns true if this block contains the given range of bytes.
 821    :    bool Contains(RelativeAddress address, size_t size) const;
 822    :  
 823    :   protected:
 824    :    // Give BlockGraph access to our innards for serialization.
 825    :    friend class BlockGraph;
 826    :    // Give BlockGraphSerializer access to our innards for serialization.
 827    :    friend class BlockGraphSerializer;
 828    :  
 829    :    // Full constructor.
 830    :    // @note This is protected so that blocks may only be created via the
 831    :    //     BlockGraph factory.
 832    :    Block(BlockId id,
 833    :          BlockType type,
 834    :          Size size,
 835    :          const base::StringPiece& name,
 836    :          BlockGraph* block_graph);
 837    :  
 838    :    // This constructor is used by serialization.
 839    :    explicit Block(BlockGraph* block_graph);
 840    :  
 841    :    // Allocates and returns a new data buffer of the given size. The returned
 842    :    // data buffer will not have been initialized in any way.
 843    :    uint8* AllocateRawData(size_t size);
 844    :  
 845    :    BlockId id_;
 846    :    BlockType type_;
 847    :    Size size_;
 848    :    Size alignment_;
 849    :    Offset alignment_offset_;
 850    :    Size padding_before_;
 851    :    const std::string* name_;
 852    :    const std::string* compiland_name_;
 853    :    RelativeAddress addr_;
 854    :  
 855    :    // BlockGraph to which belongs this Block. A block can only belongs to one
 856    :    // Block Graph.
 857    :    BlockGraph* block_graph_;
 858    :  
 859    :    SectionId section_;
 860    :    BlockAttributes attributes_;
 861    :  
 862    :    ReferenceMap references_;
 863    :    ReferrerSet referrers_;
 864    :    SourceRanges source_ranges_;
 865    :    LabelMap labels_;
 866    :  
 867    :    // True iff data_ is ours to deallocate with delete [].
 868    :    // If this is false, data_ must be guaranteed to outlive the block.
 869    :    bool owns_data_;
 870    :    // A pointer to the code or data we represent.
 871    :    const uint8* data_;
 872    :    // Size of the above.
 873    :    size_t data_size_;
 874    :  };
 875    :  
 876    :  // A graph address space endows a graph with a non-overlapping ordering
 877    :  // on blocks, where each block occupies zero or one address ranges in the
 878    :  // address space. No two blocks may overlap in an address space. Empty blocks
 879    :  // are not stored in the underlying address-space implementation itself, but do
 880    :  // have associated addresses and are stored in the block-address map.
 881    :  class BlockGraph::AddressSpace {
 882    :   public:
 883    :    typedef core::AddressSpace<RelativeAddress, BlockGraph::Size, Block*>
 884    :        AddressSpaceImpl;
 885    :    typedef AddressSpaceImpl::Range Range;
 886    :    typedef AddressSpaceImpl::RangeMap RangeMap;
 887    :    typedef AddressSpaceImpl::RangeMapIter RangeMapIter;
 888    :    typedef AddressSpaceImpl::RangeMapConstIter RangeMapConstIter;
 889    :    typedef AddressSpaceImpl::RangeMapIterPair RangeMapIterPair;
 890    :    typedef AddressSpaceImpl::RangeMapConstIterPair RangeMapConstIterPair;
 891    :    typedef stdext::hash_map<const Block*, RelativeAddress> BlockAddressMap;
 892    :  
 893    :    // Constructs a new empty address space.
 894    :    // @p start to @p start + @p size on @p graph.
 895    :    explicit AddressSpace(BlockGraph* graph);
 896    :  
 897    :    // Add a block of type @p type and @p size at @p address to our associated
 898    :    // graph, and return the new block.
 899    :    // @returns the new block, or NULL if the new block would overlap
 900    :    //     an existing block.
 901    :    Block* AddBlock(BlockType type,
 902    :                    RelativeAddress addr,
 903    :                    Size size,
 904    :                    const base::StringPiece& name);
 905    :  
 906    :    // Resizes a block in the address-space by extending to the right, or
 907    :    // trimming. Updates the block size but does not udpate its contents. This
 908    :    // invalidates any RangeMap iterators to the block in question.
 909    :    // @param block The block whose size is to change.
 910    :    // @param size The new size of the block. Must be > 0.
 911    :    // @returns true on success, false if not possible due to a conflict.
 912    :    bool ResizeBlock(Block* block, size_t size);
 913    :  
 914    :    // Merges all blocks that intersect @p range into a single block.
 915    :    // Moves labels and references from the intersecting blocks to the
 916    :    // merged block, and changes referring blocks to refer to the new,
 917    :    // merged block. Removes the original blocks from the BlockGraph.
 918    :    // @returns the new, merged block if there was at least one intersecting
 919    :    //     block in @p range, or NULL otherwise.
 920    :    Block* MergeIntersectingBlocks(const Range& range);
 921    :  
 922    :    // Insert existing block @p block at @p address.
 923    :    // @returns true on success, or false if the @p block would overlap
 924    :    //     an existing block.
 925    :    bool InsertBlock(RelativeAddress addr, Block* block);
 926    :  
 927    :    // Returns a pointer to the block containing address, or NULL
 928    :    // if no block contains address.
 929    :    Block* GetBlockByAddress(RelativeAddress addr) const;
 930    :  
 931    :    // Returns a pointer to the block containing the address range
 932    :    // [address, address + size), or NULL if no block contains that
 933    :    // range.
 934    :    Block* GetContainingBlock(RelativeAddress addr, Size size) const;
 935    :  
 936    :    // Finds the first block, if any that intersects
 937    :    // [@p address, @p address + @p size).
 938    :    Block* GetFirstIntersectingBlock(RelativeAddress address, Size size);
 939    :  
 940    :    // Check whether the address space contains @p block.
 941    :    // @param block the block in question.
 942    :    // @returns true if the block is in the address space, false otherwise.
 943    :    bool ContainsBlock(const Block* block);
 944    :  
 945    :    // Locates all blocks that intersect [@p address, @p address + @p size).
 946    :    // @returns a pair of iterators that iterate over the found blocks.
 947    :    RangeMapConstIterPair GetIntersectingBlocks(RelativeAddress address,
 948    :                                                Size size) const;
 949    :    RangeMapIterPair GetIntersectingBlocks(RelativeAddress address, Size size);
 950    :  
 951    :    // Retrieve the address off @p block.
 952    :    // @param block the block in question.
 953    :    // @param addr on success, returns the address of @p block in this
 954    :    //     address space.
 955    :    // @returns true on success, false if @p block is not in this
 956    :    //     address space.
 957    :    bool GetAddressOf(const Block* block, RelativeAddress* addr) const;
 958    :  
 959    :    // Accessor.
 960  E :    BlockGraph* graph() { return graph_; }
 961  E :    const BlockGraph* graph() const { return graph_; }
 962    :  
 963  E :    RangeMapConstIter begin() const {
 964  E :      return address_space_.ranges().begin();
 965  E :    }
 966    :  
 967  E :    RangeMapConstIter end() const {
 968  E :      return address_space_.ranges().end();
 969  E :    }
 970    :  
 971    :    // @returns the number of blocks in the address-space. This includes empty
 972    :    //     blocks, which won't actually be visited by iteration.
 973  E :    size_t size() const {
 974    :      // We use the size of the map of addresses, as zero sized blocks only live
 975    :      // there.
 976  E :      return block_addresses_.size();
 977  E :    }
 978    :  
 979    :    // @returns a reference to the underlaying address-space implementation. Only
 980    :    //     non-empty blocks are inserted in the address space.
 981  E :    const AddressSpaceImpl& address_space_impl() const {
 982  E :      return address_space_;
 983  E :    }
 984    :  
 985    :    // @returne a reference to the map of blocks addresses, by block pointer.
 986  E :    const BlockAddressMap& block_addresses() const {
 987  E :      return block_addresses_;
 988  E :    }
 989    :  
 990    :   protected:
 991    :    bool InsertImpl(RelativeAddress addr, Block* block);
 992    :  
 993    :    AddressSpaceImpl address_space_;
 994    :    BlockAddressMap block_addresses_;
 995    :    BlockGraph* graph_;
 996    :  };
 997    :  
 998    :  // Represents a reference from one block to another. References may be offset.
 999    :  // That is, they may refer to an object at a given location, but actually point
1000    :  // to a location that is some fixed distance away from that object. This allows,
1001    :  // for example, non-zero based indexing into a table. The object that is
1002    :  // intended to be dereferenced is called the 'base' of the offset.
1003    :  //
1004    :  // BlockGraph references are from a location (offset) in one block, to some
1005    :  // location in another block. The referenced block itself plays the role of the
1006    :  // 'base' of the reference, with the offset of the reference being stored as
1007    :  // an integer from the beginning of the block. However, basic block
1008    :  // decomposition requires breaking the block into smaller pieces and thus we
1009    :  // need to carry around an explicit base value, indicating which byte in the
1010    :  // block is intended to be referenced.
1011    :  //
1012    :  // A direct reference to a location will have the same value for 'base' and
1013    :  // 'offset'.
1014    :  //
1015    :  // Here is an example:
1016    :  //
1017    :  //        /----------\
1018    :  //        +---------------------------+
1019    :  //  O     |          B                | <--- Referenced block
1020    :  //        +---------------------------+      B = base
1021    :  //  \-----/                                  O = offset
1022    :  //
1023    :  class BlockGraph::Reference {
1024    :   public:
1025    :    Reference() :
1026  E :        type_(RELATIVE_REF), size_(0), referenced_(NULL), offset_(0), base_(0) {
1027  E :    }
1028    :  
1029    :    // @param type type of reference.
1030    :    // @param size size of reference.
1031    :    // @param referenced the referenced block.
1032    :    // @param offset offset from the beginning of the block of the location to be
1033    :    //     explicitly referred to.
1034    :    // @param base offset into the block of the location actually being
1035    :    //     referenced. This must be strictly within @p referenced.
1036    :    Reference(ReferenceType type,
1037    :              Size size,
1038    :              Block* referenced,
1039    :              Offset offset,
1040    :              Offset base)
1041    :        : type_(type),
1042    :          size_(size),
1043    :          referenced_(referenced),
1044    :          offset_(offset),
1045  E :          base_(base) {
1046  E :      DCHECK(IsValid());
1047  E :    }
1048    :  
1049    :    // Copy constructor.
1050    :    Reference(const Reference& other)
1051    :        : type_(other.type_),
1052    :          size_(other.size_),
1053    :          referenced_(other.referenced_),
1054    :          offset_(other.offset_),
1055  E :          base_(other.base_) {
1056  E :    }
1057    :  
1058    :    // Accessors.
1059  E :    ReferenceType type() const { return type_; }
1060  E :    Size size() const { return size_; }
1061  E :    Block* referenced() const { return referenced_; }
1062  E :    Offset offset() const { return offset_; }
1063  E :    Offset base() const { return base_; }
1064    :  
1065    :    // Determines if this is a direct reference. That is, if the actual location
1066    :    // being referenced (offset) and the intended location being referenced (base)
1067    :    // are the same.
1068    :    //
1069    :    // @returns true if the reference is direct, false otherwise.
1070  E :    bool IsDirect() const { return base_ == offset_; }
1071    :  
1072    :    // Determines if this is a valid reference, by imposing size constraints on
1073    :    // reference types, and determining if the base address of the reference is
1074    :    // strictly contained within the referenced block.
1075    :    //
1076    :    // @returns true if valid, false otherwise.
1077    :    bool IsValid() const;
1078    :  
1079  E :    bool operator==(const Reference& other) const {
1080    :      return type_ == other.type_ &&
1081    :          size_ == other.size_ &&
1082    :          referenced_ == other.referenced_ &&
1083    :          offset_ == other.offset_ &&
1084  E :          base_ == other.base_;
1085  E :    }
1086    :  
1087    :    // The maximum size that a reference may have. This needs to be kept in sync
1088    :    // with the expectations of IsValid().
1089    :    static const size_t kMaximumSize = 4;
1090    :  
1091    :    // Returns true if the given reference type and size combination is valid.
1092    :    static bool IsValidTypeSize(ReferenceType type, Size size);
1093    :  
1094    :   private:
1095    :    // Type of this reference.
1096    :    ReferenceType type_;
1097    :  
1098    :    // Size of this reference.
1099    :    // Absolute references are always pointer wide, but PC-relative
1100    :    // references can be 1, 2 or 4 bytes wide, which affects their range.
1101    :    Size size_;
1102    :  
1103    :    // The block referenced.
1104    :    Block* referenced_;
1105    :  
1106    :    // Offset into the referenced block.
1107    :    Offset offset_;
1108    :  
1109    :    // The base of the reference, as in offset in the block. This must be a
1110    :    // location strictly within the block.
1111    :    Offset base_;
1112    :  };
1113    :  
1114    :  // Commonly used container types.
1115    :  typedef std::vector<BlockGraph::Block*> BlockVector;
1116    :  typedef std::vector<const BlockGraph::Block*> ConstBlockVector;
1117    :  
1118    :  // A small helper struct for dumping block information to log messages.
1119    :  struct BlockInfo {
1120    :    enum AddressType {
1121    :      kNoAddress,
1122    :      kAbsoluteAddress,
1123    :      kFileOffsetAddress,
1124    :      kRelativeAddress,
1125    :    };
1126    :  
1127  i :    explicit BlockInfo(const BlockGraph::Block* block)
1128    :        : block(block), type(kNoAddress) {
1129  i :      DCHECK_NE(static_cast<BlockGraph::Block*>(nullptr), block);
1130  i :    }
1131    :  
1132    :    BlockInfo(const BlockGraph::Block* block,
1133    :              core::AbsoluteAddress address)
1134    :        : block(block), type(kAbsoluteAddress), abs_addr(address) {
1135    :      DCHECK_NE(static_cast<BlockGraph::Block*>(nullptr), block);
1136    :    }
1137    :    BlockInfo(const BlockGraph::Block* block,
1138    :              core::FileOffsetAddress address)
1139    :        : block(block), type(kFileOffsetAddress), file_addr(address) {
1140    :      DCHECK_NE(static_cast<BlockGraph::Block*>(nullptr), block);
1141    :    }
1142  i :    BlockInfo(const BlockGraph::Block* block,
1143    :              core::RelativeAddress address)
1144    :        : block(block), type(kRelativeAddress), rel_addr(address) {
1145  i :      DCHECK_NE(static_cast<BlockGraph::Block*>(nullptr), block);
1146  i :    }
1147    :  
1148    :    const BlockGraph::Block* block;
1149    :    AddressType type;
1150    :  
1151    :    // Ideally these would be in a union but because they have non-trivial
1152    :    // constructors they are not allowed.
1153    :    core::AbsoluteAddress abs_addr;
1154    :    core::FileOffsetAddress file_addr;
1155    :    core::RelativeAddress rel_addr;
1156    :  
1157    :   private:
1158    :    DISALLOW_COPY_AND_ASSIGN(BlockInfo);
1159    :  };
1160    :  
1161    :  }  // namespace block_graph
1162    :  
1163    :  // Pretty prints a BlockInfo to an ostream. This has to be outside of any
1164    :  // namespaces so that operator<< is found properly.
1165    :  std::ostream& operator<<(std::ostream& os, const block_graph::BlockInfo& bi);
1166    :  
1167    :  #endif  // SYZYGY_BLOCK_GRAPH_BLOCK_GRAPH_H_

Coverage information generated Thu Mar 26 16:15:41 2015.