예제 #1
0
status_t
ElfFile::_LoadFile(const char* fileName)
{
	typedef typename ElfClass::Ehdr Ehdr;
	typedef typename ElfClass::Phdr Phdr;
	typedef typename ElfClass::Shdr Shdr;

	// read the elf header
	Ehdr elfHeader;
	ssize_t bytesRead = pread(fFD, &elfHeader, sizeof(elfHeader), 0);
	if (bytesRead != (ssize_t)sizeof(elfHeader))
		return bytesRead < 0 ? errno : B_ERROR;

	// check the ELF header
	if (!_CheckRange(0, sizeof(elfHeader))
		|| !_CheckElfHeader<ElfClass>(elfHeader)) {
		WARNING("\"%s\": Not a valid ELF file\n", fileName);
		return B_BAD_DATA;
	}

	fType = Get(elfHeader.e_type);
	fMachine = Get(elfHeader.e_machine);

	if (Get(elfHeader.e_shnum) > 0) {
		// check section header table values
		uint64 sectionHeadersOffset = Get(elfHeader.e_shoff);
		size_t sectionHeaderSize = Get(elfHeader.e_shentsize);
		int sectionCount = Get(elfHeader.e_shnum);
		size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
		if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
			WARNING("\"%s\": Invalid ELF header\n", fileName);
			return B_BAD_DATA;
		}

		// read the section header table
		uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
		if (sectionHeaderTable == NULL)
			return B_NO_MEMORY;
		MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);

		bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
			sectionHeadersOffset);
		if (bytesRead != (ssize_t)sectionHeaderTableSize)
			return bytesRead < 0 ? errno : B_ERROR;

		// check and get the section header string section
		Shdr* stringSectionHeader = (Shdr*)(sectionHeaderTable
			+ Get(elfHeader.e_shstrndx) * sectionHeaderSize);
		if (!_CheckRange(Get(stringSectionHeader->sh_offset),
				Get(stringSectionHeader->sh_size))) {
			WARNING("\"%s\": Invalid string section header\n", fileName);
			return B_BAD_DATA;
		}
		size_t sectionStringSize = Get(stringSectionHeader->sh_size);

		ElfSection* sectionStringSection = new(std::nothrow) ElfSection(
			".shstrtab", Get(stringSectionHeader->sh_type),fFD,
			Get(stringSectionHeader->sh_offset), sectionStringSize,
			Get(stringSectionHeader->sh_addr),
			Get(stringSectionHeader->sh_flags),
			Get(stringSectionHeader->sh_link));
		if (sectionStringSection == NULL)
			return B_NO_MEMORY;
		if (!fSections.AddItem(sectionStringSection)) {
			delete sectionStringSection;
			return B_NO_MEMORY;
		}

		status_t error = sectionStringSection->Load();
		if (error != B_OK)
			return error;

		const char* sectionStrings = (const char*)sectionStringSection->Data();

		// read the other sections
		for (int i = 0; i < sectionCount; i++) {
			Shdr* sectionHeader = (Shdr*)(sectionHeaderTable + i
				* sectionHeaderSize);
			// skip invalid sections and the section header string section
			const char* name = sectionStrings + Get(sectionHeader->sh_name);
			if (Get(sectionHeader->sh_name) >= sectionStringSize
				|| !_CheckRange(Get(sectionHeader->sh_offset),
					Get(sectionHeader->sh_size))
				|| i == Get(elfHeader.e_shstrndx)) {
				continue;
			}

			// create an ElfSection
			ElfSection* section = new(std::nothrow) ElfSection(name,
				Get(sectionHeader->sh_type), fFD, Get(sectionHeader->sh_offset),
				Get(sectionHeader->sh_size), Get(sectionHeader->sh_addr),
				Get(sectionHeader->sh_flags), Get(sectionHeader->sh_link));
			if (section == NULL)
				return B_NO_MEMORY;
			if (!fSections.AddItem(section)) {
				delete section;
				return B_NO_MEMORY;
			}
		}
	}

	if (Get(elfHeader.e_phnum) > 0) {
		// check program header table values
		uint64 programHeadersOffset = Get(elfHeader.e_phoff);
		size_t programHeaderSize = Get(elfHeader.e_phentsize);
		int segmentCount = Get(elfHeader.e_phnum);
		size_t programHeaderTableSize = programHeaderSize * segmentCount;
		if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
			WARNING("\"%s\": Invalid ELF header\n", fileName);
			return B_BAD_DATA;
		}

		// read the program header table
		uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
		if (programHeaderTable == NULL)
			return B_NO_MEMORY;
		MemoryDeleter programHeaderTableDeleter(programHeaderTable);

		bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
			programHeadersOffset);
		if (bytesRead != (ssize_t)programHeaderTableSize)
			return bytesRead < 0 ? errno : B_ERROR;

		// read the program headers and create ElfSegment objects
		for (int i = 0; i < segmentCount; i++) {
			Phdr* programHeader = (Phdr*)(programHeaderTable + i
				* programHeaderSize);
			// skip invalid program headers
			if (Get(programHeader->p_filesz) > 0
				&& !_CheckRange(Get(programHeader->p_offset),
					Get(programHeader->p_filesz))) {
				continue;
			}

			// create an ElfSegment
			ElfSegment* segment = new(std::nothrow) ElfSegment(
				Get(programHeader->p_type), Get(programHeader->p_offset),
				Get(programHeader->p_filesz), Get(programHeader->p_vaddr),
				Get(programHeader->p_memsz), Get(programHeader->p_flags));
			if (segment == NULL)
				return B_NO_MEMORY;
			if (!fSegments.AddItem(segment)) {
				delete segment;
				return B_NO_MEMORY;
			}
		}
	}

	return B_OK;
}
예제 #2
0
status_t
ElfFile::Init(const char* fileName)
{
	// open file
	fFD = open(fileName, O_RDONLY);
	if (fFD < 0) {
		WARNING("Failed to open \"%s\": %s\n", fileName, strerror(errno));
		return errno;
	}

	// stat() file to get its size
	struct stat st;
	if (fstat(fFD, &st) < 0) {
		WARNING("Failed to stat \"%s\": %s\n", fileName, strerror(errno));
		return errno;
	}
	fFileSize = st.st_size;

	// read the elf header
	fElfHeader = (Elf32_Ehdr*)malloc(sizeof(Elf32_Ehdr));
	if (fElfHeader == NULL)
		return B_NO_MEMORY;

	ssize_t bytesRead = pread(fFD, fElfHeader, sizeof(Elf32_Ehdr), 0);
	if (bytesRead != (ssize_t)sizeof(Elf32_Ehdr))
		return bytesRead < 0 ? errno : B_ERROR;

	// check the ELF header
	if (!_CheckRange(0, sizeof(Elf32_Ehdr)) || !_CheckElfHeader()) {
		WARNING("\"%s\": Not an ELF file\n", fileName);
		return B_BAD_DATA;
	}

	// check section header table values
	off_t sectionHeadersOffset = fElfHeader->e_shoff;
	size_t sectionHeaderSize = fElfHeader->e_shentsize;
	int sectionCount = fElfHeader->e_shnum;
	size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
	if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
		WARNING("\"%s\": Invalid ELF header\n", fileName);
		return B_BAD_DATA;
	}

	// read the section header table
	uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
	if (sectionHeaderTable == NULL)
		return B_NO_MEMORY;
	MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);

	bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
		sectionHeadersOffset);
	if (bytesRead != (ssize_t)sectionHeaderTableSize)
		return bytesRead < 0 ? errno : B_ERROR;

	// check and get the section header string section
	Elf32_Shdr* stringSectionHeader = (Elf32_Shdr*)(sectionHeaderTable
		+ fElfHeader->e_shstrndx * sectionHeaderSize);
	if (!_CheckRange(stringSectionHeader->sh_offset,
			stringSectionHeader->sh_size)) {
		WARNING("\"%s\": Invalid string section header\n", fileName);
		return B_BAD_DATA;
	}
	size_t sectionStringSize = stringSectionHeader->sh_size;

	ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
		fFD, stringSectionHeader->sh_offset, sectionStringSize,
		stringSectionHeader->sh_addr, stringSectionHeader->sh_flags);
	if (sectionStringSection == NULL)
		return B_NO_MEMORY;
	fSections.Add(sectionStringSection);

	status_t error = sectionStringSection->Load();
	if (error != B_OK)
		return error;

	const char* sectionStrings = (const char*)sectionStringSection->Data();

	// read the other sections
	for (int i = 0; i < sectionCount; i++) {
		Elf32_Shdr* sectionHeader = (Elf32_Shdr*)(sectionHeaderTable
			+ i * sectionHeaderSize);
		// skip invalid sections and the section header string section
		const char* name = sectionStrings + sectionHeader->sh_name;
		if (sectionHeader->sh_name >= sectionStringSize
			|| !_CheckRange(sectionHeader->sh_offset, sectionHeader->sh_size)
			|| i == fElfHeader->e_shstrndx) {
			continue;
		}

		// create an ElfSection
		ElfSection* section = new(std::nothrow) ElfSection(name, fFD,
			sectionHeader->sh_offset, sectionHeader->sh_size,
			sectionHeader->sh_addr, sectionHeader->sh_flags);
		if (section == NULL)
			return B_NO_MEMORY;
		fSections.Add(section);
	}

	// check program header table values
	off_t programHeadersOffset = fElfHeader->e_phoff;
	size_t programHeaderSize = fElfHeader->e_phentsize;
	int segmentCount = fElfHeader->e_phnum;
	size_t programHeaderTableSize = programHeaderSize * segmentCount;
	if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
		WARNING("\"%s\": Invalid ELF header\n", fileName);
		return B_BAD_DATA;
	}

	// read the program header table
	uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
	if (programHeaderTable == NULL)
		return B_NO_MEMORY;
	MemoryDeleter programHeaderTableDeleter(programHeaderTable);

	bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
		programHeadersOffset);
	if (bytesRead != (ssize_t)programHeaderTableSize)
		return bytesRead < 0 ? errno : B_ERROR;

	// read the program headers and create ElfSegment objects
	for (int i = 0; i < segmentCount; i++) {
		Elf32_Phdr* programHeader = (Elf32_Phdr*)(programHeaderTable
			+ i * programHeaderSize);
		// skip program headers we aren't interested in or that are invalid
		if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
			|| programHeader->p_memsz == 0
			|| !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) {
			continue;
		}

		// create an ElfSegment
		ElfSegment* segment = new(std::nothrow) ElfSegment(
			programHeader->p_offset, programHeader->p_filesz,
			programHeader->p_vaddr, programHeader->p_memsz,
			(programHeader->p_flags & PF_WRITE) != 0);
		if (segment == NULL)
			return B_NO_MEMORY;
		fSegments.Add(segment);
	}

	return B_OK;
}