Esempio n. 1
0
void MachOLoader::loadDylibs(const MachO& mach, bool nobind, bool bindLazy)
{
	for (std::string dylib : mach.dylibs())
	{
		// __darwin_dlopen checks if already loaded
		// automatically adds a reference if so
		
		int flags = DARWIN_RTLD_GLOBAL;
		if (nobind)
			flags |= __DARLING_RTLD_NOBIND; 
		if (bindLazy)
			flags |= DARWIN_RTLD_LAZY;
		else
			flags |= DARWIN_RTLD_NOW;

		if (!Darling::DlopenWithContext(dylib.c_str(), flags, m_rpathContext))
		{
			LOG << "Failed to dlopen " << dylib << ", throwing an exception\n";
			std::stringstream ss;
			ss << "Cannot load " << dylib << ": " << __darwin_dlerror();
			throw std::runtime_error(ss.str());
		}
	}
}
Esempio n. 2
0
void printBinInfo(const char* path, const char* arch, const char* opt)
{
	MachO* macho = MachO::readFile(path, arch, true);
	if (!macho)
		throw std::runtime_error("Load failed");
	
	OpMode opmode = getOpMode(opt);

	std::cout << "Platform: " << macho->platform() << std::endl;
	
	switch (opmode)
	{
		case ModeDylibs:
		{
			std::cout << "Dylibs:\n";
			for (const char* name : macho->dylibs())
			{
				std::cout << "\t" << name << std::endl;
			}
			break;
		}
		case ModeSymbols:
		{
			std::cout << "Symbols:\n";
			for (const MachO::Symbol& s : macho->symbols())
			{
				if (!s.addr)
					continue;
				
				std::cout << '\t' << s.name << " at " << "[0x" << std::hex << std::setfill('0');
				
				if (macho->is64())
					std::cout << std::setw(16);
				else
					std::cout << std::setw(8);
				
				std::cout << s.addr << std::setw(0) << std::dec << ']' << std::endl;
			}
			break;
		}
		case ModeExports:
		{
			std::cout << "Exports:\n";
			for (const MachO::Export* e : macho->exports())
			{
				std::cout << '\t' << e->name << " at " << "[0x" << std::hex << std::setfill('0');
				
				if (macho->is64())
					std::cout << std::setw(16);
				else
					std::cout << std::setw(8);
				
				std::cout << e->addr << std::setw(0) << "] (flag: " << e->flag << ")" << std::dec << std::endl;
			}
			break;
		}
		case ModeBinds:
		{
			std::cout << "Binds:\n";
			for (const MachO::Bind* b : macho->binds())
			{
				std::cout << '\t' << b->name << " at " << "[0x" << std::hex << std::setfill('0');
				
				if (macho->is64())
					std::cout << std::setw(16);
				else
					std::cout << std::setw(8);
				
				std::cout << b->vmaddr << std::setw(0) << "] ";

				if (!b->is_classic)
					std::cout << "(addend: " << b->addend;
				else
					std::cout << "(value: " << b->value;

				std::cout << ", type: " << int(b->type) << ", ordinal: " << int(b->ordinal) << ")";
				
				if (b->is_weak)
					std::cout << 'W';
				if (b->is_classic)
					std::cout << 'C';
				if (b->is_lazy)
					std::cout << 'L';
				
				std::cout << std::dec << std::endl;
			}
			break;
		}
		case ModeSegments:
		{
			std::cout << "Segments:\n" << std::hex;
			printSegments(macho->segments64());
			printSegments(macho->segments());

			break;
		}
		case ModeRebases:
		{
			std::cout << "Rebases:\n";

			for (MachO::Rebase* r : macho->rebases())
			{
				std::cout << "\t at [0x" << std::hex << std::setfill('0');

				if (macho->is64())
					std::cout << std::setw(16);
				else
					std::cout << std::setw(8);

				std::cout << r->vmaddr << std::dec << std::setw(0) << "]\n";
			}
			break;
		}
		case ModeRelocations:
		{
			std::cout << "External relocations:\n";

			for (MachO::Relocation* r : macho->relocations())
			{
				std::cout << '\t' << r->name << " at " << "[0x" << std::hex << std::setfill('0');
				
				if (macho->is64())
					std::cout << std::setw(16);
				else
					std::cout << std::setw(8);
				
				std::cout << r->addr << std::setw(0) << "] ";

				if (r->pcrel)
					std::cout << "PC-REL";
				std::cout << std::endl;
			}
			break;
		}

	}
	
	delete macho;
}
Esempio n. 3
0
void MachOLoader::loadSegments(const MachO& mach, intptr* slide, intptr* base, ELFBlock* elf)
{
	*base = 0;
	--*base;
	
	if (m_pTrampolineMgr)
		m_pTrampolineMgr->invalidateMemoryMap();

	const std::vector<Segment*>& segments = getSegments(mach);
	for (Segment* seg : segments)
	{
		const char* name = seg->segname;
		if (!strcmp(name, SEG_PAGEZERO))
			continue;

		LOG << seg->segname << ": "
			<< "fileoff=" << seg->fileoff
			<< ", vmaddr=" << seg->vmaddr <<std::endl;

		int prot = 0, maxprot = 0;

		if (seg->initprot & VM_PROT_READ)
			prot |= PROT_READ;

		if (seg->initprot & VM_PROT_WRITE)
			prot |= PROT_WRITE;
		
		if (seg->initprot & VM_PROT_EXECUTE)
			prot |= PROT_EXEC;

		if (seg->maxprot & VM_PROT_READ)
			maxprot |= PROT_READ;

		if (seg->maxprot & VM_PROT_WRITE)
			maxprot |= PROT_WRITE;

		if (seg->maxprot & VM_PROT_EXECUTE)
			maxprot |= PROT_EXEC;
		

		intptr filesize = alignMem(seg->filesize, 0x1000);
		intptr vmaddr = seg->vmaddr + *slide;
		
		if (vmaddr < m_last_addr)
		{
			LOG << "will rebase: filename=" << mach.filename()
				<< ", vmaddr=" << (void*)vmaddr
				<< ", last_addr=" << (void*)m_last_addr <<std::endl;
			assert(seg == segments[0]);
			vmaddr = m_last_addr;
			*slide = vmaddr - seg->vmaddr;
		}
		*base = std::min(*base, vmaddr);

		intptr vmsize = alignMem(seg->vmsize, 0x1000);
		LOG << "mmap(file) " << mach.filename() << ' ' << name
			<< ": " << (void*)vmaddr << "-" << (void*)(vmaddr + filesize)
			<< " offset=" << mach.offset() + seg->fileoff <<std::endl;
		
		if (filesize == 0)
			continue;
		
		checkMmapMinAddr(vmaddr);
		
		void* mapped = ::mmap((void*)vmaddr, filesize, maxprot, MAP_PRIVATE | MAP_FIXED, mach.fd(), mach.offset() + seg->fileoff);

		m_mprotects.push_back(MProtect{(void*) vmaddr, filesize, prot});
		
		if (mapped == MAP_FAILED)
		{
			std::stringstream ss;
			ss << "Failed to mmap '" << mach.filename() << "': " << strerror(errno);
			throw std::runtime_error(ss.str());
		}
		
		assert(vmsize >= filesize);

		if (vmsize > filesize)
		{
			LOG << "mmap(anon) " << mach.filename() << ' ' << name
				<< ": " << (void*)(vmaddr + filesize) << "-"
				<< (void*)(vmaddr + vmsize)
				<<std::endl;
			
			void* mapped = ::mmap(reinterpret_cast<char*>(vmaddr) + filesize, vmsize - filesize, prot, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0, 0);
								
			if (mapped == MAP_FAILED)
			{
				std::stringstream ss;
				ss << "mmap(anon) failed on '" << mach.filename() << "': " << strerror(errno);
				throw std::runtime_error(ss.str());
			}
		}

		m_last_addr = std::max(m_last_addr, (intptr)vmaddr + vmsize);

		if (elf)
			elf->addSection(name, (void*)vmaddr, vmsize, 0);
	}
}