Bug 24942 - objcopy: Add option for setting section alignment
Summary: objcopy: Add option for setting section alignment
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.33
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-08-27 15:11 UTC by Niklas Gürtler
Modified: 2019-11-29 05:42 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Patch for adding --set-section-alignment (2.13 KB, patch)
2019-08-27 15:11 UTC, Niklas Gürtler
Details | Diff
Patch for specifying powers of two instead of exponents (1.08 KB, patch)
2019-09-24 16:44 UTC, Niklas Gürtler
Details | Diff
Another patch (1.42 KB, patch)
2019-10-02 11:02 UTC, Nick Clifton
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Niklas Gürtler 2019-08-27 15:11:59 UTC
Created attachment 11965 [details]
Patch for adding --set-section-alignment

When using the old trick¹ of using objcopy to convert arbitrary binary files into ELF (".o") files for including e.g. pictures or fonts into program memory, objcopy currently always sets the alignment of the produced ELF section to "1". When linking this file, the contained binary data can end up at an address that is not properly aligned, which might render it inaccessible for word-wise access or even DMA (on embedded targets).

Therefore, I would like to propose adding a command line option to objcopy to set the alignment of the produced section. Please see the attached git patch file for a possible implementation. It adds an option "--set-section-alignment <name>=<align>" that works much like "--set-section-flags", but expects a simple integer as "<align>". The specified alignment will override the alignment of the input section (if any).

Could this be included in the official binutils code?

1: https://mcuoneclipse.com/2018/01/27/converting-a-raw-binary-file-into-an-elf-dwarf-file-for-loading-and-debugging/
Comment 1 Nick Clifton 2019-08-28 09:15:25 UTC
Hi Niklas,

  There is an easier way of solving this problem - the assembler's .incbin
  directive.  For example:

  % cat foo.s
	.section foo-image, "a", @progbits
	.align 4
	.global start_of_foo
start_of_foo:
	.incbin "foo.jpg"
	.global end_of_foo
end_of_foo:

  Assembling this will create an object file called foo.o which contains
  the contents of foo.jpg in a section called foo-image, and which is 
  aligned to 4 bytes.

Cheers
  Nick
Comment 2 Niklas Gürtler 2019-08-28 09:31:02 UTC
Hi Nick,

I knew about "incbin" but needing an (additional) assembly file seems somewhat clunky. There are even more possibilities: Putting each converted .o file into its own section, and aligning those sections via the final linker script. Hacking together a tool that modifies the alignment field in the ELF header. It might even be possible to do a partial linking step to set the alignment of a objcopy-produced .o-file using a linker script.

However, if objcopy is capable of converting binary to ELF, then why not make it actually useful by setting the alignment requirement, especially since it's a rather simple fix? This would allow us to produce the desired .o file with one simple step.

Greetings,
Niklas
Comment 3 cvs-commit@gcc.gnu.org 2019-08-28 11:35:08 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=fa463e9fc644e7a3bad39aa73bf6be72ea865805

commit fa463e9fc644e7a3bad39aa73bf6be72ea865805
Author: Niklas G?rtler <profclonk@gmail.com>
Date:   Wed Aug 28 12:33:41 2019 +0100

    Add an option to objcopy to change the alignment of sections.
    
    	PR 24942
    	* objcopy.c (SECTION_CONTEXT_SET_ALIGNMENT): New constant.
    	(struct section_list): Add alignment field.
    	(command_line_switch): Add OPTION_SET_SECTION_ALIGNMENT.
    	(copy_options): Add --set-section-alignment.
    	(copy_usage): Describe --set-section-alignment.
    	(find_section_list): Initialise the alignment field.
    	(setup_section): Handle the alignment field.
    	(copy_main): Handle OPTION_SET_SECTION_ALIGNMENT.
    	* doc/binutils.texi: Document the new feature.
    	* NEWS: Mention the new feature.
Comment 4 Nick Clifton 2019-08-28 11:37:35 UTC
Hi Niklas,

  Very well, since the patch is simple enough to count as obvious, I have gone
  ahead and applied it.

Cheers
  Nick
Comment 5 Niklas Gürtler 2019-08-28 11:48:40 UTC
Hi Nick,

awesome, thank you! Now just to wait for the release... :)

Have a nice day,
Niklas
Comment 6 Fangrui Song 2019-09-17 12:09:40 UTC
+@item --set-section-alignment @var{sectionpattern}=@var{align}
+Set the alignment for any sections matching @var{sectionpattern}.  @var{align}
+specifies the alignment as the exponent for the power of two, i.e. the
+alignment in bytes will be 2^@var{align}.

objcopy -I binary -B i386:x86-64 -O elf64-x86-64 --set-section-alignment .data=8 a.txt a.o

I would expect the alignment of .data to be 8, instead of 256. Specifying the exponent for the power of two may be awkward, I hope you can change this.
Comment 7 Fangrui Song 2019-09-17 12:12:49 UTC
In addition, have you thought about its interaction with --rename-section? Which command should I use:

objcopy --rename-section=.foo=.foo2 --set-section-alignment .foo=8 a.o b.o

or

objcopy --rename-section=.foo=.foo2 --set-section-alignment .foo2=8 a.o b.o
Comment 8 Niklas Gürtler 2019-09-17 12:22:07 UTC
I think not all BFD targets support arbitrary alignment, some may only support powers of 2. The internal representation in the BFD library stores only the exponent, so there would have to be a conversion (i.e. log2), with additional potential for errors, so I think it's best to have the user do that and document it properly. The ".align" directive also works this way (at least on ARM).

When using --rename-section, the original section name would need to be specified for --set-section-alignment, just like with --set-section-flags.
Comment 9 Fangrui Song 2019-09-24 03:18:36 UTC
I don't require the support for non power-of-2 alignment. I just want to say
--set-section-alignment .foo=8 => sh_addralign=256  is counterintuitive. It is not what readelf -S displays. (objdump -h displays it as `2**8`. The `**` at least makes it clear that an exponent is involved.)

> I think not all BFD targets support arbitrary alignment, some may only support powers of 2.

We can simply reject non power-of-2 alignment when parsing the command line option, like what you've done when there is no string on the right of `=`

> The ".align" directive also works this way (at least on ARM).

I know that the .align directive is in powers of 2 on ARM/AArch64/MIPS/PowerPC, but it is in bytes on x86, Sparc and System z. I don't know how this inconsistency came, .balign and .p2align may be better.
Comment 10 James Henderson 2019-09-24 09:00:39 UTC
I'm with Fangrui on this one. Although I don't know of any instances of non-powers-of-2 alignment making sense, I still talk about an alignment of, say, 4, as "4" not "2". Similarly, tools print alignment as the actual value, not as a power of 2, in my experience. As such, I expect switches to conform to that. Indeed, as pointed out, that's exactly what .align does on many platforms, and also every tool I've ever used that has anything to do with alignment (in fact, I didn't even know .align had a different behaviour on some platforms).

Additionally, I think it's much more likely that a user who hasn't looked in depth at the documentation will try to specify the raw value, and then will end up with an incorrect modification, than the other way around. Furthermore, it is simpler for a user to not have to do the conversion of, say, 128 to 2 to the whatever.

If bfd can't support non-powers-of-2 alignment values, it should simply reject them at command-line parsing time, in my opinion.
Comment 11 Niklas Gürtler 2019-09-24 16:44:37 UTC
Created attachment 12002 [details]
Patch for specifying powers of two instead of exponents

Okay, here is a patch for specifying the alignment as a power of two instead of an exponent. I don't like it very much however...
Comment 12 Fangrui Song 2019-09-25 12:36:19 UTC
> Created attachment 12002 [details]

    if (palign <= 0 || palign & (palign-1))

can be used to simplify the code.
Comment 13 Fangrui Song 2019-10-02 06:11:19 UTC
Ping:)

FWIW, I have a patch to implement --set-section-alignment in llvm-objcopy https://reviews.llvm.org/D67656 . I don't want to cause gratuitous differences from GNU objcopy, so I haven't committed that change yet. At least two other people there think that specifying the raw value (instead of the exponent) is more intuitive.

A commitment from the binutils side that the two tools will be in agreement (with the release of binutils 2.33) is all what I need to proceed with that change.
Comment 14 cvs-commit@gcc.gnu.org 2019-10-02 10:56:25 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=de4859eacb74a440d9fd61e4a0f051e3737a05dd

commit de4859eacb74a440d9fd61e4a0f051e3737a05dd
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Oct 2 11:55:02 2019 +0100

    Change objcopy's --set-section-alignment option to take a byte alignment value rather than a power of two alignment value.
    
    	PR 24942
    	* objcopy.c (copy_usage): Update description of
    	--set-section-alignment.
    	(copy_main): Interpret numeric argument of --set-section-alignment
    	as a byte alignment, not a power of two alignment.
    	* doc/binutils.texi: Update description of
    	--set-section-alignment.
    	* testsuite/binutils-all/set-section-alignment.d: New test.
    	* testsuite/binutils-all/objcopy.exp: Run the new test.
Comment 15 cvs-commit@gcc.gnu.org 2019-10-02 10:58:37 UTC
The binutils-2_33-branch branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=146a3bb9cc78c459e63c23259d766b01c32df705

commit 146a3bb9cc78c459e63c23259d766b01c32df705
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Oct 2 11:57:16 2019 +0100

    Change objcopy's --set-section-alignment option so that it takes a byte alignment value rather than a power of two alignment value.
    
    	PR 24942
    	* objcopy.c (copy_usage): Update description of
    	--set-section-alignment.
    	(copy_main): Interpret numeric argument of --set-section-alignment
    	as a byte alignment, not a power of two alignment.
    	* doc/binutils.texi: Update description of
    	--set-section-alignment.
    	* testsuite/binutils-all/set-section-alignment.d: New test.
    	* testsuite/binutils-all/objcopy.exp: Run the new test.
Comment 16 Nick Clifton 2019-10-02 11:02:39 UTC
Created attachment 12014 [details]
Another patch

Hi Guys,

  Sorry for dropping the ball on this one.  I have now applied a
  slight variation on Niklas's second patch, with a little bit of
  code tidying and the addition of a test case.

  I have applied the patch to the mainline and the 2.33 branch,
  but the patch might not be in the official 2.33 release, if the
  release tarballs have already been made.

Cheers
  Nick
Comment 17 Isa Bella 2019-11-29 05:42:29 UTC Comment hidden (spam)