// 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 "snapshot/mac/mach_o_image_annotations_reader.h"

#include <mach-o/loader.h>
#include <mach/mach.h>
#include <sys/types.h>

#include <utility>

#include "base/logging.h"
#include "client/crashpad_info.h"
#include "client/simple_string_dictionary.h"
#include "snapshot/mac/mach_o_image_reader.h"
#include "snapshot/mac/process_reader_mac.h"
#include "snapshot/snapshot_constants.h"
#include "util/stdlib/strnlen.h"

namespace crashpad {

MachOImageAnnotationsReader::MachOImageAnnotationsReader(
    ProcessReaderMac* process_reader,
    const MachOImageReader* image_reader,
    const std::string& name)
    : name_(name),
      process_reader_(process_reader),
      image_reader_(image_reader) {}

std::vector<std::string> MachOImageAnnotationsReader::Vector() const {
  std::vector<std::string> vector_annotations;

  ReadCrashReporterClientAnnotations(&vector_annotations);
  ReadDyldErrorStringAnnotation(&vector_annotations);

  return vector_annotations;
}

std::map<std::string, std::string> MachOImageAnnotationsReader::SimpleMap()
    const {
  std::map<std::string, std::string> simple_map_annotations;

  ReadCrashpadSimpleAnnotations(&simple_map_annotations);

  return simple_map_annotations;
}

std::vector<AnnotationSnapshot> MachOImageAnnotationsReader::AnnotationsList()
    const {
  std::vector<AnnotationSnapshot> annotations;

  ReadCrashpadAnnotationsList(&annotations);

  return annotations;
}

void MachOImageAnnotationsReader::ReadCrashReporterClientAnnotations(
    std::vector<std::string>* vector_annotations) const {
  mach_vm_address_t crash_info_address;
  const process_types::section* crash_info_section =
      image_reader_->GetSectionByName(
          SEG_DATA, "__crash_info", &crash_info_address);
  if (!crash_info_section) {
    return;
  }

  process_types::crashreporter_annotations_t crash_info;
  if (!crash_info.Read(process_reader_, crash_info_address)) {
    LOG(WARNING) << "could not read crash info from " << name_;
    return;
  }

  if (crash_info.version != 4 && crash_info.version != 5) {
    LOG(WARNING) << "unexpected crash info version " << crash_info.version
                 << " in " << name_;
    return;
  }

  size_t expected_size =
      process_types::crashreporter_annotations_t::ExpectedSizeForVersion(
          process_reader_, crash_info.version);
  if (crash_info_section->size < expected_size) {
    LOG(WARNING) << "small crash info section size " << crash_info_section->size
                 << " < " << expected_size << " for version "
                 << crash_info.version << " in " << name_;
    return;
  }

  // This number was totally made up out of nowhere, but it seems prudent to
  // enforce some limit.
  constexpr size_t kMaxMessageSize = 1024;
  if (crash_info.message) {
    std::string message;
    if (process_reader_->Memory()->ReadCStringSizeLimited(
            crash_info.message, kMaxMessageSize, &message)) {
      vector_annotations->push_back(message);
    } else {
      LOG(WARNING) << "could not read crash message in " << name_;
    }
  }

  if (crash_info.message2) {
    std::string message;
    if (process_reader_->Memory()->ReadCStringSizeLimited(
            crash_info.message2, kMaxMessageSize, &message)) {
      vector_annotations->push_back(message);
    } else {
      LOG(WARNING) << "could not read crash message 2 in " << name_;
    }
  }
}

void MachOImageAnnotationsReader::ReadDyldErrorStringAnnotation(
    std::vector<std::string>* vector_annotations) const {
  // dyld stores its error string at the external symbol for |const char
  // error_string[1024]|. See 10.9.5 dyld-239.4/src/dyld.cpp error_string.
  if (image_reader_->FileType() != MH_DYLINKER) {
    return;
  }

  mach_vm_address_t error_string_address;
  if (!image_reader_->LookUpExternalDefinedSymbol("_error_string",
                                                  &error_string_address)) {
    return;
  }

  std::string message;
  // 1024 here is distinct from kMaxMessageSize above, because it refers to a
  // precisely-sized buffer inside dyld.
  if (process_reader_->Memory()->ReadCStringSizeLimited(
          error_string_address, 1024, &message)) {
    if (!message.empty()) {
      vector_annotations->push_back(message);
    }
  } else {
    LOG(WARNING) << "could not read dylinker error string from " << name_;
  }
}

void MachOImageAnnotationsReader::ReadCrashpadSimpleAnnotations(
    std::map<std::string, std::string>* simple_map_annotations) const {
  process_types::CrashpadInfo crashpad_info;
  if (!image_reader_->GetCrashpadInfo(&crashpad_info) ||
      !crashpad_info.simple_annotations) {
    return;
  }

  std::vector<SimpleStringDictionary::Entry>
      simple_annotations(SimpleStringDictionary::num_entries);
  if (!process_reader_->Memory()->Read(
          crashpad_info.simple_annotations,
          simple_annotations.size() * sizeof(simple_annotations[0]),
          &simple_annotations[0])) {
    LOG(WARNING) << "could not read simple annotations from " << name_;
    return;
  }

  for (const auto& entry : simple_annotations) {
    size_t key_length = strnlen(entry.key, sizeof(entry.key));
    if (key_length) {
      std::string key(entry.key, key_length);
      std::string value(entry.value, strnlen(entry.value, sizeof(entry.value)));
      if (!simple_map_annotations->insert(std::make_pair(key, value)).second) {
        LOG(INFO) << "duplicate simple annotation " << key << " in " << name_;
      }
    }
  }
}

// TODO(https://crbug.com/crashpad/270): Replace implementations of
// ReadCrashpadAnnotationsList and ReadCrashpadSimpleAnnotations with the
// platform-agnostic implementations in ImageAnnotationReader.
void MachOImageAnnotationsReader::ReadCrashpadAnnotationsList(
    std::vector<AnnotationSnapshot>* annotations) const {
  process_types::CrashpadInfo crashpad_info;
  if (!image_reader_->GetCrashpadInfo(&crashpad_info) ||
      !crashpad_info.annotations_list) {
    return;
  }

  process_types::AnnotationList annotation_list_object;
  if (!annotation_list_object.Read(process_reader_,
                                   crashpad_info.annotations_list)) {
    LOG(WARNING) << "could not read annotations list object in " << name_;
    return;
  }

  process_types::Annotation current = annotation_list_object.head;
  for (size_t index = 0;
       current.link_node != annotation_list_object.tail_pointer &&
       index < kMaxNumberOfAnnotations;
       ++index) {
    if (!current.Read(process_reader_, current.link_node)) {
      LOG(WARNING) << "could not read annotation at index " << index << " in "
                   << name_;
      return;
    }

    if (current.size == 0) {
      continue;
    }

    AnnotationSnapshot snapshot;
    snapshot.type = current.type;
    snapshot.value.resize(current.size);

    if (!process_reader_->Memory()->ReadCStringSizeLimited(
            current.name, Annotation::kNameMaxLength, &snapshot.name)) {
      LOG(WARNING) << "could not read annotation name at index " << index
                   << " in " << name_;
      continue;
    }

    size_t size =
        std::min(static_cast<size_t>(current.size), Annotation::kValueMaxSize);
    if (!process_reader_->Memory()->Read(
            current.value, size, snapshot.value.data())) {
      LOG(WARNING) << "could not read annotation value at index " << index
                   << " in " << name_;
      continue;
    }

    annotations->push_back(std::move(snapshot));
  }
}

}  // namespace crashpad
