Created attachment 11268 [details]
Linker script used to create the un-ihex-able elf file
Trying to convert elf to ihex files fails:
$ mipsel-elf-gcc -nostdlib -T./link.ld ./main.c -o out.elf
$ mipsel-elf-objcopy -O ihex out.elf out.hex
mipsel-elf-objcopy: out.hex: address 0xffffffff9d005a00 out of range for Intel Hex file
mipsel-elf-objcopy:out.hex: bad value
The reason is that ihex only supports 32-bit values, and the elf32-littlempis bfd sign-extends vma addresses, causing them to go out of range.
The behaviour can be tested with the source file and attached linker script:
Created attachment 11269 [details]
Workaround checking for signedness
This is the best workaround I could come up with (based on Pinguino.cc own workaround).
It has a flaw that by excluding the range 0x7fffffff..0xffffffff, it will break non-sign-extended (source) targets. a better solution would let the ihex printer know whether the original addresses were sign-extended.
The bfd_target struct could be extended, to carry some signedness about the input bfd.
Or, the ihex target could get a backend_data structure (currently null), copying the input backend.
Or, the ihex backend could get a special treatment somewhere inside copy_file. It's likely to be many places, and it likely would have to indicate that it needs such a treatment in a special way.
(In reply to rhn from comment #1)
> Created attachment 11269 [details]
> Workaround checking for signedness
[Sorry I have not had time to look at this, but...]
> The bfd_target struct could be extended, to carry some signedness about the
> input bfd.
If the bfd_target's flavour is bfd_target_elf_flavour then you can
cast bfd target's backend field to a struct elf_backend_data pointer
(or use the xvec_get_elf_backend_data macro). Then you can access the
sign_extend_vma field, which will be set for targets like the MIPS which
use signed address ranges.
the target bfd is actually bfd_target_ihex_flavor, which is at the core of the issue.
One of the solutions I was thinking about was to create an ihex backend with only the signedness information in it. That would still require ihex-specific changes in the copy procedure somewhere though. I couldn't easily identify where those would be needed, but I'm happy to dig deeper if you think it's the way forward.
Thanks for taking a look,
(In reply to rhn from comment #3)
> the target bfd is actually bfd_target_ihex_flavor, which is at the core of
> the issue.
Presumably this is the output bfd. Do you not have access to
the input bfd as well ? For example, could you put a check in
ihex_set_section_contents() ? (Following the asection->owner
pointer). Then you can make sure that the content conversion
is sign-extended as appropriate...
Yes, the ihex bfd is the output bfd. Thank you for pointing me the right direction with ihex_set_section_contents().
It turns out that the last time the input section/bfd may be access is in copy_section(), when bfd_set_section_contents() is called. This, in turn, calls ihex_set_section_contents(), where no access to the input bfd is possible.
Seeing that the signature for both _set_section_contents() function contains input bfd data:
bfd_set_section_contents (bfd *abfd,
const void *location,
, then I think adding a new parameter `bool sign_extend_vma` might do the job, if inelegantly. The address would be set correctly inside ihex_set_section_contents() in this scenario.
What do you think about that?
(In reply to rhn from comment #5)
> bfd_set_section_contents (bfd *abfd,
> sec_ptr section,
> const void *location,
> file_ptr offset,
> bfd_size_type count)
> , then I think adding a new parameter `bool sign_extend_vma` might do the
> job, if inelegantly. The address would be set correctly inside
> ihex_set_section_contents() in this scenario.
> What do you think about that?
Not a good idea IMHO, because it will mean changing a lot of code in order
to fix a very minor bug. (I apologise if you do not consider this bug to
be minor, but from the perspective of all of the architectures and file
formats supported by the BFD library, mips+ihex is a rather obscure
I am beginning to think that the original patch might actually be the best
approach. Perhaps with a small modification so that it only checks and
masks out the top 32-bits of the address. Ie it ignores the sign bit in
bit-31 and clips all addresses to 32-bits, issuing a warning only if the
upper 32 bits are not identical.
Created attachment 11288 [details]
Detect and reject 64-bit addresses.
I do not have emotional attachment to bugs, no need to apologise. I trust that you know whether this one highlights a bigger issue in the architecture or can be fixed locally.
Here's a new version of the patch. It does two things to determine whether the address was 64-bit:
- checks whether top 32 bits are the same
- removes addresses starting with top 32 bit set but bit 31 unset, as they couldn't have come from valid 32-bit addresses: sign extension would set the top to 0s, no sign extension they would have to be 0s already
This strategy will leave false negatives, since both 0x00000000ffffffff and 0xffffffffffffffff are always valid addresses now.
Since seeing impossible addresses means that 64-bit code has been provided, I decided to keep the error instead of the warning.
There's another possible way to tackle this. The code could match against bfd->arch_info.arch, and figure out sign extension behaviour from that somehow? Or even embed that flag in bfd_arch_info?
I just wanted to check if there's anything else I can do to help fix this bug.
> I just wanted to check if there's anything else I can do to help fix this bug.
No - just keep pinging me. I am actually on vacation at the moment,
but I will keep this email in my queue and get back tot he problem once I
return to work.
The master branch has been updated by Nick Clifton <firstname.lastname@example.org>:
Author: rhn <email@example.com>
Date: Fri Nov 9 14:09:44 2018 +0000
Stop corruption of ihex output shen addresses are sign extended.
* ihex.c (ihex_write_object_contents): Check for sign extended
addresses that cannot be supported in the ihex format.
Right - sorry for the delay. I have now checked in your patch from comment
#7, which I think is probably the best solution that we will get for this
problem. Thanks very much for persisting with this issue.
Thank you for letting this change go through! I can't wait to test out a new release :)
The master branch has been updated by Alan Modra <firstname.lastname@example.org>:
Author: Alan Modra <email@example.com>
Date: Tue Jan 8 22:21:57 2019 +1030
PR24065, 32-bit objcopy fails with 64-bit address ... out of range
* ihex.c (ihex_write_object_contents): Properly check 32-bit