meta: update various documentation, logs, authors, etc.
[mit.git] / elfops.c
blobda2740e7cfa360f1c657515bb2585fae459c033a
1 /* The nasty work of reading 32 and 64-bit modules is in here. */
2 #include <elf.h>
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include "depmod.h"
10 #include "util.h"
11 #include "logging.h"
12 #include "elfops.h"
13 #include "tables.h"
14 #include "zlibsupport.h"
16 #include "testing.h"
18 /* Symbol types, returned by load_dep_syms */
19 static const char *weak_sym = "W";
20 static const char *undef_sym = "U";
22 /* dump_modversions helper */
23 static const char *skip_dot(const char *str)
25 /* For our purposes, .foo matches foo. PPC64 needs this. */
26 if (str && str[0] == '.')
27 return str + 1;
28 return str;
31 #define ELF32BIT
32 #include "elfops_core.c"
33 #undef ELF32BIT
35 #define ELF64BIT
36 #include "elfops_core.c"
37 #undef ELF64BIT
40 * Check ELF file header.
42 static int elf_ident(void *file, unsigned long fsize, int *conv)
44 /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
45 unsigned char *ident = file;
47 if (fsize < EI_CLASS || memcmp(file, ELFMAG, SELFMAG) != 0)
48 return -ENOEXEC; /* Not an ELF object */
49 if (ident[EI_DATA] == 0 || ident[EI_DATA] > 2)
50 return -EINVAL; /* Unknown endianness */
52 if (conv != NULL)
53 *conv = native_endianness() != ident[EI_DATA];
54 return ident[EI_CLASS];
58 * grab_elf_file - read ELF file into memory
59 * @pathame: file to load
61 * Returns NULL, and errno set on error.
63 struct elf_file *grab_elf_file(const char *pathname)
65 int fd;
66 int err;
67 struct elf_file *file;
69 fd = open(pathname, O_RDONLY, 0);
70 if (fd < 0)
71 return NULL;
72 file = grab_elf_file_fd(pathname, fd);
74 err = errno;
75 close(fd);
76 errno = err;
77 return file;
81 * grab_elf_file_fd - read ELF file from file descriptor into memory
82 * @pathame: name of file to load
83 * @fd: file descriptor of file to load
85 * Returns NULL, and errno set on error.
87 struct elf_file *grab_elf_file_fd(const char *pathname, int fd)
89 struct elf_file *file;
91 file = malloc(sizeof(*file));
92 if (!file) {
93 errno = ENOMEM;
94 return NULL;
96 file->pathname = strdup(pathname);
97 if (!file->pathname) {
98 free(file);
99 errno = ENOMEM;
100 return NULL;
102 file->data = grab_fd(fd, &file->len);
103 if (!file->data)
104 goto fail;
106 switch (elf_ident(file->data, file->len, &file->conv)) {
107 case ELFCLASS32:
108 file->ops = &mod_ops32;
109 break;
110 case ELFCLASS64:
111 file->ops = &mod_ops64;
112 break;
113 case -ENOEXEC: /* Not an ELF object */
114 case -EINVAL: /* Unknown endianness */
115 default: /* Unknown word size */
116 errno = ENOEXEC;
117 goto fail;
119 return file;
120 fail:
121 release_elf_file(file);
122 return NULL;
125 void release_elf_file(struct elf_file *file)
127 int err = errno;
129 if (!file)
130 return;
132 release_file(file->data, file->len);
133 free(file->pathname);
134 free(file);
136 errno = err;