blob: f4fbe660b0dc527fb7e9286d77bbd560d1029248 [file] [log] [blame]
Roland McGrath59ea7f32007-10-04 08:50:09 +00001/* Return converted data from raw chunk of ELF file.
2 Copyright (C) 2007 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Roland McGrath59ea7f32007-10-04 08:50:09 +00004
Mark Wielaardde2ed972012-06-05 17:15:16 +02005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Roland McGrath59ea7f32007-10-04 08:50:09 +00007
Mark Wielaardde2ed972012-06-05 17:15:16 +02008 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
11
12 or
13
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
17
18 or both in parallel, as here.
19
20 elfutils is distributed in the hope that it will be useful, but
Roland McGrath59ea7f32007-10-04 08:50:09 +000021 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
Mark Wielaardde2ed972012-06-05 17:15:16 +020025 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
Roland McGrath59ea7f32007-10-04 08:50:09 +000028
29#ifdef HAVE_CONFIG_H
30# include <config.h>
31#endif
32
33#include <assert.h>
34#include <errno.h>
35#include <stdlib.h>
36#include <string.h>
37#include <unistd.h>
38
39#include <system.h>
40#include "libelfP.h"
41#include "common.h"
42
43Elf_Data *
44elf_getdata_rawchunk (elf, offset, size, type)
45 Elf *elf;
46 off64_t offset;
47 size_t size;
48 Elf_Type type;
49{
50 if (unlikely (elf == NULL))
51 return NULL;
52
53 if (unlikely (elf->kind != ELF_K_ELF))
54 {
55 /* No valid descriptor. */
56 __libelf_seterrno (ELF_E_INVALID_HANDLE);
57 return NULL;
58 }
59
Jan Kratochvilf1ccc412011-01-05 10:06:21 +010060 if (unlikely (offset < 0 || offset + (off64_t) size < offset
61 || offset + size > elf->maximum_size))
Roland McGrath59ea7f32007-10-04 08:50:09 +000062 {
63 /* Invalid request. */
64 __libelf_seterrno (ELF_E_INVALID_OP);
65 return NULL;
66 }
67
68 if (type >= ELF_T_NUM)
69 {
70 __libelf_seterrno (ELF_E_UNKNOWN_TYPE);
71 return NULL;
72 }
73
74 /* Get the raw bytes from the file. */
75 void *rawchunk;
76 int flags = 0;
Ulrich Drepper02f66452008-12-04 05:58:16 +000077 Elf_Data *result = NULL;
78
79 rwlock_rdlock (elf->lock);
Roland McGrath59ea7f32007-10-04 08:50:09 +000080
81 /* If the file is mmap'ed we can use it directly. */
82 if (elf->map_address != NULL)
83 rawchunk = elf->map_address + elf->start_offset + offset;
84 else
85 {
86 /* We allocate the memory and read the data from the file. */
87 rawchunk = malloc (size);
88 if (rawchunk == NULL)
89 {
90 nomem:
91 __libelf_seterrno (ELF_E_NOMEM);
Ulrich Drepper02f66452008-12-04 05:58:16 +000092 goto out;
Roland McGrath59ea7f32007-10-04 08:50:09 +000093 }
94
95 /* Read the file content. */
96 if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size,
97 elf->start_offset + offset)
98 != size))
99 {
100 /* Something went wrong. */
101 free (rawchunk);
102 __libelf_seterrno (ELF_E_READ_ERROR);
Ulrich Drepper02f66452008-12-04 05:58:16 +0000103 goto out;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000104 }
105
106 flags = ELF_F_MALLOCED;
107 }
108
109 /* Copy and/or convert the data as needed for aligned native-order access. */
110 size_t align = __libelf_type_align (elf->class, type);
111 void *buffer;
112 if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA)
113 {
114 if (((uintptr_t) rawchunk & (align - 1)) == 0)
115 /* No need to copy, we can use the raw data. */
116 buffer = rawchunk;
117 else
118 {
119 /* A malloc'd block is always sufficiently aligned. */
120 assert (flags == 0);
121
122 buffer = malloc (size);
123 if (unlikely (buffer == NULL))
124 goto nomem;
125 flags = ELF_F_MALLOCED;
126
127 /* The copy will be appropriately aligned for direct access. */
128 memcpy (buffer, rawchunk, size);
129 }
130 }
131 else
132 {
133 if (flags)
134 buffer = rawchunk;
135 else
136 {
137 buffer = malloc (size);
138 if (unlikely (buffer == NULL))
139 goto nomem;
140 flags = ELF_F_MALLOCED;
141 }
142
143 /* Call the conversion function. */
144 (*__elf_xfctstom[LIBELF_EV_IDX][LIBELF_EV_IDX][elf->class - 1][type])
145 (buffer, rawchunk, size, 0);
146 }
147
148 /* Allocate the dummy container to point at this buffer. */
149 Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk);
150 if (chunk == NULL)
151 {
152 if (flags)
153 free (buffer);
154 goto nomem;
155 }
156
157 chunk->dummy_scn.elf = elf;
158 chunk->dummy_scn.flags = flags;
159 chunk->data.s = &chunk->dummy_scn;
160 chunk->data.d.d_buf = buffer;
161 chunk->data.d.d_size = size;
162 chunk->data.d.d_type = type;
163 chunk->data.d.d_align = align;
164 chunk->data.d.d_version = __libelf_version;
165
Ulrich Drepper02f66452008-12-04 05:58:16 +0000166 rwlock_unlock (elf->lock);
167 rwlock_wrlock (elf->lock);
168
Roland McGrath59ea7f32007-10-04 08:50:09 +0000169 chunk->next = elf->state.elf.rawchunks;
170 elf->state.elf.rawchunks = chunk;
Ulrich Drepper02f66452008-12-04 05:58:16 +0000171 result = &chunk->data.d;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000172
Ulrich Drepper02f66452008-12-04 05:58:16 +0000173 out:
174 rwlock_unlock (elf->lock);
175 return result;
Roland McGrath59ea7f32007-10-04 08:50:09 +0000176}