コード例 #1
0
ファイル: info.c プロジェクト: 173210/psp2sdk_travis
int updateModinfo(FILE *fp, const scn_t *scns, Elf32_Half shnum,
	const sceScns_t *sceScns, Elf32_Addr base,
	const syslib_t *syslib, const char *strtab, const char *str)
{
	unsigned char md[SHA_DIGEST_LENGTH];
	_sceModuleInfo *info;
	const scn_t *sp;
	int res;

	if (fp == NULL || scns == NULL || sceScns == NULL
		|| sceScns->relEnt->content == NULL || strtab == NULL || str == NULL)
	{
		return EINVAL;
	}

	if (sceScns->modinfo->orgSize != sizeof(_sceModuleInfo))
		return EILSEQ;

	res = loadScn(fp, sceScns->modinfo, str);
	if (res)
		return res;

	info = sceScns->modinfo->content;

	info->expTop = sceScns->ent->shdr.sh_addr - base;
	info->expBtm = info->expTop + sceScns->ent->shdr.sh_size;

	info->impTop = sceScns->stub->shdr.sh_addr - base;
	info->impBtm = info->impTop + sceScns->stub->shdr.sh_size;


	info->start = syslib->start - base;
	info->stop = syslib->stop - base;

	sp = findScnByType(scns, shnum, SHT_ARM_EXIDX, NULL);
	if (sp != NULL) {
		info->exidxTop = sp->segOffset;
		info->exidxBtm = info->exidxTop + sp->shdr.sh_size;
	}

	sp = findScnByName(scns, shnum, strtab, ".ARM.extab", NULL);
	if (sp != NULL) {
		info->extabTop = sp->segOffset;
		info->extabBtm = info->extabTop + sp->shdr.sh_size;
	}

	if (info->nid == 0) {
		SHA1((unsigned char *)info->name, strlen(info->name), md);
		((unsigned char *)&info->nid)[0] = md[3];
		((unsigned char *)&info->nid)[1] = md[2];
		((unsigned char *)&info->nid)[2] = md[1];
		((unsigned char *)&info->nid)[3] = md[0];
	}

	return 0;
}
コード例 #2
0
ファイル: stub.c プロジェクト: psxdev/psp2sdk
int updateStubs(sceScns_t *sceScns, FILE *fp,
	const scn_t *scns, const seg_t *segs,
	const char *strtab, Elf32_Sym *symtab)
{
	union {
		uint8_t size;
		sce_libgen_mark_head head;
		sce_libgen_mark_stub stub;
	} *p;
	sceLib_stub *stubHeads;
	Psp2_Rela *relaFstubEnt, *relaStubEnt;
	Elf32_Off offset, fnidOffset, fstubOffset, stubOffset;
	Elf32_Rel *rel, *relMarkEnt;
	Elf32_Sym *sym;
	Elf32_Word i, type, *fnidEnt;
	Elf32_Half symseg;
	Elf32_Addr addend;
	int res;

	if (sceScns == NULL || fp == NULL || scns == NULL || segs == NULL
		|| strtab == NULL || symtab == NULL)
	{
		return EINVAL;
	}

	sceScns->relFstub->content = malloc(sceScns->relFstub->shdr.sh_size);
	if (sceScns->relFstub->content == NULL) {
		perror(strtab + sceScns->relFstub->shdr.sh_name);
		return errno;
	}

	sceScns->relStub->content = malloc(sceScns->relStub->shdr.sh_size);
	if (sceScns->relFstub->content == NULL) {
		perror(strtab + sceScns->relStub->shdr.sh_name);
		return errno;
	}

	sceScns->fnid->content = malloc(sceScns->fnid->shdr.sh_size);
	if (sceScns->fnid->content == NULL) {
		perror(strtab + sceScns->fnid->shdr.sh_name);
		return errno;
	}

	sceScns->stub->content = malloc(sceScns->stub->shdr.sh_size);
	if (sceScns->stub->content == NULL) {
		perror(strtab + sceScns->stub->shdr.sh_name);
		return errno;
	}

	res = loadScn(fp, sceScns->mark,
		strtab + sceScns->mark->shdr.sh_name);
	if (res)
		return res;

	res = loadScn(fp, sceScns->relMark,
		strtab + sceScns->relMark->shdr.sh_name);
	if (res)
		return res;

	relaFstubEnt = sceScns->relFstub->content;
	relaStubEnt = sceScns->relStub->content;
	fnidEnt = sceScns->fnid->content;
	stubHeads = sceScns->stub->content;
	p = sceScns->mark->content;
	fnidOffset = sceScns->fnid->segOffset;
	fstubOffset = sceScns->fstub->segOffset;
	stubOffset = sceScns->stub->segOffset;
	offset = 0;
	while (offset < sceScns->mark->shdr.sh_size) {
		if (p->size == sizeof(sce_libgen_mark_head)) {
			stubHeads->size = sizeof(sceLib_stub);
			stubHeads->ver = 1;
			stubHeads->flags = 0;
			stubHeads->nid = p->head.nid;

			// Resolve name
			rel = findRelByOffset(sceScns->relMark,
				sceScns->mark->shdr.sh_addr + offset
					+ offsetof(sce_libgen_mark_head, name),
				strtab);
			if (rel == NULL)
				return errno;

			type = ELF32_R_TYPE(rel->r_info);
			sym = symtab + ELF32_R_SYM(rel->r_info);
			symseg = scns[sym->st_shndx].phndx;

			PSP2_R_SET_SHORT(relaStubEnt, 0);
			PSP2_R_SET_SYMSEG(relaStubEnt, symseg);
			PSP2_R_SET_TYPE(relaStubEnt, type);
			PSP2_R_SET_DATSEG(relaStubEnt, sceScns->stub->phndx);
			PSP2_R_SET_OFFSET(relaStubEnt, stubOffset
				+ offsetof(sceLib_stub, name));

			PSP2_R_SET_ADDEND(relaStubEnt,
				(type == R_ARM_ABS32 || type == R_ARM_TARGET1 ?
					sym->st_value : p->head.name)
				- segs[symseg].phdr.p_vaddr);

			relaStubEnt++;

			// Resolve function NID table
			PSP2_R_SET_SHORT(relaStubEnt, 0);
			PSP2_R_SET_SYMSEG(relaStubEnt, sceScns->fnid->phndx);
			PSP2_R_SET_TYPE(relaStubEnt, R_ARM_ABS32);
			PSP2_R_SET_DATSEG(relaStubEnt, sceScns->stub->phndx);
			PSP2_R_SET_OFFSET(relaStubEnt, stubOffset
				+ offsetof(sceLib_stub, funcNids));
			PSP2_R_SET_ADDEND(relaStubEnt, fnidOffset);
			relaStubEnt++;

			// Resolve function stub table
			PSP2_R_SET_SHORT(relaStubEnt, 0);
			PSP2_R_SET_SYMSEG(relaStubEnt, sceScns->fstub->phndx);
			PSP2_R_SET_TYPE(relaStubEnt, R_ARM_ABS32);
			PSP2_R_SET_DATSEG(relaStubEnt, sceScns->stub->phndx);
			PSP2_R_SET_OFFSET(relaStubEnt, stubOffset
				+ offsetof(sceLib_stub, funcStubs));
			PSP2_R_SET_ADDEND(relaStubEnt, fstubOffset);
			relaStubEnt++;

			// TODO: Support other types
			stubHeads->varNids = 0;
			stubHeads->varStubs = 0;
			stubHeads->unkNids = 0;
			stubHeads->unkStubs = 0;

			// Resolve nids and stubs
			stubHeads->funcNum = 0;
			stubHeads->varNum = 0;
			stubHeads->unkNum = 0;

			relMarkEnt = sceScns->relMark->content;
			for (i = 0; i < sceScns->relMark->orgSize / sizeof(Elf32_Rel); i++) {
				sym = symtab + ELF32_R_SYM(relMarkEnt->r_info);
				type = ELF32_R_TYPE(relMarkEnt->r_info);

				if (type == R_ARM_ABS32 || type == R_ARM_TARGET1) {
					if (scns + sym->st_shndx != sceScns->mark)
						goto cont;

					addend = *(Elf32_Word *)((uintptr_t)sceScns->mark->content
						+ relMarkEnt->r_offset - sceScns->mark->shdr.sh_addr);
				} else
					addend = sym->st_value;

				if (addend != sceScns->mark->shdr.sh_addr + offset)
					goto cont;

				res = addStub(relaFstubEnt, sceScns->fstub, fnidEnt,
					sceScns->relMark, sceScns->mark,
					fstubOffset,
					relMarkEnt->r_offset
						- offsetof(sce_libgen_mark_stub, head),
					scns, segs, strtab, symtab);
				if (res)
					return res;

				relaFstubEnt++;
				fnidEnt++;
				fstubOffset += sizeof(Elf32_Addr);
				fnidOffset += sizeof(Elf32_Word);
				stubHeads->funcNum++;
cont:
				relMarkEnt++;
			}

			stubOffset += sizeof(sceLib_stub);
			stubHeads++;
		} else if (p->size == 0) {
			printf("%s: Invalid mark\n",
				strtab + sceScns->mark->shdr.sh_name);
			return EILSEQ;
		}

		offset += p->size;
		p = (void *)((uintptr_t)p + p->size);
	}

	sceScns->relFstub->shdr.sh_type = SHT_PSP2_RELA;
	sceScns->relStub->shdr.sh_type = SHT_PSP2_RELA;

	return 0;
}
コード例 #3
0
ファイル: info.c プロジェクト: 173210/psp2sdk_travis
int findSyslib(syslib_t *syslib, FILE *fp, scn_t *scns, Elf32_Half shnum,
	const seg_t *segs, const seg_t *rela,
	const char *strtab, const Elf32_Sym *symtab,
	scn_t *ent, const scn_t *relEnt)
{
	const Elf32_Rel *rel;
	const Elf32_Sym *sym;
	const Elf32_Word *nids;
	Elf32_Word i, stubOffset, type, *p;
	const scn_t *stubRel;
	scn_t *scn;
	int res;

	if (syslib == NULL || fp == NULL || scns == NULL || segs == NULL
		|| rela == NULL || strtab == NULL || symtab == NULL
		|| ent == NULL || relEnt == NULL || relEnt->content == NULL)
	{
		return EINVAL;
	}

	if (ent->content == NULL) {
		res = loadScn(fp, ent, strtab + ent->shdr.sh_name);
		if (res)
			return res;
	}

	// Stub Table
	rel = findRelByOffset(relEnt, ent->shdr.sh_addr + 28, strtab);
	if (rel == NULL)
		return errno;

	sym = symtab + ELF32_R_SYM(rel->r_info);
	scn = scns + sym->st_shndx;
	type = ELF32_R_TYPE(rel->r_info);
	stubOffset = (type == R_ARM_ABS32 || type == R_ARM_TARGET1 ?
		*(Elf32_Word *)((uintptr_t)ent->content + 28) : sym->st_value)
		- segs[scn->phndx].phdr.p_vaddr;

	i = 0;
	do {
		if (i >= rela->shnum) {
			fprintf(stderr, "%s: Relocation table not found\n",
				strtab + scn->shdr.sh_name);
			return EILSEQ;
		}

		stubRel = rela->scns[i];
		i++;
	} while (stubRel->shdr.sh_info != sym->st_shndx);

	// NID Table
	rel = findRelByOffset(relEnt, ent->segOffset + 24, strtab);
	if (rel == NULL)
		return errno;

	sym = symtab + ELF32_R_SYM(rel->r_info);
	scn = scns + sym->st_shndx;

	if (scn->content == NULL) {
		res = loadScn(fp, scn, strtab + scn->shdr.sh_name);
		if (res)
			return res;
	}

	type = ELF32_R_TYPE(rel->r_info);
	nids = (void *)((uintptr_t)scn->content
		+ (type == R_ARM_ABS32 || type == R_ARM_TARGET1 ?
			*(Elf32_Word *)((uintptr_t)ent->content + 24) : sym->st_value)
		- scn->shdr.sh_addr);

	// Resolve
	for (i = 0; i < ((Elf32_Half *)ent->content)[3]; i++) {
		if (nids[i] == 0x935CD196)
			p = &syslib->start;
		else if (nids[i] == 0x79F8E492)
			p = &syslib->stop;
		else
			continue;

		rel = findRelByOffset(stubRel, stubOffset + i * 4, strtab);
		if (rel == NULL)
			return errno;

		*p = symtab[ELF32_R_SYM(rel->r_info)].st_value;
	}

	return 0;
}
コード例 #4
0
ファイル: elf.c プロジェクト: 173210/psp2sdk_travis
int openElf(elf_t *dst, const char *path)
{
	int res;

	if (dst == NULL || path == NULL)
		return EINVAL;

	dst->path = path;

	dst->fp = fopen(path, "rb");
	if (dst->fp == NULL) {
		perror(path);
		return errno;
	}

	if (fread(&dst->ehdr, sizeof(dst->ehdr), 1, dst->fp) <= 0) {
		if (feof(dst->fp)) {
			fprintf(stderr, "%s: Unexpected EOF\n", path);
			errno = EILSEQ;
		} else
			perror(path);

		fclose(dst->fp);
		return errno;
	}

	dst->orgShnum = dst->ehdr.e_shnum;

	dst->scns = getScns(dst->fp, path, &dst->ehdr);
	if (dst->scns == NULL) {
		fclose(dst->fp);
		return errno;
	}

	dst->strtab = dst->scns + dst->ehdr.e_shstrndx;
	res = loadScn(dst->fp, dst->strtab, path);
	if (res) {
		free(dst->scns);
		fclose(dst->fp);
		return res;
	}

	dst->symtab = findScnByType(dst->scns, dst->ehdr.e_shnum,
		SHT_SYMTAB, path);
	if (dst->symtab == NULL) {
		free(dst->scns);
		free(dst->strtab->content);
		fclose(dst->fp);
		return errno;
	}

	res = loadScn(dst->fp, dst->symtab,
		(void *)((uintptr_t)dst->strtab->content + dst->symtab->shdr.sh_name));
	if (res) {
		free(dst->scns);
		free(dst->strtab->content);
		fclose(dst->fp);
		return res;
	}

	res = getSceScns(&dst->sceScns, dst->scns, dst->ehdr.e_shnum,
		dst->strtab->content, path);
	if (res) {
		free(dst->scns);
		free(dst->strtab->content);
		free(dst->symtab->content);
		fclose(dst->fp);
		return res;
	}

	dst->segs = getSegs(dst->fp, path, &dst->ehdr,
		dst->scns, &dst->rela, dst->sceScns.relMark);
	if (dst->segs == NULL) {
		free(dst->scns);
		free(dst->strtab->content);
		free(dst->symtab->content);
		fclose(dst->fp);
		return errno;
	}

	return 0;
}