~ubuntu-core-dev/module-init-tools/ubuntu

« back to all changes in this revision

Viewing changes to elfops.c

  • Committer: Scott James Remnant
  • Date: 2009-07-16 15:24:17 UTC
  • mfrom: (152.1.38)
  • Revision ID: scott@netsplit.com-20090716152417-7ak1sklxb59cs4fz
MergeĀ 3.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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"
 
15
 
 
16
#include "testing.h"
 
17
 
 
18
/* Symbol types, returned by load_dep_syms */
 
19
static const char *weak_sym = "W";
 
20
static const char *undef_sym = "U";
 
21
 
 
22
/* dump_modversions helper */
 
23
static const char *skip_dot(const char *str)
 
24
{
 
25
       /* For our purposes, .foo matches foo.  PPC64 needs this. */
 
26
       if (str && str[0] == '.')
 
27
               return str + 1;
 
28
       return str;
 
29
}
 
30
 
 
31
#define ELF32BIT
 
32
#include "elfops_core.c"
 
33
#undef ELF32BIT
 
34
 
 
35
#define ELF64BIT
 
36
#include "elfops_core.c"
 
37
#undef ELF64BIT
 
38
 
 
39
/*
 
40
 * Check ELF file header.
 
41
 */
 
42
static int elf_ident(void *file, unsigned long fsize, int *conv)
 
43
{
 
44
        /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
 
45
        unsigned char *ident = file;
 
46
 
 
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 */
 
51
 
 
52
        if (conv != NULL)
 
53
                *conv = native_endianness() != ident[EI_DATA];
 
54
        return ident[EI_CLASS];
 
55
}
 
56
 
 
57
/*
 
58
 * grab_elf_file - read ELF file into memory
 
59
 * @pathame: file to load
 
60
 *
 
61
 * Returns NULL, and errno set on error.
 
62
 */
 
63
struct elf_file *grab_elf_file(const char *pathname)
 
64
{
 
65
        int fd;
 
66
        int err;
 
67
        struct elf_file *file;
 
68
 
 
69
        fd = open(pathname, O_RDONLY, 0);
 
70
        if (fd < 0)
 
71
                return NULL;
 
72
        file = grab_elf_file_fd(pathname, fd);
 
73
 
 
74
        err = errno;
 
75
        close(fd);
 
76
        errno = err;
 
77
        return file;
 
78
}
 
79
 
 
80
/*
 
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
 
84
 *
 
85
 * Returns NULL, and errno set on error.
 
86
 */
 
87
struct elf_file *grab_elf_file_fd(const char *pathname, int fd)
 
88
{
 
89
        struct elf_file *file;
 
90
 
 
91
        file = malloc(sizeof(*file));
 
92
        if (!file) {
 
93
                errno = ENOMEM;
 
94
                return NULL;
 
95
        }
 
96
        file->pathname = strdup(pathname);
 
97
        if (!file->pathname) {
 
98
                free(file);
 
99
                errno = ENOMEM;
 
100
                return NULL;
 
101
        }
 
102
        file->data = grab_fd(fd, &file->len);
 
103
        if (!file->data)
 
104
                goto fail;
 
105
 
 
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;
 
118
        }
 
119
        return file;
 
120
fail:
 
121
        release_elf_file(file);
 
122
        return NULL;
 
123
}
 
124
 
 
125
void release_elf_file(struct elf_file *file)
 
126
{
 
127
        int err = errno;
 
128
 
 
129
        if (!file)
 
130
                return;
 
131
 
 
132
        release_file(file->data, file->len);
 
133
        free(file->pathname);
 
134
        free(file);
 
135
 
 
136
        errno = err;
 
137
}