patch for UPS/Solaris/x86.
"G. Narendran" <[email protected]> Fri, 21 Nov 2003 17:51:28 +0530
| Newsgroups | gmane.comp.debugging.ups.user |
|---|---|
| Message-ID | <[email protected]> |
Hi,
We had earlier reported progress in porting UPS to Solaris/x86.
Here is the patch for the port. We would welcome your feedback on
the same.
Files attached:
ups-3.38-b2-solx86.patch The patch for UPS/Solaris/x86
ups-bugs.txt UPS bugs detected during the port
Build instructions:
gtar -xzvf ups-3.38-beta2.tar.gz
cd ups-3.38-beta2
patch -cbi ups-3.38-b2-solx86.patch
./configure # + any options
make # dmake or gmake
make install # as root
Configurations tested:
. Both i386-pc-solaris2.9 (target) and sparc-sun-solaris2.9
(reference).
. Both Sun ONE Studio 8 cc, and gcc (2.95.3) (both UPS and the
debugged programs were built and tested with both the compilers.)
. Test programs:
- all in the ups/tests directory.
- additional programs to test specific scenarios (wrong multiple
execution of bp code (see below), watch points etc.,)
- UPS itself.
- For a taste of really large application, with a large number of
dynamically loaded modules etc.,: the Ximian Evolution mail
client for Solaris/x86 (this also tested stoppage at solib
event.)
UPS has been found quite stable under the above tests.
Summary of the fixes:
. On x86, PC is incremented even when the int3 (0xcc) instruction is
executed. So when resuming after a breakpoint processing, it is
not merely sufficient to replace the bp opcode with the original
opcode. The PC must be rolled back by 1 and the kernel instructed
to restart from the decremented vaddr (ao_procfs.c)
. register number fixes:
- for correct display of register variables etc., added gcc
register translation for procfs (ao_symload.c)
- to get indirect function calls working (ao_target.c)
* - for correct decoding of PLT 'jmp *off(%ebx)' (ao_elflib.c,
ao_stack.c)
*. fixed bug in the addr_cmp function for qsort, to solve UPS crashes
on a large application (evolution) with many dynamic solibs
(ao_elflib.c)
*. fix to prevent UPS from executing twice the bp interpreted code
that results in the first stop (trun_ss.c)
. to get 'next' working (ao_target.c)
. to skip _start etc., symbols in stack trace (ao_stack.c)
. fix for struct passed by value (ao_symparse.c)
. changes to resolve build issues (see the patch)
. new define ARCH_SOLARISX86 added (configure.in, ifdefs.h.in)
Those marked with * are quite possibly UPS bugs on other platforms
as well, but the fixes have been wrapped in ARCH_SOLARISX86 as we
didn't have the test environment for the other platforms. The file
ups-bugs.txt describes them in case there is interest in fixing them
for the other platforms.
We intentionally left out fixing the following:
. While attempting to display a 'register long long' variable UPS
heuristically determines the register number for second word
based on the regno. for the first word. As we could only guess
which registers gcc would use, and as even this might not match
cc's placement, we didn't alter the code. Any suggestions for
this is welcome.
---x---
Narendran Gopalakrishnan
SIP Technologies & Exports Ltd
G4, Elnet Software City, CPT Road
Taramani, Chennai 600 113
India
Phone: +91-44-22541401
+91-44-22541031
Fax : +91-44-22541475
Website: http://www.siptech.com
.
ups-3.38-b2-solx86.patch
(text/plain, 14 KB)
*** ./ups/ao_elfcore.c.orig 2003-04-01 17:44:01.000000000 +0530
--- ./ups/ao_elfcore.c 2003-11-20 16:17:09.000000000 +0530
***************
*** 65,71 ****
#include "ao_elfread.h"
#include "ao_elfcore.h"
! #if (defined ARCH_LINUX386)
#if HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
--- 65,71 ----
#include "ao_elfread.h"
#include "ao_elfcore.h"
! #if (defined ARCH_LINUX386) || (defined ARCH_SOLARISX86)
#if HAVE_SYS_REG_H
#include <sys/reg.h>
#endif
***************
*** 464,470 ****
--- 464,474 ----
elf_core_greg_t *iregs = (elf_core_greg_t *)regs;
if (regno < 0 || regno >= sizeof(elf_core_gregset_t)/sizeof(elf_core_greg_t))
panic("bad regno in egcr");
+ #if defined(AO_USE_PTRACE) /* x86_gcc_register not defined otherwise */
addr = (taddr_t)&(iregs[x86_gcc_register(regno)]);
+ #else
+ addr = (taddr_t)&(iregs[regno]);
+ #endif /* ! AO_USE_PTRACE */
}
} /* switch */
#else
*** ./ups/ao_elflib.c.orig 2003-07-16 15:30:24.000000000 +0530
--- ./ups/ao_elflib.c 2003-11-20 16:17:53.000000000 +0530
***************
*** 1595,1603 ****
--- 1595,1608 ----
const addr_t *addr1 = addr1p;
const addr_t *addr2 = addr2p;
+ #if defined(ARCH_SOLARISX86)
+ /* 3-way return needed by qsort. And we don't need that '!addr1' etc., :-) */
+ return (addr1->addr > addr2->addr) ? -1 : (addr1->addr < addr2->addr);
+ #else
if (!addr1 || !addr2)
return 1;
return addr1->addr < addr2->addr;
+ #endif
}
char *
***************
*** 1755,1761 ****
--- 1760,1770 ----
unsigned char jmp[6];
taddr_t newpc;
+ #if defined(ARCH_SOLARISX86)
+ ebx = xp_getreg(xp, 8); /* EBX is 8 on Solaris/x86 */
+ #else
ebx = xp_getreg(xp, 3);
+ #endif
xp_read_data(xp, pc, (char *)jmp, 6);
*** ./ups/ao_procfs.c.orig 2002-10-26 18:35:00.000000000 +0530
--- ./ups/ao_procfs.c 2003-11-20 15:59:55.000000000 +0530
***************
*** 429,434 ****
--- 429,437 ----
stopres = SR_USER; /* out of a bad jump to here */
else
stopres = SR_BPT;
+ #if defined(ARCH_SOLARISX86)
+ --status.pr_reg[R_PC]; /* roll back PC on Solaris/x86 */
+ #endif
pi->clear_fault_on_resume = TRUE;
break;
case FLTTRACE:
***************
*** 877,882 ****
--- 880,892 ----
prrun.pr_vaddr = (caddr_t)restart_pc;
flags |= PRSVADDR;
}
+ #if defined(ARCH_SOLARISX86)
+ else if (ip->ip_stopres == SR_BPT) {
+ /* restart from the rolled back PC */
+ prrun.pr_vaddr = (caddr_t)ip->ip_restart_pc;
+ flags |= PRSVADDR;
+ }
+ #endif
prrun.pr_flags = flags;
*** ./ups/ao_stack.c.orig 2002-11-28 20:54:35.000000000 +0530
--- ./ups/ao_stack.c 2003-11-20 16:18:24.000000000 +0530
***************
*** 438,444 ****
break;
}
#endif
! #ifdef ARCH_LINUX386
if ((strcmp(f->fu_demangled_name, "_entry") == 0) ||
(strcmp(f->fu_demangled_name, "_start") == 0) ||
(strcmp(f->fu_demangled_name, "__libc_start_main") == 0)) {
--- 438,444 ----
break;
}
#endif
! #if defined(ARCH_LINUX386) || defined(ARCH_SOLARISX86)
if ((strcmp(f->fu_demangled_name, "_entry") == 0) ||
(strcmp(f->fu_demangled_name, "_start") == 0) ||
(strcmp(f->fu_demangled_name, "__libc_start_main") == 0)) {
***************
*** 518,524 ****
--- 518,528 ----
if (ebxoffset)
dread(xp, sp + offset + ebxoffset, (char *)&ebx, sizeof(ebx));
else
+ #if defined(ARCH_SOLARISX86)
+ ebx = xp_getreg(xp, EBX); /* fix for Solaris/x86 */
+ #else
ebx = xp_getreg(xp, 3);
+ #endif
if (ebpoffset) {
if (dread(xp, sp + offset + ebpoffset, (char *)&fp, sizeof(fp)) != 0 || !fp)
***************
*** 1218,1224 ****
return 0;
}
#endif
! #ifdef ARCH_386
reg = x86_gcc_register(reg);
#endif
--- 1222,1228 ----
return 0;
}
#endif
! #if defined(ARCH_386) && defined(AO_USE_PTRACE)
reg = x86_gcc_register(reg);
#endif
*** ./ups/ao_symload.c.orig 2002-11-04 20:26:19.000000000 +0530
--- ./ups/ao_symload.c 2003-11-21 09:38:08.000000000 +0530
***************
*** 44,49 ****
--- 44,55 ----
# endif
#endif
+ #if defined(ARCH_SOLARISX86)
+ #if HAVE_SYS_REG_H
+ #include <sys/reg.h> /* defines for sol_x86_gcc_register */
+ #endif
+ #endif
+
#include <local/wn.h>
#include <local/ukcprog.h>
#include <mtrprog/strcache.h>
***************
*** 90,95 ****
--- 96,104 ----
#ifdef AO_ELF
static bool static_addrs_relative PROTO((Compiler_type compiler_type));
#endif
+ #if defined(ARCH_SOLARISX86)
+ static int sol_x86_gcc_register PROTO((int regno));
+ #endif
void display_message PROTO((const char *mesg));
***************
*** 975,981 ****
func_t *f;
unsigned long val;
{
! #if defined(ARCH_386) && defined(OS_SUNOS)
return val;
#else
#ifdef AO_ELF
--- 984,990 ----
func_t *f;
unsigned long val;
{
! #if defined(ARCH_SOLARISX86)
return val;
#else
#ifdef AO_ELF
***************
*** 983,989 ****
#else
return AO_FIDATA(f->fu_fil)->stf_addr + val;
#endif /* !AO_ELF */
! #endif /* !(ARCH_386 && OS_SUNOS) */
}
#ifdef AO_ELF
--- 992,998 ----
#else
return AO_FIDATA(f->fu_fil)->stf_addr + val;
#endif /* !AO_ELF */
! #endif /* !(ARCH_SOLARISX86) */
}
#ifdef AO_ELF
***************
*** 995,1000 ****
--- 1004,1029 ----
}
#endif /* AO_ELF */
+ #if defined(ARCH_SOLARISX86)
+ /* The following separated out of ao_pt_regs.c as we use procfs instead.
+ * This is copied from x86_gcc_register for ARCH_LINUX386. But some
+ * of the registers in Solaris/x86 sys/reg.h don't find a mention here,
+ * and some are extraneous. TODO: Check gcc code/doc for Solaris/x86
+ * to see if this translation is complete.
+ */
+
+ static int
+ sol_x86_gcc_register(regno)
+ int regno;
+ {
+ static int regmap[] = {
+ EAX, ECX, EDX, EBX, UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS, DS, ES, FS, GS /*, ORIG_EAX */
+ };
+ return regmap[regno];
+ }
+ #endif
+
block_t *
ao_get_fu_blocks(f)
func_t *f;
***************
*** 1450,1455 ****
--- 1479,1495 ----
!(stf->stf_compiler_type == CT_CC &&
f->fu_fil->fi_language == LANG_CC))
addr += ast->st_base_address;
+ #if defined(ARCH_SOLARISX86)
+ /* We have to translate what gcc has set in the symbol
+ * table to match the registers on Solaris/x86. Very
+ * similar to the x86_gcc_register, except that we
+ * translate right where the symbol is read.
+ */
+ else if (class == CL_REG &&
+ (stf->stf_compiler_type == CT_GNU_CC ||
+ stf->stf_compiler_type == CT_GNU_F77))
+ addr = sol_x86_gcc_register(addr);
+ #endif
v = ci_make_var(ap, name, class, type, addr);
v->va_language = stf->stf_language;
*** ./ups/ao_symparse.c.orig 2002-11-28 21:56:20.000000000 +0530
--- ./ups/ao_symparse.c 2003-11-20 16:01:46.000000000 +0530
***************
*** 832,838 ****
* Modern compilers support passing struct/union by value.
* Still works on Solaris 2 so keep for OS_SUNOS.
*/
! #ifdef OS_SUNOS
if ((class == CL_ARG) && (rtype->ty_code == TY_STRUCT || rtype->ty_code == TY_UNION))
class = CL_REF;
#endif
--- 832,842 ----
* Modern compilers support passing struct/union by value.
* Still works on Solaris 2 so keep for OS_SUNOS.
*/
! #if defined(OS_SUNOS) && !defined(ARCH_386)
! /* 7Nov3: on x86, this fix is needed for neither cc nor gcc.
! * on SPARC, it is needed for cc (gcc seems to use
! * CL_AUTO for CL_ARG as well.)
! */
if ((class == CL_ARG) && (rtype->ty_code == TY_STRUCT || rtype->ty_code == TY_UNION))
class = CL_REF;
#endif
*** ./ups/ao_target.c.orig 2003-07-16 15:30:28.000000000 +0530
--- ./ups/ao_target.c 2003-11-21 16:56:48.000000000 +0530
***************
*** 640,646 ****
target_t *xp;
int rlink_reg;
{
! #if defined(ARCH_SUN3) || defined(ARCH_CLIPPER) || defined(ARCH_BSDI386) || defined(ARCH_LINUX386)
taddr_t sp, retaddr;
sp = xp_getreg(xp, UPSREG_SP);
--- 640,647 ----
target_t *xp;
int rlink_reg;
{
! #if defined(ARCH_SUN3) || defined(ARCH_CLIPPER) || \
! defined(ARCH_BSDI386) || defined(ARCH_LINUX386) || defined(ARCH_SOLARISX86)
taddr_t sp, retaddr;
sp = xp_getreg(xp, UPSREG_SP);
***************
*** 987,992 ****
--- 988,997 ----
#define ALIGN_STACK(n) ((n) & ~(unsigned)07)
#endif
+ #if defined(ARCH_SOLARISX86)
+ #define RETURN_REGNO 11 /* EAX is 11 on Solaris/x86 */
+ #endif
+
#ifndef N_REG_ARGS
#define N_REG_ARGS 0
#endif
***************
*** 1282,1288 ****
}
#endif /* ARCH_VAX */
#if defined(ARCH_SUN3) || defined(ARCH_CLIPPER) || \
! defined(ARCH_BSDI386) || defined(ARCH_LINUX386)
sp -= 4;
if (ps_write_data(ip, sp, (char *)&retpc, sizeof(retpc)) != 0) {
*p_mesg = "Can't push return address";
--- 1287,1293 ----
}
#endif /* ARCH_VAX */
#if defined(ARCH_SUN3) || defined(ARCH_CLIPPER) || \
! defined(ARCH_BSDI386) || defined(ARCH_LINUX386) || defined(ARCH_SOLARISX86)
sp -= 4;
if (ps_write_data(ip, sp, (char *)&retpc, sizeof(retpc)) != 0) {
*p_mesg = "Can't push return address";
***************
*** 1316,1322 ****
ps_setreg(ip, UPSREG_SP, sp);
#endif /* ARCH_VAX */
#if defined(ARCH_SUN3) || defined(ARCH_BSDI386) || \
! defined(ARCH_LINUX386)
ps_setreg(ip, UPSREG_SP, sp);
#endif
#ifdef ARCH_MIPS
--- 1321,1327 ----
ps_setreg(ip, UPSREG_SP, sp);
#endif /* ARCH_VAX */
#if defined(ARCH_SUN3) || defined(ARCH_BSDI386) || \
! defined(ARCH_LINUX386) || defined(ARCH_SOLARISX86)
ps_setreg(ip, UPSREG_SP, sp);
#endif
#ifdef ARCH_MIPS
***************
*** 1390,1397 ****
--- 1395,1406 ----
*p_res = xp_getreg(xp, RETURN_REGNO);
#ifdef ARCH_386
if (restype == TY_LONGLONG || restype == TY_ULONGLONG)
+ #if defined(ARCH_SOLARISX86)
+ p_res[1] = xp_getreg(xp, 9); /* EDX is 9 on Solaris/x86 */
+ #else
p_res[1] = xp_getreg(xp, 2);
#endif
+ #endif
/* Copy back any stuff we copied into the target's core.
*/
*** ./ups/cx_libfuncs.h.orig 2002-10-26 18:36:36.000000000 +0530
--- ./ups/cx_libfuncs.h 2003-11-20 15:21:11.000000000 +0530
***************
*** 149,154 ****
--- 149,160 ----
#endif
#endif /* OS_SUNOS_4 */
+ #ifdef OS_SUNOS
+ #if HAVE_DOPRNT
+ int _doprnt(void);
+ #endif
+ #endif /* OS_SUNOS */
+
#endif /* WANT_DECLS */
*** ./ups/trun_ss.c.orig 2003-06-06 21:54:42.000000000 +0530
--- ./ups/trun_ss.c 2003-11-20 16:06:27.000000000 +0530
***************
*** 155,161 ****
--- 155,176 ----
if (rtype != RT_CONT)
panic("bad rtype in dx_run_target");
stopres = dx_start(xp);
+ #if defined(ARCH_SOLARISX86)
+ /* Fix on Solaris/x86 for the following bug: dx_start has
+ * inturn called dx_run_target_ss already. So when it returns
+ * SR_BPT the bp code has already been executed once. If we
+ * don't break on SR_BPT, the bp code is executed again.
+ * For e.g., after the following bp code in the ups window:
+ *
+ * i = 42;
+ * ++i && #stop;
+ *
+ * i becomes 44.
+ */
+ if (!target_process_exists(xp) || stopres == SR_WPT || stopres == SR_BPT)
+ #else
if (!target_process_exists(xp) || stopres == SR_WPT)
+ #endif
break;
sig = 0;
if (rtype == RT_CONT &&
*** ./README.orig 2002-10-26 18:31:33.000000000 +0530
--- ./README 2003-11-20 15:44:48.000000000 +0530
***************
*** 85,90 ****
--- 85,91 ----
------------ ----------
SPARC Solaris 2.X, Solaris 7, Solaris 8
SPARC SunOS 4.X
+ Intel x86 Solaris 2.X
Intel x86 FreeBSD 3.x, 4.x (ELF)
Intel x86 Linux 2.2.x (ELF)
*** ./configure.in.orig 2003-08-29 20:18:50.000000000 +0530
--- ./configure.in 2003-11-20 15:49:28.000000000 +0530
***************
*** 768,774 ****
i386-sun-sunos4.0.2)ups_arch=ARCH_SUN386 ;; # Obsolete Sun386i
m68k-*-sunos*) ups_arch=ARCH_SUN3 ;;
sparc-*-*) ups_arch=ARCH_SUN4 ;;
! i?86-*-solaris*) ups_arch=ARCH_386 ;; # Not yet supported
i?86-*-freebsd1*) ups_arch=ARCH_BSDI386 ;;
i?86-*-freebsd*) ups_arch=ARCH_FREEBSD386 ;;
i?86-*-openbsd*) ups_arch=ARCH_OPENBSD386 ;;
--- 768,774 ----
i386-sun-sunos4.0.2)ups_arch=ARCH_SUN386 ;; # Obsolete Sun386i
m68k-*-sunos*) ups_arch=ARCH_SUN3 ;;
sparc-*-*) ups_arch=ARCH_SUN4 ;;
! i?86-*-solaris*) ups_arch=ARCH_SOLARISX86 ;;
i?86-*-freebsd1*) ups_arch=ARCH_BSDI386 ;;
i?86-*-freebsd*) ups_arch=ARCH_FREEBSD386 ;;
i?86-*-openbsd*) ups_arch=ARCH_OPENBSD386 ;;
*** ./ifdefs.h.in.orig 2003-08-30 23:53:17.000000000 +0530
--- ./ifdefs.h.in 2003-11-20 16:10:58.000000000 +0530
***************
*** 43,48 ****
--- 43,49 ----
* ARCH_ALPHA - DEC Alpha
*
* ARCH_386 - any Intel x86
+ * ARCH_SOLARISX86 - Solaris (x86)
* ARCH_LINUX386 - Linux (x86)
* ARCH_BSDI386 - should be BSD/OS (x86), actually any BSD (x86)
* ARCH_FREEBSD386 - FreeBSD (x86)
***************
*** 79,84 ****
--- 80,86 ----
#undef ARCH_SUN3
#undef ARCH_SUN4
#undef ARCH_386
+ #undef ARCH_SOLARISX86
#undef ARCH_FREEBSD386
#undef ARCH_OPENBSD386
#undef ARCH_NETBSD386
***************
*** 119,125 ****
* Any 386 ?
* ---------------------------------------------------------------------------
*/
! #if (ARCH_BSDI386) || (ARCH_LINUX386)
#define ARCH_386 1
#endif
--- 121,127 ----
* Any 386 ?
* ---------------------------------------------------------------------------
*/
! #if (ARCH_BSDI386) || (ARCH_LINUX386) || (ARCH_SOLARISX86)
#define ARCH_386 1
#endif
*** ./configure.orig 2003-08-29 20:18:50.000000000 +0530
--- ./configure 2003-11-20 15:50:13.000000000 +0530
***************
*** 12177,12183 ****
i386-sun-sunos4.0.2)ups_arch=ARCH_SUN386 ;; # Obsolete Sun386i
m68k-*-sunos*) ups_arch=ARCH_SUN3 ;;
sparc-*-*) ups_arch=ARCH_SUN4 ;;
! i?86-*-solaris*) ups_arch=ARCH_386 ;; # Not yet supported
i?86-*-freebsd1*) ups_arch=ARCH_BSDI386 ;;
i?86-*-freebsd*) ups_arch=ARCH_FREEBSD386 ;;
i?86-*-openbsd*) ups_arch=ARCH_OPENBSD386 ;;
--- 12177,12183 ----
i386-sun-sunos4.0.2)ups_arch=ARCH_SUN386 ;; # Obsolete Sun386i
m68k-*-sunos*) ups_arch=ARCH_SUN3 ;;
sparc-*-*) ups_arch=ARCH_SUN4 ;;
! i?86-*-solaris*) ups_arch=ARCH_SOLARISX86 ;;
i?86-*-freebsd1*) ups_arch=ARCH_BSDI386 ;;
i?86-*-freebsd*) ups_arch=ARCH_FREEBSD386 ;;
i?86-*-openbsd*) ups_arch=ARCH_OPENBSD386 ;;
ups-bugs.txt
(text/plain, 712 B)
UPS bugs, found during the Solaris/x86 porting (they have not been fixed for platforms other than Solaris/x86 for lack of test environment.) - The interpreted code for the first breakpoint that results in a stop is executed twice. For example, after the following: i = 42; ++i && #stop; i incorrectly becomes 44 (trun_ss.c:155) - Wrong reg no. for EBX while decoding PLT (ao_elflib.c:1755, ao_stack.c:528) (It seems to be using ESI instead of EBX.) This causes ups/tests/assertion test scenario to fail. - The addr_cmp for qsort function should make a 3-way return (-1,0,1) (ao_elflib.c:1595) The current function causes qsort to corrupt memory and cause crashes when figuring out solibs.