source: rtems-tools/rtemstoolkit/elftoolchain/libelf/elf_data.c @ 87e0e76

4.104.115
Last change on this file since 87e0e76 was 87e0e76, checked in by Chris Johns <chrisj@…>, on 09/13/14 at 02:09:16

Refactor code into the RTEMS Toolkit.

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*-
2 * Copyright (c) 2006,2008,2011 Joseph Koshy
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <assert.h>
28#include <errno.h>
29#include <libelf.h>
30#include <stdlib.h>
31
32#include "_libelf.h"
33
34LIBELF_VCSID("$Id: elf_data.c 1765 2011-08-22 05:59:05Z jkoshy $");
35
36Elf_Data *
37elf_getdata(Elf_Scn *s, Elf_Data *d)
38{
39        Elf *e;
40        size_t fsz, msz, count;
41        int elfclass, elftype;
42        unsigned int sh_type;
43        uint64_t sh_align, sh_offset, sh_size;
44        int (*xlate)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap);
45
46        if (s == NULL || (e = s->s_elf) == NULL ||
47            (d != NULL && s != d->d_scn)) {
48                LIBELF_SET_ERROR(ARGUMENT, 0);
49                return (NULL);
50        }
51
52        assert(e->e_kind == ELF_K_ELF);
53
54        if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
55                return (d);
56
57        if (d != NULL)
58                return (STAILQ_NEXT(d, d_next));
59
60        if (e->e_rawfile == NULL) {
61                /*
62                 * In the ELF_C_WRITE case, there is no source that
63                 * can provide data for the section.
64                 */
65                LIBELF_SET_ERROR(ARGUMENT, 0);
66                return (NULL);
67        }
68
69        elfclass = e->e_class;
70
71        assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
72
73        if (elfclass == ELFCLASS32) {
74                sh_type   = s->s_shdr.s_shdr32.sh_type;
75                sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
76                sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
77                sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
78        } else {
79                sh_type   = s->s_shdr.s_shdr64.sh_type;
80                sh_offset = s->s_shdr.s_shdr64.sh_offset;
81                sh_size   = s->s_shdr.s_shdr64.sh_size;
82                sh_align  = s->s_shdr.s_shdr64.sh_addralign;
83        }
84
85        if (sh_type == SHT_NULL) {
86                LIBELF_SET_ERROR(SECTION, 0);
87                return (NULL);
88        }
89
90        if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
91            elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
92            sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
93                LIBELF_SET_ERROR(SECTION, 0);
94                return (NULL);
95        }
96
97        if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
98            (elftype, (size_t) 1, e->e_version)) == 0) {
99                LIBELF_SET_ERROR(UNIMPL, 0);
100                return (NULL);
101        }
102
103        if (sh_size % fsz) {
104                LIBELF_SET_ERROR(SECTION, 0);
105                return (NULL);
106        }
107
108        count = sh_size / fsz;
109
110        msz = _libelf_msize(elftype, elfclass, e->e_version);
111
112        assert(msz > 0);
113
114        if ((d = _libelf_allocate_data(s)) == NULL)
115                return (NULL);
116
117        d->d_buf     = NULL;
118        d->d_off     = 0;
119        d->d_align   = sh_align;
120        d->d_size    = msz * count;
121        d->d_type    = elftype;
122        d->d_version = e->e_version;
123
124        if (sh_type == SHT_NOBITS || sh_size == 0) {
125                STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
126                return (d);
127        }
128
129        if ((d->d_buf = malloc(msz*count)) == NULL) {
130                (void) _libelf_release_data(d);
131                LIBELF_SET_ERROR(RESOURCE, 0);
132                return (NULL);
133        }
134
135        d->d_flags  |= LIBELF_F_DATA_MALLOCED;
136
137        xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
138        if (!(*xlate)(d->d_buf, d->d_size, e->e_rawfile + sh_offset, count,
139            e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
140                _libelf_release_data(d);
141                LIBELF_SET_ERROR(DATA, 0);
142                return (NULL);
143        }
144
145        STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
146
147        return (d);
148}
149
150Elf_Data *
151elf_newdata(Elf_Scn *s)
152{
153        Elf *e;
154        Elf_Data *d;
155
156        if (s == NULL || (e = s->s_elf) == NULL) {
157                LIBELF_SET_ERROR(ARGUMENT, 0);
158                return (NULL);
159        }
160
161        assert(e->e_kind == ELF_K_ELF);
162
163        /*
164         * elf_newdata() has to append a data descriptor, so
165         * bring in existing section data if not already present.
166         */
167        if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))
168                if (elf_getdata(s, NULL) == NULL)
169                        return (NULL);
170
171        if ((d = _libelf_allocate_data(s)) == NULL)
172                return (NULL);
173
174        STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
175
176        d->d_align = 1;
177        d->d_buf = NULL;
178        d->d_off = (uint64_t) ~0;
179        d->d_size = 0;
180        d->d_type = ELF_T_BYTE;
181        d->d_version = LIBELF_PRIVATE(version);
182
183        (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);
184
185        return (d);
186}
187
188/*
189 * Retrieve a data descriptor for raw (untranslated) data for section
190 * `s'.
191 */
192
193Elf_Data *
194elf_rawdata(Elf_Scn *s, Elf_Data *d)
195{
196        Elf *e;
197        int elf_class;
198        uint32_t sh_type;
199        uint64_t sh_align, sh_offset, sh_size;
200
201        if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) {
202                LIBELF_SET_ERROR(ARGUMENT, 0);
203                return (NULL);
204        }
205
206        assert(e->e_kind == ELF_K_ELF);
207
208        if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
209                return (d);
210
211        if (d != NULL)
212                return (STAILQ_NEXT(d, d_next));
213
214        elf_class = e->e_class;
215
216        assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);
217
218        if (elf_class == ELFCLASS32) {
219                sh_type   = s->s_shdr.s_shdr32.sh_type;
220                sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
221                sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
222                sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
223        } else {
224                sh_type   = s->s_shdr.s_shdr64.sh_type;
225                sh_offset = s->s_shdr.s_shdr64.sh_offset;
226                sh_size   = s->s_shdr.s_shdr64.sh_size;
227                sh_align  = s->s_shdr.s_shdr64.sh_addralign;
228        }
229
230        if (sh_type == SHT_NULL)
231                return (NULL);
232
233        if ((d = _libelf_allocate_data(s)) == NULL)
234                return (NULL);
235
236        d->d_buf     = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
237            e->e_rawfile + sh_offset;
238        d->d_off     = 0;
239        d->d_align   = sh_align;
240        d->d_size    = sh_size;
241        d->d_type    = ELF_T_BYTE;
242        d->d_version = e->e_version;
243
244        STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);
245
246        return (d);
247}
Note: See TracBrowser for help on using the repository browser.