Re: [patch] Set calling convention of methods

Jonas Maebe
2009-09-30T14:54:05Z

[-- Attachment #1: Type: text/plain, Size: 1675 bytes --]

On 30 Sep 2009, at 13:18, Jonas Maebe wrote:

> On 30 Sep 2009, at 02:02, Joel Brobecker wrote:
>
>> One of the concerns that never got resolved from what I've read in
>> the
>> archives, was the use of a DWARF constant outside of DWARF code.
>> I am not sure I understand the problem, though. Was it the use of
>> constant zero when populating this field when reading stabs debug
>> info, or anything else?
>
> Yes, it was the use of an unnamed constant: http://sourceware.org/ml/gdb-patches/2009-04/msg00196.html

Note that the patch under discussion right now is unrelated to that
concern, as it does not yet make any modification to the Stabs reader
(that's only required once calling conventions are stored for methods).

I've also attached a version of the patch that applies against current
gdb head (dwarf2.h was moved from include/elf to include,
store_unsigned_integer now takes an extra byte_order parameter).
Additionally, I've added a test, because even in my previous new
version I messed up struct returns. This test should prevent that from
happening again.

Jonas

2009-09-30 Jonas Maebe <jonas.maebe <at> elis.ugent.be>

Add support for the "Borland fastcall" calling convention.

* dwarf2.h: Add DW_CC_GNU_borland_fastcall_i386 constant.
* i386-tdep.c: #include dwarf2.h
(i386_borland_fastcall_push_dummy_call): New.
(i386_push_dummy_generic_call): Renamed i386_push_dummy_call.
(i386_push_dummy_call): New dispatch function that calls
i386_generic_push_dummy_call or i386_push_dummy_borland_fast_call
depending on the calling convention.
* gdb.dwarf2/dw2-borland_fastcall.exp: New.
* gdb.dwarf2/dw2-borland_fastcall.S: New.

[-- Attachment #2: gdb_borland_fastcall6.patch --]
[-- Type: application/octet-stream, Size: 24757 bytes --]

diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index b79bcd2..bd8844e 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -53,6 +53,8 @@
#include "record.h"
#include <stdint.h>

+#include "dwarf2.h"
+
/* Register names. */

static char *i386_register_names[] =
@@ -1426,7 +1428,7 @@ i386_frame_this_id (struct frame_info *this_frame, void **this_cache,
if (cache->base == 0)
return;

- /* See the end of i386_push_dummy_call. */
+ /* See the end of i386_generic_push_dummy_call. */
(*this_id) = frame_id_build (cache->base + 8, cache->pc);
}

@@ -1620,7 +1622,7 @@ i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct i386_frame_cache *cache =
i386_sigtramp_frame_cache (this_frame, this_cache);

- /* See the end of i386_push_dummy_call. */
+ /* See the end of i386_generic_push_dummy_call. */
(*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame));
}

@@ -1697,7 +1699,7 @@ i386_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)

fp = get_frame_register_unsigned (this_frame, I386_EBP_REGNUM);

- /* See the end of i386_push_dummy_call. */
+ /* See the end of i386_generic_push_dummy_call. */
return frame_id_build (fp + 8, get_frame_pc (this_frame));
}
\f
@@ -1765,10 +1767,10 @@ i386_16_byte_align_p (struct type *type)
}

static CORE_ADDR
-i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
- struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
- struct value **args, CORE_ADDR sp, int struct_return,
- CORE_ADDR struct_addr)
+i386_generic_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr,
+ int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[4];
@@ -1861,6 +1863,144 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
return sp + 8;
}

+/* Borland fastcall: register parameters are passed from left to right, then
+ stack parameters also from left to right. The first three unstructured
+ parameters <= 32 bits are passed in %eax, %edx and %ecx. The others are
+ passed on the stack. Furthermore, in case of a struct return by reference,
+ the address of this struct is passed as the last parameter. */
+static CORE_ADDR
+i386_borland_fastcall_push_dummy_call (struct gdbarch *gdbarch,
+ struct value *function,
+ struct regcache *regcache,
+ CORE_ADDR bp_addr, int nargs,
+ struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
+{
+ static const int para_regs[3] = { I386_EAX_REGNUM, I386_EDX_REGNUM,
+ I386_ECX_REGNUM };
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[4];
+ int reg_paras[3] = { -1, -1, -1 };
+ int i, j;
+ int write_pass;
+ int para_regnum = 0;
+
+ /* First assign the register parameters (left to right). */
+ if (struct_return)
+ {
+ store_unsigned_integer (buf, 4, byte_order, struct_addr);
+ regcache_cooked_write (regcache, para_regs[para_regnum],
+ buf);
+ /* Use the otherwise invalid "nargs" argument index to denote the
+ function result. */
+ reg_paras[para_regnum] = nargs;
+ para_regnum++;
+ }
+
+ for (i = 0; i < nargs && para_regnum < 3; i++)
+ {
+ struct type *type = check_typedef (value_enclosing_type (args[i]));
+ int len = TYPE_LENGTH (type);
+
+ if (len <= 4
+ && TYPE_CODE (type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_FLT)
+ {
+ regcache_cooked_write (regcache, para_regs[para_regnum],
+ value_contents_all (args[i]));
+ reg_paras[para_regnum] = i;
+ para_regnum++;
+ }
+ }
+
+ /* Now process the stack parameters from left to right. */
+ for (write_pass = 0; write_pass < 2; write_pass++)
+ {
+ int args_space = 0;
+ int have_16_byte_aligned_arg = 0;
+
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ struct type *type = check_typedef (value_enclosing_type (args[i]));
+ int len = TYPE_LENGTH (type);
+ int processed = 0;
+
+ /* Skip parameters already assigned to registers. */
+ for (j = 0; j < para_regnum; j++)
+ if (reg_paras[j] == i)
+ {
+ processed = 1;
+ break;
+ }
+ if (processed)
+ continue;
+
+ if (i386_16_byte_align_p (value_enclosing_type (args[i])))
+ {
+ args_space = align_up (args_space, 16);
+ have_16_byte_aligned_arg = 1;
+ }
+ if (write_pass)
+ {
+ write_memory (sp + args_space,
+ value_contents_all (args[i]), len);
+ }
+ args_space += align_up (len, 4);
+ }
+
+ if (!write_pass)
+ {
+ /* Early exit if nothing to do. */
+ if (!args_space)
+ break;
+ if (have_16_byte_aligned_arg)
+ args_space = align_up (args_space, 16);
+ sp -= args_space;
+ }
+ }
+
+ /* Store return address. */
+ sp -= 4;
+ store_unsigned_integer (buf, 4, byte_order, bp_addr);
+ write_memory (sp, buf, 4);
+
+ /* Finally, update the stack pointer... */
+ store_unsigned_integer (buf, 4, byte_order, sp);
+ regcache_cooked_write (regcache, I386_ESP_REGNUM, buf);
+
+ /* ...and fake a frame pointer. */
+ regcache_cooked_write (regcache, I386_EBP_REGNUM, buf);
+
+ /* See the end of i386_generic_push_dummy_call. */
+ return sp + 8;
+}
+
+static CORE_ADDR
+i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+ struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
+ struct value **args, CORE_ADDR sp, int struct_return,
+ CORE_ADDR struct_addr)
+{
+ struct type *type = check_typedef (value_type (function));
+
+ /* Look up the target type in case of a function/method pointer. */
+ while (type && can_dereference (type))
+ type = TYPE_TARGET_TYPE (type);
+
+ /* Check calling convention. */
+ if (type
+ && TYPE_CALLING_CONVENTION (type) == DW_CC_GNU_borland_fastcall_i386)
+ return i386_borland_fastcall_push_dummy_call (gdbarch, function, regcache,
+ bp_addr, nargs, args, sp,
+ struct_return, struct_addr);
+ else
+ return i386_generic_push_dummy_call (gdbarch, function, regcache, bp_addr,
+ nargs, args, sp, struct_return,
+ struct_addr);
+}
+
/* These registers are used for returning integers (and on some
targets also for returning `struct' and `union' values when their
size and alignment match an integer type). */
diff --git a/include/dwarf2.h b/include/dwarf2.h
index 385ab22..9e4459a 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -721,7 +721,8 @@ enum dwarf_calling_convention
DW_CC_lo_user = 0x40,
DW_CC_hi_user = 0xff,

- DW_CC_GNU_renesas_sh = 0x40
+ DW_CC_GNU_renesas_sh = 0x40,
+ DW_CC_GNU_borland_fastcall_i386 = 0x41
};

/* Inline attribute. */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.S b/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.S
new file mode 100644
index 0000000..002d40e
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.S
@@ -0,0 +1,943 @@
+ .file "tgdbcc.pp"
+# Begin asmlist al_begin
+
+.section .debug_line
+ .type .Ldebug_linesection0,@object
+.Ldebug_linesection0:
+ .type .Ldebug_line0,@object
+.Ldebug_line0:
+
+.section .debug_abbrev
+ .type .Ldebug_abbrevsection0,@object
+.Ldebug_abbrevsection0:
+ .type .Ldebug_abbrev0,@object
+.Ldebug_abbrev0:
+
+.section .text
+.globl DEBUGSTART_P$PROGRAM
+ .type DEBUGSTART_P$PROGRAM,@object
+DEBUGSTART_P$PROGRAM:
+# End asmlist al_begin
+# Begin asmlist al_stabs
+# End asmlist al_stabs
+# Begin asmlist al_procedures
+
+.section .text
+ .balign 16,0x90
+.globl P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+ .type P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR,@function
+P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR:
+.Lc1:
+# Temps allocated between ebp-12 and ebp-12
+.Ll1:
+# [tgdbcc.pp]
+# [10] begin
+ pushl %ebp
+.Lc3:
+.Lc4:
+ movl %esp,%ebp
+.Lc5:
+ subl $12,%esp
+# Var a located at ebp-4
+# Var b located at ebp-8
+# Var c located at ebp+20
+# Var d located at ebp+16
+# Var e located at ebp+12
+# Var f located at ebp+8
+# Var $result located at ebp-12
+ movl %eax,-12(%ebp)
+ movb %dl,-4(%ebp)
+ movb %cl,-8(%ebp)
+.Ll2:
+# [11] fillchar(result.g,sizeof(result.g),0);
+ pushl %edi
+ movl -12(%ebp),%edi
+ leal 6(%edi),%edi
+ xorl %eax,%eax
+ movl $250,%ecx
+ rep stosl
+ popl %edi
+.Ll3:
+# [12] result.a:=a;
+ movl -12(%ebp),%eax
+ movb -4(%ebp),%dl
+ movb %dl,(%eax)
+.Ll4:
+# [13] result.b:=b;
+ movl -12(%ebp),%eax
+ movb -8(%ebp),%dl
+ movb %dl,1(%eax)
+.Ll5:
+# [14] result.c:=c;
+ movl -12(%ebp),%eax
+ movb 20(%ebp),%dl
+ movb %dl,2(%eax)
+.Ll6:
+# [15] result.d:=d;
+ movl -12(%ebp),%eax
+ movb 16(%ebp),%dl
+ movb %dl,3(%eax)
+.Ll7:
+# [16] result.e:=e;
+ movl -12(%ebp),%eax
+ movb 12(%ebp),%dl
+ movb %dl,4(%eax)
+.Ll8:
+# [17] result.f:=f;
+ movl -12(%ebp),%eax
+ movb 8(%ebp),%dl
+ movb %dl,5(%eax)
+.Ll9:
+# [18] end;
+ leave
+ ret $16
+.Lc2:
+.Lt2:
+.Le0:
+ .size P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR, .Le0 - P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+.Ll10:
+
+.section .text
+ .balign 16,0x90
+.globl PASCALMAIN
+ .type PASCALMAIN,@function
+PASCALMAIN:
+.globl main
+ .type main,@function
+main:
+.Lc6:
+# Temps allocated between ebp-1008 and ebp+0
+.Ll11:
+# [20] begin
+ pushl %ebp
+.Lc8:
+.Lc9:
+ movl %esp,%ebp
+.Lc10:
+ subl $1008,%esp
+.Ll12:
+# [21] func(255,254,253,252,251,250);
+ pushl $253
+ pushl $252
+ pushl $251
+ pushl $250
+ leal -1008(%ebp),%eax
+ movb $254,%cl
+ movb $255,%dl
+ call P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+.Ll13:
+# [22] end.
+ xorl %eax, %eax
+ leave
+ ret
+.Lc7:
+.Lt1:
+.Le1:
+ .size main, .Le1 - main
+.Ll14:
+
+.section .fpc
+ .balign 8
+ .ascii "FPC 2.5.1 [2009/09/12] for i386 - Linux"
+
+.section .debug_frame
+.Lc11:
+ .long .Lc13-.Lc12
+.Lc12:
+ .long -1
+ .byte 1
+ .byte 0
+ .uleb128 1
+ .sleb128 -4
+ .byte 8
+ .byte 12
+ .uleb128 4
+ .uleb128 4
+ .byte 5
+ .uleb128 8
+ .uleb128 1
+ .balign 4,0
+.Lc13:
+ .long .Lc15-.Lc14
+.Lc14:
+ .long .Lc11
+ .long .Lc1
+ .long .Lc2-.Lc1
+ .byte 4
+ .long .Lc3-.Lc1
+ .byte 14
+ .uleb128 8
+ .byte 4
+ .long .Lc4-.Lc3
+ .byte 5
+ .uleb128 5
+ .uleb128 2
+ .byte 4
+ .long .Lc5-.Lc4
+ .byte 13
+ .uleb128 5
+ .balign 4,0
+.Lc15:
+ .long .Lc17-.Lc16
+.Lc16:
+ .long .Lc11
+ .long .Lc6
+ .long .Lc7-.Lc6
+ .byte 4
+ .long .Lc8-.Lc6
+ .byte 14
+ .uleb128 8
+ .byte 4
+ .long .Lc9-.Lc8
+ .byte 5
+ .uleb128 5
+ .uleb128 2
+ .byte 4
+ .long .Lc10-.Lc9
+ .byte 13
+ .uleb128 5
+ .balign 4,0
+.Lc17:
+# End asmlist al_dwarf_frame
+# Begin asmlist al_dwarf_info
+
+.section .debug_info
+ .type .Ldebug_info0,@object
+.Ldebug_info0:
+ .long .Ledebug_info0-.Lf1
+.Lf1:
+ .short 2
+ .long .Ldebug_abbrev0
+ .byte 4
+ .uleb128 1
+ .ascii "tgdbcc.pp\000"
+ .ascii "Free Pascal 2.5.1 2009/09/12\000"
+ .ascii "/home/jmaebe/private/nobackup/fpc/test/\000"
+ .byte 9
+ .byte 3
+ .long .Ldebug_line0
+ .long DEBUGSTART_P$PROGRAM
+ .long DEBUGEND_P$PROGRAM
+# Syms - Begin Staticsymtable
+# Symbol SYSTEM
+# Symbol FPINTRES
+# Symbol OBJPAS
+# Symbol PROGRAM
+# Symbol main
+# Symbol TR
+# Symbol FUNC
+# Symbol SI_PRC
+# Syms - End Staticsymtable
+# Procdef $main; Register;
+ .uleb128 2
+ .ascii "main\000"
+ .byte 65
+ .byte 1
+ .long main
+ .long .Lt1
+ .byte 0
+# Procdef func(,Byte,Byte,Byte,Byte,Byte,Byte):<record type>;
+ .uleb128 3
+ .ascii "FUNC\000"
+ .byte 65
+ .byte 1
+ .long _$PROGRAM$_Ld1
+ .long P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+ .long .Lt2
+# Symbol A
+ .uleb128 4
+ .ascii "A\000"
+ .byte 2
+ .byte 117
+ .sleb128 -4
+ .long _$PROGRAM$_Ld3
+# Symbol B
+ .uleb128 5
+ .ascii "B\000"
+ .byte 2
+ .byte 117
+ .sleb128 -8
+ .long _$PROGRAM$_Ld3
+# Symbol C
+ .uleb128 6
+ .ascii "C\000"
+ .byte 2
+ .byte 117
+ .sleb128 20
+ .long _$PROGRAM$_Ld3
+# Symbol D
+ .uleb128 7
+ .ascii "D\000"
+ .byte 2
+ .byte 117
+ .sleb128 16
+ .long _$PROGRAM$_Ld3
+# Symbol E
+ .uleb128 8
+ .ascii "E\000"
+ .byte 2
+ .byte 117
+ .sleb128 12
+ .long _$PROGRAM$_Ld3
+# Symbol F
+ .uleb128 9
+ .ascii "F\000"
+ .byte 2
+ .byte 117
+ .sleb128 8
+ .long _$PROGRAM$_Ld3
+# Symbol result
+ .uleb128 10
+ .ascii "result\000"
+ .byte 2
+ .byte 117
+ .sleb128 -12
+ .long _$PROGRAM$_Ld2
+# Symbol FUNC
+ .uleb128 11
+ .ascii "FUNC\000"
+ .byte 2
+ .byte 117
+ .sleb128 -12
+ .long _$PROGRAM$_Ld2
+# Symbol RESULT
+ .uleb128 12
+ .ascii "RESULT\000"
+ .byte 2
+ .byte 117
+ .sleb128 -12
+ .long _$PROGRAM$_Ld2
+ .byte 0
+# Defs - Begin unit SYSTEM has index 1
+# Definition Byte
+ .type _$PROGRAM$_Ld3,@object
+_$PROGRAM$_Ld3:
+ .uleb128 13
+ .ascii "BYTE\000"
+ .long .La1
+ .type .La1,@object
+.La1:
+ .uleb128 14
+ .ascii "BYTE\000"
+ .byte 7
+ .byte 1
+ .type _$PROGRAM$_Ld4,@object
+_$PROGRAM$_Ld4:
+ .uleb128 15
+ .long _$PROGRAM$_Ld3
+# Defs - End unit SYSTEM has index 1
+# Defs - Begin unit FPINTRES has index 2
+# Defs - End unit FPINTRES has index 2
+# Defs - Begin unit OBJPAS has index 3
+# Defs - End unit OBJPAS has index 3
+# Defs - Begin unit SI_PRC has index 3
+# Defs - End unit SI_PRC has index 3
+# Defs - Begin Staticsymtable
+# Definition tr
+ .type _$PROGRAM$_Ld1,@object
+_$PROGRAM$_Ld1:
+ .uleb128 16
+ .ascii "TR\000"
+ .long .La2
+ .type .La2,@object
+.La2:
+ .uleb128 17
+ .ascii "TR\000"
+ .uleb128 1006
+ .uleb128 18
+ .ascii "A\000"
+ .byte 2
+ .byte 35
+ .uleb128 0
+ .long _$PROGRAM$_Ld3
+ .uleb128 19
+ .ascii "B\000"
+ .byte 2
+ .byte 35
+ .uleb128 1
+ .long _$PROGRAM$_Ld3
+ .uleb128 20
+ .ascii "C\000"
+ .byte 2
+ .byte 35
+ .uleb128 2
+ .long _$PROGRAM$_Ld3
+ .uleb128 21
+ .ascii "D\000"
+ .byte 2
+ .byte 35
+ .uleb128 3
+ .long _$PROGRAM$_Ld3
+ .uleb128 22
+ .ascii "E\000"
+ .byte 2
+ .byte 35
+ .uleb128 4
+ .long _$PROGRAM$_Ld3
+ .uleb128 23
+ .ascii "F\000"
+ .byte 2
+ .byte 35
+ .uleb128 5
+ .long _$PROGRAM$_Ld3
+ .uleb128 24
+ .ascii "G\000"
+ .byte 2
+ .byte 35
+ .uleb128 6
+ .long _$PROGRAM$_Ld5
+ .byte 0
+ .type _$PROGRAM$_Ld2,@object
+_$PROGRAM$_Ld2:
+ .uleb128 25
+ .long _$PROGRAM$_Ld1
+# Definition Array[0..999] Of Byte
+ .type _$PROGRAM$_Ld5,@object
+_$PROGRAM$_Ld5:
+ .uleb128 26
+ .uleb128 1000
+ .long _$PROGRAM$_Ld3
+ .uleb128 27
+ .sleb128 0
+ .sleb128 999
+ .uleb128 1
+ .long _$PROGRAM$_Ld7
+ .byte 0
+ .type _$PROGRAM$_Ld6,@object
+_$PROGRAM$_Ld6:
+ .uleb128 28
+ .long _$PROGRAM$_Ld5
+# Defs - End Staticsymtable
+# Definition SmallInt
+ .type _$PROGRAM$_Ld7,@object
+_$PROGRAM$_Ld7:
+ .uleb128 29
+ .ascii "SMALLINT\000"
+ .long .La3
+ .type .La3,@object
+.La3:
+ .uleb128 30
+ .ascii "SMALLINT\000"
+ .byte 5
+ .byte 2
+ .type _$PROGRAM$_Ld8,@object
+_$PROGRAM$_Ld8:
+ .uleb128 31
+ .long _$PROGRAM$_Ld7
+ .byte 0
+ .type .Ledebug_info0,@object
+.Ledebug_info0:
+# End asmlist al_dwarf_info
+# Begin asmlist al_dwarf_abbrev
+
+.section .debug_abbrev
+# Abbrev 1
+ .uleb128 1
+ .uleb128 17
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 37
+ .uleb128 8
+ .uleb128 27
+ .uleb128 8
+ .uleb128 19
+ .uleb128 11
+ .uleb128 66
+ .uleb128 11
+ .uleb128 16
+ .uleb128 6
+ .uleb128 17
+ .uleb128 1
+ .uleb128 18
+ .uleb128 1
+ .byte 0
+ .byte 0
+# Abbrev 2
+ .uleb128 2
+ .uleb128 46
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 54
+ .uleb128 11
+ .uleb128 63
+ .uleb128 12
+ .uleb128 17
+ .uleb128 1
+ .uleb128 18
+ .uleb128 1
+ .byte 0
+ .byte 0
+# Abbrev 3
+ .uleb128 3
+ .uleb128 46
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 54
+ .uleb128 11
+ .uleb128 63
+ .uleb128 12
+ .uleb128 73
+ .uleb128 16
+ .uleb128 17
+ .uleb128 1
+ .uleb128 18
+ .uleb128 1
+ .byte 0
+ .byte 0
+# Abbrev 4
+ .uleb128 4
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 5
+ .uleb128 5
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 6
+ .uleb128 6
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 7
+ .uleb128 7
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 8
+ .uleb128 8
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 9
+ .uleb128 9
+ .uleb128 5
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 10
+ .uleb128 10
+ .uleb128 52
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 11
+ .uleb128 11
+ .uleb128 52
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 12
+ .uleb128 12
+ .uleb128 52
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 2
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 13
+ .uleb128 13
+ .uleb128 22
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 14
+ .uleb128 14
+ .uleb128 36
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 62
+ .uleb128 11
+ .uleb128 11
+ .uleb128 11
+ .byte 0
+ .byte 0
+# Abbrev 15
+ .uleb128 15
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 16
+ .uleb128 16
+ .uleb128 22
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 17
+ .uleb128 17
+ .uleb128 19
+ .byte 1
+ .uleb128 3
+ .uleb128 8
+ .uleb128 11
+ .uleb128 15
+ .byte 0
+ .byte 0
+# Abbrev 18
+ .uleb128 18
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 19
+ .uleb128 19
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 20
+ .uleb128 20
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 21
+ .uleb128 21
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 22
+ .uleb128 22
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 23
+ .uleb128 23
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 24
+ .uleb128 24
+ .uleb128 13
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 56
+ .uleb128 10
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 25
+ .uleb128 25
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 26
+ .uleb128 26
+ .uleb128 1
+ .byte 1
+ .uleb128 11
+ .uleb128 15
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 27
+ .uleb128 27
+ .uleb128 33
+ .byte 0
+ .uleb128 34
+ .uleb128 13
+ .uleb128 47
+ .uleb128 13
+ .uleb128 81
+ .uleb128 15
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 28
+ .uleb128 28
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 29
+ .uleb128 29
+ .uleb128 22
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+# Abbrev 30
+ .uleb128 30
+ .uleb128 36
+ .byte 0
+ .uleb128 3
+ .uleb128 8
+ .uleb128 62
+ .uleb128 11
+ .uleb128 11
+ .uleb128 11
+ .byte 0
+ .byte 0
+# Abbrev 31
+ .uleb128 31
+ .uleb128 16
+ .byte 0
+ .uleb128 73
+ .uleb128 16
+ .byte 0
+ .byte 0
+ .byte 0
+# End asmlist al_dwarf_abbrev
+# Begin asmlist al_dwarf_line
+
+.section .debug_line
+# === header start ===
+ .long .Ledebug_line0-.Lf2
+.Lf2:
+ .short 2
+ .long .Lehdebug_line0-.Lf3
+.Lf3:
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 255
+ .byte 13
+ .byte 0
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 1
+ .byte 0
+ .byte 0
+ .byte 1
+# include_directories
+ .byte 0
+# file_names
+ .ascii "tgdbcc.pp\000"
+ .uleb128 0
+ .uleb128 0
+ .uleb128 0
+ .byte 0
+ .type .Lehdebug_line0,@object
+.Lehdebug_line0:
+# === header end ===
+# function: P$PROGRAM_FUNC$BYTE$BYTE$BYTE$BYTE$BYTE$BYTE$$TR
+# [10:1]
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll1
+ .byte 5
+ .uleb128 1
+ .byte 21
+# [11:18]
+ .byte 2
+ .uleb128 .Ll2-.Ll1
+ .byte 5
+ .uleb128 18
+ .byte 13
+# [12:9]
+ .byte 2
+ .uleb128 .Ll3-.Ll2
+ .byte 5
+ .uleb128 9
+ .byte 13
+# [13:9]
+ .byte 2
+ .uleb128 .Ll4-.Ll3
+ .byte 13
+# [14:9]
+ .byte 2
+ .uleb128 .Ll5-.Ll4
+ .byte 13
+# [15:9]
+ .byte 2
+ .uleb128 .Ll6-.Ll5
+ .byte 13
+# [16:9]
+ .byte 2
+ .uleb128 .Ll7-.Ll6
+ .byte 13
+# [17:9]
+ .byte 2
+ .uleb128 .Ll8-.Ll7
+ .byte 13
+# [18:1]
+ .byte 2
+ .uleb128 .Ll9-.Ll8
+ .byte 5
+ .uleb128 1
+ .byte 13
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll10
+ .byte 0
+ .byte 1
+ .byte 1
+# ###################
+# function: PASCALMAIN
+# function: main
+# [20:1]
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll11
+ .byte 5
+ .uleb128 1
+ .byte 31
+# [21:3]
+ .byte 2
+ .uleb128 .Ll12-.Ll11
+ .byte 5
+ .uleb128 3
+ .byte 13
+# [22:1]
+ .byte 2
+ .uleb128 .Ll13-.Ll12
+ .byte 5
+ .uleb128 1
+ .byte 13
+ .byte 0
+ .uleb128 5
+ .byte 2
+ .long .Ll14
+ .byte 0
+ .byte 1
+ .byte 1
+# ###################
+ .type .Ledebug_line0,@object
+.Ledebug_line0:
+# End asmlist al_dwarf_line
+# Begin asmlist al_picdata
+# End asmlist al_picdata
+# Begin asmlist al_resourcestrings
+# End asmlist al_resourcestrings
+# Begin asmlist al_objc_data
+# End asmlist al_objc_data
+# Begin asmlist al_end
+
+.section .text
+.globl DEBUGEND_P$PROGRAM
+ .type DEBUGEND_P$PROGRAM,@object
+DEBUGEND_P$PROGRAM:
+# End asmlist al_end
+.section .note.GNU-stack,"",%progbits
+
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.exp b/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.exp
new file mode 100644
index 0000000..6a18f53
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-borland_fastcall.exp
@@ -0,0 +1,52 @@
+# Copyright 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test Borland fastcall calling convention
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+ && ![istarget *-*-gnu*]
+ && ![istarget *-*-elf*]
+ && ![istarget *-*-openbsd*]} {
+ return 0;
+ }
+
+# This test can only be run on x86 targets.
+if {![istarget i?86-*]} {
+ return 0
+}
+
+set testfile "dw2-borland_fastcall"
+set srcfile ${testfile}.S
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {nodebug}] != "" } {
+ return -1
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if { ![runto_main] } {
+ gdb_suppress_tests;
+}
+
+
+gdb_test "p FUNC(1,2,3,4,5,6)" \
+ "= {A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, G = #0 <repeats 999 times>}"

[-- Attachment #3: Type: text/plain, Size: 1 bytes --]