public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Ulf Samuelsson <binutils@emagii.com>
To: Nick Clifton <nickc@redhat.com>,
	binutils@sourceware.org, Jan Beulich <jbeulich@suse.com>
Subject: Re: RFC: generating a header using the linker (ASCII, ASCIZ commands)
Date: Mon, 13 Feb 2023 17:04:31 +0100	[thread overview]
Message-ID: <324a63be-1403-edf1-23ad-6fd11e524529@emagii.com> (raw)
In-Reply-To: <7216fa28-4769-5bd2-a508-bf71184727fd@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 6209 bytes --]


Den 2023-02-13 kl. 15:11, skrev Nick Clifton:
> Hi Ulf,
>
>>> From the sound of what you have written below it would be
>>> easier to use the assembler to create the header 
>
>> One of the problems is time of build.
>> The header should contain the time when things are linked together, 
>> not when things are compiled.
>>
>> Another is that one of the fields is the size of the application 
>> which is only known at link time.
>>
>> Doing things in the linker seems to be the cleanest way.
>>
>> We would probably have the header is in a separate file which is 
>> included in the linker script.
>
> If you need to compute information in the header based upon the
> actual linked executable then you will not be able to do so from
> inside a linker script.  (Well not without modifying the linker,
> and I am trying to avoid that).
>
> But - what you can do is post-process the linked file to extract
> the information you want, create a separate file containing the
> header constructed from this information, and then insert the
> header into the executable, without relinking it.  (I am thinking
> of objcopy's --add-section command line option here).
>
> Alternatively you could link with a dummy header that is basically
> empty and then use a tool like GNU Poke[1] to insert the necessary
> bytes and strings afterwards.

This is what a typical header looks like:

header:

            QUAD(TAG1)                            // 0

ECC:    QUAD(ECC(SYNDROME, START_OF_ECC, .end_of_text))     // 8

START_OFF_ECC:

BUILDTIME:

             QUAD(SECONDS_SINCE_1970)               // 16

ENTRY: LONG(program_entry)                 // 24

SIZE:   LONG(.end_of_text - .start_of_text)                 // 28

            BYTE(VERSION1)                         // 32

            BYTE(VERSION2)                         // 33

            BYTE(VERSION3)                         // 34

            BYTE(VERSION3)                         // 35

            LONG(0)                             // 36

            LONG(0)                             // 40

            LONG(0)                             // 44

APPLICATION:

            ASCII    16, "MyApp"                          // 48

            ASCII    32, "A special app"                        // 64

            ASCII    32, "With Info"                            // 96

HELP

            ASCII    120 "No help available"                     // 120

            QUAD(TAG2)                          // 248

Total Size = 265 byte

Most of the header info is part of the linker file.
The linker needs to compute:
    ECC:

    BUILDTIME:

    ENTRY:

    SIZE:

===
We already discussed ideas for ECC.

For buildtime, we currently added an include file which we create during 
the linking process.

To have a BUILDTIME directive that generates a 64-bit word with "seconds 
since 1970-01-01 00:00"
does not seem to be very difficult - at least on linux.
Parse the call and get the |__time64_t |seconds from the OS.

ENTRY and SIZE is supported right now in the linker.

Best Regards
Ulf Samuelsson

>
> [1] http://www.jemarch.net/poke
>
>
>> Assume you have the following flash sectors.
>>
>> * 64kB (65536 bytes)
>> * 64kB (65536 bytes)
>> * 128kB
>> * n x 256kB
>>
>> The bootloader resides in the first 64 kB sector and the application 
>> starts in the second 64kB sector.
>>
>> If the application <= 65536 bytes, the section should be 64kB and 
>> should be filled with a FILL value
>>
>> If the application is 65540 bytes, the section should be 64kB+128kB 
>> and should be filled with a FILL value
>
> Ah yes.  This is a known problem for the linker.  It does not have a 
> mechanism
> to distribute section(s) across multiple memory regions, using one 
> until it is full
> and then switching to another.

I don't think we need to distribute sections amongs multiple regions.

I just need to say that the PC should be aligned to the next 64kB 
boundary and it
should be filled with my fill value.

Then I need to check the PC and if it is not at the end of a flash segment,
I want to add an additional BYTE(0xFF) and again align to the next segment.

The following would handle application up to 512kB.

     . = ALIGN(64kB)

if (. == 0x30000)

     BYTE(0xFF)

     . = ALIGN(64kB)

end if

if (. == 0x50000)

     BYTE(0xFF)

     . = ALIGN(64kB)

end if


if (. == 0x60000)

     BYTE(0xFF)

     . = ALIGN(64kB)

end if


if (. == 0x70000)

     BYTE(0xFF)

     . = ALIGN(64kB)

end if

>
> I am sorry, but I do not have an easy workaround for you.  If you are 
> able to try
> multiple links, you could start with one that just uses the smallest 
> memory configuration
> first, and if that fails move up to bigger configurations, possibly 
> with different
> assignments of sections to memory regions afterwards.
>
>
>> Would you consider adding ielftools to binutils?
>
> I would prefer to leave it as a separate project for now.  I am worried
> about bringing in a tool that will only be of use to a very small 
> audience
> (maybe just you ?) and having to maintain it.  Of course if you can 
> persuade
> more people to request that the sources be integrated then I can take 
> abother
> look at the issue...
>
>> Note that if the linker can call an external tool to compute the CRC
>> based on the extracted text segment, and insert that into the 
>> resulting ELF file.
>> then this is superior to running a utility afterwards.
>
> Actually -- there might be a way to do this: A linker plugin.  The 
> linker already
> has the architecture to support plugins, and you could create a new 
> one which would
> scan the text section, compute a CRC and then insert the value into a 
> header in the
> linked image...
>
OK, tell me more!

> Cheers
>   Nick
>
>

  reply	other threads:[~2023-02-13 16:04 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-08 17:36 Ulf Samuelsson
2023-02-13 10:09 ` Nick Clifton
2023-02-13 11:12   ` Ulf Samuelsson
2023-02-13 12:33     ` Jan Beulich
2023-02-13 15:54       ` Ulf Samuelsson
2023-02-13 14:11     ` Nick Clifton
2023-02-13 16:04       ` Ulf Samuelsson [this message]
2023-02-14 16:06         ` Nick Clifton
2023-02-14 18:12           ` Ulf Samuelsson
2023-02-15 20:07       ` RFC: generating a header using the linker (CRC calculation) Ulf Samuelsson
2023-02-15 21:01         ` Ulf Samuelsson
2023-02-15 21:29           ` Paul Koning
2023-02-15 22:08             ` Ulf Samuelsson
2023-02-15 22:11               ` Paul Koning
2023-02-16  6:45                 ` Ulf Samuelsson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=324a63be-1403-edf1-23ad-6fd11e524529@emagii.com \
    --to=binutils@emagii.com \
    --cc=binutils@sourceware.org \
    --cc=jbeulich@suse.com \
    --cc=nickc@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).