// Copyright 2014 The Crashpad Authors. 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 "minidump/minidump_writable.h"

#include <stdint.h>

#include "base/cxx17_backports.h"
#include "base/logging.h"
#include "util/file/file_writer.h"
#include "util/numeric/safe_assignment.h"

namespace {

constexpr size_t kMaximumAlignment = 16;

}  // namespace

namespace crashpad {
namespace internal {

MinidumpWritable::~MinidumpWritable() {
}

bool MinidumpWritable::WriteEverything(FileWriterInterface* file_writer) {
  DCHECK_EQ(state_, kStateMutable);

  if (!Freeze()) {
    return false;
  }

  DCHECK_EQ(state_, kStateFrozen);

  FileOffset offset = 0;
  std::vector<MinidumpWritable*> write_sequence;
  size_t size = WillWriteAtOffset(kPhaseEarly, &offset, &write_sequence);
  if (size == kInvalidSize) {
    return false;
  }

  offset += size;
  if (WillWriteAtOffset(kPhaseLate, &offset, &write_sequence) == kInvalidSize) {
    return false;
  }

  DCHECK_EQ(state_, kStateWritable);
  DCHECK_EQ(write_sequence.front(), this);

  for (MinidumpWritable* writable : write_sequence) {
    if (!writable->WritePaddingAndObject(file_writer)) {
      return false;
    }
  }

  DCHECK_EQ(state_, kStateWritten);

  return true;
}

void MinidumpWritable::RegisterRVA(RVA* rva) {
  DCHECK_LE(state_, kStateFrozen);

  registered_rvas_.push_back(rva);
}

void MinidumpWritable::RegisterLocationDescriptor(
    MINIDUMP_LOCATION_DESCRIPTOR* location_descriptor) {
  DCHECK_LE(state_, kStateFrozen);

  registered_location_descriptors_.push_back(location_descriptor);
}

MinidumpWritable::MinidumpWritable()
    : registered_rvas_(),
      registered_location_descriptors_(),
      leading_pad_bytes_(0),
      state_(kStateMutable) {
}

bool MinidumpWritable::Freeze() {
  DCHECK_EQ(state_, kStateMutable);
  state_ = kStateFrozen;

  std::vector<MinidumpWritable*> children = Children();
  for (MinidumpWritable* child : children) {
    if (!child->Freeze()) {
      return false;
    }
  }

  return true;
}

size_t MinidumpWritable::Alignment() {
  DCHECK_GE(state_, kStateFrozen);

  return 4;
}

std::vector<MinidumpWritable*> MinidumpWritable::Children() {
  DCHECK_GE(state_, kStateFrozen);

  return std::vector<MinidumpWritable*>();
}

MinidumpWritable::Phase MinidumpWritable::WritePhase() {
  return kPhaseEarly;
}

size_t MinidumpWritable::WillWriteAtOffset(
    Phase phase,
    FileOffset* offset,
    std::vector<MinidumpWritable*>* write_sequence) {
  FileOffset local_offset = *offset;
  CHECK_GE(local_offset, 0);

  size_t leading_pad_bytes_this_phase;
  size_t size;
  if (phase == WritePhase()) {
    DCHECK_EQ(state_, kStateFrozen);

    // Add this object to the sequence of MinidumpWritable objects to be
    // written.
    write_sequence->push_back(this);

    size = SizeOfObject();

    if (size > 0) {
      // Honor this object’s request to be aligned to a specific byte boundary.
      // Once the alignment is corrected, this object knows exactly what file
      // offset it will be written at.
      size_t alignment = Alignment();
      CHECK_LE(alignment, kMaximumAlignment);

      leading_pad_bytes_this_phase =
          (alignment - (local_offset % alignment)) % alignment;
      local_offset += leading_pad_bytes_this_phase;
      *offset = local_offset;
    } else {
      // If the object is size 0, alignment is of no concern.
      leading_pad_bytes_this_phase = 0;
    }
    leading_pad_bytes_ = leading_pad_bytes_this_phase;

    // Now that the file offset that this object will be written at is known,
    // let the subclass implementation know in case it’s interested.
    if (!WillWriteAtOffsetImpl(local_offset)) {
      return kInvalidSize;
    }

    // Populate the RVA fields in other objects that have registered to point to
    // this one. Typically, a parent object will have registered to point to its
    // children, but this can also occur where no parent-child relationship
    // exists.
    if (!registered_rvas_.empty() ||
        !registered_location_descriptors_.empty()) {
      RVA local_rva;
      if (!AssignIfInRange(&local_rva, local_offset)) {
        LOG(ERROR) << "offset " << local_offset << " out of range";
        return kInvalidSize;
      }

      for (RVA* rva : registered_rvas_) {
        *rva = local_rva;
      }

      if (!registered_location_descriptors_.empty()) {
        decltype(registered_location_descriptors_[0]->DataSize) local_size;
        if (!AssignIfInRange(&local_size, size)) {
          LOG(ERROR) << "size " << size << " out of range";
          return kInvalidSize;
        }

        for (MINIDUMP_LOCATION_DESCRIPTOR* location_descriptor :
                 registered_location_descriptors_) {
          location_descriptor->DataSize = local_size;
          location_descriptor->Rva = local_rva;
        }
      }
    }

    // This object is now considered writable. However, if it contains RVA or
    // MINIDUMP_LOCATION_DESCRIPTOR fields, they may not be fully updated yet,
    // because it’s the repsonsibility of these fields’ pointees to update them.
    // Once WillWriteAtOffset has completed running for both phases on an entire
    // tree, and the entire tree has moved into kStateFrozen, all RVA and
    // MINIDUMP_LOCATION_DESCRIPTOR fields within that tree will be populated.
    state_ = kStateWritable;
  } else {
    if (phase == kPhaseEarly) {
      DCHECK_EQ(state_, kStateFrozen);
    } else {
      DCHECK_EQ(state_, kStateWritable);
    }

    size = 0;
    leading_pad_bytes_this_phase = 0;
  }

  // Loop over children regardless of whether this object itself will write
  // during this phase. An object’s children are not required to be written
  // during the same phase as their parent.
  std::vector<MinidumpWritable*> children = Children();
  for (MinidumpWritable* child : children) {
    // Use “auto” here because it’s impossible to know whether size_t (size) or
    // FileOffset (local_offset) is the wider type, and thus what type the
    // result of adding these two variables will have.
    auto unaligned_child_offset = local_offset + size;
    FileOffset child_offset;
    if (!AssignIfInRange(&child_offset, unaligned_child_offset)) {
      LOG(ERROR) << "offset " << unaligned_child_offset << " out of range";
      return kInvalidSize;
    }

    size_t child_size =
        child->WillWriteAtOffset(phase, &child_offset, write_sequence);
    if (child_size == kInvalidSize) {
      return kInvalidSize;
    }

    size += child_size;
  }

  return leading_pad_bytes_this_phase + size;
}

bool MinidumpWritable::WillWriteAtOffsetImpl(FileOffset offset) {
  return true;
}

bool MinidumpWritable::WritePaddingAndObject(FileWriterInterface* file_writer) {
  DCHECK_EQ(state_, kStateWritable);

  // The number of elements in kZeroes must be at least one less than the
  // maximum Alignment() ever encountered.
  static constexpr uint8_t kZeroes[kMaximumAlignment - 1] = {};
  DCHECK_LE(leading_pad_bytes_, base::size(kZeroes));

  if (leading_pad_bytes_) {
    if (!file_writer->Write(&kZeroes, leading_pad_bytes_)) {
      return false;
    }
  }

  if (!WriteObject(file_writer)) {
    return false;
  }

  state_ = kStateWritten;
  return true;
}

}  // namespace internal
}  // namespace crashpad
