forked from Imagelibrary/binutils-gdb
Update objcopy's --section-alignment option so that it sets the alignment flag on PE sections. Add a check for aligned sections not matching their VMAs.
This commit is contained in:
@@ -4100,6 +4100,50 @@ setup_bfd_headers (bfd *ibfd, bfd *obfd)
|
||||
return;
|
||||
}
|
||||
|
||||
static inline signed int
|
||||
power_of_two (bfd_vma val)
|
||||
{
|
||||
signed int result = 0;
|
||||
|
||||
if (val == 0)
|
||||
return 0;
|
||||
|
||||
while ((val & 1) == 0)
|
||||
{
|
||||
val >>= 1;
|
||||
++result;
|
||||
}
|
||||
|
||||
if (val != 1)
|
||||
/* Number has more than one 1, i.e. wasn't a power of 2. */
|
||||
return -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
image_scn_align (unsigned int alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case 8192: return IMAGE_SCN_ALIGN_8192BYTES;
|
||||
case 4096: return IMAGE_SCN_ALIGN_4096BYTES;
|
||||
case 2048: return IMAGE_SCN_ALIGN_2048BYTES;
|
||||
case 1024: return IMAGE_SCN_ALIGN_1024BYTES;
|
||||
case 512: return IMAGE_SCN_ALIGN_512BYTES;
|
||||
case 256: return IMAGE_SCN_ALIGN_256BYTES;
|
||||
case 128: return IMAGE_SCN_ALIGN_128BYTES;
|
||||
case 64: return IMAGE_SCN_ALIGN_64BYTES;
|
||||
case 32: return IMAGE_SCN_ALIGN_32BYTES;
|
||||
case 16: return IMAGE_SCN_ALIGN_16BYTES;
|
||||
case 8: return IMAGE_SCN_ALIGN_8BYTES;
|
||||
case 4: return IMAGE_SCN_ALIGN_4BYTES;
|
||||
case 2: return IMAGE_SCN_ALIGN_2BYTES;
|
||||
case 1: return IMAGE_SCN_ALIGN_1BYTES;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a section in OBFD with the same
|
||||
name and attributes as ISECTION in IBFD. */
|
||||
|
||||
@@ -4224,6 +4268,8 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
|
||||
if (!bfd_set_section_size (osection, size))
|
||||
err = _("failed to set size");
|
||||
|
||||
bool vma_set_by_user = false;
|
||||
|
||||
vma = bfd_section_vma (isection);
|
||||
p = find_section_list (bfd_section_name (isection), false,
|
||||
SECTION_CONTEXT_ALTER_VMA | SECTION_CONTEXT_SET_VMA);
|
||||
@@ -4233,6 +4279,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
|
||||
vma = p->vma_val;
|
||||
else
|
||||
vma += p->vma_val;
|
||||
vma_set_by_user = true;
|
||||
}
|
||||
else
|
||||
vma += change_section_address;
|
||||
@@ -4240,6 +4287,8 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
|
||||
if (!bfd_set_section_vma (osection, vma))
|
||||
err = _("failed to set vma");
|
||||
|
||||
bool lma_set_by_user = false;
|
||||
|
||||
lma = isection->lma;
|
||||
p = find_section_list (bfd_section_name (isection), false,
|
||||
SECTION_CONTEXT_ALTER_LMA | SECTION_CONTEXT_SET_LMA);
|
||||
@@ -4249,6 +4298,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
|
||||
lma += p->lma_val;
|
||||
else
|
||||
lma = p->lma_val;
|
||||
lma_set_by_user = true;
|
||||
}
|
||||
else
|
||||
lma += change_section_address;
|
||||
@@ -4259,6 +4309,24 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
|
||||
SECTION_CONTEXT_SET_ALIGNMENT);
|
||||
if (p != NULL)
|
||||
alignment = p->alignment;
|
||||
else if (pe_section_alignment != (bfd_vma) -1
|
||||
&& bfd_get_flavour (obfd) == bfd_target_coff_flavour)
|
||||
{
|
||||
alignment = power_of_two (pe_section_alignment);
|
||||
|
||||
if (coff_section_data (ibfd, isection))
|
||||
{
|
||||
struct pei_section_tdata * pei_data = pei_section_data (ibfd, isection);
|
||||
|
||||
if (pei_data != NULL)
|
||||
{
|
||||
/* Set the alignment flag of the input section, which will
|
||||
be copied to the output section later on. */
|
||||
pei_data->pe_flags &= ~IMAGE_SCN_ALIGN_POWER_BIT_MASK;
|
||||
pei_data->pe_flags |= image_scn_align (pe_section_alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
alignment = bfd_section_alignment (isection);
|
||||
|
||||
@@ -4267,6 +4335,32 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
|
||||
if (!bfd_set_section_alignment (osection, alignment))
|
||||
err = _("failed to set alignment");
|
||||
|
||||
/* If the output section's VMA is not aligned
|
||||
and the alignment has changed
|
||||
and the VMA was not set by the user
|
||||
and the section does not have relocations associated with it
|
||||
then warn the user. */
|
||||
if (osection->vma & ((1 << alignment) - 1)
|
||||
&& alignment != bfd_section_alignment (isection)
|
||||
&& change_section_address == 0
|
||||
&& ! vma_set_by_user
|
||||
&& bfd_get_reloc_upper_bound (ibfd, isection) < 1)
|
||||
{
|
||||
non_fatal (_("output section %s's alignment does not match its VMA"), name);
|
||||
}
|
||||
|
||||
/* Similar check for a non-aligned LMA.
|
||||
FIXME: Since this is only an LMA, maybe it does not matter if
|
||||
it is not aligned ? */
|
||||
if (osection->lma & ((1 << alignment) - 1)
|
||||
&& alignment != bfd_section_alignment (isection)
|
||||
&& change_section_address == 0
|
||||
&& ! lma_set_by_user
|
||||
&& bfd_get_reloc_upper_bound (ibfd, isection) < 1)
|
||||
{
|
||||
non_fatal (_("output section %s's alignment does not match its LMA"), name);
|
||||
}
|
||||
|
||||
/* Copy merge entity size. */
|
||||
osection->entsize = isection->entsize;
|
||||
|
||||
@@ -5713,15 +5807,8 @@ copy_main (int argc, char *argv[])
|
||||
fatal (_("bad format for --set-section-alignment: numeric argument needed"));
|
||||
|
||||
/* Convert integer alignment into a power-of-two alignment. */
|
||||
palign = 0;
|
||||
while ((align & 1) == 0)
|
||||
{
|
||||
align >>= 1;
|
||||
++palign;
|
||||
}
|
||||
|
||||
if (align != 1)
|
||||
/* Number has more than on 1, i.e. wasn't a power of 2. */
|
||||
palign = power_of_two (align);
|
||||
if (palign == -1)
|
||||
fatal (_("bad format for --set-section-alignment: alignment is not a power of two"));
|
||||
|
||||
/* Add the alignment setting to the section list. */
|
||||
@@ -5938,6 +6025,11 @@ copy_main (int argc, char *argv[])
|
||||
case OPTION_PE_SECTION_ALIGNMENT:
|
||||
pe_section_alignment = parse_vma (optarg,
|
||||
"--section-alignment");
|
||||
if (power_of_two (pe_section_alignment) == -1)
|
||||
{
|
||||
non_fatal (_("--section-alignment argument is not a power of two: %s - ignoring"), optarg);
|
||||
pe_section_alignment = (bfd_vma) -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPTION_SUBSYSTEM:
|
||||
|
||||
Reference in New Issue
Block a user