This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


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

Re: patch for ARM GNU/Linux gdbserver


FYI,

I've split this patch into two parts.  This is the first part which I have
committed on both the branch and the mainline.

Scott

2000-04-10  Philip Blundell <philb@gnu.org>

	* arm-linux-nat.c (arm_skip_solib_resolver): Remove and move to
	arm-linux-tdep.c.
	* arm-linux-tdep.c (arm_skip_solib_resolver): New.


Philip Blundell wrote:
> 
> This patch seems to be needed for gdbserver to work on Linux/ARM.
> 
> p.
> 
> 2000-04-08  Philip Blundell  <philb@gnu.org>
> 
>         * arm-linux-nat.c (arm_skip_solib_resolver): Move to ...
>         * arm-linux-tdep.c (arm_skip_solib_resolver): ... here.
> 
>         * gdbserver/low-linux.c: Add support for ARM GNU/Linux.
>         * config/arm/tm-linux.h (ARM_GNULINUX_TARGET): Define.
>         * configure.tgt [arm*-*-linux*]: Add gdbserver to $configdirs.
> 
> Index: arm-linux-nat.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/arm-linux-nat.c,v
> retrieving revision 1.4
> diff -u -p -u -r1.4 arm-linux-nat.c
> --- arm-linux-nat.c     2000/04/05 15:38:05     1.4
> +++ arm-linux-nat.c     2000/04/08 22:36:59
> @@ -322,132 +322,6 @@ store_inferior_registers (int regno)
>      store_fpregs ();
>  }
> 
> -/*
> -   Dynamic Linking on ARM Linux
> -   ----------------------------
> -
> -   Note: PLT = procedure linkage table
> -   GOT = global offset table
> -
> -   As much as possible, ELF dynamic linking defers the resolution of
> -   jump/call addresses until the last minute. The technique used is
> -   inspired by the i386 ELF design, and is based on the following
> -   constraints.
> -
> -   1) The calling technique should not force a change in the assembly
> -   code produced for apps; it MAY cause changes in the way assembly
> -   code is produced for position independent code (i.e. shared
> -   libraries).
> -
> -   2) The technique must be such that all executable areas must not be
> -   modified; and any modified areas must not be executed.
> -
> -   To do this, there are three steps involved in a typical jump:
> -
> -   1) in the code
> -   2) through the PLT
> -   3) using a pointer from the GOT
> -
> -   When the executable or library is first loaded, each GOT entry is
> -   initialized to point to the code which implements dynamic name
> -   resolution and code finding.  This is normally a function in the
> -   program interpreter (on ARM Linux this is usually ld-linux.so.2,
> -   but it does not have to be).  On the first invocation, the function
> -   is located and the GOT entry is replaced with the real function
> -   address.  Subsequent calls go through steps 1, 2 and 3 and end up
> -   calling the real code.
> -
> -   1) In the code:
> -
> -   b    function_call
> -   bl   function_call
> -
> -   This is typical ARM code using the 26 bit relative branch or branch
> -   and link instructions.  The target of the instruction
> -   (function_call is usually the address of the function to be called.
> -   In position independent code, the target of the instruction is
> -   actually an entry in the PLT when calling functions in a shared
> -   library.  Note that this call is identical to a normal function
> -   call, only the target differs.
> -
> -   2) In the PLT:
> -
> -   The PLT is a synthetic area, created by the linker. It exists in
> -   both executables and libraries. It is an array of stubs, one per
> -   imported function call. It looks like this:
> -
> -   PLT[0]:
> -   str     lr, [sp, #-4]!       @push the return address (lr)
> -   ldr     lr, [pc, #16]   @load from 6 words ahead
> -   add     lr, pc, lr      @form an address for GOT[0]
> -   ldr     pc, [lr, #8]!   @jump to the contents of that addr
> -
> -   The return address (lr) is pushed on the stack and used for
> -   calculations.  The load on the second line loads the lr with
> -   &GOT[3] - . - 20.  The addition on the third leaves:
> -
> -   lr = (&GOT[3] - . - 20) + (. + 8)
> -   lr = (&GOT[3] - 12)
> -   lr = &GOT[0]
> -
> -   On the fourth line, the pc and lr are both updated, so that:
> -
> -   pc = GOT[2]
> -   lr = &GOT[0] + 8
> -   = &GOT[2]
> -
> -   NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
> -   "tight", but allows us to keep all the PLT entries the same size.
> -
> -   PLT[n+1]:
> -   ldr     ip, [pc, #4]    @load offset from gotoff
> -   add     ip, pc, ip      @add the offset to the pc
> -   ldr     pc, [ip]        @jump to that address
> -   gotoff: .word   GOT[n+3] - .
> -
> -   The load on the first line, gets an offset from the fourth word of
> -   the PLT entry.  The add on the second line makes ip = &GOT[n+3],
> -   which contains either a pointer to PLT[0] (the fixup trampoline) or
> -   a pointer to the actual code.
> -
> -   3) In the GOT:
> -
> -   The GOT contains helper pointers for both code (PLT) fixups and
> -   data fixups.  The first 3 entries of the GOT are special. The next
> -   M entries (where M is the number of entries in the PLT) belong to
> -   the PLT fixups. The next D (all remaining) entries belong to
> -   various data fixups. The actual size of the GOT is 3 + M + D.
> -
> -   The GOT is also a synthetic area, created by the linker. It exists
> -   in both executables and libraries.  When the GOT is first
> -   initialized , all the GOT entries relating to PLT fixups are
> -   pointing to code back at PLT[0].
> -
> -   The special entries in the GOT are:
> -
> -   GOT[0] = linked list pointer used by the dynamic loader
> -   GOT[1] = pointer to the reloc table for this module
> -   GOT[2] = pointer to the fixup/resolver code
> -
> -   The first invocation of function call comes through and uses the
> -   fixup/resolver code.  On the entry to the fixup/resolver code:
> -
> -   ip = &GOT[n+3]
> -   lr = &GOT[2]
> -   stack[0] = return address (lr) of the function call
> -   [r0, r1, r2, r3] are still the arguments to the function call
> -
> -   This is enough information for the fixup/resolver code to work
> -   with.  Before the fixup/resolver code returns, it actually calls
> -   the requested function and repairs &GOT[n+3].  */
> -
> -CORE_ADDR
> -arm_skip_solib_resolver (CORE_ADDR pc)
> -{
> -  /* FIXME */
> -  return 0;
> -}
> -
>  int
>  arm_linux_register_u_addr (int blockend, int regnum)
>  {
> Index: arm-linux-tdep.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/arm-linux-tdep.c,v
> retrieving revision 1.2
> diff -u -p -u -r1.2 arm-linux-tdep.c
> --- arm-linux-tdep.c    2000/04/05 17:24:08     1.2
> +++ arm-linux-tdep.c    2000/04/08 22:36:59
> @@ -76,6 +76,132 @@ arm_linux_extract_return_value (struct t
>    memcpy (valbuf, &regbuf[REGISTER_BYTE (regnum)], TYPE_LENGTH (type));
>  }
> 
> +/*
> +   Dynamic Linking on ARM Linux
> +   ----------------------------
> +
> +   Note: PLT = procedure linkage table
> +   GOT = global offset table
> +
> +   As much as possible, ELF dynamic linking defers the resolution of
> +   jump/call addresses until the last minute. The technique used is
> +   inspired by the i386 ELF design, and is based on the following
> +   constraints.
> +
> +   1) The calling technique should not force a change in the assembly
> +   code produced for apps; it MAY cause changes in the way assembly
> +   code is produced for position independent code (i.e. shared
> +   libraries).
> +
> +   2) The technique must be such that all executable areas must not be
> +   modified; and any modified areas must not be executed.
> +
> +   To do this, there are three steps involved in a typical jump:
> +
> +   1) in the code
> +   2) through the PLT
> +   3) using a pointer from the GOT
> +
> +   When the executable or library is first loaded, each GOT entry is
> +   initialized to point to the code which implements dynamic name
> +   resolution and code finding.  This is normally a function in the
> +   program interpreter (on ARM Linux this is usually ld-linux.so.2,
> +   but it does not have to be).  On the first invocation, the function
> +   is located and the GOT entry is replaced with the real function
> +   address.  Subsequent calls go through steps 1, 2 and 3 and end up
> +   calling the real code.
> +
> +   1) In the code:
> +
> +   b    function_call
> +   bl   function_call
> +
> +   This is typical ARM code using the 26 bit relative branch or branch
> +   and link instructions.  The target of the instruction
> +   (function_call is usually the address of the function to be called.
> +   In position independent code, the target of the instruction is
> +   actually an entry in the PLT when calling functions in a shared
> +   library.  Note that this call is identical to a normal function
> +   call, only the target differs.
> +
> +   2) In the PLT:
> +
> +   The PLT is a synthetic area, created by the linker. It exists in
> +   both executables and libraries. It is an array of stubs, one per
> +   imported function call. It looks like this:
> +
> +   PLT[0]:
> +   str     lr, [sp, #-4]!       @push the return address (lr)
> +   ldr     lr, [pc, #16]   @load from 6 words ahead
> +   add     lr, pc, lr      @form an address for GOT[0]
> +   ldr     pc, [lr, #8]!   @jump to the contents of that addr
> +
> +   The return address (lr) is pushed on the stack and used for
> +   calculations.  The load on the second line loads the lr with
> +   &GOT[3] - . - 20.  The addition on the third leaves:
> +
> +   lr = (&GOT[3] - . - 20) + (. + 8)
> +   lr = (&GOT[3] - 12)
> +   lr = &GOT[0]
> +
> +   On the fourth line, the pc and lr are both updated, so that:
> +
> +   pc = GOT[2]
> +   lr = &GOT[0] + 8
> +   = &GOT[2]
> +
> +   NOTE: PLT[0] borrows an offset .word from PLT[1]. This is a little
> +   "tight", but allows us to keep all the PLT entries the same size.
> +
> +   PLT[n+1]:
> +   ldr     ip, [pc, #4]    @load offset from gotoff
> +   add     ip, pc, ip      @add the offset to the pc
> +   ldr     pc, [ip]        @jump to that address
> +   gotoff: .word   GOT[n+3] - .
> +
> +   The load on the first line, gets an offset from the fourth word of
> +   the PLT entry.  The add on the second line makes ip = &GOT[n+3],
> +   which contains either a pointer to PLT[0] (the fixup trampoline) or
> +   a pointer to the actual code.
> +
> +   3) In the GOT:
> +
> +   The GOT contains helper pointers for both code (PLT) fixups and
> +   data fixups.  The first 3 entries of the GOT are special. The next
> +   M entries (where M is the number of entries in the PLT) belong to
> +   the PLT fixups. The next D (all remaining) entries belong to
> +   various data fixups. The actual size of the GOT is 3 + M + D.
> +
> +   The GOT is also a synthetic area, created by the linker. It exists
> +   in both executables and libraries.  When the GOT is first
> +   initialized , all the GOT entries relating to PLT fixups are
> +   pointing to code back at PLT[0].
> +
> +   The special entries in the GOT are:
> +
> +   GOT[0] = linked list pointer used by the dynamic loader
> +   GOT[1] = pointer to the reloc table for this module
> +   GOT[2] = pointer to the fixup/resolver code
> +
> +   The first invocation of function call comes through and uses the
> +   fixup/resolver code.  On the entry to the fixup/resolver code:
> +
> +   ip = &GOT[n+3]
> +   lr = &GOT[2]
> +   stack[0] = return address (lr) of the function call
> +   [r0, r1, r2, r3] are still the arguments to the function call
> +
> +   This is enough information for the fixup/resolver code to work
> +   with.  Before the fixup/resolver code returns, it actually calls
> +   the requested function and repairs &GOT[n+3].  */
> +
> +CORE_ADDR
> +arm_skip_solib_resolver (CORE_ADDR pc)
> +{
> +  /* FIXME */
> +  return 0;
> +}
> +
>  void
>  _initialize_arm_linux_tdep (void)
>  {
> Index: configure.tgt
> ===================================================================
> RCS file: /cvs/src/src/gdb/configure.tgt,v
> retrieving revision 1.5
> diff -u -p -u -r1.5 configure.tgt
> --- configure.tgt       2000/03/21 05:26:31     1.5
> +++ configure.tgt       2000/04/08 22:37:00
> @@ -52,7 +52,8 @@ alpha*-*-linux*)      gdb_target=alpha-linux
>  arc-*-*)               gdb_target=arc ;;
> 
>  arm*-wince-pe)         gdb_target=wince ;;
> -arm*-*-linux*)         gdb_target=linux ;;
> +arm*-*-linux*)         gdb_target=linux
> +                       configdirs="${configdirs} gdbserver" ;;
>  arm*-*-* | thumb*-*-* | strongarm*-*-*)
>                         gdb_target=embed
>                          configdirs="$configdirs rdi-share"
> Index: config/arm/tm-linux.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/config/arm/tm-linux.h,v
> retrieving revision 1.3
> diff -u -p -u -r1.3 tm-linux.h
> --- config/arm/tm-linux.h       2000/02/28 20:51:08     1.3
> +++ config/arm/tm-linux.h       2000/04/08 22:37:11
> @@ -26,6 +26,8 @@
> 
>  #include "tm-linux.h"
> 
> +#define ARM_GNULINUX_TARGET
> +
>  /* Target byte order on ARM Linux is not selectable.  */
>  #undef TARGET_BYTE_ORDER_SELECTABLE_P
>  #define TARGET_BYTE_ORDER_SELECTABLE_P         0
> Index: gdbserver/low-linux.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbserver/low-linux.c,v
> retrieving revision 1.2
> diff -u -p -u -r1.2 low-linux.c
> --- gdbserver/low-linux.c       2000/03/21 05:23:05     1.2
> +++ gdbserver/low-linux.c       2000/04/08 22:37:15
> @@ -276,6 +276,20 @@ m68k_linux_register_u_addr (blockend, re
>  {
>    return (blockend + 4 * regmap[regnum]);
>  }
> +#elif defined(ARM_GNULINUX_TARGET)
> +static void
> +initialize_arch ()
> +{
> +  return;
> +}
> +
> +/* From arm-linux-nat.c */
> +int
> +arm_linux_register_u_addr (int blockend, int regnum)
> +{
> +  return blockend + REGISTER_BYTE (regnum);
> +}
> +
>  #elif defined(IA64_GNULINUX_TARGET)
>  #undef NUM_FREGS
>  #define NUM_FREGS 0

-- 
Scott Bambrough - Software Engineer
REBEL.COM    http://www.rebel.com
NetWinder    http://www.netwinder.org

philb1.patch


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