Changeset View
Changeset View
Standalone View
Standalone View
elfcopy/sections.c
Show First 20 Lines • Show All 759 Lines • ▼ Show 20 Lines | if (gelf_getshdr(s->os, &osh) == NULL) | ||||
errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", | errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", | ||||
elf_errmsg(-1)); | elf_errmsg(-1)); | ||||
osh.sh_size = s->sz + s->pad_sz; | osh.sh_size = s->sz + s->pad_sz; | ||||
if (!gelf_update_shdr(s->os, &osh)) | if (!gelf_update_shdr(s->os, &osh)) | ||||
errx(EXIT_FAILURE, "elf_update_shdr failed: %s", | errx(EXIT_FAILURE, "elf_update_shdr failed: %s", | ||||
elf_errmsg(-1)); | 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 | void | ||||
resync_sections(struct elfcopy *ecp) | resync_sections(struct elfcopy *ecp) | ||||
{ | { | ||||
struct section *s, *ps; | struct section *s, *ps; | ||||
GElf_Shdr osh; | GElf_Shdr osh; | ||||
uint64_t off; | uint64_t off; | ||||
int first; | int first; | ||||
int min_alignment; | |||||
ps = NULL; | ps = NULL; | ||||
first = 1; | first = 1; | ||||
off = 0; | off = 0; | ||||
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { | TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { | ||||
if (first) { | if (first) { | ||||
off = s->off; | off = s->off; | ||||
first = 0; | first = 0; | ||||
} | } | ||||
/* | /* | ||||
* Ignore TLS sections with load address 0 and without | * Ignore TLS sections with load address 0 and without | ||||
* content. We don't need to adjust their file offset or | * content. We don't need to adjust their file offset or | ||||
* VMA, only the size matters. | * VMA, only the size matters. | ||||
*/ | */ | ||||
if (s->seg_tls != NULL && s->type == SHT_NOBITS && | if (s->seg_tls != NULL && s->type == SHT_NOBITS && | ||||
s->off == 0) | s->off == 0) | ||||
continue; | continue; | ||||
/* Align section offset. */ | /* Align section offset. */ | ||||
if (s->align == 0) | if (s->align == 0) | ||||
s->align = 1; | 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 (off <= s->off) { | ||||
if (!s->loadable) | if (!s->loadable) | ||||
s->off = roundup(off, s->align); | s->off = roundup(off, s->align); | ||||
} else { | } else { | ||||
if (s->loadable) | if (s->loadable) | ||||
warnx("moving loadable section %s, " | warnx("moving loadable section %s, " | ||||
"is this intentional?", s->name); | "is this intentional?", s->name); | ||||
s->off = roundup(off, s->align); | s->off = roundup(off, s->align); | ||||
Show All 14 Lines | if (s->pad_sz > 0) | ||||
off += s->pad_sz; | off += s->pad_sz; | ||||
/* Update section header accordingly. */ | /* Update section header accordingly. */ | ||||
if (gelf_getshdr(s->os, &osh) == NULL) | if (gelf_getshdr(s->os, &osh) == NULL) | ||||
errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", | errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", | ||||
elf_errmsg(-1)); | elf_errmsg(-1)); | ||||
osh.sh_addr = s->vma; | osh.sh_addr = s->vma; | ||||
osh.sh_offset = s->off; | osh.sh_offset = s->off; | ||||
osh.sh_size = s->sz; | osh.sh_size = s->sz; | ||||
emaste: We'd also need a `osh.sh_addralign = s->align;` here | |||||
if (!gelf_update_shdr(s->os, &osh)) | if (!gelf_update_shdr(s->os, &osh)) | ||||
errx(EXIT_FAILURE, "elf_update_shdr failed: %s", | errx(EXIT_FAILURE, "elf_update_shdr failed: %s", | ||||
elf_errmsg(-1)); | elf_errmsg(-1)); | ||||
/* Add padding for previous section, if need. */ | /* Add padding for previous section, if need. */ | ||||
if (ps != NULL) { | if (ps != NULL) { | ||||
if (ps->pad_sz > 0) { | if (ps->pad_sz > 0) { | ||||
/* Apply padding added by --pad-to. */ | /* Apply padding added by --pad-to. */ | ||||
▲ Show 20 Lines • Show All 738 Lines • Show Last 20 Lines |
We'd also need a osh.sh_addralign = s->align; here