⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 insmod.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 5 页
字号:
	case R_SH_GOTOFF:		assert(got != 0);		*loc = v - got;		break;#endif	default:        printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));		ret = obj_reloc_unhandled;		break;#if defined (__v850e__)	case R_V850_NONE:		break;	case R_V850_32:		/* We write two shorts instead of a long because even		   32-bit insns only need half-word alignment, but		   32-bit data needs to be long-word aligned.  */		v += ((unsigned short *)loc)[0];		v += ((unsigned short *)loc)[1] << 16;		((unsigned short *)loc)[0] = v & 0xffff;		((unsigned short *)loc)[1] = (v >> 16) & 0xffff;		break;	case R_V850_22_PCREL:		goto bb_use_plt;#endif#if defined(CONFIG_USE_PLT_ENTRIES)	  bb_use_plt:      /* find the plt entry and initialize it if necessary */      assert(isym != NULL);#if defined(CONFIG_USE_PLT_LIST)      for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)	pe = pe->next;      assert(pe != NULL);#else      pe = &isym->pltent;#endif      if (! pe->inited) {	  	ip = (unsigned long *) (ifile->plt->contents + pe->offset);		/* generate some machine code */#if defined(__arm__)	  	ip[0] = 0xe51ff004;			/* ldr pc,[pc,#-4] */	  	ip[1] = v;				/* sym@ */#endif#if defined(__powerpc__)	  ip[0] = 0x3d600000 + ((v + 0x8000) >> 16);  /* lis r11,sym@ha */	  ip[1] = 0x396b0000 + (v & 0xffff);	      /* addi r11,r11,sym@l */	  ip[2] = 0x7d6903a6;			      /* mtctr r11 */	  ip[3] = 0x4e800420;			      /* bctr */#endif#if defined (__v850e__)		/* We have to trash a register, so we assume that any control		   transfer more than 21-bits away must be a function call		   (so we can use a call-clobbered register).  */		ip[0] = 0x0621 + ((v & 0xffff) << 16);   /* mov sym, r1 ... */		ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */#endif	  	pe->inited = 1;	  }      /* relative distance to target */      v -= dot;      /* if the target is too far away.... */#if defined (__arm__) || defined (__powerpc__)      if ((int)v < -0x02000000 || (int)v >= 0x02000000) #elif defined (__v850e__)      if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)#endif	    /* go via the plt */	    v = plt + pe->offset - dot;#if defined (__v850e__)      if (v & 1)#else      if (v & 3)#endif	    ret = obj_reloc_dangerous;      /* merge the offset into the instruction. */#if defined(__arm__)      /* Convert to words. */      v >>= 2;      *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);#endif#if defined(__powerpc__)      *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);#endif#if defined (__v850e__)      /* We write two shorts instead of a long because even 32-bit insns	 only need half-word alignment, but the 32-bit data write needs	 to be long-word aligned.  */      ((unsigned short *)loc)[0] =	      (*(unsigned short *)loc & 0xffc0) /* opcode + reg */	      | ((v >> 16) & 0x3f);             /* offs high part */      ((unsigned short *)loc)[1] =	      (v & 0xffff);                    /* offs low part */#endif      break;#endif /* CONFIG_USE_PLT_ENTRIES */#if defined(CONFIG_USE_GOT_ENTRIES)	  bb_use_got:		assert(isym != NULL);        /* needs an entry in the .got: set it, once */		if (!isym->gotent.inited) {			isym->gotent.inited = 1;			*(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;		}        /* make the reloc with_respect_to_.got */#if defined(__sh__)		*loc += isym->gotent.offset + rel->r_addend;#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)		*loc += isym->gotent.offset;#endif		break;#endif /* CONFIG_USE_GOT_ENTRIES */	}	return ret;}#if defined(CONFIG_USE_LIST) static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,			  int offset, int size){	struct arch_list_entry *pe;	for (pe = *list; pe != NULL; pe = pe->next) {		if (pe->addend == rel->r_addend) {			break;		}	}	if (pe == NULL) {		pe = xmalloc(sizeof(struct arch_list_entry));		pe->next = *list;		pe->addend = rel->r_addend;		pe->offset = offset;		pe->inited = 0;		*list = pe;		return size;	}	return 0;}#endif#if defined(CONFIG_USE_SINGLE) static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,			     int offset, int size){	if (single->allocated == 0) {		single->allocated = 1;		single->offset = offset;		single->inited = 0;		return size;	}	return 0;}#endif#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)static struct obj_section *arch_xsect_init(struct obj_file *f, char *name, 					   int offset, int size){	struct obj_section *myrelsec = obj_find_section(f, name);	if (offset == 0) {		offset += size;	}	if (myrelsec) {		obj_extend_section(myrelsec, offset);	} else {		myrelsec = obj_create_alloced_section(f, name, 						      size, offset);		assert(myrelsec);	}	return myrelsec;}#endifstatic void arch_create_got(struct obj_file *f){#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)	struct arch_file *ifile = (struct arch_file *) f;	int i;#if defined(CONFIG_USE_GOT_ENTRIES)	int got_offset = 0, got_needed = 0, got_allocate;#endif#if defined(CONFIG_USE_PLT_ENTRIES)	int plt_offset = 0, plt_needed = 0, plt_allocate;#endif    struct obj_section *relsec, *symsec, *strsec;	ElfW(RelM) *rel, *relend;	ElfW(Sym) *symtab, *extsym;	const char *strtab, *name;	struct arch_symbol *intsym;	for (i = 0; i < f->header.e_shnum; ++i) {		relsec = f->sections[i];		if (relsec->header.sh_type != SHT_RELM)			continue;		symsec = f->sections[relsec->header.sh_link];		strsec = f->sections[symsec->header.sh_link];		rel = (ElfW(RelM) *) relsec->contents;		relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));		symtab = (ElfW(Sym) *) symsec->contents;		strtab = (const char *) strsec->contents;		for (; rel < relend; ++rel) {			extsym = &symtab[ELF32_R_SYM(rel->r_info)];#if defined(CONFIG_USE_GOT_ENTRIES)			got_allocate = 0;#endif#if defined(CONFIG_USE_PLT_ENTRIES)			plt_allocate = 0;#endif			switch (ELF32_R_TYPE(rel->r_info)) {#if defined(__arm__)			case R_ARM_PC24:			case R_ARM_PLT32:				plt_allocate = 1;				break;			case R_ARM_GOTOFF:			case R_ARM_GOTPC:				got_needed = 1;				continue;			case R_ARM_GOT32:				got_allocate = 1;				break;#elif defined(__i386__)			case R_386_GOTPC:			case R_386_GOTOFF:				got_needed = 1;				continue;			case R_386_GOT32:				got_allocate = 1;				break;#elif defined(__powerpc__)			case R_PPC_REL24:				plt_allocate = 1;				break;#elif defined(__mc68000__)			case R_68K_GOT32:				got_allocate = 1;				break;			case R_68K_GOTOFF:				got_needed = 1;				continue;#elif defined(__sh__)			case R_SH_GOT32:				got_allocate = 1; 				break;			case R_SH_GOTPC:			case R_SH_GOTOFF:				got_needed = 1;				continue;#elif defined (__v850e__)			case R_V850_22_PCREL:				plt_needed = 1;				break;#endif			default:				continue;			}			if (extsym->st_name != 0) {				name = strtab + extsym->st_name;			} else {				name = f->sections[extsym->st_shndx]->name;			}			intsym = (struct arch_symbol *) obj_find_symbol(f, name);#if defined(CONFIG_USE_GOT_ENTRIES)			if (got_allocate) {				got_offset += arch_single_init(					rel, &intsym->gotent, 					got_offset, CONFIG_GOT_ENTRY_SIZE);				got_needed = 1;			}#endif#if defined(CONFIG_USE_PLT_ENTRIES)			if (plt_allocate) {#if defined(CONFIG_USE_PLT_LIST) 				plt_offset += arch_list_add(					rel, &intsym->pltent, 					plt_offset, CONFIG_PLT_ENTRY_SIZE);#else				plt_offset += arch_single_init(					rel, &intsym->pltent, 					plt_offset, CONFIG_PLT_ENTRY_SIZE);#endif				plt_needed = 1;			}#endif		}	}#if defined(CONFIG_USE_GOT_ENTRIES)	if (got_needed) {		ifile->got = arch_xsect_init(f, ".got", got_offset,					    CONFIG_GOT_ENTRY_SIZE);	}#endif#if defined(CONFIG_USE_PLT_ENTRIES)	if (plt_needed) {		ifile->plt = arch_xsect_init(f, ".plt", plt_offset,					    CONFIG_PLT_ENTRY_SIZE);	}#endif#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */}#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACEstatic int arch_init_module(struct obj_file *f, struct new_module *mod){	return 1;}#endif/*======================================================================*//* Standard ELF hash function.  */static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n){	unsigned long h = 0;	unsigned long g;	unsigned char ch;	while (n > 0) {		ch = *name++;		h = (h << 4) + ch;		if ((g = (h & 0xf0000000)) != 0) {			h ^= g >> 24;			h &= ~g;		}		n--;	}	return h;}static unsigned long obj_elf_hash(const char *name){	return obj_elf_hash_n(name, strlen(name));}#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING/* String comparison for non-co-versioned kernel and module.  */static int ncv_strcmp(const char *a, const char *b){	size_t alen = strlen(a), blen = strlen(b);	if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')		return strncmp(a, b, alen);	else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')		return strncmp(a, b, blen);	else		return strcmp(a, b);}/* String hashing for non-co-versioned kernel and module.  Here   we are simply forced to drop the crc from the hash.  */static unsigned long ncv_symbol_hash(const char *str){	size_t len = strlen(str);	if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')		len -= 10;	return obj_elf_hash_n(str, len);}static voidobj_set_symbol_compare(struct obj_file *f,					   int (*cmp) (const char *, const char *),					   unsigned long (*hash) (const char *)){	if (cmp)		f->symbol_cmp = cmp;	if (hash) {		struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;		int i;		f->symbol_hash = hash;		memcpy(tmptab, f->symtab, sizeof(tmptab));		memset(f->symtab, 0, sizeof(f->symtab));		for (i = 0; i < HASH_BUCKETS; ++i)			for (sym = tmptab[i]; sym; sym = next) {				unsigned long h = hash(sym->name) % HASH_BUCKETS;				next = sym->next;				sym->next = f->symtab[h];				f->symtab[h] = sym;			}	}}#endif							/* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */static struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,								  unsigned long symidx, int info,								  int secidx, ElfW(Addr) value,								  unsigned long size){	struct obj_symbol *sym;	unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;	int n_type = ELFW(ST_TYPE) (info);	int n_binding = ELFW(ST_BIND) (info);	for (sym = f->symtab[hash]; sym; sym = sym->next)		if (f->symbol_cmp(sym->name, name) == 0) {			int o_secidx = sym->secidx;			int o_info = sym->info;			int o_type = ELFW(ST_TYPE) (o_info);			int o_binding = ELFW(ST_BIND) (o_info);			/* A redefinition!  Is it legal?  */			if (secidx == SHN_UNDEF)				return sym;			else if (o_secidx == SHN_UNDEF)				goto found;			else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {				/* Cope with local and global symbols of the same name				   in the same object file, as might have been created				   by ld -r.  The only reason locals are now seen at this				   level at all is so that we can do semi-sensible things				   with parameters.  */				struct obj_symbol *nsym, **p;				nsym = arch_new_symbol();				nsym->next = sym->next;				nsym->ksymidx = -1;				/* Excise the old (local) symbol from the hash chain.  */				for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)					continue;				*p = sym = nsym;				goto found;			} else if (n_binding == STB_LOCAL) {				/* Another symbol of the same name has already been defined.				   Just add this to the local table.  */				sym = arch_new_symbol();				sym->next = NULL;				sym->ksymidx = -1;				f->local_symtab[symidx] = sym;				goto found;			} else if (n_binding == STB_WEAK)				return sym;			else if (o_binding == STB_WEAK)				goto found;			/* Don't unify COMMON symbols with object types the programmer			   doesn't expect.  */			else if (secidx == SHN_COMMON					 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))				return sym;			else if (o_secidx == SHN_COMMON					 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))				goto found;			else {				/* Don't report an error if the symbol is coming from				   the kernel or some external module.  */				if (secidx <= SHN_HIRESERVE)					error_msg("%s multiply defined", name);				return sym;			}		}	/* Completely new symbol.  */	sym = arch_new_symbol();	sym->next = f->symtab[hash];	f->symtab[hash] = sym;	sym->ksymidx = -1;	if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {		if (symidx >= f->local_symtab_size)			error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",					name, (long) symidx, (long) f->local_symtab_size);		else			f->local_symtab[symidx] = sym;	}  found:	sym->name = name;	sym->value = value;	sym->size = size;	sym->secidx = secidx;	sym->info = info;	return sym;}static struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name){	struct obj_symbol *sym;	unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;	for (sym = f->symtab[hash]; sym; sym = sym->next)		if (f->symbol_cmp(sym->name, name) == 0)			return sym;	return NULL;}static ElfW(Addr)	obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -