// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// 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 Inc. 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.

// elf_core_dump.cc: Implement google_breakpad::ElfCoreDump.
// See elf_core_dump.h for details.

#include "common/linux/elf_core_dump.h"

#include <stddef.h>
#include <string.h>

namespace google_breakpad {

// Implementation of ElfCoreDump::Note.

ElfCoreDump::Note::Note() {}

ElfCoreDump::Note::Note(const MemoryRange& content) : content_(content) {}

bool ElfCoreDump::Note::IsValid() const {
  return GetHeader() != NULL;
}

const ElfCoreDump::Nhdr* ElfCoreDump::Note::GetHeader() const {
  return content_.GetData<Nhdr>(0);
}

ElfCoreDump::Word ElfCoreDump::Note::GetType() const {
  const Nhdr* header = GetHeader();
  // 0 is not being used as a NOTE type.
  return header ? header->n_type : 0;
}

MemoryRange ElfCoreDump::Note::GetName() const {
  const Nhdr* header = GetHeader();
  if (header) {
      return content_.Subrange(sizeof(Nhdr), header->n_namesz);
  }
  return MemoryRange();
}

MemoryRange ElfCoreDump::Note::GetDescription() const {
  const Nhdr* header = GetHeader();
  if (header) {
    return content_.Subrange(AlignedSize(sizeof(Nhdr) + header->n_namesz),
                             header->n_descsz);
  }
  return MemoryRange();
}

ElfCoreDump::Note ElfCoreDump::Note::GetNextNote() const {
  MemoryRange next_content;
  const Nhdr* header = GetHeader();
  if (header) {
    size_t next_offset = AlignedSize(sizeof(Nhdr) + header->n_namesz);
    next_offset = AlignedSize(next_offset + header->n_descsz);
    next_content =
        content_.Subrange(next_offset, content_.length() - next_offset);
  }
  return Note(next_content);
}

// static
size_t ElfCoreDump::Note::AlignedSize(size_t size) {
  size_t mask = sizeof(Word) - 1;
  return (size + mask) & ~mask;
}


// Implementation of ElfCoreDump.

ElfCoreDump::ElfCoreDump() {}

ElfCoreDump::ElfCoreDump(const MemoryRange& content)
    : content_(content) {
}

void ElfCoreDump::SetContent(const MemoryRange& content) {
  content_ = content;
}

bool ElfCoreDump::IsValid() const {
  const Ehdr* header = GetHeader();
  return (header &&
          header->e_ident[0] == ELFMAG0 &&
          header->e_ident[1] == ELFMAG1 &&
          header->e_ident[2] == ELFMAG2 &&
          header->e_ident[3] == ELFMAG3 &&
          header->e_ident[4] == kClass &&
          header->e_version == EV_CURRENT &&
          header->e_type == ET_CORE);
}

const ElfCoreDump::Ehdr* ElfCoreDump::GetHeader() const {
  return content_.GetData<Ehdr>(0);
}

const ElfCoreDump::Phdr* ElfCoreDump::GetProgramHeader(unsigned index) const {
  const Ehdr* header = GetHeader();
  if (header) {
    return reinterpret_cast<const Phdr*>(content_.GetArrayElement(
        header->e_phoff, header->e_phentsize, index));
  }
  return NULL;
}

const ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType(
    Word type) const {
  for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) {
    const Phdr* program = GetProgramHeader(i);
    if (program->p_type == type) {
      return program;
    }
  }
  return NULL;
}

unsigned ElfCoreDump::GetProgramHeaderCount() const {
  const Ehdr* header = GetHeader();
  return header ? header->e_phnum : 0;
}

bool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) {
  for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) {
    const Phdr* program = GetProgramHeader(i);
    if (program->p_type != PT_LOAD)
      continue;

    size_t offset_in_segment = virtual_address - program->p_vaddr;
    if (virtual_address >= program->p_vaddr &&
        offset_in_segment < program->p_filesz) {
      const void* data =
          content_.GetData(program->p_offset + offset_in_segment, length);
      if (data) {
        memcpy(buffer, data, length);
        return true;
      }
    }
  }
  return false;
}

ElfCoreDump::Note ElfCoreDump::GetFirstNote() const {
  MemoryRange note_content;
  const Phdr* program_header = GetFirstProgramHeaderOfType(PT_NOTE);
  if (program_header) {
    note_content = content_.Subrange(program_header->p_offset,
                                     program_header->p_filesz);
  }
  return Note(note_content);
}

}  // namespace google_breakpad
