blob: 63a9914fd2c601280d6a4ef26dcffe32e77f66d4 [file] [log] [blame]
Ben Cheng25b3c042013-11-20 14:45:36 -08001/* Return converted data from raw chunk of ELF file.
Elliott Hughes03333822015-02-18 22:19:45 -08002 Copyright (C) 2007, 2014 Red Hat, Inc.
3 This file is part of elfutils.
Ben Cheng25b3c042013-11-20 14:45:36 -08004
Elliott Hughes03333822015-02-18 22:19:45 -08005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Ben Cheng25b3c042013-11-20 14:45:36 -08007
Elliott Hughes03333822015-02-18 22:19:45 -08008 * 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
Ben Cheng25b3c042013-11-20 14:45:36 -080021 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
Elliott Hughes03333822015-02-18 22:19:45 -080025 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/>. */
Ben Cheng25b3c042013-11-20 14:45:36 -080028
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
Elliott Hughes03333822015-02-18 22:19:45 -080060 if (unlikely (offset < 0 || (uint64_t) offset > elf->maximum_size
61 || elf->maximum_size - (uint64_t) offset < size))
62
Ben Cheng25b3c042013-11-20 14:45:36 -080063 {
64 /* Invalid request. */
65 __libelf_seterrno (ELF_E_INVALID_OP);
66 return NULL;
67 }
68
69 if (type >= ELF_T_NUM)
70 {
71 __libelf_seterrno (ELF_E_UNKNOWN_TYPE);
72 return NULL;
73 }
74
75 /* Get the raw bytes from the file. */
76 void *rawchunk;
77 int flags = 0;
78 Elf_Data *result = NULL;
79
80 rwlock_rdlock (elf->lock);
81
82 /* If the file is mmap'ed we can use it directly. */
83 if (elf->map_address != NULL)
84 rawchunk = elf->map_address + elf->start_offset + offset;
85 else
86 {
87 /* We allocate the memory and read the data from the file. */
88 rawchunk = malloc (size);
89 if (rawchunk == NULL)
90 {
91 nomem:
92 __libelf_seterrno (ELF_E_NOMEM);
93 goto out;
94 }
95
96 /* Read the file content. */
97 if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size,
98 elf->start_offset + offset)
99 != size))
100 {
101 /* Something went wrong. */
102 free (rawchunk);
103 __libelf_seterrno (ELF_E_READ_ERROR);
104 goto out;
105 }
106
107 flags = ELF_F_MALLOCED;
108 }
109
110 /* Copy and/or convert the data as needed for aligned native-order access. */
111 size_t align = __libelf_type_align (elf->class, type);
112 void *buffer;
113 if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA)
114 {
115 if (((uintptr_t) rawchunk & (align - 1)) == 0)
116 /* No need to copy, we can use the raw data. */
117 buffer = rawchunk;
118 else
119 {
120 /* A malloc'd block is always sufficiently aligned. */
121 assert (flags == 0);
122
123 buffer = malloc (size);
124 if (unlikely (buffer == NULL))
125 goto nomem;
126 flags = ELF_F_MALLOCED;
127
128 /* The copy will be appropriately aligned for direct access. */
129 memcpy (buffer, rawchunk, size);
130 }
131 }
132 else
133 {
134 if (flags)
135 buffer = rawchunk;
136 else
137 {
138 buffer = malloc (size);
139 if (unlikely (buffer == NULL))
140 goto nomem;
141 flags = ELF_F_MALLOCED;
142 }
143
144 /* Call the conversion function. */
145 (*__elf_xfctstom[LIBELF_EV_IDX][LIBELF_EV_IDX][elf->class - 1][type])
146 (buffer, rawchunk, size, 0);
147 }
148
149 /* Allocate the dummy container to point at this buffer. */
150 Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk);
151 if (chunk == NULL)
152 {
153 if (flags)
154 free (buffer);
155 goto nomem;
156 }
157
158 chunk->dummy_scn.elf = elf;
159 chunk->dummy_scn.flags = flags;
160 chunk->data.s = &chunk->dummy_scn;
161 chunk->data.d.d_buf = buffer;
162 chunk->data.d.d_size = size;
163 chunk->data.d.d_type = type;
164 chunk->data.d.d_align = align;
165 chunk->data.d.d_version = __libelf_version;
166
167 rwlock_unlock (elf->lock);
168 rwlock_wrlock (elf->lock);
169
170 chunk->next = elf->state.elf.rawchunks;
171 elf->state.elf.rawchunks = chunk;
172 result = &chunk->data.d;
173
174 out:
175 rwlock_unlock (elf->lock);
176 return result;
177}