186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// Copyright (c) 2011, Google Inc. 286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// All rights reserved. 386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// 486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// Redistribution and use in source and binary forms, with or without 586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// modification, are permitted provided that the following conditions are 686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// met: 786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// 886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// * Redistributions of source code must retain the above copyright 986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// notice, this list of conditions and the following disclaimer. 1086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// * Redistributions in binary form must reproduce the above 1186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// copyright notice, this list of conditions and the following disclaimer 1286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// in the documentation and/or other materials provided with the 1386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// distribution. 1486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// * Neither the name of Google Inc. nor the names of its 1586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// contributors may be used to endorse or promote products derived from 1686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// this software without specific prior written permission. 1786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// 1886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 3086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// elf_core_dump.cc: Implement google_breakpad::ElfCoreDump. 3186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// See elf_core_dump.h for details. 3286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 3386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org#include "common/linux/elf_core_dump.h" 3486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 3586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org#include <stddef.h> 3686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org#include <string.h> 3786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 3886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgnamespace google_breakpad { 3986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 4086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// Implementation of ElfCoreDump::Note. 4186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 4286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgElfCoreDump::Note::Note() {} 4386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 4486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgElfCoreDump::Note::Note(const MemoryRange& content) : content_(content) {} 4586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 4686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgbool ElfCoreDump::Note::IsValid() const { 4786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return GetHeader() != NULL; 4886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 4986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 5086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgconst ElfCoreDump::Nhdr* ElfCoreDump::Note::GetHeader() const { 5186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return content_.GetData<Nhdr>(0); 5286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 5386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 5486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgElfCoreDump::Word ElfCoreDump::Note::GetType() const { 5586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Nhdr* header = GetHeader(); 5686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org // 0 is not being used as a NOTE type. 5786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return header ? header->n_type : 0; 5886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 5986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 6086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgMemoryRange ElfCoreDump::Note::GetName() const { 6186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Nhdr* header = GetHeader(); 6286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (header) { 6386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return content_.Subrange(sizeof(Nhdr), header->n_namesz); 6486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 6586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return MemoryRange(); 6686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 6786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 6886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgMemoryRange ElfCoreDump::Note::GetDescription() const { 6986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Nhdr* header = GetHeader(); 7086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (header) { 7186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return content_.Subrange(AlignedSize(sizeof(Nhdr) + header->n_namesz), 7286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->n_descsz); 7386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 7486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return MemoryRange(); 7586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 7686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 7786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgElfCoreDump::Note ElfCoreDump::Note::GetNextNote() const { 7886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org MemoryRange next_content; 7986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Nhdr* header = GetHeader(); 8086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (header) { 8186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org size_t next_offset = AlignedSize(sizeof(Nhdr) + header->n_namesz); 8286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org next_offset = AlignedSize(next_offset + header->n_descsz); 8386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org next_content = 8486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org content_.Subrange(next_offset, content_.length() - next_offset); 8586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 8686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return Note(next_content); 8786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 8886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 8986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// static 9086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgsize_t ElfCoreDump::Note::AlignedSize(size_t size) { 9186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org size_t mask = sizeof(Word) - 1; 9286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return (size + mask) & ~mask; 9386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 9486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 9586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 9686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org// Implementation of ElfCoreDump. 9786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 9886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgElfCoreDump::ElfCoreDump() {} 9986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 10086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgElfCoreDump::ElfCoreDump(const MemoryRange& content) 10186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org : content_(content) { 10286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 10386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 10486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgvoid ElfCoreDump::SetContent(const MemoryRange& content) { 10586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org content_ = content; 10686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 10786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 10886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgbool ElfCoreDump::IsValid() const { 10986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Ehdr* header = GetHeader(); 11086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return (header && 11186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_ident[0] == ELFMAG0 && 11286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_ident[1] == ELFMAG1 && 11386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_ident[2] == ELFMAG2 && 11486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_ident[3] == ELFMAG3 && 11586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_ident[4] == kClass && 11686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_version == EV_CURRENT && 11786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_type == ET_CORE); 11886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 11986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 12086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgconst ElfCoreDump::Ehdr* ElfCoreDump::GetHeader() const { 12186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return content_.GetData<Ehdr>(0); 12286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 12386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 12486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgconst ElfCoreDump::Phdr* ElfCoreDump::GetProgramHeader(unsigned index) const { 12586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Ehdr* header = GetHeader(); 12686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (header) { 12786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return reinterpret_cast<const Phdr*>(content_.GetArrayElement( 12886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org header->e_phoff, header->e_phentsize, index)); 12986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 13086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return NULL; 13186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 13286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 13386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgconst ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType( 13486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org Word type) const { 13586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) { 13686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Phdr* program = GetProgramHeader(i); 13786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (program->p_type == type) { 13886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return program; 13986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 14086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 14186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return NULL; 14286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 14386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 14486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgunsigned ElfCoreDump::GetProgramHeaderCount() const { 14586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Ehdr* header = GetHeader(); 14686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return header ? header->e_phnum : 0; 14786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 14886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 14986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgbool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) { 15086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) { 15186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Phdr* program = GetProgramHeader(i); 15286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (program->p_type != PT_LOAD) 15386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org continue; 15486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 15586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org size_t offset_in_segment = virtual_address - program->p_vaddr; 15686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (virtual_address >= program->p_vaddr && 15786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org offset_in_segment < program->p_filesz) { 15886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const void* data = 15986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org content_.GetData(program->p_offset + offset_in_segment, length); 16086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (data) { 16186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org memcpy(buffer, data, length); 16286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return true; 16386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 16486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 16586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 16686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return false; 16786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 16886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 16986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.orgElfCoreDump::Note ElfCoreDump::GetFirstNote() const { 17086cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org MemoryRange note_content; 17186cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org const Phdr* program_header = GetFirstProgramHeaderOfType(PT_NOTE); 17286cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org if (program_header) { 17386cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org note_content = content_.Subrange(program_header->p_offset, 17486cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org program_header->p_filesz); 17586cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org } 17686cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org return Note(note_content); 17786cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} 17886cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org 17986cbb1e5cc967853dfc2b10f8fc8da43fc734c77benchan@chromium.org} // namespace google_breakpad 180