Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Unified Diff: util/mac/mach_o_image_reader.cc

Issue 539263003: Add MachOImageSymbolTableReader and hook it up to MachOImageReader (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Fix 32-bit x86 Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: util/mac/mach_o_image_reader.cc
diff --git a/util/mac/mach_o_image_reader.cc b/util/mac/mach_o_image_reader.cc
index 243976ee2a39f767f010b4409385b4b11ebbb26a..7e8a1e28328cce091be6e781856af3b378f7f5b7 100644
--- a/util/mac/mach_o_image_reader.cc
+++ b/util/mac/mach_o_image_reader.cc
@@ -25,6 +25,7 @@
#include "base/strings/stringprintf.h"
#include "util/mac/checked_mach_address_range.h"
#include "util/mac/mach_o_image_segment_reader.h"
+#include "util/mac/mach_o_image_symbol_table_reader.h"
#include "util/mac/process_reader.h"
namespace {
@@ -47,10 +48,12 @@ MachOImageReader::MachOImageReader()
source_version_(0),
symtab_command_(),
dysymtab_command_(),
+ symbol_table_(),
id_dylib_command_(),
process_reader_(NULL),
file_type_(0),
- initialized_() {
+ initialized_(),
+ symbol_table_initialized_() {
}
MachOImageReader::~MachOImageReader() {
@@ -224,20 +227,18 @@ bool MachOImageReader::Initialize(ProcessReader* process_reader,
}
if (load_command.cmdsize < kLoadCommandReaders[reader_index].size) {
- LOG(WARNING)
- << base::StringPrintf(
- "load command cmdsize 0x%x insufficient for 0x%zx",
- load_command.cmdsize,
- kLoadCommandReaders[reader_index].size)
- << load_command_info;
+ LOG(WARNING) << base::StringPrintf(
+ "load command cmdsize 0x%x insufficient for 0x%zx",
+ load_command.cmdsize,
+ kLoadCommandReaders[reader_index].size)
+ << load_command_info;
return false;
}
if (kLoadCommandReaders[reader_index].singleton) {
if (singleton_indices[reader_index] != kInvalidSegmentIndex) {
LOG(WARNING) << "duplicate load command at "
- << singleton_indices[reader_index]
- << load_command_info;
+ << singleton_indices[reader_index] << load_command_info;
return false;
}
@@ -349,6 +350,7 @@ const process_types::section* MachOImageReader::GetSectionByName(
const process_types::section* MachOImageReader::GetSectionAtIndex(
size_t index,
+ const MachOImageSegmentReader** containing_segment,
mach_vm_address_t* address) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
@@ -367,6 +369,9 @@ const process_types::section* MachOImageReader::GetSectionAtIndex(
const process_types::section* section =
segment->GetSectionAtIndex(local_index);
+ if (containing_segment) {
+ *containing_segment = segment;
+ }
if (address) {
*address = section->addr + (segment->SegmentSlides() ? slide_ : 0);
}
@@ -381,6 +386,86 @@ const process_types::section* MachOImageReader::GetSectionAtIndex(
return NULL;
}
+bool MachOImageReader::LookUpExternalDefinedSymbol(
+ const std::string& name,
+ mach_vm_address_t* value) const {
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_);
+
+ if (symbol_table_initialized_.is_uninitialized()) {
+ InitializeSymbolTable();
+ }
+
+ if (!symbol_table_initialized_.is_valid() || !symbol_table_) {
+ return false;
+ }
+
+ const MachOImageSymbolTableReader::SymbolInformation* symbol_info =
+ symbol_table_->LookUpExternalDefinedSymbol(name);
+ if (!symbol_info) {
+ return false;
+ }
+
+ if (symbol_info->section == NO_SECT) {
+ // This is an absolute (N_ABS) symbol, which requires no further validation
+ // or processing.
+ *value = symbol_info->value;
+ return true;
+ }
+
+ // This is a symbol defined in a particular section, so make sure that it’s
+ // valid for that section and fix it up for any “slide” as needed.
+
+ mach_vm_address_t section_address;
+ const MachOImageSegmentReader* segment;
+ const process_types::section* section =
+ GetSectionAtIndex(symbol_info->section, &segment, &section_address);
+ if (!section) {
+ return false;
+ }
+
+ mach_vm_address_t slid_value =
+ symbol_info->value + (segment->SegmentSlides() ? slide_ : 0);
+
+ // The __mh_execute_header (_MH_EXECUTE_SYM) symbol is weird. In
+ // position-independent executables, it shows up in the symbol table as a
+ // symbol in section 1, although it’s not really in that section. It points to
+ // the mach_header[_64], which is the beginning of the __TEXT segment, and the
+ // __text section normally begins after the load commands in the __TEXT
+ // segment. The range check below will fail for this symbol, because it’s not
+ // really in the section it claims to be in. See Xcode 5.1
+ // ld64-236.3/src/ld/OutputFile.cpp ld::tool::OutputFile::buildSymbolTable().
+ // There, ld takes symbols that refer to anything in the mach_header[_64] and
+ // marks them as being in section 1. Here, section 1 is treated in this same
+ // special way as long as it’s in the __TEXT segment that begins at the start
+ // of the image, which is normally the case, and as long as the symbol’s value
+ // is the base of the image.
+ //
+ // This only happens for PIE executables, because __mh_execute_header needs
+ // to slide. In non-PIE executables, __mh_execute_header is an absolute
+ // symbol.
+ CheckedMachAddressRange section_range(
+ process_reader_, section_address, section->size);
+ if (!section_range.ContainsValue(slid_value) &&
+ !(symbol_info->section == 1 && segment->Name() == SEG_TEXT &&
+ slid_value == Address())) {
+ std::string section_name_full =
+ MachOImageSegmentReader::SegmentAndSectionNameString(section->segname,
+ section->sectname);
+ LOG(WARNING) << base::StringPrintf(
+ "symbol %s (0x%llx) outside of section %s (0x%llx + "
+ "0x%llx)",
+ name.c_str(),
+ slid_value,
+ section_name_full.c_str(),
+ section_address,
+ section->size) << module_info_;
+ return false;
+ }
+
+ *value = slid_value;
+ return true;
+}
+
uint32_t MachOImageReader::DylibVersion() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
DCHECK_EQ(FileType(), static_cast<uint32_t>(MH_DYLIB));
@@ -577,4 +662,43 @@ bool MachOImageReader::ReadUnexpectedCommand(
return false;
}
+void MachOImageReader::InitializeSymbolTable() const {
+ DCHECK(symbol_table_initialized_.is_uninitialized());
+ symbol_table_initialized_.set_invalid();
+
+ if (!symtab_command_) {
+ // It’s technically valid for there to be no LC_SYMTAB, and in that case,
+ // any symbol lookups should fail. Mark the symbol table as valid, and
+ // LookUpExternalDefinedSymbol() will understand what it means when this is
+ // valid but symbol_table_ is not present.
+ symbol_table_initialized_.set_valid();
+ return;
+ }
+
+ // Find the __LINKEDIT segment. Technically, the symbol table can be in any
+ // mapped segment, but by convention, it’s in the one named __LINKEDIT.
+ mach_vm_address_t linkedit_address;
+ mach_vm_size_t linkedit_size;
+ const MachOImageSegmentReader* linkedit_segment =
+ GetSegmentByName(SEG_LINKEDIT, &linkedit_address, &linkedit_size);
+ if (!linkedit_segment) {
+ LOG(WARNING) << "no " SEG_LINKEDIT " segment";
+ return;
+ }
+
+ symbol_table_.reset(new MachOImageSymbolTableReader());
+ if (!symbol_table_->Initialize(process_reader_,
+ symtab_command_.get(),
+ dysymtab_command_.get(),
+ linkedit_segment,
+ linkedit_address,
+ linkedit_size,
+ module_info_)) {
+ symbol_table_.reset();
+ return;
+ }
+
+ symbol_table_initialized_.set_valid();
+}
+
} // namespace crashpad

Powered by Google App Engine
This is Rietveld 408576698