elfcopy/strip: Ensure sections have required alignment on output
Object files may specify insufficient alignment on certain sections, for
example due to a bug in NASM[1]. When we detect that case in elfcopy or
strip, emit a warning and increase the alignment to the minimum
required.
The NASM bug was fixed in 2015[2], but we might as well have this fixup
(and warning) in elfcopy in case we encounter such a file for any other
reason.
This might be reworked somewhat upstream - see ELF Tool Chain
ticket 485[3].
[1] https://bugzilla.nasm.us/show_bug.cgi?id=3392307
[2] 1f0cb0f2c1
[3] https://sourceforge.net/p/elftoolchain/tickets/485/
PR: 198611
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D2292
This commit is contained in:
parent
9dc7ed6253
commit
4133f23624
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354544
@ -879,6 +879,43 @@ pad_section(struct elfcopy *ecp, struct section *s)
|
||||
elf_errmsg(-1));
|
||||
}
|
||||
|
||||
static int
|
||||
section_type_alignment(int sht, int class)
|
||||
{
|
||||
switch (sht)
|
||||
{
|
||||
case SHT_DYNAMIC:
|
||||
case SHT_DYNSYM:
|
||||
case SHT_FINI_ARRAY:
|
||||
case SHT_GNU_HASH:
|
||||
case SHT_INIT_ARRAY:
|
||||
case SHT_PREINIT_ARRAY:
|
||||
case SHT_REL:
|
||||
case SHT_RELA:
|
||||
case SHT_SYMTAB:
|
||||
return (class == ELFCLASS64 ? 8 : 4);
|
||||
case SHT_SUNW_move:
|
||||
return (8);
|
||||
case SHT_GNU_LIBLIST:
|
||||
case SHT_GROUP:
|
||||
case SHT_HASH:
|
||||
case SHT_NOTE:
|
||||
case SHT_SUNW_verdef: /* == SHT_GNU_verdef */
|
||||
case SHT_SUNW_verneed: /* == SHT_GNU_verneed */
|
||||
case SHT_SYMTAB_SHNDX:
|
||||
return (4);
|
||||
case SHT_SUNW_syminfo:
|
||||
case SHT_SUNW_versym: /* == SHT_GNU_versym */
|
||||
return (2);
|
||||
case SHT_NOBITS:
|
||||
case SHT_PROGBITS:
|
||||
case SHT_STRTAB:
|
||||
case SHT_SUNW_dof:
|
||||
return (1);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
resync_sections(struct elfcopy *ecp)
|
||||
{
|
||||
@ -886,6 +923,7 @@ resync_sections(struct elfcopy *ecp)
|
||||
GElf_Shdr osh;
|
||||
uint64_t off;
|
||||
int first;
|
||||
int min_alignment;
|
||||
|
||||
ps = NULL;
|
||||
first = 1;
|
||||
@ -908,6 +946,12 @@ resync_sections(struct elfcopy *ecp)
|
||||
/* Align section offset. */
|
||||
if (s->align == 0)
|
||||
s->align = 1;
|
||||
min_alignment = section_type_alignment(s->type, ecp->oec);
|
||||
if (s->align < INT_MAX && (int)s->align < min_alignment) {
|
||||
warnx("section %s alignment %d increased to %d",
|
||||
s->name, (int)s->align, min_alignment);
|
||||
s->align = min_alignment;
|
||||
}
|
||||
if (off <= s->off) {
|
||||
if (!s->loadable || (ecp->flags & RELOCATABLE))
|
||||
s->off = roundup(off, s->align);
|
||||
@ -937,6 +981,7 @@ resync_sections(struct elfcopy *ecp)
|
||||
errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
|
||||
elf_errmsg(-1));
|
||||
osh.sh_addr = s->vma;
|
||||
osh.sh_addralign = s->align;
|
||||
osh.sh_offset = s->off;
|
||||
osh.sh_size = s->sz;
|
||||
if (!gelf_update_shdr(s->os, &osh))
|
||||
|
Loading…
Reference in New Issue
Block a user