Bug Summary

File:util/cbfstool/elfheaders.c
Warning:line 990, column 18
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name elfheaders.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild -resource-dir /opt/xgcc/lib/clang/17 -include /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/bsd/include/commonlib/bsd/compiler.h -include /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/bsd/include/commonlib/bsd/compiler.h -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _SVID_SOURCE -D _GNU_SOURCE -I /home/coreboot/node-root/workspace/coreboot_scanbuild/util/cbfstool/flashmap -I /home/coreboot/node-root/workspace/coreboot_scanbuild/util/cbfstool -I /cb-build/coreboot_scanbuild.0/sharedutils/cbfstool -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/include -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src/commonlib/bsd/include -I 3rdparty/vboot/firmware/include -I 3rdparty/vboot/firmware/2lib/include -I 3rdparty/vboot/host/include -I 3rdparty/vboot/host/lib/include -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src -I /home/coreboot/node-root/workspace/coreboot_scanbuild/src/vendorcode/intel/edk2/uefi_2.4/MdePkg/Include -internal-isystem /opt/xgcc/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -source-date-epoch 1714465709 -O2 -Wwrite-strings -std=c11 -fconst-strings -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /cb-build/coreboot_scanbuild.0/sharedutils-scanbuildtmp/2024-05-02-073004-2299942-1 -x c /home/coreboot/node-root/workspace/coreboot_scanbuild/util/cbfstool/elfheaders.c
1/* elf header parsing */
2/* SPDX-License-Identifier: GPL-2.0-only */
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8#include "elfparsing.h"
9#include "common.h"
10#include "cbfs.h"
11
12/*
13 * Short form: this is complicated, but we've tried making it simple
14 * and we keep hitting problems with our ELF parsing.
15 *
16 * The ELF parsing situation has always been a bit tricky. In fact,
17 * we (and most others) have been getting it wrong in small ways for
18 * years. Recently this has caused real trouble for the ARM V8 build.
19 * In this file we attempt to finally get it right for all variations
20 * of endian-ness and word size and target architectures and
21 * architectures we might get run on. Phew!. To do this we borrow a
22 * page from the FreeBSD NFS xdr model (see elf_ehdr and elf_phdr),
23 * the Plan 9 endianness functions (see xdr.c), and Go interfaces (see
24 * how we use buffer structs in this file). This ends up being a bit
25 * wordy at the lowest level, but greatly simplifies the elf parsing
26 * code and removes a common source of bugs, namely, forgetting to
27 * flip type endianness when referencing a struct member.
28 *
29 * ELF files can have four combinations of data layout: 32/64, and
30 * big/little endian. Further, to add to the fun, depending on the
31 * word size, the size of the ELF structs varies. The coreboot SELF
32 * format is simpler in theory: it's supposed to be always BE, and the
33 * various struct members allow room for growth: the entry point is
34 * always 64 bits, for example, so the size of a SELF struct is
35 * constant, regardless of target architecture word size. Hence, we
36 * need to do some transformation of the ELF files.
37 *
38 * A given architecture, realistically, only supports one of the four
39 * combinations at a time as the 'native' format. Hence, our code has
40 * been sprinkled with every variation of [nh]to[hn][sll] over the
41 * years. We've never quite gotten it all right, however, and a quick
42 * pass over this code revealed another bug. It's all worked because,
43 * until now, all the working platforms that had CBFS were 32 LE. Even then,
44 * however, bugs crept in: we recently realized that we're not
45 * transforming the entry point to big format when we store into the
46 * SELF image.
47 *
48 * The problem is essentially an XDR operation:
49 * we have something in a foreign format and need to transform it.
50 * It's most like XDR because:
51 * 1) the byte order can be wrong
52 * 2) the word size can be wrong
53 * 3) the size of elements in the stream depends on the value
54 * of other elements in the stream
55 * it's not like XDR because:
56 * 1) the byte order can be right
57 * 2) the word size can be right
58 * 3) the struct members are all on a natural alignment
59 *
60 * Hence, this new approach. To cover word size issues, we *always*
61 * transform the two structs we care about, the file header and
62 * program header, into a native struct in the 64 bit format:
63 *
64 * [32,little] -> [Elf64_Ehdr, Elf64_Phdr]
65 * [64,little] -> [Elf64_Ehdr, Elf64_Phdr]
66 * [32,big] -> [Elf64_Ehdr, Elf64_Phdr]
67 * [64,big] -> [Elf64_Ehdr, Elf64_Phdr]
68 * Then we just use those structs, and all the need for inline ntoh* goes away,
69 * as well as all the chances for error.
70 * This works because all the SELF structs have fields large enough for
71 * the largest ELF 64 struct members, and all the Elf64 struct members
72 * are at least large enough for all ELF 32 struct members.
73 * We end up with one function to do all our ELF parsing, and two functions
74 * to transform the headers. For the put case, we also have
75 * XDR functions, and hopefully we'll never again spend 5 years with the
76 * wrong endian-ness on an output value :-)
77 * This should work for all word sizes and endianness we hope to target.
78 * I *really* don't want to be here for 128 bit addresses.
79 *
80 * The parse functions are called with a pointer to an input buffer
81 * struct. One might ask: are there enough bytes in the input buffer?
82 * We know there need to be at *least* sizeof(Elf32_Ehdr) +
83 * sizeof(Elf32_Phdr) bytes. Realistically, there has to be some data
84 * too. If we start to worry, though we have not in the past, we
85 * might apply the simple test: the input buffer needs to be at least
86 * sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) bytes because, even if it's
87 * ELF 32, there's got to be *some* data! This is not theoretically
88 * accurate but it is actually good enough in practice. It allows the
89 * header transformation code to ignore the possibility of underrun.
90 *
91 * We also must accommodate different ELF files, and hence formats,
92 * in the same cbfs invocation. We might load a 64-bit payload
93 * on a 32-bit machine; we might even have a mixed armv7/armv8
94 * SOC or even a system with an x86/ARM!
95 *
96 * A possibly problematic (though unlikely to be so) assumption
97 * is that we expect the BIOS to remain in the lowest 32 bits
98 * of the physical address space. Since ARMV8 has standardized
99 * on that, and x86_64 also has, this seems a safe assumption.
100 *
101 * To repeat, ELF structs are different sizes because ELF struct
102 * members are different sizes, depending on values in the ELF file
103 * header. For this we use the functions defined in xdr.c, which
104 * consume bytes, convert the endianness, and advance the data pointer
105 * in the buffer struct.
106 */
107
108
109static int iself(const void *input)
110{
111 const Elf32_Ehdr *ehdr = input;
112 return !memcmp(ehdr->e_ident, ELFMAG"\177ELF", 4);
113}
114
115/* Get the ident array, so we can figure out
116 * endian-ness, word size, and in future other useful
117 * parameters
118 */
119static void
120elf_eident(struct buffer *input, Elf64_Ehdr *ehdr)
121{
122 bgets(input, ehdr->e_ident, sizeof(ehdr->e_ident));
123}
124
125
126static int
127check_size(const struct buffer *b, size_t offset, size_t size, const char *desc)
128{
129 if (size == 0)
130 return 0;
131
132 if (offset >= buffer_size(b) || (offset + size) > buffer_size(b)) {
133 ERROR("The file is not large enough for the '%s'. "fprintf(stderr, "E: " "The file is not large enough for the '%s'. "
"%zu bytes @ offset %zu, input %zu bytes.\n", desc, size, offset
, buffer_size(b))
134 "%zu bytes @ offset %zu, input %zu bytes.\n",fprintf(stderr, "E: " "The file is not large enough for the '%s'. "
"%zu bytes @ offset %zu, input %zu bytes.\n", desc, size, offset
, buffer_size(b))
135 desc, size, offset, buffer_size(b))fprintf(stderr, "E: " "The file is not large enough for the '%s'. "
"%zu bytes @ offset %zu, input %zu bytes.\n", desc, size, offset
, buffer_size(b))
;
136 return -1;
137 }
138 return 0;
139}
140
141static void
142elf_ehdr(struct buffer *input, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64)
143{
144 ehdr->e_type = xdr->get16(input);
145 ehdr->e_machine = xdr->get16(input);
146 ehdr->e_version = xdr->get32(input);
147 if (bit64){
148 ehdr->e_entry = xdr->get64(input);
149 ehdr->e_phoff = xdr->get64(input);
150 ehdr->e_shoff = xdr->get64(input);
151 } else {
152 ehdr->e_entry = xdr->get32(input);
153 ehdr->e_phoff = xdr->get32(input);
154 ehdr->e_shoff = xdr->get32(input);
155 }
156 ehdr->e_flags = xdr->get32(input);
157 ehdr->e_ehsize = xdr->get16(input);
158 ehdr->e_phentsize = xdr->get16(input);
159 ehdr->e_phnum = xdr->get16(input);
160 ehdr->e_shentsize = xdr->get16(input);
161 ehdr->e_shnum = xdr->get16(input);
162 ehdr->e_shstrndx = xdr->get16(input);
163}
164
165static void
166elf_phdr(struct buffer *pinput, Elf64_Phdr *phdr,
167 int entsize, struct xdr *xdr, int bit64)
168{
169 /*
170 * The entsize need not be sizeof(*phdr).
171 * Hence, it is easier to keep a copy of the input,
172 * as the xdr functions may not advance the input
173 * pointer the full entsize; rather than get tricky
174 * we just advance it below.
175 */
176 struct buffer input;
177 buffer_clone(&input, pinput);
178 if (bit64){
179 phdr->p_type = xdr->get32(&input);
180 phdr->p_flags = xdr->get32(&input);
181 phdr->p_offset = xdr->get64(&input);
182 phdr->p_vaddr = xdr->get64(&input);
183 phdr->p_paddr = xdr->get64(&input);
184 phdr->p_filesz = xdr->get64(&input);
185 phdr->p_memsz = xdr->get64(&input);
186 phdr->p_align = xdr->get64(&input);
187 } else {
188 phdr->p_type = xdr->get32(&input);
189 phdr->p_offset = xdr->get32(&input);
190 phdr->p_vaddr = xdr->get32(&input);
191 phdr->p_paddr = xdr->get32(&input);
192 phdr->p_filesz = xdr->get32(&input);
193 phdr->p_memsz = xdr->get32(&input);
194 phdr->p_flags = xdr->get32(&input);
195 phdr->p_align = xdr->get32(&input);
196 }
197 buffer_seek(pinput, entsize);
198}
199
200static void
201elf_shdr(struct buffer *pinput, Elf64_Shdr *shdr,
202 int entsize, struct xdr *xdr, int bit64)
203{
204 /*
205 * The entsize need not be sizeof(*shdr).
206 * Hence, it is easier to keep a copy of the input,
207 * as the xdr functions may not advance the input
208 * pointer the full entsize; rather than get tricky
209 * we just advance it below.
210 */
211 struct buffer input = *pinput;
212 if (bit64){
213 shdr->sh_name = xdr->get32(&input);
214 shdr->sh_type = xdr->get32(&input);
215 shdr->sh_flags = xdr->get64(&input);
216 shdr->sh_addr = xdr->get64(&input);
217 shdr->sh_offset = xdr->get64(&input);
218 shdr->sh_size= xdr->get64(&input);
219 shdr->sh_link = xdr->get32(&input);
220 shdr->sh_info = xdr->get32(&input);
221 shdr->sh_addralign = xdr->get64(&input);
222 shdr->sh_entsize = xdr->get64(&input);
223 } else {
224 shdr->sh_name = xdr->get32(&input);
225 shdr->sh_type = xdr->get32(&input);
226 shdr->sh_flags = xdr->get32(&input);
227 shdr->sh_addr = xdr->get32(&input);
228 shdr->sh_offset = xdr->get32(&input);
229 shdr->sh_size = xdr->get32(&input);
230 shdr->sh_link = xdr->get32(&input);
231 shdr->sh_info = xdr->get32(&input);
232 shdr->sh_addralign = xdr->get32(&input);
233 shdr->sh_entsize = xdr->get32(&input);
234 }
235 buffer_seek(pinput, entsize);
236}
237
238static int
239phdr_read(const struct buffer *in, struct parsed_elf *pelf,
240 struct xdr *xdr, int bit64)
241{
242 struct buffer b;
243 Elf64_Phdr *phdr;
244 Elf64_Ehdr *ehdr;
245 int i;
246
247 ehdr = &pelf->ehdr;
248 /* cons up an input buffer for the headers.
249 * Note that the program headers can be anywhere,
250 * per the ELF spec, You'd be surprised how many ELF
251 * readers miss this little detail.
252 */
253 buffer_splice(&b, in, ehdr->e_phoff,
254 (uint32_t)ehdr->e_phentsize * ehdr->e_phnum);
255 if (check_size(in, ehdr->e_phoff, buffer_size(&b), "program headers"))
256 return -1;
257
258 /* gather up all the phdrs.
259 * We do them all at once because there is more
260 * than one loop over all the phdrs.
261 */
262 phdr = calloc(ehdr->e_phnum, sizeof(*phdr));
263 for (i = 0; i < ehdr->e_phnum; i++) {
264 DEBUG("Parsing segment %d\n", i)do { if (verbose > 1) fprintf(stderr, "DEBUG: " "Parsing segment %d\n"
, i); } while (0)
;
265 elf_phdr(&b, &phdr[i], ehdr->e_phentsize, xdr, bit64);
266
267 /* Ensure the contents are valid within the elf file. */
268 if (check_size(in, phdr[i].p_offset, phdr[i].p_filesz,
269 "segment contents")) {
270 free(phdr);
271 return -1;
272 }
273 }
274
275 pelf->phdr = phdr;
276
277 return 0;
278}
279
280static int
281shdr_read(const struct buffer *in, struct parsed_elf *pelf,
282 struct xdr *xdr, int bit64)
283{
284 struct buffer b;
285 Elf64_Shdr *shdr;
286 Elf64_Ehdr *ehdr;
287 int i;
288
289 ehdr = &pelf->ehdr;
290
291 /* cons up an input buffer for the section headers.
292 * Note that the section headers can be anywhere,
293 * per the ELF spec, You'd be surprised how many ELF
294 * readers miss this little detail.
295 */
296 buffer_splice(&b, in, ehdr->e_shoff,
297 (uint32_t)ehdr->e_shentsize * ehdr->e_shnum);
298 if (check_size(in, ehdr->e_shoff, buffer_size(&b), "section headers"))
299 return -1;
300
301 /* gather up all the shdrs. */
302 shdr = calloc(ehdr->e_shnum, sizeof(*shdr));
303 for (i = 0; i < ehdr->e_shnum; i++) {
304 DEBUG("Parsing section %d\n", i)do { if (verbose > 1) fprintf(stderr, "DEBUG: " "Parsing section %d\n"
, i); } while (0)
;
305 elf_shdr(&b, &shdr[i], ehdr->e_shentsize, xdr, bit64);
306 }
307
308 pelf->shdr = shdr;
309
310 return 0;
311}
312
313static int
314reloc_read(const struct buffer *in, struct parsed_elf *pelf,
315 struct xdr *xdr, int bit64)
316{
317 struct buffer b;
318 Elf64_Word i;
319 Elf64_Ehdr *ehdr;
320
321 ehdr = &pelf->ehdr;
322 pelf->relocs = calloc(ehdr->e_shnum, sizeof(Elf64_Rela *));
323
324 /* Allocate array for each section that contains relocation entries. */
325 for (i = 0; i < ehdr->e_shnum; i++) {
326 Elf64_Shdr *shdr;
327 Elf64_Rela *rela;
328 Elf64_Xword j;
329 Elf64_Xword nrelocs;
330 int is_rela;
331
332 shdr = &pelf->shdr[i];
333
334 /* Only process REL and RELA sections. */
335 if (shdr->sh_type != SHT_REL9 && shdr->sh_type != SHT_RELA4)
336 continue;
337
338 DEBUG("Checking relocation section %u\n", i)do { if (verbose > 1) fprintf(stderr, "DEBUG: " "Checking relocation section %u\n"
, i); } while (0)
;
339
340 /* Ensure the section that relocations apply is a valid. */
341 if (shdr->sh_info >= ehdr->e_shnum ||
342 shdr->sh_info == SHN_UNDEF0) {
343 ERROR("Relocations apply to an invalid section: %u\n",fprintf(stderr, "E: " "Relocations apply to an invalid section: %u\n"
, shdr[i].sh_info)
344 shdr[i].sh_info)fprintf(stderr, "E: " "Relocations apply to an invalid section: %u\n"
, shdr[i].sh_info)
;
345 return -1;
346 }
347
348 is_rela = shdr->sh_type == SHT_RELA4;
349
350 /* Determine the number relocations in this section. */
351 nrelocs = shdr->sh_size / shdr->sh_entsize;
352
353 pelf->relocs[i] = calloc(nrelocs, sizeof(Elf64_Rela));
354
355 buffer_splice(&b, in, shdr->sh_offset, shdr->sh_size);
356 if (check_size(in, shdr->sh_offset, buffer_size(&b),
357 "relocation section")) {
358 ERROR("Relocation section %u failed.\n", i)fprintf(stderr, "E: " "Relocation section %u failed.\n", i);
359 return -1;
360 }
361
362 rela = pelf->relocs[i];
363 for (j = 0; j < nrelocs; j++) {
364 if (bit64) {
365 rela->r_offset = xdr->get64(&b);
366 rela->r_info = xdr->get64(&b);
367 if (is_rela)
368 rela->r_addend = xdr->get64(&b);
369 } else {
370 uint32_t r_info;
371
372 rela->r_offset = xdr->get32(&b);
373 r_info = xdr->get32(&b);
374 rela->r_info = ELF64_R_INFO(ELF32_R_SYM(r_info),((((Elf64_Xword) (((r_info) >> 8))) << 32) + (((r_info
) & 0xff)))
375 ELF32_R_TYPE(r_info))((((Elf64_Xword) (((r_info) >> 8))) << 32) + (((r_info
) & 0xff)))
;
376 if (is_rela)
377 rela->r_addend = xdr->get32(&b);
378 }
379 rela++;
380 }
381 }
382
383 return 0;
384}
385
386static int strtab_read(const struct buffer *in, struct parsed_elf *pelf)
387{
388 Elf64_Ehdr *ehdr;
389 Elf64_Word i;
390
391 ehdr = &pelf->ehdr;
392
393 if (ehdr->e_shstrndx >= ehdr->e_shnum) {
394 ERROR("Section header string table index out of range: %d\n",fprintf(stderr, "E: " "Section header string table index out of range: %d\n"
, ehdr->e_shstrndx)
395 ehdr->e_shstrndx)fprintf(stderr, "E: " "Section header string table index out of range: %d\n"
, ehdr->e_shstrndx)
;
396 return -1;
397 }
398
399 /* For each section of type SHT_STRTAB create a symtab buffer. */
400 pelf->strtabs = calloc(ehdr->e_shnum, sizeof(struct buffer *));
401
402 for (i = 0; i < ehdr->e_shnum; i++) {
403 struct buffer *b;
404 Elf64_Shdr *shdr = &pelf->shdr[i];
405
406 if (shdr->sh_type != SHT_STRTAB3)
407 continue;
408
409 b = calloc(1, sizeof(*b));
410 buffer_splice(b, in, shdr->sh_offset, shdr->sh_size);
411 if (check_size(in, shdr->sh_offset, buffer_size(b), "strtab")) {
412 ERROR("STRTAB section not within bounds: %d\n", i)fprintf(stderr, "E: " "STRTAB section not within bounds: %d\n"
, i)
;
413 free(b);
414 return -1;
415 }
416 pelf->strtabs[i] = b;
417 }
418
419 return 0;
420}
421
422static int
423symtab_read(const struct buffer *in, struct parsed_elf *pelf,
424 struct xdr *xdr, int bit64)
425{
426 Elf64_Ehdr *ehdr;
427 Elf64_Shdr *shdr;
428 Elf64_Half shnum;
429 Elf64_Xword i;
430 Elf64_Xword nsyms;
431 Elf64_Sym *sym;
432 struct buffer b;
433
434 ehdr = &pelf->ehdr;
435
436 shdr = NULL((void*)0);
437 for (shnum = 0; shnum < ehdr->e_shnum; shnum++) {
438 if (pelf->shdr[shnum].sh_type != SHT_SYMTAB2)
439 continue;
440
441 if (shdr != NULL((void*)0)) {
442 ERROR("Multiple symbol sections found. %u and %u\n",fprintf(stderr, "E: " "Multiple symbol sections found. %u and %u\n"
, (unsigned int)(shdr - pelf->shdr), shnum)
443 (unsigned int)(shdr - pelf->shdr), shnum)fprintf(stderr, "E: " "Multiple symbol sections found. %u and %u\n"
, (unsigned int)(shdr - pelf->shdr), shnum)
;
444 return -1;
445 }
446
447 shdr = &pelf->shdr[shnum];
448 }
449
450 if (shdr == NULL((void*)0)) {
451 ERROR("No symbol table found.\n")fprintf(stderr, "E: " "No symbol table found.\n");
452 return -1;
453 }
454
455 buffer_splice(&b, in, shdr->sh_offset, shdr->sh_size);
456 if (check_size(in, shdr->sh_offset, buffer_size(&b), "symtab"))
457 return -1;
458
459 nsyms = shdr->sh_size / shdr->sh_entsize;
460
461 pelf->syms = calloc(nsyms, sizeof(Elf64_Sym));
462
463 for (i = 0; i < nsyms; i++) {
464 sym = &pelf->syms[i];
465
466 if (bit64) {
467 sym->st_name = xdr->get32(&b);
468 sym->st_info = xdr->get8(&b);
469 sym->st_other = xdr->get8(&b);
470 sym->st_shndx = xdr->get16(&b);
471 sym->st_value = xdr->get64(&b);
472 sym->st_size = xdr->get64(&b);
473 } else {
474 sym->st_name = xdr->get32(&b);
475 sym->st_value = xdr->get32(&b);
476 sym->st_size = xdr->get32(&b);
477 sym->st_info = xdr->get8(&b);
478 sym->st_other = xdr->get8(&b);
479 sym->st_shndx = xdr->get16(&b);
480 }
481 }
482
483 return 0;
484}
485
486int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
487{
488 struct xdr *xdr = &xdr_le;
489 int bit64 = 0;
490 struct buffer input;
491 Elf64_Ehdr *ehdr;
492
493 /* Zero out the parsed elf structure. */
494 memset(pelf, 0, sizeof(*pelf));
495
496 if (!iself(buffer_get(pinput))) {
497 DEBUG("The stage file is not in ELF format!\n")do { if (verbose > 1) fprintf(stderr, "DEBUG: " "The stage file is not in ELF format!\n"
); } while (0)
;
498 return -1;
499 }
500
501 buffer_clone(&input, pinput);
502 ehdr = &pelf->ehdr;
503 elf_eident(&input, ehdr);
504 bit64 = ehdr->e_ident[EI_CLASS4] == ELFCLASS642;
505 /* Assume LE unless we are sure otherwise.
506 * We're not going to take on the task of
507 * fully validating the ELF file. That way
508 * lies madness.
509 */
510 if (ehdr->e_ident[EI_DATA5] == ELFDATA2MSB2)
511 xdr = &xdr_be;
512
513 elf_ehdr(&input, ehdr, xdr, bit64);
514
515 /* Relocation processing requires section header parsing. */
516 if (flags & ELF_PARSE_RELOC(1 << 2))
517 flags |= ELF_PARSE_SHDR(1 << 1);
518
519 /* String table processing requires section header parsing. */
520 if (flags & ELF_PARSE_STRTAB(1 << 3))
521 flags |= ELF_PARSE_SHDR(1 << 1);
522
523 /* Symbole table processing requires section header parsing. */
524 if (flags & ELF_PARSE_SYMTAB(1 << 4))
525 flags |= ELF_PARSE_SHDR(1 << 1);
526
527 if ((flags & ELF_PARSE_PHDR(1 << 0)) && phdr_read(pinput, pelf, xdr, bit64))
528 goto fail;
529
530 if ((flags & ELF_PARSE_SHDR(1 << 1)) && shdr_read(pinput, pelf, xdr, bit64))
531 goto fail;
532
533 if ((flags & ELF_PARSE_RELOC(1 << 2)) && reloc_read(pinput, pelf, xdr, bit64))
534 goto fail;
535
536 if ((flags & ELF_PARSE_STRTAB(1 << 3)) && strtab_read(pinput, pelf))
537 goto fail;
538
539 if ((flags & ELF_PARSE_SYMTAB(1 << 4)) && symtab_read(pinput, pelf, xdr, bit64))
540 goto fail;
541
542 return 0;
543
544fail:
545 parsed_elf_destroy(pelf);
546 return -1;
547}
548
549void parsed_elf_destroy(struct parsed_elf *pelf)
550{
551 Elf64_Half i;
552
553 free(pelf->phdr);
554 free(pelf->shdr);
555 if (pelf->relocs != NULL((void*)0)) {
556 for (i = 0; i < pelf->ehdr.e_shnum; i++)
557 free(pelf->relocs[i]);
558 }
559 free(pelf->relocs);
560
561 if (pelf->strtabs != NULL((void*)0)) {
562 for (i = 0; i < pelf->ehdr.e_shnum; i++)
563 free(pelf->strtabs[i]);
564 }
565 free(pelf->strtabs);
566 free(pelf->syms);
567}
568
569/* Get the headers from the buffer.
570 * Return -1 in the event of an error.
571 * The section headers are optional; if NULL
572 * is passed in for pshdr they won't be parsed.
573 * We don't (yet) make payload parsing optional
574 * because we've never seen a use case.
575 */
576int
577elf_headers(const struct buffer *pinput,
578 Elf64_Ehdr *ehdr,
579 Elf64_Phdr **pphdr,
580 Elf64_Shdr **pshdr)
581{
582 struct parsed_elf pelf;
583 int flags;
584
585 flags = ELF_PARSE_PHDR(1 << 0);
586
587 if (pshdr != NULL((void*)0))
588 flags |= ELF_PARSE_SHDR(1 << 1);
589
590 if (parse_elf(pinput, &pelf, flags))
591 return -1;
592
593 /* Copy out the parsed elf header. */
594 memcpy(ehdr, &pelf.ehdr, sizeof(*ehdr));
595
596 *pphdr = calloc(ehdr->e_phnum, sizeof(Elf64_Phdr));
597 memcpy(*pphdr, pelf.phdr, ehdr->e_phnum * sizeof(Elf64_Phdr));
598
599 if (pshdr != NULL((void*)0)) {
600 *pshdr = calloc(ehdr->e_shnum, sizeof(Elf64_Shdr));
601 memcpy(*pshdr, pelf.shdr, ehdr->e_shnum * sizeof(Elf64_Shdr));
602 }
603
604 parsed_elf_destroy(&pelf);
605
606 return 0;
607}
608
609/* ELF Writing Support
610 *
611 * The ELF file is written according to the following layout:
612 * +------------------+
613 * | ELF Header |
614 * +------------------+
615 * | Section Headers |
616 * +------------------+
617 * | Program Headers |
618 * +------------------+
619 * | String table |
620 * +------------------+ <- 4KiB Aligned
621 * | Code/Data |
622 * +------------------+
623 */
624
625void elf_init_eheader(Elf64_Ehdr *ehdr, int machine, int nbits, int endian)
626{
627 memset(ehdr, 0, sizeof(*ehdr));
628 ehdr->e_ident[EI_MAG00] = ELFMAG00x7f;
629 ehdr->e_ident[EI_MAG11] = ELFMAG1'E';
630 ehdr->e_ident[EI_MAG22] = ELFMAG2'L';
631 ehdr->e_ident[EI_MAG33] = ELFMAG3'F';
632 ehdr->e_ident[EI_CLASS4] = nbits;
633 ehdr->e_ident[EI_DATA5] = endian;
634 ehdr->e_ident[EI_VERSION6] = EV_CURRENT1;
635 ehdr->e_type = ET_EXEC2;
636 ehdr->e_machine = machine;
637 ehdr->e_version = EV_CURRENT1;
638 if (nbits == ELFCLASS642) {
639 ehdr->e_ehsize = sizeof(Elf64_Ehdr);
640 ehdr->e_phentsize = sizeof(Elf64_Phdr);
641 ehdr->e_shentsize = sizeof(Elf64_Shdr);
642 } else {
643 ehdr->e_ehsize = sizeof(Elf32_Ehdr);
644 ehdr->e_phentsize = sizeof(Elf32_Phdr);
645 ehdr->e_shentsize = sizeof(Elf32_Shdr);
646 }
647}
648
649/* Arbitrary maximum number of sections. */
650#define MAX_SECTIONS16 16
651struct elf_writer_section {
652 Elf64_Shdr shdr;
653 struct buffer content;
654 const char *name;
655};
656
657struct elf_writer_string_table {
658 size_t next_offset;
659 size_t max_size;
660 char *buffer;
661};
662
663struct elf_writer_sym_table {
664 size_t max_entries;
665 size_t num_entries;
666 Elf64_Sym *syms;
667};
668
669#define MAX_REL_NAME32 32
670struct elf_writer_rel {
671 size_t num_entries;
672 size_t max_entries;
673 Elf64_Rel *rels;
674 struct elf_writer_section *sec;
675 char name[MAX_REL_NAME32];
676};
677
678struct elf_writer
679{
680 Elf64_Ehdr ehdr;
681 struct xdr *xdr;
682 size_t num_secs;
683 struct elf_writer_section sections[MAX_SECTIONS16];
684 struct elf_writer_rel rel_sections[MAX_SECTIONS16];
685 Elf64_Phdr *phdrs;
686 struct elf_writer_section *shstrtab_sec;
687 struct elf_writer_section *strtab_sec;
688 struct elf_writer_section *symtab_sec;
689 struct elf_writer_string_table strtab;
690 struct elf_writer_sym_table symtab;
691 int bit64;
692};
693
694static size_t section_index(struct elf_writer *ew,
695 struct elf_writer_section *sec)
696{
697 return sec - &ew->sections[0];
698}
699
700static struct elf_writer_section *last_section(struct elf_writer *ew)
701{
702 return &ew->sections[ew->num_secs - 1];
703}
704
705static void strtab_init(struct elf_writer *ew, size_t size)
706{
707 struct buffer b;
708 Elf64_Shdr shdr;
709
710 /* Start adding strings after the initial NUL entry. */
711 ew->strtab.next_offset = 1;
712 ew->strtab.max_size = size;
713 ew->strtab.buffer = calloc(1, ew->strtab.max_size);
714
715 buffer_init(&b, NULL((void*)0), ew->strtab.buffer, ew->strtab.max_size);
716 memset(&shdr, 0, sizeof(shdr));
717 shdr.sh_type = SHT_STRTAB3;
718 shdr.sh_addralign = 1;
719 shdr.sh_size = ew->strtab.max_size;
720 elf_writer_add_section(ew, &shdr, &b, ".strtab");
721 ew->strtab_sec = last_section(ew);
722}
723
724static void symtab_init(struct elf_writer *ew, size_t max_entries)
725{
726 struct buffer b;
727 Elf64_Shdr shdr;
728
729 memset(&shdr, 0, sizeof(shdr));
730 shdr.sh_type = SHT_SYMTAB2;
731
732 if (ew->bit64) {
733 shdr.sh_entsize = sizeof(Elf64_Sym);
734 shdr.sh_addralign = sizeof(Elf64_Addr);
735 } else {
736 shdr.sh_entsize = sizeof(Elf32_Sym);
737 shdr.sh_addralign = sizeof(Elf32_Addr);
738 }
739
740 shdr.sh_size = shdr.sh_entsize * max_entries;
741
742 ew->symtab.syms = calloc(max_entries, sizeof(Elf64_Sym));
743 ew->symtab.num_entries = 1;
744 ew->symtab.max_entries = max_entries;
745
746 buffer_init(&b, NULL((void*)0), ew->symtab.syms, shdr.sh_size);
747
748 elf_writer_add_section(ew, &shdr, &b, ".symtab");
749 ew->symtab_sec = last_section(ew);
750}
751
752struct elf_writer *elf_writer_init(const Elf64_Ehdr *ehdr)
753{
754 struct elf_writer *ew;
755 Elf64_Shdr shdr;
756 struct buffer empty_buffer;
757
758 if (!iself(ehdr))
759 return NULL((void*)0);
760
761 ew = calloc(1, sizeof(*ew));
762
763 memcpy(&ew->ehdr, ehdr, sizeof(ew->ehdr));
764
765 ew->bit64 = ew->ehdr.e_ident[EI_CLASS4] == ELFCLASS642;
766
767 /* Set the endinan ops. */
768 if (ew->ehdr.e_ident[EI_DATA5] == ELFDATA2MSB2)
769 ew->xdr = &xdr_be;
770 else
771 ew->xdr = &xdr_le;
772
773 /* Reset count and offsets */
774 ew->ehdr.e_phoff = 0;
775 ew->ehdr.e_shoff = 0;
776 ew->ehdr.e_shnum = 0;
777 ew->ehdr.e_phnum = 0;
778
779 memset(&empty_buffer, 0, sizeof(empty_buffer));
780 memset(&shdr, 0, sizeof(shdr));
781
782 /* Add SHT_NULL section header. */
783 shdr.sh_type = SHT_NULL0;
784 elf_writer_add_section(ew, &shdr, &empty_buffer, NULL((void*)0));
785
786 /* Add section header string table and maintain reference to it. */
787 shdr.sh_type = SHT_STRTAB3;
788 elf_writer_add_section(ew, &shdr, &empty_buffer, ".shstrtab");
789 ew->shstrtab_sec = last_section(ew);
790 ew->ehdr.e_shstrndx = section_index(ew, ew->shstrtab_sec);
791
792 /* Add a small string table and symbol table. */
793 strtab_init(ew, 4096);
794 symtab_init(ew, 100);
795
796 return ew;
797}
798
799/*
800 * Clean up any internal state represented by ew. Aftewards the elf_writer
801 * is invalid.
802 * It is safe to call elf_writer_destroy with ew as NULL. It returns without
803 * performing any action.
804 */
805void elf_writer_destroy(struct elf_writer *ew)
806{
807 int i;
808 if (ew == NULL((void*)0))
809 return;
810 if (ew->phdrs != NULL((void*)0))
811 free(ew->phdrs);
812 free(ew->strtab.buffer);
813 free(ew->symtab.syms);
814 for (i = 0; i < MAX_SECTIONS16; i++)
815 free(ew->rel_sections[i].rels);
816 free(ew);
817}
818
819/*
820 * Add a section to the ELF file. Section type, flags, and memsize are
821 * maintained from the passed in Elf64_Shdr. The buffer represents the
822 * content of the section while the name is the name of section itself.
823 * Returns < 0 on error, 0 on success.
824 */
825int elf_writer_add_section(struct elf_writer *ew, const Elf64_Shdr *shdr,
826 struct buffer *contents, const char *name)
827{
828 struct elf_writer_section *newsh;
829
830 if (ew->num_secs == MAX_SECTIONS16)
831 return -1;
832
833 newsh = &ew->sections[ew->num_secs];
834 ew->num_secs++;
835
836 memcpy(&newsh->shdr, shdr, sizeof(newsh->shdr));
837 newsh->shdr.sh_offset = 0;
838
839 newsh->name = name;
840 if (contents != NULL((void*)0))
841 buffer_clone(&newsh->content, contents);
842
843 return 0;
844}
845
846static void ehdr_write(struct elf_writer *ew, struct buffer *m)
847{
848 int i;
849
850 for (i = 0; i < EI_NIDENT(16); i++)
851 ew->xdr->put8(m, ew->ehdr.e_ident[i]);
852 ew->xdr->put16(m, ew->ehdr.e_type);
853 ew->xdr->put16(m, ew->ehdr.e_machine);
854 ew->xdr->put32(m, ew->ehdr.e_version);
855 if (ew->bit64) {
856 ew->xdr->put64(m, ew->ehdr.e_entry);
857 ew->xdr->put64(m, ew->ehdr.e_phoff);
858 ew->xdr->put64(m, ew->ehdr.e_shoff);
859 } else {
860 ew->xdr->put32(m, ew->ehdr.e_entry);
861 ew->xdr->put32(m, ew->ehdr.e_phoff);
862 ew->xdr->put32(m, ew->ehdr.e_shoff);
863 }
864 ew->xdr->put32(m, ew->ehdr.e_flags);
865 ew->xdr->put16(m, ew->ehdr.e_ehsize);
866 ew->xdr->put16(m, ew->ehdr.e_phentsize);
867 ew->xdr->put16(m, ew->ehdr.e_phnum);
868 ew->xdr->put16(m, ew->ehdr.e_shentsize);
869 ew->xdr->put16(m, ew->ehdr.e_shnum);
870 ew->xdr->put16(m, ew->ehdr.e_shstrndx);
871}
872
873static void shdr_write(struct elf_writer *ew, size_t n, struct buffer *m)
874{
875 struct xdr *xdr = ew->xdr;
876 int bit64 = ew->bit64;
877 struct elf_writer_section *sec = &ew->sections[n];
878 Elf64_Shdr *shdr = &sec->shdr;
879
880 xdr->put32(m, shdr->sh_name);
881 xdr->put32(m, shdr->sh_type);
882 if (bit64) {
883 xdr->put64(m, shdr->sh_flags);
884 xdr->put64(m, shdr->sh_addr);
885 xdr->put64(m, shdr->sh_offset);
886 xdr->put64(m, shdr->sh_size);
887 xdr->put32(m, shdr->sh_link);
888 xdr->put32(m, shdr->sh_info);
889 xdr->put64(m, shdr->sh_addralign);
890 xdr->put64(m, shdr->sh_entsize);
891 } else {
892 xdr->put32(m, shdr->sh_flags);
893 xdr->put32(m, shdr->sh_addr);
894 xdr->put32(m, shdr->sh_offset);
895 xdr->put32(m, shdr->sh_size);
896 xdr->put32(m, shdr->sh_link);
897 xdr->put32(m, shdr->sh_info);
898 xdr->put32(m, shdr->sh_addralign);
899 xdr->put32(m, shdr->sh_entsize);
900 }
901}
902
903static void
904phdr_write(struct elf_writer *ew, struct buffer *m, Elf64_Phdr *phdr)
905{
906 if (ew->bit64) {
907 ew->xdr->put32(m, phdr->p_type);
908 ew->xdr->put32(m, phdr->p_flags);
909 ew->xdr->put64(m, phdr->p_offset);
910 ew->xdr->put64(m, phdr->p_vaddr);
911 ew->xdr->put64(m, phdr->p_paddr);
912 ew->xdr->put64(m, phdr->p_filesz);
913 ew->xdr->put64(m, phdr->p_memsz);
914 ew->xdr->put64(m, phdr->p_align);
915 } else {
916 ew->xdr->put32(m, phdr->p_type);
917 ew->xdr->put32(m, phdr->p_offset);
918 ew->xdr->put32(m, phdr->p_vaddr);
919 ew->xdr->put32(m, phdr->p_paddr);
920 ew->xdr->put32(m, phdr->p_filesz);
921 ew->xdr->put32(m, phdr->p_memsz);
922 ew->xdr->put32(m, phdr->p_flags);
923 ew->xdr->put32(m, phdr->p_align);
924 }
925
926}
927
928static int section_consecutive(struct elf_writer *ew, Elf64_Half secidx)
929{
930 Elf64_Half i;
931 struct elf_writer_section *prev_alloc = NULL((void*)0);
932
933 if (secidx == 0)
934 return 0;
935
936 for (i = 0; i < secidx; i++) {
937 if (ew->sections[i].shdr.sh_flags & SHF_ALLOC(1 << 1))
938 prev_alloc = &ew->sections[i];
939 }
940
941 if (prev_alloc == NULL((void*)0))
942 return 0;
943
944 if (prev_alloc->shdr.sh_addr + prev_alloc->shdr.sh_size ==
945 ew->sections[secidx].shdr.sh_addr)
946 return 1;
947
948 return 0;
949}
950
951static void write_phdrs(struct elf_writer *ew, struct buffer *phdrs)
952{
953 Elf64_Half i;
954 Elf64_Phdr phdr;
955 size_t num_written = 0;
956 size_t num_needs_write = 0;
957
958 for (i = 0; i < ew->num_secs; i++) {
20
Loop condition is true. Entering loop body
959 struct elf_writer_section *sec = &ew->sections[i];
960
961 if (!(sec->shdr.sh_flags & SHF_ALLOC(1 << 1)))
21
Assuming the condition is false
22
Taking false branch
962 continue;
963
964 if (!section_consecutive(ew, i)) {
23
Assuming the condition is false
24
Taking false branch
965 /* Write out previously set phdr. */
966 if (num_needs_write != num_written) {
967 phdr_write(ew, phdrs, &phdr);
968 num_written++;
969 }
970 phdr.p_type = PT_LOAD1;
971 phdr.p_offset = sec->shdr.sh_offset;
972 phdr.p_vaddr = sec->shdr.sh_addr;
973 phdr.p_paddr = sec->shdr.sh_addr;
974 phdr.p_filesz = buffer_size(&sec->content);
975 phdr.p_memsz = sec->shdr.sh_size;
976 phdr.p_flags = 0;
977 if (sec->shdr.sh_flags & SHF_EXECINSTR(1 << 2))
978 phdr.p_flags |= PF_X(1 << 0) | PF_R(1 << 2);
979 if (sec->shdr.sh_flags & SHF_WRITE(1 << 0))
980 phdr.p_flags |= PF_W(1 << 1);
981 phdr.p_align = sec->shdr.sh_addralign;
982 num_needs_write++;
983
984 } else {
985 /* Accumulate file size and memsize. The assumption
986 * is that each section is either NOBITS or full
987 * (sh_size == file size). This is standard in that
988 * an ELF section doesn't have a file size component. */
989 if (sec->shdr.sh_flags & SHF_EXECINSTR(1 << 2))
25
Assuming the condition is true
26
Taking true branch
990 phdr.p_flags |= PF_X(1 << 0) | PF_R(1 << 2);
27
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage
991 if (sec->shdr.sh_flags & SHF_WRITE(1 << 0))
992 phdr.p_flags |= PF_W(1 << 1);
993 phdr.p_filesz += buffer_size(&sec->content);
994 phdr.p_memsz += sec->shdr.sh_size;
995 }
996 }
997
998 /* Write out the last phdr. */
999 if (num_needs_write != num_written) {
1000 phdr_write(ew, phdrs, &phdr);
1001 num_written++;
1002 }
1003 assert(num_written == ew->ehdr.e_phnum)((num_written == ew->ehdr.e_phnum) ? (void) (0) : __assert_fail
("num_written == ew->ehdr.e_phnum", "/home/coreboot/node-root/workspace/coreboot_scanbuild/util/cbfstool/elfheaders.c"
, 1003, __extension__ __PRETTY_FUNCTION__))
;
1004}
1005
1006static void fixup_symbol_table(struct elf_writer *ew)
1007{
1008 struct elf_writer_section *sec = ew->symtab_sec;
1009
1010 /* If there is only the NULL section, mark section as inactive. */
1011 if (ew->symtab.num_entries == 1) {
1012 sec->shdr.sh_type = SHT_NULL0;
1013 sec->shdr.sh_size = 0;
1014 } else {
1015 size_t i;
1016 struct buffer wr;
1017
1018 buffer_clone(&wr, &sec->content);
1019 /* To appease xdr. */
1020 buffer_set_size(&wr, 0);
1021 for (i = 0; i < ew->symtab.num_entries; i++) {
1022 /* Create local copy as were over-writing backing
1023 * store of the symbol. */
1024 Elf64_Sym sym = ew->symtab.syms[i];
1025 if (ew->bit64) {
1026 ew->xdr->put32(&wr, sym.st_name);
1027 ew->xdr->put8(&wr, sym.st_info);
1028 ew->xdr->put8(&wr, sym.st_other);
1029 ew->xdr->put16(&wr, sym.st_shndx);
1030 ew->xdr->put64(&wr, sym.st_value);
1031 ew->xdr->put64(&wr, sym.st_size);
1032 } else {
1033 ew->xdr->put32(&wr, sym.st_name);
1034 ew->xdr->put32(&wr, sym.st_value);
1035 ew->xdr->put32(&wr, sym.st_size);
1036 ew->xdr->put8(&wr, sym.st_info);
1037 ew->xdr->put8(&wr, sym.st_other);
1038 ew->xdr->put16(&wr, sym.st_shndx);
1039 }
1040 }
1041
1042 /* Update section size. */
1043 sec->shdr.sh_size = sec->shdr.sh_entsize;
1044 sec->shdr.sh_size *= ew->symtab.num_entries;
1045
1046 /* Fix up sh_link to point to string table. */
1047 sec->shdr.sh_link = section_index(ew, ew->strtab_sec);
1048 /* sh_info is supposed to be 1 greater than symbol table
1049 * index of last local binding. Just use max symbols. */
1050 sec->shdr.sh_info = ew->symtab.num_entries;
1051 }
1052
1053 buffer_set_size(&sec->content, sec->shdr.sh_size);
1054}
1055
1056static void fixup_relocations(struct elf_writer *ew)
1057{
1058 int i;
1059 Elf64_Xword type;
1060
1061 switch (ew->ehdr.e_machine) {
1062 case EM_3863:
1063 type = R_386_321;
1064 break;
1065 case EM_X86_6462:
1066 type = R_AMD64_641;
1067 break;
1068 case EM_ARM40:
1069 type = R_ARM_ABS322;
1070 break;
1071 case EM_AARCH64183:
1072 type = R_AARCH64_ABS64257;
1073 break;
1074 case EM_MIPS8:
1075 type = R_MIPS_322;
1076 break;
1077 case EM_RISCV0xF3:
1078 type = R_RISCV_322;
1079 break;
1080 case EM_PPC6421:
1081 type = R_PPC64_ADDR321;
1082 break;
1083 default:
1084 ERROR("Unable to handle relocations for e_machine %x\n",fprintf(stderr, "E: " "Unable to handle relocations for e_machine %x\n"
, ew->ehdr.e_machine)
1085 ew->ehdr.e_machine)fprintf(stderr, "E: " "Unable to handle relocations for e_machine %x\n"
, ew->ehdr.e_machine)
;
1086 return;
1087 }
1088
1089 for (i = 0; i < MAX_SECTIONS16; i++) {
1090 struct elf_writer_rel *rel_sec = &ew->rel_sections[i];
1091 struct elf_writer_section *sec = rel_sec->sec;
1092 struct buffer writer;
1093 size_t j;
1094
1095 if (sec == NULL((void*)0))
1096 continue;
1097
1098 /* Update section header size as well as content size. */
1099 buffer_init(&sec->content, sec->content.name, rel_sec->rels,
1100 rel_sec->num_entries * sec->shdr.sh_entsize);
1101 sec->shdr.sh_size = buffer_size(&sec->content);
1102 buffer_clone(&writer, &sec->content);
1103 /* To make xdr happy. */
1104 buffer_set_size(&writer, 0);
1105
1106 for (j = 0; j < ew->rel_sections[i].num_entries; j++) {
1107 /* Make copy as we're overwriting backing store. */
1108 Elf64_Rel rel = rel_sec->rels[j];
1109 rel.r_info = ELF64_R_INFO(ELF64_R_SYM(rel.r_info),((((Elf64_Xword) (((rel.r_info) >> 32))) << 32) +
(((type) & 0xffffffff)))
1110 ELF64_R_TYPE(type))((((Elf64_Xword) (((rel.r_info) >> 32))) << 32) +
(((type) & 0xffffffff)))
;
1111
1112 if (ew->bit64) {
1113 ew->xdr->put64(&writer, rel.r_offset);
1114 ew->xdr->put64(&writer, rel.r_info);
1115 } else {
1116 Elf32_Rel rel32;
1117 rel32.r_offset = rel.r_offset;
1118 rel32.r_info =
1119 ELF32_R_INFO(ELF64_R_SYM(rel.r_info),(((((rel.r_info) >> 32)) << 8) + ((((rel.r_info) &
0xffffffff)) & 0xff))
1120 ELF64_R_TYPE(rel.r_info))(((((rel.r_info) >> 32)) << 8) + ((((rel.r_info) &
0xffffffff)) & 0xff))
;
1121 ew->xdr->put32(&writer, rel32.r_offset);
1122 ew->xdr->put32(&writer, rel32.r_info);
1123 }
1124 }
1125 }
1126}
1127
1128/*
1129 * Serialize the ELF file to the output buffer. Return < 0 on error,
1130 * 0 on success.
1131 */
1132int elf_writer_serialize(struct elf_writer *ew, struct buffer *out)
1133{
1134 Elf64_Half i;
1135 Elf64_Xword metadata_size;
1136 Elf64_Xword program_size;
1137 Elf64_Off shstroffset;
1138 size_t shstrlen;
1139 struct buffer metadata;
1140 struct buffer phdrs;
1141 struct buffer data;
1142 struct buffer *strtab;
1143
1144 INFO("Writing %zu sections.\n", ew->num_secs)do { if (verbose > 0) fprintf(stderr, "INFO: " "Writing %zu sections.\n"
, ew->num_secs); } while (0)
;
1
Assuming 'verbose' is <= 0
2
Taking false branch
3
Loop condition is false. Exiting loop
1145
1146 /* Perform any necessary work for special sections. */
1147 fixup_symbol_table(ew);
1148 fixup_relocations(ew);
1149
1150 /* Determine size of sections to be written. */
1151 program_size = 0;
1152 /* Start with 1 byte for first byte of section header string table. */
1153 shstrlen = 1;
1154 for (i = 0; i < ew->num_secs; i++) {
4
Assuming 'i' is >= field 'num_secs'
5
Loop condition is false. Execution continues on line 1170
1155 struct elf_writer_section *sec = &ew->sections[i];
1156
1157 if (sec->shdr.sh_flags & SHF_ALLOC(1 << 1)) {
1158 if (!section_consecutive(ew, i))
1159 ew->ehdr.e_phnum++;
1160 }
1161
1162 program_size += buffer_size(&sec->content);
1163
1164 /* Keep track of the length sections' names. */
1165 if (sec->name != NULL((void*)0)) {
1166 sec->shdr.sh_name = shstrlen;
1167 shstrlen += strlen(sec->name) + 1;
1168 }
1169 }
1170 ew->ehdr.e_shnum = ew->num_secs;
1171 metadata_size = 0;
1172 metadata_size += ew->ehdr.e_ehsize;
1173 metadata_size += (Elf64_Xword)ew->ehdr.e_shnum * ew->ehdr.e_shentsize;
1174 metadata_size += (Elf64_Xword)ew->ehdr.e_phnum * ew->ehdr.e_phentsize;
1175 shstroffset = metadata_size;
1176 /* Align up section header string size and metadata size to 4KiB */
1177 metadata_size = ALIGN_UP(metadata_size + shstrlen, 4096)((((metadata_size + shstrlen))+((__typeof__((metadata_size + shstrlen
)))((4096))-1UL))&~((__typeof__((metadata_size + shstrlen
)))((4096))-1UL))
;
1178
1179 if (buffer_create(out, metadata_size + program_size, "elfout")) {
6
Assuming the condition is false
7
Taking false branch
1180 ERROR("Could not create output buffer for ELF.\n")fprintf(stderr, "E: " "Could not create output buffer for ELF.\n"
)
;
1181 return -1;
1182 }
1183
1184 INFO("Created %zu output buffer for ELF file.\n", buffer_size(out))do { if (verbose > 0) fprintf(stderr, "INFO: " "Created %zu output buffer for ELF file.\n"
, buffer_size(out)); } while (0)
;
8
Assuming 'verbose' is <= 0
9
Taking false branch
10
Loop condition is false. Exiting loop
1185
1186 /*
1187 * Write out ELF header. Section headers come right after ELF header
1188 * followed by the program headers. Buffers need to be created first
1189 * to do the writing.
1190 */
1191 ew->ehdr.e_shoff = ew->ehdr.e_ehsize;
1192 ew->ehdr.e_phoff = ew->ehdr.e_shoff +
1193 (Elf64_Off)ew->ehdr.e_shnum * ew->ehdr.e_shentsize;
1194
1195 buffer_splice(&metadata, out, 0, metadata_size);
1196 buffer_splice(&phdrs, out, ew->ehdr.e_phoff,
1197 (uint32_t)ew->ehdr.e_phnum * ew->ehdr.e_phentsize);
1198 buffer_splice(&data, out, metadata_size, program_size);
1199 /* Set up the section header string table contents. */
1200 strtab = &ew->shstrtab_sec->content;
1201 buffer_splice(strtab, out, shstroffset, shstrlen);
1202 ew->shstrtab_sec->shdr.sh_size = shstrlen;
1203
1204 /* Reset current locations. */
1205 buffer_set_size(&metadata, 0);
1206 buffer_set_size(&data, 0);
1207 buffer_set_size(&phdrs, 0);
1208 buffer_set_size(strtab, 0);
1209
1210 /* ELF Header */
1211 ehdr_write(ew, &metadata);
1212
1213 /* Write out section headers, section strings, section content, and
1214 * program headers. */
1215 ew->xdr->put8(strtab, 0);
1216 for (i = 0; i < ew->num_secs; i++) {
11
Assuming 'i' is < field 'num_secs'
12
Loop condition is true. Entering loop body
17
Assuming 'i' is >= field 'num_secs'
18
Loop condition is false. Execution continues on line 1239
1217 struct elf_writer_section *sec = &ew->sections[i];
1218
1219 /* Update section offsets. Be sure to not update SHN_UNDEF. */
1220 if (sec == ew->shstrtab_sec)
13
Assuming 'sec' is equal to field 'shstrtab_sec'
14
Taking true branch
1221 sec->shdr.sh_offset = shstroffset;
1222 else if (i != SHN_UNDEF0)
1223 sec->shdr.sh_offset = buffer_size(&data) +
1224 metadata_size;
1225
1226 shdr_write(ew, i, &metadata);
1227
1228 /* Add section name to string table. */
1229 if (sec->name != NULL((void*)0))
15
Assuming field 'name' is not equal to NULL
16
Taking true branch
1230 bputs(strtab, sec->name, strlen(sec->name) + 1);
1231
1232 /* Output section data for all sections but SHN_UNDEF and
1233 * section header string table. */
1234 if (i
16.1
'i' is equal to SHN_UNDEF
!= SHN_UNDEF0 && sec != ew->shstrtab_sec)
1235 bputs(&data, buffer_get(&sec->content),
1236 buffer_size(&sec->content));
1237 }
1238
1239 write_phdrs(ew, &phdrs);
19
Calling 'write_phdrs'
1240
1241 return 0;
1242}
1243
1244/* Add a string to the string table returning index on success, < 0 on error. */
1245static int elf_writer_add_string(struct elf_writer *ew, const char *new)
1246{
1247 size_t current_offset;
1248 size_t new_len;
1249
1250 for (current_offset = 0; current_offset < ew->strtab.next_offset; ) {
1251 const char *str = ew->strtab.buffer + current_offset;
1252 size_t len = strlen(str) + 1;
1253
1254 if (!strcmp(str, new))
1255 return current_offset;
1256 current_offset += len;
1257 }
1258
1259 new_len = strlen(new) + 1;
1260
1261 if (current_offset + new_len > ew->strtab.max_size) {
1262 ERROR("No space for string in .strtab.\n")fprintf(stderr, "E: " "No space for string in .strtab.\n");
1263 return -1;
1264 }
1265
1266 memcpy(ew->strtab.buffer + current_offset, new, new_len);
1267 ew->strtab.next_offset = current_offset + new_len;
1268
1269 return current_offset;
1270}
1271
1272static int elf_writer_section_index(struct elf_writer *ew, const char *name)
1273{
1274 size_t i;
1275
1276 for (i = 0; i < ew->num_secs; i++) {
1277 if (ew->sections[i].name == NULL((void*)0))
1278 continue;
1279 if (!strcmp(ew->sections[i].name, name))
1280 return i;
1281 }
1282
1283 ERROR("ELF Section not found: %s\n", name)fprintf(stderr, "E: " "ELF Section not found: %s\n", name);
1284
1285 return -1;
1286}
1287
1288int elf_writer_add_symbol(struct elf_writer *ew, const char *name,
1289 const char *section_name,
1290 Elf64_Addr value, Elf64_Word size,
1291 int binding, int type)
1292{
1293 int i;
1294 Elf64_Sym sym = {
1295 .st_value = value,
1296 .st_size = size,
1297 .st_info = ELF64_ST_INFO(binding, type)((((binding)) << 4) + (((type)) & 0xf)),
1298 };
1299
1300 if (ew->symtab.max_entries == ew->symtab.num_entries) {
1301 ERROR("No more symbol entries left.\n")fprintf(stderr, "E: " "No more symbol entries left.\n");
1302 return -1;
1303 }
1304
1305 i = elf_writer_add_string(ew, name);
1306 if (i < 0)
1307 return -1;
1308 sym.st_name = i;
1309
1310 i = elf_writer_section_index(ew, section_name);
1311 if (i < 0)
1312 return -1;
1313 sym.st_shndx = i;
1314
1315 ew->symtab.syms[ew->symtab.num_entries++] = sym;
1316
1317 return 0;
1318}
1319
1320static int elf_sym_index(struct elf_writer *ew, const char *sym)
1321{
1322 int j;
1323 size_t i;
1324 Elf64_Word st_name;
1325
1326 /* Determine index of symbol in the string table. */
1327 j = elf_writer_add_string(ew, sym);
1328 if (j < 0)
1329 return -1;
1330
1331 st_name = j;
1332
1333 for (i = 0; i < ew->symtab.num_entries; i++)
1334 if (ew->symtab.syms[i].st_name == st_name)
1335 return i;
1336
1337 return -1;
1338}
1339
1340static struct elf_writer_rel *rel_section(struct elf_writer *ew,
1341 const Elf64_Rel *r)
1342{
1343 Elf64_Sym *sym;
1344 struct elf_writer_rel *rel;
1345 Elf64_Shdr shdr;
1346 struct buffer b;
1347
1348 sym = &ew->symtab.syms[ELF64_R_SYM(r->r_info)((r->r_info) >> 32)];
1349
1350 /* Determine if section has been initialized yet. */
1351 rel = &ew->rel_sections[sym->st_shndx];
1352 if (rel->sec != NULL((void*)0))
1353 return rel;
1354
1355 memset(&shdr, 0, sizeof(shdr));
1356 shdr.sh_type = SHT_REL9;
1357 shdr.sh_link = section_index(ew, ew->symtab_sec);
1358 shdr.sh_info = sym->st_shndx;
1359
1360 if (ew->bit64) {
1361 shdr.sh_addralign = sizeof(Elf64_Addr);
1362 shdr.sh_entsize = sizeof(Elf64_Rel);
1363 } else {
1364 shdr.sh_addralign = sizeof(Elf32_Addr);
1365 shdr.sh_entsize = sizeof(Elf32_Rel);
1366 }
1367
1368 if ((strlen(".rel") + strlen(ew->sections[sym->st_shndx].name) + 1) >
1369 MAX_REL_NAME32) {
1370 ERROR("Rel Section name won't fit\n")fprintf(stderr, "E: " "Rel Section name won't fit\n");
1371 return NULL((void*)0);
1372 }
1373
1374 strcat(rel->name, ".rel");
1375 strcat(rel->name, ew->sections[sym->st_shndx].name);
1376 buffer_init(&b, rel->name, NULL((void*)0), 0);
1377
1378 elf_writer_add_section(ew, &shdr, &b, rel->name);
1379 rel->sec = last_section(ew);
1380
1381 return rel;
1382}
1383
1384static int add_rel(struct elf_writer_rel *rel_sec, const Elf64_Rel *rel)
1385{
1386 if (rel_sec->num_entries == rel_sec->max_entries) {
1387 size_t num = rel_sec->max_entries * 2;
1388 Elf64_Rel *old_rels;
1389
1390 if (num == 0)
1391 num = 128;
1392
1393 old_rels = rel_sec->rels;
1394 rel_sec->rels = calloc(num, sizeof(Elf64_Rel));
1395
1396 memcpy(rel_sec->rels, old_rels,
1397 rel_sec->num_entries * sizeof(Elf64_Rel));
1398 free(old_rels);
1399
1400 rel_sec->max_entries = num;
1401 }
1402
1403 rel_sec->rels[rel_sec->num_entries] = *rel;
1404 rel_sec->num_entries++;
1405
1406 return 0;
1407}
1408
1409int elf_writer_add_rel(struct elf_writer *ew, const char *sym, Elf64_Addr addr)
1410{
1411 Elf64_Rel rel;
1412 Elf64_Xword sym_info;
1413 int sym_index;
1414 struct elf_writer_rel *rel_sec;
1415
1416 sym_index = elf_sym_index(ew, sym);
1417
1418 if (sym_index < 0) {
1419 ERROR("Unable to locate symbol: %s\n", sym)fprintf(stderr, "E: " "Unable to locate symbol: %s\n", sym);
1420 return -1;
1421 }
1422
1423 sym_info = sym_index;
1424
1425 /* The relocation type will get fixed prior to serialization. */
1426 rel.r_offset = addr;
1427 rel.r_info = ELF64_R_INFO(sym_info, 0)((((Elf64_Xword) (sym_info)) << 32) + (0));
1428
1429 rel_sec = rel_section(ew, &rel);
1430
1431 if (rel_sec == NULL((void*)0))
1432 return -1;
1433
1434 return add_rel(rel_sec, &rel);
1435}
1436
1437int elf_program_file_size(const struct buffer *input, size_t *file_size)
1438{
1439 Elf64_Ehdr ehdr;
1440 Elf64_Phdr *phdr;
1441 int i;
1442 size_t loadable_file_size = 0;
1443
1444 if (elf_headers(input, &ehdr, &phdr, NULL((void*)0)))
1445 return -1;
1446
1447 for (i = 0; i < ehdr.e_phnum; i++) {
1448 if (phdr[i].p_type != PT_LOAD1)
1449 continue;
1450 loadable_file_size += phdr[i].p_filesz;
1451 }
1452
1453 *file_size = loadable_file_size;
1454
1455 free(phdr);
1456
1457 return 0;
1458}