The attached patches correct an issue that exists in gas. The problem is general but only manifests itself when OCTETS_PER_BYTE > 1. I have found the problem in binutils 2.22 in connection with TI C4x (i.e. ./configure --target=c4x-coff).
Function frag_offset_fixed_p in frags.[ch] returns an offset through its last parameter. The parameter type is bfd_vma which is unsigned. The only calls to the function are in expr.c; the offset is returned to local variables frag_off which are also of type bfd_vma. The variables frag_off are divided by OCTETS_PER_BYTE; the problem is that these divisions are unsigned as a result of the use of bfd_vma. Dividing these offsets must be done signed. No actual division takes place when OCTETS_PER_BYTE = 1 so this problem only manifests itself when OCTETS_PER_BYTE > 1. These uses of bfd_vma are the only ones in the three sources expr.c, frags.c, frags.h. I believe all these uses of bfd_vma should be changed to offsetT. This will be more consistent with the definitions of the struct members used in frag_offset_fixed_p and the fact that the returned value is supposed to be an offset; it also makes the divisions produce the correct values when OCTETS_PER_BYTE > 1. Please consider these patches for future binutils releases. The revisions of the original expr.c, frags.c, and frags.h are respectively 1.90, 1.30.2.1, and 1.24.4.1. Thanks, Johan Olmutz Nielsen --- expr.1.90.c 2011-03-17 11:59:29.000000000 +0100 +++ expr.c 2012-06-22 12:33:40.531010600 +0200 @@ -1746,7 +1746,7 @@ while (op_left != O_illegal && op_rank[(int) op_left] > rank) { segT rightseg; - bfd_vma frag_off; + offsetT frag_off; input_line_pointer += op_chars; /* -> after operator. */ @@ -2030,7 +2030,7 @@ valueT left, right; segT seg_left, seg_right; fragS *frag_left, *frag_right; - bfd_vma frag_off; + offsetT frag_off; switch (op) { --- frags.1.30.2.1.c 2011-11-21 10:29:28.000000000 +0100 +++ frags.c 2012-06-22 12:23:46.886766700 +0200 @@ -394,10 +394,10 @@ not already accounted for in the frag FR_ADDRESS. */ bfd_boolean -frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, bfd_vma *offset) +frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset) { const fragS *frag; - bfd_vma off; + offsetT off; /* Start with offset initialised to difference between the two frags. Prior to assigning frag addresses this will be zero. */ --- frags.1.24.4.1.h 2011-11-21 10:29:28.000000000 +0100 +++ frags.h 2012-06-22 12:23:02.655089200 +0200 @@ -151,6 +151,6 @@ offsetT offset, char *opcode); -bfd_boolean frag_offset_fixed_p (const fragS *, const fragS *, bfd_vma *); +bfd_boolean frag_offset_fixed_p (const fragS *, const fragS *, offsetT *); #endif /* FRAGS_H */ _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils