/* The nasty work of reading 32 and 64-bit modules is in here. */ #include #include #include #include #include #include #include #include "depmod.h" #include "util.h" #include "logging.h" #include "elfops.h" #include "tables.h" #include "zlibsupport.h" #include "testing.h" /* Symbol types, returned by load_dep_syms */ static const char *weak_sym = "W"; static const char *undef_sym = "U"; /* dump_modversions helper */ static const char *skip_dot(const char *str) { /* For our purposes, .foo matches foo. PPC64 needs this. */ if (str && str[0] == '.') return str + 1; return str; } #define ELF32BIT #include "elfops_core.c" #undef ELF32BIT #define ELF64BIT #include "elfops_core.c" #undef ELF64BIT /* * Check ELF file header. */ static int elf_ident(void *file, unsigned long fsize, int *conv) { /* "\177ELF" where byte = 001 for 32-bit, 002 for 64 */ unsigned char *ident = file; if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0) return -ENOEXEC; /* Not an ELF object */ if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2) return -EINVAL; /* Unknown endianness */ if (conv != NULL) *conv = native_endianness() != ident[EI_DATA]; return ident[EI_CLASS]; } /* * grab_elf_file - read ELF file into memory * @pathame: file to load * * Returns NULL, and errno set on error. */ struct elf_file *grab_elf_file(const char *pathname) { struct elf_file *file; file = malloc(sizeof(*file)); if (!file) { errno = ENOMEM; goto fail; } file->pathname = strdup(pathname); if (!file->pathname) { errno = ENOMEM; goto fail_free_file; } file->data = grab_file(pathname, &file->len); if (!file->data) goto fail_free_pathname; switch (elf_ident(file->data, file->len, &file->conv)) { case ELFCLASS32: file->ops = &mod_ops32; break; case ELFCLASS64: file->ops = &mod_ops64; break; case -ENOEXEC: /* Not an ELF object */ case -EINVAL: /* Unknown endianness */ default: /* Unknown word size */ errno = ENOEXEC; goto fail; } return file; fail_free_pathname: free(file->pathname); fail_free_file: free(file); fail: return NULL; } void release_elf_file(struct elf_file *file) { int err = errno; if (!file) return; release_file(file->data, file->len); free(file->pathname); free(file); errno = err; }