* PowerPC specific code stolen from modutils-2.3.16,
* written by Paul Mackerras, Copyright 1996, 1997 Linux International.
* I've only tested the code on mpc8xx platforms in big-endian mode.
- * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
+ * Did some cleanup and added USE_xxx_ENTRIES...
*
* Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
* based on modutils-2.4.2
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include "busybox.h"
+#include "libbb.h"
#include <libgen.h>
#include <sys/utsname.h>
-#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
- !defined(CONFIG_FEATURE_2_6_MODULES)
-#define CONFIG_FEATURE_2_4_MODULES
+#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
+#undef ENABLE_FEATURE_2_4_MODULES
+#define ENABLE_FEATURE_2_4_MODULES 1
#endif
-#if !defined(CONFIG_FEATURE_2_4_MODULES)
+#if !ENABLE_FEATURE_2_4_MODULES
#define insmod_ng_main insmod_main
#endif
-#if defined(CONFIG_FEATURE_2_6_MODULES)
-extern int insmod_ng_main( int argc, char **argv);
+#if ENABLE_FEATURE_2_6_MODULES
+extern int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
#endif
-#if defined(CONFIG_FEATURE_2_4_MODULES)
+#if ENABLE_FEATURE_2_4_MODULES
-#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
+#if ENABLE_FEATURE_INSMOD_LOADINKMEM
#define LOADBITS 0
#else
#define LOADBITS 1
#define SHT_RELM SHT_REL
#define Elf32_RelM Elf32_Rel
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 8
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 8
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 8
+#define USE_SINGLE
#endif
/* blackfin */
#define SHT_RELM SHT_RELA
#define Elf32_RelM Elf32_Rela
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_SINGLE
+#define USE_SINGLE
#define SYMBOL_PREFIX "_"
#endif
#define SHT_RELM SHT_REL
#define Elf32_RelM Elf32_Rel
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 4
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 4
+#define USE_SINGLE
#endif
/* IA64, aka Itanium */
#define SHT_RELM SHT_RELA
#define Elf32_RelM Elf32_Rela
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 4
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 4
+#define USE_SINGLE
#endif
/* Microblaze */
#if defined(__microblaze__)
-#define CONFIG_USE_SINGLE
+#define USE_SINGLE
#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
#define SHT_RELM SHT_RELA
#define Elf32_RelM Elf32_Rela
#define SHT_RELM SHT_RELA
#define Elf32_RelM Elf32_Rela
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 16
-#define CONFIG_USE_PLT_LIST
-#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
-#define CONFIG_USE_LIST
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 16
+#define USE_PLT_LIST
+#define LIST_ARCHTYPE ElfW(Addr)
+#define USE_LIST
#define ARCHDATAM "__ftr_fixup"
#endif
#define SHT_RELM SHT_RELA
#define Elf32_RelM Elf32_Rela
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 8
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 8
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 8
+#define USE_SINGLE
#endif
/* SuperH */
#define SHT_RELM SHT_RELA
#define Elf32_RelM Elf32_Rela
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 4
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 4
+#define USE_SINGLE
/* the SH changes have only been tested in =little endian= mode */
/* I'm not sure about big endian, so let's warn: */
#if defined(__sh__) && BB_BIG_ENDIAN
#endif
/* v850e */
-#if defined (__v850e__)
+#if defined(__v850e__)
#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
#define SHT_RELM SHT_RELA
#define Elf32_RelM Elf32_Rela
#define ELFCLASSM ELFCLASS32
-#define CONFIG_USE_PLT_ENTRIES
-#define CONFIG_PLT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_PLT_ENTRIES
+#define PLT_ENTRY_SIZE 8
+#define USE_SINGLE
#ifndef EM_CYGNUS_V850 /* grumble */
#define EM_CYGNUS_V850 0x9080
#endif
#if defined(__x86_64__)
#define MATCH_MACHINE(x) (x == EM_X86_64)
#define SHT_RELM SHT_RELA
-#define CONFIG_USE_GOT_ENTRIES
-#define CONFIG_GOT_ENTRY_SIZE 8
-#define CONFIG_USE_SINGLE
+#define USE_GOT_ENTRIES
+#define GOT_ENTRY_SIZE 8
+#define USE_SINGLE
#define Elf64_RelM Elf64_Rela
#define ELFCLASSM ELFCLASS64
#endif
#ifndef MODUTILS_MODULE_H
-/* Why? static const int MODUTILS_MODULE_H = 1;*/
/*======================================================================*/
/* For sizeof() which are related to the module platform and not to the
#ifndef MODUTILS_OBJ_H
-/* Why? static const int MODUTILS_OBJ_H = 1; */
/* The relocatable object is manipulated using elfin types. */
-#include <stdio.h>
#include <elf.h>
#include <endian.h>
static unsigned long obj_elf_hash_n(const char *, unsigned long len);
-static struct obj_symbol *obj_find_symbol (struct obj_file *f,
+static struct obj_symbol *obj_find_symbol(struct obj_file *f,
const char *name);
static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
struct obj_symbol *sym);
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
static void obj_set_symbol_compare(struct obj_file *f,
int (*cmp)(const char *, const char *),
unsigned long (*hash)(const char *));
#endif
-static struct obj_section *obj_find_section (struct obj_file *f,
+static struct obj_section *obj_find_section(struct obj_file *f,
const char *name);
-static void obj_insert_section_load_order (struct obj_file *f,
+static void obj_insert_section_load_order(struct obj_file *f,
struct obj_section *sec);
-static struct obj_section *obj_create_alloced_section (struct obj_file *f,
+static struct obj_section *obj_create_alloced_section(struct obj_file *f,
const char *name,
unsigned long align,
unsigned long size);
-static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
+static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
const char *name,
unsigned long align,
unsigned long size);
-static void *obj_extend_section (struct obj_section *sec, unsigned long more);
+static void *obj_extend_section(struct obj_section *sec, unsigned long more);
static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
const char *string);
static void obj_allocate_commons(struct obj_file *f);
-static unsigned long obj_load_size (struct obj_file *f);
+static unsigned long obj_load_size(struct obj_file *f);
-static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
+static int obj_relocate(struct obj_file *f, ElfW(Addr) base);
static struct obj_file *obj_load(FILE *f, int loadprogbits);
-static int obj_create_image (struct obj_file *f, char *image);
+static int obj_create_image(struct obj_file *f, char *image);
/* Architecture specific manipulation routines. */
-static struct obj_file *arch_new_file (void);
+static struct obj_file *arch_new_file(void);
-static struct obj_section *arch_new_section (void);
+static struct obj_section *arch_new_section(void);
-static struct obj_symbol *arch_new_symbol (void);
+static struct obj_symbol *arch_new_symbol(void);
-static enum obj_reloc arch_apply_relocation (struct obj_file *f,
+static enum obj_reloc arch_apply_relocation(struct obj_file *f,
struct obj_section *targsec,
struct obj_section *symsec,
struct obj_symbol *sym,
ElfW(RelM) *rel, ElfW(Addr) value);
-static void arch_create_got (struct obj_file *f);
+static void arch_create_got(struct obj_file *f);
#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
static int obj_gpl_license(struct obj_file *f, const char **license);
-#endif /* ENABLE_FEATURE_CHECK_TAINTED_MODULE */
+#endif /* FEATURE_CHECK_TAINTED_MODULE */
#endif /* obj.h */
//----------------------------------------------------------------------------
//--------end of modutils obj.h
#define _PATH_MODULES "/lib/modules"
-enum { STRVERSIONLEN = 32 };
+enum { STRVERSIONLEN = 64 };
/*======================================================================*/
#define flag_verbose (option_mask32 & OPT_v)
#define flag_quiet (option_mask32 & OPT_q)
#define flag_noexport (option_mask32 & OPT_x)
-#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP
#define flag_print_load_map (option_mask32 & OPT_m)
#else
#define flag_print_load_map 0
/*======================================================================*/
-#if defined(CONFIG_USE_LIST)
+#if defined(USE_LIST)
struct arch_list_entry
{
struct arch_list_entry *next;
- CONFIG_LIST_ARCHTYPE addend;
+ LIST_ARCHTYPE addend;
int offset;
int inited : 1;
};
#endif
-#if defined(CONFIG_USE_SINGLE)
+#if defined(USE_SINGLE)
struct arch_single_entry
{
struct arch_file {
struct obj_file root;
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
struct obj_section *plt;
#endif
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
struct obj_section *got;
#endif
#if defined(__mips__)
struct arch_symbol {
struct obj_symbol root;
-#if defined(CONFIG_USE_PLT_ENTRIES)
-#if defined(CONFIG_USE_PLT_LIST)
+#if defined(USE_PLT_ENTRIES)
+#if defined(USE_PLT_LIST)
struct arch_list_entry *pltent;
#else
struct arch_single_entry pltent;
#endif
#endif
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
struct arch_single_entry gotent;
#endif
};
static int check_module_name_match(const char *filename, struct stat *statbuf,
- void *userdata)
+ void *userdata, int depth)
{
char *fullname = (char *) userdata;
if (fullname[0] == '\0')
- return (FALSE);
+ return FALSE;
else {
char *tmp, *tmp1 = xstrdup(filename);
- tmp = bb_get_last_path_component(tmp1);
+ tmp = bb_get_last_path_component_nostrip(tmp1);
if (strcmp(tmp, fullname) == 0) {
free(tmp1);
/* Stop searching if we find a match */
m_filename = xstrdup(filename);
- return (FALSE);
+ return FALSE;
}
free(tmp1);
}
- return (TRUE);
+ return TRUE;
}
enum obj_reloc ret = obj_reloc_ok;
ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
-#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
struct arch_symbol *isym = (struct arch_symbol *) sym;
#endif
#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
#endif
#endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
unsigned long *ip;
-# if defined(CONFIG_USE_PLT_LIST)
+# if defined(USE_PLT_LIST)
struct arch_list_entry *pe;
# else
struct arch_single_entry *pe;
*loc += v - got;
break;
-#elif defined (__microblaze__)
+#elif defined(__microblaze__)
case R_MICROBLAZE_NONE:
case R_MICROBLAZE_64_NONE:
case R_MICROBLAZE_32_SYM_OP_SYM:
/* We cannot relocate this one now because we don't know the value
of the carry we need to add. Save the information, and let LO16
do the actual relocation. */
- n = (struct mips_hi16 *) xmalloc(sizeof *n);
+ n = xmalloc(sizeof *n);
n->addr = loc;
n->value = v;
n->next = ifile->mips_hi16_list;
}
# endif /* __SH5__ */
-#elif defined (__v850e__)
+#elif defined(__v850e__)
case R_V850_NONE:
break;
ret = obj_reloc_unhandled;
break;
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
bb_use_plt:
/* find the plt entry and initialize it if necessary */
-#if defined(CONFIG_USE_PLT_LIST)
+#if defined(USE_PLT_LIST)
for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
pe = pe->next;
#else
ip[2] = 0x7d6903a6; /* mtctr r11 */
ip[3] = 0x4e800420; /* bctr */
#endif
-#if defined (__v850e__)
+#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). */
/* relative distance to target */
v -= dot;
/* if the target is too far away.... */
-#if defined (__arm__) || defined (__powerpc__)
+#if defined(__arm__) || defined(__powerpc__)
if ((int)v < -0x02000000 || (int)v >= 0x02000000)
-#elif defined (__v850e__)
+#elif defined(__v850e__)
if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
#endif
/* go via the plt */
v = plt + pe->offset - dot;
-#if defined (__v850e__)
+#if defined(__v850e__)
if (v & 1)
#else
if (v & 3)
#if defined(__powerpc__)
*loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
#endif
-#if defined (__v850e__)
+#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. */
(v & 0xffff); /* offs low part */
#endif
break;
-#endif /* CONFIG_USE_PLT_ENTRIES */
+#endif /* USE_PLT_ENTRIES */
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
bb_use_got:
/* needs an entry in the .got: set it, once */
#endif
break;
-#endif /* CONFIG_USE_GOT_ENTRIES */
+#endif /* USE_GOT_ENTRIES */
}
return ret;
}
-#if defined(CONFIG_USE_LIST)
+#if defined(USE_LIST)
static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
int offset, int size)
#endif
-#if defined(CONFIG_USE_SINGLE)
+#if defined(USE_SINGLE)
static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
int offset, int size)
#endif
-#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
-static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
+static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
int offset, int size)
{
struct obj_section *myrelsec = obj_find_section(f, name);
static void arch_create_got(struct obj_file *f)
{
-#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
struct arch_file *ifile = (struct arch_file *) f;
int i;
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
int got_offset = 0, got_needed = 0, got_allocate;
#endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
int plt_offset = 0, plt_needed = 0, plt_allocate;
#endif
struct obj_section *relsec, *symsec, *strsec;
for (; rel < relend; ++rel) {
extsym = &symtab[ELF_R_SYM(rel->r_info)];
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
got_allocate = 0;
#endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
plt_allocate = 0;
#endif
got_needed = 1;
continue;
-#elif defined (__v850e__)
+#elif defined(__v850e__)
case R_V850_22_PCREL:
plt_needed = 1;
break;
name = f->sections[extsym->st_shndx]->name;
}
intsym = (struct arch_symbol *) obj_find_symbol(f, name);
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
if (got_allocate) {
got_offset += arch_single_init(
rel, &intsym->gotent,
- got_offset, CONFIG_GOT_ENTRY_SIZE);
+ got_offset, GOT_ENTRY_SIZE);
got_needed = 1;
}
#endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
if (plt_allocate) {
-#if defined(CONFIG_USE_PLT_LIST)
+#if defined(USE_PLT_LIST)
plt_offset += arch_list_add(
rel, &intsym->pltent,
- plt_offset, CONFIG_PLT_ENTRY_SIZE);
+ plt_offset, PLT_ENTRY_SIZE);
#else
plt_offset += arch_single_init(
rel, &intsym->pltent,
- plt_offset, CONFIG_PLT_ENTRY_SIZE);
+ plt_offset, PLT_ENTRY_SIZE);
#endif
plt_needed = 1;
}
}
}
-#if defined(CONFIG_USE_GOT_ENTRIES)
+#if defined(USE_GOT_ENTRIES)
if (got_needed) {
ifile->got = arch_xsect_init(f, ".got", got_offset,
- CONFIG_GOT_ENTRY_SIZE);
+ GOT_ENTRY_SIZE);
}
#endif
-#if defined(CONFIG_USE_PLT_ENTRIES)
+#if defined(USE_PLT_ENTRIES)
if (plt_needed) {
ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
- CONFIG_PLT_ENTRY_SIZE);
+ PLT_ENTRY_SIZE);
}
#endif
-#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
+#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
}
/*======================================================================*/
return obj_elf_hash_n(name, strlen(name));
}
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
/* String comparison for non-co-versioned kernel and module. */
static int ncv_strcmp(const char *a, const char *b)
}
}
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
static struct obj_symbol *
obj_add_symbol(struct obj_file *f, const char *name,
char *name_buf = 0;
size_t name_alloced_size = 0;
#endif
-#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
int gpl;
gpl = obj_gpl_license(f, NULL) == 0;
* their references.
*/
if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
-#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
if (gpl)
s->name += 8;
else
kernel exports `C names', but module object files
reference `linker names'). */
size_t extra = sizeof SYMBOL_PREFIX;
- size_t name_size = strlen (name) + extra;
+ size_t name_size = strlen(name) + extra;
if (name_size > name_alloced_size) {
name_alloced_size = name_size * 2;
- name_buf = alloca (name_alloced_size);
+ name_buf = alloca(name_alloced_size);
}
- strcpy (name_buf, SYMBOL_PREFIX);
- strcpy (name_buf + extra - 1, name);
+ strcpy(name_buf, SYMBOL_PREFIX);
+ strcpy(name_buf + extra - 1, name);
name = name_buf;
#endif /* SYMBOL_PREFIX */
if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
#ifdef SYMBOL_PREFIX
/* Put NAME_BUF into more permanent storage. */
- name = xmalloc (name_size);
- strcpy (name, name_buf);
+ name = xmalloc(name_size);
+ strcpy(name, name_buf);
#endif
sym = obj_add_symbol(f, name, -1,
ELF_ST_INFO(STB_GLOBAL,
/* Add module symbols first. */
- for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
+ for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
if (m->nsyms
- && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
- m->nsyms)) m->used = 1, ++nused;
+ && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
+ ) {
+ m->used = 1;
+ ++nused;
+ }
+ }
n_ext_modules_used = nused;
}
#ifdef SYMBOL_PREFIX
- sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
- strcpy (sym_name, SYMBOL_PREFIX);
- strcat (sym_name, key);
+ sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
+ strcpy(sym_name, SYMBOL_PREFIX);
+ strcat(sym_name, key);
#else
sym_name = key;
#endif
} else {
/* last string */
str = q;
- q = "";
+ q = (char*)"";
}
}
obj_string_patch(f, sym->secidx, loc - contents, str);
loc += tgt_sizeof_char_p;
} else {
- /* Array of chars (in fact, matrix !) */
+ /* Array of chars (in fact, matrix!) */
unsigned long charssize; /* size of each member */
/* Get the size of each member */
return 1;
}
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
static int new_is_module_checksummed(struct obj_file *f)
{
const char *p = get_modinfo_value(f, "using_checksums");
return a << 16 | b << 8 | c;
}
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
/* Fetch the loaded modules, and all currently exported symbols. */
return 1;
}
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
/* add an entry to the __ksymtab section, creating it if necessary */
static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
{
if (!sec)
return;
sec->header.sh_flags |= SHF_ALLOC;
- sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
- be byte-aligned */
+ /* Empty section might be byte-aligned */
+ sec->header.sh_addralign = tgt_sizeof_void_p;
ofs = sec->header.sh_size;
obj_symbol_patch(f, sec->idx, ofs, sym);
obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
obj_extend_section(sec, 2 * tgt_sizeof_char_p);
}
-#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
static int new_create_module_ksymtab(struct obj_file *f)
{
sec->header = section_headers[i];
sec->idx = i;
- if(sec->header.sh_size) {
+ if (sec->header.sh_size) {
switch (sec->header.sh_type) {
case SHT_NULL:
case SHT_NOTE:
return f;
}
-#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
+#if ENABLE_FEATURE_INSMOD_LOADINKMEM
/*
* load the unloaded sections directly into the memory allocated by
* kernel for the module
}
-#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
static int obj_gpl_license(struct obj_file *f, const char **license)
{
struct obj_section *sec;
* linux/include/linux/module.h. Checking for leading "GPL" will not
* work, somebody will use "GPL sucks, this is proprietary".
*/
- static const char * const gpl_licenses[] = {
+ static const char *const gpl_licenses[] = {
"GPL",
"GPL v2",
"GPL and additional rights",
"Dual BSD/GPL",
- "Dual MPL/GPL",
+ "Dual MPL/GPL"
};
sec = obj_find_section(f, ".modinfo");
int i;
if (license)
*license = value+1;
- for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
+ for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
if (strcmp(value+1, gpl_licenses[i]) == 0)
- return(0);
+ return 0;
}
- return(2);
+ return 2;
}
if (strchr(ptr, '\0'))
ptr = strchr(ptr, '\0') + 1;
ptr = endptr;
}
}
- return(1);
+ return 1;
}
#define TAINT_FILENAME "/proc/sys/kernel/tainted"
static void set_tainted(struct obj_file *f, int fd, char *m_name,
int kernel_has_tainted, int taint, const char *text1, const char *text2)
{
+ static smallint printed_info;
+
char buf[80];
int oldval;
- static int first = 1;
+
if (fd < 0 && !kernel_has_tainted)
return; /* New modutils on old kernel */
printf("Warning: loading %s will taint the kernel: %s%s\n",
m_name, text1, text2);
- if (first) {
+ if (!printed_info) {
printf(" See %s for information about tainted modules\n", TAINT_URL);
- first = 0;
+ printed_info = 1;
}
if (fd >= 0) {
read(fd, buf, sizeof(buf)-1);
/* Check if loading this module will taint the kernel. */
static void check_tainted_module(struct obj_file *f, char *m_name)
{
- static const char tainted_file[] = TAINT_FILENAME;
+ static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
+
int fd, kernel_has_tainted;
const char *ptr;
if (fd >= 0)
close(fd);
}
-#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
-#define check_tainted_module(x, y) do { } while(0);
-#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
+#else /* FEATURE_CHECK_TAINTED_MODULE */
+#define check_tainted_module(x, y) do { } while (0);
+#endif /* FEATURE_CHECK_TAINTED_MODULE */
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
/* add module source, timestamp, kernel version and a symbol for the
* start of some sections. this info is used by ksymoops to do better
* debugging.
static int
get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
{
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
return new_get_module_version(f, str);
-#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#else /* FEATURE_INSMOD_VERSION_CHECKING */
strncpy(str, "???", sizeof(str));
return -1;
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
}
/* add module source, timestamp, kernel version and a symbol for the
add_ksymoops_symbols(struct obj_file *f, const char *filename,
const char *m_name)
{
- static const char symprefix[] = "__insmod_";
+ static const char symprefix[] ALIGN1 = "__insmod_";
+
struct obj_section *sec;
struct obj_symbol *sym;
char *name, *absolute_filename;
if (realpath(filename, real)) {
absolute_filename = xstrdup(real);
- }
- else {
- int save_errno = errno;
- bb_error_msg("cannot get realpath for %s", filename);
- errno = save_errno;
- perror("");
+ } else {
+ bb_perror_msg("cannot get realpath for %s", filename);
absolute_filename = xstrdup(filename);
}
*/
use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
- if ((sec = obj_find_section(f, ".this"))) {
+ sec = obj_find_section(f, ".this");
+ if (sec) {
/* tag the module header with the object name, last modified
* timestamp and module version. worst case for module version
* is 0xffffff, decimal 16777215. putting all three fields in
#endif /* _NOT_SUPPORTED_ */
/* tag the desired sections if size is non-zero */
- for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
- if ((sec = obj_find_section(f, section_names[i])) &&
- sec->header.sh_size) {
+ for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
+ sec = obj_find_section(f, section_names[i]);
+ if (sec && sec->header.sh_size) {
l = sizeof(symprefix)+ /* "__insmod_" */
lm_name+ /* module name */
2+ /* "_S" */
}
}
}
-#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
-#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP
static void print_load_map(struct obj_file *f)
{
- struct obj_symbol *sym;
- struct obj_symbol **all, **p;
struct obj_section *sec;
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
+ struct obj_symbol **all, **p;
int i, nsyms, *loaded;
-
+ struct obj_symbol *sym;
+#endif
/* Report on the section layout. */
printf("Sections: Size %-*s Align\n",
(long)sec->header.sh_addr,
a);
}
-#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
+#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
/* Quick reference which section indicies are loaded. */
loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
}
#endif
}
-#else /* !CONFIG_FEATURE_INSMOD_LOAD_MAP */
+#else /* !FEATURE_INSMOD_LOAD_MAP */
void print_load_map(struct obj_file *f);
#endif
-int insmod_main( int argc, char **argv)
+int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int insmod_main(int argc, char **argv)
{
char *opt_o, *arg1;
int len;
char *m_name = 0;
int exit_status = EXIT_FAILURE;
int m_has_modinfo;
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
struct utsname uts_info;
char m_strversion[STRVERSIONLEN];
int m_version, m_crcs;
#endif
-#ifdef CONFIG_FEATURE_CLEAN_UP
- FILE *fp = 0;
+#if ENABLE_FEATURE_CLEAN_UP
+ FILE *fp = NULL;
#else
FILE *fp;
#endif
struct utsname myuname;
/* Parse any options */
- getopt32(argc, argv, OPTION_STR, &opt_o);
+ getopt32(argv, OPTION_STR, &opt_o);
arg1 = argv[optind];
if (option_mask32 & OPT_o) { // -o /* name the output module */
free(m_name);
}
}
-#if defined(CONFIG_FEATURE_2_6_MODULES)
+#if ENABLE_FEATURE_2_6_MODULES
if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
&& tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
) {
}
-#if defined(CONFIG_FEATURE_2_6_MODULES)
+#if ENABLE_FEATURE_2_6_MODULES
if (k_version > 4)
m_fullName = xasprintf("%s.ko", tmp);
else
tmp1 = 0; /* flag for free(m_name) before exit() */
}
- /* Get a filedesc for the module. Check we we have a complete path */
+ /* Get a filedesc for the module. Check that we have a complete path */
if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
|| (fp = fopen(arg1, "r")) == NULL
) {
module_dir = tmdn;
else
module_dir = real_module_dir;
- recursive_action(module_dir, TRUE, FALSE, FALSE,
- check_module_name_match, 0, m_fullName);
+ recursive_action(module_dir, ACTION_RECURSE,
+ check_module_name_match, 0, m_fullName, 0);
free(tmdn);
}
/* Check if we have found anything yet */
- if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL)) {
+ if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
char module_dir[FILENAME_MAX];
free(m_filename);
- m_filename = 0;
- if (realpath (_PATH_MODULES, module_dir) == NULL)
+ m_filename = NULL;
+ if (realpath(_PATH_MODULES, module_dir) == NULL)
strcpy(module_dir, _PATH_MODULES);
/* No module found under /lib/modules/`uname -r`, this
* time cast the net a bit wider. Search /lib/modules/ */
- if (!recursive_action(module_dir, TRUE, FALSE, FALSE,
- check_module_name_match, 0, m_fullName)
+ if (!recursive_action(module_dir, ACTION_RECURSE,
+ check_module_name_match, 0, m_fullName, 0)
) {
if (m_filename == 0
|| ((fp = fopen(m_filename, "r")) == NULL)
) {
- bb_error_msg("%s: no module by that name found", m_fullName);
+ bb_error_msg("%s: module not found", m_fullName);
goto out;
}
} else
- bb_error_msg_and_die("%s: no module by that name found", m_fullName);
+ bb_error_msg_and_die("%s: module not found", m_fullName);
}
} else
m_filename = xstrdup(arg1);
if (flag_verbose)
printf("Using %s\n", m_filename);
-#ifdef CONFIG_FEATURE_2_6_MODULES
+#if ENABLE_FEATURE_2_6_MODULES
if (k_version > 4) {
argv[optind] = m_filename;
optind--;
else
m_has_modinfo = 1;
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
/* Version correspondence? */
if (!flag_quiet) {
if (uname(&uts_info) < 0)
}
if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
- if (flag_force_load) {
- bb_error_msg("Warning: kernel-module version mismatch\n"
- "\t%s was compiled for kernel version %s\n"
- "\twhile this kernel is version %s",
- m_filename, m_strversion, uts_info.release);
- } else {
- bb_error_msg("kernel-module version mismatch\n"
- "\t%s was compiled for kernel version %s\n"
- "\twhile this kernel is version %s.",
- m_filename, m_strversion, uts_info.release);
+ bb_error_msg("%skernel-module version mismatch\n"
+ "\t%s was compiled for kernel version %s\n"
+ "\twhile this kernel is version %s",
+ flag_force_load ? "warning: " : "",
+ m_filename, m_strversion, uts_info.release);
+ if (!flag_force_load)
goto out;
- }
}
}
k_crcs = 0;
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
if (!query_module(NULL, 0, NULL, 0, NULL)) {
if (!new_get_kernel_symbols())
goto out;
k_crcs = new_is_kernel_checksummed();
} else {
- bb_error_msg("Not configured to support old kernels");
+ bb_error_msg("not configured to support old kernels");
goto out;
}
-#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
+#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
m_crcs = 0;
if (m_has_modinfo)
m_crcs = new_is_module_checksummed(f);
if (m_crcs != k_crcs)
obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
-#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
+#endif /* FEATURE_INSMOD_VERSION_CHECKING */
/* Let the module know about the kernel symbols. */
add_kernel_symbols(f);
arch_create_got(f);
hide_special_symbols(f);
-#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
+#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
add_ksymoops_symbols(f, m_filename, m_name);
-#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
+#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
new_create_module_ksymtab(f);
goto out;
}
- if(flag_print_load_map)
+ if (flag_print_load_map)
print_load_map(f);
exit_status = EXIT_SUCCESS;
out:
-#ifdef CONFIG_FEATURE_CLEAN_UP
- if(fp)
+#if ENABLE_FEATURE_CLEAN_UP
+ if (fp)
fclose(fp);
free(tmp1);
- if(!tmp1) {
+ if (!tmp1)
free(m_name);
- }
free(m_filename);
#endif
- return(exit_status);
+ return exit_status;
}
#endif
-#ifdef CONFIG_FEATURE_2_6_MODULES
+#if ENABLE_FEATURE_2_6_MODULES
#include <sys/mman.h>
#include <asm/unistd.h>
}
}
-int insmod_ng_main( int argc, char **argv)
+int insmod_ng_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int insmod_ng_main(int argc, char **argv)
{
- int i;
- int fd;
- long int ret;
- struct stat st;
- unsigned long len;
+ long ret;
+ size_t len;
+ int optlen;
void *map;
- char *filename, *options = xstrdup("");
+ char *filename, *options;
- filename = argv[1];
- if (!filename) {
+ filename = *++argv;
+ if (!filename)
bb_show_usage();
- return -1;
- }
/* Rest is options */
- for (i = 2; i < argc; i++) {
- options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
+ options = xzalloc(1);
+ optlen = 0;
+ while (*++argv) {
+ options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
/* Spaces handled by "" pairs, but no way of escaping quotes */
- if (strchr(argv[i], ' ')) {
- strcat(options, "\"");
- strcat(options, argv[i]);
- strcat(options, "\"");
- } else {
- strcat(options, argv[i]);
- }
- strcat(options, " ");
+ optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
}
+#if 0
+ /* Any special reason why mmap? It isn't performace critical... */
+ int fd;
+ struct stat st;
+ unsigned long len;
fd = xopen(filename, O_RDONLY);
-
fstat(fd, &st);
len = st.st_size;
map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
- bb_perror_msg_and_die("cannot mmap `%s'", filename);
+ bb_perror_msg_and_die("cannot mmap '%s'", filename);
+ }
+
+ /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
+ if (map == NULL) {
+ map = xmalloc(len);
+ xread(fd, map, len);
}
+#else
+ len = MAXINT(ssize_t);
+ map = xmalloc_open_read_close(filename, &len);
+#endif
ret = syscall(__NR_init_module, map, len, options);
if (ret != 0) {
- bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
+ bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
filename, moderror(errno), ret);
}