2 ;* Copyright (C) 2014 Google, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
22 #include "elfparsing.h"
24 #include "../../src/include/rmodule-defs.h"
30 /* Determine if relocation is a valid type for the architecture. */
31 int (*valid_type
)(struct rmod_context
*ctx
, Elf64_Rela
*rel
);
32 /* Determine if relocation should be emitted. */
33 int (*should_emit
)(struct rmod_context
*ctx
, Elf64_Rela
*rel
);
37 /* Ops to process relocations. */
40 /* endian conversion ops */
43 /* Parsed ELF sturcture. */
44 struct parsed_elf pelf
;
45 /* Program segment. */
48 /* Collection of relocation addresses fixup in the module. */
50 Elf64_Addr
*emitted_relocs
;
52 /* The following fields are addresses within the linked program. */
55 Elf64_Addr parameters_begin
;
56 Elf64_Addr parameters_end
;
63 * Architecture specific support operations.
65 static int valid_reloc_386(struct rmod_context
*ctx
, Elf64_Rela
*rel
)
69 type
= ELF64_R_TYPE(rel
->r_info
);
71 /* Only these 2 relocations are expected to be found. */
72 return (type
== R_386_32
|| type
== R_386_PC32
);
75 static int should_emit_386(struct rmod_context
*ctx
, Elf64_Rela
*rel
)
79 type
= ELF64_R_TYPE(rel
->r_info
);
81 /* R_386_32 relocations are absolute. Must emit these. */
82 return (type
== R_386_32
);
85 static int valid_reloc_arm(struct rmod_context
*ctx
, Elf64_Rela
*rel
)
89 type
= ELF64_R_TYPE(rel
->r_info
);
91 /* Only these 6 relocations are expected to be found. */
92 return (type
== R_ARM_ABS32
|| type
== R_ARM_THM_PC22
||
93 type
== R_ARM_THM_JUMP24
|| type
== R_ARM_V4BX
||
94 type
== R_ARM_CALL
|| type
== R_ARM_JUMP24
);
97 static int should_emit_arm(struct rmod_context
*ctx
, Elf64_Rela
*rel
)
101 type
= ELF64_R_TYPE(rel
->r_info
);
103 /* R_ARM_ABS32 relocations are absolute. Must emit these. */
104 return (type
== R_ARM_ABS32
);
107 static int valid_reloc_aarch64(struct rmod_context
*ctx
, Elf64_Rela
*rel
)
111 type
= ELF64_R_TYPE(rel
->r_info
);
113 return (type
== R_AARCH64_ADR_PREL_PG_HI21
||
114 type
== R_AARCH64_ADD_ABS_LO12_NC
||
115 type
== R_AARCH64_LDST8_ABS_LO12_NC
||
116 type
== R_AARCH64_JUMP26
||
117 type
== R_AARCH64_LDST32_ABS_LO12_NC
||
118 type
== R_AARCH64_LDST64_ABS_LO12_NC
||
119 type
== R_AARCH64_CALL26
||
120 type
== R_AARCH64_ABS64
||
121 type
== R_AARCH64_LD_PREL_LO19
||
122 type
== R_AARCH64_ADR_PREL_LO21
);
125 static int should_emit_aarch64(struct rmod_context
*ctx
, Elf64_Rela
*rel
)
129 type
= ELF64_R_TYPE(rel
->r_info
);
131 return (type
== R_AARCH64_ABS64
);
134 static struct arch_ops reloc_ops
[] = {
137 .valid_type
= valid_reloc_386
,
138 .should_emit
= should_emit_386
,
142 .valid_type
= valid_reloc_arm
,
143 .should_emit
= should_emit_arm
,
147 .valid_type
= valid_reloc_aarch64
,
148 .should_emit
= should_emit_aarch64
,
153 * Relocation processing loops.
156 static int for_each_reloc(struct rmod_context
*ctx
, int do_emit
)
159 struct parsed_elf
*pelf
= &ctx
->pelf
;
161 for (i
= 0; i
< pelf
->ehdr
.e_shnum
; i
++) {
167 relocs
= pelf
->relocs
[i
];
169 /* No relocations in this section. */
173 shdr
= &pelf
->shdr
[i
];
174 nrelocs
= shdr
->sh_size
/ shdr
->sh_entsize
;
176 for (j
= 0; j
< nrelocs
; j
++) {
177 Elf64_Rela
*r
= &relocs
[j
];
179 if (!ctx
->ops
->valid_type(ctx
, r
)) {
180 ERROR("Invalid reloc type: %u\n",
181 (unsigned int)ELF64_R_TYPE(r
->r_info
));
185 if (ctx
->ops
->should_emit(ctx
, r
)) {
186 int n
= ctx
->nrelocs
;
188 ctx
->emitted_relocs
[n
] = r
->r_offset
;
197 static int find_program_segment(struct rmod_context
*ctx
)
201 struct parsed_elf
*pelf
;
206 /* There should only be a single loadable segment. */
208 for (i
= 0; i
< pelf
->ehdr
.e_phnum
; i
++) {
209 if (pelf
->phdr
[i
].p_type
!= PT_LOAD
)
211 phdr
= &pelf
->phdr
[i
];
215 if (nsegments
!= 1) {
216 ERROR("Unexepcted number of loadable segments: %d.\n",
221 INFO("Segment at 0x%0llx, file size 0x%0llx, mem size 0x%0llx.\n",
222 (long long)phdr
->p_vaddr
, (long long)phdr
->p_filesz
,
223 (long long)phdr
->p_memsz
);
231 filter_relocation_sections(struct rmod_context
*ctx
)
234 const char *shstrtab
;
235 struct parsed_elf
*pelf
;
236 const Elf64_Phdr
*phdr
;
240 shstrtab
= buffer_get(pelf
->strtabs
[pelf
->ehdr
.e_shstrndx
]);
243 * Find all relocation sections that contain relocation entries
244 * for sections that fall within the bounds of the segment. For
245 * easier processing the pointer to the relocation array for the
246 * sections that don't fall within the loadable program are NULL'd
249 for (i
= 0; i
< pelf
->ehdr
.e_shnum
; i
++) {
252 const char *section_name
;
254 shdr
= &pelf
->shdr
[i
];
256 /* Ignore non-relocation sections. */
257 if (shdr
->sh_type
!= SHT_RELA
&& shdr
->sh_type
!= SHT_REL
)
260 /* Obtain section which relocations apply. */
261 sh_info
= shdr
->sh_info
;
262 shdr
= &pelf
->shdr
[sh_info
];
264 section_name
= &shstrtab
[shdr
->sh_name
];
265 DEBUG("Relocation section found for '%s' section.\n",
268 /* Do not process relocations for debug sections. */
269 if (strstr(section_name
, ".debug") != NULL
) {
270 pelf
->relocs
[i
] = NULL
;
275 * If relocations apply to a non program section ignore the
276 * relocations for future processing.
278 if (shdr
->sh_type
!= SHT_PROGBITS
) {
279 pelf
->relocs
[i
] = NULL
;
283 if (shdr
->sh_addr
< phdr
->p_vaddr
||
284 ((shdr
->sh_addr
+ shdr
->sh_size
) >
285 (phdr
->p_vaddr
+ phdr
->p_memsz
))) {
286 ERROR("Relocations being applied to section %d not "
287 "within segment region.\n", sh_info
);
295 static int vaddr_cmp(const void *a
, const void *b
)
297 const Elf64_Addr
*pa
= a
;
298 const Elf64_Addr
*pb
= b
;
307 static int collect_relocations(struct rmod_context
*ctx
)
312 * The relocs array in the pelf should only contain relocations that
313 * apply to the program. Count the number relocations. Then collect
314 * them into the allocated buffer.
316 if (for_each_reloc(ctx
, 0))
319 nrelocs
= ctx
->nrelocs
;
320 INFO("%d relocations to be emitted.\n", nrelocs
);
324 /* Reset the counter for indexing into the array. */
326 ctx
->emitted_relocs
= calloc(nrelocs
, sizeof(Elf64_Addr
));
327 /* Write out the relocations into the emitted_relocs array. */
328 if (for_each_reloc(ctx
, 1))
331 if (ctx
->nrelocs
!= nrelocs
) {
332 ERROR("Mismatch counted and emitted relocations: %zu vs %zu.\n",
333 (size_t)nrelocs
, (size_t)ctx
->nrelocs
);
337 /* Sort the relocations by their address. */
338 qsort(ctx
->emitted_relocs
, nrelocs
, sizeof(Elf64_Addr
), vaddr_cmp
);
344 populate_sym(struct rmod_context
*ctx
, const char *sym_name
, Elf64_Addr
*addr
,
345 int nsyms
, const char *strtab
)
350 syms
= ctx
->pelf
.syms
;
352 for (i
= 0; i
< nsyms
; i
++) {
353 if (syms
[i
].st_name
== 0)
355 if (strcmp(sym_name
, &strtab
[syms
[i
].st_name
]))
357 DEBUG("%s -> 0x%llx\n", sym_name
, (long long)syms
[i
].st_value
);
358 *addr
= syms
[i
].st_value
;
361 ERROR("symbol '%s' not found.\n", sym_name
);
365 static int populate_program_info(struct rmod_context
*ctx
)
369 struct parsed_elf
*pelf
;
376 /* Obtain the string table. */
378 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
379 if (ctx
->pelf
.strtabs
[i
] == NULL
)
381 /* Don't use the section headers' string table. */
382 if (i
== ehdr
->e_shstrndx
)
384 strtab
= buffer_get(ctx
->pelf
.strtabs
[i
]);
388 if (strtab
== NULL
) {
389 ERROR("No string table found.\n");
393 /* Determine number of symbols. */
395 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
396 if (pelf
->shdr
[i
].sh_type
!= SHT_SYMTAB
)
399 nsyms
= pelf
->shdr
[i
].sh_size
/ pelf
->shdr
[i
].sh_entsize
;
403 if (populate_sym(ctx
, "_module_params_begin", &ctx
->parameters_begin
,
407 if (populate_sym(ctx
, "_module_params_end", &ctx
->parameters_end
,
411 if (populate_sym(ctx
, "_bss", &ctx
->bss_begin
, nsyms
, strtab
))
414 if (populate_sym(ctx
, "_ebss", &ctx
->bss_end
, nsyms
, strtab
))
417 if (populate_sym(ctx
, "__rmodule_entry", &ctx
->entry
, nsyms
, strtab
))
420 /* Link address is the virtual address of the program segment. */
421 ctx
->link_addr
= ctx
->phdr
->p_vaddr
;
423 /* The program size is the memsz of the program segment. */
424 ctx
->size
= ctx
->phdr
->p_memsz
;
430 add_section(struct elf_writer
*ew
, struct buffer
*data
, const char *name
,
431 Elf64_Addr addr
, Elf64_Word size
)
436 memset(&shdr
, 0, sizeof(shdr
));
438 shdr
.sh_type
= SHT_PROGBITS
;
439 shdr
.sh_flags
= SHF_ALLOC
| SHF_WRITE
| SHF_EXECINSTR
;
441 shdr
.sh_type
= SHT_NOBITS
;
442 shdr
.sh_flags
= SHF_ALLOC
;
445 shdr
.sh_offset
= addr
;
448 ret
= elf_writer_add_section(ew
, &shdr
, data
, name
);
451 ERROR("Could not add '%s' section.\n", name
);
457 write_elf(const struct rmod_context
*ctx
, const struct buffer
*in
,
464 size_t rmod_data_size
;
465 struct elf_writer
*ew
;
466 struct buffer rmod_data
;
467 struct buffer rmod_header
;
468 struct buffer program
;
469 struct buffer relocs
;
470 Elf64_Xword total_size
;
474 bit64
= ctx
->pelf
.ehdr
.e_ident
[EI_CLASS
] == ELFCLASS64
;
477 * 3 sections will be added to the ELF file.
478 * +------------------+
480 * +------------------+
482 * +------------------+
484 * +------------------+
487 /* Create buffer for header and relocations. */
488 rmod_data_size
= sizeof(struct rmodule_header
);
490 rmod_data_size
+= ctx
->nrelocs
* sizeof(Elf64_Addr
);
492 rmod_data_size
+= ctx
->nrelocs
* sizeof(Elf32_Addr
);
494 if (buffer_create(&rmod_data
, rmod_data_size
, "rmod"))
497 buffer_splice(&rmod_header
, &rmod_data
,
498 0, sizeof(struct rmodule_header
));
499 buffer_clone(&relocs
, &rmod_data
);
500 buffer_seek(&relocs
, sizeof(struct rmodule_header
));
502 /* Reset current location. */
503 buffer_set_size(&rmod_header
, 0);
504 buffer_set_size(&relocs
, 0);
506 /* Program contents. */
507 buffer_splice(&program
, in
, ctx
->phdr
->p_offset
, ctx
->phdr
->p_filesz
);
509 /* Create ELF writer with modified entry point. */
510 memcpy(&ehdr
, &ctx
->pelf
.ehdr
, sizeof(ehdr
));
511 ehdr
.e_entry
= ctx
->entry
;
512 ew
= elf_writer_init(&ehdr
);
515 ERROR("Failed to create ELF writer.\n");
516 buffer_delete(&rmod_data
);
520 /* Write out rmodule_header. */
521 ctx
->xdr
->put16(&rmod_header
, RMODULE_MAGIC
);
522 ctx
->xdr
->put8(&rmod_header
, RMODULE_VERSION_1
);
523 ctx
->xdr
->put8(&rmod_header
, 0);
524 /* payload_begin_offset */
525 loc
= sizeof(struct rmodule_header
);
526 ctx
->xdr
->put32(&rmod_header
, loc
);
527 /* payload_end_offset */
528 loc
+= ctx
->phdr
->p_filesz
;
529 ctx
->xdr
->put32(&rmod_header
, loc
);
530 /* relocations_begin_offset */
531 ctx
->xdr
->put32(&rmod_header
, loc
);
532 /* relocations_end_offset */
534 loc
+= ctx
->nrelocs
* sizeof(Elf64_Addr
);
536 loc
+= ctx
->nrelocs
* sizeof(Elf32_Addr
);
537 ctx
->xdr
->put32(&rmod_header
, loc
);
538 /* module_link_start_address */
539 ctx
->xdr
->put32(&rmod_header
, ctx
->link_addr
);
540 /* module_program_size */
541 ctx
->xdr
->put32(&rmod_header
, ctx
->size
);
542 /* module_entry_point */
543 ctx
->xdr
->put32(&rmod_header
, ctx
->entry
);
544 /* parameters_begin */
545 ctx
->xdr
->put32(&rmod_header
, ctx
->parameters_begin
);
547 ctx
->xdr
->put32(&rmod_header
, ctx
->parameters_end
);
549 ctx
->xdr
->put32(&rmod_header
, ctx
->bss_begin
);
551 ctx
->xdr
->put32(&rmod_header
, ctx
->bss_end
);
553 ctx
->xdr
->put32(&rmod_header
, 0);
554 ctx
->xdr
->put32(&rmod_header
, 0);
555 ctx
->xdr
->put32(&rmod_header
, 0);
556 ctx
->xdr
->put32(&rmod_header
, 0);
558 /* Write the relocations. */
559 for (i
= 0; i
< ctx
->nrelocs
; i
++) {
561 ctx
->xdr
->put64(&relocs
, ctx
->emitted_relocs
[i
]);
563 ctx
->xdr
->put32(&relocs
, ctx
->emitted_relocs
[i
]);
570 * There are 2 cases to deal with. The program has a large NOBITS
571 * section and the relocations can fit entirely within occupied memory
572 * region for the program. The other is that the relocations increase
573 * the memory footprint of the program if it was loaded directly into
574 * the region it would run. The rmdoule header is a fixed cost that
575 * is considered a part of the program.
577 total_size
+= buffer_size(&rmod_header
);
578 if (buffer_size(&relocs
) + ctx
->phdr
->p_filesz
> ctx
->phdr
->p_memsz
) {
579 total_size
+= buffer_size(&relocs
);
580 total_size
+= ctx
->phdr
->p_filesz
;
582 total_size
+= ctx
->phdr
->p_memsz
;
585 ret
= add_section(ew
, &rmod_header
, ".header", addr
,
586 buffer_size(&rmod_header
));
589 addr
+= buffer_size(&rmod_header
);
591 ret
= add_section(ew
, &program
, ".program", addr
, ctx
->phdr
->p_filesz
);
594 addr
+= ctx
->phdr
->p_filesz
;
597 ret
= add_section(ew
, &relocs
, ".relocs", addr
,
598 buffer_size(&relocs
));
601 addr
+= buffer_size(&relocs
);
604 if (total_size
!= addr
) {
605 ret
= add_section(ew
, NULL
, ".empty", addr
, total_size
- addr
);
611 * Ensure last section has a memory usage that meets the required
612 * total size of the program in memory.
615 ret
= elf_writer_serialize(ew
, out
);
617 ERROR("Failed to serialize ELF to buffer.\n");
620 buffer_delete(&rmod_data
);
621 elf_writer_destroy(ew
);
626 int rmodule_create(const struct buffer
*elfin
, struct buffer
*elfout
)
628 struct rmod_context ctx
;
629 struct parsed_elf
*pelf
;
634 memset(&ctx
, 0, sizeof(ctx
));
637 if (parse_elf(elfin
, pelf
, ELF_PARSE_ALL
)) {
638 ERROR("Couldn't parse ELF!\n");
642 /* Only allow executables to be turned into rmodules. */
643 if (pelf
->ehdr
.e_type
!= ET_EXEC
) {
644 ERROR("ELF is not an executable: %u.\n", pelf
->ehdr
.e_type
);
648 /* Determine if architecture is supported. */
649 for (i
= 0; i
< ARRAY_SIZE(reloc_ops
); i
++) {
650 if (reloc_ops
[i
].arch
== pelf
->ehdr
.e_machine
) {
651 ctx
.ops
= &reloc_ops
[i
];
656 if (ctx
.ops
== NULL
) {
657 ERROR("ELF is unsupported arch: %u.\n", pelf
->ehdr
.e_machine
);
661 /* Set the endian ops. */
662 if (ctx
.pelf
.ehdr
.e_ident
[EI_DATA
] == ELFDATA2MSB
)
667 if (find_program_segment(&ctx
))
670 if (filter_relocation_sections(&ctx
))
673 if (collect_relocations(&ctx
))
676 if (populate_program_info(&ctx
))
679 if (write_elf(&ctx
, elfin
, elfout
))
685 free(ctx
.emitted_relocs
);
686 parsed_elf_destroy(pelf
);