| Index: util/mac/mach_o_image_segment_reader.cc
 | 
| diff --git a/util/mac/mach_o_image_segment_reader.cc b/util/mac/mach_o_image_segment_reader.cc
 | 
| deleted file mode 100644
 | 
| index 58f850639676c3ece904e827d20024d856430052..0000000000000000000000000000000000000000
 | 
| --- a/util/mac/mach_o_image_segment_reader.cc
 | 
| +++ /dev/null
 | 
| @@ -1,275 +0,0 @@
 | 
| -// 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 "util/mac/mach_o_image_segment_reader.h"
 | 
| -
 | 
| -#include <mach-o/loader.h>
 | 
| -
 | 
| -#include "base/logging.h"
 | 
| -#include "base/strings/stringprintf.h"
 | 
| -#include "util/mac/checked_mach_address_range.h"
 | 
| -#include "util/mac/process_reader.h"
 | 
| -#include "util/stdlib/strnlen.h"
 | 
| -
 | 
| -namespace crashpad {
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -std::string SizeLimitedCString(const char* c_string, size_t max_length) {
 | 
| -  return std::string(c_string, strnlen(c_string, max_length));
 | 
| -}
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -MachOImageSegmentReader::MachOImageSegmentReader()
 | 
| -    : segment_command_(),
 | 
| -      sections_(),
 | 
| -      section_map_(),
 | 
| -      slide_(0),
 | 
| -      initialized_(),
 | 
| -      initialized_slide_() {
 | 
| -}
 | 
| -
 | 
| -MachOImageSegmentReader::~MachOImageSegmentReader() {
 | 
| -}
 | 
| -
 | 
| -bool MachOImageSegmentReader::Initialize(ProcessReader* process_reader,
 | 
| -                                         mach_vm_address_t load_command_address,
 | 
| -                                         const std::string& load_command_info) {
 | 
| -  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
 | 
| -
 | 
| -  if (!segment_command_.Read(process_reader, load_command_address)) {
 | 
| -    LOG(WARNING) << "could not read segment_command" << load_command_info;
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  const uint32_t kExpectedSegmentCommand =
 | 
| -      process_reader->Is64Bit() ? LC_SEGMENT_64 : LC_SEGMENT;
 | 
| -  DCHECK_EQ(segment_command_.cmd, kExpectedSegmentCommand);
 | 
| -  DCHECK_GE(segment_command_.cmdsize, segment_command_.Size());
 | 
| -  const size_t kSectionStructSize =
 | 
| -      process_types::section::ExpectedSize(process_reader);
 | 
| -  const size_t kRequiredSize =
 | 
| -      segment_command_.Size() + segment_command_.nsects * kSectionStructSize;
 | 
| -  if (segment_command_.cmdsize < kRequiredSize) {
 | 
| -    LOG(WARNING) << base::StringPrintf(
 | 
| -                        "segment command cmdsize 0x%x insufficient for %u "
 | 
| -                        "section%s (0x%zx)",
 | 
| -                        segment_command_.cmdsize,
 | 
| -                        segment_command_.nsects,
 | 
| -                        segment_command_.nsects == 1 ? "" : "s",
 | 
| -                        kRequiredSize) << load_command_info;
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  std::string segment_name = NameInternal();
 | 
| -  std::string segment_info = base::StringPrintf(
 | 
| -      ", segment %s%s", segment_name.c_str(), load_command_info.c_str());
 | 
| -
 | 
| -  // This checks the unslid segment range. The slid range (as loaded into
 | 
| -  // memory) will be checked later by MachOImageReader.
 | 
| -  CheckedMachAddressRange segment_range(
 | 
| -      process_reader, segment_command_.vmaddr, segment_command_.vmsize);
 | 
| -  if (!segment_range.IsValid()) {
 | 
| -    LOG(WARNING) << base::StringPrintf("invalid segment range 0x%llx + 0x%llx",
 | 
| -                                       segment_command_.vmaddr,
 | 
| -                                       segment_command_.vmsize) << segment_info;
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  sections_.resize(segment_command_.nsects);
 | 
| -  if (!process_types::section::ReadArrayInto(
 | 
| -          process_reader,
 | 
| -          load_command_address + segment_command_.Size(),
 | 
| -          segment_command_.nsects,
 | 
| -          §ions_[0])) {
 | 
| -    LOG(WARNING) << "could not read sections" << segment_info;
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  for (size_t section_index = 0;
 | 
| -       section_index < sections_.size();
 | 
| -       ++section_index) {
 | 
| -    const process_types::section& section = sections_[section_index];
 | 
| -    std::string section_segment_name = SegmentNameString(section.segname);
 | 
| -    std::string section_name = SectionNameString(section.sectname);
 | 
| -    std::string section_full_name =
 | 
| -        SegmentAndSectionNameString(section.segname, section.sectname);
 | 
| -
 | 
| -    std::string section_info = base::StringPrintf(", section %s %zu/%zu%s",
 | 
| -                                                  section_full_name.c_str(),
 | 
| -                                                  section_index,
 | 
| -                                                  sections_.size(),
 | 
| -                                                  load_command_info.c_str());
 | 
| -
 | 
| -    if (section_segment_name != segment_name) {
 | 
| -      LOG(WARNING) << "section.segname incorrect in segment " << segment_name
 | 
| -                   << section_info;
 | 
| -      return false;
 | 
| -    }
 | 
| -
 | 
| -    CheckedMachAddressRange section_range(
 | 
| -        process_reader, section.addr, section.size);
 | 
| -    if (!section_range.IsValid()) {
 | 
| -      LOG(WARNING) << base::StringPrintf(
 | 
| -                          "invalid section range 0x%llx + 0x%llx",
 | 
| -                          section.addr,
 | 
| -                          section.size) << section_info;
 | 
| -      return false;
 | 
| -    }
 | 
| -
 | 
| -    if (!segment_range.ContainsRange(section_range)) {
 | 
| -      LOG(WARNING) << base::StringPrintf(
 | 
| -                          "section at 0x%llx + 0x%llx outside of segment at "
 | 
| -                          "0x%llx + 0x%llx",
 | 
| -                          section.addr,
 | 
| -                          section.size,
 | 
| -                          segment_command_.vmaddr,
 | 
| -                          segment_command_.vmsize) << section_info;
 | 
| -      return false;
 | 
| -    }
 | 
| -
 | 
| -    uint32_t section_type = (section.flags & SECTION_TYPE);
 | 
| -    bool zero_fill = section_type == S_ZEROFILL ||
 | 
| -                     section_type == S_GB_ZEROFILL ||
 | 
| -                     section_type == S_THREAD_LOCAL_ZEROFILL;
 | 
| -
 | 
| -    // Zero-fill section types aren’t mapped from the file, so their |offset|
 | 
| -    // fields are irrelevant and are typically 0.
 | 
| -    if (!zero_fill &&
 | 
| -        section.offset - segment_command_.fileoff !=
 | 
| -            section.addr - segment_command_.vmaddr) {
 | 
| -      LOG(WARNING) << base::StringPrintf(
 | 
| -                          "section type 0x%x at 0x%llx has unexpected offset "
 | 
| -                          "0x%x in segment at 0x%llx with offset 0x%llx",
 | 
| -                          section_type,
 | 
| -                          section.addr,
 | 
| -                          section.offset,
 | 
| -                          segment_command_.vmaddr,
 | 
| -                          segment_command_.fileoff) << section_info;
 | 
| -      return false;
 | 
| -    }
 | 
| -
 | 
| -    const auto& iterator = section_map_.find(section_name);
 | 
| -    if (iterator != section_map_.end()) {
 | 
| -      LOG(WARNING) << base::StringPrintf("duplicate section name at %zu",
 | 
| -                                         iterator->second) << section_info;
 | 
| -      return false;
 | 
| -    }
 | 
| -
 | 
| -    section_map_[section_name] = section_index;
 | 
| -  }
 | 
| -
 | 
| -  INITIALIZATION_STATE_SET_VALID(initialized_);
 | 
| -  return true;
 | 
| -}
 | 
| -
 | 
| -std::string MachOImageSegmentReader::Name() const {
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 | 
| -  return NameInternal();
 | 
| -}
 | 
| -
 | 
| -mach_vm_address_t MachOImageSegmentReader::Address() const {
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_slide_);
 | 
| -  return vmaddr() + (SegmentSlides() ? slide_ : 0);
 | 
| -}
 | 
| -
 | 
| -mach_vm_size_t MachOImageSegmentReader::Size() const {
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_slide_);
 | 
| -  return vmsize() + (SegmentSlides() ? 0 : slide_);
 | 
| -}
 | 
| -
 | 
| -const process_types::section* MachOImageSegmentReader::GetSectionByName(
 | 
| -    const std::string& section_name,
 | 
| -    mach_vm_address_t* address) const {
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 | 
| -
 | 
| -  const auto& iterator = section_map_.find(section_name);
 | 
| -  if (iterator == section_map_.end()) {
 | 
| -    return nullptr;
 | 
| -  }
 | 
| -
 | 
| -  return GetSectionAtIndex(iterator->second, address);
 | 
| -}
 | 
| -
 | 
| -const process_types::section* MachOImageSegmentReader::GetSectionAtIndex(
 | 
| -    size_t index,
 | 
| -    mach_vm_address_t* address) const {
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 | 
| -  CHECK_LT(index, sections_.size());
 | 
| -
 | 
| -  const process_types::section* section = §ions_[index];
 | 
| -
 | 
| -  if (address) {
 | 
| -    INITIALIZATION_STATE_DCHECK_VALID(initialized_slide_);
 | 
| -    *address = section->addr + (SegmentSlides() ? slide_ : 0);
 | 
| -  }
 | 
| -
 | 
| -  return section;
 | 
| -}
 | 
| -
 | 
| -bool MachOImageSegmentReader::SegmentSlides() const {
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 | 
| -
 | 
| -  // These are the same rules that the kernel uses to identify __PAGEZERO. See
 | 
| -  // 10.9.4 xnu-2422.110.17/bsd/kern/mach_loader.c load_segment().
 | 
| -  return !(segment_command_.vmaddr == 0 && segment_command_.filesize == 0 &&
 | 
| -           segment_command_.vmsize != 0 &&
 | 
| -           (segment_command_.initprot & VM_PROT_ALL) == VM_PROT_NONE &&
 | 
| -           (segment_command_.maxprot & VM_PROT_ALL) == VM_PROT_NONE);
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -std::string MachOImageSegmentReader::SegmentNameString(
 | 
| -    const char* segment_name_c) {
 | 
| -  // This is used to interpret the segname field of both the segment_command and
 | 
| -  // section structures, so be sure that they’re identical.
 | 
| -  static_assert(sizeof(process_types::segment_command::segname) ==
 | 
| -                    sizeof(process_types::section::segname),
 | 
| -                "sizes must be equal");
 | 
| -
 | 
| -  return SizeLimitedCString(segment_name_c,
 | 
| -                            sizeof(process_types::segment_command::segname));
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -std::string MachOImageSegmentReader::SectionNameString(
 | 
| -    const char* section_name_c) {
 | 
| -  return SizeLimitedCString(section_name_c,
 | 
| -                            sizeof(process_types::section::sectname));
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -std::string MachOImageSegmentReader::SegmentAndSectionNameString(
 | 
| -    const char* segment_name_c,
 | 
| -    const char* section_name_c) {
 | 
| -  return base::StringPrintf("%s,%s",
 | 
| -                            SegmentNameString(segment_name_c).c_str(),
 | 
| -                            SectionNameString(section_name_c).c_str());
 | 
| -}
 | 
| -
 | 
| -std::string MachOImageSegmentReader::NameInternal() const {
 | 
| -  return SegmentNameString(segment_command_.segname);
 | 
| -}
 | 
| -
 | 
| -void MachOImageSegmentReader::SetSlide(mach_vm_size_t slide) {
 | 
| -  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
 | 
| -  INITIALIZATION_STATE_SET_INITIALIZING(initialized_slide_);
 | 
| -  slide_ = slide;
 | 
| -  INITIALIZATION_STATE_SET_VALID(initialized_slide_);
 | 
| -}
 | 
| -
 | 
| -}  // namespace crashpad
 | 
| 
 |