gnupic: gpasm `relocatable mode' and org directives (bugfix,patch)
Subject:
gpasm `relocatable mode' and org directives (bugfix,patch)
From:
Ian Jackson ####@####.####
Date:
25 Apr 2005 03:09:17 +0100
Message-Id: <17004.20803.109754.93585@davenant.relativity.greenend.org.uk>
When gpasm is producing an object file for future linking, which the
manual calls `relocatable mode', there is an infelicity in the
processing of `org' directives without explicit section names.
If the program contains two such directives, they'll use the same
autogenerated section name, producing the following error from the
linker:
error: section ".org_0" is absolute but occurs in more than one file
gpasm/directive.c (gputils 0.12.4) tries to generate a unique section
name, but the names are only unique within a file - not unique
throughout the whole program. I suggest the simple patch below, which
additionally encodes the address (from the RHS of the .org) into the
autogenerated name. Thus a program which says `org X' in one file and
`org Y' in another will link so long as X != Y. I've tested this and
it seems to work for me.
You'll see that in the patch I moved the assignment of new_sec_addr.
This is so that I could use it in the snprintf. r could be used
instead, but it is a gpasmVal and would have to be cast to a concrete
C type (eg to unsigned long) so that the right printf format specifier
could be known and be used (%lx in that case). new_sec_addr is an int
so it can be printed with %x. I should point out that it is (at least
technically) wrong that ints are used for PIC addresses, because the
guarantee made by the C Standard is only that an int can hold at least
16 bits' worth. gpasm will go wrong on hosts with 16-bit ints (for
example, certain DOS memory models). Fixing that would require fairly
widespread changes and I think it's best left for another day :-).
Thanks,
Ian.
--- gpasm/directive.c~ Fri Sep 24 21:56:28 2004
+++ gpasm/directive.c Mon Apr 25 02:45:25 2005
@@ -1634,8 +1634,8 @@
} else {
/* Default section name, this will be overwritten if a label is
present. */
- snprintf(state.obj.new_sec_name, sizeof(state.obj.new_sec_name), ".org_%d", state.obj.org_num++);
state.obj.new_sec_addr = r;
+ snprintf(state.obj.new_sec_name, sizeof(state.obj.new_sec_name), ".org_%d_%x", state.obj.org_num++, state.obj.new_sec_addr);
state.obj.new_sec_flags = STYP_TEXT | STYP_ABS;
state.lst.line.linetype = sec;
state.next_state = state_section;
--
Ian Jackson, at home. Local/personal: ####@####.####
####@####.#### http://www.chiark.greenend.org.uk/~ijackson/