* [RFC] Adding new files, for new port to Interix (Services For Unix)
@ 2002-07-24 6:07 Joel Brobecker
2002-07-24 14:34 ` Mark Kettenis
2002-07-24 15:09 ` [RFC] Adding new files, for new port to Interix (Services For Unix) Andrew Cagney
0 siblings, 2 replies; 7+ messages in thread
From: Joel Brobecker @ 2002-07-24 6:07 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1441 bytes --]
Hello,
ACT is working on the integration of some changes that would allow GDB
to be built on interix (Services For Unix). The port has been done by
Donn Terry, with a bit of light rework here and there from myself.
The port was initially made some time ago so it was not multi-arched.
I started the conversion, and part of it is done. I haven't finished the
conversion, because I need a bit of help for the remaining part
to avoid spending too much time going in the wrong direction.
I am attaching to this message some files that I'd like to add to the
GDB trunk. These are only new files, and some other changes are still
needed for GDB to first configure properly, and then build.
My current plan regarding the inclusion of this new port is the
following:
- check-in the attached files, possibly (probably) with your comments
incorporated
- check-in the changes in the configury machinery in order for GDB to
configure
- check-in the minimal changes to allow GDB to build
- And then finally check-in the remaining changes that make GDB work.
For the curious, my regression testsuite results show about 6600
passes, and 1200 failures.
Any comments on the attached files, as well as the strategy above would
be greatly appreciated. I'd like to commit these new files as soon as
acceptable, as it makes it easier for me to discuss new changes and also
facilitate the management of these files.
Thanks,
--
Joel
[-- Attachment #2: i386-interix-nat.c --]
[-- Type: text/plain, Size: 11506 bytes --]
/* Native-dependent code for Interix running on i386's, for GDB.
Copyright 2002 Free Software Foundation, Inc.
This file is part of GDB.
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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include <sys/procfs.h>
#include <ucontext.h>
#include <frame.h>
#include <inferior.h>
#include <fcntl.h>
#include <i386-tdep.h>
#include "symfile.h"
#include "objfiles.h"
#include "gdb-stabs.h"
#include "gdbcore.h"
#include "gregset.h"
typedef unsigned long greg_t; /* Where should this be defined? */
/* See procfs.c and *interix*.h in config/[alpha,i386] */
/* The /proc interface traditionally divides the target machine's register
set up into two different sets, the general register set (gregset)
and the floating point register set (fpregset). This is reflected
in the data structures in <sys/regset.h>.
However, the read/write /proc for interix treats them all as part
of the status subfile.
These routines provide the packing and unpacking of gregset_t and
fpregset_t formatted data.
*/
/* This is a duplicate of the table in i386-xdep.c. */
static int regmap[] =
{
EAX, ECX, EDX, EBX,
UESP, EBP, ESI, EDI,
EIP, EFL, CS, SS,
DS, ES, FS, GS,
};
/* Given a pointer to a general register set in /proc format (gregset_t *),
unpack the register contents and supply them as gdb's idea of the current
register values. */
void
supply_gregset (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register greg_t *regp = (greg_t *) &gregsetp->gregs;
for (regi = 0; regi < I386_NUM_GREGS; regi++)
{
supply_register (regi, (char *) (regp + regmap[regi]));
}
}
/* Fill in a gregset_t object with selected data from a gdb-format
register file.
- GREGSETP points to the gregset_t object to be filled.
- GDB_REGS points to the GDB-style register file providing the data.
- VALID is an array indicating which registers in GDB_REGS are
valid; the parts of *GREGSETP that would hold registers marked
invalid in GDB_REGS are left unchanged. If VALID is zero, all
registers are assumed to be valid. */
void
convert_to_gregset (gregset_t *gregsetp,
char *gdb_regs,
signed char *valid)
{
int regi;
register greg_t *regp = (greg_t *) gregsetp->gregs;
for (regi = 0; regi < I386_NUM_GREGS; regi++)
if (! valid || valid[regi])
*(regp + regmap[regi]) = * (int *) ®isters[REGISTER_BYTE (regi)];
}
/* Store GDB's value for REGNO in *GREGSETP. If REGNO is -1, do all
of them. */
void
fill_gregset (gregset_t *gregsetp,
int regno)
{
if (regno == -1)
convert_to_gregset (gregsetp, registers, 0);
else if (regno >= 0 && regno < I386_NUM_GREGS)
{
signed char valid[I386_NUM_GREGS];
memset (valid, 0, sizeof (valid));
valid[regno] = 1;
convert_to_gregset (gregsetp, registers, valid);
}
}
/* Given a pointer to a floating point register set in /proc format
(fpregset_t *), unpack the register contents and supply them as gdb's
idea of the current floating point register values. */
/* What is the address of st(N) within the fpregset_t structure F? */
#define FPREGSET_T_FPREG_ADDR(f, n) \
((char *) &(f)->fpstate.fpregs + (n) * 10)
/* Fill GDB's register file with the floating-point register values in
*FPREGSETP. */
void
supply_fpregset (fpregset_t *fpregsetp)
{
int i;
long l;
/* Supply the floating-point registers. */
for (i = 0; i < 8; i++)
supply_register (FP0_REGNUM + i, FPREGSET_T_FPREG_ADDR (fpregsetp, i));
l = fpregsetp->fpstate.control & 0xffff;
supply_register (FCTRL_REGNUM, (char *) &l);
l = fpregsetp->fpstate.status & 0xffff;
supply_register (FSTAT_REGNUM, (char *) &l);
l = fpregsetp->fpstate.tag & 0xffff;
supply_register (FTAG_REGNUM, (char *) &l);
supply_register (FCOFF_REGNUM, (char *) &fpregsetp->fpstate.erroroffset);
l = fpregsetp->fpstate.dataselector & 0xffff;
supply_register (FDS_REGNUM, (char *) &l);
supply_register (FDOFF_REGNUM, (char *) &fpregsetp->fpstate.dataoffset);
/* Extract the code segment and opcode from the "fcs" member. */
l = fpregsetp->fpstate.errorselector & 0xffff;
supply_register (FCS_REGNUM, (char *) &l);
l = (fpregsetp->fpstate.errorselector >> 16) & ((1 << 11) - 1);
supply_register (FOP_REGNUM, (char *) &l);
}
/* Fill in an fpregset_t structure with selected data from a
gdb-format register file.
- FPREGSETP points to the structure to be filled.
- GDB_REGS points to the GDB-style register file providing the data.
- VALID is an array indicating which registers in GDB_REGS are
valid; the parts of *FPREGSETP that would hold registers marked
invalid in GDB_REGS are left unchanged. If VALID is zero, all
registers are assumed to be valid. */
void
convert_to_fpregset (fpregset_t *fpregsetp,
char *gdb_regs,
signed char *valid)
{
int i;
/* Fill in the floating-point registers. */
for (i = 0; i < 8; i++)
if (!valid || valid[i])
memcpy (FPREGSET_T_FPREG_ADDR (fpregsetp, i),
®isters[REGISTER_BYTE (FP0_REGNUM + i)],
REGISTER_RAW_SIZE(FP0_REGNUM + i));
#define fill(MEMBER, REGNO) \
if (! valid || valid[(REGNO)]) \
memcpy (&fpregsetp->fpstate.MEMBER, ®isters[REGISTER_BYTE (REGNO)], \
sizeof (fpregsetp->fpstate.MEMBER))
fill (control, FCTRL_REGNUM);
fill (status, FSTAT_REGNUM);
fill (tag, FTAG_REGNUM);
fill (erroroffset, FCOFF_REGNUM);
fill (dataoffset, FDOFF_REGNUM);
fill (dataselector, FDS_REGNUM);
#undef fill
if (! valid || valid[FCS_REGNUM])
fpregsetp->fpstate.errorselector
= ((fpregsetp->fpstate.errorselector & ~0xffff)
| (* (int *) ®isters[REGISTER_BYTE (FCS_REGNUM)] & 0xffff));
if (! valid || valid[FOP_REGNUM])
fpregsetp->fpstate.errorselector
= ((fpregsetp->fpstate.errorselector & 0xffff)
| ((*(int *) ®isters[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1))
<< 16));
}
/* Given a pointer to a floating point register set in (fpregset_t *)
format, update all of the registers from gdb's idea of the current
floating point register set. */
void
fill_fpregset (fpregset_t *fpregsetp,
int regno)
{
convert_to_fpregset (fpregsetp, registers, 0);
}
/*
GLOBAL FUNCTION
fetch_core_registers -- fetch current registers from core file
SYNOPSIS
void fetch_core_registers (char *core_reg_sect,
unsigned core_reg_size,
int which, CORE_ADDR reg_addr)
DESCRIPTION
Read the values of either the general register set (WHICH equals 0)
or the floating point register set (WHICH equals 2) from the core
file data (pointed to by CORE_REG_SECT), and update gdb's idea of
their current values. The CORE_REG_SIZE parameter is compared to
the size of the gregset or fpgregset structures (as appropriate) to
validate the size of the structure from the core file. The
REG_ADDR parameter is ignored.
*/
static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
CORE_ADDR reg_addr)
{
gdb_gregset_t gregset;
gdb_fpregset_t fpregset;
if (which == 0)
{
if (core_reg_size != sizeof (gregset))
{
warning ("wrong size gregset struct in core file");
}
else
{
memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
supply_gregset (&gregset);
}
}
else if (which == 2)
{
if (core_reg_size != sizeof (fpregset))
{
warning ("wrong size fpregset struct in core file");
}
else
{
memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
if (FP0_REGNUM >= 0)
supply_fpregset (&fpregset);
}
}
}
/* the name of the proc status struct depends on the implementation */
#ifdef HAVE_PSTATUS_T
typedef pstatus_t gdb_prstatus_t;
#else
typedef prstatus_t gdb_prstatus_t;
#endif
/* Figure out where the longjmp will land.
We expect the first arg to be a pointer to the jmp_buf structure from which
we extract the pc that we will land at. The pc is copied into PC.
This routine returns true on success. */
#include <setjmp.h>
int
get_longjmp_target (pc)
CORE_ADDR *pc;
{
CORE_ADDR sp, jb_addr;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
sp = read_register (SP_REGNUM);
if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
raw_buffer,
TARGET_PTR_BIT / TARGET_CHAR_BIT))
return 0;
jb_addr = extract_address (raw_buffer, TARGET_PTR_BIT / TARGET_CHAR_BIT);
if (target_read_memory(jb_addr + offsetof(_JUMP_BUFFER,Eip), raw_buffer,
sizeof(CORE_ADDR)))
return 0;
*pc = extract_address (raw_buffer, sizeof(CORE_ADDR));
return 1;
}
static struct core_fns interix_core_fns =
{
bfd_target_coff_flavour, /* core_flavour (more or less) */
default_check_format, /* check_format */
default_core_sniffer, /* core_sniffer */
fetch_core_registers, /* core_read_registers */
NULL /* next */
};
void
_initialize_core_interix (void)
{
add_core_fns (&interix_core_fns);
if (TARGET_LONG_BIT != 32)
printf_unfiltered ("ERROR: TARGET_LONG_BIT = %d /= 32!\n", TARGET_LONG_BIT);
if (TARGET_LONG_LONG_BIT != 64)
printf_unfiltered
("ERROR: TARGET_LONG_LONG_BIT = %d /= 64!\n", TARGET_LONG_LONG_BIT);
}
/* Adjust the section offsets in an objfile structure so that it's correct
for the type of symbols being read (or undo it with the _restore
arguments).
If main programs ever start showing up at other than the default Image
Base, this is where that would likely be applied. */
void
pei_adjust_objfile_offsets(struct objfile *objfile, enum objfile_adjusts type)
{
int i;
CORE_ADDR symbols_offset;
switch (type) {
case adjust_for_symtab:
symbols_offset = NONZERO_LINK_BASE(objfile->obfd);
break;
case adjust_for_symtab_restore:
symbols_offset = -NONZERO_LINK_BASE(objfile->obfd);
break;
case adjust_for_stabs:
case adjust_for_stabs_restore:
case adjust_for_dwarf:
case adjust_for_dwarf_restore:
default:
return;
}
for (i = 0; i < SECT_OFF_MAX; i++)
{
(objfile->section_offsets)->offsets[i] += symbols_offset;
}
}
/* We don't have a /proc/pid/file or /proc/pid/exe to read a link from,
so read it from the same place ps gets the name. */
char *
child_pid_to_exec_file (int pid)
{
char *path;
char *buf;
int fd, c;
char *p;
asprintf (&path, "/proc/%d/stat", pid);
buf = xcalloc (MAXPATHLEN+1, sizeof (char));
make_cleanup (xfree, path);
make_cleanup (xfree, buf);
fd = open (path, O_RDONLY);
if (fd < 0)
return NULL;
/* Skip over "Argv0\t" */
lseek (fd, 6, SEEK_SET);
c = read (fd, buf, MAXPATHLEN);
close (fd);
if (c < 0)
return NULL;
buf[c] = '\0'; /* Ensure null termintion. */
p = strchr(buf, '\n');
if (p != NULL)
*p = '\0';
return buf;
}
[-- Attachment #3: i386-interix-tdep.c --]
[-- Type: text/plain, Size: 13457 bytes --]
/* Native-dependent code for Interix running on i386's, for GDB.
Copyright 2002 Free Software Foundation, Inc.
This file is part of GDB.
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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "arch-utils.h"
#include "frame.h"
#include "gdb_string.h"
#include "gdbcore.h"
#include "gdbtypes.h"
#include "inferior.h"
#include "libbfd.h"
#include "osabi.h"
/* FIXME: This is not right, we should not be including this file in
-tdep module. But this is needed by interix_back_one_frame. */
#include <sys/procfs.h>
/* ??? Why do we need an extern here??? */
extern CORE_ADDR skip_trampoline_code (CORE_ADDR pc, char *name);
/* Some constants describing the i386 interix target */
static const int i386_interix_long_bit = 32;
static const int i386_interix_long_long_bit = 64;
static const int i386_interix_ptr_bit = 32;
static const CORE_ADDR i386_interix_decr_pc_after_break = 0;
/* See procfs.c and *interix*.h in config/[alpha,i386] */
/* ??? These should be static, but this needs a bit of work before this
can be done. */
CORE_ADDR tramp_start;
CORE_ADDR tramp_end;
CORE_ADDR null_start;
CORE_ADDR null_end;
int winver; /* Windows NT version number */
static int
i386_interix_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
/* This is sufficient, where used, but is NOT a complete test; There
is more in INIT_EXTRA_FRAME_INFO (a.k.a. interix_back_one_frame) */
return (pc >= tramp_start && pc < tramp_end)
|| (pc >= null_start && pc < null_end);
}
static int
i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
{
return skip_trampoline_code (pc, name);
}
static CORE_ADDR
i386_interix_skip_trampoline_code (CORE_ADDR pc)
{
return skip_trampoline_code (pc, 0);
}
static void
i386_interix_init_frame_pc (int fromleaf, struct frame_info *prev)
{
/* Nothing to do on Interix */
}
static int
i386_interix_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
{
/* In the context where this is used, we get the saved PC before we've
successfully unwound far enough to be sure what we've got (it may
be a signal handler caller). If we're dealing with a signal
handler caller, this will return valid, which is fine. If not,
it'll make the correct test. */
return thisframe->signal_handler_caller
|| (chain != 0
&& !inside_entry_file (read_memory_integer (thisframe->frame + 4,
4)));
}
/* We want to find the previous frame, which on Interix is tricky when signals
are involved; set frame->frame appropriately, and also get the pc
and tweak signal_handler_caller; this replaces a boatload of nested
macros, as well. */
static void
i386_interix_back_one_frame (fromleaf, frame)
int fromleaf;
struct frame_info *frame;
{
CORE_ADDR ra;
CORE_ADDR fm;
CORE_ADDR context;
long t;
if (frame == NULL)
abort();
if (fromleaf)
{
frame->pc = SAVED_PC_AFTER_CALL (frame->next);
return;
}
if (!frame->next)
{
frame->pc = read_pc();
/* part of the signal stuff... see below */
if (stopped_by_random_signal)
{
/* we know we're in a system call mini-frame; was it
NullApi or something else? */
ra = SAVED_PC_AFTER_CALL (frame);
if (ra >= null_start && ra < null_end)
frame->signal_handler_caller = 1;
/* There might also be an indirect call to the mini-frame,
putting one more return address on the stack. (XP only,
I think?) This can't (reasonably) return the address of the
signal handler caller unless it's that situation, so this
is safe. */
ra = read_memory_unsigned_integer (
(CORE_ADDR) read_register (SP_REGNUM)+4, 4);
if (ra >= null_start && ra < null_end)
frame->signal_handler_caller = 1;
}
return;
}
if (!frame->next->signal_handler_caller)
{
frame->pc = (CORE_ADDR)read_memory_integer (frame->next->frame + 4, 4);
return;
}
/* This is messy... (actually AWFUL) the "trampoline" might be 2, 3
or all 5 entities on the frame.
Chunk 1 will be present when we're actually in a signal handler.
Chunk 2 will be present when an asynchronous signal (one that
didn't come in with a system call) is present.
We may not (yet) be in the handler, if we're just returning
from the call.
When we're actually in a handler taken from an asynchronous
signal, both will be present.
Chunk 1:
PdxSignalDeliverer's frame
+ Context struct -- not accounted for in any frame
Chunk 2:
+ PdxNullPosixApi's frame
+ PdxNullApiCaller's frame
+ Context struct = 0x230 not accounted for in any frame
The symbol names come from examining objdumps of psxdll.dll;
they don't appear in the runtime image.
For gdb's purposes, we can pile all this into one frame.
*/
ra = frame->next->pc;
/* Are we already pointing at PdxNullPosixApi? We are if
this is a signal frame, we're at next-to-top, and were stopped
by a random signal. (If it wasn't the right address under
these circumstances, we wouldn't be here at all by tests above
on the prior frame.) */
if (frame->next->next == NULL && stopped_by_random_signal)
{
/* We're pointing at the frame FOR PdxNullApi */
fm = frame->frame;
}
else
{
/* No... we must be pointing at the frame that
was called by PdxSignalDeliverer; back up across the
whole mess */
/* extract the frame for PdxSignalDeliverer; note...FRAME_CHAIN
used the "old" frame pointer because we were a deliverer.
Get the address of the context record that's on here frameless */
context = read_memory_integer (frame->frame, 4); /* an Arg */
/* Now extract the frame pointer contained in the context */
fm = (CORE_ADDR)read_memory_integer
(context + offsetof(mcontext_t, gregs.gregs[EBP]), 4);
ra = (CORE_ADDR)read_memory_integer
(context + offsetof(mcontext_t, gregs.gregs[EIP]), 4);
/* We need to know if we're in a system call because we'll be
in a syscall mini-frame, if so, and the rules are different;
reserved[1] contains 0 if running free, 1 if blocked on a system
call, and 2 if blocked on an exception message (e.g. a trap);
we don't expect to get here with a 2. */
t = (long)read_memory_integer
(context + offsetof(mcontext_t, gregs.reserved[1]), 4);
if (t != 1)
{
/* not at a system call, therefore it can't be NullApi */
frame->pc = ra;
frame->frame = fm;
return;
}
/* It's a system call... mini frame, then look for NullApi */
/* Get the RA (on the stack) associated with this... it's
a system call mini-frame */
ra = (CORE_ADDR)read_memory_integer
(context + offsetof(mcontext_t, gregs.gregs[UESP]), 4);
if (winver>=51) {
/* Newer versions of Windows NT interpose another return
address (but no other "stack frame" stuff) that we need
to simply ignore here. */
ra+=4;
}
ra = (CORE_ADDR)read_memory_integer(ra,4);
/* We might be done (no Null API if so) */
if (!(ra >= null_start && ra < null_end))
{
/* No Null API present; we're done */
frame->pc = ra;
frame->frame = fm;
return;
}
}
/* At this point, we're looking at the frame for PdxNullPosixApi,
in either case.
PdxNullPosixApi is called by PdxNullApiCaller (which in turn
is called by _PdxNullApiCaller (note the _).)
PdxNullPosixApiCaller (no _) is a frameless function.
The saved frame pointer is as fm, but it's not of interest
to us because it skips us over the saved context, which is
the wrong thing to do, because it skips the interrrupted
routine! PdxNullApiCaller takes as its only argument the
address of the context of the interrupded function (which
is really in no frame, but jammed on the stack by the system)
So: fm+0: saved bp
fm+4: return address to _PdxNullApiCaller
fm+8: arg to PdxNullApiCaller pushed by _Pdx... */
fm = (CORE_ADDR)read_memory_integer (fm+0x8, 4);
/* Extract the second context record */
ra = (CORE_ADDR)read_memory_integer
(fm + offsetof(mcontext_t, gregs.gregs[EIP]), 4);
fm = (CORE_ADDR)read_memory_integer
(fm + offsetof(mcontext_t, gregs.gregs[EBP]), 4);
frame->frame = fm;
frame->pc = ra;
return;
}
static CORE_ADDR
i386_interix_frame_saved_pc (struct frame_info *fi)
{
/* Assume that we've already unwound enough to have the caller's address
if we're dealing with a signal handler caller. (And if that fails,
return 0.) */
if (fi->signal_handler_caller)
return fi->next ? fi->next->pc : 0;
else
return (CORE_ADDR) read_memory_integer (fi->frame + 4, 4);
}
static int
i386_interix_use_struct_convention (int gcc_p, struct type *type)
{
/* Directly copied from nbsd where this function is no longer defined,
as a generic mechanism is used. Maybe we should take advantage of
this mechanism too? */
return !(TYPE_LENGTH (type) == 1
|| TYPE_LENGTH (type) == 2
|| TYPE_LENGTH (type) == 4
|| TYPE_LENGTH (type) == 8);
}
void
i386_interix_cache_trampoline_addresses_from_bfd (void)
{
/* This is painful, but there doesn't seem to be a better way.
See interix tm.h, IN_SIGTRAMP, and procfs.c for more details. */
asection *section;
pstatus_t *p;
section = bfd_get_section_by_name (core_bfd, ".pstatus");
if (section == NULL)
{
/* This should never happen, we are just being extra cautious. */
warning (".pstatus section not found.");
return;
}
p = (pstatus_t *)section->contents;
if (p == NULL)
{
p = (pstatus_t *)bfd_alloc(core_bfd, section->_raw_size);
bfd_get_section_contents (core_bfd, section, p, 0, section->_raw_size);
}
tramp_start = (CORE_ADDR)p->pr_signaldeliverer;
tramp_end = (CORE_ADDR)p->pr_endsignaldeliverer;
null_start = (CORE_ADDR)p->pr_nullapi;
null_end = (CORE_ADDR)p->pr_endnullapi;
}
void
i386_interix_cache_trampoline_addresses (CORE_ADDR trampoline_start,
CORE_ADDR trampoline_end,
CORE_ADDR nullapi_start,
CORE_ADDR nullapi_end)
{
/* On Interix, the location of the trampoline code can
float, and it's not part of the symbol table (because
it's internal to a DLL). However, the system knows where
it is, and tells us, so we capture that info here. */
/* While we're doing such ugly things, find out which
version of NT this is, so we can change our unwind rules
a bit.
FIXME: If we move this, move the include of utsname.h, too.*/
tramp_start = trampoline_start;
tramp_end = trampoline_end;
null_start = nullapi_start;
null_end = nullapi_end;
}
static void
i386_interix_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
/* ??? Externs, temporarily defined */
extern int get_longjmp_target (CORE_ADDR *pc);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
set_gdbarch_long_bit (gdbarch, i386_interix_long_bit);
set_gdbarch_long_long_bit (gdbarch, i386_interix_long_long_bit);
set_gdbarch_use_struct_convention (gdbarch,
i386_interix_use_struct_convention);
set_gdbarch_ptr_bit (gdbarch, i386_interix_ptr_bit);
set_gdbarch_decr_pc_after_break (gdbarch, i386_interix_decr_pc_after_break);
set_gdbarch_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
/* ??? The following may already be the default on i386 architecture */
set_gdbarch_in_solib_call_trampoline (gdbarch,
i386_interix_in_solib_call_trampoline);
set_gdbarch_skip_trampoline_code (gdbarch, i386_interix_skip_trampoline_code);
set_gdbarch_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
set_gdbarch_init_frame_pc (gdbarch, i386_interix_init_frame_pc);
set_gdbarch_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
set_gdbarch_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
/* ??? the following may already be the default for i386 architecture */
set_gdbarch_get_longjmp_target (gdbarch, get_longjmp_target);
}
static enum gdb_osabi
i386_interix_osabi_sniffer (bfd *abfd)
{
char *target_name = bfd_get_target (abfd);
if (strcmp (target_name, "pei-i386") == 0)
return GDB_OSABI_INTERIX;
return GDB_OSABI_UNKNOWN;
}
void
_initialize_i386_interix_tdep (void)
{
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
i386_interix_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_INTERIX,
i386_interix_init_abi);
}
[-- Attachment #4: config/i386/tm-i386interix.h --]
[-- Type: text/plain, Size: 1920 bytes --]
/* Macro definitions for i386 running under Interix
Copyright 2002 Free Software Foundation, Inc.
This file is part of GDB.
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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef TM_INTERIX_H
#define TM_INTERIX_H
#include "i386/tm-i386.h"
/* configure can't be expected to noodle out MS's alternate spelling for
64-bit integers, so we'll tell it. */
#define PRINTF_HAS_LONG_LONG 1
#ifdef __GNUC__
#define BFD_HOST_64_BIT long long
#define BFD_HOST_U_64_BIT unsigned long long
#elif defined(_MSC_VER)
#define BFD_HOST_64_BIT __int64
#define BFD_HOST_U_64_BIT unsigned __int64
#else
#error... OK what compiler is this?
#endif
#undef LONGEST
#define LONGEST BFD_HOST_64_BIT
#undef ULONGEST
#define ULONGEST BFD_HOST_U_64_BIT
#define I386_FLOATS_RETURN_IN_ST0
/* Interix has a minimal sbrk() (but not what's wanted for this usage),
and it's relationship to environ[] is not what's usually expected
(as in, there is no specific relationship at all). Just pretend we don't
have an sbrk(). */
#undef HAVE_SBRK
#define ADJUST_OBJFILE_OFFSETS(objfile, type) \
pei_adjust_objfile_offsets(objfile, type)
extern CORE_ADDR bfd_getImageBase(bfd *abfd);
#define NONZERO_LINK_BASE(abfd) bfd_getImageBase(abfd)
#define NAME_OF_MALLOC "_malloc"
#endif /* TM_INTERIX_H */
[-- Attachment #5: config/i386/nm-interix.h --]
[-- Type: text/plain, Size: 1835 bytes --]
/* Native-dependent definitions for Intel 386 running Interix, for GDB.
Copyright 2002 Free Software Foundation, Inc.
This file is part of GDB.
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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef NM_INTERIX_H
#define NM_INTERIX_H
#define USE_PROC_FS
/* submodes of USE_PROC_FS */
#define PROCFS_USE_READ_WRITE
#define HAVE_MULTIPLE_PROC_FDS
#define UNIXWARE
#define HAVE_STRUCT_LWP
#define ATTACH_DETACH
/* Be shared lib aware */
#include "solib.h"
/* This is the amount to subtract from u.u_ar0
to get the offset in the core file of the register values. */
#if 0
#include <machine/vmparam.h>
#define KERNEL_U_ADDR USRSTACK
#endif
#define REGISTER_U_ADDR(addr, blockend, regno) \
(addr) = i386_register_u_addr ((blockend),(regno));
extern int
i386_register_u_addr PARAMS ((int, int));
#define PTRACE_ARG3_TYPE char*
/* Return sizeof user struct to callers in less machine dependent routines */
#define KERNEL_U_SIZE kernel_u_size()
extern int kernel_u_size PARAMS ((void));
/* It's ALMOST coff; bfd does the same thing */
#define COFF_WITH_PE
#define COFF_IMAGE_WITH_PE
/* Turn on our own child_pid_to_exec_file. */
#define CHILD_PID_TO_EXEC_FILE
#endif /* NM_INTERIX_H */
[-- Attachment #6: config/i386/interix.mh --]
[-- Type: text/plain, Size: 305 bytes --]
# Host: Intel 386 running Interix
XDEPFILES=
NATDEPFILES= corelow.o core-regset.o fork-child.o i386-interix-nat.o \
procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
NAT_FILE= nm-interix.h
# The below may be temporary; mmalloc relies on sbrk() at the moment
MMALLOC=
MMALLOC_CFLAGS=-DNO_MMALLOC
[-- Attachment #7: config/i386/interix.mt --]
[-- Type: text/plain, Size: 163 bytes --]
# Target: Intel 386 running Interix
TDEPFILES= i386-tdep.o i387-tdep.o i386-interix-tdep.o \
solib.o solib-pei.o i386nbsd-tdep.o
TM_FILE= tm-i386interix.h
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [RFC] Adding new files, for new port to Interix (Services For Unix)
2002-07-24 6:07 [RFC] Adding new files, for new port to Interix (Services For Unix) Joel Brobecker
@ 2002-07-24 14:34 ` Mark Kettenis
2002-07-24 15:45 ` Andrew Cagney
2002-07-24 15:09 ` [RFC] Adding new files, for new port to Interix (Services For Unix) Andrew Cagney
1 sibling, 1 reply; 7+ messages in thread
From: Mark Kettenis @ 2002-07-24 14:34 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[ Sorry Joel for the duplicate, I forgot to CC gdb-patches. ]
Joel Brobecker <brobecker@gnat.com> writes:
> --uQr8t48UFsdbeI+V
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: inline
>
> Hello,
>
> ACT is working on the integration of some changes that would allow GDB
> to be built on interix (Services For Unix). The port has been done by
> Donn Terry, with a bit of light rework here and there from myself.
Thanks for the contribution.
> The port was initially made some time ago so it was not multi-arched.
> I started the conversion, and part of it is done. I haven't finished the
> conversion, because I need a bit of help for the remaining part
> to avoid spending too much time going in the wrong direction.
Ok, I reviewed the new files. I hope my comments will be useful to you.
> I am attaching to this message some files that I'd like to add to the
> GDB trunk. These are only new files, and some other changes are still
> needed for GDB to first configure properly, and then build.
>
> My current plan regarding the inclusion of this new port is the
> following:
> - check-in the attached files, possibly (probably) with your comments
> incorporated
> - check-in the changes in the configury machinery in order for GDB to
> configure
> - check-in the minimal changes to allow GDB to build
> - And then finally check-in the remaining changes that make GDB work.
> For the curious, my regression testsuite results show about 6600
> passes, and 1200 failures.
Looks like a good strategy to me.
> Any comments on the attached files, as well as the strategy above would
> be greatly appreciated. I'd like to commit these new files as soon as
> acceptable, as it makes it easier for me to discuss new changes and also
> facilitate the management of these files.
A general remark: It looks like the port was started a while back, and
not all changes in coding conventions for GDB that we had in the
meantime have been followed:
* Comments should always be full sentences in the sense that they
start with a capital and end with a full stop (dot). After a full
stop we use two spaces.
* Don't use the keyword `register'.
* Use ISO C prototypes.
* Use spaces after every ',' and before and after '=', '+=' etc.
Success!
Mark
> --uQr8t48UFsdbeI+V
> Content-Type: text/plain; charset=us-ascii
> Content-Description: i386-interix-nat.c
> Content-Disposition: attachment; filename="i386-interix-nat.c"
>
> /* Native-dependent code for Interix running on i386's, for GDB.
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> 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 2 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, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
>
> #include "defs.h"
>
> #include <sys/procfs.h>
> #include <ucontext.h>
> #include <frame.h>
> #include <inferior.h>
> #include <fcntl.h>
>
> #include <i386-tdep.h>
> #include "symfile.h"
> #include "objfiles.h"
> #include "gdb-stabs.h"
> #include "gdbcore.h"
> #include "gregset.h"
>
>
> typedef unsigned long greg_t; /* Where should this be defined? */
It should be in <sys/reg.h> if Interix is trying too look like SVR4.
>
> /* See procfs.c and *interix*.h in config/[alpha,i386] */
>
> /* The /proc interface traditionally divides the target machine's register
> set up into two different sets, the general register set (gregset)
> and the floating point register set (fpregset). This is reflected
> in the data structures in <sys/regset.h>.
>
> However, the read/write /proc for interix treats them all as part
> of the status subfile.
>
> These routines provide the packing and unpacking of gregset_t and
> fpregset_t formatted data.
>
> */
>
> /* This is a duplicate of the table in i386-xdep.c. */
This statement is defenitely not true.
> static int regmap[] =
> {
> EAX, ECX, EDX, EBX,
> UESP, EBP, ESI, EDI,
> EIP, EFL, CS, SS,
> DS, ES, FS, GS,
> };
>
> /* Given a pointer to a general register set in /proc format (gregset_t *),
> unpack the register contents and supply them as gdb's idea of the current
> register values. */
>
> void
> supply_gregset (gregsetp)
> gregset_t *gregsetp;
> {
> register int regi;
> register greg_t *regp = (greg_t *) &gregsetp->gregs;
>
> for (regi = 0; regi < I386_NUM_GREGS; regi++)
> {
> supply_register (regi, (char *) (regp + regmap[regi]));
> }
> }
>
> /* Fill in a gregset_t object with selected data from a gdb-format
> register file.
> - GREGSETP points to the gregset_t object to be filled.
> - GDB_REGS points to the GDB-style register file providing the data.
> - VALID is an array indicating which registers in GDB_REGS are
> valid; the parts of *GREGSETP that would hold registers marked
> invalid in GDB_REGS are left unchanged. If VALID is zero, all
> registers are assumed to be valid. */
> void
> convert_to_gregset (gregset_t *gregsetp,
> char *gdb_regs,
> signed char *valid)
> {
> int regi;
> register greg_t *regp = (greg_t *) gregsetp->gregs;
>
> for (regi = 0; regi < I386_NUM_GREGS; regi++)
> if (! valid || valid[regi])
> *(regp + regmap[regi]) = * (int *) ®isters[REGISTER_BYTE (regi)];
> }
Using `registers' is no longer allowed.
>
> /* Store GDB's value for REGNO in *GREGSETP. If REGNO is -1, do all
> of them. */
> void
> fill_gregset (gregset_t *gregsetp,
> int regno)
> {
> if (regno == -1)
> convert_to_gregset (gregsetp, registers, 0);
> else if (regno >= 0 && regno < I386_NUM_GREGS)
> {
> signed char valid[I386_NUM_GREGS];
> memset (valid, 0, sizeof (valid));
> valid[regno] = 1;
> convert_to_gregset (gregsetp, registers, valid);
> }
> }
Why this complicated stuff with two functions and an extra array necessary?
> /* Given a pointer to a floating point register set in /proc format
> (fpregset_t *), unpack the register contents and supply them as gdb's
> idea of the current floating point register values. */
>
> /* What is the address of st(N) within the fpregset_t structure F? */
> #define FPREGSET_T_FPREG_ADDR(f, n) \
> ((char *) &(f)->fpstate.fpregs + (n) * 10)
>
> /* Fill GDB's register file with the floating-point register values in
> *FPREGSETP. */
> void
> supply_fpregset (fpregset_t *fpregsetp)
> {
> int i;
> long l;
>
> /* Supply the floating-point registers. */
> for (i = 0; i < 8; i++)
> supply_register (FP0_REGNUM + i, FPREGSET_T_FPREG_ADDR (fpregsetp, i));
>
> l = fpregsetp->fpstate.control & 0xffff;
> supply_register (FCTRL_REGNUM, (char *) &l);
> l = fpregsetp->fpstate.status & 0xffff;
> supply_register (FSTAT_REGNUM, (char *) &l);
> l = fpregsetp->fpstate.tag & 0xffff;
> supply_register (FTAG_REGNUM, (char *) &l);
> supply_register (FCOFF_REGNUM, (char *) &fpregsetp->fpstate.erroroffset);
> l = fpregsetp->fpstate.dataselector & 0xffff;
> supply_register (FDS_REGNUM, (char *) &l);
> supply_register (FDOFF_REGNUM, (char *) &fpregsetp->fpstate.dataoffset);
>
> /* Extract the code segment and opcode from the "fcs" member. */
>
> l = fpregsetp->fpstate.errorselector & 0xffff;
> supply_register (FCS_REGNUM, (char *) &l);
>
> l = (fpregsetp->fpstate.errorselector >> 16) & ((1 << 11) - 1);
> supply_register (FOP_REGNUM, (char *) &l);
> }
>
>
> /* Fill in an fpregset_t structure with selected data from a
> gdb-format register file.
> - FPREGSETP points to the structure to be filled.
> - GDB_REGS points to the GDB-style register file providing the data.
> - VALID is an array indicating which registers in GDB_REGS are
> valid; the parts of *FPREGSETP that would hold registers marked
> invalid in GDB_REGS are left unchanged. If VALID is zero, all
> registers are assumed to be valid. */
> void
> convert_to_fpregset (fpregset_t *fpregsetp,
> char *gdb_regs,
> signed char *valid)
> {
> int i;
>
> /* Fill in the floating-point registers. */
> for (i = 0; i < 8; i++)
> if (!valid || valid[i])
> memcpy (FPREGSET_T_FPREG_ADDR (fpregsetp, i),
> ®isters[REGISTER_BYTE (FP0_REGNUM + i)],
> REGISTER_RAW_SIZE(FP0_REGNUM + i));
>
> #define fill(MEMBER, REGNO) \
> if (! valid || valid[(REGNO)]) \
> memcpy (&fpregsetp->fpstate.MEMBER, ®isters[REGISTER_BYTE (REGNO)], \
> sizeof (fpregsetp->fpstate.MEMBER))
>
> fill (control, FCTRL_REGNUM);
> fill (status, FSTAT_REGNUM);
> fill (tag, FTAG_REGNUM);
> fill (erroroffset, FCOFF_REGNUM);
> fill (dataoffset, FDOFF_REGNUM);
> fill (dataselector, FDS_REGNUM);
>
> #undef fill
>
> if (! valid || valid[FCS_REGNUM])
> fpregsetp->fpstate.errorselector
> = ((fpregsetp->fpstate.errorselector & ~0xffff)
> | (* (int *) ®isters[REGISTER_BYTE (FCS_REGNUM)] & 0xffff));
>
> if (! valid || valid[FOP_REGNUM])
> fpregsetp->fpstate.errorselector
> = ((fpregsetp->fpstate.errorselector & 0xffff)
> | ((*(int *) ®isters[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1))
> << 16));
> }
>
>
> /* Given a pointer to a floating point register set in (fpregset_t *)
> format, update all of the registers from gdb's idea of the current
> floating point register set. */
>
> void
> fill_fpregset (fpregset_t *fpregsetp,
> int regno)
> {
> convert_to_fpregset (fpregsetp, registers, 0);
> }
Is there any reason you can't use i387_supply_fsave and
i387_fill_fsave here? I would be seriously surprised if you couldn't.
That said, please consider using i386v4-nat.c for Interix. Apart from
the greg_t typedef issue that should work without problems, and I'm
certainly willing to add something like:
#ifndef HAVE_GREG_T
typedef unsigned long greg_t;
#endif
to that file together with a suitable autoconf check.
> /*
>
> GLOBAL FUNCTION
>
> fetch_core_registers -- fetch current registers from core file
>
> SYNOPSIS
>
> void fetch_core_registers (char *core_reg_sect,
> unsigned core_reg_size,
> int which, CORE_ADDR reg_addr)
>
> DESCRIPTION
>
> Read the values of either the general register set (WHICH equals 0)
> or the floating point register set (WHICH equals 2) from the core
> file data (pointed to by CORE_REG_SECT), and update gdb's idea of
> their current values. The CORE_REG_SIZE parameter is compared to
> the size of the gregset or fpgregset structures (as appropriate) to
> validate the size of the structure from the core file. The
> REG_ADDR parameter is ignored.
>
> */
Please change this comment to only the description.
>
> static void
> fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
> CORE_ADDR reg_addr)
> {
> gdb_gregset_t gregset;
> gdb_fpregset_t fpregset;
>
> if (which == 0)
> {
> if (core_reg_size != sizeof (gregset))
> {
> warning ("wrong size gregset struct in core file");
> }
> else
> {
> memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
> supply_gregset (&gregset);
> }
> }
> else if (which == 2)
> {
> if (core_reg_size != sizeof (fpregset))
> {
> warning ("wrong size fpregset struct in core file");
> }
> else
> {
> memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
> if (FP0_REGNUM >= 0)
> supply_fpregset (&fpregset);
> }
> }
> }
If that check for FP0_REGNUM is really necessary (it is if there are
Interix sub-targets that don't include the floating point registers),
please change it to:
if (FP0_REGNUM > 0)
>
> /* the name of the proc status struct depends on the implementation */
> #ifdef HAVE_PSTATUS_T
> typedef pstatus_t gdb_prstatus_t;
> #else
> typedef prstatus_t gdb_prstatus_t;
> #endif
What's this doing here? These typedefs aren't used anywhere in this file.
> /* Figure out where the longjmp will land.
> We expect the first arg to be a pointer to the jmp_buf structure from which
> we extract the pc that we will land at. The pc is copied into PC.
> This routine returns true on success. */
>
> #include <setjmp.h>
>
> int
> get_longjmp_target (pc)
> CORE_ADDR *pc;
> {
> CORE_ADDR sp, jb_addr;
> char raw_buffer[MAX_REGISTER_RAW_SIZE];
>
> sp = read_register (SP_REGNUM);
>
> if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
> raw_buffer,
> TARGET_PTR_BIT / TARGET_CHAR_BIT))
> return 0;
>
> jb_addr = extract_address (raw_buffer, TARGET_PTR_BIT / TARGET_CHAR_BIT);
>
> if (target_read_memory(jb_addr + offsetof(_JUMP_BUFFER,Eip), raw_buffer,
> sizeof(CORE_ADDR)))
> return 0;
>
> *pc = extract_address (raw_buffer, sizeof(CORE_ADDR));
> return 1;
> }
This function does not beling in a *-nat.c file but in a *-tdep.c file.
Is there any reason why the new i386-tdep.c:i386_get_longjmp_target()
cannot be used? Just setting tdep->jb_pc_offset to the numeric value
of offsetof (_JMP_BUFFER, Eip) should work fine AFAICT.
> static struct core_fns interix_core_fns =
> {
> bfd_target_coff_flavour, /* core_flavour (more or less) */
> default_check_format, /* check_format */
> default_core_sniffer, /* core_sniffer */
> fetch_core_registers, /* core_read_registers */
> NULL /* next */
> };
>
> void
> _initialize_core_interix (void)
> {
> add_core_fns (&interix_core_fns);
> if (TARGET_LONG_BIT != 32)
> printf_unfiltered ("ERROR: TARGET_LONG_BIT = %d /= 32!\n", TARGET_LONG_BIT);
> if (TARGET_LONG_LONG_BIT != 64)
> printf_unfiltered
> ("ERROR: TARGET_LONG_LONG_BIT = %d /= 64!\n", TARGET_LONG_LONG_BIT);
> }
What is the purpose for the TARGET_LONG_BIT and TARGET_LONG_LONG_BIT
checks here?
> /* Adjust the section offsets in an objfile structure so that it's correct
> for the type of symbols being read (or undo it with the _restore
> arguments).
>
> If main programs ever start showing up at other than the default Image
> Base, this is where that would likely be applied. */
> void
> pei_adjust_objfile_offsets(struct objfile *objfile, enum objfile_adjusts type)
> {
> int i;
> CORE_ADDR symbols_offset;
>
> switch (type) {
> case adjust_for_symtab:
> symbols_offset = NONZERO_LINK_BASE(objfile->obfd);
> break;
> case adjust_for_symtab_restore:
> symbols_offset = -NONZERO_LINK_BASE(objfile->obfd);
> break;
> case adjust_for_stabs:
> case adjust_for_stabs_restore:
> case adjust_for_dwarf:
> case adjust_for_dwarf_restore:
> default:
> return;
> }
>
> for (i = 0; i < SECT_OFF_MAX; i++)
> {
> (objfile->section_offsets)->offsets[i] += symbols_offset;
> }
> }
Seems to me that this function doesn't belong in *-nat.c but in *-tdep.c.
> /* We don't have a /proc/pid/file or /proc/pid/exe to read a link from,
> so read it from the same place ps gets the name. */
>
> char *
> child_pid_to_exec_file (int pid)
> {
> char *path;
> char *buf;
> int fd, c;
> char *p;
>
> asprintf (&path, "/proc/%d/stat", pid);
> buf = xcalloc (MAXPATHLEN+1, sizeof (char));
> make_cleanup (xfree, path);
> make_cleanup (xfree, buf);
>
> fd = open (path, O_RDONLY);
>
> if (fd < 0)
> return NULL;
>
> /* Skip over "Argv0\t" */
> lseek (fd, 6, SEEK_SET);
>
> c = read (fd, buf, MAXPATHLEN);
> close (fd);
>
> if (c < 0)
> return NULL;
>
> buf[c] = '\0'; /* Ensure null termintion. */
> p = strchr(buf, '\n');
> if (p != NULL)
> *p = '\0';
>
> return buf;
> }
> --uQr8t48UFsdbeI+V
> Content-Type: text/plain; charset=us-ascii
> Content-Description: i386-interix-tdep.c
> Content-Disposition: attachment; filename="i386-interix-tdep.c"
>
> /* Native-dependent code for Interix running on i386's, for GDB.
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> 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 2 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, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
>
> #include "defs.h"
> #include "arch-utils.h"
>
> #include "frame.h"
> #include "gdb_string.h"
> #include "gdbcore.h"
> #include "gdbtypes.h"
> #include "inferior.h"
> #include "libbfd.h"
> #include "osabi.h"
>
> /* FIXME: This is not right, we should not be including this file in
> -tdep module. But this is needed by interix_back_one_frame. */
> #include <sys/procfs.h>
Yup that defenitely should be fixed before checking in this code. It
seems that this is neccessary since you use `offset (mcontext_t,
...)'. Can't you replace that by a constant, or does the value of
those expressions depend on the particular version of Interix or
Windhoos (Sorry that's the name we use for a particular OS we're not
too fond of at the company where I work; means something like
whirlwind).
> /* ??? Why do we need an extern here??? */
> extern CORE_ADDR skip_trampoline_code (CORE_ADDR pc, char *name);
Better add the prototype to i386-tdep.h.
> /* Some constants describing the i386 interix target */
> static const int i386_interix_long_bit = 32;
> static const int i386_interix_long_long_bit = 64;
> static const int i386_interix_ptr_bit = 32;
> static const CORE_ADDR i386_interix_decr_pc_after_break = 0;
What's the purpose of these constants? Apart from decr_pc_after_break
these are just the default values for the i386 target.
> /* See procfs.c and *interix*.h in config/[alpha,i386] */
> /* ??? These should be static, but this needs a bit of work before this
> can be done. */
> CORE_ADDR tramp_start;
> CORE_ADDR tramp_end;
> CORE_ADDR null_start;
> CORE_ADDR null_end;
> int winver; /* Windows NT version number */
The fact that it needs some more work, isn't a problem for me. Can be
done after this code has been checked in.
> static int
> i386_interix_pc_in_sigtramp (CORE_ADDR pc, char *name)
> {
> /* This is sufficient, where used, but is NOT a complete test; There
> is more in INIT_EXTRA_FRAME_INFO (a.k.a. interix_back_one_frame) */
> return (pc >= tramp_start && pc < tramp_end)
> || (pc >= null_start && pc < null_end);
> }
>
> static int
> i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
> {
> return skip_trampoline_code (pc, name);
> }
>
> static CORE_ADDR
> i386_interix_skip_trampoline_code (CORE_ADDR pc)
> {
> return skip_trampoline_code (pc, 0);
> }
>
> static void
> i386_interix_init_frame_pc (int fromleaf, struct frame_info *prev)
> {
> /* Nothing to do on Interix */
> }
>
> static int
> i386_interix_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
> {
> /* In the context where this is used, we get the saved PC before we've
> successfully unwound far enough to be sure what we've got (it may
> be a signal handler caller). If we're dealing with a signal
> handler caller, this will return valid, which is fine. If not,
> it'll make the correct test. */
> return thisframe->signal_handler_caller
> || (chain != 0
> && !inside_entry_file (read_memory_integer (thisframe->frame + 4,
> 4)));
> }
>
> /* We want to find the previous frame, which on Interix is tricky when signals
> are involved; set frame->frame appropriately, and also get the pc
> and tweak signal_handler_caller; this replaces a boatload of nested
> macros, as well. */
> static void
> i386_interix_back_one_frame (fromleaf, frame)
> int fromleaf;
> struct frame_info *frame;
> {
> CORE_ADDR ra;
> CORE_ADDR fm;
> CORE_ADDR context;
> long t;
>
> if (frame == NULL)
> abort();
>
> if (fromleaf)
> {
> frame->pc = SAVED_PC_AFTER_CALL (frame->next);
> return;
> }
>
> if (!frame->next)
> {
> frame->pc = read_pc();
>
> /* part of the signal stuff... see below */
> if (stopped_by_random_signal)
> {
> /* we know we're in a system call mini-frame; was it
> NullApi or something else? */
> ra = SAVED_PC_AFTER_CALL (frame);
> if (ra >= null_start && ra < null_end)
> frame->signal_handler_caller = 1;
> /* There might also be an indirect call to the mini-frame,
> putting one more return address on the stack. (XP only,
> I think?) This can't (reasonably) return the address of the
> signal handler caller unless it's that situation, so this
> is safe. */
> ra = read_memory_unsigned_integer (
> (CORE_ADDR) read_register (SP_REGNUM)+4, 4);
> if (ra >= null_start && ra < null_end)
> frame->signal_handler_caller = 1;
> }
> return;
> }
>
> if (!frame->next->signal_handler_caller)
> {
> frame->pc = (CORE_ADDR)read_memory_integer (frame->next->frame + 4, 4);
> return;
> }
>
> /* This is messy... (actually AWFUL) the "trampoline" might be 2, 3
> or all 5 entities on the frame.
>
> Chunk 1 will be present when we're actually in a signal handler.
> Chunk 2 will be present when an asynchronous signal (one that
> didn't come in with a system call) is present.
> We may not (yet) be in the handler, if we're just returning
> from the call.
> When we're actually in a handler taken from an asynchronous
> signal, both will be present.
>
> Chunk 1:
> PdxSignalDeliverer's frame
> + Context struct -- not accounted for in any frame
>
> Chunk 2:
> + PdxNullPosixApi's frame
> + PdxNullApiCaller's frame
> + Context struct = 0x230 not accounted for in any frame
>
> The symbol names come from examining objdumps of psxdll.dll;
> they don't appear in the runtime image.
>
> For gdb's purposes, we can pile all this into one frame.
> */
>
> ra = frame->next->pc;
> /* Are we already pointing at PdxNullPosixApi? We are if
> this is a signal frame, we're at next-to-top, and were stopped
> by a random signal. (If it wasn't the right address under
> these circumstances, we wouldn't be here at all by tests above
> on the prior frame.) */
> if (frame->next->next == NULL && stopped_by_random_signal)
> {
> /* We're pointing at the frame FOR PdxNullApi */
> fm = frame->frame;
> }
> else
> {
> /* No... we must be pointing at the frame that
> was called by PdxSignalDeliverer; back up across the
> whole mess */
>
> /* extract the frame for PdxSignalDeliverer; note...FRAME_CHAIN
> used the "old" frame pointer because we were a deliverer.
> Get the address of the context record that's on here frameless */
> context = read_memory_integer (frame->frame, 4); /* an Arg */
>
> /* Now extract the frame pointer contained in the context */
> fm = (CORE_ADDR)read_memory_integer
> (context + offsetof(mcontext_t, gregs.gregs[EBP]), 4);
>
> ra = (CORE_ADDR)read_memory_integer
> (context + offsetof(mcontext_t, gregs.gregs[EIP]), 4);
>
> /* We need to know if we're in a system call because we'll be
> in a syscall mini-frame, if so, and the rules are different;
> reserved[1] contains 0 if running free, 1 if blocked on a system
> call, and 2 if blocked on an exception message (e.g. a trap);
> we don't expect to get here with a 2. */
> t = (long)read_memory_integer
> (context + offsetof(mcontext_t, gregs.reserved[1]), 4);
> if (t != 1)
> {
> /* not at a system call, therefore it can't be NullApi */
> frame->pc = ra;
> frame->frame = fm;
> return;
> }
>
> /* It's a system call... mini frame, then look for NullApi */
> /* Get the RA (on the stack) associated with this... it's
> a system call mini-frame */
> ra = (CORE_ADDR)read_memory_integer
> (context + offsetof(mcontext_t, gregs.gregs[UESP]), 4);
>
> if (winver>=51) {
> /* Newer versions of Windows NT interpose another return
> address (but no other "stack frame" stuff) that we need
> to simply ignore here. */
> ra+=4;
> }
>
> ra = (CORE_ADDR)read_memory_integer(ra,4);
>
> /* We might be done (no Null API if so) */
> if (!(ra >= null_start && ra < null_end))
> {
> /* No Null API present; we're done */
> frame->pc = ra;
> frame->frame = fm;
> return;
> }
> }
> /* At this point, we're looking at the frame for PdxNullPosixApi,
> in either case.
>
> PdxNullPosixApi is called by PdxNullApiCaller (which in turn
> is called by _PdxNullApiCaller (note the _).)
> PdxNullPosixApiCaller (no _) is a frameless function.
>
> The saved frame pointer is as fm, but it's not of interest
> to us because it skips us over the saved context, which is
> the wrong thing to do, because it skips the interrrupted
> routine! PdxNullApiCaller takes as its only argument the
> address of the context of the interrupded function (which
> is really in no frame, but jammed on the stack by the system)
>
> So: fm+0: saved bp
> fm+4: return address to _PdxNullApiCaller
> fm+8: arg to PdxNullApiCaller pushed by _Pdx... */
>
> fm = (CORE_ADDR)read_memory_integer (fm+0x8, 4);
>
> /* Extract the second context record */
>
> ra = (CORE_ADDR)read_memory_integer
> (fm + offsetof(mcontext_t, gregs.gregs[EIP]), 4);
> fm = (CORE_ADDR)read_memory_integer
> (fm + offsetof(mcontext_t, gregs.gregs[EBP]), 4);
>
> frame->frame = fm;
> frame->pc = ra;
>
> return;
> }
>
> static CORE_ADDR
> i386_interix_frame_saved_pc (struct frame_info *fi)
> {
> /* Assume that we've already unwound enough to have the caller's address
> if we're dealing with a signal handler caller. (And if that fails,
> return 0.) */
> if (fi->signal_handler_caller)
> return fi->next ? fi->next->pc : 0;
> else
> return (CORE_ADDR) read_memory_integer (fi->frame + 4, 4);
> }
>
> static int
> i386_interix_use_struct_convention (int gcc_p, struct type *type)
> {
> /* Directly copied from nbsd where this function is no longer defined,
> as a generic mechanism is used. Maybe we should take advantage of
> this mechanism too? */
> return !(TYPE_LENGTH (type) == 1
> || TYPE_LENGTH (type) == 2
> || TYPE_LENGTH (type) == 4
> || TYPE_LENGTH (type) == 8);
> }
Please use the generic mechanism. Just set tdep->struct_return to
reg_struct_return.
> void
> i386_interix_cache_trampoline_addresses_from_bfd (void)
> {
> /* This is painful, but there doesn't seem to be a better way.
> See interix tm.h, IN_SIGTRAMP, and procfs.c for more details. */
> asection *section;
> pstatus_t *p;
>
> section = bfd_get_section_by_name (core_bfd, ".pstatus");
> if (section == NULL)
> {
> /* This should never happen, we are just being extra cautious. */
> warning (".pstatus section not found.");
> return;
> }
>
> p = (pstatus_t *)section->contents;
> if (p == NULL)
> {
> p = (pstatus_t *)bfd_alloc(core_bfd, section->_raw_size);
> bfd_get_section_contents (core_bfd, section, p, 0, section->_raw_size);
> }
>
> tramp_start = (CORE_ADDR)p->pr_signaldeliverer;
> tramp_end = (CORE_ADDR)p->pr_endsignaldeliverer;
> null_start = (CORE_ADDR)p->pr_nullapi;
> null_end = (CORE_ADDR)p->pr_endnullapi;
> }
>
> void
> i386_interix_cache_trampoline_addresses (CORE_ADDR trampoline_start,
> CORE_ADDR trampoline_end,
> CORE_ADDR nullapi_start,
> CORE_ADDR nullapi_end)
> {
> /* On Interix, the location of the trampoline code can
> float, and it's not part of the symbol table (because
> it's internal to a DLL). However, the system knows where
> it is, and tells us, so we capture that info here. */
> /* While we're doing such ugly things, find out which
> version of NT this is, so we can change our unwind rules
> a bit.
> FIXME: If we move this, move the include of utsname.h, too.*/
>
> tramp_start = trampoline_start;
> tramp_end = trampoline_end;
> null_start = nullapi_start;
> null_end = nullapi_end;
> }
>
> static void
> i386_interix_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> {
> /* ??? Externs, temporarily defined */
> extern int get_longjmp_target (CORE_ADDR *pc);
>
> struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>
> set_gdbarch_long_bit (gdbarch, i386_interix_long_bit);
> set_gdbarch_long_long_bit (gdbarch, i386_interix_long_long_bit);
> set_gdbarch_use_struct_convention (gdbarch,
> i386_interix_use_struct_convention);
> set_gdbarch_ptr_bit (gdbarch, i386_interix_ptr_bit);
See earlier comments.
> set_gdbarch_decr_pc_after_break (gdbarch, i386_interix_decr_pc_after_break);
Just using 0 here is fine by me. It's obvious where to look for it.
> set_gdbarch_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
> /* ??? The following may already be the default on i386 architecture */
> set_gdbarch_in_solib_call_trampoline (gdbarch,
> i386_interix_in_solib_call_trampoline);
It isn't the default on the i386 target, so removing this comment is fine.
> set_gdbarch_skip_trampoline_code (gdbarch, i386_interix_skip_trampoline_code);
> set_gdbarch_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
> set_gdbarch_init_frame_pc (gdbarch, i386_interix_init_frame_pc);
> set_gdbarch_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
> set_gdbarch_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
> /* ??? the following may already be the default for i386 architecture */
> set_gdbarch_get_longjmp_target (gdbarch, get_longjmp_target);
Yes, please use the generic mechanism as indicated by the comments in
the Interix *-nat.c file.
> }
>
> static enum gdb_osabi
> i386_interix_osabi_sniffer (bfd *abfd)
> {
> char *target_name = bfd_get_target (abfd);
>
> if (strcmp (target_name, "pei-i386") == 0)
> return GDB_OSABI_INTERIX;
>
> return GDB_OSABI_UNKNOWN;
> }
>
> void
> _initialize_i386_interix_tdep (void)
> {
> gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
> i386_interix_osabi_sniffer);
>
> gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_INTERIX,
> i386_interix_init_abi);
> }
>
>
> --uQr8t48UFsdbeI+V
> Content-Type: text/plain; charset=us-ascii
> Content-Description: config/i386/tm-i386interix.h
> Content-Disposition: attachment; filename="tm-i386interix.h"
>
> /* Macro definitions for i386 running under Interix
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> 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 2 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, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
>
> #ifndef TM_INTERIX_H
> #define TM_INTERIX_H
>
> #include "i386/tm-i386.h"
>
> /* configure can't be expected to noodle out MS's alternate spelling for
> 64-bit integers, so we'll tell it. */
> #define PRINTF_HAS_LONG_LONG 1
> #ifdef __GNUC__
> #define BFD_HOST_64_BIT long long
> #define BFD_HOST_U_64_BIT unsigned long long
> #elif defined(_MSC_VER)
> #define BFD_HOST_64_BIT __int64
> #define BFD_HOST_U_64_BIT unsigned __int64
> #else
> #error... OK what compiler is this?
> #endif
>
> #undef LONGEST
> #define LONGEST BFD_HOST_64_BIT
>
> #undef ULONGEST
> #define ULONGEST BFD_HOST_U_64_BIT
Well, then configure should be taught about it. We might tolerate
some hacks like this but not in the tm-*.h files. Put it a xm-*.h
file, but bether yet avoid it if you can: Add an appropriate configure
check for PRINTF_HAS_LONG_LONG and fix the BFD_HOST_* handling in BFD.
See the *-*-windows*) case in bfd/configure.host.
> #define I386_FLOATS_RETURN_IN_ST0
What's the purpose of this? The standard i386 target already stores
floating point return values in $st(0), and I don't see any use of
this macro in these files.
> /* Interix has a minimal sbrk() (but not what's wanted for this usage),
> and it's relationship to environ[] is not what's usually expected
> (as in, there is no specific relationship at all). Just pretend we don't
> have an sbrk(). */
> #undef HAVE_SBRK
That defenitely belongs in an xm-*.h file.
> #define ADJUST_OBJFILE_OFFSETS(objfile, type) \
> pei_adjust_objfile_offsets(objfile, type)
What's the purpose of this. This macro is used nowhere in the entire
GDB tree.
> extern CORE_ADDR bfd_getImageBase(bfd *abfd);
> #define NONZERO_LINK_BASE(abfd) bfd_getImageBase(abfd)
Eventually you'll have to find another location for these defines.
Why not put them into *-tdep.c right from the start?
> #define NAME_OF_MALLOC "_malloc"
What's this for?
>
> #endif /* TM_INTERIX_H */
The bottom line seems to be that we don't need a special tm-*.h for
Interix. Please use tm-i386.h for this new target.
> --uQr8t48UFsdbeI+V
> Content-Type: text/plain; charset=us-ascii
> Content-Description: config/i386/nm-interix.h
> Content-Disposition: attachment; filename="nm-interix.h"
>
> /* Native-dependent definitions for Intel 386 running Interix, for GDB.
> Copyright 2002 Free Software Foundation, Inc.
>
> This file is part of GDB.
>
> 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 2 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, write to the Free Software
> Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
>
> #ifndef NM_INTERIX_H
> #define NM_INTERIX_H
>
> #define USE_PROC_FS
>
> /* submodes of USE_PROC_FS */
> #define PROCFS_USE_READ_WRITE
> #define HAVE_MULTIPLE_PROC_FDS
> #define UNIXWARE
> #define HAVE_STRUCT_LWP
>
> #define ATTACH_DETACH
>
> /* Be shared lib aware */
> #include "solib.h"
>
> /* This is the amount to subtract from u.u_ar0
> to get the offset in the core file of the register values. */
>
> #if 0
> #include <machine/vmparam.h>
> #define KERNEL_U_ADDR USRSTACK
> #endif
>
> #define REGISTER_U_ADDR(addr, blockend, regno) \
> (addr) = i386_register_u_addr ((blockend),(regno));
>
> extern int
> i386_register_u_addr PARAMS ((int, int));
>
> #define PTRACE_ARG3_TYPE char*
>
> /* Return sizeof user struct to callers in less machine dependent routines */
>
> #define KERNEL_U_SIZE kernel_u_size()
> extern int kernel_u_size PARAMS ((void));
What's the purpose of all these Unix-specific defines on Interix?
> /* It's ALMOST coff; bfd does the same thing */
> #define COFF_WITH_PE
> #define COFF_IMAGE_WITH_PE
These are referenced nowhere in the entire GDB source tree.
> /* Turn on our own child_pid_to_exec_file. */
> #define CHILD_PID_TO_EXEC_FILE
>
> #endif /* NM_INTERIX_H */
>
> --uQr8t48UFsdbeI+V
> Content-Type: text/plain; charset=us-ascii
> Content-Description: config/i386/interix.mh
> Content-Disposition: attachment; filename="interix.mh"
>
> # Host: Intel 386 running Interix
> XDEPFILES=
> NATDEPFILES= corelow.o core-regset.o fork-child.o i386-interix-nat.o \
> procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
> NAT_FILE= nm-interix.h
> # The below may be temporary; mmalloc relies on sbrk() at the moment
> MMALLOC=
> MMALLOC_CFLAGS=-DNO_MMALLOC
>
> --uQr8t48UFsdbeI+V
> Content-Type: text/plain; charset=us-ascii
> Content-Description: config/i386/interix.mt
> Content-Disposition: attachment; filename="interix.mt"
>
> # Target: Intel 386 running Interix
> TDEPFILES= i386-tdep.o i387-tdep.o i386-interix-tdep.o \
> solib.o solib-pei.o i386nbsd-tdep.o
i386nbsd-tdep.o ???
> TM_FILE= tm-i386interix.h
>
> --uQr8t48UFsdbeI+V--
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [RFC] Adding new files, for new port to Interix (Services For Unix)
2002-07-24 14:34 ` Mark Kettenis
@ 2002-07-24 15:45 ` Andrew Cagney
2002-07-25 14:05 ` Joel Brobecker
2002-07-25 17:47 ` Tools to generate the ARI bug lists Joel Brobecker
0 siblings, 2 replies; 7+ messages in thread
From: Andrew Cagney @ 2002-07-24 15:45 UTC (permalink / raw)
To: Mark Kettenis, Joel Brobecker; +Cc: gdb-patches
>> I am attaching to this message some files that I'd like to add to the
>> GDB trunk. These are only new files, and some other changes are still
>> needed for GDB to first configure properly, and then build.
>>
>> My current plan regarding the inclusion of this new port is the
>> following:
>> - check-in the attached files, possibly (probably) with your comments
>> incorporated
Before any initial commit, could you please go through them with a fine
tooth comb and eliminate anything obvious. See
http://sources.redhat.com/gdb/current/ari/ for a reference. You need to
at least work through Fixed (Critical), Coding and Deprecated
(interestingly ``register'' isn't yet listed under any of those :-)
The move to commit the Ada files and have them slowly cleaned up was an
experiment. Until that experiment is finished I'm reluctant to see
other similar sized files accepted under that same loose criteria.
>> - check-in the changes in the configury machinery in order for GDB to
>> configure
>> - check-in the minimal changes to allow GDB to build
>> - And then finally check-in the remaining changes that make GDB work.
>> For the curious, my regression testsuite results show about 6600
>> passes, and 1200 failures.
Andrew
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] Adding new files, for new port to Interix (Services For Unix)
2002-07-24 15:45 ` Andrew Cagney
@ 2002-07-25 14:05 ` Joel Brobecker
2002-07-25 17:47 ` Tools to generate the ARI bug lists Joel Brobecker
1 sibling, 0 replies; 7+ messages in thread
From: Joel Brobecker @ 2002-07-25 14:05 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Mark Kettenis, gdb-patches
> Before any initial commit, could you please go through them with a fine
> tooth comb and eliminate anything obvious. See
> http://sources.redhat.com/gdb/current/ari/ for a reference. You need to
> at least work through Fixed (Critical), Coding and Deprecated
> (interestingly ``register'' isn't yet listed under any of those :-)
Will sure do.
As you have guessed, the initial port was made a while ago, and it
needs a bit of dusting. I'll make the necessary cleanup.
A Big Thank You to Mark for his careful review. His comments are very
helpful.
--
Joel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Tools to generate the ARI bug lists
2002-07-24 15:45 ` Andrew Cagney
2002-07-25 14:05 ` Joel Brobecker
@ 2002-07-25 17:47 ` Joel Brobecker
2002-07-29 9:59 ` Andrew Cagney
1 sibling, 1 reply; 7+ messages in thread
From: Joel Brobecker @ 2002-07-25 17:47 UTC (permalink / raw)
To: Andrew Cagney; +Cc: gdb-patches
> Before any initial commit, could you please go through them with a fine
> tooth comb and eliminate anything obvious. See
> http://sources.redhat.com/gdb/current/ari/ for a reference. You need to
> at least work through Fixed (Critical), Coding and Deprecated
> (interestingly ``register'' isn't yet listed under any of those :-)
Can you tell me how the list was generated? I have cleaned the few
instances of the "register" keyword, but would appreciate the assistance
of some tools to spot the other bad constructs.
Unfortunately, I can't find the tool that was used to produce the ari
bug files.
I tried to checkout the gdbadmin repository, but that failed, due to a
permission denied:
| cvs -z9 -d :pserver:anoncvs@sources.redhat.com:/cvs/gdbadmin co .
| cvs server: Updating .
| cvs server: failed to create lock directory for `/cvs/gdbadmin' (/cvs/gdbadmin/#cvs.lock): Permission denied
| cvs server: failed to obtain dir lock in repository `/cvs/gdbadmin'
| cvs [server aborted]: read lock failed - giving up
Thanks,
--
Joel
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Tools to generate the ARI bug lists
2002-07-25 17:47 ` Tools to generate the ARI bug lists Joel Brobecker
@ 2002-07-29 9:59 ` Andrew Cagney
0 siblings, 0 replies; 7+ messages in thread
From: Andrew Cagney @ 2002-07-29 9:59 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 193 bytes --]
Just FYI, the breakdown of what came from where is in:
http://sources.redhat.com/gdb/current/ari/ari.source.bug
(I only very recently added a link to this). The script is attached.
Andrew
[-- Attachment #2: update-web-ari --]
[-- Type: text/plain, Size: 60007 bytes --]
#!/bin/sh -x
# TODO: setjmp.h, setjmp and longjmp.
PATH=/bin:/usr/bin:/usr/local/bin:$HOME/bin
export PATH
# Direct stderr into stdout but still hang onto stderr (/dev/fd/3)
exec 3>&2 2>&1
ECHO ()
{
# echo "$@" | tee /dev/fd/3 1>&2
echo "$@" 1>&2
echo "$@" 1>&3
}
# Really mindless usage
if test $# -ne 4
then
echo "Usage: $0 <snapshot> <tmpdir> <destdir> <project>" 1>&2
exit 1
fi
snapshot=$1 ; shift
tmpdir=$1 ; shift
wwwdir=$1 ; shift
project=$1 ; shift
if [ ! -w ${wwwdir} -o ! -d ${wwwdir} ]
then
echo ERROR: Can not write to directory ${wwwdir} >&2
exit 2
fi
if [ ! -r ${snapshot} ]
then
echo ERROR: Can not read snapshot file 1>&2
exit 1
fi
# FILE formats
# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
# Where ``*'' is {source,warning,format,doschk}
ARI_REGRESSION=0
ARI_DEPRECATED=1
ARI_CODE=2
ARI_WARNING=3
ARI_INFO=4
ARI_FIRST=$ARI_CODE
unpack_source_p=true
delete_source_p=true
check_warning_p=false # broken
check_format_p=false # broken
check_source_p=true
check_doschk_p=true
check_werror_p=true
update_web_p=true
if awk --version 2>&1 </dev/null | grep -i gnu > /dev/null
then
AWK=awk
else
AWK=gawk
fi
# Set up a few cleanups
if ${delete_source_p}
then
trap "cd /tmp; rm -rf ${tmpdir}; exit" 0 1 2 15
fi
# unpack the tar-ball
if ${unpack_source_p}
then
/bin/rm -rf ${tmpdir}
/bin/mkdir ${tmpdir}
if [ ! -d ${tmpdir} ]
then
echo "Problem creating work directory"
exit 1
fi
cd ${tmpdir} || exit 1
echo `date`: Unpacking tar-ball ...
case ${snapshot} in
*.tar.bz2 ) bzcat ${snapshot} ;;
*.tar ) cat ${snapshot} ;;
* ) ECHO Bad file ${snapshot} ; exit 1 ;;
esac | tar xf -
fi
module=`basename ${snapshot}`
module=`basename ${module} .bz2`
module=`basename ${module} .tar`
srcdir=`echo ${tmpdir}/${module}*`
version_in=${srcdir}/gdb/version.in
if [ ! -r ${version_in} ]
then
echo ERROR: missing version file 1>&2
exit 1
fi
version=`cat ${version_in}`
# THIS HAS SUFFERED BIT ROT
if ${check_warning_p} && test -d "${srcdir}"
then
echo `date`: Parsing compiler warnings 1>&2
$AWK < ${root}/ari.compile '
BEGIN {
FS=":";
}
/^[^:]*:[0-9]*: warning:/ {
file = $1;
#sub (/^.*\//, "", file);
warning[file] += 1;
}
/^[^:]*:[0-9]*: error:/ {
file = $1;
#sub (/^.*\//, "", file);
error[file] += 1;
}
END {
for (file in warning) {
print file ":warning:" level[file]
}
for (file in error) {
print file ":error:" level[file]
}
}
' > ${root}/ari.warning.bug
fi
# THIS HAS SUFFERED BIT ROT
if ${check_format_p} && test -d "${srcdir}"
then
printf "Analizing file formatting:" 1>&2
( cd "${srcdir}/${project}" && ls | sed -n -e '/\.[hc]$/p'
) | while read f
do
printf " $f" 1>&2
lines=`( indent < "${srcdir}/${project}/${f}" | diff -e - "${srcdir}/${project}/${f}" ) 2>&1 | wc -l`
if test $lines -gt 0
then
echo ${f}:format:`echo ${lines}`
fi
done > ${wwwdir}/ari.format.bug
echo ""
fi
if ${check_source_p} && test -d "${srcdir}"
then
echo "`date`: Checking source code" 1>&2
rm -f ${wwwdir}/ari.source.*
find "${srcdir}/${project}" \
-name 'testsuite' -prune \
-o -name 'stop-gdb.c' -prune \
-o -name 'stuff.c' -prune \
-o -name '*-stub.c' -prune \
-o -name '*-share' -prune \
-o -name 'tui' -prune \
-o -name 'nlm' -prune \
-o -name 'gnu-regex.c' -prune \
-o -name 'gnu-regex.h' -prune \
-o -name '*\.tab\.c' -prune \
-o -name 'gdbserver' -prune \
-o -name '*.[hc]' -type f -print \
| $AWK > ${wwwdir}/ari.source.bug '
BEGIN {
comment_p = 0
string_p = 0
}
function fail (bug) {
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
if (fixit[bug, file] > 0) {
fixit[bug, file] -= 1
} else {
print bug ":" 1 ":" level[bug] ":" file ":" FNR
total[bug] += 1
}
}
function fix(bug, file, count) {
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
# print bug ":" -count ":" level[bug] ":" file ":" 0
fixit[bug, file] = count
}
# Load the list of files into an initially empty argument list.
# While STDIN is being parsed, ARGIND will remain zero.
ARGIND == 0 {
ARGV[ARGC++] = $0;
next;
}
# Initialize the PARSER
FNR == 1 {
file = FILENAME;
sub (/^.*\/'"${project}"'\//, "", file);
file = "'"${project}"'/" file
#printf " %s", file > "/dev/stderr";
#fflush (/dev/stderr);
}
# Skip deprecated/obsolete lines
/(^|[^_[:alnum:]])OBSOLETE([^_[:alnum:]]|$)/ { next; }
# Things in comments
BEGIN { doc["GNU/Linux"] = "\
Use either ``GNU/Linux'\'\'' or ``Linux kernel'\'\'' in comments. \
This test assumes that the word ``Linux'\'\'' appears on the same line \
as the ``GNU'\'\'' or ``kernel'\'\''."
level["GNU/Linux"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])Linux([^_[:alnum:]]|$)/ \
&& !/(^|[^_[:alnum:]])GNU\/Linux([^_[:alnum:]]|$)/ \
&& !/(^|[^_[:alnum:]])Linux kernel([^_[:alnum:]]|$)/ {
fail("GNU/Linux")
}
# SNIP - Strip out comments - SNIP
FNR == 1 { comment_p = 0; }
comment_p && /\*\// { gsub (/^([^\*]|\*+[^\/\*])*\*+\//, " "); comment_p = 0; }
comment_p { next; }
!comment_p { gsub (/\/\*([^\*]|\*+[^\/\*])*\*+\//, " "); }
!comment_p && /\/\*/ { gsub (/\/\*.*$/, " "); comment_p = 1; }
BEGIN { doc["error capital"] = "\
An error message should start with a capital letter"
level["error capital"] = '$ARI_INFO'
}
/(^[^_[:alnum:]])error([^_[:alnum:]]|$)\([[:space:]]*"[^A-Z]*[^\/]"/ {
fail("error capital")
}
BEGIN { doc["error full-stop"] = "\
An error message should not have a trailing full-stop"
level["error full-stop"] = '$ARI_REGRESSION'
}
/(^[^_[:alnum:]])error([^_[:alnum:]]|$)\([[:space:]]*"[^"]\."/ {
fail("error full-stop")
}
# Include files for which GDB has a custom version.
BEGIN { doc["assert.h"] = "\
Instead of assert.h, use gdb_assert.h";
level["assert.h"] = '$ARI_REGRESSION'
fix("assert.h", "gdb/gdb_assert.h", 0) # it does not use it
}
/^#[[:blank:]]*include[[:blank:]]+.assert\.h./ {
fail("assert.h")
}
BEGIN { doc["dirent.h"] = "\
Instead of dirent.h, use gdb_dirent.h";
level["dirent.h"] = '$ARI_REGRESSION'
fix("dirent.h", "gdb/gdb_dirent.h", 1);
}
/^#[[:blank:]]*include[[:blank:]]*.dirent\.h./ {
fail("dirent.h")
}
BEGIN { doc["proc_service.h"] = "\
Instead of proc_service.h, use gdb_proc_service.h";
level["proc_service.h"] = '$ARI_CODE'
fix("proc_service.h", "gdb/gdb_proc_service.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.proc_service\.h./ {
fail("proc_service.h")
}
BEGIN { doc["regex.h"] = "\
Instead of regex.h, use gdb_regex.h";
level["regex.h"] = '$ARI_REGRESSION'
fix("regex.h", "gdb/gdb_regex.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.regex\.h./ {
fail("regex.h")
}
BEGIN { doc["xregex.h"] = "\
Instead of xregex.h, use gdb_regex.h";
level["xregex.h"] = '$ARI_REGRESSION'
fix("xregex.h", "gdb/gdb_regex.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.xregex\.h./ {
fail("xregex.h")
}
BEGIN { doc["gnu-regex.h"] = "\
Instead of gnu-regex.h, use gdb_regex.h";
level["gnu-regex.h"] = '$ARI_REGRESSION'
}
/^#[[:blank:]]*include[[:blank:]]*.gnu-regex\.h./ {
fail("gnu regex.h")
}
BEGIN { doc["stat.h"] = "\
Instead of stat.h or sys/stat.h, use gdb_stat.h";
level["stat.h"] = '$ARI_CODE'
fix("stat.h", "gdb/gdb_stat.h", 1)
}
/^#[[:blank:]]*include[[:blank:]]*.stat\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.sys\/stat\.h./ {
fail("stat.h")
}
BEGIN { doc["string.h"] = "\
Instead of string.h, strings.h or memory.h, use gdb_string.h";
level["string.h"] = '$ARI_REGRESSION'
fix("string.h", "gdb/gdb_string.h", 4)
}
/^#[[:blank:]]*include[[:blank:]]*.string\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.strings\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.memory\.h./ {
fail("string.h")
}
BEGIN { doc["thread_db.h"] = "\
Instead of thread_db.h, use gdb_thread_db.h";
fix("thread_db.h", "gdb/gdb_thread_db.h", 1);
level["thread_db.h"] = '$ARI_CODE'
}
/^#[[:blank:]]*include[[:blank:]]*.thread_db\.h./ {
fail("thread_db.h")
}
BEGIN { doc["wait.h"] = "\
Instead of wait.h or sys/wait.h, use gdb_wait.h";
fix("wait.h", "gdb/gdb_wait.h", 2);
level["wait.h"] = '$ARI_CODE'
}
/^#[[:blank:]]*include[[:blank:]]*.wait\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.sys\/wait\.h./ {
fail("wait.h")
}
BEGIN { doc["vfork.h"] = "\
Instead of vfork.h, use gdb_vfork.h";
fix("vfork.h", "gdb/gdb_vfork.h", 1);
level["vfork.h"] = '$ARI_REGRESSION'
}
/^#[[:blank:]]*include[[:blank:]]*.vfork\.h./ {
fail("vfork.h")
}
BEGIN { doc["Xm-OS.h"] = "\
Some config/ARCH/Xm-OS.h files use #include \"Xm-OS.h\". To include the \
file \"config/Xm-OS.h\". They should use the latter path."
level["Xm-OS.h"] = '$ARI_REGRESSION'
}
/^#[[:blank:]]*include[[:blank:]]*.nm-[^\.]*\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.tm[^\.]*-\.h./ \
|| /^#[[:blank:]]*include[[:blank:]]*.xm-[^\.]*\.h./ {
fail("Xm-OS.h")
}
BEGIN { doc["error printing internal error"] = "\
Code should call the internal_error() function rather than print an \
internal-error message directly";
level["error printing internal error"] = '$ARI_WARNING'
}
/error.*\"Internal error/ || /error.*\"internal error/ {
fail("error printing internal error")
}
BEGIN { doc["%p"] = "\
Use %s and paddr() to print target addresses, not %p.";
level["%p"] = '$ARI_CODE'
}
/%p/ && !/%prec/ {
fail("%p")
}
BEGIN { doc["%ll"] = "\
Use %s and phex() et.al. to print long long values, not %ll.";
level["%ll"] = '$ARI_CODE'
}
/%ll/ {
fail("%ll")
}
# SNIP - Strip out strings - SNIP
# awk
# Test on top.c, scm-valprint.c, remote-rdi.c, ada-lang.c
FNR == 1 { string_p = 0; }
# Strip escaped characters.
{ gsub(/\\./, "."); }
# Strip quoted quotes.
{ gsub(/'\''.'\''/, "'\''.'\''"); }
# End of multi-line string
string_p && /\"/ {
# print "EOS:", $0;
gsub (/^[^\"]*\"/, "'\''");
string_p = 0;
}
# Middle of multi-line string, discard line.
string_p {
# print "MOS:", $0;
$0 = ""
}
# Strip complete strings from the middle of the line
!string_p {
# print "COS:", $0;
gsub (/\"[^\"]*\"/, "'\'\''");
}
# Start of multi-line string
!string_p && /\"/ {
# print "SOS:", $0;
gsub (/\"[^\"]*$/, "'\''");
string_p = 1;
}
# { print }
# Accumulate continuation lines
FNR == 1 { cont_p = 0; }
!cont_p { full_line = ""; }
/[^\\]\\$/ { gsub (/\\$/, ""); full_line = full_line $0; cont_p = 1; next; }
cont_p { $0 = full_line $0; cont_p = 0; full_line = ""; }
# GDB uses ISO C. Check for any non pure ISO C code
BEGIN { doc["PARAMS"] = "\
Still uses the PARAMS macro.";
level["PARAMS"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])PARAMS([^_[:alnum:]]|$)/ {
fail("PARAMS")
}
BEGIN { doc["__STDC__"] = "\
GDB assumes ISO C, testing for __STDC__ makes little sense";
level["__STDC__"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])__STDC__([^_[:alnum:]]|$)/ {
fail("__STDC__")
}
BEGIN { doc["__func__"] = "\
__func__ is a post ISO C 90 extension. EGCS 1.1.2, for instance, does not \
support it."
level["__func__"] = '$ARI_REGRESSION'
fix("__func__", "gdb/gdb_assert.h", 1)
}
/(^|[^_[:alnum:]])__func__([^_[:alnum:]]|$)/ {
fail("__func__")
}
BEGIN { doc["__FUNCTION__"] = "\
__FUNCTION__ is a post ISO C 90 extension."
level["__FUNCTION__"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])__FUNCTION__([^_[:alnum:]]|$)/ {
fail("__FUNCTION__")
}
BEGIN { doc["__CYGWIN32__"] = "\
__CYGWIN32__ has been replaced by __CYGWIN__ or, better, explicit \
autoconf tests";
level["__CYGWIN32__"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])__CYGWIN32__([^_[:alnum:]]|$)/ {
fail("__CYGWIN32__")
}
BEGIN { doc["PTR"] = "\
Use ``void *'\'\''. PTR dates back to the days before ISO C.";
level["PTR"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])PTR([^_[:alnum:]]|$)/ {
fail("PTR")
}
BEGIN { doc["//"] = "\
C++ comments - // - are not valid ISO C."
level["//"] = '$ARI_REGRESSION'
}
/\/\// {
fail("//")
}
BEGIN { doc["CONST_PTR"] = "\
Use ``const void *'\'\''. PTR dates back to the days before ISO C.";
level["CONST_PTR"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])CONST_PTR([^_[:alnum:]]|$)/ {
fail("CONST_PTR")
}
BEGIN { doc["grep ^func"] = "\
A function declaration with the function name positioned at the very start \
of a line. Only as part of the function definition should the function \
name appear at the very start of a line. This is so that \
``grep ^func'\'\'' works";
level["grep ^func"] = '$ARI_CODE'
}
{ grep_func = 0; }
/^[[:alnum:]_]+[[:blank:]]*\([[:blank:]]*[^\*].*\);[[:blank:]]*/ {
# FYI, it matches:
#NAME (...);
# when a normal declaration would have:
#TYPE NAME (...);
fail("grep ^func")
grep_func = 1;
}
BEGIN { doc["K&R defn"] = "\
Still uses an old style K&R function definition (not declaration). \
This check also trips up on incorrectly indented function declarations \
(see ``grep ^func'\'\'')."
level["K&R defn"] = '$ARI_REGRESSION'
fix("K&R defn", "gdb/ser-go32.c", 2)
}
/^[[:alnum:]_]+[[:blank:]]*\([[:alnum:]_]*[[:blank:]]*[,\)]/ && \
! /\(void\)/ && ! /\);/ && !grep_func {
fail("K&R defn")
}
BEGIN { doc["hash"] = "\
Some compilers will only corectly parse a preprocessor directive when the \
``#'\'\'' is the first character on the line. \
"
level["hash"] = '$ARI_REGRESSION'
}
/^[[:blank:]]+#/ {
fail("hash")
}
BEGIN { doc["#define JB_..."] = "\
The system header <setjmp.h> is free to define macros with the JB_ prefix.\
level["#define JB_..."] = '$ARI_CODE'
}
/^#[[:space:]]*define[[:space:]]*JB_/ {
fail("#define JB_...")
}
BEGIN { doc["make_cleanup_func"] = "\
Type casting using make_cleanup_func is invalid ISO C";
level["make_cleanup_func"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])make_cleanup_func([^_[:alnum:]]|$)/ {
fail("make_cleanup_func")
}
BEGIN { doc["catch_errors_ftype"] = "\
Type casting using catch_errors_ftype is invalid ISO C";
level["catch_errors_ftype"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])catch_errors_ftype([^_[:alnum:]]|$)/ {
fail("catch_errors_ftype")
}
BEGIN { doc["catch_errors"] = "\
Use catch_exceptions() in preference to catch_errors().";
level["catch_errors"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])catch_errors[[:space:]]*\(/ {
fail("catch_errors")
}
BEGIN { doc["strerror"] = "\
Use safe_strerror() in preference to strerror().";
level["strerror"] = '$ARI_REGRESSION'
fix("strerror", "gdb/gdb_string.h", 2)
fix("strerror", "gdb/utils.c", 1)
}
/(^|[^_[:alnum:]])strerror[[:space:]]*\(/ {
fail("strerror")
}
BEGIN { doc["long long"] = "\
Change ``long long'\'\'' to ``LONGEST'\'\''.";
level["long long"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])long[[:space:]]+long([^_[:alnum:]]|$)/ {
fail("long long")
}
BEGIN { doc["ATTRIBUTE_UNUSED"] = "\
GDB is compiled with -Werror and, consequently, is not able to tolerate \
false warnings. Since -Wunused-param produces such warnings, neither \
that warning flag nor ATTRIBUTE_UNUSED are used in GDB."
level["ATTRIBUTE_UNUSED"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])ATTRIBUTE_UNUSED([^_[:alnum:]]|$)/ {
fail("ATTRIBUTE_UNUSED")
}
# General problems
BEGIN { doc["_func"] = "\
The suffixes ..._func and ..._ftype are used inconsistently in the source. \
Perhaps just ..._ftype should be used.";
level["_func"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])[[:alpha:]_][[:alnum:]_]*_func([^_[:alnum:]]|$)/ {
fail("_func")
}
BEGIN { doc["TARGET_BYTE_ORDER_SELECTABLE"] = "\
This macro is made redundant by multi-arch."
level["TARGET_BYTE_ORDER_SELECTABLE"] = '$ARI_REGRESSION'
}
/TARGET_BYTE_ORDER_SELECTABLE/ {
fail("TARGET_BYTE_ORDER_SELECTABLE")
}
BEGIN { doc["TARGET_BYTE_ORDER_DEFAULT"] = "\
This macro is made redundant by multi-arch."
level["TARGET_BYTE_ORDER_DEFAULT"] = '$ARI_REGRESSION'
}
/TARGET_BYTE_ORDER_DEFAULT/ {
fail("TARGET_BYTE_ORDER_DEFAULT")
}
# Correct use of initialized?
BEGIN {
doc["_initialize decl"] = "\
Declaration of _initialize*() missing. The declaration stops a -Wmissing-declarations \
warning from GCC.";
level["_initialize decl"] = '$ARI_INFO'
doc["_initialize ftype"] = "\
Declaration of _initialize*() does not use initialize_file_ftype, should it?";
level["_initialize ftype"] = '$ARI_INFO'
}
# Remember what type declaration, if any, we see
FNR == 1 {
initialize_decl = 0;
initialize_ftype = 0;
}
/^extern[[:space:]]+void[[:space:]]+_initialize_[_[:alnum:]]*/ {
initialize_decl = 1
}
/^extern[[:space:]]+initialize_file_ftype[[:space:]]+_initialize_[_[:alnum:]]*/ {
initialize_ftype = 1
}
# Check it against the definition
/^_initialize_[_[:alnum:]]*[[:space:]]+/ {
if (!initialize_decl && !initialize_ftype) {
fail("_initialize decl")
}
if (!initialize_ftype) {
fail("_initialize ftype")
}
}
BEGIN { doc["inline"] = "\
Using INLINE generally suggests a micro-optimization - a better \
algorithm will likely produce greater performance improvements. \
Instead let the compiler decide if/when something needs to be \
made inline."
level["inline"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])inline([^_[:alnum:]]|$)/ {
fail("inline")
}
BEGIN { doc["register"] = "\
Let the compiler decide if something needs to be made register"
level["register"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])register([^_[:alnum:]]|$)/ {
fail("register")
}
BEGIN { doc["return_to_top_level"] = "\
return_to_top_level() is deprecated in favor of the verror(), error_stream() \
et.al.";
level["return_to_top_level"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])return_to_top_level[[:blank:]]*\(/ {
fail("return_to_top_level")
}
BEGIN { doc["error_begin"] = "\
error_begin() is deprecated in favor of verror(), error_stream() et.al.";
level["error_begin"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])error_begin[[:blank:]]*\(/ {
fail("error_begin")
}
BEGIN { doc["warning_begin"] = "\
warning_begin() is deprecated in favor of vwarning(), warning_stream() \
et.al. (see error_begin())";
level["warning_begin"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])warning_begin[[:blank:]]*\(/ {
fail("warning_begin")
}
BEGIN { doc["sizeof CORE_ADDR"] = "\
Taking the sizeof a CORE_ADDR is wrong. CORE_ADDR is at \
least as big as the target pointer, _not_ the same size. Use \
TARGET_PTR_BIT or TARGET_ADDR_BIT.";
level["sizeof CORE_ADDR"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])sizeof[[:blank:]]*\(CORE_ADDR\)/ \
|| /(^|[^_[:alnum:]])sizeof[[:blank:]]*CORE_ADDR([^_[:alnum:]]|$)/ {
fail("sizeof CORE_ADDR")
}
BEGIN { doc["REGNO"] = "\
Use the ..._REGNUM instead of the ..._REGNO name suffix";
level["REGNO"] = '$ARI_INFO'
}
/_REGNO([^_[:alnum:]]|$)/ || /_regno([^_[:alnum:]]|$)/ {
fail("REGNO")
}
BEGIN { doc["abort"] = "\
GDB should never abort - use internal_error()";
level["abort"] = '$ARI_REGRESSION'
fix("abort", "gdb/utils.c", 3)
}
/(^|[^_[:alnum:]])abort[[:blank:]]*\(/ {
fail("abort")
}
BEGIN { doc["basename"] = "\
GDB should never basename - use ``const char *lbasename(const char *)'\'\''";
level["basename"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])basename[[:blank:]]*\(/ {
fail("basename")
}
BEGIN { doc["assert"] = "\
GDB should never use assert(). Assert() calls abort() and GDB should \
not abort. Use internal_error() or gdb_assert() instead.";
level["assert"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])assert[[:blank:]]*\(/ {
fail("assert")
}
BEGIN { doc["CORE_ADDR cast"] = "\
Casting something to a CORE_ADDR is typically dangerous and non-portable. \
(The data from this pattern may be wrong)";
level["CORE_ADDR cast"] = '$ARI_WARNING'
}
/\(CORE_ADDR\)[:blank:]*[^,);]/ {
fail("CORE_ADDR cast")
}
BEGIN { doc["QUIT"] = "\
Uses QUIT which could be unsafe. Should it instead use ``if (QUIT_P ()) \
return ...;'\'\'' (which does not yet exist)."
level["QUIT"] = '$ARI_INFO'
}
/QUIT[[:blank:]]*[^;]/ {
fail("QUIT")
}
BEGIN { doc["quit_flag"] = "\
Uses ``quit_flag'\'\''. Should it instead use ``if (QUIT_P ()) ...'\'\'' \
(which does not yet exist).";
level["quit_flag"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])quit_flag([^_[:alnum:]]|$)/ {
fail("quit_flag")
}
BEGIN { doc["extern"] = "\
An ``extern'\'\'' declaration appears in a .c file";
level["extern"] = '$ARI_WARNING'
fix("extern", "gdb/ser-go32.c", 1) # extern *environ;
}
/^[[:blank:]]*extern[[:blank:]]*/ && ! /_initialize_/ && file ~ /\.c$/ {
fail("extern")
}
BEGIN { doc["#define"] = "\
Delcare an enum in preference to define a macro. ???";
level["#define"] = '$ARI_INFO'
}
/^#[[:blank:]]*define[[:blank:]]+[[:alnum:]_]+[[:blank:]]+/ {
fail("#define")
}
BEGIN { doc["#if"] = "\
Use an if statement in preference to conditionally compiled code. ???";
level["#if"] = '$ARI_INFO'
}
/^#[[:blank:]]*if/ && ! / HAVE_/ {
fail("#if")
}
BEGIN { doc["GDBTK"] = "\
#ifdef GDBTK should not be needed.";
level["GDBTK"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])GDBTK([^_[:alnum:]]|$)/ {
fail("GDBTK")
}
BEGIN { doc["TUI"] = "\
#ifdef TUI should not be needed.";
level["TUI"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])TUI([^_[:alnum:]]|$)/ {
fail("TUI")
}
BEGIN { doc["HAVE_VFORK"] = "\
#ifdef HAVE_VFORK is redundant. Include \"gdb_vfork.h\" and call vfork() \
unconditionally.";
level["HAVE_VFORK"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])HAVE_VFORK([^_[:alnum:]]|$)/ {
fail("HAVE_VFORK")
}
BEGIN { doc["DEBUG"] = "\
Nothing should depend on a macro like DEBUG"
level["DEBUG"] = '$ARI_INFO'
}
/^#[[:blank:]]*if.*DEBUG/ {
fail("DEBUG")
}
BEGIN { doc["union"] = "\
The union construct always leads to problems...";
level["union"] = '$ARI_INFO'
}
/[[:blank:]]*union[[:blank:]]*/ {
fail("union")
}
BEGIN { doc["unsafe getpkt"] = "\
Function that can call longjmp.";
level["unsafe getpkt"] = '$ARI_INFO'
}
/^[^_[:alnum:]]getpkt([^_[:alnum:]]|$)/ {
fail("unsafe getpkt")
}
BEGIN { doc["unsafe error"] = "\
Function that can can call longjmp.";
level["unsafe error"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])error[[:blank:]]*\(/ {
fail("unsafe error")
}
BEGIN { doc["readchar"] = "\
Parameterise the remote serial read/write code with the serial device \
being read.";
level["readchar"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])readchar[[:blank:]]*\(/ {
fail("readchar")
}
BEGIN { doc["sigsetmask"] = "\
sigsetmask() should be replaced by sigprocmask().";
level["sigsetmask"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])sigsetmask[[:blank:]]*\(/ {
fail("sigsetmask")
}
BEGIN { doc["bcmp"] = "\
bcmp() is deprecated in favor of the ISO C function memcmp().";
level["bcmp"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])bcmp[[:blank:]]*\(/ {
fail("bcmp")
}
BEGIN { doc["bzero"] = "\
bzero() id deprecated in favour of the ISO C function memset().";
level["bzero"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])bzero[[:blank:]]*\(/ {
fail("bzero")
}
BEGIN { doc["bcopy"] = "\
bcopy() id deprecated in favour of the ISO C functions memcpy() and \
memmove().";
level["bcopy"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])bcopy[[:blank:]]*\(/ {
fail("bcopy")
}
BEGIN { doc["atoi"] = "\
GDB needs a string to LONGEST conversion function. Something like \
string_to_core_addr() but in the style of strtol(). The latter has a habit \
of accepting dud strings."
level["atoi"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])atoi[[:blank:]]*\(/ {
fail("atoi")
}
BEGIN { doc["strtol"] = "\
GDB needs a string to LONGEST conversion function. Something like \
string_to_core_addr() but in the style of strtol(). The latter has a habit \
of accepting dud strings."
level["strtol"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])strtol[[:blank:]]*\(/ {
fail("strtol")
}
BEGIN { doc["printf"] = "\
All GDB output should use the *printf*filtered() functions.";
level["printf"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])printf[[:blank:]]*\(/ {
fail("printf")
}
BEGIN { doc["extract_floating"] = "\
extract_floating() is deprecated in favour of extract_typed_floating().";
level["extract_floating"] = '$ARI_DEPRECATED'
fix("extract_floating", "gdb/floatformat.c", 1)
}
/(^|[^_[:alnum:]])extract_floating[[:blank:]]*\(/ {
fail("extract_floating")
}
BEGIN { doc["store_floating"] = "\
store_floating() is deprecated in favour of store_typed_floating().";
level["store_floating"] = '$ARI_DEPRECATED'
fix("store_floating", "gdb/floatformat.c", 1)
}
/(^|[^_[:alnum:]])store_floating[[:blank:]]*\(/ {
fail("store_floating")
}
BEGIN { doc["floatformat_to_double"] = "\
floatformat_to_double() is deprecated in favour of \
floatformat_to_doublest().";
level["floatformat_to_double"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])floatformat_to_double[[:blank:]]*\(/ {
fail("floatformat_to_double")
}
BEGIN { doc["floatformat_from_double"] = "\
floatformat_from_double() is deprecated in favour of \
floatformat_from_doublest().";
level["floatformat_from_double"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])floatformat_from_double[[:blank:]]*\(/ {
fail("floatformat_from_double")
}
BEGIN { doc["floatformat_arm_ext"] = "\
GDB should use floatformat_arm_big or floatformat_arm_littlebyte_bigword.";
level["floatformat_arm_ext"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])floatformat_arm_ext([^_[:alnum:]]|$)/ {
fail("floatformat_arm_ext")
}
BEGIN { doc["IEEE_FLOAT"] = "\
The macro IEEE_FLOAT is no longer needed.";
level["IEEE_FLOAT"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])IEEE_FLOAT([^_[:alnum:]]|$)/ {
fail("IEEE_FLOAT")
}
BEGIN { doc["address of builtin_type"] = "\
The builtin_type* defined in \"gdbtypes.h\" are going to be changed to either \
dynamic variables or functions. Taking their address - as is often done in \
c-lang.c - will no longer be possible";
level["address of builtin_type"] = '$ARI_WARNING'
}
/\&builtin_type/ {
fail("address of builtin_type")
}
BEGIN { doc["FLOAT_INFO"] = "\
The macro FLOAT_INFO is deprecated in favour of PRINT_FLOAT_INFO.";
level["FLOAT_INFO"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])FLOAT_INFO([^_[:alnum:]]|$)/ {
fail("FLOAT_INFO")
}
BEGIN { doc["PRINT_REGISTER_HOOK"] = "\
The macro PRINT_REGISTER_HOOK is redundant. The macro DO_REGISTERS_INFO \
and a helper function can do similar."
level["PRINT_REGISTER_HOOK"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])PRINT_REGISTER_HOOK([^_[:alnum:]]|$)/ {
fail("PRINT_REGISTER_HOOK")
}
BEGIN { doc["INVALID_FLOAT"] = "\
The macro INVALID_FLOAT was just just wierd.";
level["INVALID_FLOAT"] = '$ARI_REGRESSION'
fix("INVALID_FLOAT", "gdb/vax-tdep.c", 3);
}
/(^|[^_[:alnum:]])INVALID_FLOAT([^_[:alnum:]]|$)/ {
fail("INVALID_FLOAT")
}
BEGIN { doc["HOST_BYTE_ORDER"] = "\
The macro HOST_BYTE_ORDER is not used.";
level["HOST_BYTE_ORDER"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])HOST_BYTE_ORDER([^_[:alnum:]]|$)/ {
fail("HOST_BYTE_ORDER")
}
BEGIN { doc["BIG_ENDIAN"] = "\
The macro BIG_ENDIAN is being replaced with BFD_ENDIAN_BIG.";
level["BIG_ENDIAN"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])BIG_ENDIAN([^_[:alnum:]]|$)/ {
fail("BIG_ENDIAN")
}
BEGIN { doc["LITTLE_ENDIAN"] = "\
The macro LITTLE_ENDIAN is being replaced with BFD_ENDIAN_LITTLE.";
level["LITTLE_ENDIAN"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])LITTLE_ENDIAN([^_[:alnum:]]|$)/ {
fail("LITTLE_ENDIAN")
}
BEGIN { doc["report_transfer_performance"] = "\
?????";
level["report_transfer_performance"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])report_transfer_performance([^_[:alnum:]]|$)/ {
fail("report_transfer_performance")
}
BEGIN { doc["DECR_PC_AFTER_BREAK"] = "\
I wish this would just go away. An ISA has one or more hardware registers \
that define a processors current execution point in an instruction stream. \
Sometimes those registers specify the instruction about to be executed \
and sometimes one beyond that. None of this is of interest to core-gdb. \
Instead the architecture should provide a current instruction address \
method that always returns the address of the instruction about to be \
executed (as determined from the hardware registers).";
level["DECR_PC_AFTER_BREAK"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])DECR_PC_AFTER_BREAK([^_[:alnum:]]|$)/ {
fail("DECR_PC_AFTER_BREAK")
}
BEGIN { doc["USG"] = "\
What does USG even tell us?";
level["USG"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])USG([^_[:alnum:]]|$)/ {
fail("USG")
}
BEGIN { doc["EXTRA_FRAME_INFO"] = "\
The macro EXTRA_FRAME_INFO is replaced by ``struct frame_extra_info'\'\''.";
level["EXTRA_FRAME_INFO"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])EXTRA_FRAME_INFO([^_[:alnum:]]|$)/ {
fail("EXTRA_FRAME_INFO")
}
BEGIN { doc["FRAME_FIND_SAVED_REGS"] = "\
The macro FRAME_FIND_SAVED_REGS is replaced by FRAME_INIT_SAVED_REGS.";
level["FRAME_FIND_SAVED_REGS"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])FRAME_FIND_SAVED_REGS([^_[:alnum:]]|$)/ {
fail("FRAME_FIND_SAVED_REGS")
}
BEGIN { doc["SIZEOF_FRAME_SAVED_REGS"] = "\
The macro SIZEOF_FRAME_SAVED_REGS typically should not be needed.";
level["SIZEOF_FRAME_SAVED_REGS"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])SIZEOF_FRAME_SAVED_REGS([^_[:alnum:]]|$)/ {
fail("SIZEOF_FRAME_SAVED_REGS")
}
BEGIN { doc["strsignal"] = "\
GDB should be using the ABI to convert a signal into a string.";
level["strsignal"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])strsignal[[:blank:]]*\(/ {
fail("strsignal")
}
BEGIN { doc["target_signal"] = "\
This is really badly named. It should be called something like gdb_signal \
as it is GDBs internal representation of the target signal. It gets worse \
as target_signal_to_host() is actually translating to/from the true target \
signal.";
level["target_signal"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])target_signal([^_[:alnum:]]|$)/ {
fail("target_signal")
}
# The register cache and the addition of a frame argument.
BEGIN { doc["registers []"] = "\
Too many cases of code just blatting registers[]. Use existing interfaces \
and mechanisms.";
level["registers []"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])registers([^_[:alnum:]]|$)/ && ! /->registers([^_[:alnum:]]|$)/ {
fail("registers []")
}
BEGIN { doc["register_valid []"] = "\
Too many cases of code just blatting register_valid[]. Use existing \
interfaces and mechanisms.";
level["register_valid []"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])register_valid([^_[:alnum:]]|$)/ {
fail("register_valid []")
}
BEGIN { doc["read_register_gen in target"] = "\
Target and nat code should fetch values from the cache using \
regcache_collect()."
level["read_register_gen in target"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])read_register_gen([^_[:alnum:]]|$)/ && file ~ /.*-nat\.c/ {
fail("read_register_gen in target")
}
BEGIN { doc["read_register_bytes"] = "\
The function read_register_bytes() should be avoided. Typically \
read_register_gen() can be used. There are unfortunatly still one or \
two cases where read_register_bytes() is needed that need to be fixed \
and until that is done, it is not possible to make this an error."
level["read_register_bytes"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])read_register_bytes[[:blank:]]*\(/ {
fail("read_register_bytes")
}
BEGIN { doc["write_register_bytes"] = "\
The function write_register_bytes() should be avoided. Typically \
write_register_gen() can be used. There are unfortunatly still one or \
two cases where write_register_bytes() is needed that need to be fixed \
and until that is done, it is not possible to make this an error."
level["write_register_bytes"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])write_register_bytes[[:blank:]]*\(/ {
fail("write_register_bytes")
}
BEGIN { doc["registers_fetched"] = "\
registers_fetched() is replaced by supply_register().";
level["registers_fetched"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])registers_fetched[[:blank:]]*\(/ {
fail("registers_fetched")
}
BEGIN { doc["generic_get_saved_register"] = "\
generic_get_saved_register() is replaced by \
generic_unwind_get_saved_register() (which really should be made the \
default).";
level["generic_get_saved_register"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])generic_get_saved_register[[:blank:]]*\(/ {
fail("generic_get_saved_register")
}
BEGIN { doc["deprecated"] = "\
Uses a deprecated function or macro.";
level["DEPRECATED"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])DEPRECATED_/ || \
/(^|[^_[:alnum:]])deprecated_/ {
fail("deprecated")
}
BEGIN { doc["REGISTER_NAME_ALIAS_HOOK"] = "\
REGISTER_NAME_ALIAS_HOOK() is obsolete.";
level["REGISTER_NAME_ALIAS_HOOK"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])REGISTER_NAME_ALIAS_HOOK[[:blank:]]*\(/ \
|| /(^|[^_[:alnum:]])REGISTER_NAME_ALIAS_HOOK[[:blank:]]*\(/ {
fail("REGISTER_NAME_ALIAS_HOOK")
}
BEGIN { doc["STORE_PSEUDO_REGISTER"] = "\
STORE_PSEUDO_REGISTER() is replaced with gdbarch_register_write().";
level["STORE_PSEUDO_REGISTER"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])STORE_PSEUDO_REGISTER[[:blank:]]*\(/ \
|| /(^|[^_[:alnum:]])set_gdbarch_store_pseudo_register[[:blank:]]*\(/ {
fail("STORE_PSEUDO_REGISTER")
}
BEGIN { doc["FETCH_PSEUDO_REGISTER"] = "\
FETCH_PSEUDO_REGISTER() is replaced by gdbarch_register_read().";
level["FETCH_PSEUDO_REGISTER"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])FETCH_PSEUDO_REGISTER[[:blank:]]*\(/ || \
/(^|[^_[:alnum:]])set_gdbarch_fetch_pseudo_register[[:blank:]]*\(/ {
fail("FETCH_PSEUDO_REGISTER")
}
BEGIN { doc["IS_TRAPPED_INTERNALVAR"] = "\
IS_TRAPPED_INTERNALVAR() is replaced by gdbarch_register_read().";
level["IS_TRAPPED_INTERNALVAR"] = '$ARI_DEPRECATED'
}
/(^|[^_[:alnum:]])IS_TRAPPED_INTERNALVAR[[:blank:]]*\(/ {
fail("IS_TRAPPED_INTERNALVAR")
}
BEGIN { doc["REGISTER_BYTE"] = "\
REGISTER_BYTE and its co-conspirator, registers[] should both be deleted. \
The successor, computed at run-time, should be local to regcache.c.";
level["REGISTER_BYTE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_BYTE[[:blank:]]*\(/ {
fail("REGISTER_BYTE")
}
BEGIN { doc["REGISTER_BYTES"] = "\
REGISTER_BYTES the size of the regcache can be computed at run time.";
level["REGISTER_BYTES"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_BYTES[[:blank:]]*\(/ {
fail("REGISTER_BYTES")
}
BEGIN { doc["REGISTER_VIRTUAL_TYPE"] = "\
REGISTER_VIRTUAL_TYPE() should be replaced by a single \
REGISTER_TYPE() function."
level["REGISTER_VIRTUAL_TYPE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_VIRTUAL_TYPE[[:blank:]]*\(/ {
fail("REGISTER_VIRTUAL_TYPE")
}
BEGIN { doc["REGISTER_{RAW,VIRTUAL}_SIZE"] = "\
REGISTER_{RAW,VIRTUAL}_SIZE() should be replaced by a single \
REGISTER_SIZE() function that computes the size from \
REGISTER_VIRTUAL_TYPE().";
level["REGISTER_{RAW,VIRTUAL}_SIZE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_RAW_SIZE[[:blank:]]*\(/ || \
/(^|[^_[:alnum:]])REGISTER_VIRTUAL_SIZE[[:blank:]]*\(/ {
fail("REGISTER_{RAW,VIRTUAL}_SIZE")
}
BEGIN { doc["MAX_REGISTER_{RAW,VIRTUAL}_SIZE"] = "\
MAX_REGISTER_{RAW,VIRTUAL}_SIZE can be computed at runtime from \
REGISTER_{RAW,VIRTUAL}_SIZE().";
level["MAX_REGISTER_{RAW,VIRTUAL}_SIZE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])MAX_REGISTER_RAW_SIZE([^_[:alnum:]]|$)/ || \
/(^|[^_[:alnum:]])MAX_REGISTER_VIRTUAL_SIZE([^_[:alnum:]]|$)/ {
fail("MAX_REGISTER_{RAW,VIRTUAL}_SIZE")
}
BEGIN { doc["[MAX_REGISTER_{RAW,VIRTUAL}_SIZE]"] = "\
MAX_REGISTER_{RAW,VIRTUAL}_SIZE is a function and, hence, can not be \
used to specify the size of an array.";
level["[MAX_REGISTER_{RAW,VIRTUAL}_SIZE]"] = '$ARI_CODE'
}
/\[[[:blank:]]*MAX_REGISTER_RAW_SIZE[[:blank:]]*\]/ || \
/\[[[:blank:]]*MAX_REGISTER_VIRTUAL_SIZE[[:blank:]]*\]/ {
fail("[MAX_REGISTER_{RAW,VIRTUAL}_SIZE]")
}
BEGIN { doc["DO_REGISTERS_INFO"] = "\
DO_REGISTERS_INFO() should be replaced by FRAME_REGISTERS_INFO.";
level["DO_REGISTERS_INFO"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])DO_REGISTERS_INFO[[:blank:]]*\(/ {
fail("DO_REGISTERS_INFO")
}
BEGIN { doc["REGISTER_CONVERTIBLE"] = "\
REGISTER_CONVERTIBLE() has overloaded semantics.";
level["REGISTER_CONVERTIBLE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_CONVERTIBLE[[:blank:]]*\(/ {
fail("REGISTER_CONVERTIBLE")
}
BEGIN { doc["REGISTER_CONVERT_TO_RAW"] = "\
REGISTER_CONVERT_TO_RAW() has overloaded semantics.";
level["REGISTER_CONVERT_TO_RAW"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_CONVERT_TO_RAW[[:blank:]]*\(/ {
fail("REGISTER_CONVERT_TO_RAW")
}
BEGIN { doc["REGISTER_CONVERT_TO_VIRTUAL"] = "\
REGISTER_CONVERT_TO_VIRTUAL() has overloaded semantics.";
level["REGISTER_CONVERT_TO_VIRTUAL"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])REGISTER_CONVERT_TO_VIRTUAL[[:blank:]]*\(/ {
fail("REGISTER_CONVERT_TO_VIRTUAL")
}
# The totally dreaded FP REGNUM code.
BEGIN { doc["FP_REGNUM"] = "\
FP_REGNUM() is going to be deleted.";
level["FP_REGNUM"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])FP_REGNUM[[:blank:]]*\(/ {
fail("FP_REGNUM")
}
BEGIN { doc["TARGET_WRITE_FP"] = "\
TARGET_WRITE_FP() has been deleted.";
level["TARGET_WRITE_FP"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])TARGET_WRITE_FP[[:blank:]]*\(/ {
fail("TARGET_WRITE_FP")
}
BEGIN { doc["write_fp"] = "\
write_fp() has been deleted.";
level["write_fp"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])write_fp[[:blank:]]*\(/ {
fail("write_fp")
}
BEGIN { doc["TARGET_READ_FP"] = "\
TARGET_READ_FP() might be deleted.";
level["TARGET_READ_FP"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])TARGET_READ_FP[[:blank:]]*\(/ {
fail("TARGET_READ_FP")
}
BEGIN { doc["read_fp"] = "\
read_fp() might be deleted.";
level["read_fp"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])read_fp[[:blank:]]*\(/ {
fail("read_fp")
}
# Print functions: Use versions that either check for buffer overflow
# or safely allocate a fresh buffer.
BEGIN { doc["sprintf"] = "\
sprintf() should be avoided. Use either xasprintf() or snprintf().";
level["sprintf"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])sprintf[[:blank:]]*\(/ {
fail("sprintf")
}
BEGIN { doc["vsprint"] = "\
vsprint() should be avoided. Use either xvasprint() or vsnprintf().";
level["vsprint"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])vsprint[[:blank:]]*\(/ {
fail("vsprint")
}
BEGIN { doc["asprintf"] = "\
asprintf() is deprecated in favour of xasprintf().";
level["asprintf"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])asprintf[[:blank:]]*\(/ {
fail("asprintf")
}
BEGIN { doc["vasprintf"] = "\
vasprintf() is deprecated in favour of xvasprintf().";
fix("vasprintf", "gdb/utils.c", 1)
level["vasprintf"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])vasprintf[[:blank:]]*\(/ {
fail("vasprintf")
}
# Memory allocation: malloc(): Use versions that check for NULL memory
# buffers. gdb/utils.c contains wrappers that call the underlying
# functions.
BEGIN { doc["malloc"] = "\
GDB uses xmalloc() and not malloc()";
level["malloc"] = '$ARI_REGRESSION';
fix("malloc", "gdb/utils.c", 2); # decl, use
}
/(^|[^_[:alnum:]])malloc[[:blank:]]*\(/ {
fail("malloc")
}
BEGIN { doc["calloc"] = "\
GDB uses xcalloc() and not calloc()";
level["calloc"] = '$ARI_REGRESSION';
fix("calloc", "gdb/utils.c", 1);
}
/(^|[^_[:alnum:]])calloc[[:blank:]]*\(/ {
fail("calloc")
}
BEGIN { doc["realloc"] = "\
GDB uses xrealloc() and not realloc()";
level["realloc"] = '$ARI_REGRESSION';
fix("realloc", "gdb/utils.c", 2); # decl, use
}
/(^|[^_[:alnum:]])realloc[[:blank:]]*\(/ {
fail("realloc")
}
BEGIN { doc["free"] = "\
GDB uses xfree() and not free(). xfree() can handle NULL.";
level["free"] = '$ARI_REGRESSION';
fix("free", "gdb/utils.c", 2); # decl, use
}
/(^|[^_[:alnum:]>\.])free[[:blank:]]*\(/ {
fail("free")
}
# Memory allocation: mmalloc(): Use versions that check for NULL memory
# buffers. gdb/utils.c contains wrappers that call the underlying
# functions.
BEGIN { doc["mmalloc"] = "\
GDB uses xmmalloc() and not mmalloc()";
level["mmalloc"] = '$ARI_REGRESSION'
fix("mmalloc", "gdb/utils.c", 4);
}
/(^|[^_[:alnum:]])mmalloc[[:blank:]]*\(/ {
fail("mmalloc")
}
BEGIN { doc["mcalloc"] = "\
GDB uses xmcalloc() and not mcalloc()";
level["mcalloc"] = '$ARI_REGRESSION'
fix("mcalloc", "gdb/utils.c", 2);
}
/(^|[^_[:alnum:]])mcalloc[[:blank:]]*\(/ {
fail("mcalloc")
}
BEGIN { doc["mrealloc"] = "\
GDB uses xmrealloc() and not mrealloc()";
level["mrealloc"] = '$ARI_REGRESSION'
fix("mrealloc", "gdb/utils.c", 2);
}
/(^|[^_[:alnum:]])mrealloc[[:blank:]]*\(/ {
fail("mrealloc")
}
BEGIN { doc["mfree"] = "\
GDB uses xmfree() and not mfree()";
level["mfree"] = '$ARI_REGRESSION'
fix("mfree", "gdb/utils.c", 3);
}
/(^|[^_[:alnum:]>\.])mfree[[:blank:]]*\(/ {
fail("mfree")
}
# Memory allocation: xmmalloc(): We are trying to eliminate these
# versions and just use simple xmalloc() and obstacks.
BEGIN { doc["xmmalloc"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
level["xmmalloc"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])xmmalloc[[:blank:]]*\(/ {
fail("xmmalloc")
}
BEGIN { doc["xmcalloc"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
level["xmcalloc"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])xmcalloc[[:blank:]]*\(/ {
fail("xmcalloc")
}
BEGIN { doc["xmrealloc"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
level["xmrealloc"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])xmrealloc[[:blank:]]*\(/ {
fail("xmrealloc")
}
BEGIN { doc["xmfree"] = "\
GDB is trying to elminate the [x]mmalloc() family.";
level["xmfree"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]>\.])xmfree[[:blank:]]*\(/ {
fail("xmfree")
}
# More generic memory operations
BEGIN { doc["FREEIF"] = "\
GDB uses xfree() and not FREEIF()";
level["FREEIF"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])FREEIF[[:blank:]]*\(/ {
fail("FREEIF")
}
BEGIN { doc["MALLOC_INCOMPATIBLE"] = "\
MALLOC_INCOMPATIBLE should be handled by autoconf.";
level["MALLOC_INCOMPATIBLE"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])MALLOC_INCOMPATIBLE([^_[:alnum:]]|$)/ {
fail("MALLOC_INCOMPATIBLE")
}
BEGIN { doc["strdup"] = "\
GDB uses xstrdup() and not strdup()";
level["strdup"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])strdup[[:blank:]]*\(/ {
fail("strdup")
}
BEGIN { doc["strsave"] = "\
strsave() is deprecated in favour of xstrdup() et.al.";
level["strsave"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])strsave[[:blank:]]*\(/ {
fail("strsave")
}
BEGIN { doc["savestring"] = "\
savestring() needs a rethink. Should there be a xstrldup() (???).";
level["savestring"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])savestring[[:blank:]]*\(/ {
fail("savestring")
}
BEGIN { doc["alloca"] = "\
alloca() is non-portable but its use is tolerated";
level["alloca"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])alloca[[:blank:]]*\(/ {
fail("alloca")
}
# String compare functions
BEGIN { doc["STREQ"] = "\
Use ``strcmp() == 0'\'\'' instead of STREQ()."
level["STREQ"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])STREQ[[:blank:]]*\(/ {
fail("STREQ")
}
BEGIN { doc["STRCMP"] = "\
Use ``strcmp() == 0'\'\'' instead of STRCMP()"
level["STRCMP"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])STRCMP[[:blank:]]*\(/ {
fail("STRCMP")
}
BEGIN { doc["STREQN"] = "\
Use ``strncmp() == 0'\'\'' instead of STREQN()"
level["STREQN"] = '$ARI_CODE'
}
/(^|[^_[:alnum:]])STREQN[[:blank:]]*\(/ {
fail("STREQN")
}
BEGIN { doc["strncpy"] = "\
Uses strncpy instead of strlcpy (which does not yet exist)";
level["strncpy"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])strncpy[[:blank:]]*\(/ {
fail("strncpy")
}
BEGIN { doc["!strcmp"] = "\
Use ``strcmp() == 0'\'\'' rather than ``!strcmp()'\'\''. Correctly \
understanding ``string-compare equals ...'\'\'' is easier than the \
backward logic of ``Not string-compare'\'\''.";
level["!strcmp"] = '$ARI_INFO'
}
/\![[:blank:]]*str/ {
fail("!strcmp")
}
BEGIN { doc["strnicmp"] = "\
GDB uses strncasecmp() and not strnicmp()";
level["strnicmp"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])strnicmp[[:blank:]]*\(/ {
fail("strnicmp")
}
# Boolean expressions and conditionals
BEGIN { doc["FALSE"] = "\
Definitely do not use FALSE in boolean expressions.";
level["FALSE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])FALSE([^_[:alnum:]]|$)/ {
fail("FALSE")
}
BEGIN { doc["TRUE"] = "\
Do not try to use TRUE in boolean expressions.";
level["TRUE"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])TRUE([^_[:alnum:]]|$)/ {
fail("TRUE")
}
BEGIN { doc["false"] = "\
Definitely do not use ``false'\'\'' in boolean expressions.";
level["false"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])false([^_[:alnum:]]|$)/ {
fail("false")
}
BEGIN { doc["true"] = "\
Do not try to use ``true'\'\'' in boolean expressions.";
level["true"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])true([^_[:alnum:]]|$)/ {
fail("true")
}
BEGIN { doc["if assignment"] = "\
An IF statement'\''s expression contains an assignment. The GNU coding \
standard discourages this.";
level["if assignment"] = '$ARI_WARNING'
}
/ if .* = / {
fail("if assignment")
}
# Typedefs that are either redundant or can be reduced to ``struct
# type *''.
BEGIN { doc["GDB_FILE"] = "\
GDB_FILE is deprecated in favor of ``struct ui_file'\'\''";
level["GDB_FILE"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])GDB_FILE([^_[:alnum:]]|$)/ {
fail("GDB_FILE")
}
BEGIN { doc["struct complaint"] = "\
``struct complaint'\'\'' is just nasty and over complex - hashing the \
format string would probably have done the trick";
level["struct complaint"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])struct complaint([^_[:alnum:]]|$)/ {
fail("struct complaint")
}
BEGIN { doc["serial_t"] = "\
Change serial_t to ``struct serial'\'\''.";
level["serial_t"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])serial_t([^_[:alnum:]]|$)/ {
fail("serial_t")
}
BEGIN { doc["value_ptr"] = "\
Change value_ptr to ``struct value *'\'\''.";
level["value_ptr"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])value_ptr([^_[:alnum:]]|$)/ {
fail("value_ptr")
}
BEGIN { doc["tm_print_insn"] = "\
tm_print_insn has been multi-arched.";
level["tm_print_insn"] = '$ARI_DEPRECATED'
}
/tm_print_insn[[:space:]]*=/ {
fail("tm_print_insn")
}
BEGIN { doc["goto"] = "\
Please do not use ``goto'\'\''.";
level["goto"] = '$ARI_INFO'
}
/(^|[^_[:alnum:]])goto([^_[:alnum:]]|$)/ {
fail("goto")
}
BEGIN { doc["label"] = "\
Please do not use labels.";
level["label"] = '$ARI_INFO'
}
/^[[:space:]]*[[:alpha:]_][[:alnum:]_]*[[:space:]]*:/ \
&& ! /^[[:space:]]*default[[:space:]]*:/ {
fail("label")
}
BEGIN { doc["codestream"] = "\
Several targets contain a codestream - aka instruction cache. More than anything \
is is probably caused by the broken target stack.";
level["codestream"] = '$ARI_INFO'
}
/codestream/ {
fail("codestream")
}
BEGIN { doc["wrap_"] = "\
Several targets are using a wrapper function found in wrapper.c. \
Unfortunatly, they are hard to debug and contain a bad cast."
level["wrap_"] = '$ARI_INFO'
}
/wrap_/ {
fail("wrap_")
}
BEGIN { doc["var_auto_boolean"] = "\
Use the function add_setshow_auto_boolean_cmd() instead of var_auto_boolean.";
fix("var_auto_boolean", "gdb/cli/cli-decode.c", 1)
fix("var_auto_boolean", "gdb/cli/cli-decode.h", 1)
fix("var_auto_boolean", "gdb/cli/cli-setshow.c", 2)
fix("var_auto_boolean", "gdb/command.h", 1)
level["var_auto_boolean"] = '$ARI_REGRESSION'
}
/(^|[^_[:alnum:]])var_auto_boolean([^_[:alnum:]]|$)/ {
fail("var_auto_boolean")
}
BEGIN { doc["var_boolean"] = "\
Use the function add_setshow_boolean_cmd() instead of var_boolean.";
level["var_boolean"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])var_boolean([^_[:alnum:]]|$)/ {
fail("var_boolean")
}
BEGIN { doc["add_show_from_set"] = "\
See gdb/434. \
The function add_show_from_set() is very i18n unfriendly. \
Create, and then use an equivalent add_setshow_...._cmd()."
level["add_show_from_set"] = '$ARI_WARNING'
}
/(^|[^_[:alnum:]])add_show_from_set([^_[:alnum:]]|$)/ {
fail("add_show_from_set")
}
END {
# Dump the documentation
for (bug in doc) {
if (! (bug in total)) {
total[bug] = 0
}
}
for (bug in doc) {
# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
print bug ":" total[bug] ":" level[bug] ":" doc[bug] >> "'${wwwdir}'/ari.source.doc"
}
}'
fi
if ${check_doschk_p} && test -d "${srcdir}"
then
echo "`date`: Checking for doschk" 1>&2
rm -f "${wwwdir}"/ari.doschk.*
fnchange_lst="${srcdir}"/gdb/config/djgpp/fnchange.lst
fnchange_sed="${wwwdir}"/ari.doschk.sed
# Create fnchange.sed
sed -e 's;@[^@]*@[/]*\([^ ]*\) @[^@]*@[/]*\([^ ]*\);s,\1,\2,;' \
< "${fnchange_lst}" > "${fnchange_sed}"
# Do the raw analysis
( cd "${srcdir}" && find * \
-name '*.info-[0-9]*' -prune \
-o -name tcl -prune \
-o -name itcl -prune \
-o -name tk -prune \
-o -name libgui -prune \
-o -name tix -prune \
-o -name dejagnu -prune \
-o -name expect -prune \
-o -type f -print ) | sed -f ${fnchange_sed} \
| doschk > ${wwwdir}/ari.doschk.out
# Magic to map ari.doschk.out to ari.doschk.bug goes here
$AWK < ${wwwdir}/ari.doschk.out > ${wwwdir}/ari.doschk.bug '
BEGIN {
state = 1;
invalid_dos = state++; bug[invalid_dos] = "invalid dos"; level[invalid_dos] = '$ARI_INFO';
same_dos = state++; bug[same_dos] = "DOS"; level[same_dos] = '$ARI_REGRESSION';
same_sysv = state++; bug[same_sysv] = "SysV"; level[same_sysv] = '$ARI_INFO';
long_sysv = state++; bug[long_sysv] = "long SysV"; level[long_sysv] = '$ARI_INFO';
internal = state++; bug[internal] = "internal doschk"; level[internal] = '$ARI_INFO';
state = 0;
DOCFILE = "'"${wwwdir}/ari.doschk.doc"'"
}
/^$/ { state = 0; next; }
/^The .* not valid DOS/ { state = invalid_dos; next; }
/^The .* same DOS/ { state = same_dos; next; }
/^The .* same SysV/ { state = same_sysv; next; }
/^The .* too long for SysV/ { state = long_sysv; next; }
/^The .* / { state = internal; next; }
NF == 3 { name = $1 ; file = $3 }
NF == 1 { file = $1 }
NF == 0 { next }
state == same_dos || state == same_sysv {
BUG = bug[state] " dup " name
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
print BUG ":1:" level[state] ":" file ":0"
bug_count[BUG] += 1
bug_level[BUG] = level[state]
bug_doc[BUG] = "\
The name " name " resolves to duplicate files on a " bug[state] " system. \
For DOS, this can be fixed by modifying the file fnchange.lst."
next
}
{
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
BUG = bug[state]
print BUG ":1:" level[state] ":" file ":0"
bug_count[BUG] += 1
bug_level[BUG] = level[state]
bug_doc[BUG] = "DOSCHK reports a " bug[state] " problem"
}
END {
for (BUG in bug_count) {
# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
print BUG ":" bug_count[BUG] ":" bug_level[BUG] ":" bug_doc[BUG] >> DOCFILE
}
}
'
fi
if ${check_werror_p} && test -d "${srcdir}"
then
echo "`date`: Checking Makefile.in for non- -Werror rules"
rm -f ${wwwdir}/ari.werror.*
$AWK < "${srcdir}/${project}/Makefile.in" > ${wwwdir}/ari.werror.bug '
BEGIN {
level = '$ARI_WARNING'
count = 0
}
/^[-_[:alnum:]]+\.o:/ {
file = gensub(/.o:.*/, "", 1) ".c"
}
/\$\(CC\).*\$\(INTERNAL_WARN_CFLAGS\)/ {
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
print "no -Werror:1:" level ":" file ":0"
count++
}
END {
# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
print "no -Werror:" count ":" level ":\
The file has compiler warnings and is not being compiled with -Werror" \
>> "'"${wwwdir}/ari.werror.doc"'"
}
'
fi
# print_toc LEVEL LO_LEVEL HI_LEVEL TITLE [MIN_COUNT]
# Print a table of contents containing the bugs in the range [LO_LEVEL
# .. HI_LEVEL]. If the bug has an error-count >= MIN_COUNT include a
# link into the error table and include the error in the output. If
# MIN_COUNT is less than zero, don't bother printing any links but
# still print all errors. MIN_COUNT defaults to 0/-1 depending on
# LEVEL.
print_toc ()
{
level=$1 ; shift
lo_level="$1" ; shift
hi_level="$1" ; shift
echo "<p>" >> ${newari}
echo "<h3>$1</h3>" >> ${newari} ; shift
cat >> ${newari}
if [ $# -gt 0 ]
then
min_count=$1 ; shift
elif [ $level -ge $hi_level ]
then
min_count=0
else
min_count=-1
fi
cat >> ${newari} <<EOF
<p>
<table>
<tr><th align=left>BUG</th><th>Total</th><th align=left>Description</th></tr>
EOF
# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
cat ${wwwdir}/ari.*.doc \
| sort -u \
| sort -t: +1rn -2 +0d \
| $AWK >> ${newari} '
BEGIN {
FS=":"
LO_LEVEL = '${lo_level}'
HI_LEVEL = '${hi_level}'
MIN_COUNT = '${min_count}'
}
{
# ari.*.doc: <BUG>:<COUNT>:<LEVEL>:<DOC>
bug = $1
count = $2
level = $3
doc = $4
if (level > HI_LEVEL) next
if (level < LO_LEVEL) next
if (count < MIN_COUNT) next
printf "<tr>"
printf "<th align=left valign=top><a name=\"%s\">", bug
printf "%s", gensub(/_/, " ", "g", bug)
printf "</a></th>"
printf "<td align=right valign=top>"
if (count > 0 && MIN_COUNT >= 0) {
printf "<a href=\"#%s,\">%d</a></td>", bug, count
} else {
printf "%d", count
}
printf "</td>"
printf "<td align=left valign=top>%s</td>", doc
printf "</tr>"
print ""
}'
cat >> ${newari} <<EOF
</table>
<p>
EOF
}
# Merge, generating the ARI tables.
if ${update_web_p}
then
for level in $ARI_FIRST $ARI_WARNING
do
echo "Create the ARI table (level ${level})" 1>&2
case ${level} in
$ARI_FIRST )
oldari=${wwwdir}/old.html
ari=${wwwdir}/index.html
newari=${wwwdir}/new.html
critical=$ARI_REGRESSION
;;
* )
oldari=${wwwdir}/old-ari.html
ari=${wwwdir}/ari.html
newari=${wwwdir}/new-ari.html
critical=${level}
;;
esac
rm -f ${newari} ${newari}.gz
cat <<EOF >> ${newari}
<html>
<head>
<title>A.R. Index for GDB version ${version}</title>
</head>
<body>
<center><h2>A.R. Index for GDB version ${version}<h2></center>
<!-- body, update above using ../index.sh -->
<center><h3>You can not take this seriously!</h3></center>
<center>
Also available:
<a href="../gdb/ari/">most recent branch</a>
|
<a href="../gdb/current/ari/">current</a>
|
<a href="../gdb/download/ari/">last release</a>
</center>
<center>
Last updated: `date -u`
</center>
<center>
Input files: `( cd ${wwwdir} && ls ari.*.bug ) | while read bug
do
echo "<a href=\"${bug}\">${bug}</a>"
done`
</center>
EOF
print_toc ${level} 0 ${critical} Critical 1 <<EOF
(or things that have been eliminated)
EOF
# Remember to prune the dir prefix from projects files
cat ${wwwdir}/ari.*.bug \
| sort -t: +3 \
| sed -e "s,:${project}/,:," \
| $AWK >> ${newari} '
function print_heading (where_i) {
print ""
print "<tr border=1>"
print "<th align=left>File</th>"
print "<th></th>"
print "<th align=left><em>Total</em></th>"
print "<th></th>"
for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
bug = i2bug[bug_i];
printf "<th>"
printf "<a name=\"%s,\"> </a>", bug
printf "<a href=\"#%s\">", bug
printf "%s", gensub(/_/, " ", "g", bug)
printf "</a>\n"
printf "</th>\n"
}
print "<th></th>"
print "<th align=left><em>Total</em></th>"
print "<th></th>"
print "<th align=left>File</th>"
print "</tr>"
}
function print_totals (where) {
print "<th align=left><em>Totals</em></th>"
print "<th></th>"
print "<th align=right><em>" total "</em></th>"
print "<th></th>";
for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
bug = i2bug[bug_i];
printf "<th align=right>"
printf "<a name=\"%s,%s\"> </a>", bug, where
printf "<em>"
printf "<a href=\"#%s\">%d</a>", bug, bug_total[bug]
printf "</em>";
printf "<a href=\"#%s,%s\">^</a>", bug, prev_file[bug, where]
printf "<a href=\"#%s,%s\">v</a>", bug, next_file[bug, where]
printf "</th>";
print ""
}
print "<th></th>"
print "<th align=right><em>" total "</em></th>";
print "<th></th>"
print "<th align=left><em>Totals</em></th>"
print "</tr>"
}
BEGIN {
FS = ":"
LEVEL = '${level}'
nr_file = 0;
nr_bug = 0;
# Dummy entries for first/last
i2file[0] = 0
i2file[-1] = -1
i2bug[0] = 0
i2bug[-1] = -1
}
{
# ari.*.bug: <BUG>:<COUNT>:<LEVEL>:<FILE>:<LINE>
bug = $1
count = $2
level = $3
file = $4
line = $5
# Interested in this
if (level > LEVEL) next
# Totals
if (count != 0) {
if (level < LEVEL) {
bold[bug, file] = "th"
} else {
bold[bug, file] = "td"
}
db[bug, file] += count
bug_total[bug] += count
file_total[file] += count
total += count
}
# Map file <-> index
if (! (file in file2i)) {
nr_file++;
i2file[nr_file] = file;
file2i[file] = nr_file;
};
# Map bug <-> index
if (! (bug in bug2i)) {
nr_bug++;
i2bug[nr_bug] = bug;
bug2i[bug] = nr_bug;
}
}
END {
# Construct a table of next/prev
# For all the bugs, create a cycle that goes to the prev / next file.
for (bug in bug2i) {
prev = 0
prev_file[bug, 0] = -1
next_file[bug, -1] = 0
for (file_i = 1; file_i <= nr_file; file_i++) {
file = i2file[file_i]
if ((bug, file) in db) {
prev_file[bug, file] = prev
next_file[bug, prev] = file
prev = file
}
}
prev_file[bug, -1] = prev
next_file[bug, prev] = -1
}
# For all the files, create a cycle that goes to the prev / next bug.
for (file in file2i) {
prev = 0
prev_bug[0, file] = -1
next_bug[-1, file] = 0
for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
bug = i2bug[bug_i]
if ((bug, file) in db) {
prev_bug[bug, file] = prev
next_bug[prev, bug] = bug
prev = bug
}
}
prev_bug[-1, file] = prev
next_bug[prev, file] = -1
}
print "<table border=1 cellspacing=0>"
print "<tr></tr>"
print_heading(0);
print "<tr></tr>"
print_totals(0);
print "<tr></tr>"
for (file_i = 1; file_i <= nr_file; file_i++) {
file = i2file[file_i];
print ""
print "<tr>"
print "<th align=left>" file "</th>"
print "<th></th>"
print "<th align=right>" file_total[file] "</th>"
print "<th></th>"
for (bug_i = 1; bug_i <= nr_bug; bug_i++) {
bug = i2bug[bug_i];
if ((bug, file) in db) {
printf "<td align=right>"
printf "<a name=\"%s,%s\"> </a>", bug, file
#printf "<a href=\"#%s,%s\">", bug, next_file[bug, file]
printf "<a href=\"#%s\">%d</a>", bug, db[bug, file]
printf "<a href=\"#%s,%s\">^</a>", bug, prev_file[bug, file]
printf "<a href=\"#%s,%s\">v</a>", bug, next_file[bug, file]
printf "</td>"
print ""
} else {
print "<td> </td>"
#print "<td></td>"
}
}
print "<th></th>"
print "<th align=right>" file_total[file] "</th>"
print "<th></th>"
print "<th align=left>" file "</th>"
print "</tr>"
}
print "<tr></tr>"
print_totals(-1)
print "<tr></tr>"
print_heading(-1);
print "<tr></tr>"
print ""
print "</table>"
print ""
}
'
echo "<hr>" >> ${newari}
print_toc ${level} $ARI_DEPRECATED $ARI_DEPRECATED Deprecated <<EOF
(or mechanisms that have been replaced with something better,
simpler, cleaner)
EOF
echo "<hr>" >> ${newari}
print_toc ${level} $ARI_CODE $ARI_CODE Coding <<EOF
(or things that can cause portability, readability, or coding standard
problems)
EOF
echo "<hr>" >> ${newari}
print_toc ${level} $ARI_WARNING $ARI_WARNING Warnings <<EOF
(or things that are thought to a problem and will likely either be
added to Deprecated or Coding)
EOF
echo "<hr>" >> ${newari}
print_toc ${level} $ARI_INFO $ARI_INFO Info <<EOF
(or things that, er mostly, no one is even seriously considering)
EOF
echo "<hr>" >> ${newari}
print_toc ${level} $ARI_REGRESSION $ARI_REGRESSION Fixed <<EOF
(or things that have been eliminated - unless they regressed, sigh)
EOF
cat >> ${newari} <<EOF
<!-- /body, update below using ../index.sh -->
</body>
</html>
EOF
for i in . .. ../..
do
x=${wwwdir}/${i}/index.sh
if test -x $x
then
$x ${newari}
break
fi
done
gzip -c -v -9 ${newari} > ${newari}.gz
cp ${ari} ${oldari}
cp ${ari}.gz ${oldari}.gz
cp ${newari} ${ari}
cp ${newari}.gz ${ari}.gz
done # level
fi # update_web_p
# ls -l ${wwwdir}
exit 0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] Adding new files, for new port to Interix (Services For Unix)
2002-07-24 6:07 [RFC] Adding new files, for new port to Interix (Services For Unix) Joel Brobecker
2002-07-24 14:34 ` Mark Kettenis
@ 2002-07-24 15:09 ` Andrew Cagney
1 sibling, 0 replies; 7+ messages in thread
From: Andrew Cagney @ 2002-07-24 15:09 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
Just FYI, I've sent an e-mail to RMS. It appears that there was an
Interix VS UWIN debate on the GCC mailing list and I don't see a
definitive statement attributed to RMS that resolves the issues raised.
Sigh.
Andrew
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2002-07-29 16:02 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-07-24 6:07 [RFC] Adding new files, for new port to Interix (Services For Unix) Joel Brobecker
2002-07-24 14:34 ` Mark Kettenis
2002-07-24 15:45 ` Andrew Cagney
2002-07-25 14:05 ` Joel Brobecker
2002-07-25 17:47 ` Tools to generate the ARI bug lists Joel Brobecker
2002-07-29 9:59 ` Andrew Cagney
2002-07-24 15:09 ` [RFC] Adding new files, for new port to Interix (Services For Unix) Andrew Cagney
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox