1 /* SPDX-License-Identifier: GPL-2.0-only */
8 #include "elfparsing.h"
10 #include <commonlib/rmodule-defs.h>
13 * Architecture specific support operations.
15 static int valid_reloc_386(Elf64_Rela
*rel
)
19 type
= ELF64_R_TYPE(rel
->r_info
);
21 /* Only these 2 relocations are expected to be found. */
22 return (type
== R_386_32
|| type
== R_386_PC32
);
25 static int should_emit_386(Elf64_Rela
*rel
)
29 type
= ELF64_R_TYPE(rel
->r_info
);
31 /* R_386_32 relocations are absolute. Must emit these. */
32 return (type
== R_386_32
);
35 static int valid_reloc_amd64(Elf64_Rela
*rel
)
39 type
= ELF64_R_TYPE(rel
->r_info
);
42 * Relocation R_AMD64_32S is not allowed. It can only be safely used in protected mode,
43 * and when the address pointed to is below 2 GiB in long mode.
44 * Using it in assembly operations will break compilation with error:
45 * E: Invalid reloc type: 11
48 /* Only these 5 relocations are expected to be found. */
49 return (type
== R_AMD64_64
||
50 type
== R_AMD64_PC64
||
52 type
== R_AMD64_PC32
||
54 * binutils 2.31 introduced R_AMD64_PLT32 for non local
55 * functions. As we don't care about procedure linkage
56 * table entries handle it as R_X86_64_PC32.
58 type
== R_AMD64_PLT32
);
61 static int should_emit_amd64(Elf64_Rela
*rel
)
65 type
= ELF64_R_TYPE(rel
->r_info
);
67 /* Only emit absolute relocations */
68 return (type
== R_AMD64_64
||
72 static int valid_reloc_arm(Elf64_Rela
*rel
)
76 type
= ELF64_R_TYPE(rel
->r_info
);
78 /* Only these 6 relocations are expected to be found. */
79 return (type
== R_ARM_ABS32
|| type
== R_ARM_THM_PC22
||
80 type
== R_ARM_THM_JUMP24
|| type
== R_ARM_V4BX
||
81 type
== R_ARM_CALL
|| type
== R_ARM_JUMP24
);
84 static int should_emit_arm(Elf64_Rela
*rel
)
88 type
= ELF64_R_TYPE(rel
->r_info
);
90 /* R_ARM_ABS32 relocations are absolute. Must emit these. */
91 return (type
== R_ARM_ABS32
);
94 static int valid_reloc_aarch64(Elf64_Rela
*rel
)
98 type
= ELF64_R_TYPE(rel
->r_info
);
100 return (type
== R_AARCH64_ADR_PREL_PG_HI21
||
101 type
== R_AARCH64_ADD_ABS_LO12_NC
||
102 type
== R_AARCH64_LDST8_ABS_LO12_NC
||
103 type
== R_AARCH64_CONDBR19
||
104 type
== R_AARCH64_JUMP26
||
105 type
== R_AARCH64_LDST32_ABS_LO12_NC
||
106 type
== R_AARCH64_LDST64_ABS_LO12_NC
||
107 type
== R_AARCH64_CALL26
||
108 type
== R_AARCH64_ABS64
||
109 type
== R_AARCH64_LD_PREL_LO19
||
110 type
== R_AARCH64_ADR_PREL_LO21
);
113 static int should_emit_aarch64(Elf64_Rela
*rel
)
117 type
= ELF64_R_TYPE(rel
->r_info
);
119 return (type
== R_AARCH64_ABS64
);
122 static const struct arch_ops reloc_ops
[] = {
125 .valid_type
= valid_reloc_386
,
126 .should_emit
= should_emit_386
,
130 .valid_type
= valid_reloc_amd64
,
131 .should_emit
= should_emit_amd64
,
135 .valid_type
= valid_reloc_arm
,
136 .should_emit
= should_emit_arm
,
140 .valid_type
= valid_reloc_aarch64
,
141 .should_emit
= should_emit_aarch64
,
145 static int relocation_for_absolute_symbol(struct rmod_context
*ctx
, Elf64_Rela
*r
)
147 Elf64_Sym
*s
= &ctx
->pelf
.syms
[ELF64_R_SYM(r
->r_info
)];
149 if (s
->st_shndx
== SHN_ABS
) {
150 DEBUG("Omitting relocation for absolute symbol: %s\n",
151 &ctx
->strtab
[s
->st_name
]);
158 static int relocation_for_weak_extern_symbols(struct rmod_context
*ctx
, Elf64_Rela
*r
)
160 Elf64_Sym
*s
= &ctx
->pelf
.syms
[ELF64_R_SYM(r
->r_info
)];
162 if (ELF64_ST_BIND(s
->st_info
) == STB_WEAK
&& ELF64_ST_TYPE(s
->st_info
) == STT_NOTYPE
) {
163 DEBUG("Omitting relocation for undefined extern: %s\n",
164 &ctx
->strtab
[s
->st_name
]);
171 static int relocation_for_undefined_symbol(struct rmod_context
*ctx
, Elf64_Rela
*r
)
173 Elf64_Sym
*s
= &ctx
->pelf
.syms
[ELF64_R_SYM(r
->r_info
)];
175 if (s
->st_shndx
== SHN_UNDEF
) {
176 DEBUG("Omitting relocation for undefined symbol: %s\n",
177 &ctx
->strtab
[s
->st_name
]);
185 * Relocation processing loops.
188 static int for_each_reloc(struct rmod_context
*ctx
, struct reloc_filter
*f
,
192 struct parsed_elf
*pelf
= &ctx
->pelf
;
194 for (i
= 0; i
< pelf
->ehdr
.e_shnum
; i
++) {
200 relocs
= pelf
->relocs
[i
];
202 /* No relocations in this section. */
206 shdr
= &pelf
->shdr
[i
];
207 nrelocs
= shdr
->sh_size
/ shdr
->sh_entsize
;
209 for (j
= 0; j
< nrelocs
; j
++) {
211 Elf64_Rela
*r
= &relocs
[j
];
213 if (!ctx
->ops
->valid_type(r
)) {
214 ERROR("Invalid reloc type: %u\n",
215 (unsigned int)ELF64_R_TYPE(r
->r_info
));
216 if ((ctx
->ops
->arch
== EM_X86_64
) &&
217 (ELF64_R_TYPE(r
->r_info
) == R_AMD64_32S
))
218 ERROR("Illegal use of 32bit sign extended addressing at offset 0x%x\n",
219 (unsigned int)r
->r_offset
);
223 if (relocation_for_absolute_symbol(ctx
, r
))
226 if (relocation_for_weak_extern_symbols(ctx
, r
))
229 if (relocation_for_undefined_symbol(ctx
, r
))
232 /* Allow the provided filter to have precedence. */
234 filter_emit
= f
->filter(f
, r
);
240 if (filter_emit
&& ctx
->ops
->should_emit(r
)) {
241 int n
= ctx
->nrelocs
;
243 ctx
->emitted_relocs
[n
] = r
->r_offset
;
252 static int find_program_segment(struct rmod_context
*ctx
)
256 struct parsed_elf
*pelf
;
257 Elf64_Phdr
*phdr
= NULL
;
261 /* There should only be a single loadable segment. */
263 for (i
= 0; i
< pelf
->ehdr
.e_phnum
; i
++) {
264 if (pelf
->phdr
[i
].p_type
!= PT_LOAD
)
267 phdr
= &pelf
->phdr
[i
];
271 if (nsegments
== 0) {
272 ERROR("No loadable segment found.\n");
276 INFO("Segment at 0x%0llx, file size 0x%0llx, mem size 0x%0llx.\n",
277 (long long)phdr
->p_vaddr
, (long long)phdr
->p_filesz
,
278 (long long)phdr
->p_memsz
);
281 ctx
->nsegments
= nsegments
;
287 filter_relocation_sections(struct rmod_context
*ctx
)
290 const char *shstrtab
;
291 struct parsed_elf
*pelf
;
292 const Elf64_Phdr
*phdr
;
295 shstrtab
= buffer_get(pelf
->strtabs
[pelf
->ehdr
.e_shstrndx
]);
298 * Find all relocation sections that contain relocation entries
299 * for sections that fall within the bounds of the segments. For
300 * easier processing the pointer to the relocation array for the
301 * sections that don't fall within the loadable program are NULL'd
304 for (i
= 0; i
< pelf
->ehdr
.e_shnum
; i
++) {
307 const char *section_name
;
309 shdr
= &pelf
->shdr
[i
];
311 /* Ignore non-relocation sections. */
312 if (shdr
->sh_type
!= SHT_RELA
&& shdr
->sh_type
!= SHT_REL
)
315 /* Obtain section which relocations apply. */
316 sh_info
= shdr
->sh_info
;
317 shdr
= &pelf
->shdr
[sh_info
];
319 section_name
= &shstrtab
[shdr
->sh_name
];
320 DEBUG("Relocation section found for '%s' section.\n",
323 /* Do not process relocations for debug sections. */
324 if (strstr(section_name
, ".debug") != NULL
) {
325 pelf
->relocs
[i
] = NULL
;
330 * If relocations apply to a non program section ignore the
331 * relocations for future processing.
333 if (shdr
->sh_type
!= SHT_PROGBITS
) {
334 pelf
->relocs
[i
] = NULL
;
338 for (j
= 0; j
< pelf
->ehdr
.e_phnum
; j
++) {
339 phdr
= &pelf
->phdr
[j
];
340 if (phdr
->p_type
== PT_LOAD
&&
341 shdr
->sh_addr
>= phdr
->p_vaddr
&&
342 ((shdr
->sh_addr
+ shdr
->sh_size
) <=
343 (phdr
->p_vaddr
+ phdr
->p_memsz
)))
346 if (j
== pelf
->ehdr
.e_phnum
) {
347 ERROR("Relocations being applied to section %d not "
348 "within segments region.\n", sh_info
);
349 pelf
->relocs
[i
] = NULL
;
357 static int vaddr_cmp(const void *a
, const void *b
)
359 const Elf64_Addr
*pa
= a
;
360 const Elf64_Addr
*pb
= b
;
369 int rmodule_collect_relocations(struct rmod_context
*ctx
,
370 struct reloc_filter
*f
)
375 * The relocs array in the pelf should only contain relocations that
376 * apply to the program. Count the number relocations. Then collect
377 * them into the allocated buffer.
379 if (for_each_reloc(ctx
, f
, 0))
382 nrelocs
= ctx
->nrelocs
;
383 INFO("%" PRIu64
" relocations to be emitted.\n", nrelocs
);
387 /* Reset the counter for indexing into the array. */
389 ctx
->emitted_relocs
= calloc(nrelocs
, sizeof(Elf64_Addr
));
390 /* Write out the relocations into the emitted_relocs array. */
391 if (for_each_reloc(ctx
, f
, 1))
394 if (ctx
->nrelocs
!= nrelocs
) {
395 ERROR("Mismatch counted and emitted relocations: %zu vs %zu.\n",
396 (size_t)nrelocs
, (size_t)ctx
->nrelocs
);
400 /* Sort the relocations by their address. */
401 qsort(ctx
->emitted_relocs
, nrelocs
, sizeof(Elf64_Addr
), vaddr_cmp
);
407 populate_sym(struct rmod_context
*ctx
, const char *sym_name
, Elf64_Addr
*addr
,
408 int nsyms
, int optional
)
413 syms
= ctx
->pelf
.syms
;
415 for (i
= 0; i
< nsyms
; i
++) {
416 if (syms
[i
].st_name
== 0)
418 if (strcmp(sym_name
, &ctx
->strtab
[syms
[i
].st_name
]))
420 DEBUG("%s -> 0x%llx\n", sym_name
, (long long)syms
[i
].st_value
);
421 *addr
= syms
[i
].st_value
;
426 DEBUG("optional symbol '%s' not found.\n", sym_name
);
431 ERROR("symbol '%s' not found.\n", sym_name
);
435 static int populate_rmodule_info(struct rmod_context
*ctx
)
438 struct parsed_elf
*pelf
;
445 /* Determine number of symbols. */
447 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
448 if (pelf
->shdr
[i
].sh_type
!= SHT_SYMTAB
)
451 nsyms
= pelf
->shdr
[i
].sh_size
/ pelf
->shdr
[i
].sh_entsize
;
455 if (populate_sym(ctx
, "_rmodule_params", &ctx
->parameters_begin
, nsyms
, 1))
458 if (populate_sym(ctx
, "_ermodule_params", &ctx
->parameters_end
, nsyms
, 1))
461 if (populate_sym(ctx
, "_bss", &ctx
->bss_begin
, nsyms
, 0))
464 if (populate_sym(ctx
, "_ebss", &ctx
->bss_end
, nsyms
, 0))
471 add_section(struct elf_writer
*ew
, struct buffer
*data
, const char *name
,
472 Elf64_Addr addr
, Elf64_Word size
)
477 memset(&shdr
, 0, sizeof(shdr
));
479 shdr
.sh_type
= SHT_PROGBITS
;
480 shdr
.sh_flags
= SHF_ALLOC
| SHF_WRITE
| SHF_EXECINSTR
;
482 shdr
.sh_type
= SHT_NOBITS
;
483 shdr
.sh_flags
= SHF_ALLOC
;
486 shdr
.sh_offset
= addr
;
489 ret
= elf_writer_add_section(ew
, &shdr
, data
, name
);
492 ERROR("Could not add '%s' section.\n", name
);
498 write_elf(const struct rmod_context
*ctx
, const struct buffer
*in
,
504 size_t rmod_data_size
;
505 struct elf_writer
*ew
;
506 struct buffer rmod_data
;
507 struct buffer rmod_header
;
508 struct buffer program
;
509 struct buffer relocs
;
510 Elf64_Xword total_size
;
514 if (ctx
->nsegments
!= 1) {
515 ERROR("Multiple loadable segments is not supported.\n");
519 bit64
= ctx
->pelf
.ehdr
.e_ident
[EI_CLASS
] == ELFCLASS64
;
522 * 3 sections will be added to the ELF file.
523 * +------------------+
525 * +------------------+
527 * +------------------+
529 * +------------------+
532 /* Create buffer for header and relocations. */
533 rmod_data_size
= sizeof(struct rmodule_header
);
535 rmod_data_size
+= ctx
->nrelocs
* sizeof(Elf64_Addr
);
537 rmod_data_size
+= ctx
->nrelocs
* sizeof(Elf32_Addr
);
539 if (buffer_create(&rmod_data
, rmod_data_size
, "rmod"))
542 buffer_splice(&rmod_header
, &rmod_data
,
543 0, sizeof(struct rmodule_header
));
544 buffer_clone(&relocs
, &rmod_data
);
545 buffer_seek(&relocs
, sizeof(struct rmodule_header
));
547 /* Reset current location. */
548 buffer_set_size(&rmod_header
, 0);
549 buffer_set_size(&relocs
, 0);
551 /* Program contents. */
552 buffer_splice(&program
, in
, ctx
->phdr
->p_offset
, ctx
->phdr
->p_filesz
);
554 /* Create ELF writer. Set entry point to 0 to match section offsets. */
555 memcpy(&ehdr
, &ctx
->pelf
.ehdr
, sizeof(ehdr
));
557 ew
= elf_writer_init(&ehdr
);
560 ERROR("Failed to create ELF writer.\n");
561 buffer_delete(&rmod_data
);
565 /* Write out rmodule_header. */
566 ctx
->xdr
->put16(&rmod_header
, RMODULE_MAGIC
);
567 ctx
->xdr
->put8(&rmod_header
, RMODULE_VERSION_1
);
568 ctx
->xdr
->put8(&rmod_header
, 0);
569 /* payload_begin_offset */
570 loc
= sizeof(struct rmodule_header
);
571 ctx
->xdr
->put32(&rmod_header
, loc
);
572 /* payload_end_offset */
573 loc
+= ctx
->phdr
->p_filesz
;
574 ctx
->xdr
->put32(&rmod_header
, loc
);
575 /* relocations_begin_offset */
576 ctx
->xdr
->put32(&rmod_header
, loc
);
577 /* relocations_end_offset */
579 loc
+= ctx
->nrelocs
* sizeof(Elf64_Addr
);
581 loc
+= ctx
->nrelocs
* sizeof(Elf32_Addr
);
582 ctx
->xdr
->put32(&rmod_header
, loc
);
583 /* module_link_start_address */
584 ctx
->xdr
->put32(&rmod_header
, ctx
->phdr
->p_vaddr
);
585 /* module_program_size */
586 ctx
->xdr
->put32(&rmod_header
, ctx
->phdr
->p_memsz
);
587 /* module_entry_point */
588 ctx
->xdr
->put32(&rmod_header
, ctx
->pelf
.ehdr
.e_entry
);
589 /* parameters_begin */
590 ctx
->xdr
->put32(&rmod_header
, ctx
->parameters_begin
);
592 ctx
->xdr
->put32(&rmod_header
, ctx
->parameters_end
);
594 ctx
->xdr
->put32(&rmod_header
, ctx
->bss_begin
);
596 ctx
->xdr
->put32(&rmod_header
, ctx
->bss_end
);
598 ctx
->xdr
->put32(&rmod_header
, 0);
599 ctx
->xdr
->put32(&rmod_header
, 0);
600 ctx
->xdr
->put32(&rmod_header
, 0);
601 ctx
->xdr
->put32(&rmod_header
, 0);
603 /* Write the relocations. */
604 for (unsigned i
= 0; i
< ctx
->nrelocs
; i
++) {
606 ctx
->xdr
->put64(&relocs
, ctx
->emitted_relocs
[i
]);
608 ctx
->xdr
->put32(&relocs
, ctx
->emitted_relocs
[i
]);
615 * There are 2 cases to deal with. The program has a large NOBITS
616 * section and the relocations can fit entirely within occupied memory
617 * region for the program. The other is that the relocations increase
618 * the memory footprint of the program if it was loaded directly into
619 * the region it would run. The rmodule header is a fixed cost that
620 * is considered a part of the program.
622 total_size
+= buffer_size(&rmod_header
);
623 if (buffer_size(&relocs
) + ctx
->phdr
->p_filesz
> ctx
->phdr
->p_memsz
) {
624 total_size
+= buffer_size(&relocs
);
625 total_size
+= ctx
->phdr
->p_filesz
;
627 total_size
+= ctx
->phdr
->p_memsz
;
630 ret
= add_section(ew
, &rmod_header
, ".header", addr
,
631 buffer_size(&rmod_header
));
634 addr
+= buffer_size(&rmod_header
);
636 ret
= add_section(ew
, &program
, ".program", addr
, ctx
->phdr
->p_filesz
);
639 addr
+= ctx
->phdr
->p_filesz
;
642 ret
= add_section(ew
, &relocs
, ".relocs", addr
,
643 buffer_size(&relocs
));
646 addr
+= buffer_size(&relocs
);
649 if (total_size
!= addr
) {
650 ret
= add_section(ew
, NULL
, ".empty", addr
, total_size
- addr
);
656 * Ensure last section has a memory usage that meets the required
657 * total size of the program in memory.
660 ret
= elf_writer_serialize(ew
, out
);
662 ERROR("Failed to serialize ELF to buffer.\n");
665 buffer_delete(&rmod_data
);
666 elf_writer_destroy(ew
);
671 int rmodule_init(struct rmod_context
*ctx
, const struct buffer
*elfin
)
673 struct parsed_elf
*pelf
;
678 memset(ctx
, 0, sizeof(*ctx
));
681 if (parse_elf(elfin
, pelf
, ELF_PARSE_ALL
)) {
682 ERROR("Couldn't parse ELF!\n");
686 /* Only allow executables to be turned into rmodules. */
687 if (pelf
->ehdr
.e_type
!= ET_EXEC
) {
688 ERROR("ELF is not an executable: %u.\n", pelf
->ehdr
.e_type
);
692 /* Determine if architecture is supported. */
693 for (i
= 0; i
< ARRAY_SIZE(reloc_ops
); i
++) {
694 if (reloc_ops
[i
].arch
== pelf
->ehdr
.e_machine
) {
695 ctx
->ops
= &reloc_ops
[i
];
700 if (ctx
->ops
== NULL
) {
701 ERROR("ELF is unsupported arch: %u.\n", pelf
->ehdr
.e_machine
);
705 /* Set the endian ops. */
706 if (ctx
->pelf
.ehdr
.e_ident
[EI_DATA
] == ELFDATA2MSB
)
711 /* Obtain the string table. */
712 for (i
= 0; i
< pelf
->ehdr
.e_shnum
; i
++) {
713 if (pelf
->strtabs
[i
] == NULL
)
715 /* Don't use the section headers' string table. */
716 if (i
== pelf
->ehdr
.e_shstrndx
)
718 ctx
->strtab
= buffer_get(pelf
->strtabs
[i
]);
722 if (ctx
->strtab
== NULL
) {
723 ERROR("No string table found.\n");
727 if (find_program_segment(ctx
))
730 if (filter_relocation_sections(ctx
))
739 void rmodule_cleanup(struct rmod_context
*ctx
)
741 free(ctx
->emitted_relocs
);
742 parsed_elf_destroy(&ctx
->pelf
);
745 int rmodule_create(const struct buffer
*elfin
, struct buffer
*elfout
)
747 struct rmod_context ctx
;
750 if (rmodule_init(&ctx
, elfin
))
753 if (rmodule_collect_relocations(&ctx
, NULL
))
756 if (populate_rmodule_info(&ctx
))
759 if (write_elf(&ctx
, elfin
, elfout
))
765 rmodule_cleanup(&ctx
);
769 static void rmod_deserialize(struct rmodule_header
*rmod
, struct buffer
*buff
,
772 rmod
->magic
= xdr
->get16(buff
);
773 rmod
->version
= xdr
->get8(buff
);
774 rmod
->type
= xdr
->get8(buff
);
775 rmod
->payload_begin_offset
= xdr
->get32(buff
);
776 rmod
->payload_end_offset
= xdr
->get32(buff
);
777 rmod
->relocations_begin_offset
= xdr
->get32(buff
);
778 rmod
->relocations_end_offset
= xdr
->get32(buff
);
779 rmod
->module_link_start_address
= xdr
->get32(buff
);
780 rmod
->module_program_size
= xdr
->get32(buff
);
781 rmod
->module_entry_point
= xdr
->get32(buff
);
782 rmod
->parameters_begin
= xdr
->get32(buff
);
783 rmod
->parameters_end
= xdr
->get32(buff
);
784 rmod
->bss_begin
= xdr
->get32(buff
);
785 rmod
->bss_end
= xdr
->get32(buff
);
786 rmod
->padding
[0] = xdr
->get32(buff
);
787 rmod
->padding
[1] = xdr
->get32(buff
);
788 rmod
->padding
[2] = xdr
->get32(buff
);
789 rmod
->padding
[3] = xdr
->get32(buff
);
792 int rmodule_stage_to_elf(Elf64_Ehdr
*ehdr
, struct buffer
*buff
)
794 struct buffer reader
;
795 struct buffer elf_out
;
796 struct rmodule_header rmod
;
798 struct elf_writer
*ew
;
802 const char *section_name
= ".program";
803 const size_t input_sz
= buffer_size(buff
);
805 buffer_clone(&reader
, buff
);
807 xdr
= (ehdr
->e_ident
[EI_DATA
] == ELFDATA2MSB
) ? &xdr_be
: &xdr_le
;
808 bit64
= ehdr
->e_ident
[EI_CLASS
] == ELFCLASS64
;
810 rmod_deserialize(&rmod
, &reader
, xdr
);
812 /* Indicate that file is not an rmodule if initial checks fail. */
813 if (rmod
.magic
!= RMODULE_MAGIC
)
815 if (rmod
.version
!= RMODULE_VERSION_1
)
818 if (rmod
.payload_begin_offset
> input_sz
||
819 rmod
.payload_end_offset
> input_sz
||
820 rmod
.relocations_begin_offset
> input_sz
||
821 rmod
.relocations_end_offset
> input_sz
) {
822 ERROR("Rmodule fields out of bounds.\n");
826 ehdr
->e_entry
= rmod
.module_entry_point
;
827 ew
= elf_writer_init(ehdr
);
832 payload_sz
= rmod
.payload_end_offset
- rmod
.payload_begin_offset
;
833 memset(&shdr
, 0, sizeof(shdr
));
834 shdr
.sh_type
= SHT_PROGBITS
;
835 shdr
.sh_flags
= SHF_WRITE
| SHF_ALLOC
| SHF_EXECINSTR
;
836 shdr
.sh_addr
= rmod
.module_link_start_address
;
837 shdr
.sh_size
= payload_sz
;
838 buffer_splice(&reader
, buff
, rmod
.payload_begin_offset
, payload_sz
);
840 if (elf_writer_add_section(ew
, &shdr
, &reader
, section_name
)) {
841 ERROR("Unable to add ELF section: %s\n", section_name
);
842 elf_writer_destroy(ew
);
846 if (payload_sz
!= rmod
.module_program_size
) {
849 buffer_init(&b
, NULL
, NULL
, 0);
850 memset(&shdr
, 0, sizeof(shdr
));
851 shdr
.sh_type
= SHT_NOBITS
;
852 shdr
.sh_flags
= SHF_WRITE
| SHF_ALLOC
;
853 shdr
.sh_addr
= rmod
.module_link_start_address
+ payload_sz
;
854 shdr
.sh_size
= rmod
.module_program_size
- payload_sz
;
855 if (elf_writer_add_section(ew
, &shdr
, &b
, ".empty")) {
856 ERROR("Unable to add ELF section: .empty\n");
857 elf_writer_destroy(ew
);
862 /* Provide a section symbol so the relcoations can reference that. */
863 if (elf_writer_add_symbol(ew
, section_name
, section_name
, shdr
.sh_addr
,
864 0, STB_LOCAL
, STT_SECTION
)) {
865 ERROR("Unable to add section symbol to ELF.\n");
866 elf_writer_destroy(ew
);
870 /* Add symbols for the parameters if they are non-zero. */
871 if (rmod
.parameters_begin
!= rmod
.parameters_end
) {
874 ret
|= elf_writer_add_symbol(ew
, "_rmodule_params",
876 rmod
.parameters_begin
, 0,
877 STB_GLOBAL
, STT_NOTYPE
);
878 ret
|= elf_writer_add_symbol(ew
, "_ermodule_params",
880 rmod
.parameters_end
, 0,
881 STB_GLOBAL
, STT_NOTYPE
);
884 ERROR("Unable to add module params symbols to ELF\n");
885 elf_writer_destroy(ew
);
890 if (elf_writer_add_symbol(ew
, "_bss", section_name
, rmod
.bss_begin
, 0,
891 STB_GLOBAL
, STT_NOTYPE
) ||
892 elf_writer_add_symbol(ew
, "_ebss", section_name
, rmod
.bss_end
, 0,
893 STB_GLOBAL
, STT_NOTYPE
)) {
894 ERROR("Unable to add bss symbols to ELF\n");
895 elf_writer_destroy(ew
);
899 ssize_t relocs_sz
= rmod
.relocations_end_offset
;
900 relocs_sz
-= rmod
.relocations_begin_offset
;
901 buffer_splice(&reader
, buff
, rmod
.relocations_begin_offset
, relocs_sz
);
902 while (relocs_sz
> 0) {
906 relocs_sz
-= sizeof(Elf64_Addr
);
907 addr
= xdr
->get64(&reader
);
909 relocs_sz
-= sizeof(Elf32_Addr
);
910 addr
= xdr
->get32(&reader
);
913 /* Skip any relocations that are below the link address. */
914 if (addr
< rmod
.module_link_start_address
)
917 if (elf_writer_add_rel(ew
, section_name
, addr
)) {
918 ERROR("Relocation addition failure.\n");
919 elf_writer_destroy(ew
);
924 if (elf_writer_serialize(ew
, &elf_out
)) {
925 ERROR("ELF writer serialize failure.\n");
926 elf_writer_destroy(ew
);
930 elf_writer_destroy(ew
);
932 /* Flip buffer with the created ELF one. */