chromium/third_party/breakpad/breakpad/src/client/linux/microdump_writer/microdump_writer.cc

// Copyright 2014 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// This translation unit generates microdumps into the console (logcat on
// Android). See crbug.com/410294 for more info and design docs.

#ifdef HAVE_CONFIG_H
#include <config.h>  // Must come first
#endif

#include "client/linux/microdump_writer/microdump_writer.h"

#include <limits>

#include <sys/utsname.h>

#include "client/linux/dump_writer_common/thread_info.h"
#include "client/linux/dump_writer_common/ucontext_reader.h"
#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/microdump_extra_info.h"
#include "client/linux/log/log.h"
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
#include "common/linux/file_id.h"
#include "common/linux/linux_libc_support.h"
#include "common/memory_allocator.h"

namespace {

auto_wasteful_vector;
kDefaultBuildIdSize;
ExceptionHandler;
LinuxDumper;
LinuxPtraceDumper;
MappingInfo;
MappingList;
MicrodumpExtraInfo;
RawContextCPU;
ThreadInfo;
UContextReader;

const size_t kLineBufferSize =;

#if !defined(__LP64__)
// The following are only used by DumpFreeSpace, so need to be compiled
// in conditionally in the same way.

template <typename Dst, typename Src>
Dst saturated_cast(Src src) {
  if (src >= std::numeric_limits<Dst>::max())
    return std::numeric_limits<Dst>::max();
  if (src <= std::numeric_limits<Dst>::min())
    return std::numeric_limits<Dst>::min();
  return static_cast<Dst>(src);
}

int Log2Floor(uint64_t n) {
  // Copied from chromium src/base/bits.h
  if (n == 0)
    return -1;
  int log = 0;
  uint64_t value = n;
  for (int i = 5; i >= 0; --i) {
    int shift = (1 << i);
    uint64_t x = value >> shift;
    if (x != 0) {
      value = x;
      log += shift;
    }
  }
  assert(value == 1u);
  return log;
}

bool MappingsAreAdjacent(const MappingInfo& a, const MappingInfo& b) {
  // Because of load biasing, we can end up with a situation where two
  // mappings actually overlap. So we will define adjacency to also include a
  // b start address that lies within a's address range (including starting
  // immediately after a).
  // Because load biasing only ever moves the start address backwards, the end
  // address should still increase.
  return a.start_addr <= b.start_addr && a.start_addr + a.size >= b.start_addr;
}

bool MappingLessThan(const MappingInfo* a, const MappingInfo* b) {
  // Return true if mapping a is before mapping b.
  // For the same reason (load biasing) we compare end addresses, which - unlike
  // start addresses - will not have been modified.
  return a->start_addr + a->size < b->start_addr + b->size;
}

size_t NextOrderedMapping(
    const google_breakpad::wasteful_vector<MappingInfo*>& mappings,
    size_t curr) {
  // Find the mapping that directly follows mappings[curr].
  // If no such mapping exists, return |invalid| to indicate this.
  const size_t invalid = std::numeric_limits<size_t>::max();
  size_t best = invalid;
  for (size_t next = 0; next < mappings.size(); ++next) {
    if (MappingLessThan(mappings[curr], mappings[next]) &&
        (best == invalid || MappingLessThan(mappings[next], mappings[best]))) {
      best = next;
    }
  }
  return best;
}

#endif  // !__LP64__

class MicrodumpWriter {};
}  // namespace

namespace google_breakpad {

bool WriteMicrodump(pid_t crashing_process,
                    const void* blob,
                    size_t blob_size,
                    const MappingList& mappings,
                    bool skip_dump_if_principal_mapping_not_referenced,
                    uintptr_t address_within_principal_mapping,
                    bool sanitize_stack,
                    const MicrodumpExtraInfo& microdump_extra_info) {}

}  // namespace google_breakpad