コード例 #1
0
ファイル: stub.c プロジェクト: psxdev/psp2sdk
// fstubOffset and markOffset should be relative to segment
static int addStub(Psp2_Rela *relaFstub, const scn_t *fstub,
	Elf32_Word *fnid, const scn_t *relMark, const scn_t *mark,
	Elf32_Addr fstubOffset, Elf32_Addr markOffset,
	const scn_t *scns, const seg_t *segs,
	const char *strtab, const Elf32_Sym *symtab)
{
	const Elf32_Rel *rel;
	const Elf32_Sym *sym;
	Elf32_Word type;
	Elf32_Half symseg;
	Elf32_Addr addend;

	if (relaFstub == NULL || fstub == NULL || fnid == NULL
		|| relMark == NULL || relMark->content == NULL
		|| mark == NULL || mark->content == NULL
		|| scns == NULL || symtab == NULL)
	{
		return EINVAL;
	}

	rel = findRelByOffset(relMark,
		markOffset + offsetof(sce_libgen_mark_stub, stub), 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(relaFstub, 0);
	PSP2_R_SET_SYMSEG(relaFstub, symseg);
	PSP2_R_SET_TYPE(relaFstub, type);
	PSP2_R_SET_DATSEG(relaFstub, fstub->phndx);
	PSP2_R_SET_OFFSET(relaFstub, fstubOffset);

	if (type == R_ARM_ABS32 || type == R_ARM_TARGET1) {
		if (mark->content == NULL)
			return EINVAL;

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

	addend -= segs[symseg].phdr.p_vaddr;
	PSP2_R_SET_ADDEND(relaFstub, addend);

	*fnid = *(Elf32_Word *)((uintptr_t)mark->content
		+ markOffset - mark->shdr.sh_addr
		+ offsetof(sce_libgen_mark_stub, nid));

	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;
}