[PATCH] Add support for ARM ELF Mapping Symbols

Nick Clifton nickc@redhat.com
Thu Nov 13 14:19:00 GMT 2003


Hi Guys.

  The ARM ELF spec requires that special mapping symbols be generated
  at the start of arm and thumb regions of code and at the start of
  data.  The patch below adds support to GAS to generate these
  symbols.

  Two other patches are going one to follow this one.  The first is a
  change to objdump so that the mapping symbols are skipped when
  displaying a disassembly.  The second, which I will be sending to
  the gdb list is a hack to solve the same problem when gdb is doing a
  disassembly.

Cheers
        Nick

gas/ChangeLog
2003-11-13  Nick Clifton  <nickc@redhat.com>

	* tc-arm.c (mapping_state): New function.  Emit a mapping
	symbol if necessary.
        (arm_elf_change_section): New function.  Intercept section
	changes and generate mapping symbols.
        (s_bss): Likewise.
        (s_arm_elf_cons): Likewise.
        (opcode_select): Choose the correct mapping state.
        (md_assemble): Likewise.
        * tc-arm.h (md_elf_section_change_hook): Define.
        * doc/c-arm.texi (ARM Mapping Symbols): New node.
	* NEWS: Mention new feature.

gas/testsuite/ChangeLog
2003-11-13  Nick Clifton  <nickc@redhat.com>

	* gas/arm/mapping.s: New test: Source for ARM ELF mapping
	symbols test.
	* gas/arm/mapping.d: New file: Expected output.
	* gas/arm/arm.exp: Run new test.

Index: gas/NEWS
===================================================================
RCS file: /cvs/src/src/gas/NEWS,v
retrieving revision 1.49
diff -c -3 -p -r1.49 NEWS
*** gas/NEWS	6 Nov 2003 15:30:03 -0000	1.49
--- gas/NEWS	13 Nov 2003 12:53:48 -0000
***************
*** 1,5 ****
--- 1,8 ----
  -*- text -*-
  
+ * Limited support for Mapping Symbols as specified in the ARM ELF specification
+   has been added to the arm assembler.
+ 
  * On ARM architectures, added a new gas directive ".unreq" that undoes
    definitions created by ".req".
  
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.147
diff -c -3 -p -r1.147 tc-arm.c
*** gas/config/tc-arm.c	6 Nov 2003 15:30:04 -0000	1.147
--- gas/config/tc-arm.c	13 Nov 2003 12:53:57 -0000
*************** validate_offset_imm (val, hwse)
*** 2646,2651 ****
--- 2646,2823 ----
    return val;
  }
  
+ 
+ #ifdef OBJ_ELF
+ enum mstate
+ {
+   MAP_DATA,
+   MAP_ARM,
+   MAP_THUMB
+ };
+ 
+ /* This code is to handle mapping symbols as defined in the ARM ELF spec.
+    (This text is taken from version B-02 of the spec):
+ 
+       4.4.7 Mapping and tagging symbols
+ 
+       A section of an ARM ELF file can contain a mixture of ARM code,
+       Thumb code, and data.  There are inline transitions between code
+       and data at literal pool boundaries. There can also be inline
+       transitions between ARM code and Thumb code, for example in
+       ARM-Thumb inter-working veneers.  Linkers, machine-level
+       debuggers, profiling tools, and disassembly tools need to map
+       images accurately. For example, setting an ARM breakpoint on a
+       Thumb location, or in a literal pool, can crash the program
+       being debugged, ruining the debugging session.
+ 
+       ARM ELF entities are mapped (see section 4.4.7.1 below) and
+       tagged (see section 4.4.7.2 below) using local symbols (with
+       binding STB_LOCAL).  To assist consumers, mapping and tagging
+       symbols should be collated first in the symbol table, before
+       other symbols with binding STB_LOCAL.
+ 
+       To allow properly collated mapping and tagging symbols to be
+       skipped by consumers that have no interest in them, the first
+       such symbol should have the name $m and its st_value field equal
+       to the total number of mapping and tagging symbols (including
+       the $m) in the symbol table.
+ 
+       4.4.7.1 Mapping symbols
+ 
+       $a    Labels the first byte of a sequence of ARM instructions.
+             Its type is STT_FUNC.
+ 
+       $d    Labels the first byte of a sequence of data items.
+             Its type is STT_OBJECT.
+ 
+       $t    Labels the first byte of a sequence of Thumb instructions.
+             Its type is STT_FUNC.
+ 
+       This list of mapping symbols may be extended in the future.
+ 
+       Section-relative mapping symbols
+ 
+       Mapping symbols defined in a section define a sequence of
+       half-open address intervals that cover the address range of the
+       section. Each interval starts at the address defined by a
+       mapping symbol, and continues up to, but not including, the
+       address defined by the next (in address order) mapping symbol or
+       the end of the section. A corollary is that there must be a
+       mapping symbol defined at the beginning of each section.
+       Consumers can ignore the size of a section-relative mapping
+       symbol. Producers can set it to 0.
+ 
+       Absolute mapping symbols
+ 
+       Because of the need to crystallize a Thumb address with the
+       Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
+       STT_FUNC defined in section SHN_ABS) need to be mapped with $a
+       or $t.
+ 
+       The extent of a mapping symbol defined in SHN_ABS is [st_value,
+       st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
+       where [x, y) denotes the half-open address range from x,
+       inclusive, to y, exclusive.
+ 
+       In the absence of a mapping symbol, a consumer can interpret a
+       function symbol with an odd value as the Thumb code address
+       obtained by clearing the least significant bit of the
+       value. This interpretation is deprecated, and it may not work in
+       the future.
+ 
+    Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
+    the EABI (which is still under development), so they are not
+    implemented here.  */
+ 
+ static void
+ mapping_state (enum mstate state)
+ {
+   static enum mstate mapstate = MAP_DATA;
+   symbolS * symbolP;
+   const char * symname;
+   int type;
+ 
+   if (mapstate == state)
+     /* The mapping symbol has already been emitted.
+        There is nothing else to do.  */
+     return;
+ 
+   mapstate = state;
+ 
+   switch (state)
+     {
+     case MAP_DATA:
+       symname = "$d";
+       type = BSF_OBJECT;
+       break;
+     case MAP_ARM:
+       symname = "$a";
+       type = BSF_FUNCTION;
+       break;
+     case MAP_THUMB:
+       symname = "$t";
+       type = BSF_FUNCTION;
+       break;
+     default:
+       abort ();
+     }
+ 
+   symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
+   symbol_table_insert (symbolP);
+   symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
+   
+   switch (state)
+     {
+     case MAP_ARM:
+       THUMB_SET_FUNC (symbolP, 0);
+       ARM_SET_THUMB (symbolP, 0);
+       ARM_SET_INTERWORK (symbolP, support_interwork);
+       break;
+       
+     case MAP_THUMB:
+       THUMB_SET_FUNC (symbolP, 1);
+       ARM_SET_THUMB (symbolP, 1);
+       ARM_SET_INTERWORK (symbolP, support_interwork);
+       break;
+       
+     case MAP_DATA:
+     default:
+       return;
+     }
+ }
+ 
+ /* When we change sections we need to issue a new mapping symbol.  */
+ 
+ static void
+ arm_elf_change_section (void)
+ {
+   flagword flags;
+ 
+   if (!SEG_NORMAL (now_seg))
+     return;
+ 
+   flags = bfd_get_section_flags (stdoutput, now_seg);
+ 
+   /* We can ignore sections that only contain debug info.  */
+   if ((flags & SEC_ALLOC) == 0)
+     return;
+ 
+   if (flags & SEC_CODE)
+     {
+       if (thumb_mode)
+ 	mapping_state (MAP_THUMB);
+       else
+ 	mapping_state (MAP_ARM);
+     }
+   else
+     /* This section does not contain code.  Therefore it must contain data.  */
+     mapping_state (MAP_DATA);    
+ }
+ #else
+ #define mapping_state(a)
+ #endif /* OBJ_ELF */
+ 
+ 
  static void
  s_req (a)
       int a ATTRIBUTE_UNUSED;
*************** s_bss (ignore)
*** 2732,2737 ****
--- 2904,2910 ----
       marking in_bss, then looking at s_skip for clues.  */
    subseg_set (bss_section, 0);
    demand_empty_rest_of_line ();
+   mapping_state (MAP_DATA);
  }
  
  static void
*************** opcode_select (width)
*** 2970,2975 ****
--- 3143,3149 ----
               coming from ARM mode, which is word-aligned.  */
  	  record_alignment (now_seg, 1);
  	}
+       mapping_state (MAP_THUMB);
        break;
  
      case 32:
*************** opcode_select (width)
*** 2985,2990 ****
--- 3159,3165 ----
  
  	  record_alignment (now_seg, 1);
  	}
+       mapping_state (MAP_ARM);
        break;
  
      default:
*************** md_assemble (str)
*** 11681,11686 ****
--- 11856,11862 ----
  	      return;
  	    }
  
+ 	  mapping_state (MAP_THUMB);
  	  inst.instruction = opcode->value;
  	  inst.size = opcode->size;
  	  (*opcode->parms) (p);
*************** md_assemble (str)
*** 11706,11711 ****
--- 11882,11888 ----
  	      return;
  	    }
  
+           mapping_state (MAP_ARM);
  	  inst.instruction = opcode->value;
  	  inst.size = INSN_SIZE;
  	  (*opcode->parms) (p);
*************** s_arm_elf_cons (nbytes)
*** 12809,12814 ****
--- 12986,12992 ----
    md_cons_align (nbytes);
  #endif
  
+   mapping_state (MAP_DATA);
    do
      {
        bfd_reloc_code_real_type reloc;
Index: gas/config/tc-arm.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.h,v
retrieving revision 1.19
diff -c -3 -p -r1.19 tc-arm.h
*** gas/config/tc-arm.h	5 Dec 2002 11:46:50 -0000	1.19
--- gas/config/tc-arm.h	13 Nov 2003 12:53:57 -0000
*************** struct fix;
*** 90,95 ****
--- 90,98 ----
  #ifdef OBJ_ELF
  # define TARGET_FORMAT elf32_arm_target_format()
    extern const char * elf32_arm_target_format PARAMS ((void));
+ 
+ # define md_elf_section_change_hook() arm_elf_change_section
+   extern void arm_elf_change_section (void);
  #endif
  
  #define TC_FORCE_RELOCATION(FIX) arm_force_relocation (FIX)
Index: gas/doc/c-arm.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-arm.texi,v
retrieving revision 1.20
diff -c -3 -p -r1.20 c-arm.texi
*** gas/doc/c-arm.texi	6 Nov 2003 15:30:04 -0000	1.20
--- gas/doc/c-arm.texi	13 Nov 2003 12:53:57 -0000
***************
*** 22,27 ****
--- 22,28 ----
  * ARM Floating Point::       Floating Point
  * ARM Directives::           ARM Machine Directives
  * ARM Opcodes::              Opcodes
+ * ARM Mapping Symbols::      Mapping Symbols
  @end menu
  
  @node ARM Options
*************** This instruction will not make use of th
*** 438,441 ****
--- 439,471 ----
  For information on the ARM or Thumb instruction sets, see @cite{ARM
  Software Development Toolkit Reference Manual}, Advanced RISC Machines
  Ltd.
+ 
+ @node ARM Mapping Symbols
+ @section Mapping Symbols
+ 
+ The ARM ELF specification requires that special symbols be inserted
+ into object files to mark certain features:
+ 
+ @table @code
+ 
+ @cindex @code{$a}
+ @item $a
+ At the start of a region of code containing ARM instructions.
+ 
+ @cindex @code{$t}
+ @item $t
+ At the start of a region of code containing THUMB instructions.
+ 
+ @cindex @code{$d}
+ @item $d
+ At the start of a region of data.
+ 
+ @end table
+ 
+ The assembler will automatically insert these symbols for you - there
+ is no need to code them yourself.  Support for tagging symbols ($b,
+ $f, $p and $m) which is also mentioned in the current ARM ELF
+ specification is not implemented.  This is because they have been
+ dropped from the new EABI and so tools cannot rely upon their
+ presence.
  
Index: gas/testsuite/gas/arm/arm.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/arm.exp,v
retrieving revision 1.22
diff -c -3 -p -r1.22 arm.exp
*** gas/testsuite/gas/arm/arm.exp	6 Nov 2003 15:30:05 -0000	1.22
--- gas/testsuite/gas/arm/arm.exp	13 Nov 2003 12:53:58 -0000
*************** if {[istarget *arm*-*-*] || [istarget "x
*** 68,73 ****
--- 68,75 ----
      
      if {[istarget *-*-elf*] || [istarget *-*-linux*]} then {
  	run_dump_test "pic"
+ 
+ 	run_dump_test "mapping"
      }
  
      gas_test "offset.s" "" $stdoptlist "OFFSET_IMM regression"

*** /dev/null	2003-01-30 10:24:37.000000000 +0000
--- gas/testsuite/gas/arm/mapping.s	2003-11-10 08:53:18.000000000 +0000
***************
*** 0 ****
--- 1,20 ----
+ 	.text
+ 	.arm
+ 	.global mapping
+ mapping:
+ 	nop
+ 	bl mapping
+ 
+ 	.global thumb_mapping
+ 	.thumb_func
+ thumb_mapping:
+ 	.thumb
+ 	nop
+ 	bl thumb_mapping
+ 	
+ 	.data
+ 	.word 0x123456
+ 
+ 	.section foo,"ax"
+ 	nop

*** /dev/null	2003-01-30 10:24:37.000000000 +0000
--- gas/testsuite/gas/arm/mapping.d	2003-11-12 17:03:58.000000000 +0000
***************
*** 0 ****
--- 1,21 ----
+ #objdump: --syms
+ #name: ARM Mapping Symbols
+ 
+ # Test the generation of ARM ELF Mapping Symbols
+ 
+ .*: +file format.*arm.*
+ 
+ SYMBOL TABLE:
+ 0+00 l    d  .text	0+0 
+ 0+00 l    d  .data	0+0 
+ 0+00 l    d  .bss	0+0 
+ 0+00 l     F .text	0+0 \$a
+ 0+08 l       .text	0+0 \$t
+ 0+00 l     O .data	0+0 \$d
+ 0+00 l    d  foo	0+0 
+ 0+00 l       foo	0+0 \$t
+ 0+00 g       .text	0+0 mapping
+ 0+08 g       .text	0+0 thumb_mapping




More information about the Binutils mailing list