Fix: erroneous computation of ELF in-memory size
[lttng-ust.git] / include / lttng / ust-elf.h
1 #ifndef _LTTNG_UST_ELF_H
2 #define _LTTNG_UST_ELF_H
3 /*
4 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <stdlib.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <byteswap.h>
25 #include <elf.h>
26 #include <lttng/ust-endian.h>
27
28 /*
29 * Determine native endianness in order to convert when reading an ELF
30 * file if there is a mismatch.
31 */
32 #if BYTE_ORDER == LITTLE_ENDIAN
33 #define NATIVE_ELF_ENDIANNESS ELFDATA2LSB
34 #else
35 #define NATIVE_ELF_ENDIANNESS ELFDATA2MSB
36 #endif
37
38 /*
39 * The size in bytes of the debug link CRC as contained in an ELF
40 * section.
41 */
42 #define ELF_CRC_SIZE 4
43 /*
44 * ELF notes are aligned on 4 bytes. ref: ELF specification version
45 * 1.1 p. 2-5.
46 */
47 #define ELF_NOTE_ENTRY_ALIGN 4
48 /*
49 * Within an ELF note, the `desc` field is also aligned on 4
50 * bytes. ref: ELF specification version 1.1 p. 2-5.
51 */
52 #define ELF_NOTE_DESC_ALIGN 4
53
54 #define bswap(x) \
55 do { \
56 switch (sizeof(x)) { \
57 case 8: \
58 x = bswap_64(x); \
59 break; \
60 case 4: \
61 x = bswap_32(x); \
62 break; \
63 case 2: \
64 x = bswap_16(x); \
65 break; \
66 case 1: \
67 break; \
68 default: \
69 abort(); \
70 } \
71 } while (0)
72
73 #define bswap_phdr(phdr) \
74 do { \
75 bswap((phdr).p_type); \
76 bswap((phdr).p_offset); \
77 bswap((phdr).p_filesz); \
78 bswap((phdr).p_memsz); \
79 bswap((phdr).p_align); \
80 bswap((phdr).p_vaddr); \
81 } while (0)
82
83 #define bswap_shdr(shdr) \
84 do { \
85 bswap((shdr).sh_name); \
86 bswap((shdr).sh_type); \
87 bswap((shdr).sh_flags); \
88 bswap((shdr).sh_addr); \
89 bswap((shdr).sh_offset); \
90 bswap((shdr).sh_size); \
91 bswap((shdr).sh_link); \
92 bswap((shdr).sh_info); \
93 bswap((shdr).sh_addralign); \
94 bswap((shdr).sh_entsize); \
95 } while (0)
96
97 #define bswap_ehdr(ehdr) \
98 do { \
99 bswap((ehdr).e_type); \
100 bswap((ehdr).e_machine); \
101 bswap((ehdr).e_version); \
102 bswap((ehdr).e_entry); \
103 bswap((ehdr).e_phoff); \
104 bswap((ehdr).e_shoff); \
105 bswap((ehdr).e_flags); \
106 bswap((ehdr).e_ehsize); \
107 bswap((ehdr).e_phentsize); \
108 bswap((ehdr).e_phnum); \
109 bswap((ehdr).e_shentsize); \
110 bswap((ehdr).e_shnum); \
111 bswap((ehdr).e_shstrndx); \
112 } while (0)
113
114 #define copy_phdr(src_phdr, dst_phdr) \
115 do { \
116 (dst_phdr).p_type = (src_phdr).p_type; \
117 (dst_phdr).p_offset = (src_phdr).p_offset; \
118 (dst_phdr).p_filesz = (src_phdr).p_filesz; \
119 (dst_phdr).p_memsz = (src_phdr).p_memsz; \
120 (dst_phdr).p_align = (src_phdr).p_align; \
121 (dst_phdr).p_vaddr = (src_phdr).p_vaddr; \
122 } while (0)
123
124 #define copy_shdr(src_shdr, dst_shdr) \
125 do { \
126 (dst_shdr).sh_name = (src_shdr).sh_name; \
127 (dst_shdr).sh_type = (src_shdr).sh_type; \
128 (dst_shdr).sh_flags = (src_shdr).sh_flags; \
129 (dst_shdr).sh_addr = (src_shdr).sh_addr; \
130 (dst_shdr).sh_offset = (src_shdr).sh_offset; \
131 (dst_shdr).sh_size = (src_shdr).sh_size; \
132 (dst_shdr).sh_link = (src_shdr).sh_link; \
133 (dst_shdr).sh_info = (src_shdr).sh_info; \
134 (dst_shdr).sh_addralign = (src_shdr).sh_addralign; \
135 (dst_shdr).sh_entsize = (src_shdr).sh_entsize; \
136 } while (0)
137
138 #define copy_ehdr(src_ehdr, dst_ehdr) \
139 do { \
140 (dst_ehdr).e_type = (src_ehdr).e_type; \
141 (dst_ehdr).e_machine = (src_ehdr).e_machine; \
142 (dst_ehdr).e_version = (src_ehdr).e_version; \
143 (dst_ehdr).e_entry = (src_ehdr).e_entry; \
144 (dst_ehdr).e_phoff = (src_ehdr).e_phoff; \
145 (dst_ehdr).e_shoff = (src_ehdr).e_shoff; \
146 (dst_ehdr).e_flags = (src_ehdr).e_flags; \
147 (dst_ehdr).e_ehsize = (src_ehdr).e_ehsize; \
148 (dst_ehdr).e_phentsize = (src_ehdr).e_phentsize; \
149 (dst_ehdr).e_phnum = (src_ehdr).e_phnum; \
150 (dst_ehdr).e_shentsize = (src_ehdr).e_shentsize; \
151 (dst_ehdr).e_shnum = (src_ehdr).e_shnum; \
152 (dst_ehdr).e_shstrndx = (src_ehdr).e_shstrndx; \
153 } while (0)
154
155 struct lttng_ust_elf_ehdr {
156 uint16_t e_type;
157 uint16_t e_machine;
158 uint32_t e_version;
159 uint64_t e_entry;
160 uint64_t e_phoff;
161 uint64_t e_shoff;
162 uint32_t e_flags;
163 uint16_t e_ehsize;
164 uint16_t e_phentsize;
165 uint16_t e_phnum;
166 uint16_t e_shentsize;
167 uint16_t e_shnum;
168 uint16_t e_shstrndx;
169 };
170
171 struct lttng_ust_elf_phdr {
172 uint32_t p_type;
173 uint64_t p_offset;
174 uint64_t p_filesz;
175 uint64_t p_memsz;
176 uint64_t p_align;
177 uint64_t p_vaddr;
178 };
179
180 struct lttng_ust_elf_shdr {
181 uint32_t sh_name;
182 uint32_t sh_type;
183 uint64_t sh_flags;
184 uint64_t sh_addr;
185 uint64_t sh_offset;
186 uint64_t sh_size;
187 uint32_t sh_link;
188 uint32_t sh_info;
189 uint64_t sh_addralign;
190 uint64_t sh_entsize;
191 };
192
193 struct lttng_ust_elf_nhdr {
194 uint32_t n_namesz;
195 uint32_t n_descsz;
196 uint32_t n_type;
197 };
198
199 struct lttng_ust_elf {
200 /* Offset in bytes to start of section names string table. */
201 off_t section_names_offset;
202 /* Size in bytes of section names string table. */
203 size_t section_names_size;
204 char *path;
205 int fd;
206 struct lttng_ust_elf_ehdr *ehdr;
207 uint8_t bitness;
208 uint8_t endianness;
209 };
210
211 static inline
212 int is_elf_32_bit(struct lttng_ust_elf *elf)
213 {
214 return elf->bitness == ELFCLASS32;
215 }
216
217 static inline
218 int is_elf_native_endian(struct lttng_ust_elf *elf)
219 {
220 return elf->endianness == NATIVE_ELF_ENDIANNESS;
221 }
222
223 struct lttng_ust_elf *lttng_ust_elf_create(const char *path);
224 void lttng_ust_elf_destroy(struct lttng_ust_elf *elf);
225 uint8_t lttng_ust_elf_is_pic(struct lttng_ust_elf *elf);
226 int lttng_ust_elf_get_memsz(struct lttng_ust_elf *elf, uint64_t *memsz);
227 int lttng_ust_elf_get_build_id(struct lttng_ust_elf *elf, uint8_t **build_id,
228 size_t *length, int *found);
229 int lttng_ust_elf_get_debug_link(struct lttng_ust_elf *elf, char **filename,
230 uint32_t *crc, int *found);
231
232 #endif /* _LTTNG_UST_ELF_H */
This page took 0.034518 seconds and 5 git commands to generate.