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

📄 insmod.c

📁 为samsung2410 ARM移植的busybox工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
		*loc += got - dot + rel->r_addend;;#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)		*loc += got - dot;#endif		break;#endif // __68k__#if defined(__sh__)	case R_SH_GOT32:#elif defined(__arm__)	case R_ARM_GOT32:#elif defined(__i386__)	case R_386_GOT32:#elif defined(__mc68000__)	case R_68K_GOT32:#endif		assert(isym != NULL);        /* needs an entry in the .got: set it, once */		if (!isym->gotent.reloc_done) {			isym->gotent.reloc_done = 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;    /* address relative to the got */#if !defined(__mc68000__)#if defined(__sh__)	case R_SH_GOTOFF:#elif defined(__arm__)	case R_ARM_GOTOFF:#elif defined(__i386__)	case R_386_GOTOFF:#elif defined(__mc68000__)	case R_68K_GOTOFF:#endif		assert(got != 0);		*loc += v - got;		break;#endif // __mc68000__#endif /* BB_USE_GOT_ENTRIES */	default:        printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));		ret = obj_reloc_unhandled;		break;	}	return ret;}static int arch_create_got(struct obj_file *f){#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)	struct arch_file *ifile = (struct arch_file *) f;	int i;#if defined(BB_USE_GOT_ENTRIES)	int got_offset = 0, gotneeded = 0;#endif#if defined(BB_USE_PLT_ENTRIES)	int plt_offset = 0, pltneeded = 0;#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)];			switch (ELF32_R_TYPE(rel->r_info)) {#if defined(__arm__)			case R_ARM_GOT32:				break;#elif defined(__sh__)			case R_SH_GOT32:				break;#elif defined(__i386__)			case R_386_GOT32:				break;#elif defined(__mc68000__)			case R_68K_GOT32:				break;#endif#if defined(__powerpc__)			case R_PPC_REL24:				pltneeded = 1;				break;#endif#if defined(__arm__)			case R_ARM_PC24:			case R_ARM_PLT32:				pltneeded = 1;				break;			case R_ARM_GOTPC:			case R_ARM_GOTOFF:				gotneeded = 1;				if (got_offset == 0)					got_offset = 4;#elif defined(__sh__)			case R_SH_GOTPC:			case R_SH_GOTOFF:				gotneeded = 1;#elif defined(__i386__)			case R_386_GOTPC:			case R_386_GOTOFF:				gotneeded = 1;#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(BB_USE_GOT_ENTRIES)			if (!intsym->gotent.offset_done) {				intsym->gotent.offset_done = 1;				intsym->gotent.offset = got_offset;				got_offset += BB_GOT_ENTRY_SIZE;			}#endif#if defined(BB_USE_PLT_ENTRIES)			if (pltneeded && intsym->pltent.allocated == 0) {				intsym->pltent.allocated = 1;				intsym->pltent.offset = plt_offset;				plt_offset += BB_PLT_ENTRY_SIZE;				intsym->pltent.inited = 0;				pltneeded = 0;			}#endif			}		}#if defined(BB_USE_GOT_ENTRIES)	if (got_offset) {		struct obj_section* myrelsec = obj_find_section(f, ".got");		if (myrelsec) {			obj_extend_section(myrelsec, got_offset);		} else {			myrelsec = obj_create_alloced_section(f, ".got", 							    BB_GOT_ENTRY_SIZE,							    got_offset);			assert(myrelsec);		}		ifile->got = myrelsec;	}#endif#if defined(BB_USE_PLT_ENTRIES)	if (plt_offset)		ifile->plt = obj_create_alloced_section(f, ".plt", 							BB_PLT_ENTRY_SIZE, 							plt_offset);#endif#endif	return 1;}static int arch_init_module(struct obj_file *f, struct new_module *mod){	return 1;}/*======================================================================*//* 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 BB_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							/* BB_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){	if (sym) {		if (sym->secidx >= SHN_LORESERVE)			return sym->value;		return sym->value + f->sections[sym->secidx]->header.sh_addr;	} else {		/* As a special case, a NULL sym has value zero.  */		return 0;	}}static struct obj_section *obj_find_section(struct obj_file *f, const char *name){	int i, n = f->header.e_shnum;	for (i = 0; i < n; ++i)		if (strcmp(f->sections[i]->name, name) == 0)			return f->sections[i];	return NULL;}static int obj_load_order_prio(struct obj_section *a){	unsigned long af, ac;	af = a->header.sh_flags;	ac = 0;	if (a->name[0] != '.' || strlen(a->name) != 10 ||		strcmp(a->name + 5, ".init"))		ac |= 32;	if (af & SHF_ALLOC)		ac |= 16;	if (!(af & SHF_WRITE))		ac |= 8;	if (af & SHF_EXECINSTR)		ac |= 4;	if (a->header.sh_type != SHT_NOBITS)		ac |= 2;	return ac;}static voidobj_insert_section_load_order(struct obj_file *f, struct obj_section *sec){	struct obj_section **p;	int prio = obj_load_order_prio(sec);	for (p = f->load_order_search_start; *p; p = &(*p)->load_next)		if (obj_load_order_prio(*p) < prio)			break;	sec->load_next = *p;	*p = sec;}static struct obj_section *obj_create_alloced_section(struct obj_file *f,											   const char *name,											   unsigned long align,											   unsigned long size){	int newidx = f->header.e_shnum++;	struct obj_section *sec;	f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));	f->sections[newidx] = sec = arch_new_section();	memset(sec, 0, sizeof(*sec));	sec->header.sh_type = SHT_PROGBITS;	sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;	sec->header.sh_size = size;	sec->header.sh_addralign = align;	sec->name = name;	sec->idx = newidx;	if (size)		sec->contents = xmalloc(size);	obj_insert_section_load_order(f, sec);	return sec;}static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,													 const char *name,													 unsigned long align,													 unsigned long size){	int newidx = f->header.e_shnum++;	struct obj_section *sec;	f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));	f->sections[newidx] = sec = arch_new_section();	memset(sec, 0, sizeof(*sec));	sec->header.sh_type = SHT_PROGBITS;	sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;	sec->header.sh_size = size;	sec->header.sh_addralign = align;	sec->name = name;	sec->idx = newidx;	if (size)		sec->contents = xmalloc(size);	sec->load_next = f->load_order;	f->load_order = sec;	if (f->load_order_search_start == &f->load_order)		f->load_order_search_start = &sec->load_next;	return sec;}static void *obj_extend_section(struct obj_section *sec, unsigned long more){	unsigned long oldsize = sec->header.sh_size;	if (more) { 		sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);	}	return sec->contents + oldsize;}/* Conditionally add the symbols from the given symbol set to the   new module.  */static intadd_symbols_from(				 struct obj_file *f,				 int idx, struct new_module_symbol *syms, size_t nsyms){	struct new_module_symbol *s;	size_t i;	int used = 0;	for (i = 0, s = syms; i < nsyms; ++i, ++s) {		/* Only add symbols that are already marked external.  If we		   override locals we may cause problems for argument initialization.		   We will also create a false dependency on the module.  */		struct obj_symbol *sym;		sym = obj_find_symbol(f, (char *) s->name);		if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {			sym = obj_add_symbol(f, (char *) s->name, -1,								 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),								 idx, s->value, 0);			/* Did our symbol just get installed?  If so, mark the			   module as "used".  */			if (sym->secidx == idx)				used = 1;		}	}	return used;}static void add_kernel_symbols(struct obj_file *f)

⌨️ 快捷键说明

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