xref: /aosp_15_r20/external/coreboot/util/cbfstool/elfheaders.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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 
iself(const void * input)109 static int iself(const void *input)
110 {
111 	const Elf32_Ehdr *ehdr = input;
112 	return !memcmp(ehdr->e_ident, ELFMAG, 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  */
119 static void
elf_eident(struct buffer * input,Elf64_Ehdr * ehdr)120 elf_eident(struct buffer *input, Elf64_Ehdr *ehdr)
121 {
122 	bgets(input, ehdr->e_ident, sizeof(ehdr->e_ident));
123 }
124 
125 
126 static int
check_size(const struct buffer * b,size_t offset,size_t size,const char * desc)127 check_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'. "
134 		      "%zu bytes @ offset %zu, input %zu bytes.\n",
135 		      desc, size, offset, buffer_size(b));
136 		return -1;
137 	}
138 	return 0;
139 }
140 
141 static void
elf_ehdr(struct buffer * input,Elf64_Ehdr * ehdr,struct xdr * xdr,int bit64)142 elf_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 
165 static void
elf_phdr(struct buffer * pinput,Elf64_Phdr * phdr,int entsize,struct xdr * xdr,int bit64)166 elf_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 
200 static void
elf_shdr(struct buffer * pinput,Elf64_Shdr * shdr,int entsize,struct xdr * xdr,int bit64)201 elf_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 
238 static int
phdr_read(const struct buffer * in,struct parsed_elf * pelf,struct xdr * xdr,int bit64)239 phdr_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);
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 
280 static int
shdr_read(const struct buffer * in,struct parsed_elf * pelf,struct xdr * xdr,int bit64)281 shdr_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);
305 		elf_shdr(&b, &shdr[i], ehdr->e_shentsize, xdr, bit64);
306 	}
307 
308 	pelf->shdr = shdr;
309 
310 	return 0;
311 }
312 
313 static int
reloc_read(const struct buffer * in,struct parsed_elf * pelf,struct xdr * xdr,int bit64)314 reloc_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_REL && shdr->sh_type != SHT_RELA)
336 			continue;
337 
338 		DEBUG("Checking relocation section %u\n", i);
339 
340 		/* Ensure the section that relocations apply is a valid. */
341 		if (shdr->sh_info >= ehdr->e_shnum ||
342 		    shdr->sh_info == SHN_UNDEF) {
343 			ERROR("Relocations apply to an invalid section: %u\n",
344 			      shdr[i].sh_info);
345 			return -1;
346 		}
347 
348 		is_rela = shdr->sh_type == SHT_RELA;
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);
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),
375 				                          ELF32_R_TYPE(r_info));
376 				if (is_rela)
377 					rela->r_addend = xdr->get32(&b);
378 			}
379 			rela++;
380 		}
381 	}
382 
383 	return 0;
384 }
385 
strtab_read(const struct buffer * in,struct parsed_elf * pelf)386 static 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",
395 		      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_STRTAB)
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);
413 			free(b);
414 			return -1;
415 		}
416 		pelf->strtabs[i] = b;
417 	}
418 
419 	return 0;
420 }
421 
422 static int
symtab_read(const struct buffer * in,struct parsed_elf * pelf,struct xdr * xdr,int bit64)423 symtab_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;
437 	for (shnum = 0; shnum < ehdr->e_shnum; shnum++) {
438 		if (pelf->shdr[shnum].sh_type != SHT_SYMTAB)
439 			continue;
440 
441 		if (shdr != NULL) {
442 			ERROR("Multiple symbol sections found. %u and %u\n",
443 			      (unsigned int)(shdr - pelf->shdr), shnum);
444 			return -1;
445 		}
446 
447 		shdr = &pelf->shdr[shnum];
448 	}
449 
450 	if (shdr == NULL) {
451 		ERROR("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 
parse_elf(const struct buffer * pinput,struct parsed_elf * pelf,int flags)486 int 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");
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_CLASS] == ELFCLASS64;
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_DATA] == ELFDATA2MSB)
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)
517 		flags |= ELF_PARSE_SHDR;
518 
519 	/* String table processing requires section header parsing. */
520 	if (flags & ELF_PARSE_STRTAB)
521 		flags |= ELF_PARSE_SHDR;
522 
523 	/* Symbole table processing requires section header parsing. */
524 	if (flags & ELF_PARSE_SYMTAB)
525 		flags |= ELF_PARSE_SHDR;
526 
527 	if ((flags & ELF_PARSE_PHDR) && phdr_read(pinput, pelf, xdr, bit64))
528 		goto fail;
529 
530 	if ((flags & ELF_PARSE_SHDR) && shdr_read(pinput, pelf, xdr, bit64))
531 		goto fail;
532 
533 	if ((flags & ELF_PARSE_RELOC) && reloc_read(pinput, pelf, xdr, bit64))
534 		goto fail;
535 
536 	if ((flags & ELF_PARSE_STRTAB) && strtab_read(pinput, pelf))
537 		goto fail;
538 
539 	if ((flags & ELF_PARSE_SYMTAB) && symtab_read(pinput, pelf, xdr, bit64))
540 		goto fail;
541 
542 	return 0;
543 
544 fail:
545 	parsed_elf_destroy(pelf);
546 	return -1;
547 }
548 
parsed_elf_destroy(struct parsed_elf * pelf)549 void 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) {
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) {
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  */
576 int
elf_headers(const struct buffer * pinput,Elf64_Ehdr * ehdr,Elf64_Phdr ** pphdr,Elf64_Shdr ** pshdr)577 elf_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;
586 
587 	if (pshdr != NULL)
588 		flags |= ELF_PARSE_SHDR;
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) {
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 
elf_init_eheader(Elf64_Ehdr * ehdr,int machine,int nbits,int endian)625 void elf_init_eheader(Elf64_Ehdr *ehdr, int machine, int nbits, int endian)
626 {
627 	memset(ehdr, 0, sizeof(*ehdr));
628 	ehdr->e_ident[EI_MAG0] = ELFMAG0;
629 	ehdr->e_ident[EI_MAG1] = ELFMAG1;
630 	ehdr->e_ident[EI_MAG2] = ELFMAG2;
631 	ehdr->e_ident[EI_MAG3] = ELFMAG3;
632 	ehdr->e_ident[EI_CLASS] = nbits;
633 	ehdr->e_ident[EI_DATA] = endian;
634 	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
635 	ehdr->e_type = ET_EXEC;
636 	ehdr->e_machine = machine;
637 	ehdr->e_version = EV_CURRENT;
638 	if (nbits == ELFCLASS64) {
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_SECTIONS 16
651 struct elf_writer_section {
652 	Elf64_Shdr shdr;
653 	struct buffer content;
654 	const char *name;
655 };
656 
657 struct elf_writer_string_table {
658 	size_t next_offset;
659 	size_t max_size;
660 	char *buffer;
661 };
662 
663 struct elf_writer_sym_table {
664 	size_t max_entries;
665 	size_t num_entries;
666 	Elf64_Sym *syms;
667 };
668 
669 #define MAX_REL_NAME 32
670 struct 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_NAME];
676 };
677 
678 struct elf_writer
679 {
680 	Elf64_Ehdr ehdr;
681 	struct xdr *xdr;
682 	size_t num_secs;
683 	struct elf_writer_section sections[MAX_SECTIONS];
684 	struct elf_writer_rel rel_sections[MAX_SECTIONS];
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 
section_index(struct elf_writer * ew,struct elf_writer_section * sec)694 static size_t section_index(struct elf_writer *ew,
695 					struct elf_writer_section *sec)
696 {
697 	return sec - &ew->sections[0];
698 }
699 
last_section(struct elf_writer * ew)700 static struct elf_writer_section *last_section(struct elf_writer *ew)
701 {
702 	return &ew->sections[ew->num_secs - 1];
703 }
704 
strtab_init(struct elf_writer * ew,size_t size)705 static 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, ew->strtab.buffer, ew->strtab.max_size);
716 	memset(&shdr, 0, sizeof(shdr));
717 	shdr.sh_type = SHT_STRTAB;
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 
symtab_init(struct elf_writer * ew,size_t max_entries)724 static 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_SYMTAB;
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, 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 
elf_writer_init(const Elf64_Ehdr * ehdr)752 struct 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;
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_CLASS] == ELFCLASS64;
766 
767 	/* Set the endinan ops. */
768 	if (ew->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
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_NULL;
784 	elf_writer_add_section(ew, &shdr, &empty_buffer, NULL);
785 
786 	/* Add section header string table and maintain reference to it.  */
787 	shdr.sh_type = SHT_STRTAB;
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  */
elf_writer_destroy(struct elf_writer * ew)805 void elf_writer_destroy(struct elf_writer *ew)
806 {
807 	int i;
808 	if (ew == NULL)
809 		return;
810 	if (ew->phdrs != NULL)
811 		free(ew->phdrs);
812 	free(ew->strtab.buffer);
813 	free(ew->symtab.syms);
814 	for (i = 0; i < MAX_SECTIONS; 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  */
elf_writer_add_section(struct elf_writer * ew,const Elf64_Shdr * shdr,struct buffer * contents,const char * name)825 int 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_SECTIONS)
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)
841 		buffer_clone(&newsh->content, contents);
842 
843 	return 0;
844 }
845 
ehdr_write(struct elf_writer * ew,struct buffer * m)846 static void ehdr_write(struct elf_writer *ew, struct buffer *m)
847 {
848 	int i;
849 
850 	for (i = 0; i < EI_NIDENT; 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 
shdr_write(struct elf_writer * ew,size_t n,struct buffer * m)873 static 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 
903 static void
phdr_write(struct elf_writer * ew,struct buffer * m,Elf64_Phdr * phdr)904 phdr_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 
section_consecutive(struct elf_writer * ew,Elf64_Half secidx)928 static int section_consecutive(struct elf_writer *ew, Elf64_Half secidx)
929 {
930 	Elf64_Half i;
931 	struct elf_writer_section *prev_alloc = NULL;
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)
938 			prev_alloc = &ew->sections[i];
939 	}
940 
941 	if (prev_alloc == NULL)
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 
write_phdrs(struct elf_writer * ew,struct buffer * phdrs)951 static 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++) {
959 		struct elf_writer_section *sec = &ew->sections[i];
960 
961 		if (!(sec->shdr.sh_flags & SHF_ALLOC))
962 			continue;
963 
964 		if (!section_consecutive(ew, i)) {
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_LOAD;
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)
978 				phdr.p_flags |= PF_X | PF_R;
979 			if (sec->shdr.sh_flags & SHF_WRITE)
980 				phdr.p_flags |= PF_W;
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)
990 				phdr.p_flags |= PF_X | PF_R;
991 			if (sec->shdr.sh_flags & SHF_WRITE)
992 				phdr.p_flags |= PF_W;
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);
1004 }
1005 
fixup_symbol_table(struct elf_writer * ew)1006 static 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_NULL;
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 
fixup_relocations(struct elf_writer * ew)1056 static 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_386:
1063 		type = R_386_32;
1064 		break;
1065 	case EM_X86_64:
1066 		type =  R_AMD64_64;
1067 		break;
1068 	case EM_ARM:
1069 		type = R_ARM_ABS32;
1070 		break;
1071 	case EM_AARCH64:
1072 		type = R_AARCH64_ABS64;
1073 		break;
1074 	case EM_MIPS:
1075 		type = R_MIPS_32;
1076 		break;
1077 	case EM_RISCV:
1078 		type = R_RISCV_32;
1079 		break;
1080 	case EM_PPC64:
1081 		type = R_PPC64_ADDR32;
1082 		break;
1083 	default:
1084 		ERROR("Unable to handle relocations for e_machine %x\n",
1085 			ew->ehdr.e_machine);
1086 		return;
1087 	}
1088 
1089 	for (i = 0; i < MAX_SECTIONS; 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)
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),
1110 						  ELF64_R_TYPE(type));
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),
1120 						     ELF64_R_TYPE(rel.r_info));
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  */
elf_writer_serialize(struct elf_writer * ew,struct buffer * out)1132 int 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);
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++) {
1155 		struct elf_writer_section *sec = &ew->sections[i];
1156 
1157 		if (sec->shdr.sh_flags & SHF_ALLOC) {
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) {
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);
1178 
1179 	if (buffer_create(out, metadata_size + program_size, "elfout")) {
1180 		ERROR("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));
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++) {
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)
1221 			sec->shdr.sh_offset = shstroffset;
1222 		else if (i != SHN_UNDEF)
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)
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 != SHN_UNDEF && sec != ew->shstrtab_sec)
1235 			bputs(&data, buffer_get(&sec->content),
1236 			      buffer_size(&sec->content));
1237 	}
1238 
1239 	write_phdrs(ew, &phdrs);
1240 
1241 	return 0;
1242 }
1243 
1244 /* Add a string to the string table returning index on success, < 0 on error. */
elf_writer_add_string(struct elf_writer * ew,const char * new)1245 static 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");
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 
elf_writer_section_index(struct elf_writer * ew,const char * name)1272 static 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)
1278 			continue;
1279 		if (!strcmp(ew->sections[i].name, name))
1280 			return i;
1281 	}
1282 
1283 	ERROR("ELF Section not found: %s\n", name);
1284 
1285 	return -1;
1286 }
1287 
elf_writer_add_symbol(struct elf_writer * ew,const char * name,const char * section_name,Elf64_Addr value,Elf64_Word size,int binding,int type)1288 int 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),
1298 	};
1299 
1300 	if (ew->symtab.max_entries == ew->symtab.num_entries) {
1301 		ERROR("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 
elf_sym_index(struct elf_writer * ew,const char * sym)1320 static 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 
rel_section(struct elf_writer * ew,const Elf64_Rel * r)1340 static 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)];
1349 
1350 	/* Determine if section has been initialized yet. */
1351 	rel = &ew->rel_sections[sym->st_shndx];
1352 	if (rel->sec != NULL)
1353 		return rel;
1354 
1355 	memset(&shdr, 0, sizeof(shdr));
1356 	shdr.sh_type = SHT_REL;
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_NAME) {
1370 		ERROR("Rel Section name won't fit\n");
1371 		return NULL;
1372 	}
1373 
1374 	strcat(rel->name, ".rel");
1375 	strcat(rel->name, ew->sections[sym->st_shndx].name);
1376 	buffer_init(&b, rel->name, NULL, 0);
1377 
1378 	elf_writer_add_section(ew, &shdr, &b, rel->name);
1379 	rel->sec = last_section(ew);
1380 
1381 	return rel;
1382 }
1383 
add_rel(struct elf_writer_rel * rel_sec,const Elf64_Rel * rel)1384 static 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 
elf_writer_add_rel(struct elf_writer * ew,const char * sym,Elf64_Addr addr)1409 int 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);
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);
1428 
1429 	rel_sec = rel_section(ew, &rel);
1430 
1431 	if (rel_sec == NULL)
1432 		return -1;
1433 
1434 	return add_rel(rel_sec, &rel);
1435 }
1436 
elf_program_file_size_align(const struct buffer * input,size_t * file_size,size_t * align)1437 int elf_program_file_size_align(const struct buffer *input, size_t *file_size, size_t *align)
1438 {
1439 	Elf64_Ehdr ehdr;
1440 	Elf64_Phdr *phdr;
1441 	int i;
1442 	size_t loadable_file_size = 0;
1443 	size_t align_size = 0;
1444 
1445 	if (elf_headers(input, &ehdr, &phdr, NULL))
1446 		return -1;
1447 
1448 	for (i = 0; i < ehdr.e_phnum; i++) {
1449 		if (phdr[i].p_type != PT_LOAD)
1450 			continue;
1451 		loadable_file_size += phdr[i].p_filesz;
1452 		align_size = MAX(align_size, phdr[i].p_align);
1453 	}
1454 
1455 	*file_size = loadable_file_size;
1456 	*align = align_size;
1457 
1458 	free(phdr);
1459 
1460 	return 0;
1461 }
1462