Bug 997 - invalid error messages, and internal error abort
Summary: invalid error messages, and internal error abort
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: pre-2.15
: P2 normal
Target Milestone: ---
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks: 998
  Show dependency treegraph
 
Reported: 2005-06-08 20:12 UTC by Alan Larson
Modified: 2022-06-22 06:22 UTC (History)
1 user (show)

See Also:
Host: i386-pc-freebsd
Target: i386
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alan Larson 2005-06-08 20:12:15 UTC
azp:44% cat h.s
        .data

msg:    .asciz  "hello world.\n"
msglen = .-msg-1
msglen=msglen & 0xff
azp:45% as -a h.s -o h.o
h.s: Assembler messages:
h.s:5: Error: symbol definition loop encountered at `msglen'
h.s:5: Error: undefined symbol `msglen' in operation setting `msglen'
h.s:5: Internal error, aborting at
/usr/src/gnu/usr.bin/binutils/as/i386-freebsd/../../../../../contrib/binutils/gas/symbols.c
line 1166 in resolve_symbol_value
Please report this bug.
azp:46% as h.s -o h.o

Interesting that it doesn't crash with -a flag.
Comment 1 Alan Modra 2005-06-09 06:29:42 UTC
This is a consequence of the way gas resolves symbols.  The problem is that the
first assignment to msglen isn't resolved immediately when parts of the
expression use symbols ("." and "msg" here) in different frags.  A frag is a
chunk of code/data being assembled, with a fixed part and a variable part. 
Because gas knows that frags might have a variable part, it leaves such
expressions for later evaluation, after all frags have their variable parts
fixed.  Thus the second assignment to msglen also can't be evaluated
immediately, and gas simply sets the value of msglen to "msglen & 0xff", exactly
as would be done if the first assignment had never been encountered.  Which
results in a symbol definition loop.

The reason that -a causes the failure is that turning on listings employs a hack
where a frag is allocated for each line.  However, this can happen without -a if
 a new frag is needed for some other reason.

I see a number of possible solutions, all of which I'm disinclined to implement
myself.
1) Rewrite gas listing code to do without frags, possibly combined with
2) Modify gas symbol evaluation code to allow immediate subtraction of symbols
in different frags if all intervening frags are fixed in size.
3) Have gas generate multiple versions of symbols.

(3) is probably the easiest to implement.  You can do it yourself at the user
level, of course:

msg: .asciz  "hello world.\n"
x = .-msg-1
msglen=x & 0xff
Comment 2 Alan Larson 2005-06-13 23:21:33 UTC
Subject: Re:  invalid error messages, and internal error abort


That explains why the problem also affects things like:
	.if	xlen & 1		/* is length odd? */
fails.

It looks to me like the evaluation should be forced at the point that
the value is needed, such as the .if mentioned here, the pushl $xlen,
the foo=foo&3  --if it cannot be evaluated then, it is either an error
or a 32 bit value.

As for  -a  causing the different push instruction being used, this is a
particularly annoying problem, as it is a perfectly reasonable thing to
assemble a program with a listing to find where it failed running the
binary from a previous assemble.  It is also desirable for a binary
built for production (with an assembly listing for documentation) to
generate optimal code.

	Alan