Add address ranges for individual macho sections on darwin
Summary: This is a re-upload of the reverted commit r308644. It has changed quite a bit to reflect post-commit comments by kcc, so I'm re-uploading as a new review. Reviewers: kubamracek, alekseyshl, kcc Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D35799 llvm-svn: 308977
This commit is contained in:
		
							parent
							
								
									85cc5687df
								
							
						
					
					
						commit
						ec4ac0f0c6
					
				| 
						 | 
				
			
			@ -37,9 +37,12 @@ static const uptr kProtectionWrite = 2;
 | 
			
		|||
static const uptr kProtectionExecute = 4;
 | 
			
		||||
static const uptr kProtectionShared = 8;
 | 
			
		||||
 | 
			
		||||
struct MemoryMappedSegment {
 | 
			
		||||
struct MemoryMappedSegmentData;
 | 
			
		||||
 | 
			
		||||
class MemoryMappedSegment {
 | 
			
		||||
 public:
 | 
			
		||||
  MemoryMappedSegment(char *buff = nullptr, uptr size = 0)
 | 
			
		||||
      : filename(buff), filename_size(size) {}
 | 
			
		||||
      : filename(buff), filename_size(size), data_(nullptr) {}
 | 
			
		||||
  ~MemoryMappedSegment() {}
 | 
			
		||||
 | 
			
		||||
  bool IsReadable() const { return protection & kProtectionRead; }
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +50,8 @@ struct MemoryMappedSegment {
 | 
			
		|||
  bool IsExecutable() const { return protection & kProtectionExecute; }
 | 
			
		||||
  bool IsShared() const { return protection & kProtectionShared; }
 | 
			
		||||
 | 
			
		||||
  void AddAddressRanges(LoadedModule *module);
 | 
			
		||||
 | 
			
		||||
  uptr start;
 | 
			
		||||
  uptr end;
 | 
			
		||||
  uptr offset;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,6 +60,12 @@ struct MemoryMappedSegment {
 | 
			
		|||
  uptr protection;
 | 
			
		||||
  ModuleArch arch;
 | 
			
		||||
  u8 uuid[kModuleUUIDSize];
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  friend class MemoryMappingLayout;
 | 
			
		||||
 | 
			
		||||
  // This field is assigned and owned by MemoryMappingLayout if needed
 | 
			
		||||
  MemoryMappedSegmentData *data_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class MemoryMappingLayout {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,6 +64,10 @@ uptr ParseHex(const char **p) {
 | 
			
		|||
  return ParseNumber(p, 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
 | 
			
		||||
  module->addAddressRange(start, end, IsExecutable(), IsWritable());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
 | 
			
		||||
  ReadProcMaps(&proc_self_maps_);
 | 
			
		||||
  if (cache_enabled) {
 | 
			
		||||
| 
						 | 
				
			
			@ -139,8 +143,7 @@ void MemoryMappingLayout::DumpListOfModules(
 | 
			
		|||
    uptr base_address = (i ? segment.start : 0) - segment.offset;
 | 
			
		||||
    LoadedModule cur_module;
 | 
			
		||||
    cur_module.set(cur_name, base_address);
 | 
			
		||||
    cur_module.addAddressRange(segment.start, segment.end,
 | 
			
		||||
                               segment.IsExecutable(), segment.IsWritable());
 | 
			
		||||
    segment.AddAddressRanges(&cur_module);
 | 
			
		||||
    modules->push_back(cur_module);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,48 @@
 | 
			
		|||
 | 
			
		||||
namespace __sanitizer {
 | 
			
		||||
 | 
			
		||||
// Contains information used to iterate through sections.
 | 
			
		||||
struct MemoryMappedSegmentData {
 | 
			
		||||
  uptr nsects;
 | 
			
		||||
  char *current_load_cmd_addr;
 | 
			
		||||
  u32 lc_type;
 | 
			
		||||
  uptr base_virt_addr;
 | 
			
		||||
  uptr addr_mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Section>
 | 
			
		||||
static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data,
 | 
			
		||||
                            bool isWritable) {
 | 
			
		||||
  const Section *sc = (const Section *)data->current_load_cmd_addr;
 | 
			
		||||
  data->current_load_cmd_addr += sizeof(Section);
 | 
			
		||||
 | 
			
		||||
  uptr sec_start = (sc->addr & data->addr_mask) + data->base_virt_addr;
 | 
			
		||||
  uptr sec_end = sec_start + sc->size;
 | 
			
		||||
  module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
 | 
			
		||||
  // Don't iterate over sections when the caller hasn't set up the
 | 
			
		||||
  // data pointer, when there are no sections, or when the segment
 | 
			
		||||
  // is executable. Avoid iterating over executable sections because
 | 
			
		||||
  // it will confuse libignore, and because the extra granularity
 | 
			
		||||
  // of information is not needed by any sanitizers.
 | 
			
		||||
  if (!data_ || !data_->nsects || IsExecutable()) {
 | 
			
		||||
    module->addAddressRange(start, end, IsExecutable(), IsWritable());
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  do {
 | 
			
		||||
    if (data_->lc_type == LC_SEGMENT) {
 | 
			
		||||
      NextSectionLoad<struct section>(module, data_, IsWritable());
 | 
			
		||||
#ifdef MH_MAGIC_64
 | 
			
		||||
    } else if (data_->lc_type == LC_SEGMENT_64) {
 | 
			
		||||
      NextSectionLoad<struct section_64>(module, data_, IsWritable());
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
  } while (--data_->nsects);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
 | 
			
		||||
  Reset();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -144,19 +186,32 @@ bool MemoryMappingLayout::NextSegmentLoad(MemoryMappedSegment *segment) {
 | 
			
		|||
  if (((const load_command *)lc)->cmd == kLCSegment) {
 | 
			
		||||
    const SegmentCommand* sc = (const SegmentCommand *)lc;
 | 
			
		||||
 | 
			
		||||
    uptr base_virt_addr, addr_mask;
 | 
			
		||||
    if (current_image_ == kDyldImageIdx) {
 | 
			
		||||
      base_virt_addr = (uptr)get_dyld_hdr();
 | 
			
		||||
      // vmaddr is masked with 0xfffff because on macOS versions < 10.12,
 | 
			
		||||
      // it contains an absolute address rather than an offset for dyld.
 | 
			
		||||
      // To make matters even more complicated, this absolute address
 | 
			
		||||
      // isn't actually the absolute segment address, but the offset portion
 | 
			
		||||
      // of the address is accurate when combined with the dyld base address,
 | 
			
		||||
      // and the mask will give just this offset.
 | 
			
		||||
      segment->start = (sc->vmaddr & 0xfffff) + (uptr)get_dyld_hdr();
 | 
			
		||||
      segment->end = (sc->vmaddr & 0xfffff) + sc->vmsize + (uptr)get_dyld_hdr();
 | 
			
		||||
      addr_mask = 0xfffff;
 | 
			
		||||
    } else {
 | 
			
		||||
      const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
 | 
			
		||||
      segment->start = sc->vmaddr + dlloff;
 | 
			
		||||
      segment->end = sc->vmaddr + sc->vmsize + dlloff;
 | 
			
		||||
      base_virt_addr = (uptr)_dyld_get_image_vmaddr_slide(current_image_);
 | 
			
		||||
      addr_mask = ~0;
 | 
			
		||||
    }
 | 
			
		||||
    segment->start = (sc->vmaddr & addr_mask) + base_virt_addr;
 | 
			
		||||
    segment->end = segment->start + sc->vmsize;
 | 
			
		||||
 | 
			
		||||
    // Most callers don't need section information, so only fill this struct
 | 
			
		||||
    // when required.
 | 
			
		||||
    if (segment->data_) {
 | 
			
		||||
      segment->data_->nsects = sc->nsects;
 | 
			
		||||
      segment->data_->current_load_cmd_addr =
 | 
			
		||||
          (char *)lc + sizeof(SegmentCommand);
 | 
			
		||||
      segment->data_->lc_type = kLCSegment;
 | 
			
		||||
      segment->data_->base_virt_addr = base_virt_addr;
 | 
			
		||||
      segment->data_->addr_mask = addr_mask;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Return the initial protection.
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +347,9 @@ void MemoryMappingLayout::DumpListOfModules(
 | 
			
		|||
  Reset();
 | 
			
		||||
  InternalScopedString module_name(kMaxPathLength);
 | 
			
		||||
  MemoryMappedSegment segment(module_name.data(), kMaxPathLength);
 | 
			
		||||
  for (uptr i = 0; Next(&segment); i++) {
 | 
			
		||||
  MemoryMappedSegmentData data;
 | 
			
		||||
  segment.data_ = &data;
 | 
			
		||||
  while (Next(&segment)) {
 | 
			
		||||
    if (segment.filename[0] == '\0') continue;
 | 
			
		||||
    LoadedModule *cur_module = nullptr;
 | 
			
		||||
    if (!modules->empty() &&
 | 
			
		||||
| 
						 | 
				
			
			@ -304,8 +361,7 @@ void MemoryMappingLayout::DumpListOfModules(
 | 
			
		|||
      cur_module->set(segment.filename, segment.start, segment.arch,
 | 
			
		||||
                      segment.uuid, current_instrumented_);
 | 
			
		||||
    }
 | 
			
		||||
    cur_module->addAddressRange(segment.start, segment.end,
 | 
			
		||||
                                segment.IsExecutable(), segment.IsWritable());
 | 
			
		||||
    segment.AddAddressRanges(cur_module);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue