This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: don't sign-extend address in ihex files


The Intel Hex format reader in BFD sign-extends some addresses on
64-bit targets.

Consider the following ihex file:

:0200000480007A
:101B6C00000000010000000200000003000000045F
:101B7C00000000050000000600000007000000083F
:101B8C00000000090000000A0000000B0000000C1F
:101B9C000000000D0000000E0000000F00000010FF
:101BAC0000000011000000120000001300000014DF
:101BBC0000000015000000160000001700000018BF
:101BCC00000000190000001A0000001B0000001C9F
:101BDC000000001D0000001E0000001F000000207F
:00000001FF

An ihex data record (type 00) has a fixed-width 16-bit address field.
To place data at addresses above 64k, a file can contain Extended
Linear Address records (type 04), which supply the top 16 address bits
for subsequent data records.

In the above example, the first line is an Extended Linear Address
record, setting the top 16 address bits to 0x8000.  The second line is
a data record with an offset of 0x1b6c; its data should be stored at
0x80001b6c.

On any system where bfd_vma is 64 bits long, BFD will actually store
that record at 0xffffffff80001b6c.  Since the value of the hex_value
macro (defined in libiberty.h) is signed, the type of a HEX2 or HEX4
macro (defined in ihex.c) is signed; casting that to an unsigned
64-bit integer type causes the value to be sign-extended.

This situation actually arises on Linux for the IBM s390x 64-bit
processor.  The linker likes to locate data around 0x80000000, so
dumping values in ihex format with GDB's 'dump' command produces ihex
values that the binutils won't process properly.

It's worth pointing out that the Intel Hex format spec doesn't
actually say anything about how 32-bit addresess should be interpreted
on systems where addresses are 64 bits long.  And there are processors
(e.g., MIPS) that customarily sign-extended 32-bit addresses when used
in a 64-bit context.  So while this patch fixes a bug on the s390x,
it's not clear it's universally right, and there's no authority to
settle the question.  And since ihex records don't give any indication
of the architecture they're intended for (they're just a hex dump),
BFD can't discriminate based on the architecture.

But I'd argue that the format itself treats addresses as unsigned.
Data records' 16-bit addresses are not sign-extended when an ihex file
is loaded into a 32-bit system in the absence of a Extended Linear
Address records.  If one uses Extended Address Records to generate
20-bit addresses, those aren't sign-extended to make 32-bit addresses.
So it seems most consistent not to sign-extend 32-bit addresses on a
64-bit system.

Here is a patch.

2003-05-07  Jim Blandy  <jimb@redhat.com>

	* ihex.c (NIBBLE): Make this unsigned, to avoid sign-extension
	when the value of a HEX2 or HEX4 application gets stored in a
	64-bit bfd_vma.

Index: bfd/ihex.c
===================================================================
RCS file: /cvs/src/src/bfd/ihex.c,v
retrieving revision 1.18
diff -c -c -F'^(' -r1.18 ihex.c
*** bfd/ihex.c	30 Nov 2002 08:39:39 -0000	1.18
--- bfd/ihex.c	13 May 2003 19:53:10 -0000
***************
*** 158,164 ****
  
  /* Macros for converting between hex and binary.  */
  
! #define NIBBLE(x)    (hex_value (x))
  #define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
  #define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
  #define ISHEX(x)     (hex_p (x))
--- 158,178 ----
  
  /* Macros for converting between hex and binary.  */
  
! /* NIBBLE is unsigned, to avoid sign-extension in bfd_vma values.
! 
!    Every use of HEX2 and HEX4 in this file converts the value to an
!    unsigned type --- sometimes unsigned int, sometimes bfd_vma.  The
!    latter is larger than an int on some platforms, so if HEX2 and HEX4
!    are signed, 32-bit addresses from ihex files will be sign-extended
!    when they're made into bfd_vma values.
! 
!    Since we don't sign-extend 16-bit addresses from data records, nor
!    20-bit addresses generated with Extended Address or Start Address
!    records, it seems most consistent not to sign-extend the 32-bit
!    addresses generated with Extended Linear Address and Start Linear
!    Address records.  */
! 
! #define NIBBLE(x)    ((unsigned) hex_value (x))
  #define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
  #define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
  #define ISHEX(x)     (hex_p (x))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]