You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(32) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
1
(44) |
2
(9) |
3
(30) |
4
(28) |
5
(42) |
6
(14) |
7
(10) |
|
8
(7) |
9
(8) |
10
(6) |
11
(15) |
12
(13) |
13
(14) |
14
(23) |
|
15
(17) |
16
(10) |
17
(82) |
18
(14) |
19
(21) |
20
(14) |
21
(21) |
|
22
(7) |
23
(13) |
24
(16) |
25
(11) |
26
(11) |
27
(6) |
28
(7) |
|
29
(8) |
30
(13) |
31
(8) |
|
|
|
|
|
From: <sv...@va...> - 2006-10-17 01:41:20
|
Author: sewardj
Date: 2006-10-17 02:41:17 +0100 (Tue, 17 Oct 2006)
New Revision: 6271
Log:
Merge r6134:
Accumulate statistics about the number of searches in the errors and
suppressions lists, and rearrange the suppressions list when searching
to reduce cost of future searches.
Modified:
trunk/coregrind/m_errormgr.c
Modified: trunk/coregrind/m_errormgr.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_errormgr.c 2006-10-17 01:40:33 UTC (rev 6270)
+++ trunk/coregrind/m_errormgr.c 2006-10-17 01:41:17 UTC (rev 6271)
@@ -68,7 +68,8 @@
static Error* errors =3D NULL;
=20
/* The list of suppression directives, as read from the specified
- suppressions file. */
+ suppressions file. Note that the list gets rearranged as a result
+ of the searches done by is_suppressible_error(). */
static Supp* suppressions =3D NULL;
=20
/* Running count of unsuppressed errors detected. */
@@ -82,6 +83,20 @@
=20
static ThreadId last_tid_printed =3D 1;
=20
+/* Stats: number of searches of the error list initiated. */
+static UWord em_errlist_searches =3D 0;
+
+/* Stats: number of comparisons done during error list
+ searching. */
+static UWord em_errlist_cmps =3D 0;
+
+/* Stats: number of searches of the suppression list initiated. */
+static UWord em_supplist_searches =3D 0;
+
+/* Stats: number of comparisons done during suppression list
+ searching. */
+static UWord em_supplist_cmps =3D 0;
+
/*------------------------------------------------------------*/
/*--- Error type ---*/
/*------------------------------------------------------------*/
@@ -532,9 +547,11 @@
construct_error ( &err, tid, ekind, a, s, extra, NULL );
=20
/* First, see if we've got an error record matching this one. */
- p =3D errors;
- p_prev =3D NULL;
+ em_errlist_searches++;
+ p =3D errors;
+ p_prev =3D NULL;
while (p !=3D NULL) {
+ em_errlist_cmps++;
if (eq_Error(exe_res, p, &err)) {
/* Found it. */
p->count++;
@@ -692,7 +709,7 @@
" </pair>",=20
su->count, su->sname);
} else {
- VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname)=
;
+ VG_(message)(Vg_DebugMsg, "supp: %6d %s", su->count, su->sname)=
;
}
}
=20
@@ -818,6 +835,34 @@
/*--- Standard suppressions ---*/
/*------------------------------------------------------------*/
=20
+/* Get the next char from fd into *out_buf. Returns 1 if success,
+ 0 if eof or < 0 if error. */
+
+static Int get_char ( Int fd, Char* out_buf )
+{
+ Int r;
+ static Char buf[64];
+ static Int buf_size =3D 0;
+ static Int buf_used =3D 0;
+ vg_assert(buf_size >=3D 0 && buf_size <=3D 64);
+ vg_assert(buf_used >=3D 0 && buf_used <=3D buf_size);
+ if (buf_used =3D=3D buf_size) {
+ r =3D VG_(read)(fd, buf, 64);
+ if (r < 0) return r; /* read failed */
+ vg_assert(r >=3D 0 && r <=3D 64);
+ buf_size =3D r;
+ buf_used =3D 0;
+ }
+ if (buf_size =3D=3D 0)
+ return 0; /* eof */
+ vg_assert(buf_size >=3D 0 && buf_size <=3D 64);
+ vg_assert(buf_used >=3D 0 && buf_used < buf_size);
+ *out_buf =3D buf[buf_used];
+ buf_used++;
+ return 1;
+}
+
+
/* Get a non-blank, non-comment line of at most nBuf chars from fd.
Skips leading spaces on the line. Return True if EOF was hit instead.=
=20
*/
@@ -828,17 +873,17 @@
while (True) {
/* First, read until a non-blank char appears. */
while (True) {
- n =3D VG_(read)(fd, &ch, 1);
+ n =3D get_char(fd, &ch);
if (n =3D=3D 1 && !VG_(isspace)(ch)) break;
- if (n =3D=3D 0) return True;
+ if (n <=3D 0) return True;
}
=20
/* Now, read the line into buf. */
i =3D 0;
buf[i++] =3D ch; buf[i] =3D 0;
while (True) {
- n =3D VG_(read)(fd, &ch, 1);
- if (n =3D=3D 0) return False; /* the next call will return True=
*/
+ n =3D get_char(fd, &ch);
+ if (n <=3D 0) return False; /* the next call will return True *=
/
if (ch =3D=3D '\n') break;
if (i > 0 && i =3D=3D nBuf-1) i--;
buf[i++] =3D ch; buf[i] =3D 0;
@@ -920,7 +965,7 @@
filename );
VG_(exit)(1);
}
- fd =3D sres.val;
+ fd =3D sres.res;
=20
# define BOMB(S) { err_str =3D S; goto syntax_error; }
=20
@@ -1137,18 +1182,45 @@
static Supp* is_suppressible_error ( Error* err )
{
Supp* su;
+ Supp* su_prev;
=20
+ /* stats gathering */
+ em_supplist_searches++;
+
/* See if the error context matches any suppression. */
+ su_prev =3D NULL;
for (su =3D suppressions; su !=3D NULL; su =3D su->next) {
- if (supp_matches_error(su, err) &&
- supp_matches_callers(err, su))
- {
+ em_supplist_cmps++;
+ if (supp_matches_error(su, err) && supp_matches_callers(err, su)) =
{
+ /* got a match. Move this entry to the head of the list
+ in the hope of making future searches cheaper. */
+ if (su_prev) {
+ vg_assert(su_prev->next =3D=3D su);
+ su_prev->next =3D su->next;
+ su->next =3D suppressions;
+ suppressions =3D su;
+ }
return su;
}
+ su_prev =3D su;
}
return NULL; /* no matches */
}
=20
+/* Show accumulated error-list and suppression-list search stats.=20
+*/
+void VG_(print_errormgr_stats) ( void )
+{
+ VG_(message)(Vg_DebugMsg,=20
+ " errormgr: %,lu supplist searches, %,lu comparisons during search=
",
+ em_supplist_searches, em_supplist_cmps
+ );
+ VG_(message)(Vg_DebugMsg,=20
+ " errormgr: %,lu errlist searches, %,lu comparisons during search"=
,
+ em_errlist_searches, em_errlist_cmps
+ );
+}
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
|
|
From: <sv...@va...> - 2006-10-17 01:40:35
|
Author: sewardj
Date: 2006-10-17 02:40:33 +0100 (Tue, 17 Oct 2006)
New Revision: 6270
Log:
Merge r6133:
Inline stackPush and stackPop and placate gcc's resulting concerns
about uninitialised variables.
and also change ownership.
Modified:
trunk/coregrind/m_oset.c
trunk/coregrind/pub_core_oset.h
trunk/include/pub_tool_oset.h
Modified: trunk/coregrind/m_oset.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_oset.c 2006-10-17 01:39:30 UTC (rev 6269)
+++ trunk/coregrind/m_oset.c 2006-10-17 01:40:33 UTC (rev 6270)
@@ -7,7 +7,7 @@
This file is part of Valgrind, a dynamic binary instrumentation
framework.
=20
- Copyright (C) 2005 Nicholas Nethercote
+ Copyright (C) 2005-2006 Nicholas Nethercote
nj...@va...
=20
This program is free software; you can redistribute it and/or
@@ -236,7 +236,7 @@
}
=20
// Push onto the iterator stack.
-static void stackPush(AvlTree* t, AvlNode* n, Int i)
+static inline void stackPush(AvlTree* t, AvlNode* n, Int i)
{
vg_assert(t->stackTop < STACK_MAX);
vg_assert(1 <=3D i && i <=3D 3);
@@ -246,7 +246,7 @@
}
=20
// Pop from the iterator stack.
-static Bool stackPop(AvlTree* t, AvlNode** n, Int* i)
+static inline Bool stackPop(AvlTree* t, AvlNode** n, Int* i)
{
vg_assert(t->stackTop <=3D STACK_MAX);
=20
@@ -296,8 +296,8 @@
// Destructor, frees up all memory held by remaining nodes.
void VG_(OSet_Destroy)(AvlTree* t, OSetNodeDestroy_t destroyNode)
{
- AvlNode* n;
- Int i, sz =3D 0;
+ AvlNode* n =3D NULL;
+ Int i =3D 0, sz =3D 0;
=20
vg_assert(t);
stackClear(t);
@@ -682,8 +682,8 @@
=20
void* VG_(OSet_Next)(AvlTree* t)
{
- Int i;
- OSetNode* n;
+ Int i =3D 0;
+ OSetNode* n =3D NULL;
=20
vg_assert(t);
=20
Modified: trunk/coregrind/pub_core_oset.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_oset.h 2006-10-17 01:39:30 UTC (rev 6269)
+++ trunk/coregrind/pub_core_oset.h 2006-10-17 01:40:33 UTC (rev 6270)
@@ -1,14 +1,14 @@
=20
/*--------------------------------------------------------------------*/
-/*--- An ordered set implemenation. pub_core_oset.h ---*/
+/*--- An ordered set implementation. pub_core_oset.h ---*/
/*--------------------------------------------------------------------*/
=20
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
=20
- Copyright (C) 2000-2006 Julian Seward
- js...@ac...
+ Copyright (C) 2005-2006 Nicholas Nethercote
+ nj...@va...
=20
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
Modified: trunk/include/pub_tool_oset.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_oset.h 2006-10-17 01:39:30 UTC (rev 6269)
+++ trunk/include/pub_tool_oset.h 2006-10-17 01:40:33 UTC (rev 6270)
@@ -7,8 +7,8 @@
This file is part of Valgrind, a dynamic binary instrumentation
framework.
=20
- Copyright (C) 2000-2006 Julian Seward
- js...@ac...
+ Copyright (C) 2005-2006 Nicholas Nethercote
+ nj...@va...
=20
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
|
|
From: <sv...@va...> - 2006-10-17 01:39:35
|
Author: sewardj
Date: 2006-10-17 02:39:30 +0100 (Tue, 17 Oct 2006)
New Revision: 6269
Log:
Merge r6132:
Minor changes for redirection on AIX. The only significant change is
that it now checks for, warns about and disallows, attempts to
redirect to, or wrap with, a function for which no TOC pointer can be
found, since that would be really asking for trouble (a segfault).
Modified:
trunk/coregrind/m_redir.c
trunk/include/pub_tool_redir.h
Modified: trunk/coregrind/m_redir.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_redir.c 2006-10-17 01:38:48 UTC (rev 6268)
+++ trunk/coregrind/m_redir.c 2006-10-17 01:39:30 UTC (rev 6269)
@@ -43,7 +43,7 @@
#include "pub_core_trampoline.h"
#include "pub_core_transtab.h"
#include "pub_core_tooliface.h" // VG_(needs).malloc_replacement
-#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry)
+#include "pub_core_machine.h" // VG_(fnptr_to_fnentry)
#include "pub_core_aspacemgr.h" // VG_(am_find_nsegment)
#include "pub_core_clientstate.h" // VG_(client___libc_freeres_wrapper)
#include "pub_core_demangle.h" // VG_(maybe_Z_demangle)
@@ -269,6 +269,7 @@
static void symtab_free(void*);
static HChar* symtab_strdup(HChar*);
static Bool is_plausible_guest_addr(Addr);
+static Bool is_aix5_glink_idiom(Addr);
=20
static void show_redir_state ( HChar* who );
static void show_active ( HChar* left, Active* act );
@@ -300,19 +301,23 @@
=20
void VG_(redir_notify_new_SegInfo)( SegInfo* newsi )
{
- Bool ok, isWrap;
- Int i, nsyms;
- Spec* specList;
- Spec* spec;
- TopSpec* ts;
- TopSpec* newts;
- HChar* sym_name;
- Addr sym_addr;
- HChar demangled_sopatt[N_DEMANGLED];
- HChar demangled_fnpatt[N_DEMANGLED];
-
+ Bool ok, isWrap;
+ Int i, nsyms;
+ Spec* specList;
+ Spec* spec;
+ TopSpec* ts;
+ TopSpec* newts;
+ HChar* sym_name;
+ Addr sym_addr, sym_toc;
+ HChar demangled_sopatt[N_DEMANGLED];
+ HChar demangled_fnpatt[N_DEMANGLED];
+ Bool check_ppcTOCs =3D False;
const UChar* newsi_soname;
=20
+# if defined(VG_PLAT_USES_PPCTOC)
+ check_ppcTOCs =3D True;
+# endif
+
vg_assert(newsi);
newsi_soname =3D VG_(seginfo_soname)(newsi);
vg_assert(newsi_soname !=3D NULL);
@@ -328,15 +333,23 @@
=20
nsyms =3D VG_(seginfo_syms_howmany)( newsi );
for (i =3D 0; i < nsyms; i++) {
- VG_(seginfo_syms_getidx)( newsi, i, &sym_addr, NULL, &sym_name );
+ VG_(seginfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,=20
+ NULL, &sym_name );
ok =3D VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEMANG=
LED,
- demangled_fnpatt, N_DEMANGLED, &isWrap );
+ demangled_fnpatt, N_DEMANGLED, &isWrap=
);
if (!ok) {
/* It's not a full-scale redirect, but perhaps it is a load-not=
ify
fn? Let the load-notify department see it. */
handle_maybe_load_notifier( newsi_soname, sym_name, sym_addr );
continue;=20
}
+ if (check_ppcTOCs && sym_toc =3D=3D 0) {
+ /* This platform uses toc pointers, but none could be found
+ for this symbol, so we can't safely redirect/wrap to it.
+ Just skip it; we'll make a second pass over the symbols in
+ the following loop, and complain at that point. */
+ continue;
+ }
spec =3D symtab_alloc(sizeof(Spec));
vg_assert(spec);
spec->from_sopatt =3D symtab_strdup(demangled_sopatt);
@@ -352,6 +365,35 @@
specList =3D spec;
}
=20
+ if (check_ppcTOCs) {
+ for (i =3D 0; i < nsyms; i++) {
+ VG_(seginfo_syms_getidx)( newsi, i, &sym_addr, &sym_toc,=20
+ NULL, &sym_name );
+ ok =3D VG_(maybe_Z_demangle)( sym_name, demangled_sopatt, N_DEM=
ANGLED,
+ demangled_fnpatt, N_DEMANGLED, &isW=
rap );
+ if (!ok)
+ /* not a redirect. Ignore. */
+ continue;
+ if (sym_toc !=3D 0)
+ /* has a valid toc pointer. Ignore. */
+ continue;
+
+ for (spec =3D specList; spec; spec =3D spec->next)=20
+ if (0 =3D=3D VG_(strcmp)(spec->from_sopatt, demangled_sopatt=
)
+ && 0 =3D=3D VG_(strcmp)(spec->from_fnpatt, demangled_fnp=
att))
+ break;
+ if (spec)
+ /* a redirect to some other copy of that symbol, which does have
+ a TOC value, already exists */
+ continue;
+
+ /* Complain */
+ VG_(message)(Vg_DebugMsg,
+ "WARNING: no TOC ptr for redir/wrap to %s %s",
+ demangled_sopatt, demangled_fnpatt);
+ }
+ }
+
/* Ok. Now specList holds the list of specs from the SegInfo.=20
Build a new TopSpec, but don't add it to topSpecs yet. */
newts =3D symtab_alloc(sizeof(TopSpec));
@@ -384,7 +426,7 @@
generate_and_add_actives( specList, newts,
ts->seginfo, ts );
}
-=09
+
/* Case (2) */
for (ts =3D topSpecs; ts; ts =3D ts->next) {
generate_and_add_actives( ts->specs, ts,=20
@@ -445,7 +487,18 @@
of trashing the caches less. */
nsyms =3D VG_(seginfo_syms_howmany)( si );
for (i =3D 0; i < nsyms; i++) {
- VG_(seginfo_syms_getidx)( si, i, &sym_addr, NULL, &sym_name );
+ VG_(seginfo_syms_getidx)( si, i, &sym_addr, NULL, NULL, &sym_name =
);
+
+ /* On AIX, we cannot redirect calls to a so-called glink
+ function for reasons which are not obvious - something to do
+ with saving r2 across the call. Not a problem, as we don't
+ want to anyway; presumably it is the target of the glink we
+ need to redirect. Hence just spot them and ignore them.
+ They are always of a very specific (more or less
+ ABI-mandated) form. */
+ if (is_aix5_glink_idiom(sym_addr))
+ continue;
+
for (sp =3D specs; sp; sp =3D sp->next) {
if (!sp->mark)
continue; /* soname doesn't match */
@@ -785,6 +838,12 @@
=20
}
=20
+# elif defined(VGP_ppc32_aix5)
+ /* nothing so far */
+
+# elif defined(VGP_ppc64_aix5)
+ /* nothing so far */
+
# else
# error Unknown platform
# endif
@@ -817,12 +876,48 @@
in m_translate. */
static Bool is_plausible_guest_addr(Addr a)
{
- NSegment* seg =3D VG_(am_find_nsegment)(a);
+ NSegment const* seg =3D VG_(am_find_nsegment)(a);
return seg !=3D NULL
&& (seg->kind =3D=3D SkAnonC || seg->kind =3D=3D SkFileC)
&& (seg->hasX || seg->hasR); /* crude x86-specific hack */
}
=20
+/* A function which spots AIX 'glink' functions. A 'glink' function
+ is a stub function which has something to do with AIX-style dynamic
+ linking, and jumps to the real target (with which it typically
+ shares the same name). See also comment where this function is
+ used (above). */
+static Bool is_aix5_glink_idiom ( Addr sym_addr )
+{
+# if defined(VGP_ppc32_aix5)
+ UInt* w =3D (UInt*)sym_addr;
+ if (VG_IS_4_ALIGNED(w)
+ && is_plausible_guest_addr((Addr)(w+0))
+ && is_plausible_guest_addr((Addr)(w+6))
+ && (w[0] & 0xFFFF0000) =3D=3D 0x81820000 /* lwz r12,func@toc(r2) =
*/
+ && w[1] =3D=3D 0x90410014 /* stw r2,20(r1) */
+ && w[2] =3D=3D 0x800c0000 /* lwz r0,0(r12) */
+ && w[3] =3D=3D 0x804c0004 /* lwz r2,4(r12) */
+ && w[4] =3D=3D 0x7c0903a6 /* mtctr r0 */
+ && w[5] =3D=3D 0x4e800420 /* bctr */
+ && w[6] =3D=3D 0x00000000 /* illegal */)
+ return True;
+# elif defined(VGP_ppc64_aix5)
+ UInt* w =3D (UInt*)sym_addr;
+ if (VG_IS_4_ALIGNED(w)
+ && is_plausible_guest_addr((Addr)(w+0))
+ && is_plausible_guest_addr((Addr)(w+6))
+ && (w[0] & 0xFFFF0000) =3D=3D 0xE9820000 /* ld r12,func@toc(r2) =
*/
+ && w[1] =3D=3D 0xF8410028 /* std r2,40(r1) */
+ && w[2] =3D=3D 0xE80C0000 /* ld r0,0(r12) */
+ && w[3] =3D=3D 0xE84C0008 /* ld r2,8(r12) */
+ && w[4] =3D=3D 0x7c0903a6 /* mtctr r0 */
+ && w[5] =3D=3D 0x4e800420 /* bctr */
+ && w[6] =3D=3D 0x00000000 /* illegal */)
+ return True;
+# endif
+ return False;
+}
=20
/*------------------------------------------------------------*/
/*--- NOTIFY-ON-LOAD FUNCTIONS ---*/
@@ -866,7 +961,7 @@
static void show_spec ( HChar* left, Spec* spec )
{
VG_(message)(Vg_DebugMsg,=20
- "%s%18s %30s %s-> 0x%08llx",
+ "%s%25s %30s %s-> 0x%08llx",
left,
spec->from_sopatt, spec->from_fnpatt,
spec->isWrap ? "W" : "R",
@@ -884,7 +979,7 @@
ok =3D VG_(get_fnname_w_offset)(act->to_addr, name2, 64);
if (!ok) VG_(strcpy)(name2, "???");
=20
- VG_(message)(Vg_DebugMsg, "%s0x%08llx (%10s) %s-> 0x%08llx %s",=20
+ VG_(message)(Vg_DebugMsg, "%s0x%08llx (%20s) %s-> 0x%08llx %s",=20
left,=20
(ULong)act->from_addr, name1,
act->isWrap ? "W" : "R",
Modified: trunk/include/pub_tool_redir.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_redir.h 2006-10-17 01:38:48 UTC (rev 6268)
+++ trunk/include/pub_tool_redir.h 2006-10-17 01:39:30 UTC (rev 6269)
@@ -136,8 +136,10 @@
_ --> Zu (underscore)
- --> Zh (hyphen)
(space) --> Zs (space)
- @ -> ZA (at)
+ @ --> ZA (at)
Z --> ZZ (Z)
+ ( --> ZL (left)
+ ) --> ZR (right)
=20
Everything else is left unchanged.
*/
@@ -146,12 +148,17 @@
changed accordingly. NOTE: duplicates
I_{WRAP,REPLACE}_SONAME_FNNAME_Z{U,Z} in valgrind.h. */
=20
-#define VG_REPLACE_FUNCTION_ZU(soname,fnname) _vgrZU_##soname##_##fnname
-#define VG_REPLACE_FUNCTION_ZZ(soname,fnname) _vgrZZ_##soname##_##fnname
+/* Use an extra level of macroisation so as to ensure the soname/fnname
+ args are fully macro-expanded before pasting them together. */
+#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
=20
-#define VG_WRAP_FUNCTION_ZU(soname,fnname) _vgwZU_##soname##_##fnname
-#define VG_WRAP_FUNCTION_ZZ(soname,fnname) _vgwZZ_##soname##_##fnname
+#define VG_REPLACE_FUNCTION_ZU(soname,fnname) VG_CONCAT4(_vgrZU_,soname,=
_,fnname)
+#define VG_REPLACE_FUNCTION_ZZ(soname,fnname) VG_CONCAT4(_vgrZZ_,soname,=
_,fnname)
=20
+#define VG_WRAP_FUNCTION_ZU(soname,fnname) VG_CONCAT4(_vgwZU_,soname,_,f=
nname)
+#define VG_WRAP_FUNCTION_ZZ(soname,fnname) VG_CONCAT4(_vgwZZ_,soname,_,f=
nname)
+
+
#endif // __PUB_TOOL_REDIR_H
=20
/*--------------------------------------------------------------------*/
|
|
From: <sv...@va...> - 2006-10-17 01:38:54
|
Author: sewardj
Date: 2006-10-17 02:38:48 +0100 (Tue, 17 Oct 2006)
New Revision: 6268
Log:
Merge r6131:
Change the SysRes type so as to represent both the error value and the
non-error result at the same time.
Modified:
trunk/include/pub_tool_basics.h
Modified: trunk/include/pub_tool_basics.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_basics.h 2006-10-17 01:38:13 UTC (rev 6267)
+++ trunk/include/pub_tool_basics.h 2006-10-17 01:38:48 UTC (rev 6268)
@@ -80,6 +80,7 @@
# define NULL ((void*)0)
#endif
=20
+
/* ---------------------------------------------------------------------
non-builtin types
------------------------------------------------------------------ */
@@ -91,15 +92,35 @@
typedef UInt ThreadId;
=20
/* An abstraction of syscall return values.
- When .isError =3D=3D False, val holds the return value.
- When .isError =3D=3D True, val holds the error code.
+ Linux:
+ When .isError =3D=3D False,=20
+ res holds the return value, and err is zero.
+ When .isError =3D=3D True, =20
+ err holds the error code, and res is zero.
+
+ AIX:
+ res is the POSIX result of the syscall.
+ err is the corresponding errno value.
+ isError =3D=3D=3D err=3D=3D0
+
+ Unlike on Linux, it is possible for 'err' to be nonzero (thus an
+ error has occurred), nevertheless 'res' is also nonzero. AIX
+ userspace does not appear to consistently inspect 'err' to
+ determine whether or not an error has occurred. For example,
+ sys_open() will return -1 for 'val' if a file cannot be opened,
+ as well as the relevant errno value in 'err', but AIX userspace
+ then consults 'val' to figure out if the syscall failed, rather
+ than looking at 'err'. Hence we need to represent them both.
*/
-typedef struct {=20
- UWord val;
- Bool isError;
-}
-SysRes;
+typedef
+ struct {
+ UWord res;
+ UWord err;
+ Bool isError;
+ }
+ SysRes;
=20
+
/* ---------------------------------------------------------------------
Miscellaneous (word size, endianness, regparmness, stringification)
------------------------------------------------------------------ */
|
|
From: <sv...@va...> - 2006-10-17 01:38:16
|
Author: sewardj
Date: 2006-10-17 02:38:13 +0100 (Tue, 17 Oct 2006)
New Revision: 6267
Log:
Merge r6130:
- AIX implementations of various stuff, nothing surprising.
- For all platforms: make VG_(read) and VG_(write) return (negative)
actual error values rather than producing -1 for all failures.
Modified:
trunk/coregrind/m_libcfile.c
trunk/coregrind/pub_core_libcfile.h
trunk/include/pub_tool_libcfile.h
Modified: trunk/coregrind/m_libcfile.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_libcfile.c 2006-10-17 01:37:10 UTC (rev 6266)
+++ trunk/coregrind/m_libcfile.c 2006-10-17 01:38:13 UTC (rev 6267)
@@ -30,6 +30,7 @@
=20
#include "pub_core_basics.h"
#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
#include "pub_core_libcfile.h"
@@ -37,7 +38,6 @@
#include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
#include "pub_core_clientstate.h" // VG_(fd_hard_limit)
#include "pub_core_syscall.h"
-#include "pub_core_vkiscnums.h"
=20
/* ---------------------------------------------------------------------
File stuff
@@ -61,6 +61,7 @@
if (newfd !=3D -1)
VG_(close)(oldfd);
=20
+ /* Set the close-on-exec flag for this fd. */
VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
=20
vg_assert(newfd >=3D VG_(fd_hard_limit));
@@ -96,14 +97,30 @@
=20
Int VG_(read) ( Int fd, void* buf, Int count)
{
+ Int ret;
SysRes res =3D VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
- return res.isError ? -1 : res.val;
+ if (res.isError) {
+ ret =3D - (Int)(Word)res.err;
+ vg_assert(ret < 0);
+ } else {
+ ret =3D (Int)(Word)res.res;
+ vg_assert(ret >=3D 0);
+ }
+ return ret;
}
=20
Int VG_(write) ( Int fd, const void* buf, Int count)
{
+ Int ret;
SysRes res =3D VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
- return res.isError ? -1 : res.val;
+ if (res.isError) {
+ ret =3D - (Int)(Word)res.err;
+ vg_assert(ret < 0);
+ } else {
+ ret =3D (Int)(Word)res.res;
+ vg_assert(ret >=3D 0);
+ }
+ return ret;
}
=20
Int VG_(pipe) ( Int fd[2] )
@@ -115,39 +132,61 @@
OffT VG_(lseek) ( Int fd, OffT offset, Int whence )
{
SysRes res =3D VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
- return res.isError ? (-1) : res.val;
+ return res.isError ? (-1) : res.res;
/* if you change the error-reporting conventions of this, also
change VG_(pread) and all other usage points. */
}
=20
SysRes VG_(stat) ( Char* file_name, struct vki_stat* buf )
{
+# if defined(VGO_linux)
SysRes res =3D VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)b=
uf);
return res;
+# elif defined(VGO_aix5)
+ SysRes res =3D VG_(do_syscall4)(__NR_AIX5_statx,
+ (UWord)file_name,
+ (UWord)buf,
+ sizeof(struct vki_stat),
+ VKI_STX_NORMAL);
+ return res;
+# else
+# error Unknown OS
+# endif
}
=20
Int VG_(fstat) ( Int fd, struct vki_stat* buf )
{
+# if defined(VGO_linux)
SysRes res =3D VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
return res.isError ? (-1) : 0;
+# elif defined(VGO_aix5)
+ I_die_here;
+# else
+# error Unknown OS
+# endif
}
=20
Int VG_(fsize) ( Int fd )
{
-#ifdef __NR_fstat64
+# if defined(VGO_linux) && defined(__NR_fstat64)
struct vki_stat64 buf;
SysRes res =3D VG_(do_syscall2)(__NR_fstat64, fd, (UWord)&buf);
-#else
+ return res.isError ? (-1) : buf.st_size;
+# elif defined(VGO_linux) && !defined(__NR_fstat64)
struct vki_stat buf;
SysRes res =3D VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
-#endif
return res.isError ? (-1) : buf.st_size;
+# elif defined(VGO_aix5)
+ I_die_here;
+# else
+# error Unknown OS
+# endif
}
=20
Bool VG_(is_dir) ( HChar* f )
{
struct vki_stat buf;
- SysRes res =3D VG_(do_syscall2)(__NR_stat, (UWord)f, (UWord)&buf);
+ SysRes res =3D VG_(stat)(f, &buf);
return res.isError ? False
: VKI_S_ISDIR(buf.st_mode) ? True : False;
}
@@ -161,7 +200,7 @@
Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
{
SysRes res =3D VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
}
=20
Int VG_(rename) ( Char* old_name, Char* new_name )
@@ -176,14 +215,25 @@
return res.isError ? (-1) : 0;
}
=20
-/* Nb: we do not allow the Linux extension which malloc()s memory for th=
e
- buffer if buf=3D=3DNULL, because we don't want Linux calling malloc()=
*/
Bool VG_(getcwd) ( Char* buf, SizeT size )
{
+# if defined(VGO_linux)
SysRes res;
vg_assert(buf !=3D NULL);
res =3D VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
return res.isError ? False : True;
+# elif defined(VGO_aix5)
+ static Int complaints =3D 3;
+ if (complaints-- > 0)
+ VG_(debugLog)(0, "libcfile",
+ "Warning: AIX5: m_libcfile.c: kludged 'getcwd'\n"=
);
+ if (size < 2) return False;
+ buf[0] =3D '.';
+ buf[1] =3D 0;
+ return True;
+# else
+# error Unknown OS
+# endif
}
=20
Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
@@ -191,7 +241,7 @@
SysRes res;
/* res =3D readlink( path, buf, bufsiz ); */
res =3D VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufs=
iz);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
}
=20
Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
@@ -199,14 +249,14 @@
SysRes res;
/* res =3D getdents( fd, dirp, count ); */
res =3D VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
}
=20
/* Check accessibility of a file. Returns zero for access granted,
nonzero otherwise. */
Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
{
-#if defined(VGO_linux)
+# if defined(VGO_linux)
/* Very annoyingly, I cannot find any definition for R_OK et al in
the kernel interfaces. Therefore I reluctantly resort to
hardwiring in these magic numbers that I determined by
@@ -215,10 +265,16 @@
| (iwusr ? 2/*W_OK*/ : 0)
| (ixusr ? 1/*X_OK*/ : 0);
SysRes res =3D VG_(do_syscall2)(__NR_access, (UWord)path, w);
- return res.isError ? 1 : res.val;
-#else
-# error "Don't know how to do VG_(access) on this OS"
-#endif
+ return res.isError ? 1 : 0;
+# elif defined(VGO_aix5)
+ UWord w =3D (irusr ? VKI_R_OK : 0)
+ | (iwusr ? VKI_W_OK : 0)
+ | (ixusr ? VKI_X_OK : 0);
+ SysRes res =3D VG_(do_syscall2)(__NR_access, (UWord)path, w);
+ return res.isError ? 1 : 0; =20
+# else
+# error "Don't know how to do VG_(access) on this OS"
+# endif
}
=20
/*=20
@@ -244,11 +300,11 @@
#endif
=20
if (res.isError) {
- return res.val;
+ return res.err;
}
=20
if (st.st_mode & (VKI_S_ISUID | VKI_S_ISGID)) {
- //VG_(printf)("Can't execute suid/sgid executable %s\n", exe);
+ /* VG_(printf)("Can't execute suid/sgid executable %s\n", exe); */
return VKI_EACCES;
}
=20
@@ -326,7 +382,7 @@
if (sres.isError)
continue;
/* VG_(safe_fd) doesn't return if it fails. */
- fd =3D VG_(safe_fd)( sres.val );
+ fd =3D VG_(safe_fd)( sres.res );
if (fullname)
VG_(strcpy)( fullname, buf );
return fd;
@@ -346,7 +402,12 @@
Int my_socket ( Int domain, Int type, Int protocol );
=20
static
-Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,=20
+Int my_connect ( Int sockfd,=20
+# if defined(VGO_linux)
+ struct vki_sockaddr_in* serv_addr,=20
+# else
+ void* serv_addr,
+# endif
Int addrlen );
=20
UInt VG_(htonl) ( UInt x )
@@ -404,6 +465,9 @@
*/
Int VG_(connect_via_socket)( UChar* str )
{
+#if defined(VGO_aix5)
+ I_die_here;
+#else /* Yay, Linux */
Int sd, res;
struct vki_sockaddr_in servAddr;
UInt ip =3D 0;
@@ -438,13 +502,14 @@
}
=20
return sd;
+#endif
}
=20
=20
/* Let d =3D one or more digits. Accept either:
d.d.d.d or d.d.d.d:d
*/
-Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
+static Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort*=
port )
{
# define GET_CH ((*str) ? (*str++) : 0)
UInt ipa, i, j, c, any;
@@ -495,20 +560,28 @@
args[1] =3D type;
args[2] =3D protocol;
res =3D VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&arg=
s);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
#elif defined(VGP_amd64_linux)
SysRes res;
res =3D VG_(do_syscall3)(__NR_socket, domain, type, protocol );
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
+#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ I_die_here;
+
#else
# error Unknown arch
#endif
}
=20
static
-Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,=20
+Int my_connect ( Int sockfd,
+# if defined(VGO_linux)
+ struct vki_sockaddr_in* serv_addr,=20
+# else
+ void* serv_addr,
+# endif
Int addrlen )
{
#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
@@ -518,13 +591,16 @@
args[1] =3D (UWord)serv_addr;
args[2] =3D addrlen;
res =3D VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&ar=
gs);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
#elif defined(VGP_amd64_linux)
SysRes res;
res =3D VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addr=
len);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
+#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ I_die_here;
+
#else
# error Unknown arch
#endif
@@ -533,10 +609,9 @@
Int VG_(write_socket)( Int sd, void *msg, Int count )
{
/* This is actually send(). */
- /* Requests not to send SIGPIPE on errors on stream oriented
- sockets when the other end breaks the connection. The EPIPE
- error is still returned. */
- Int flags =3D VKI_MSG_NOSIGNAL;
+ /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
+ errors on stream oriented sockets when the other end breaks the
+ connection. The EPIPE error is still returned. */
=20
#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
SysRes res;
@@ -544,15 +619,19 @@
args[0] =3D sd;
args[1] =3D (UWord)msg;
args[2] =3D count;
- args[3] =3D flags;
+ args[3] =3D VKI_MSG_NOSIGNAL;
res =3D VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args)=
;
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
#elif defined(VGP_amd64_linux)
SysRes res;
- res =3D VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, flags, 0=
,0);
- return res.isError ? -1 : res.val;
+ res =3D VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,=20
+ count, VKI_MSG_NOSIGNAL, 0,0);
+ return res.isError ? -1 : res.res;
=20
+#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ I_die_here;
+
#else
# error Unknown arch
#endif
@@ -560,21 +639,24 @@
=20
Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
SysRes res;
-
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
UWord args[3];
args[0] =3D sd;
args[1] =3D (UWord)name;
args[2] =3D (UWord)namelen;
res =3D VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord=
)&args);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
#elif defined(VGP_amd64_linux)
+ SysRes res;
res =3D VG_(do_syscall3)( __NR_getsockname,
(UWord)sd, (UWord)name, (UWord)namelen );
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
+#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ I_die_here;
+
#else
# error Unknown arch
#endif
@@ -582,32 +664,34 @@
=20
Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
SysRes res;
-
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
UWord args[3];
args[0] =3D sd;
args[1] =3D (UWord)name;
args[2] =3D (UWord)namelen;
res =3D VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord=
)&args);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
#elif defined(VGP_amd64_linux)
+ SysRes res;
res =3D VG_(do_syscall3)( __NR_getpeername,
(UWord)sd, (UWord)name, (UWord)namelen );
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
+#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ I_die_here;
+
#else
-# error Unknown archx
+# error Unknown arch
#endif
}
=20
Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
Int *optlen)
{
+#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
SysRes res;
-
-#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_pp=
c64_linux)
UWord args[5];
args[0] =3D sd;
args[1] =3D level;
@@ -615,14 +699,18 @@
args[3] =3D (UWord)optval;
args[4] =3D (UWord)optlen;
res =3D VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)=
&args);
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
#elif defined(VGP_amd64_linux)
+ SysRes res;
res =3D VG_(do_syscall5)( __NR_getsockopt,
(UWord)sd, (UWord)level, (UWord)optname,=20
(UWord)optval, (UWord)optlen );
- return res.isError ? -1 : res.val;
+ return res.isError ? -1 : res.res;
=20
+#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ I_die_here;
+
#else
# error Unknown arch
#endif
Modified: trunk/coregrind/pub_core_libcfile.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_libcfile.h 2006-10-17 01:37:10 UTC (rev 6266=
)
+++ trunk/coregrind/pub_core_libcfile.h 2006-10-17 01:38:13 UTC (rev 6267=
)
@@ -34,6 +34,7 @@
//--------------------------------------------------------------------
// PURPOSE: This module contains all the libc code that relates to
// files and sockets: opening, reading, writing, etc.
+// To use, you must first include: pub_core_vki.h
//--------------------------------------------------------------------
=20
#include "pub_tool_libcfile.h"
Modified: trunk/include/pub_tool_libcfile.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_libcfile.h 2006-10-17 01:37:10 UTC (rev 6266)
+++ trunk/include/pub_tool_libcfile.h 2006-10-17 01:38:13 UTC (rev 6267)
@@ -35,6 +35,8 @@
File-related functions.
------------------------------------------------------------------ */
=20
+/* To use this file you must first include pub_tool_vki.h. */
+
extern SysRes VG_(open) ( const Char* pathname, Int flags, Int mode );
extern void VG_(close) ( Int fd );
extern Int VG_(read) ( Int fd, void* buf, Int count);
|
|
From: <sv...@va...> - 2006-10-17 01:37:15
|
Author: sewardj
Date: 2006-10-17 02:37:10 +0100 (Tue, 17 Oct 2006)
New Revision: 6266
Log:
Merge r6129:
Changes to support XCOFF:
- allow modules to have 'member names' as well as file names. A member
name is a "foo.o" name inside a "bar.a"; necessary as AIX
keeps all its dynamic libraries in .a files.
- rename the type RiLoc to DiLoc (this holds a line number indication).
No idea why it was called RiLoc in the first place.
- trace changes in type SysRes
- implement VG_(di_aix5_notify_segchange)
Modified:
trunk/coregrind/m_debuginfo/debuginfo.c
trunk/coregrind/m_debuginfo/priv_storage.h
trunk/coregrind/m_debuginfo/readelf.c
trunk/coregrind/m_debuginfo/storage.c
Modified: trunk/coregrind/m_debuginfo/debuginfo.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/debuginfo.c 2006-10-17 01:36:37 UTC (rev =
6265)
+++ trunk/coregrind/m_debuginfo/debuginfo.c 2006-10-17 01:37:10 UTC (rev =
6266)
@@ -46,12 +46,19 @@
#include "pub_core_options.h"
#include "pub_core_redir.h" // VG_(redir_notify_{new,delete}_SegIn=
fo)
#include "pub_core_aspacemgr.h"
+#include "pub_core_machine.h" // VG_PLAT_USES_PPCTOC
#include "priv_storage.h"
#include "priv_readdwarf.h"
#include "priv_readstabs.h"
-#include "priv_readelf.h"
+#if defined(VGO_linux)
+# include "priv_readelf.h"
+#elif defined(VGO_aix5)
+# include "pub_core_debuglog.h"
+# include "pub_core_libcproc.h"
+# include "pub_core_libcfile.h"
+# include "priv_readxcoff.h"
+#endif
=20
-
/*------------------------------------------------------------*/
/*--- Root structure ---*/
/*------------------------------------------------------------*/
@@ -72,7 +79,8 @@
/* Allocate and zero out a new SegInfo record. */
static=20
SegInfo* alloc_SegInfo(Addr start, SizeT size, OffT foffset,=20
- const HChar* filename)
+ const UChar* filename,
+ const UChar* memname)
{
SegInfo* si =3D VG_(arena_calloc)(VG_AR_SYMTAB, 1, sizeof(SegInfo));
=20
@@ -80,6 +88,8 @@
si->size =3D size;
si->foffset =3D foffset;
si->filename =3D VG_(arena_strdup)(VG_AR_SYMTAB, filename);
+ si->memname =3D memname ? VG_(arena_strdup)(VG_AR_SYMTAB, memname)
+ : NULL;
=20
// Everything else -- pointers, sizes, arrays -- is zeroed by calloc.
return si;
@@ -110,6 +120,14 @@
*/
static void discard_SegInfo ( SegInfo* si )
{
+# if defined(VGP_ppc32_aix5)
+ HChar* reason =3D "__unload";
+# elif defined(VGP_ppc64_aix5)
+ HChar* reason =3D "kunload64";
+# else
+ HChar* reason =3D "munmap";
+# endif
+
SegInfo** prev_next_ptr =3D &segInfo_list;
SegInfo* curr =3D segInfo_list;
=20
@@ -118,9 +136,10 @@
// Found it; remove from list and free it.
if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
VG_(message)(Vg_DebugMsg,=20
- "Discarding syms at %p-%p in %s due to munmap()=
",=20
+ "Discarding syms at %p-%p in %s due to %s()",=20
si->start, si->start + si->size,
- curr->filename ? curr->filename : (UChar*)"???"=
);
+ curr->filename ? curr->filename : (UChar*)"???"=
,
+ reason);
vg_assert(*prev_next_ptr =3D=3D curr);
*prev_next_ptr =3D curr->next;
VG_(redir_notify_delete_SegInfo)( curr );
@@ -170,12 +189,29 @@
/* Create a new SegInfo with the specific address/length/vma offset,
then snarf whatever info we can from the given filename into it. */
static
-SegInfo* acquire_syms_for_range( Addr seg_addr, SizeT seg_len,
- OffT seg_offset, const Char* seg_filena=
me)
+SegInfo* acquire_syms_for_range(=20
+ /* ALL */ Addr seg_addr,=20
+ /* ALL */ SizeT seg_len,
+ /* ELF only */ OffT seg_offset,=20
+ /* ALL */ const UChar* seg_filename,
+ /* XCOFF only */ const UChar* seg_memname,
+ /* XCOFF only */ Addr data_addr,
+ /* XCOFF only */ SizeT data_len,
+ /* XCOFF only */ Bool is_mainexe
+ )
{
- SegInfo* si =3D alloc_SegInfo(seg_addr, seg_len, seg_offset, seg_file=
name);
+ Bool ok;
+ SegInfo* si =3D alloc_SegInfo(seg_addr, seg_len, seg_offset,=20
+ seg_filename, seg_memname);
+# if defined(VGO_linux)
+ ok =3D ML_(read_elf_debug_info) ( si );
+# elif defined(VGO_aix5)
+ ok =3D ML_(read_xcoff_debug_info) ( si, data_addr, data_len, is_maine=
xe );
+# else
+# error Unknown OS
+# endif
=20
- if (! ML_(read_elf_debug_info) ( si )) {
+ if (!ok) {
// Something went wrong (eg. bad ELF file).
free_SegInfo( si );
si =3D NULL;
@@ -195,12 +231,14 @@
}
=20
=20
-/*------------------------------------------------------------*/
-/*--- ---*/
-/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) ---*/
-/*--- ---*/
-/*------------------------------------------------------------*/
+/*--------------------------------------------------------------*/
+/*--- ---*/
+/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
+/*--- ---*/
+/*--------------------------------------------------------------*/
=20
+#if defined(VGO_linux)
+
/* The debug info system is driven by notifications that a text
segment has been mapped in, or unmapped. When that happens it
tries to acquire/discard whatever info is available for the
@@ -216,7 +254,7 @@
=20
void VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV )
{
- NSegment* seg;
+ NSegment const * seg;
HChar* filename;
Bool ok;
=20
@@ -260,7 +298,7 @@
seg =3D VG_(am_find_nsegment)(a);
vg_assert(seg);
=20
- filename =3D VG_(am_get_filename)( seg );
+ filename =3D VG_(am_get_filename)( (NSegment*)seg );
if (!filename)
return;
=20
@@ -284,7 +322,8 @@
=20
/* .. and acquire new info. */
acquire_syms_for_range( seg->start, seg->end + 1 - seg->start,=20
- seg->offset, filename );
+ seg->offset, filename,
+ /* XCOFF only */ NULL, 0, 0, False );
=20
/* acquire_syms_for_range makes its own copy of filename, so is
safe to free it. */
@@ -314,7 +353,71 @@
discard_syms_in_range(a, len);
}
=20
+#endif /* defined(VGO_linux) */
=20
+
+/*-------------------------------------------------------------*/
+/*--- ---*/
+/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (AIX5) ---*/
+/*--- ---*/
+/*-------------------------------------------------------------*/
+
+#if defined(VGO_aix5)
+
+/* The supplied parameters describe a code segment and its associated
+ data segment, that have recently been mapped in -- so we need to
+ read debug info for it -- or conversely, have recently been dumped,
+ in which case the relevant debug info has to be unloaded. */
+
+void VG_(di_aix5_notify_segchange)(=20
+ Addr code_start,
+ Word code_len,
+ Addr data_start,
+ Word data_len,
+ UChar* file_name,
+ UChar* mem_name,
+ Bool is_mainexe,
+ Bool acquire )
+{
+ SegInfo* si;
+
+ if (acquire) {
+
+ acquire_syms_for_range(
+ /* ALL */ code_start,=20
+ /* ALL */ code_len,
+ /* ELF only */ 0,
+ /* ALL */ file_name,
+ /* XCOFF only */ mem_name,
+ /* XCOFF only */ data_start,
+ /* XCOFF only */ data_len,
+ /* XCOFF only */ is_mainexe=20
+ );
+
+ } else {
+
+ /* Dump all the segInfos which intersect code_start/code_len. */
+ while (True) {
+ for (si =3D segInfo_list; si; si =3D si->next) {
+ if (code_start + code_len <=3D si->start
+ || si->start + si->size <=3D code_start)
+ continue; /* no overlap */
+ else=20
+ break;
+ }
+ if (si =3D=3D NULL)
+ break;
+ /* Need to delete 'si' */
+ discard_SegInfo(si);
+ }
+
+ }
+}
+ =20
+
+#endif /* defined(VGO_aix5) */
+
+
/*------------------------------------------------------------*/
/*--- ---*/
/*--- TOP LEVEL: QUERYING EXISTING DEBUG INFO ---*/
@@ -499,11 +602,25 @@
Caller supplies buf and nbuf. */
Bool VG_(get_objname) ( Addr a, Char* buf, Int nbuf )
{
+ Int used;
SegInfo* si;
=20
+ vg_assert(nbuf > 0);
for (si =3D segInfo_list; si !=3D NULL; si =3D si->next) {
if (si->start <=3D a && a < si->start+si->size) {
VG_(strncpy_safely)(buf, si->filename, nbuf);
+ if (si->memname) {
+ used =3D VG_(strlen)(buf);
+ if (used < nbuf)=20
+ VG_(strncpy_safely)(&buf[used], "(", nbuf-used);
+ used =3D VG_(strlen)(buf);
+ if (used < nbuf)=20
+ VG_(strncpy_safely)(&buf[used], si->memname, nbuf-used);
+ used =3D VG_(strlen)(buf);
+ if (used < nbuf)=20
+ VG_(strncpy_safely)(&buf[used], ")", nbuf-used);
+ }
+ buf[nbuf-1] =3D 0;
return True;
}
}
@@ -590,6 +707,43 @@
}
=20
=20
+/* Map a function name to its entry point and toc pointer. Is done by
+ sequential search of all symbol tables, so is very slow. To
+ mitigate the worst performance effects, you may specify a soname
+ pattern, and only objects matching that pattern are searched.
+ Therefore specify "*" to search all the objects. On TOC-afflicted
+ platforms, a symbol is deemed to be found only if it has a nonzero
+ TOC pointer. */
+Bool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name, Addr* pEnt, Add=
r* pToc)
+{
+ Bool require_pToc =3D False;
+ Int i;
+ SegInfo* si;
+ Bool debug =3D False;
+# if defined(VG_PLAT_USES_PPCTOC)
+ require_pToc =3D True;
+# endif
+ for (si =3D segInfo_list; si; si =3D si->next) {
+ if (debug)
+ VG_(printf)("lookup_symbol_SLOW: considering %s\n", si->soname)=
;
+ if (!VG_(string_match)(sopatt, si->soname)) {
+ if (debug)
+ VG_(printf)(" ... skip\n");
+ continue;
+ }
+ for (i =3D 0; i < si->symtab_used; i++) {
+ if (0=3D=3DVG_(strcmp)(name, si->symtab[i].name)
+ && (require_pToc ? si->symtab[i].tocptr : True)) {
+ *pEnt =3D si->symtab[i].addr;
+ *pToc =3D si->symtab[i].tocptr;
+ return True;
+ }
+ }
+ }
+ return False;
+}
+
+
/* Print into buf info on code address, function name and filename */
=20
static Int putStr ( Int n, Int n_buf, Char* buf, Char* str )=20
@@ -632,7 +786,9 @@
static UChar buf_srcloc[BUF_LEN];
static UChar buf_dirname[BUF_LEN];
Bool know_dirinfo =3D False;
- Bool know_fnname =3D VG_(get_fnname) (eip, buf_fn, BUF_LEN);
+ Bool know_fnname =3D VG_(clo_sym_offsets)
+ ? VG_(get_fnname_w_offset) (eip, buf_fn, BUF_LEN=
)
+ : VG_(get_fnname) (eip, buf_fn, BUF_LEN);
Bool know_objname =3D VG_(get_objname)(eip, buf_obj, BUF_LEN);
Bool know_srcloc =3D VG_(get_filename_linenum)(
eip,=20
@@ -921,13 +1077,15 @@
void VG_(seginfo_syms_getidx) ( const SegInfo *si,=20
Int idx,
/*OUT*/Addr* addr,
+ /*OUT*/Addr* tocptr,
/*OUT*/UInt* size,
/*OUT*/HChar** name )
{
vg_assert(idx >=3D 0 && idx < si->symtab_used);
- if (addr) *addr =3D si->symtab[idx].addr;
- if (size) *size =3D si->symtab[idx].size;
- if (name) *name =3D (HChar*)si->symtab[idx].name;
+ if (addr) *addr =3D si->symtab[idx].addr;
+ if (tocptr) *tocptr =3D si->symtab[idx].tocptr;
+ if (size) *size =3D si->symtab[idx].size;
+ if (name) *name =3D (HChar*)si->symtab[idx].name;
}
=20
=20
Modified: trunk/coregrind/m_debuginfo/priv_storage.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/priv_storage.h 2006-10-17 01:36:37 UTC (r=
ev 6265)
+++ trunk/coregrind/m_debuginfo/priv_storage.h 2006-10-17 01:37:10 UTC (r=
ev 6266)
@@ -142,6 +142,7 @@
Addr start;
UInt size;
UChar* filename; /* in mallocville */
+ UChar* memname; /* malloc'd. AIX5 only: .a member name */
OffT foffset;
UChar* soname;
=20
Modified: trunk/coregrind/m_debuginfo/readelf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/readelf.c 2006-10-17 01:36:37 UTC (rev 62=
65)
+++ trunk/coregrind/m_debuginfo/readelf.c 2006-10-17 01:37:10 UTC (rev 62=
66)
@@ -738,8 +738,8 @@
if (fd.isError)
return 0;
=20
- if (VG_(fstat)(fd.val, &stat_buf) !=3D 0) {
- VG_(close)(fd.val);
+ if (VG_(fstat)(fd.res, &stat_buf) !=3D 0) {
+ VG_(close)(fd.res);
return 0;
}
=20
@@ -749,23 +749,23 @@
*size =3D stat_buf.st_size;
=20
sres =3D VG_(am_mmap_file_float_valgrind)
- ( *size, VKI_PROT_READ, fd.val, 0 );
+ ( *size, VKI_PROT_READ, fd.res, 0 );
=20
- VG_(close)(fd.val);
+ VG_(close)(fd.res);
=20
if (sres.isError)
return 0;
=20
- calccrc =3D calc_gnu_debuglink_crc32(0, (UChar*)sres.val, *size);
+ calccrc =3D calc_gnu_debuglink_crc32(0, (UChar*)sres.res, *size);
if (calccrc !=3D crc) {
- SysRes res =3D VG_(am_munmap_valgrind)(sres.val, *size);
+ SysRes res =3D VG_(am_munmap_valgrind)(sres.res, *size);
vg_assert(!res.isError);
if (VG_(clo_verbosity) > 1)
VG_(message)(Vg_DebugMsg, "... CRC mismatch (computed %08x wanted %08x=
)", calccrc, crc);
return 0;
}
=20
- return sres.val;
+ return sres.res;
}
=20
/*
@@ -838,17 +838,17 @@
return False;
}
=20
- n_oimage =3D VG_(fsize)(fd.val);
+ n_oimage =3D VG_(fsize)(fd.res);
if (n_oimage < 0) {
ML_(symerr)("Can't stat .so/.exe (to determine its size)?!");
- VG_(close)(fd.val);
+ VG_(close)(fd.res);
return False;
}
=20
sres =3D VG_(am_mmap_file_float_valgrind)
- ( n_oimage, VKI_PROT_READ, fd.val, 0 );
+ ( n_oimage, VKI_PROT_READ, fd.res, 0 );
=20
- VG_(close)(fd.val);
+ VG_(close)(fd.res);
=20
if (sres.isError) {
VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", si->filenam=
e );
@@ -856,7 +856,7 @@
return False;
}
=20
- oimage =3D sres.val;
+ oimage =3D sres.res;
=20
/* Ok, the object image is safely in oimage[0 .. n_oimage-1].=20
Now verify that it is a valid ELF .so or executable image.
Modified: trunk/coregrind/m_debuginfo/storage.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/storage.c 2006-10-17 01:36:37 UTC (rev 62=
65)
+++ trunk/coregrind/m_debuginfo/storage.c 2006-10-17 01:37:10 UTC (rev 62=
66)
@@ -562,7 +562,7 @@
ranges do not overlap. This facilitates using binary search to map
addresses to locations when we come to query the table.
*/
-static Int compare_RiLoc ( void* va, void* vb )=20
+static Int compare_DiLoc ( void* va, void* vb )=20
{
DiLoc* a =3D (DiLoc*)va;
DiLoc* b =3D (DiLoc*)vb;
@@ -583,7 +583,7 @@
=20
/* Sort by start address. */
VG_(ssort)(si->loctab, si->loctab_used,=20
- sizeof(*si->loctab), compare_RiLoc);
+ sizeof(*si->loctab), compare_DiLoc);
=20
/* If two adjacent entries overlap, truncate the first. */
for (i =3D 0; i < ((Int)si->loctab_used)-1; i++) {
|
|
From: <sv...@va...> - 2006-10-17 01:36:41
|
Author: sewardj
Date: 2006-10-17 02:36:37 +0100 (Tue, 17 Oct 2006)
New Revision: 6265
Log:
Merge r6128:
Interface changes for m_debuginfo:
- new fn VG_(di_aix5_notify_segchange) to notify XCOFF loads/unloads
- new fn VG_(lookup_symbol_SLOW) for looking up the address of a fn
given its name and soname
Modified:
trunk/coregrind/pub_core_debuginfo.h
trunk/include/pub_tool_debuginfo.h
Modified: trunk/coregrind/pub_core_debuginfo.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_debuginfo.h 2006-10-17 01:35:58 UTC (rev 626=
4)
+++ trunk/coregrind/pub_core_debuginfo.h 2006-10-17 01:36:37 UTC (rev 626=
5)
@@ -39,18 +39,39 @@
=20
#include "pub_tool_debuginfo.h"
=20
-/* Notify the debuginfo system about a new mapping. This is the way
- new debug information gets loaded. If allow_SkFileV is True, it
- will try load debug info if the mapping at 'a' belongs to Valgrind;
- whereas normally (False) it will not do that. This allows us to
- carefully control when the thing will read symbols from the
- Valgrind executable itself. */
+/* LINUX: Notify the debuginfo system about a new mapping, or the
+ disappearance of such, or a permissions change on an existing
+ mapping. This is the way new debug information gets loaded. If
+ allow_SkFileV is True, it will try load debug info if the mapping
+ at 'a' belongs to Valgrind; whereas normally (False) it will not do
+ that. This allows us to carefully control when the thing will read
+ symbols from the Valgrind executable itself. */
+#if defined(VGO_linux)
extern void VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV );
=20
extern void VG_(di_notify_munmap)( Addr a, SizeT len );
=20
extern void VG_(di_notify_mprotect)( Addr a, SizeT len, UInt prot );
+#endif
=20
+#if defined(VGO_aix5)
+/* AIX5: Very similar, except packaged more neatly. The supplied
+ parameters describe a code segment and its associated data segment,
+ that have recently been mapped in -- so we need to read debug info
+ for it -- or conversely, have recently been dumped, in which case
+ the relevant debug info has to be unloaded. */
+extern void VG_(di_aix5_notify_segchange)(=20
+ Addr code_start,
+ Word code_len,
+ Addr data_start,
+ Word data_len,
+ UChar* file_name,
+ UChar* mem_name,
+ Bool is_mainexe,
+ Bool acquire
+ );
+#endif
+
extern Bool VG_(get_fnname_nodemangle)( Addr a,=20
Char* fnname, Int n_fnname );
=20
@@ -72,6 +93,16 @@
extern
Bool VG_(get_fnname_Z_demangle_only) ( Addr a, Char* buf, Int nbuf );
=20
+/* Map a function name to its entry point and toc pointer. Is done by
+ sequential search of all symbol tables, so is very slow. To
+ mitigate the worst performance effects, you may specify a soname
+ pattern, and only objects matching that pattern are searched.
+ Therefore specify "*" to search all the objects. On TOC-afflicted
+ platforms, a symbol is deemed to be found only if it has a nonzero
+ TOC pointer. */
+extern
+Bool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name, Addr* pEnt, Add=
r* pToc);
+
#endif // __PUB_CORE_DEBUGINFO_H
=20
/*--------------------------------------------------------------------*/
Modified: trunk/include/pub_tool_debuginfo.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_debuginfo.h 2006-10-17 01:35:58 UTC (rev 6264)
+++ trunk/include/pub_tool_debuginfo.h 2006-10-17 01:36:37 UTC (rev 6265)
@@ -119,6 +119,7 @@
extern void VG_(seginfo_syms_getidx) ( const SegInfo *si,=20
Int idx,
/*OUT*/Addr* addr,
+ /*OUT*/Addr* tocptr,
/*OUT*/UInt* size,
/*OUT*/HChar** name );
=20
|
|
From: <sv...@va...> - 2006-10-17 01:36:03
|
Author: sewardj
Date: 2006-10-17 02:35:58 +0100 (Tue, 17 Oct 2006)
New Revision: 6264
Log:
Merge r6127: Extend for AIX5. Nothing surprising here.
Modified:
trunk/coregrind/m_machine.c
trunk/coregrind/pub_core_machine.h
trunk/include/pub_tool_machine.h
Modified: trunk/coregrind/m_machine.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_machine.c 2006-10-17 01:34:57 UTC (rev 6263)
+++ trunk/coregrind/m_machine.c 2006-10-17 01:35:58 UTC (rev 6264)
@@ -370,7 +370,7 @@
if (__builtin_setjmp(env_sigill)) {
have_F =3D False;
} else {
- __asm__ __volatile__("fmr 0,0");
+ __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
}
=20
/* Altivec insns */
@@ -397,7 +397,7 @@
if (__builtin_setjmp(env_sigill)) {
have_FX =3D False;
} else {
- __asm__ __volatile__("fsqrt 0,0");
+ __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
}
=20
/* Graphics optional (stfiwx, fres, frsqrte, fsel) */
@@ -408,7 +408,7 @@
if (__builtin_setjmp(env_sigill)) {
have_GX =3D False;
} else {
- __asm__ __volatile__("frsqrte 0,0");
+ __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
}
=20
r =3D VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
@@ -482,7 +482,7 @@
if (__builtin_setjmp(env_sigill)) {
have_V =3D False;
} else {
- __asm__ __volatile__("vor 0,0,0");
+ __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
}
=20
/* General-Purpose optional (fsqrt, fsqrts) */
@@ -492,7 +492,7 @@
if (__builtin_setjmp(env_sigill)) {
have_FX =3D False;
} else {
- __asm__ __volatile__("fsqrt 0,0");
+ __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
}
=20
/* Graphics optional (stfiwx, fres, frsqrte, fsel) */
@@ -502,7 +502,7 @@
if (__builtin_setjmp(env_sigill)) {
have_GX =3D False;
} else {
- __asm__ __volatile__("frsqrte 0,0");
+ __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
}
=20
VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
@@ -582,22 +582,18 @@
=20
=20
// Given a pointer to a function as obtained by "& functionname" in C,
-// produce a pointer to the actual entry point for the function. For
-// most platforms it's the identity function. Unfortunately, on
-// ppc64-linux it isn't (sigh).
+// produce a pointer to the actual entry point for the function.
void* VG_(fnptr_to_fnentry)( void* f )
{
-#if defined(VGP_x86_linux)
+#if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
+ || defined(VGP_ppc32_linux)
return f;
-#elif defined(VGP_amd64_linux)
- return f;
-#elif defined(VGP_ppc32_linux)
- return f;
-#elif defined(VGP_ppc64_linux)
- /* f is a pointer to a 3-word function descriptor, of which
- the first word is the entry address. */
- /* Don't ask me. Really. I have no idea why. */
- ULong* descr =3D (ULong*)f;
+#elif defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
+ || defined(VGP_ppc64_aix5)
+ /* All other ppc variants use the AIX scheme, in which f is a
+ pointer to a 3-word function descriptor, of which the first word
+ is the entry address. */
+ UWord* descr =3D (UWord*)f;
return (void*)(descr[0]);
#else
# error "Unknown platform"
Modified: trunk/coregrind/pub_core_machine.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_machine.h 2006-10-17 01:34:57 UTC (rev 6263)
+++ trunk/coregrind/pub_core_machine.h 2006-10-17 01:35:58 UTC (rev 6264)
@@ -39,24 +39,33 @@
=20
#include "pub_tool_machine.h"
=20
-#if defined(VGA_x86)
+#if defined(VGP_x86_linux)
# define VG_ELF_DATA2XXX ELFDATA2LSB
# define VG_ELF_MACHINE EM_386
# define VG_ELF_CLASS ELFCLASS32
-#elif defined(VGA_amd64)
+# undef VG_PLAT_USES_PPCTOC
+#elif defined(VGP_amd64_linux)
# define VG_ELF_DATA2XXX ELFDATA2LSB
# define VG_ELF_MACHINE EM_X86_64
# define VG_ELF_CLASS ELFCLASS64
-#elif defined(VGA_ppc32)
+# undef VG_PLAT_USES_PPCTOC
+#elif defined(VGP_ppc32_linux)
# define VG_ELF_DATA2XXX ELFDATA2MSB
# define VG_ELF_MACHINE EM_PPC
# define VG_ELF_CLASS ELFCLASS32
-#elif defined(VGA_ppc64)
+# undef VG_PLAT_USES_PPCTOC
+#elif defined(VGP_ppc64_linux)
# define VG_ELF_DATA2XXX ELFDATA2MSB
# define VG_ELF_MACHINE EM_PPC64
# define VG_ELF_CLASS ELFCLASS64
+# define VG_PLAT_USES_PPCTOC 1
+#elif defined(VGO_aix5)
+# undef VG_ELF_DATA2XXX
+# undef VG_ELF_MACHINE
+# undef VG_ELF_CLASS
+# define VG_PLAT_USES_PPCTOC 1
#else
-# error Unknown arch
+# error Unknown platform
#endif
=20
#if defined(VGA_x86)
Modified: trunk/include/pub_tool_machine.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_machine.h 2006-10-17 01:34:57 UTC (rev 6263)
+++ trunk/include/pub_tool_machine.h 2006-10-17 01:35:58 UTC (rev 6264)
@@ -31,30 +31,45 @@
#ifndef __PUB_TOOL_MACHINE_H
#define __PUB_TOOL_MACHINE_H
=20
-#if defined(VGA_x86)
+#if defined(VGP_x86_linux)
# define VG_MIN_INSTR_SZB 1 // min length of native instructi=
on
# define VG_MAX_INSTR_SZB 16 // max length of native instructi=
on
# define VG_CLREQ_SZB 14 // length of a client request, ma=
y
// be larger than VG_MAX_INSTR_=
SZB
# define VG_STACK_REDZONE_SZB 0 // number of addressable bytes be=
low %RSP
-#elif defined(VGA_amd64)
+#elif defined(VGP_amd64_linux)
# define VG_MIN_INSTR_SZB 1
# define VG_MAX_INSTR_SZB 16
# define VG_CLREQ_SZB 19
# define VG_STACK_REDZONE_SZB 128
-#elif defined(VGA_ppc32)
+#elif defined(VGP_ppc32_linux)
# define VG_MIN_INSTR_SZB 4
# define VG_MAX_INSTR_SZB 4=20
# define VG_CLREQ_SZB 20
# define VG_STACK_REDZONE_SZB 0
-#elif defined(VGA_ppc64)
+#elif defined(VGP_ppc64_linux)
# define VG_MIN_INSTR_SZB 4
# define VG_MAX_INSTR_SZB 4=20
# define VG_CLREQ_SZB 20
# define VG_STACK_REDZONE_SZB 288 // number of addressable bytes be=
low R1
// from 64-bit PowerPC ELF ABI Su=
pplement 1.7
+#elif defined(VGP_ppc32_aix5)
+# define VG_MIN_INSTR_SZB 4
+# define VG_MAX_INSTR_SZB 4=20
+# define VG_CLREQ_SZB 20
+ /* The PowerOpen ABI actually says 220 bytes, but that is not an
+ 8-aligned number, and frequently forces Memcheck's
+ mc_{new,die}_mem_stack_N routines into slow cases by losing
+ 8-alignment of the area to be messed with. So let's just say
+ 224 instead. Gdb has a similar kludge. */
+# define VG_STACK_REDZONE_SZB 224
+#elif defined(VGP_ppc64_aix5)
+# define VG_MIN_INSTR_SZB 4
+# define VG_MAX_INSTR_SZB 4=20
+# define VG_CLREQ_SZB 20
+# define VG_STACK_REDZONE_SZB 288 // is this right?
#else
-# error Unknown arch
+# error Unknown platform
#endif
=20
// Guest state accessors
|
|
From: <sv...@va...> - 2006-10-17 01:35:02
|
Author: sewardj Date: 2006-10-17 02:34:57 +0100 (Tue, 17 Oct 2006) New Revision: 6263 Log: Merge r6126: New option --sym-offsets=3Dyes|no [no], which causes all symbols to be shown in the form 'name+offset'. Mostly useful for debugging Valgrind itself. Also move command-line-error functions from m_main into m_options. [Will move them back shortly.] Modified: trunk/coregrind/m_options.c trunk/coregrind/pub_core_options.h Modified: trunk/coregrind/m_options.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/coregrind/m_options.c 2006-10-17 01:32:48 UTC (rev 6262) +++ trunk/coregrind/m_options.c 2006-10-17 01:34:57 UTC (rev 6263) @@ -70,6 +70,7 @@ Int VG_(clo_dump_error) =3D 0; Int VG_(clo_backtrace_size) =3D 12; Char* VG_(clo_sim_hints) =3D NULL; +Bool VG_(clo_sym_offsets) =3D False; Bool VG_(clo_run_libc_freeres) =3D True; Bool VG_(clo_track_fds) =3D False; Bool VG_(clo_show_below_main)=3D False; Modified: trunk/coregrind/pub_core_options.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/coregrind/pub_core_options.h 2006-10-17 01:32:48 UTC (rev 6262) +++ trunk/coregrind/pub_core_options.h 2006-10-17 01:34:57 UTC (rev 6263) @@ -127,6 +127,8 @@ extern Int VG_(clo_backtrace_size); /* Engage miscellaneous weird hacks needed for some progs. */ extern Char* VG_(clo_sim_hints); +/* Show symbols in the form 'name+offset' ? Default: NO */ +extern Bool VG_(clo_sym_offsets); =20 /* Track open file descriptors? */ extern Bool VG_(clo_track_fds); |
|
From: <sv...@va...> - 2006-10-17 01:32:51
|
Author: sewardj
Date: 2006-10-17 02:32:48 +0100 (Tue, 17 Oct 2006)
New Revision: 6262
Log:
Merge r6125: Function-wrapping macros and associated stuff, for AIX.
Modified:
trunk/include/valgrind.h
Modified: trunk/include/valgrind.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/valgrind.h 2006-10-17 01:31:58 UTC (rev 6261)
+++ trunk/include/valgrind.h 2006-10-17 01:32:48 UTC (rev 6262)
@@ -79,31 +79,39 @@
we can't use C++ style "//" comments nor the "asm" keyword (instead
use "__asm__"). */
=20
-/* Derive some tags indicating what the target architecture is. Note
+/* Derive some tags indicating what the target platform is. Note
that in this file we're using the compiler's CPP symbols for
identifying architectures, which are different to the ones we use
within the rest of Valgrind. Note, __powerpc__ is active for both
32 and 64-bit PPC, whereas __powerpc64__ is only active for the
- latter. */
-#undef ARCH_x86
-#undef ARCH_amd64
-#undef ARCH_ppc32
-#undef ARCH_ppc64
+ latter (on Linux, that is). */
+#undef PLAT_x86_linux
+#undef PLAT_amd64_linux
+#undef PLAT_ppc32_linux
+#undef PLAT_ppc64_linux
+#undef PLAT_ppc32_aix5
+#undef PLAT_ppc64_aix5
=20
-#if defined(__i386__)
-# define ARCH_x86 1
-#elif defined(__x86_64__)
-# define ARCH_amd64 1
-#elif defined(__powerpc__) && !defined(__powerpc64__)
-# define ARCH_ppc32 1
-#elif defined(__powerpc__) && defined(__powerpc64__)
-# define ARCH_ppc64 1
+#if !defined(_AIX) && defined(__i386__)
+# define PLAT_x86_linux 1
+#elif !defined(_AIX) && defined(__x86_64__)
+# define PLAT_amd64_linux 1
+#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
+# define PLAT_ppc32_linux 1
+#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
+# define PLAT_ppc64_linux 1
+#elif defined(_AIX) && defined(__64BIT__)
+# define PLAT_ppc64_aix5 1
+#elif defined(_AIX) && !defined(__64BIT__)
+# define PLAT_ppc32_aix5 1
#endif
=20
-/* If we're not compiling for our target architecture, don't generate
+
+/* If we're not compiling for our target platform, don't generate
any inline asms. */
-#if !defined(ARCH_x86) && !defined(ARCH_amd64) \
- && !defined(ARCH_ppc32) && !defined(ARCH_ppc64)
+#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
+ && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
+ && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
# if !defined(NVALGRIND)
# define NVALGRIND 1
# endif
@@ -164,9 +172,9 @@
inline asm stuff to be useful.
*/
=20
-/* ---------------------------- x86 ---------------------------- */
+/* ------------------------- x86-linux ------------------------- */
=20
-#if defined(ARCH_x86)
+#if defined(PLAT_x86_linux)
=20
typedef
struct {=20
@@ -216,11 +224,11 @@
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir *%EAX */ \
"xchgl %%edx,%%edx\n\t"
-#endif /* ARCH_x86 */
+#endif /* PLAT_x86_linux */
=20
-/* --------------------------- amd64 --------------------------- */
+/* ------------------------ amd64-linux ------------------------ */
=20
-#if defined(ARCH_amd64)
+#if defined(PLAT_amd64_linux)
=20
typedef
struct {=20
@@ -270,11 +278,11 @@
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir *%RAX */ \
"xchgq %%rdx,%%rdx\n\t"
-#endif /* ARCH_amd64 */
+#endif /* PLAT_amd64_linux */
=20
-/* --------------------------- ppc32 --------------------------- */
+/* ------------------------ ppc32-linux ------------------------ */
=20
-#if defined(ARCH_ppc32)
+#if defined(PLAT_ppc32_linux)
=20
typedef
struct {=20
@@ -326,11 +334,11 @@
__SPECIAL_INSTRUCTION_PREAMBLE \
/* branch-and-link-to-noredir *%R11 */ \
"or 3,3,3\n\t"
-#endif /* ARCH_ppc32 */
+#endif /* PLAT_ppc32_linux */
=20
-/* --------------------------- ppc64 --------------------------- */
+/* ------------------------ ppc64-linux ------------------------ */
=20
-#if defined(ARCH_ppc64)
+#if defined(PLAT_ppc64_linux)
=20
typedef
struct {=20
@@ -392,15 +400,159 @@
/* branch-and-link-to-noredir *%R11 */ \
"or 3,3,3\n\t"
=20
-#endif /* ARCH_ppc64 */
+#endif /* PLAT_ppc64_linux */
=20
-/* Insert assembly code for other architectures here... */
+/* ------------------------ ppc32-aix5 ------------------------- */
=20
+#if defined(PLAT_ppc32_aix5)
+
+typedef
+ struct {=20
+ unsigned int nraddr; /* where's the code? */
+ unsigned int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
+ "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned int _zzq_args[7]; \
+ register unsigned int _zzq_result; \
+ register unsigned int* _zzq_ptr; \
+ _zzq_args[0] =3D (unsigned int)(_zzq_request); \
+ _zzq_args[1] =3D (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] =3D (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] =3D (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] =3D (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] =3D (unsigned int)(_zzq_arg5); \
+ _zzq_args[6] =3D (unsigned int)(_zzq_default); \
+ _zzq_ptr =3D _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "lwz 3, 24(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 =3D client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=3Db" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval =3D _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig =3D &(_zzq_rlval); \
+ register unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 =3D guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=3Db" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr =3D __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 =3D guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=3Db" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 =3D __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+typedef
+ struct {=20
+ unsigned long long int nraddr; /* where's the code? */
+ unsigned long long int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned long long int _zzq_args[7]; \
+ register unsigned long long int _zzq_result; \
+ register unsigned long long int* _zzq_ptr; \
+ _zzq_args[0] =3D (unsigned int long long)(_zzq_request); \
+ _zzq_args[1] =3D (unsigned int long long)(_zzq_arg1); \
+ _zzq_args[2] =3D (unsigned int long long)(_zzq_arg2); \
+ _zzq_args[3] =3D (unsigned int long long)(_zzq_arg3); \
+ _zzq_args[4] =3D (unsigned int long long)(_zzq_arg4); \
+ _zzq_args[5] =3D (unsigned int long long)(_zzq_arg5); \
+ _zzq_args[6] =3D (unsigned int long long)(_zzq_default); \
+ _zzq_ptr =3D _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "ld 3, 48(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 =3D client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=3Db" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval =3D _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig =3D &(_zzq_rlval); \
+ register unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 =3D guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=3Db" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr =3D __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 =3D guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=3Db" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 =3D __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc64_aix5 */
+
+/* Insert assembly code for other platforms here... */
+
#endif /* NVALGRIND */
=20
=20
/* ------------------------------------------------------------------ */
-/* ARCHITECTURE SPECIFICS for FUNCTION WRAPPING. This is all very */
+/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
/* ugly. It's the least-worst tradeoff I can think of. */
/* ------------------------------------------------------------------ */
=20
@@ -456,9 +608,9 @@
do { volatile unsigned long _junk; \
CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
=20
-/* ---------------------------- x86 ---------------------------- */
+/* ------------------------- x86-linux ------------------------- */
=20
-#if defined(ARCH_x86)
+#if defined(PLAT_x86_linux)
=20
/* These regs are trashed by the hidden call. No need to mention eax
as gcc can already see that, plus causes gcc to bomb. */
@@ -851,11 +1003,11 @@
lval =3D (__typeof__(lval)) _res; \
} while (0)
=20
-#endif /* ARCH_x86 */
+#endif /* PLAT_x86_linux */
=20
-/* --------------------------- amd64 --------------------------- */
+/* ------------------------ amd64-linux ------------------------ */
=20
-#if defined(ARCH_amd64)
+#if defined(PLAT_amd64_linux)
=20
/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
=20
@@ -1242,11 +1394,11 @@
lval =3D (__typeof__(lval)) _res; \
} while (0)
=20
-#endif /* ARCH_amd64 */
+#endif /* PLAT_amd64_linux */
=20
-/* --------------------------- ppc32 --------------------------- */
+/* ------------------------ ppc32-linux ------------------------ */
=20
-#if defined(ARCH_ppc32)
+#if defined(PLAT_ppc32_linux)
=20
/* This is useful for finding out about the on-stack stuff:
=20
@@ -1709,11 +1861,11 @@
lval =3D (__typeof__(lval)) _res; \
} while (0)
=20
-#endif /* ARCH_ppc32 */
+#endif /* PLAT_ppc32_linux */
=20
-/* --------------------------- ppc64 --------------------------- */
+/* ------------------------ ppc64-linux ------------------------ */
=20
-#if defined(ARCH_ppc64)
+#if defined(PLAT_ppc64_linux)
=20
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
=20
@@ -2233,9 +2385,1131 @@
lval =3D (__typeof__(lval)) _res; \
} while (0)
=20
-#endif /* ARCH_ppc64 */
+#endif /* PLAT_ppc64_linux */
=20
+/* ------------------------ ppc32-aix5 ------------------------- */
=20
+#if defined(PLAT_ppc32_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "lwz 3," #_n_fr "(1)\n\t" \
+ "stw 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
+ long) =3D=3D 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ _argvec[2+6] =3D (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ _argvec[2+6] =3D (unsigned long)arg6; \
+ _argvec[2+7] =3D (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ _argvec[2+6] =3D (unsigned long)arg6; \
+ _argvec[2+7] =3D (unsigned long)arg7; \
+ _argvec[2+8] =3D (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ _argvec[2+6] =3D (unsigned long)arg6; \
+ _argvec[2+7] =3D (unsigned long)arg7; \
+ _argvec[2+8] =3D (unsigned long)arg8; \
+ _argvec[2+9] =3D (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ _argvec[2+6] =3D (unsigned long)arg6; \
+ _argvec[2+7] =3D (unsigned long)arg7; \
+ _argvec[2+8] =3D (unsigned long)arg8; \
+ _argvec[2+9] =3D (unsigned long)arg9; \
+ _argvec[2+10] =3D (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ _argvec[2+6] =3D (unsigned long)arg6; \
+ _argvec[2+7] =3D (unsigned long)arg7; \
+ _argvec[2+8] =3D (unsigned long)arg8; \
+ _argvec[2+9] =3D (unsigned long)arg9; \
+ _argvec[2+10] =3D (unsigned long)arg10; \
+ _argvec[2+11] =3D (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ _argvec[2+4] =3D (unsigned long)arg4; \
+ _argvec[2+5] =3D (unsigned long)arg5; \
+ _argvec[2+6] =3D (unsigned long)arg6; \
+ _argvec[2+7] =3D (unsigned long)arg7; \
+ _argvec[2+8] =3D (unsigned long)arg8; \
+ _argvec[2+9] =3D (unsigned long)arg9; \
+ _argvec[2+10] =3D (unsigned long)arg10; \
+ _argvec[2+11] =3D (unsigned long)arg11; \
+ _argvec[2+12] =3D (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg12 */ \
+ "lwz 3,48(11)\n\t" \
+ "stw 3,68(1)\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "ld 3," #_n_fr "(1)\n\t" \
+ "std 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
+ long) =3D=3D 8. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; \
+ _argvec[2] =3D (unsigned long)_orig.nraddr; \
+ _argvec[2+1] =3D (unsigned long)arg1; \
+ _argvec[2+2] =3D (unsigned long)arg2; \
+ _argvec[2+3] =3D (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=3Dr" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval =3D (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig =3D (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] =3D (unsigned long)_orig.r2; ...
[truncated message content] |
|
From: <sv...@va...> - 2006-10-17 01:32:00
|
Author: sewardj
Date: 2006-10-17 02:31:58 +0100 (Tue, 17 Oct 2006)
New Revision: 6261
Log:
Merge r6123:
Extensions for unwinding stacks on ppc32-aix5 and ppc64-aix5. Also,
extend the mechanism developed for ppc64-linux for fishing return
addresses out of the thread's redirection-stack when needed.
Modified:
trunk/coregrind/m_stacktrace.c
Modified: trunk/coregrind/m_stacktrace.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_stacktrace.c 2006-10-17 01:31:27 UTC (rev 6260)
+++ trunk/coregrind/m_stacktrace.c 2006-10-17 01:31:58 UTC (rev 6261)
@@ -60,9 +60,17 @@
Addr ip, Addr sp, Addr fp, Addr lr,
Addr fp_min, Addr fp_max_orig )
{
-#if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
- Bool lr_is_first_RA =3D False; /* ppc only */
-#endif
+# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+ || defined(VGP_ppc32_aix5) \
+ || defined(VGP_ppc64_aix5)
+ Bool lr_is_first_RA =3D False;
+# endif
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5) \
+ || defined(VGP_ppc32_aix5)
+ Word redir_stack_size =3D 0;
+ Word redirs_used =3D 0;
+# endif
+
Bool debug =3D False;
Int i;
Addr fp_max;
@@ -154,7 +162,7 @@
continue;
}
=20
- /* That didn't work out, so see if there is any CFI info to hand
+ /* That didn't work out, so see if there is any CF info to hand
which can be used. */
if ( VG_(use_CF_info)( &ip, &sp, &fp, fp_min, fp_max ) ) {
ips[i++] =3D ip;
@@ -235,26 +243,45 @@
break;
}
=20
-# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
+# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
+ || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
=20
/*--------------------- ppc32/64 ---------------------*/
=20
/* fp is %r1. ip is %cia. Note, ppc uses r1 as both the stack and
frame pointers. */
=20
-# if defined(VGP_ppc64_linux)
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+ redir_stack_size =3D VEX_GUEST_PPC64_REDIR_STACK_SIZE;
+ redirs_used =3D 0;
+# elif defined(VGP_ppc32_aix5)
+ redir_stack_size =3D VEX_GUEST_PPC32_REDIR_STACK_SIZE;
+ redirs_used =3D 0;
+# endif
+
+# if defined(VG_PLAT_USES_PPCTOC)
/* Deal with bogus LR values caused by function
- interception/wrapping; see comment on similar code a few lines
- further down. */
- if (lr =3D=3D (Addr)&VG_(ppc64_linux_magic_redirect_return_stub)
+ interception/wrapping on ppc-TOC platforms; see comment on
+ similar code a few lines further down. */
+ if (ULong_to_Ptr(lr) =3D=3D (void*)&VG_(ppctoc_magic_redirect_return_=
stub)
&& VG_(is_valid_tid)(tid_if_known)) {
- Long hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP;
- if (hsp >=3D 1 && hsp < VEX_GUEST_PPC64_REDIR_STACK_SIZE)
+ Word hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_REDIR_SP;
+ redirs_used++;
+ if (hsp >=3D 1 && hsp < redir_stack_size)
lr =3D VG_(threads)[tid_if_known]
.arch.vex.guest_REDIR_STACK[hsp-1];
}
# endif
=20
+ /* We have to determine whether or not LR currently holds this fn
+ (call it F)'s return address. It might not if F has previously
+ called some other function, hence overwriting LR with a pointer
+ to some part of F. Hence if LR and IP point to the same
+ function then we conclude LR does not hold this function's
+ return address; instead the LR at entry must have been saved in
+ the stack by F's prologue and so we must get it from there
+ instead. Note all this guff only applies to the innermost
+ frame. */
lr_is_first_RA =3D False;
{
# define M_VG_ERRTXT 1000
@@ -276,10 +303,11 @@
=20
while (True) {
=20
- /* on ppc64-linux (ppc64-elf, really), the lr save slot is 2
- words back from sp, whereas on ppc32-elf(?) it's only one
- word back. */
-# if defined(VGP_ppc64_linux)
+ /* On ppc64-linux (ppc64-elf, really), and on AIX, the lr save
+ slot is 2 words back from sp, whereas on ppc32-elf(?) it's
+ only one word back. */
+# if defined(VGP_ppc64_linux) \
+ || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
const Int lr_offset =3D 2;
# else
const Int lr_offset =3D 1;
@@ -298,19 +326,23 @@
else
ip =3D (((UWord*)fp)[lr_offset]);
=20
-# if defined(VGP_ppc64_linux)
+# if defined(VG_PLAT_USES_PPCTOC)
/* Nasty hack to do with function replacement/wrapping on
- ppc64-linux. If LR points to our magic return stub,
- then we are in a wrapped or intercepted function, in
- which LR has been messed with. The original LR will
- have been pushed onto the thread's hidden REDIR stack
- one down from the top (top element is the saved R2) and
- so we should restore the value from there instead. */
- if (i =3D=3D 1=20
- && ip =3D=3D (Addr)&VG_(ppc64_linux_magic_redirect_retur=
n_stub)
+ ppc64-linux/ppc64-aix/ppc32-aix. If LR points to our
+ magic return stub, then we are in a wrapped or
+ intercepted function, in which LR has been messed with.
+ The original LR will have been pushed onto the thread's
+ hidden REDIR stack one down from the top (top element
+ is the saved R2) and so we should restore the value
+ from there instead. Since nested redirections can and
+ do happen, we keep track of the number of nested LRs
+ used by the unwinding so far with 'redirs_used'. */
+ if (ip =3D=3D (Addr)&VG_(ppctoc_magic_redirect_return_stub)
&& VG_(is_valid_tid)(tid_if_known)) {
- Long hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_RE=
DIR_SP;
- if (hsp >=3D 1 && hsp < VEX_GUEST_PPC64_REDIR_STACK_SIZE)
+ Word hsp =3D VG_(threads)[tid_if_known].arch.vex.guest_RE=
DIR_SP;
+ hsp -=3D 2 * redirs_used;
+ redirs_used ++;
+ if (hsp >=3D 1 && hsp < redir_stack_size)
ip =3D VG_(threads)[tid_if_known]
.arch.vex.guest_REDIR_STACK[hsp-1];
}
|
|
From: <sv...@va...> - 2006-10-17 01:31:30
|
Author: sewardj
Date: 2006-10-17 02:31:27 +0100 (Tue, 17 Oct 2006)
New Revision: 6260
Log:
Merge r6121: Don't define uchar; it might already be defined.
Modified:
trunk/perf/bz2.c
Modified: trunk/perf/bz2.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/perf/bz2.c 2006-10-17 01:30:47 UTC (rev 6259)
+++ trunk/perf/bz2.c 2006-10-17 01:31:27 UTC (rev 6260)
@@ -5946,7 +5946,6 @@
=20
#define M_BLOCK 1000000
=20
-typedef unsigned char uchar;
=20
#define M_BLOCK_OUT (M_BLOCK + 1000000)
char inbuf[M_BLOCK];
@@ -5981,7 +5980,7 @@
{
int byteno =3D bit / 8;
int bitno =3D bit % 8;
- uchar mask =3D 1 << bitno;
+ UChar mask =3D 1 << bitno;
//fprintf ( stderr, "(byte %d bit %d mask %d)",
// byteno, bitno, (int)mask );
zbuf[byteno] ^=3D mask;
|
|
From: <sv...@va...> - 2006-10-17 01:30:50
|
Author: sewardj
Date: 2006-10-17 02:30:47 +0100 (Tue, 17 Oct 2006)
New Revision: 6259
Log:
Merge r6120:
Get rid of VG_(sigtimedwait) and replace it a simpler version,
VG_(sigtimedwait_zero), which polls for signals and returns
immediately. AIX doesn't have a sigtimedwait syscall, so in that case
try and implement VG_(sigtimedwait_zero) using various other signal
syscalls.
Modified:
trunk/coregrind/m_libcsignal.c
trunk/coregrind/pub_core_libcsignal.h
Modified: trunk/coregrind/m_libcsignal.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_libcsignal.c 2006-10-17 01:30:07 UTC (rev 6258)
+++ trunk/coregrind/m_libcsignal.c 2006-10-17 01:30:47 UTC (rev 6259)
@@ -29,15 +29,18 @@
*/
=20
#include "pub_core_basics.h"
+#include "pub_core_debuglog.h"
#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
-#include "pub_core_libcsignal.h"
#include "pub_core_syscall.h"
-#include "pub_core_vkiscnums.h"
+#include "pub_core_libcsignal.h" /* self */
=20
/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
success and -1 on error. */
+/* I believe the indexing scheme in ->sig[] is also correct for
+ 32- and 64-bit AIX (verified 27 July 06). */
=20
Int VG_(sigfillset)( vki_sigset_t* set )
{
@@ -122,7 +125,6 @@
return 0;
}
=20
-
/* Add all signals in src to dst. */
void VG_(sigaddset_from_set)( vki_sigset_t* dst, vki_sigset_t* src )
{
@@ -164,55 +166,144 @@
}
=20
=20
-Int VG_(sigtimedwait)( const vki_sigset_t *set, vki_siginfo_t *info,=20
- const struct vki_timespec *timeout )
+Int VG_(kill)( Int pid, Int signo )
{
- SysRes res =3D VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UW=
ord)info,=20
- (UWord)timeout, sizeof(*set));
- return res.isError ? -1 : res.val;
+ SysRes res =3D VG_(do_syscall2)(__NR_kill, pid, signo);
+ return res.isError ? -1 : 0;
}
-=20
-Int VG_(signal)(Int signum, void (*sighandler)(Int))
+
+
+Int VG_(tkill)( ThreadId tid, Int signo )
{
- SysRes res;
- Int n;
- struct vki_sigaction sa;
- sa.ksa_handler =3D sighandler;
- sa.sa_flags =3D VKI_SA_ONSTACK | VKI_SA_RESTART;
- sa.sa_restorer =3D NULL;
- n =3D VG_(sigemptyset)( &sa.sa_mask );
- vg_assert(n =3D=3D 0);
- res =3D VG_(do_syscall4)(__NR_rt_sigaction, signum, (UWord)&sa, (UWor=
d)NULL,
- _VKI_NSIG_WORDS * sizeof(UWord));
+ SysRes res =3D VG_(mk_SysRes_Error)(VKI_ENOSYS);
+ res =3D VG_(do_syscall2)(__NR_tkill, tid, signo);
+ if (res.isError && res.err =3D=3D VKI_ENOSYS)
+ res =3D VG_(do_syscall2)(__NR_kill, tid, signo);
return res.isError ? -1 : 0;
}
=20
=20
-Int VG_(kill)( Int pid, Int signo )
+/* A cut-down version of POSIX sigtimedwait: poll for pending signals
+ mentioned in the sigset_t, and if any are present, select one
+ arbitrarily, return its number (which must be > 0), and put
+ auxiliary info about it in the siginfo_t, and make it
+ not-pending-any-more. If none are pending, return zero. The _zero
+ refers to the fact that there is zero timeout, so if no signals are
+ pending it returns immediately. Perhaps a better name would be
+ 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
+ if signal n was selected.=20
+
+ The Linux implementation is trivial: do the corresponding syscall.
+
+ The AIX implementation is horrible and probably broken in a dozen
+ obscure ways. I suspect it's only thread-safe because V forces
+ single-threadedness. */
+
+#if defined(VGO_linux)
+Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,=20
+ vki_siginfo_t *info )
{
- SysRes res =3D VG_(do_syscall2)(__NR_kill, pid, signo);
- return res.isError ? -1 : 0;
+ static const struct vki_timespec zero =3D { 0, 0 };
+ SysRes res =3D VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UW=
ord)info,=20
+ (UWord)&zero, sizeof(*set));
+ return res.isError ? -1 : res.res;
}
=20
+#elif defined(VGO_aix5)
+/* The general idea is:
+ - use sigpending to find out which signals are pending
+ - choose one
+ - temporarily set its handler to sigtimedwait_zero_handler
+ - use sigsuspend atomically unblock it and wait for the signal.
+ Upon return, sigsuspend restores the signal mask to what it
+ was to start with.
+ - Restore the handler for the signal to whatever it was before.
+*/
=20
-Int VG_(tkill)( ThreadId tid, Int signo )
+/* A signal handler which does nothing (it doesn't need to). It does
+ however check that it's not handing a sync signal for which
+ returning is meaningless. */
+static void sigtimedwait_zero_handler ( Int sig )=20
+{=20
+ vg_assert(sig !=3D VKI_SIGILL);
+ vg_assert(sig !=3D VKI_SIGSEGV);
+ vg_assert(sig !=3D VKI_SIGBUS);
+ vg_assert(sig !=3D VKI_SIGTRAP);
+ /* do nothing */=20
+}
+
+Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,=20
+ vki_siginfo_t *info )
{
- SysRes res =3D VG_(mk_SysRes_Error)(VKI_ENOSYS);
+ Int i, ir;
+ SysRes sr;
+ vki_sigset_t pending, blocked, allbutone;
+ struct vki_sigaction sa, saved_sa;
=20
-#if 0
- /* This isn't right because the client may create a process
- structure with multiple thread groups */
- res =3D VG_(do_syscall3)(__NR_tgkill, VG_(getpid)(), tid, signo);
-#endif
+ /* Find out what's pending: AIX _sigpending */
+ sr =3D VG_(do_syscall1)(__NR__sigpending, (UWord)&pending);
+ vg_assert(!sr.isError);
=20
- res =3D VG_(do_syscall2)(__NR_tkill, tid, signo);
+ /* don't try for signals not in 'set' */
+ /* pending =3D pending `intersect` set */
+ for (i =3D 0; i < _VKI_NSIG_WORDS; i++)
+ pending.sig[i] &=3D set->sig[i];
=20
- if (res.isError && res.val =3D=3D VKI_ENOSYS)
- res =3D VG_(do_syscall2)(__NR_kill, tid, signo);
+ /* don't try for signals not blocked at the moment */
+ ir =3D VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
+ vg_assert(ir =3D=3D 0);
=20
- return res.isError ? -1 : 0;
+ /* pending =3D pending `intersect` blocked */
+ for (i =3D 0; i < _VKI_NSIG_WORDS; i++)
+ pending.sig[i] &=3D blocked.sig[i];
+
+ /* decide which signal we're going to snarf */
+ for (i =3D 1; i < _VKI_NSIG; i++)
+ if (VG_(sigismember)(&pending,i))
+ break;
+
+ if (i =3D=3D _VKI_NSIG)
+ return 0;
+
+ /* fetch signal i.
+ pre: i is blocked and pending
+ pre: we are the only thread running=20
+ */
+ /* Set up alternative signal handler */
+ VG_(sigfillset)(&allbutone);
+ VG_(sigdelset)(&allbutone, i);
+ sa.sa_mask =3D allbutone;
+ sa.ksa_handler =3D &sigtimedwait_zero_handler;
+ sa.sa_flags =3D 0;
+ ir =3D VG_(sigaction)(i, &sa, &saved_sa);
+ vg_assert(ir =3D=3D 0);
+
+ /* Switch signal masks and wait for the signal. This should happen
+ immediately, since we've already established it is pending and
+ blocked. */
+ sr =3D VG_(do_syscall1)(__NR__sigsuspend, (UWord)&allbutone);
+ vg_assert(sr.isError);
+ if (0)
+ VG_(debugLog)(0, "libcsignal",
+ "sigtimedwait_zero: sigsuspend got res %ld err %ld=
\n",=20
+ sr.res, sr.err);
+ vg_assert(sr.res =3D=3D (UWord)-1);
+
+ /* Restore signal's handler to whatever it was before */
+ ir =3D VG_(sigaction)(i, &saved_sa, NULL);
+ vg_assert(ir =3D=3D 0);
+
+ /* This is bogus - we could get more info from the sighandler. */
+ VG_(memset)( info, 0, sizeof(*info) );
+ info->si_signo =3D i;
+
+ return i;
}
=20
+#else
+# error Unknown OS
+#endif
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/pub_core_libcsignal.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_libcsignal.h 2006-10-17 01:30:07 UTC (rev 62=
58)
+++ trunk/coregrind/pub_core_libcsignal.h 2006-10-17 01:30:47 UTC (rev 62=
59)
@@ -65,14 +65,19 @@
const struct vki_sigaction* act,
struct vki_sigaction* oldact );
=20
-extern Int VG_(sigtimedwait)( const vki_sigset_t *, vki_siginfo_t *,=20
- const struct vki_timespec * );
-
-extern Int VG_(signal) ( Int signum, void (*sighandler)(Int) );
-
extern Int VG_(kill) ( Int pid, Int signo );
extern Int VG_(tkill) ( ThreadId tid, Int signo );
=20
+/* A cut-down version of POSIX sigtimedwait: poll for pending signals
+ mentioned in the sigset_t, and if any are present, select one
+ arbitrarily, return its number (which must be > 0), and put
+ auxiliary info about it in the siginfo_t, and make it
+ not-pending-any-more. If none are pending, return zero. The _zero
+ refers to the fact that there is zero timeout, so if no signals are
+ pending it returns immediately. Perhaps a better name would be
+ 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
+ if signal n was selected. */
+extern Int VG_(sigtimedwait_zero)( const vki_sigset_t *, vki_siginfo_t *=
);
=20
#endif // __PUB_CORE_LIBCSIGNAL_H
=20
|
|
From: <sv...@va...> - 2006-10-17 01:30:12
|
Author: sewardj
Date: 2006-10-17 02:30:07 +0100 (Tue, 17 Oct 2006)
New Revision: 6258
Log:
Merge r6119:
Changes to this interface to facilitate actions needed by AIX5.
Modified:
trunk/coregrind/pub_core_aspacemgr.h
trunk/include/pub_tool_aspacemgr.h
Modified: trunk/coregrind/pub_core_aspacemgr.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_aspacemgr.h 2006-10-17 01:28:48 UTC (rev 625=
7)
+++ trunk/coregrind/pub_core_aspacemgr.h 2006-10-17 01:30:07 UTC (rev 625=
8)
@@ -66,13 +66,14 @@
// Querying current status
=20
/* Finds the segment containing 'a'. Only returns file/anon/resvn
- segments. */
+ segments. This returns a 'NSegment const *' - a pointer to
+ readonly data. */
// Is in tool-visible header file.
-// extern NSegment* VG_(am_find_nsegment) ( Addr a );
+// extern NSegment const * VG_(am_find_nsegment) ( Addr a );
=20
/* Find the next segment along from 'here', if it is a file/anon/resvn
segment. */
-extern NSegment* VG_(am_next_nsegment) ( NSegment* here, Bool fwds );
+extern NSegment const* VG_(am_next_nsegment) ( NSegment* here, Bool fwds=
);
=20
/* Is the area [start .. start+len-1] validly accessible by the=20
client with at least the permissions 'prot' ? To find out
@@ -181,7 +182,6 @@
address range. */
extern Bool VG_(am_notify_munmap)( Addr start, SizeT len );
=20
-
/* Hand a raw mmap to the kernel, without aspacem updating the segment
array. THIS FUNCTION IS DANGEROUS -- it will cause aspacem's view
of the address space to diverge from that of the kernel. DO NOT
@@ -192,6 +192,51 @@
=20
=20
//--------------------------------------------------------------
+// Functions pertaining to AIX5-specific notifications.
+
+/* Describes followup actions that need to be done following a call to
+ VG_(am_aix5_reread_procmap). When acquire=3D=3DTrue, the specified
+ code and data segments have been mapped into the process, and so
+ m_debuginfo needs to read info for it; also m_redir needs to know,
+ and the tool needs to be told. When acquire=3D=3DFalse, the specifie=
d
+ segments have been unloaded and m_debuginfo, m_redir and the tool
+ (and m_transtab?) need to notified appropriately. */
+typedef
+ struct {
+ Addr code_start;
+ Word code_len;
+ Addr data_start;
+ Word data_len;
+ UChar* file_name;
+ UChar* mem_name;
+ Bool is_mainexe;
+ Bool acquire;
+ }
+ AixCodeSegChange;
+
+/* Tell aspacem that /proc/<pid>/map may have changed (eg following
+ __loadx) and so it should be re-read, and the code/data segment
+ list updated accordingly. The resulting array of AixCodeChangeSeg
+ directives are written to 'directives', and the number of entries
+ to *ndirectives. */
+extern void VG_(am_aix5_reread_procmap)
+ ( /*OUT*/AixCodeSegChange* directives, /*OUT*/Int* ndirectives );
+
+/* Find out the size of the AixCodeSegChange that must be
+ presented to VG_(am_aix5_reread_procmap). */
+extern Int VG_(am_aix5_reread_procmap_howmany_directives)(void);
+
+/* Tell aspacem where the initial client stack is, so that it
+ can later produce a faked-up NSegment in response to
+ VG_(am_find_nsegment) for athat address, if asked. */
+extern void VG_(am_aix5_set_initial_client_sp)( Addr );
+
+/* The AIX5 aspacem implementation needs to be told when it is and
+ isn't allowed to use sbrk to allocate memory. Hence: */
+extern Bool VG_(am_aix5_sbrk_allowed);
+
+
+//--------------------------------------------------------------
// Dealing with mappings which do not arise directly from the
// simulation of the client. These are typically used for
// loading the client and building its stack/data segment, before
@@ -209,15 +254,32 @@
extern SysRes VG_(am_mmap_anon_fixed_client)
( Addr start, SizeT length, UInt prot );
=20
+
/* Map anonymously at an unconstrained address for the client, and
update the segment array accordingly. */
extern SysRes VG_(am_mmap_anon_float_client) ( SizeT length, Int prot );
=20
+/* Similarly, acquire new address space for the client but with
+ considerable restrictions on what can be done with it: (1) the
+ actual protections may exceed those stated in 'prot', (2) the
+ area's protections cannot be later changed using any form of
+ mprotect, and (3) the area cannot be freed using any form of
+ munmap. On Linux this behaves the same as
+ VG_(am_mmap_anon_float_client). On AIX5 this *may* allocate memory
+ by using sbrk, so as to make use of large pages on AIX. */
+extern SysRes VG_(am_sbrk_anon_float_client) ( SizeT length, Int prot );
+
+
/* Map anonymously at an unconstrained address for V, and update the
segment array accordingly. This is fundamentally how V allocates
itself more address space when needed. */
extern SysRes VG_(am_mmap_anon_float_valgrind)( SizeT cszB );
=20
+/* Same comments apply as per VG_(am_sbrk_anon_float_client). On
+ Linux this behaves the same as VG_(am_mmap_anon_float_valgrind). */
+extern SysRes VG_(am_sbrk_anon_float_valgrind)( SizeT cszB );
+
+
/* Map a file at an unconstrained address for V, and update the
segment array accordingly. This is used by V for transiently
mapping in object files to read their debug info. */
@@ -238,6 +300,19 @@
suitable segment. */
extern Bool VG_(am_change_ownership_v_to_c)( Addr start, SizeT len );
=20
+/* 'seg' must be NULL or have been obtained from
+ VG_(am_find_nsegment), and still valid. If non-NULL, and if it
+ denotes a SkAnonC (anonymous client mapping) area, set the .isCH
+ (is-client-heap) flag for that area. Otherwise do nothing.
+ (Bizarre interface so that the same code works for both Linux and
+ AIX and does not impose inefficiencies on the Linux version.) */
+extern void VG_(am_set_segment_isCH_if_SkAnonC)( NSegment* seg );
+
+/* Same idea as VG_(am_set_segment_isCH_if_SkAnonC), except set the
+ segment's hasT bit (has-cached-code) if this is SkFileC or SkAnonC
+ segment. */
+extern void VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( NSegment* );
+
/* --- --- --- reservations --- --- --- */
=20
/* Create a reservation from START .. START+LENGTH-1, with the given
Modified: trunk/include/pub_tool_aspacemgr.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/include/pub_tool_aspacemgr.h 2006-10-17 01:28:48 UTC (rev 6257)
+++ trunk/include/pub_tool_aspacemgr.h 2006-10-17 01:30:07 UTC (rev 6258)
@@ -134,7 +134,7 @@
=20
=20
// See pub_core_aspacemgr.h for description.
-extern NSegment* VG_(am_find_nsegment) ( Addr a );=20
+extern NSegment const * VG_(am_find_nsegment) ( Addr a );=20
=20
// See pub_core_aspacemgr.h for description.
extern HChar* VG_(am_get_filename)( NSegment* );
|
|
From: <sv...@va...> - 2006-10-17 01:28:51
|
Author: sewardj
Date: 2006-10-17 02:28:48 +0100 (Tue, 17 Oct 2006)
New Revision: 6257
Log:
Merge r6113:
Various minor changes to make these compile on AIX5.
Modified:
trunk/none/tests/async-sigs.c
trunk/none/tests/blockfault.c
trunk/none/tests/fdleak_cmsg.c
trunk/none/tests/mq.c
trunk/none/tests/mremap.c
trunk/none/tests/mremap2.c
trunk/none/tests/pth_atfork1.c
trunk/none/tests/pth_cancel1.c
trunk/none/tests/sigstackgrowth.c
trunk/none/tests/susphello.c
trunk/none/tests/threaded-fork.c
trunk/none/tests/threadederrno.c
trunk/none/tests/threadederrno.stdout.exp
Modified: trunk/none/tests/async-sigs.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/async-sigs.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/async-sigs.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -72,6 +72,7 @@
}
=20
if (pid =3D=3D 0) {
+ alarm(10); /* if something breaks, don't spin forever */
signal(caughtsig, handler);
=20
for(;;)
Modified: trunk/none/tests/blockfault.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/blockfault.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/blockfault.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -13,6 +13,10 @@
the default handler */
int main()
{
+#if defined(_AIX)
+ printf("this test hangs when run (even natively) on AIX\n");
+ return 0;
+#endif
struct sigaction sa;
sigset_t mask;
=20
@@ -25,7 +29,7 @@
sigfillset(&mask);
sigprocmask(SIG_BLOCK, &mask, NULL);
=20
- *(volatile int *)1234 =3D 213;
+ *(volatile int *)12345 =3D 213;
=20
return 0;
}
Modified: trunk/none/tests/fdleak_cmsg.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/fdleak_cmsg.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/fdleak_cmsg.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -1,6 +1,26 @@
+
+/* On AIX 5.2, _LINUX_SOURCE_COMPAT needs to be defined when reading
+ sys/socket.h in order to make CMSG_SPACE and CMSG_LEN visible. */
+
+#if defined(_AIX)
+#define _LINUX_SOURCE_COMPAT 1
+#endif
+
+#include <sys/socket.h>
+
+#if defined(_AIX)
+#undef _LINUX_SOURCE_COMPAT
+#endif
+
+
+/* Needed for 'memset' on AIX 5.2 */
+#if defined(_AIX)
+# include <memory.h>
+#endif
+
+
#include <sys/types.h>
#include <sys/wait.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <fcntl.h>
@@ -8,12 +28,13 @@
#include <stdlib.h>
#include <errno.h>
=20
+
char filea[24];
char fileb[24];
char sock[24];
=20
void
-server ()
+server (void)
{
int s, fd1, fd2;
struct sockaddr_un addr;
@@ -90,7 +111,7 @@
}
=20
void
-client ()
+client (void)
{
int s, fd1 =3D -1, fd2 =3D -1, size, count =3D 0, ret;
struct sockaddr_un addr;
Modified: trunk/none/tests/mq.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/mq.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/mq.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <fcntl.h>
=20
#ifdef HAVE_MQUEUE_H
=20
Modified: trunk/none/tests/mremap.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/mremap.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/mremap.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -3,6 +3,16 @@
#include <stdio.h>
#include <stdlib.h>
=20
+#if defined(_AIX)
+
+int main ( void )
+{
+ printf("This test is Linux-specific.\n");
+ return 0;
+}
+
+#else
+
static char *mkmap(unsigned sz)
{
static char *map;
@@ -96,3 +106,5 @@
=20
return 0;
}
+
+#endif /* defined(_AIX) */
Modified: trunk/none/tests/mremap2.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/mremap2.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/mremap2.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -1,6 +1,17 @@
#define _GNU_SOURCE
=20
#include <stdio.h>
+
+#if defined(_AIX)
+
+int main ( void )
+{
+ printf("This test is Linux-specific.\n");
+ return 0;
+}
+
+#else
+
#include <sys/mman.h>
#include <assert.h>
#include <stdlib.h>
@@ -161,3 +172,5 @@
}
return 0;
}
+
+#endif /* defined(_AIX5) */
Modified: trunk/none/tests/pth_atfork1.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/pth_atfork1.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/pth_atfork1.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -18,13 +18,28 @@
Boston, MA 02111-1307, USA. */
=20
#include <errno.h>
-#include <error.h>
+#if !defined(_AIX)
+# include <error.h>
+#endif
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
=20
+#if defined(_AIX)
+#include <string.h> /* strerror */
+static void error (int status, int errnum, char* msg)
+{
+ fprintf(stderr, "%s%s%s\n",
+ msg,
+ errnum ? ": " : "",
+ errnum ? strerror(errnum) : "");
+ if (errnum)
+ exit(errnum);
+}
+#endif
+
enum
{
PREPARE_BIT =3D 1,
Modified: trunk/none/tests/pth_cancel1.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/pth_cancel1.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/pth_cancel1.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -5,7 +5,7 @@
=20
static void thread_cleanup(void *arg)
{
- printf("cleaning up %p\n", arg);
+ printf("cleaning up 0x%lx\n", (long)arg);
=20
return;
}
Modified: trunk/none/tests/sigstackgrowth.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/sigstackgrowth.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/sigstackgrowth.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -4,6 +4,10 @@
#include <sys/types.h>
#include <unistd.h>
=20
+#if defined(_AIX) && !defined(SA_NOMASK)
+# define SA_NOMASK 0
+#endif
+
static char *deep;
=20
#define SIZE (4*1024*1024)
Modified: trunk/none/tests/susphello.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/susphello.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/susphello.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -18,7 +18,6 @@
#include <string.h>
#include <sys/resource.h>
#include <unistd.h>
-#include <sys/syscall.h>
#include <dlfcn.h>
=20
=20
@@ -132,7 +131,12 @@
sa.sa_flags =3D SA_RESTART | SA_SIGINFO | SA_ONSTACK;
sa.sa_sigaction =3D ptiSrSigHandler;
sigfillset(&sa.sa_mask);
+
+# if !defined(_AIX)
+ /* jrs 20060615: is this important? I don't know. */
sigdelset(&sa.sa_mask, (__SIGRTMIN+1));
+# endif
+
if (sigaction(srSignal, &sa, 0) =3D=3D -1) {
perror("sigaction");
exit(1);
@@ -163,7 +167,11 @@
}
=20
void takedown_altstack(void* stack) {
+# if defined(_AIX)
+ stack_t ss;
+# else
struct sigaltstack ss;
+# endif
int result;
=20
ss.ss_flags =3D SS_DISABLE;
Modified: trunk/none/tests/threaded-fork.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/threaded-fork.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/threaded-fork.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -14,6 +14,7 @@
=20
int main( int argc, char **argv )
{
+ int ctr;
pid_t childpid;
pthread_t childthread;
void *res;
@@ -36,8 +37,15 @@
}
=20
pthread_join( childthread, &res );
- while(waitpid(childpid, &status, 0) !=3D childpid)
- ;
+ ctr =3D 0;
+ while(waitpid(childpid, &status, 0) !=3D childpid) {
+ sleep(1);
+ ctr++;
+ if (ctr >=3D 10) {
+ printf("FAILED - timeout waiting for child\n");
+ return 0;
+ }
+ }
=20
printf("PASS\n");
=20
Modified: trunk/none/tests/threadederrno.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/threadederrno.c 2006-10-17 01:28:10 UTC (rev 6256)
+++ trunk/none/tests/threadederrno.c 2006-10-17 01:28:48 UTC (rev 6257)
@@ -8,14 +8,14 @@
void* thr2 ( void* v )
{
FILE* f =3D fopen("bogus2", "r");
- printf("f =3D %p, errno =3D %d (%s)\n", f, errno, strerror(errno));
+ printf("f =3D %ld, errno =3D %d (%s)\n", (long)f, errno, strerror(er=
rno));
return NULL;
}
=20
void* thr3 ( void* v )
{
FILE* f =3D fopen("bogus3", "r");
- printf("f =3D %p, errno =3D %d (%s)\n", f, errno, strerror(errno));
+ printf("f =3D %ld, errno =3D %d (%s)\n", (long)f, errno, strerror(er=
rno));
return NULL;
}
=20
@@ -27,7 +27,7 @@
pthread_create(&tid2, NULL, &thr2, NULL);
pthread_create(&tid3, NULL, &thr3, NULL);
f =3D fopen("bogus", "r");
- printf("f =3D %p, errno =3D %d (%s)\n", f, errno, strerror(errno));
+ printf("f =3D %ld, errno =3D %d (%s)\n", (long)f, errno, strerror(er=
rno));
pthread_join(tid2, NULL);
pthread_join(tid3, NULL);
return 0;
Modified: trunk/none/tests/threadederrno.stdout.exp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/none/tests/threadederrno.stdout.exp 2006-10-17 01:28:10 UTC (re=
v 6256)
+++ trunk/none/tests/threadederrno.stdout.exp 2006-10-17 01:28:48 UTC (re=
v 6257)
@@ -1,3 +1,3 @@
-f =3D (nil), errno =3D 2 (No such file or directory)
-f =3D (nil), errno =3D 2 (No such file or directory)
-f =3D (nil), errno =3D 2 (No such file or directory)
+f =3D 0, errno =3D 2 (No such file or directory)
+f =3D 0, errno =3D 2 (No such file or directory)
+f =3D 0, errno =3D 2 (No such file or directory)
|
|
From: <sv...@va...> - 2006-10-17 01:28:14
|
Author: sewardj
Date: 2006-10-17 02:28:10 +0100 (Tue, 17 Oct 2006)
New Revision: 6256
Log:
Merge r6112:
Changes resulting from porting to AIX5:
- Auxiliary primary map handling has been redone, so that the
performance penalty for hitting memory above the magic 32G limit is
much reduced, and also the number of usable maps is limited only by
how much memory is available. The current code has been tested on
64-bit AIX for processes up to about 8GB in size.
The auxiliary primary maps are now stored in an OSet, "auxmap_L2".
However, looking up in an OSet for each memory reference is
expensive. So the OSet is 'fronted' by 24-entry array which holds
pointers to the 24 most recently used auxiliary primary maps.
Accesses to this array are made faster by incrementally rearranging
it on every lookup (if the requested map is found in the array, it
is moved one element closer to the start of the array).
Logically speaking, auxmap_L1 is a cache of auxmap_L2. The L2-L1
relationship is one of inclusion; iow L2 is not a victim cache.
There is extensive new sanity check code for these structures.
- Along with the auxmap changes are semi-fast cases in mc_LOADVn_slow
and mc_STOREVn_slow. These catch naturally aligned, word-size loads
which fall into addressible memory, and handle them directly rather
than in a byte-by-byte fashion.
- Fix longstanding error with alignment checks in
{new,die}_mem_stack_N. Previously, these checked the alignment of
the new SP value without taking the stack redzone size into account.
This is only safe if the redzone size is 8-aligned. The right thing
to do is check alignment after adding on the redzone size.
- Add a new mechanism which allows specification, on the command line,
of address ranges which memcheck is to 'ignore'. Meaning that it
regards all writes to those ranges as acceptable and all reads from
those ranges as acceptable and returning initialised data. This is
done without disturbing the existing finally-balanced bitmap=20
machinery. Instead, in mc_record_address_error, just ignore the
error if the address falls inside an ignored-range.
There is a new command-line flag --ignore-ranges=3D to specify
the address ranges. Currently up to 4 non-overlapping ranges may
be specified.
This kind of thing is useful if you want to do some strange thing
like map a high-performance network card into memory and can't be
bothered to tell memcheck about it through the official channels
(intercepting syscalls/ioctls and telling aspacem about them.)
Modified:
trunk/memcheck/mc_main.c
Modified: trunk/memcheck/mc_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mc_main.c 2006-10-17 01:27:13 UTC (rev 6255)
+++ trunk/memcheck/mc_main.c 2006-10-17 01:28:10 UTC (rev 6256)
@@ -43,6 +43,7 @@
#include "pub_tool_replacemalloc.h"
#include "pub_tool_tooliface.h"
#include "pub_tool_threadstate.h"
+#include "pub_tool_oset.h"
=20
#include "mc_include.h"
#include "memcheck.h" /* for client requests */
@@ -305,8 +306,14 @@
static Int max_defined_SMs =3D 0;
static Int max_non_DSM_SMs =3D 0;
=20
-static ULong n_auxmap_searches =3D 0;
-static ULong n_auxmap_cmps =3D 0;
+/* # searches initiated in auxmap_L1, and # base cmps required */
+static ULong n_auxmap_L1_searches =3D 0;
+static ULong n_auxmap_L1_cmps =3D 0;
+/* # of searches that missed in auxmap_L1 and therefore had to
+ be handed to auxmap_L2. And the number of nodes inserted. */
+static ULong n_auxmap_L2_searches =3D 0;
+static ULong n_auxmap_L2_nodes =3D 0;
+
static Int n_sanity_cheap =3D 0;
static Int n_sanity_expensive =3D 0;
=20
@@ -345,7 +352,8 @@
/* An entry in the auxiliary primary map. base must be a 64k-aligned
value, and sm points at the relevant secondary map. As with the
main primary map, the secondary may be either a real secondary, or
- one of the three distinguished secondaries.
+ one of the three distinguished secondaries. DO NOT CHANGE THIS
+ LAYOUT: the first word has to be the key for OSet fast lookups.
*/
typedef
struct {=20
@@ -354,83 +362,215 @@
}
AuxMapEnt;
=20
-/* An expanding array of AuxMapEnts. */
-#define N_AUXMAPS 20000 /* HACK */
-static AuxMapEnt hacky_auxmaps[N_AUXMAPS];
-static Int auxmap_size =3D N_AUXMAPS;
-static Int auxmap_used =3D 0;
-static AuxMapEnt* auxmap =3D &hacky_auxmaps[0];
+/* Tunable parameter: How big is the L1 queue? */
+#define N_AUXMAP_L1 24
=20
+/* Tunable parameter: How far along the L1 queue to insert
+ entries resulting from L2 lookups? */
+#define AUXMAP_L1_INSERT_IX 12
=20
-/* Find an entry in the auxiliary map. If an entry is found, move it
- one step closer to the front of the array, then return its address.
- If an entry is not found, return NULL. Note carefully that
- because a each call potentially rearranges the entries, each call
- to this function invalidates ALL AuxMapEnt*s previously obtained by
- calling this fn. =20
-*/
-static AuxMapEnt* maybe_find_in_auxmap ( Addr a )
+static struct {
+ Addr base;
+ AuxMapEnt* ent; // pointer to the matching auxmap_L2 node
+ }=20
+ auxmap_L1[N_AUXMAP_L1];
+
+static OSet* auxmap_L2 =3D NULL;
+
+static void init_auxmap_L1_L2 ( void )
{
- UWord i;
+ Int i;
+ for (i =3D 0; i < N_AUXMAP_L1; i++) {
+ auxmap_L1[i].base =3D 0;
+ auxmap_L1[i].ent =3D NULL;
+ }
+
+ tl_assert(0 =3D=3D offsetof(AuxMapEnt,base));
+ tl_assert(sizeof(Addr) =3D=3D sizeof(void*));
+ auxmap_L2 =3D VG_(OSet_Create)( /*keyOff*/ offsetof(AuxMapEnt,base),
+ /*fastCmp*/ NULL,
+ VG_(malloc), VG_(free) );
+}
+
+/* Check representation invariants; if OK return NULL; else a
+ descriptive bit of text. Also return the number of
+ non-distinguished secondary maps referred to from the auxiliary
+ primary maps. */
+
+static HChar* check_auxmap_L1_L2_sanity ( Word* n_secmaps_found )
+{
+ Word i, j;
+ /* On a 32-bit platform, the L2 and L1 tables should
+ both remain empty forever.
+
+ On a 64-bit platform:
+ In the L2 table:
+ all .base & 0xFFFF =3D=3D 0
+ all .base > MAX_PRIMARY_ADDRESS
+ In the L1 table:
+ all .base & 0xFFFF =3D=3D 0
+ all (.base > MAX_PRIMARY_ADDRESS
+ .base & 0xFFFF =3D=3D 0
+ and .ent points to an AuxMapEnt with the same .base)
+ or
+ (.base =3D=3D 0 and .ent =3D=3D NULL)
+ */
+ *n_secmaps_found =3D 0;
+ if (sizeof(void*) =3D=3D 4) {
+ /* 32-bit platform */
+ if (VG_(OSet_Size)(auxmap_L2) !=3D 0)
+ return "32-bit: auxmap_L2 is non-empty";
+ for (i =3D 0; i < N_AUXMAP_L1; i++)=20
+ if (auxmap_L1[i].base !=3D 0 || auxmap_L1[i].ent !=3D NULL)
+ return "32-bit: auxmap_L1 is non-empty";
+ } else {
+ /* 64-bit platform */
+ UWord elems_seen =3D 0;
+ AuxMapEnt *elem, *res;
+ AuxMapEnt key;
+ /* L2 table */
+ VG_(OSet_ResetIter)(auxmap_L2);
+ while ( (elem =3D VG_(OSet_Next)(auxmap_L2)) ) {
+ elems_seen++;
+ if (0 !=3D (elem->base & (Addr)0xFFFF))
+ return "64-bit: nonzero .base & 0xFFFF in auxmap_L2";
+ if (elem->base <=3D MAX_PRIMARY_ADDRESS)
+ return "64-bit: .base <=3D MAX_PRIMARY_ADDRESS in auxmap_L2"=
;
+ if (elem->sm =3D=3D NULL)
+ return "64-bit: .sm in _L2 is NULL";
+ if (!is_distinguished_sm(elem->sm))
+ (*n_secmaps_found)++;
+ }
+ if (elems_seen !=3D n_auxmap_L2_nodes)
+ return "64-bit: disagreement on number of elems in _L2";
+ /* Check L1-L2 correspondence */
+ for (i =3D 0; i < N_AUXMAP_L1; i++) {
+ if (auxmap_L1[i].base =3D=3D 0 && auxmap_L1[i].ent =3D=3D NULL)
+ continue;
+ if (0 !=3D (auxmap_L1[i].base & (Addr)0xFFFF))
+ return "64-bit: nonzero .base & 0xFFFF in auxmap_L1";
+ if (auxmap_L1[i].base <=3D MAX_PRIMARY_ADDRESS)
+ return "64-bit: .base <=3D MAX_PRIMARY_ADDRESS in auxmap_L1"=
;
+ if (auxmap_L1[i].ent =3D=3D NULL)
+ return "64-bit: .ent is NULL in auxmap_L1";
+ if (auxmap_L1[i].ent->base !=3D auxmap_L1[i].base)
+ return "64-bit: _L1 and _L2 bases are inconsistent";
+ /* Look it up in auxmap_L2. */
+ key.base =3D auxmap_L1[i].base;
+ key.sm =3D 0;
+ res =3D VG_(OSet_Lookup)(auxmap_L2, &key);
+ if (res =3D=3D NULL)
+ return "64-bit: _L1 .base not found in _L2";
+ if (res !=3D auxmap_L1[i].ent)
+ return "64-bit: _L1 .ent disagrees with _L2 entry";
+ }
+ /* Check L1 contains no duplicates */
+ for (i =3D 0; i < N_AUXMAP_L1; i++) {
+ if (auxmap_L1[i].base =3D=3D 0)
+ continue;
+ for (j =3D i+1; j < N_AUXMAP_L1; j++) {
+ if (auxmap_L1[j].base =3D=3D 0)
+ continue;
+ if (auxmap_L1[j].base =3D=3D auxmap_L1[i].base)
+ return "64-bit: duplicate _L1 .base entries";
+ }
+ }
+ }
+ return NULL; /* ok */
+}
+
+static void insert_into_auxmap_L1_at ( Word rank, AuxMapEnt* ent )
+{
+ Word i;
+ tl_assert(ent);
+ tl_assert(rank >=3D 0 && rank < N_AUXMAP_L1);
+ for (i =3D N_AUXMAP_L1-1; i > rank; i--)
+ auxmap_L1[i] =3D auxmap_L1[i-1];
+ auxmap_L1[rank].base =3D ent->base;
+ auxmap_L1[rank].ent =3D ent;
+}
+
+static INLINE AuxMapEnt* maybe_find_in_auxmap ( Addr a )
+{
+ AuxMapEnt key;
+ AuxMapEnt* res;
+ Word i;
+
tl_assert(a > MAX_PRIMARY_ADDRESS);
-
a &=3D ~(Addr)0xFFFF;
=20
- /* Search .. */
- n_auxmap_searches++;
- for (i =3D 0; i < auxmap_used; i++) {
- if (auxmap[i].base =3D=3D a)
+ /* First search the front-cache, which is a self-organising
+ list containing the most popular entries. */
+
+ if (EXPECTED_TAKEN(auxmap_L1[0].base =3D=3D a))
+ return auxmap_L1[0].ent;
+ if (EXPECTED_TAKEN(auxmap_L1[1].base =3D=3D a)) {
+ Addr t_base =3D auxmap_L1[0].base;
+ AuxMapEnt* t_ent =3D auxmap_L1[0].ent;
+ auxmap_L1[0].base =3D auxmap_L1[1].base;
+ auxmap_L1[0].ent =3D auxmap_L1[1].ent;
+ auxmap_L1[1].base =3D t_base;
+ auxmap_L1[1].ent =3D t_ent;
+ return auxmap_L1[0].ent;
+ }
+
+ n_auxmap_L1_searches++;
+
+ for (i =3D 0; i < N_AUXMAP_L1; i++) {
+ if (auxmap_L1[i].base =3D=3D a) {
break;
+ }
}
- n_auxmap_cmps +=3D (ULong)(i+1);
+ tl_assert(i >=3D 0 && i <=3D N_AUXMAP_L1);
=20
- if (i < auxmap_used) {
- /* Found it. Nudge it a bit closer to the front. */
+ n_auxmap_L1_cmps +=3D (ULong)(i+1);
+
+ if (i < N_AUXMAP_L1) {
if (i > 0) {
- AuxMapEnt tmp =3D auxmap[i-1];
- auxmap[i-1] =3D auxmap[i];
- auxmap[i] =3D tmp;
+ Addr t_base =3D auxmap_L1[i-1].base;
+ AuxMapEnt* t_ent =3D auxmap_L1[i-1].ent;
+ auxmap_L1[i-1].base =3D auxmap_L1[i-0].base;
+ auxmap_L1[i-1].ent =3D auxmap_L1[i-0].ent;
+ auxmap_L1[i-0].base =3D t_base;
+ auxmap_L1[i-0].ent =3D t_ent;
i--;
}
- return &auxmap[i];
+ return auxmap_L1[i].ent;
}
=20
- return NULL;
+ n_auxmap_L2_searches++;
+
+ /* First see if we already have it. */
+ key.base =3D a;
+ key.sm =3D 0;
+
+ res =3D VG_(OSet_Lookup)(auxmap_L2, &key);
+ if (res)
+ insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, res );
+ return res;
}
=20
-
-/* Find an entry in the auxiliary map. If an entry is found, move it
- one step closer to the front of the array, then return its address.
- If an entry is not found, allocate one. Note carefully that
- because a each call potentially rearranges the entries, each call
- to this function invalidates ALL AuxMapEnt*s previously obtained by
- calling this fn. =20
-*/
static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
{
- AuxMapEnt* am =3D maybe_find_in_auxmap(a);
- if (am)
- return am;
+ AuxMapEnt *nyu, *res;
=20
- /* We didn't find it. Hmm. This is a new piece of address space.
- We'll need to allocate a new AuxMap entry for it. */
- if (auxmap_used >=3D auxmap_size) {
- tl_assert(auxmap_used =3D=3D auxmap_size);
- /* Out of auxmap entries. */
- tl_assert2(0, "failed to expand the auxmap table");
- }
+ /* First see if we already have it. */
+ res =3D maybe_find_in_auxmap( a );
+ if (EXPECTED_TAKEN(res))
+ return res;
=20
- tl_assert(auxmap_used < auxmap_size);
+ /* Ok, there's no entry in the secondary map, so we'll have
+ to allocate one. */
+ a &=3D ~(Addr)0xFFFF;
=20
- auxmap[auxmap_used].base =3D a & ~(Addr)0xFFFF;
- auxmap[auxmap_used].sm =3D &sm_distinguished[SM_DIST_NOACCESS];
-
- if (0)
- VG_(printf)("new auxmap, base =3D 0x%llx\n",=20
- (ULong)auxmap[auxmap_used].base );
-
- auxmap_used++;
- return &auxmap[auxmap_used-1];
+ nyu =3D (AuxMapEnt*) VG_(OSet_AllocNode)( auxmap_L2, sizeof(AuxMapEnt=
) );
+ tl_assert(nyu);
+ nyu->base =3D a;
+ nyu->sm =3D &sm_distinguished[SM_DIST_NOACCESS];
+ VG_(OSet_Insert)( auxmap_L2, nyu );
+ insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, nyu );
+ n_auxmap_L2_nodes++;
+ return nyu;
}
=20
/* --------------- SecMap fundamentals --------------- */
@@ -491,7 +631,7 @@
secmap may be a distinguished one as the caller will only want to
be able to read it.=20
*/
-static SecMap* get_secmap_for_reading ( Addr a )
+static INLINE SecMap* get_secmap_for_reading ( Addr a )
{
return ( a <=3D MAX_PRIMARY_ADDRESS
? get_secmap_for_reading_low (a)
@@ -870,6 +1010,129 @@
return bigendian ? (wordszB-1-byteno) : byteno;
}
=20
+
+/* --------------- Ignored address ranges --------------- */
+
+#define M_IGNORE_RANGES 4
+
+typedef
+ struct {
+ Int used;
+ Addr start[M_IGNORE_RANGES];
+ Addr end[M_IGNORE_RANGES];
+ }
+ IgnoreRanges;
+
+static IgnoreRanges ignoreRanges;
+
+static INLINE Bool in_ignored_range ( Addr a )
+{
+ Int i;
+ if (EXPECTED_TAKEN(ignoreRanges.used =3D=3D 0))
+ return False;
+ for (i =3D 0; i < ignoreRanges.used; i++) {
+ if (a >=3D ignoreRanges.start[i] && a < ignoreRanges.end[i])
+ return True;
+ }
+ return False;
+}
+
+
+/* Parse a 32- or 64-bit hex number, including leading 0x, from string
+ starting at *ppc, putting result in *result, and return True. Or
+ fail, in which case *ppc and *result are undefined, and return
+ False. */
+
+static Bool isHex ( UChar c )
+{
+ return ((c >=3D '0' && c <=3D '9')
+ || (c >=3D 'a' && c <=3D 'f')
+ || (c >=3D 'A' && c <=3D 'F'));
+}
+
+static UInt fromHex ( UChar c )
+{
+ if (c >=3D '0' && c <=3D '9')
+ return (UInt)c - (UInt)'0';
+ if (c >=3D 'a' && c <=3D 'f')
+ return 10 + (UInt)c - (UInt)'a';
+ if (c >=3D 'A' && c <=3D 'F')
+ return 10 + (UInt)c - (UInt)'A';
+ /*NOTREACHED*/
+ tl_assert(0);
+ return 0;
+}
+
+static Bool parse_Addr ( UChar** ppc, Addr* result )
+{
+ Int used, limit =3D 2 * sizeof(Addr);
+ if (**ppc !=3D '0')
+ return False;
+ (*ppc)++;
+ if (**ppc !=3D 'x')
+ return False;
+ (*ppc)++;
+ *result =3D 0;
+ used =3D 0;
+ while (isHex(**ppc)) {
+ UInt d =3D fromHex(**ppc);
+ tl_assert(d < 16);
+ *result =3D ((*result) << 4) | fromHex(**ppc);
+ (*ppc)++;
+ used++;
+ if (used > limit) return False;
+ }
+ if (used =3D=3D 0)
+ return False;
+ return True;
+}
+
+/* Parse two such numbers separated by a dash, or fail. */
+
+static Bool parse_range ( UChar** ppc, Addr* result1, Addr* result2 )
+{
+ Bool ok =3D parse_Addr(ppc, result1);
+ if (!ok)
+ return False;
+ if (**ppc !=3D '-')
+ return False;
+ (*ppc)++;
+ ok =3D parse_Addr(ppc, result2);
+ if (!ok)
+ return False;
+ return True;
+}
+
+/* Parse a set of ranges separated by commas into 'ignoreRanges', or
+ fail. */
+
+static Bool parse_ignore_ranges ( UChar* str0 )
+{
+ Addr start, end;
+ Bool ok;
+ UChar* str =3D str0;
+ UChar** ppc =3D &str;
+ ignoreRanges.used =3D 0;
+ while (1) {
+ ok =3D parse_range(ppc, &start, &end);
+ if (!ok)
+ return False;
+ if (ignoreRanges.used >=3D M_IGNORE_RANGES)
+ return False;
+ ignoreRanges.start[ignoreRanges.used] =3D start;
+ ignoreRanges.end[ignoreRanges.used] =3D end;
+ ignoreRanges.used++;
+ if (**ppc =3D=3D 0)
+ return True;
+ if (**ppc !=3D ',')
+ return False;
+ (*ppc)++;
+ }
+ /*NOTREACHED*/
+ return False;
+}
+
+
/* --------------- Load/store slow cases. --------------- */
=20
// Forward declarations
@@ -900,6 +1163,39 @@
Bool ok;
=20
PROF_EVENT(30, "mc_LOADVn_slow");
+
+ /* ------------ BEGIN semi-fast cases ------------ */
+ /* These deal quickly-ish with the common auxiliary primary map
+ cases on 64-bit platforms. Are merely a speedup hack; can be
+ omitted without loss of correctness/functionality. Note that in
+ both cases the "sizeof(void*) =3D=3D 8" causes these cases to be
+ folded out by compilers on 32-bit platforms. These are derived
+ from LOADV64 and LOADV32.
+ */
+ if (EXPECTED_TAKEN(sizeof(void*) =3D=3D 8=20
+ && nBits =3D=3D 64 && VG_IS_8_ALIGNED(a))) {
+ SecMap* sm =3D get_secmap_for_reading(a);
+ UWord sm_off16 =3D SM_OFF_16(a);
+ UWord vabits16 =3D ((UShort*)(sm->vabits8))[sm_off16];
+ if (EXPECTED_TAKEN(vabits16 =3D=3D VA_BITS16_DEFINED))
+ return V_BITS64_DEFINED;
+ if (EXPECTED_TAKEN(vabits16 =3D=3D VA_BITS16_UNDEFINED))
+ return V_BITS64_UNDEFINED;
+ /* else fall into the slow case */
+ }
+ if (EXPECTED_TAKEN(sizeof(void*) =3D=3D 8=20
+ && nBits =3D=3D 32 && VG_IS_4_ALIGNED(a))) {
+ SecMap* sm =3D get_secmap_for_reading(a);
+ UWord sm_off =3D SM_OFF(a);
+ UWord vabits8 =3D sm->vabits8[sm_off];
+ if (EXPECTED_TAKEN(vabits8 =3D=3D VA_BITS8_DEFINED))
+ return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_DEFINED)=
;
+ if (EXPECTED_TAKEN(vabits8 =3D=3D VA_BITS8_UNDEFINED))
+ return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_UNDEFINE=
D);
+ /* else fall into slow case */
+ }
+ /* ------------ END semi-fast cases ------------ */
+
tl_assert(nBits =3D=3D 64 || nBits =3D=3D 32 || nBits =3D=3D 16 || nB=
its =3D=3D 8);
=20
for (i =3D szB-1; i >=3D 0; i--) {
@@ -949,6 +1245,61 @@
Bool ok;
=20
PROF_EVENT(35, "mc_STOREVn_slow");
+
+ /* ------------ BEGIN semi-fast cases ------------ */
+ /* These deal quickly-ish with the common auxiliary primary map
+ cases on 64-bit platforms. Are merely a speedup hack; can be
+ omitted without loss of correctness/functionality. Note that in
+ both cases the "sizeof(void*) =3D=3D 8" causes these cases to be
+ folded out by compilers on 32-bit platforms. These are derived
+ from STOREV64 and STOREV32.
+ */
+ if (EXPECTED_TAKEN(sizeof(void*) =3D=3D 8=20
+ && nBits =3D=3D 64 && VG_IS_8_ALIGNED(a))) {
+ SecMap* sm =3D get_secmap_for_reading(a);
+ UWord sm_off16 =3D SM_OFF_16(a);
+ UWord vabits16 =3D ((UShort*)(sm->vabits8))[sm_off16];
+ if (EXPECTED_TAKEN( !is_distinguished_sm(sm) &&=20
+ (VA_BITS16_DEFINED =3D=3D vabits16 ||
+ VA_BITS16_UNDEFINED =3D=3D vabits16) )) {
+ /* Handle common case quickly: a is suitably aligned, */
+ /* is mapped, and is addressible. */
+ // Convert full V-bits in register to compact 2-bit form.
+ if (EXPECTED_TAKEN(V_BITS64_DEFINED =3D=3D vbytes)) {
+ ((UShort*)(sm->vabits8))[sm_off16] =3D (UShort)VA_BITS16_DEF=
INED;
+ return;
+ } else if (V_BITS64_UNDEFINED =3D=3D vbytes) {
+ ((UShort*)(sm->vabits8))[sm_off16] =3D (UShort)VA_BITS16_UND=
EFINED;
+ return;
+ }
+ /* else fall into the slow case */
+ }
+ /* else fall into the slow case */
+ }
+ if (EXPECTED_TAKEN(sizeof(void*) =3D=3D 8
+ && nBits =3D=3D 32 && VG_IS_4_ALIGNED(a))) {
+ SecMap* sm =3D get_secmap_for_reading(a);
+ UWord sm_off =3D SM_OFF(a);
+ UWord vabits8 =3D sm->vabits8[sm_off];
+ if (EXPECTED_TAKEN( !is_distinguished_sm(sm) &&=20
+ (VA_BITS8_DEFINED =3D=3D vabits8 ||
+ VA_BITS8_UNDEFINED =3D=3D vabits8) )) {
+ /* Handle common case quickly: a is suitably aligned, */
+ /* is mapped, and is addressible. */
+ // Convert full V-bits in register to compact 2-bit form.
+ if (EXPECTED_TAKEN(V_BITS32_DEFINED =3D=3D (vbytes & 0xFFFFFFFF=
))) {
+ sm->vabits8[sm_off] =3D VA_BITS8_DEFINED;
+ return;
+ } else if (V_BITS32_UNDEFINED =3D=3D (vbytes & 0xFFFFFFFF)) {
+ sm->vabits8[sm_off] =3D VA_BITS8_UNDEFINED;
+ return;
+ }
+ /* else fall into the slow case */
+ }
+ /* else fall into the slow case */
+ }
+ /* ------------ END semi-fast cases ------------ */
+
tl_assert(nBits =3D=3D 64 || nBits =3D=3D 32 || nBits =3D=3D 16 || nB=
its =3D=3D 8);
=20
/* Dump vbytes in memory, iterating from least to most significant
@@ -1433,7 +1784,7 @@
static void VG_REGPARM(1) mc_new_mem_stack_4(Addr new_SP)
{
PROF_EVENT(110, "new_mem_stack_4");
- if (VG_IS_4_ALIGNED(new_SP)) {
+ if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
} else {
MC_(make_mem_undefined) ( -VG_STACK_REDZONE_SZB + new_SP, 4 );
@@ -1443,7 +1794,7 @@
static void VG_REGPARM(1) mc_die_mem_stack_4(Addr new_SP)
{
PROF_EVENT(120, "die_mem_stack_4");
- if (VG_IS_4_ALIGNED(new_SP)) {
+ if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
} else {
MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-4, 4 );
@@ -1453,9 +1804,9 @@
static void VG_REGPARM(1) mc_new_mem_stack_8(Addr new_SP)
{
PROF_EVENT(111, "new_mem_stack_8");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP )=
;
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 )=
;
} else {
@@ -1466,9 +1817,9 @@
static void VG_REGPARM(1) mc_die_mem_stack_8(Addr new_SP)
{
PROF_EVENT(121, "die_mem_stack_8");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
} else {
@@ -1479,10 +1830,10 @@
static void VG_REGPARM(1) mc_new_mem_stack_12(Addr new_SP)
{
PROF_EVENT(112, "new_mem_stack_12");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP )=
;
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 )=
;
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP )=
;
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 )=
;
} else {
@@ -1497,7 +1848,7 @@
if (VG_IS_8_ALIGNED(new_SP-12)) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 )=
;
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 )=
;
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 )=
;
} else {
@@ -1508,10 +1859,10 @@
static void VG_REGPARM(1) mc_new_mem_stack_16(Addr new_SP)
{
PROF_EVENT(113, "new_mem_stack_16");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP )=
;
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 )=
;
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 =
);
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+12 =
);
@@ -1523,10 +1874,10 @@
static void VG_REGPARM(1) mc_die_mem_stack_16(Addr new_SP)
{
PROF_EVENT(123, "die_mem_stack_16");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 )=
;
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 )=
;
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 )=
;
@@ -1538,12 +1889,12 @@
static void VG_REGPARM(1) mc_new_mem_stack_32(Addr new_SP)
{
PROF_EVENT(114, "new_mem_stack_32");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 =
);
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+12 =
);
@@ -1557,12 +1908,12 @@
static void VG_REGPARM(1) mc_die_mem_stack_32(Addr new_SP)
{
PROF_EVENT(124, "die_mem_stack_32");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 )=
;
- } else if (VG_IS_4_ALIGNED(new_SP)) {
+ } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-28 )=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-20 )=
;
@@ -1576,7 +1927,7 @@
static void VG_REGPARM(1) mc_new_mem_stack_112(Addr new_SP)
{
PROF_EVENT(115, "new_mem_stack_112");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 =
);
@@ -1599,7 +1950,7 @@
static void VG_REGPARM(1) mc_die_mem_stack_112(Addr new_SP)
{
PROF_EVENT(125, "die_mem_stack_112");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 )=
;
@@ -1622,7 +1973,7 @@
static void VG_REGPARM(1) mc_new_mem_stack_128(Addr new_SP)
{
PROF_EVENT(116, "new_mem_stack_128");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 =
);
@@ -1647,7 +1998,7 @@
static void VG_REGPARM(1) mc_die_mem_stack_128(Addr new_SP)
{
PROF_EVENT(126, "die_mem_stack_128");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-120)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112)=
;
@@ -1672,7 +2023,7 @@
static void VG_REGPARM(1) mc_new_mem_stack_144(Addr new_SP)
{
PROF_EVENT(117, "new_mem_stack_144");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 =
);
@@ -1699,7 +2050,7 @@
static void VG_REGPARM(1) mc_die_mem_stack_144(Addr new_SP)
{
PROF_EVENT(127, "die_mem_stack_144");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-144)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-136)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128)=
;
@@ -1726,7 +2077,7 @@
static void VG_REGPARM(1) mc_new_mem_stack_160(Addr new_SP)
{
PROF_EVENT(118, "new_mem_stack_160");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 =
);
make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 =
);
@@ -1755,7 +2106,7 @@
static void VG_REGPARM(1) mc_die_mem_stack_160(Addr new_SP)
{
PROF_EVENT(128, "die_mem_stack_160");
- if (VG_IS_8_ALIGNED(new_SP)) {
+ if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-160)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-152)=
;
make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-144)=
;
@@ -2201,7 +2552,7 @@
static void mc_post_reg_write ( CorePart part, ThreadId tid,=20
OffT offset, SizeT size)
{
-# define MAX_REG_WRITE_SIZE 1392
+# define MAX_REG_WRITE_SIZE 1408
UChar area[MAX_REG_WRITE_SIZE];
tl_assert(size <=3D MAX_REG_WRITE_SIZE);
VG_(memset)(area, V_BITS8_DEFINED, size);
@@ -2589,8 +2940,40 @@
Bool isWrite )
{
MC_Error err_extra;
- Bool just_below_esp;
+ Bool just_below_esp;
=20
+ if (in_ignored_range(a))=20
+ return;
+
+# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ /* AIX zero-page handling. On AIX, reads from page zero are,
+ bizarrely enough, legitimate. Writes to page zero aren't,
+ though. Since memcheck can't distinguish reads from writes, the
+ best we can do is to 'act normal' and mark the A bits in the
+ normal way as noaccess, but then hide any reads from that page
+ that get reported here. */
+ if ((!isWrite) && a >=3D 0 && a+size <=3D 4096)=20
+ return;
+
+ /* Appalling AIX hack. It suppresses reads done by glink
+ fragments. Getting rid of this would require figuring out
+ somehow where the referenced data areas are (and their
+ sizes). */
+ if ((!isWrite) && size =3D=3D sizeof(Word)) {=20
+ UInt i1, i2;
+ UInt* pc =3D (UInt*)VG_(get_IP)(tid);
+ if (sizeof(Word) =3D=3D 4) {
+ i1 =3D 0x800c0000; /* lwz r0,0(r12) */
+ i2 =3D 0x804c0004; /* lwz r2,4(r12) */
+ } else {
+ i1 =3D 0xe80c0000; /* ld r0,0(r12) */
+ i2 =3D 0xe84c0008; /* ld r2,8(r12) */
+ }
+ if (pc[0] =3D=3D i1 && pc[1] =3D=3D i2) return;
+ if (pc[0] =3D=3D i2 && pc[-1] =3D=3D i1) return;
+ }
+# endif
+
just_below_esp =3D is_just_below_ESP( VG_(get_SP)(tid), a );
=20
/* If this is caused by an access immediately below %ESP, and the
@@ -3667,7 +4050,8 @@
Bool mc_is_within_valid_secondary ( Addr a )
{
SecMap* sm =3D maybe_get_secmap_for ( a );
- if (sm =3D=3D NULL || sm =3D=3D &sm_distinguished[SM_DIST_NOACCESS]) =
{
+ if (sm =3D=3D NULL || sm =3D=3D &sm_distinguished[SM_DIST_NOACCESS]
+ || in_ignored_range(a)) {
/* Definitely not in use. */
return False;
} else {
@@ -3687,7 +4071,8 @@
} else {
tl_assert(VG_IS_8_ALIGNED(a));
}
- if (is_mem_defined( a, sizeof(UWord), NULL ) =3D=3D MC_Ok) {
+ if (is_mem_defined( a, sizeof(UWord), NULL ) =3D=3D MC_Ok
+ && !in_ignored_range(a)) {
return True;
} else {
return False;
@@ -3739,6 +4124,9 @@
for (i =3D 0; i < N_PRIMARY_MAP; i++)
primary_map[i] =3D &sm_distinguished[SM_DIST_NOACCESS];
=20
+ /* Auxiliary primary maps */
+ init_auxmap_L1_L2();
+
/* auxmap_size =3D auxmap_used =3D 0;=20
no ... these are statically initialised */
=20
@@ -3761,10 +4149,15 @@
=20
static Bool mc_expensive_sanity_check ( void )
{
- Int i, n_secmaps_found;
+ Int i;
+ Word n_secmaps_found;
SecMap* sm;
+ HChar* errmsg;
Bool bad =3D False;
=20
+ if (0) VG_(printf)("expensive sanity check\n");
+ if (0) return True;
+
n_sanity_expensive++;
PROF_EVENT(491, "expensive_sanity_check");
=20
@@ -3801,37 +4194,28 @@
return False;
}
=20
- /* check nonsensical auxmap sizing */
- if (auxmap_used > auxmap_size)
- bad =3D True;
-
- if (bad) {
- VG_(printf)("memcheck expensive sanity: "
- "nonsensical auxmap sizing\n");
+ /* check the auxiliary maps, very thoroughly */
+ n_secmaps_found =3D 0;
+ errmsg =3D check_auxmap_L1_L2_sanity( &n_secmaps_found );
+ if (errmsg) {
+ VG_(printf)("memcheck expensive sanity, auxmaps:\n\t%s", errmsg);
return False;
}
=20
- /* check that the number of secmaps issued matches the number that
- are reachable (iow, no secmap leaks) */
- n_secmaps_found =3D 0;
+ /* n_secmaps_found is now the number referred to by the auxiliary
+ primary map. Now add on the ones referred to by the main
+ primary map. */
for (i =3D 0; i < N_PRIMARY_MAP; i++) {
- if (primary_map[i] =3D=3D NULL) {
- bad =3D True;
- } else {
- if (!is_distinguished_sm(primary_map[i]))
- n_secmaps_found++;
- }
- }
-
- for (i =3D 0; i < auxmap_used; i++) {
- if (auxmap[i].sm =3D=3D NULL) {
+ if (primary_map[i] =3D=3D NULL) {
bad =3D True;
} else {
- if (!is_distinguished_sm(auxmap[i].sm))
+ if (!is_distinguished_sm(primary_map[i]))
n_secmaps_found++;
}
}
=20
+ /* check that the number of secmaps issued matches the number that
+ are reachable (iow, no secmap leaks) */
if (n_secmaps_found !=3D (n_issued_SMs - n_deissued_SMs))
bad =3D True;
=20
@@ -3841,12 +4225,6 @@
return False;
}
=20
- /* check that auxmap only covers address space that the primary doesn=
't */
- =20
- for (i =3D 0; i < auxmap_used; i++)
- if (auxmap[i].base <=3D MAX_PRIMARY_ADDRESS)
- bad =3D True;
-
if (bad) {
VG_(printf)("memcheck expensive sanity: "
"auxmap covers wrong address space\n");
@@ -3895,6 +4273,35 @@
else if (VG_CLO_STREQ(arg, "--leak-resolution=3Dhigh"))
MC_(clo_leak_resolution) =3D Vg_HighRes;
=20
+ else if (VG_CLO_STREQN(16,arg,"--ignore-ranges=3D")) {
+ Int i;
+ UChar* txt =3D (UChar*)(arg+16);
+ Bool ok =3D parse_ignore_ranges(txt);
+ if (!ok)
+ return False;
+ tl_assert(ignoreRanges.used >=3D 0);
+ tl_assert(ignoreRanges.used < M_IGNORE_RANGES);
+ for (i =3D 0; i < ignoreRanges.used; i++) {
+ Addr s =3D ignoreRanges.start[i];
+ Addr e =3D ignoreRanges.end[i];
+ Addr limit =3D 0x4000000; /* 64M - entirely arbitrary limit */
+ if (e <=3D s) {
+ VG_(message)(Vg_DebugMsg,=20
+ "ERROR: --ignore-ranges: end <=3D start in range:");
+ VG_(message)(Vg_DebugMsg,=20
+ " 0x%lx-0x%lx", s, e);
+ return False;
+ }
+ if (e - s > limit) {
+ VG_(message)(Vg_DebugMsg,=20
+ "ERROR: --ignore-ranges: suspiciously large range:");
+ VG_(message)(Vg_DebugMsg,=20
+ " 0x%lx-0x%lx (size %ld)", s, e, (UWord)(e-s));
+ return False;
+ }
+ }
+ }
+
else
return VG_(replacement_malloc_process_cmd_line_option)(arg);
=20
@@ -3911,6 +4318,7 @@
" --partial-loads-ok=3Dno|yes too hard to explain here; see ma=
nual [no]\n"
" --freelist-vol=3D<number> volume of freed blocks queue [50=
00000]\n"
" --workaround-gcc296-bugs=3Dno|yes self explanatory [no]\n"
+" --ignore-ranges=3D0xPP-0xQQ[,0xRR-0xSS] assume given addresses ar=
e OK\n"
);
VG_(replacement_malloc_print_usage)();
}
@@ -4374,12 +4782,19 @@
n_sanity_cheap, n_sanity_expensive );
VG_(message)(Vg_DebugMsg,
" memcheck: auxmaps: %d auxmap entries (%dk, %dM) in use",
- auxmap_used,=20
- auxmap_used * 64,=20
- auxmap_used / 16 );
+ n_auxmap_L2_nodes,=20
+ n_auxmap_L2_nodes * 64,=20
+ n_auxmap_L2_nodes / 16 );
VG_(message)(Vg_DebugMsg,
- " memcheck: auxmaps: %lld searches, %lld comparisons",
- n_auxmap_searches, n_auxmap_cmps ); =20
+ " memcheck: auxmaps_L1: %lld searches, %lld cmps, ratio %lld:10=
",
+ n_auxmap_L1_searches, n_auxmap_L1_cmps,
+ (10ULL * n_auxmap_L1_cmps)=20
+ / (n_auxmap_L1_searches ? n_auxmap_L1_searches : 1)=20
+ ); =20
+ VG_(message)(Vg_DebugMsg,
+ " memcheck: auxmaps_L2: %lld searches, %lld nodes",
+ n_auxmap_L2_searches, n_auxmap_L2_nodes
+ ); =20
=20
print_SM_info("n_issued ", n_issued_SMs);
print_SM_info("n_deissued ", n_deissued_SMs);
@@ -4425,7 +4840,7 @@
VG_(details_copyright_author)(
"Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.")=
;
VG_(details_bug_reports_to) (VG_BUGS_TO);
- VG_(details_avg_translation_sizeB) ( 370 );
+ VG_(details_avg_translation_sizeB) ( 556 );
=20
VG_(basic_tool_funcs) (mc_post_clo_init,
MC_(instrument),
@@ -4529,6 +4944,8 @@
=20
// {LOADV,STOREV}[8421] will all fail horribly if this isn't true.
tl_assert(sizeof(UWord) =3D=3D sizeof(Addr));
+ // Call me paranoid. I don't care.
+ tl_assert(sizeof(void*) =3D=3D sizeof(Addr));
=20
// BYTES_PER_SEC_VBIT_NODE must be a power of two.
tl_assert(-1 !=3D VG_(log2)(BYTES_PER_SEC_VBIT_NODE));
|
|
From: <sv...@va...> - 2006-10-17 01:27:15
|
Author: sewardj
Date: 2006-10-17 02:27:13 +0100 (Tue, 17 Oct 2006)
New Revision: 6255
Log:
Merge r6111:
AIX5 changes. Perhaps this isn't quite the right place to add a
sqrt() replacement. Hmm.
Modified:
trunk/memcheck/mc_replace_strmem.c
Modified: trunk/memcheck/mc_replace_strmem.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/mc_replace_strmem.c 2006-10-17 01:26:12 UTC (rev 6254)
+++ trunk/memcheck/mc_replace_strmem.c 2006-10-17 01:27:13 UTC (rev 6255)
@@ -116,8 +116,23 @@
RECORD_OVERLAP_ERROR( s, &extra );
}
=20
-// Some handy Z-encoded names
-#define m_libc_so_star libcZdsoZa // libc.so*
+/* --------- Some handy Z-encoded names. --------- */
+
+/* --- Soname of the standard C library. --- */
+
+#if defined(VGO_linux)
+# define m_libc_soname libcZdsoZa // libc.so*
+#elif defined(VGP_ppc32_aix5)
+ /* AIX has both /usr/lib/libc.a and /usr/lib/libc_r.a. */
+# define m_libc_soname libcZaZdaZLshrZdoZR // libc*.a(shr.o)
+#elif defined(VGP_ppc64_aix5)
+# define m_libc_soname libcZaZdaZLshrZu64ZdoZR // libc*.a(shr_64.o=
)
+#else
+# error "Unknown platform"
+#endif
+
+/* --- Sonames for Linux ELF linkers. --- */
+
#define m_ld_linux_so_2 ldZhlinuxZdsoZd2 // ld-linux.=
so.2
#define m_ld_linux_x86_64_so_2 ldZhlinuxZhx86Zh64ZdsoZd2 // ld-linux-=
x86-64.so.2
#define m_ld64_so_1 ld64ZdsoZd1 // ld64.so.1
@@ -139,8 +154,8 @@
}
=20
// Apparently rindex() is the same thing as strrchr()
-STRRCHR(m_libc_so_star, strrchr)
-STRRCHR(m_libc_so_star, rindex)
+STRRCHR(m_libc_soname, strrchr)
+STRRCHR(m_libc_soname, rindex)
STRRCHR(m_ld_linux_so_2, rindex)
=20
=20
@@ -158,10 +173,10 @@
}
=20
// Apparently index() is the same thing as strchr()
-STRCHR(m_libc_so_star, strchr)
+STRCHR(m_libc_soname, strchr)
STRCHR(m_ld_linux_so_2, strchr)
STRCHR(m_ld_linux_x86_64_so_2, strchr)
-STRCHR(m_libc_so_star, index)
+STRCHR(m_libc_soname, index)
STRCHR(m_ld_linux_so_2, index)
STRCHR(m_ld_linux_x86_64_so_2, index)
=20
@@ -187,7 +202,7 @@
return dst_orig; \
}
=20
-STRCAT(m_libc_so_star, strcat)
+STRCAT(m_libc_soname, strcat)
=20
=20
#define STRNCAT(soname, fnname) \
@@ -215,9 +230,9 @@
return dst_orig; \
}
=20
-STRNCAT(m_libc_so_star, strncat)
- =20
+STRNCAT(m_libc_soname, strncat)
=20
+
#define STRNLEN(soname, fnname) \
SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT =
n ); \
SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* str, SizeT =
n ) \
@@ -227,7 +242,7 @@
return i; \
}
=20
-STRNLEN(m_libc_so_star, strnlen)
+STRNLEN(m_libc_soname, strnlen)
=20
=20
// Note that this replacement often doesn't get used because gcc inlines
@@ -243,11 +258,11 @@
return i; \
}
=20
-STRLEN(m_libc_so_star, strlen)
+STRLEN(m_libc_soname, strlen)
STRLEN(m_ld_linux_so_2, strlen)
STRLEN(m_ld_linux_x86_64_so_2, strlen)
- =20
=20
+
#define STRCPY(soname, fnname) \
char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char*=
src ); \
char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char*=
src ) \
@@ -269,7 +284,7 @@
return dst_orig; \
}
=20
-STRCPY(m_libc_so_star, strcpy)
+STRCPY(m_libc_soname, strcpy)
=20
=20
#define STRNCPY(soname, fnname) \
@@ -292,7 +307,7 @@
return dst_orig; \
}
=20
-STRNCPY(m_libc_so_star, strncpy)
+STRNCPY(m_libc_soname, strncpy)
=20
=20
#define STRNCMP(soname, fnname) \
@@ -315,7 +330,7 @@
} \
}
=20
-STRNCMP(m_libc_so_star, strncmp)
+STRNCMP(m_libc_soname, strncmp)
=20
=20
#define STRCMP(soname, fnname) \
@@ -338,7 +353,7 @@
return 0; \
}
=20
-STRCMP(m_libc_so_star, strcmp)
+STRCMP(m_libc_soname, strcmp)
STRCMP(m_ld_linux_x86_64_so_2, strcmp)
STRCMP(m_ld64_so_1, strcmp)
=20
@@ -355,7 +370,7 @@
return NULL; \
}
=20
-MEMCHR(m_libc_so_star, memchr)
+MEMCHR(m_libc_soname, memchr)
=20
=20
#define MEMCPY(soname, fnname) \
@@ -403,10 +418,10 @@
return dst; \
}
=20
-MEMCPY(m_libc_so_star, memcpy)
-MEMCPY(m_ld_so_1, memcpy) /* ld.so.1 */
- =20
+MEMCPY(m_libc_soname, memcpy)
+MEMCPY(m_ld_so_1, memcpy) /* ld.so.1 */
=20
+
#define MEMCMP(soname, fnname) \
int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
( const void *s1V, const void *s2V, SizeT n ); \
@@ -432,8 +447,8 @@
return 0; \
}
=20
-MEMCMP(m_libc_so_star, memcmp)
-MEMCMP(m_libc_so_star, bcmp)
+MEMCMP(m_libc_soname, memcmp)
+MEMCMP(m_libc_soname, bcmp)
=20
=20
/* Copy SRC to DEST, returning the address of the terminating '\0' in
@@ -459,7 +474,7 @@
return dst; \
}
=20
-STPCPY(m_libc_so_star, stpcpy)
+STPCPY(m_libc_soname, stpcpy)
STPCPY(m_ld_linux_so_2, stpcpy)
STPCPY(m_ld_linux_x86_64_so_2, stpcpy)
=20
@@ -476,7 +491,7 @@
return s; \
}
=20
-MEMSET(m_libc_so_star, memset)
+MEMSET(m_libc_soname, memset)
=20
=20
#define MEMMOVE(soname, fnname) \
@@ -500,7 +515,7 @@
return dst; \
}
=20
-MEMMOVE(m_libc_so_star, memmove)
+MEMMOVE(m_libc_soname, memmove)
=20
=20
/* Find the first occurrence of C in S or the final NUL byte. */
@@ -517,7 +532,7 @@
} \
}
=20
-GLIBC232_STRCHRNUL(m_libc_so_star, strchrnul)
+GLIBC232_STRCHRNUL(m_libc_soname, strchrnul)
=20
=20
/* Find the first occurrence of C in S. */
@@ -533,9 +548,312 @@
} \
}
=20
-GLIBC232_RAWMEMCHR(m_libc_so_star, rawmemchr)
+GLIBC232_RAWMEMCHR(m_libc_soname, rawmemchr)
=20
=20
+/*------------------------------------------------------------*/
+/*--- AIX stuff only after this point ---*/
+/*------------------------------------------------------------*/
+
+/* Generate replacements for strcat, strncat, strcpy, strncpy,
+ in the given soname. */
+#define Str4FNs(_soname) \
+ STRCAT(_soname, strcat) \
+ STRNCAT(_soname, strncat) \
+ STRCPY(_soname, strcpy) \
+ STRNCPY(_soname, strncpy)
+
+#if defined(VGP_ppc32_aix5)
+Str4FNs(NONE) /* in main exe */
+Str4FNs(libCZdaZLshrcoreZdoZR) /* libC.a(shrcore.o) */
+Str4FNs(libX11ZdaZLshr4ZdoZR) /* libX11.a(shr4.o) */
+Str4FNs(libXmZdaZLshrZaZdoZR) /* libXm.a(shr*.o) */
+Str4FNs(libXtZdaZLshr4ZdoZR) /* libXt.a(shr4.o) */
+Str4FNs(libppeZurZdaZLdynamicZdoZR) /* libppe_r.a(dynamic.o) */
+Str4FNs(libodmZdaZLshrZdoZR) /* libodm.a(shr.o) */
+Str4FNs(libmpiZurZdaZLmpicoreZurZdoZR) /* libmpi_r.a(mpicore_r.o) */
+Str4FNs(libmpiZurZdaZLmpipoeZurZdoZR) /* libmpi_r.a(mpipoe_r.o) */
+Str4FNs(libmpiZurZdaZLmpciZurZdoZR) /* libmpi_r.a(mpci_r.o) */
+Str4FNs(libslurmZdso) /* libslurm.so */
+Str4FNs(libglibZdso) /* libglib.so */
+Str4FNs(libIMZdaZLshrZdoZR) /* libIM.a(shr.o) */
+Str4FNs(libiconvZdaZLshr4ZdoZR) /* libiconv.a(shr4.o) */
+Str4FNs(libGLZdaZLshrZdoZR) /* libGL.a(shr.o) */
+Str4FNs(libgdkZdso) /* libgdk.so */
+Str4FNs(libcursesZdaZLshr42ZdoZR) /* libcurses.a(shr42.o) */
+Str4FNs(libqtZda) /* libqt.a */
+#endif
+#if defined(VGP_ppc64_aix5)
+Str4FNs(NONE) /* in main exe */
+Str4FNs(libX11ZdaZLshrZu64ZdoZR) /* libX11.a(shr_64.o) */
+Str4FNs(libiconvZdaZLshr4Zu64ZdoZR) /* libiconv.a(shr4_64.o) */
+Str4FNs(libGLZdaZLshrZu64ZdoZR) /* libGL.a(shr_64.o) */
+Str4FNs(libppeZurZdaZLdynamic64ZdoZR) /* libppe_r.a(dynamic64.o) */
+Str4FNs(libodmZdaZLshrZu64ZdoZR) /* libodm.a(shr_64.o) */
+Str4FNs(libmpiZurZdaZLmpicore64ZurZdoZR) /* libmpi_r.a(mpicore64_r.o) *=
/
+Str4FNs(libmpiZurZdaZLmpipoe64ZurZdoZR) /* libmpi_r.a(mpipoe64_r.o) */
+Str4FNs(libCZdaZLshrcoreZu64ZdoZR) /* libC.a(shrcore_64.o) */
+Str4FNs(libmpiZurZdaZLmpci64ZurZdoZR) /* libmpi_r.a(mpci64_r.o) */
+Str4FNs(libqtZda) /* libqt.a */
+#endif
+
+
+/* AIX's libm contains a sqrt implementation which does a nasty thing:
+ it loads the initial estimate of the root into a FP register, but
+ only the upper half of the number is initialised data. Hence the
+ least significant 32 mantissa bits are undefined, and it then uses
+ Newton-Raphson iteration to compute the final, defined result.
+ This fools memcheck completely; the only solution I can think of is
+ provide our own substitute. The _FAST variant is almost right
+ except the result is not correctly rounded. The _EXACT variant,
+ which is selected by default, is always right; but it's also pretty
+ darn slow. */
+
+#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+#define SQRT_FAST(soname, fnname) \
+ double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
+ double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
+ { \
+ static UInt T1[32] =3D \
+ { 0, 1024, 3062, 5746, 9193, 13348, \
+ 18162, 23592, 29598, 36145, 43202, 50740, \
+ 58733, 67158, 75992, 85215, 83599, 71378, \
+ 60428, 50647, 41945, 34246, 27478, 21581, \
+ 16499, 12183, 8588, 5674, 3403, 1742, \
+ 661, 130 }; \
+ UInt x0, x1, sign, expo, mant0, bIGENDIAN =3D 1; \
+ union { UInt w[2]; double d; } u; \
+ u.d =3D x; \
+ x0 =3D u.w[1 - bIGENDIAN]; /* high half */ \
+ x1 =3D u.w[bIGENDIAN]; /* low half */ \
+ sign =3D x0 >> 31; \
+ expo =3D (x0 >> 20) & 0x7FF; \
+ mant0 =3D x0 & 0xFFFFF; \
+ if ( (sign =3D=3D 0 && expo >=3D 1 && expo <=3D 0x7FE) /* +normal =
*/ \
+ || (sign =3D=3D 0 && expo =3D=3D 0 \
+ && (mant0 | x1) > 0) /* +denorm */) { \
+ /* common case; do Newton-Raphson */ \
+ /* technically k should be signed int32, but since we're \
+ always entering here with x > 0, doesn't matter that it's \
+ unsigned. */ \
+ double y; \
+ UInt k =3D (x0>>1) + 0x1ff80000; \
+ u.w[1 - bIGENDIAN] =3D k - T1[31&(k>>15)]; \
+ u.w[bIGENDIAN] =3D 0; \
+ y =3D u.d; \
+ y =3D (y+x/y)/2.0 ; \
+ y =3D (y+x/y)/2.0 ; \
+ y =3D y-(y-x/y)/2.0 ; \
+ return y; \
+ } \
+ if ( (sign =3D=3D 1 && expo >=3D 1 && expo <=3D 0x7FE) /* -normal =
*/ \
+ || (sign =3D=3D 1 && expo =3D=3D 0 \
+ && (mant0 | x1) > 0) /* -denorm */) { \
+ u.w[1 - bIGENDIAN] =3D 0xFFF00000; \
+ u.w[bIGENDIAN] =3D 0x1; \
+ return u.d; /* -Inf -> NaN */ \
+ } \
+ if ((expo | mant0 | x1) =3D=3D 0) \
+ return x; /* +/-zero -> self */ \
+ if (expo =3D=3D 0x7FF && (mant0 | x1) =3D=3D 0) { \
+ if (sign =3D=3D 0) \
+ return x; /* +Inf -> self */ \
+ u.w[1 - bIGENDIAN] =3D 0xFFF00000; \
+ u.w[bIGENDIAN] =3D 0x1; \
+ return u.d; /* -Inf -> NaN */ \
+ } \
+ /* must be +/- NaN */ \
+ return x; /* +/-NaN -> self */ \
+ }
+
+#define SQRT_EXACT(soname, fnname) \
+ /* \
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D \
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. =
\
+ * \
+ * Developed at SunPro, a Sun Microsystems, Inc. business. \
+ * Permission to use, copy, modify, and distribute this \
+ * software is freely granted, provided that this notice \
+ * is preserved. \
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D \
+ */ \
+ /* \
+ * Return correctly rounded sqrt. \
+ * ------------------------------------------ \
+ * | Use the hardware sqrt if you have one | \
+ * ------------------------------------------ \
+ * Method: \
+ * Bit by bit method using integer arithmetic. (Slow, but portable)=
\
+ * 1. Normalization \
+ * Scale x to y in [1,4) with even powers of 2: \
+ * find an integer k such that 1 <=3D (y=3Dx*2^(2k)) < 4, then =
\
+ * sqrt(x) =3D 2^k * sqrt(y) \
+ * 2. Bit by bit computation \
+ * Let q =3D sqrt(y) truncated to i bit after binary point (q =3D=
1), \
+ * i 0 \
+ * i+1 2 \
+ * s =3D 2*q , and y =3D 2 * ( y - q ). (=
1) \
+ * i i i i \
+ * \
+ * To compute q from q , one checks whether \
+ * i+1 i \
+ * \
+ * -(i+1) 2 \
+ * (q + 2 ) <=3D y. (2)=
\
+ * i \
+ * -(i+1) =
\
+ * If (2) is false, then q =3D q ; otherwise q =3D q + 2 =
. \
+ * i+1 i i+1 i \
+ * \
+ * With some algebric manipulation, it is not difficult to see \
+ * that (2) is equivalent to \
+ * -(i+1) \
+ * s + 2 <=3D y (3)=
\
+ * i i \
+ * \
+ * The advantage of (3) is that s and y can be computed by \
+ * i i \
+ * the following recurrence formula: \
+ * if (3) is false \
+ * \
+ * s =3D s , y =3D y ; (=
4) \
+ * i+1 i i+1 i \
+ * \
+ * otherwise, \
+ * -i -(i+1) \
+ * s =3D s + 2 , y =3D y - s - 2 (=
5) \
+ * i+1 i i+1 i i \
+ * \
+ * \
+ * One may easily use induction to prove (4) and (5). \
+ * Note. Since the left hand side of (3) contain only i+2 bits, =
\
+ * it does not necessary to do a full (53-bit) comparison =
\
+ * in (3). \
+ * 3. Final rounding \
+ * After generating the 53 bits result, we compute one more bit.=
\
+ * Together with the remainder, we can decide whether the \
+ * result is exact, bigger than 1/2ulp, or less than 1/2ulp \
+ * (it will never equal to 1/2ulp). \
+ * The rounding mode can be detected by checking whether \
+ * huge + tiny is equal to huge, and whether huge - tiny is \
+ * equal to huge for some floating point number "huge" and "tiny=
". \
+ * \
+ * Special cases: \
+ * sqrt(+-0) =3D +-0 ... exact \
+ * sqrt(inf) =3D inf \
+ * sqrt(-ve) =3D NaN ... with invalid signal \
+ * sqrt(NaN) =3D NaN ... with invalid signal for signali=
ng NaN \
+ * \
+ */ \
+ double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ); \
+ double VG_REPLACE_FUNCTION_ZU(soname,fnname)( double x ) \
+ { \
+ const Int bIGENDIAN =3D 1; \
+ const double one =3D 1.0, tiny=3D1.0e-300; \
+ double z; \
+ Int sign =3D (Int)0x80000000; \
+ Int ix0,s0,q,m,t,i; \
+ UInt r,t1,s1,ix1,q1; \
+ union { UInt w[2]; double d; } u; \
+ u.d =3D x; \
+ ix0 =3D u.w[1-bIGENDIAN]; \
+ ix1 =3D u.w[bIGENDIAN]; \
+ \
+ /* take care of Inf and NaN */ \
+ if((ix0&0x7ff00000)=3D=3D0x7ff00000) { \
+ return x*x+x; /* sqrt(NaN)=3DNaN, sqrt(+inf)=3D+i=
nf \
+ sqrt(-inf)=3DsNaN */ \
+ } \
+ /* take care of zero */ \
+ if(ix0<=3D0) { \
+ if(((ix0&(~sign))|ix1)=3D=3D0) return x;/* sqrt(+-0) =3D +-0 */=
\
+ else if(ix0<0) \
+ return (x-x)/(x-x); /* sqrt(-ve) =3D sNaN */ \
+ } \
+ /* normalize x */ \
+ m =3D (ix0>>20); \
+ if(m=3D=3D0) { /* subnormal x */ \
+ while(ix0=3D=3D0) { \
+ m -=3D 21; \
+ ix0 |=3D (ix1>>11); ix1 <<=3D 21; \
+ } \
+ for(i=3D0;(ix0&0x00100000)=3D=3D0;i++) ix0<<=3D1; \
+ m -=3D i-1; \
+ ix0 |=3D (ix1>>(32-i)); \
+ ix1 <<=3D i; \
+ } \
+ m -=3D 1023; /* unbias exponent */ \
+ ix0 =3D (ix0&0x000fffff)|0x00100000; \
+ if(m&1){ /* odd m, double x to make it even */ \
+ ix0 +=3D ix0 + ((ix1&sign)>>31); \
+ ix1 +=3D ix1; \
+ } \
+ m >>=3D 1; /* m =3D [m/2] */ \
+ /* generate sqrt(x) bit by bit */ \
+ ix0 +=3D ix0 + ((ix1&sign)>>31); \
+ ix1 +=3D ix1; \
+ q =3D q1 =3D s0 =3D s1 =3D 0; /* [q,q1] =3D sqrt(x) */ \
+ r =3D 0x00200000; /* r =3D moving bit from right to left *=
/ \
+ while(r!=3D0) { \
+ t =3D s0+r; \
+ if(t<=3Dix0) { \
+ s0 =3D t+r; \
+ ix0 -=3D t; \
+ q +=3D r; \
+ } \
+ ix0 +=3D ix0 + ((ix1&sign)>>31); \
+ ix1 +=3D ix1; \
+ r>>=3D1; \
+ } \
+ r =3D sign; \
+ while(r!=3D0) { \
+ t1 =3D s1+r; \
+ t =3D s0; \
+ if((t<ix0)||((t=3D=3Dix0)&&(t1<=3Dix1))) { \
+ s1 =3D t1+r; \
+ if(((t1&sign)=3D=3Dsign)&&(s1&sign)=3D=3D0) s0 +=3D 1; \
+ ix0 -=3D t; \
+ if (ix1 < t1) ix0 -=3D 1; \
+ ix1 -=3D t1; \
+ q1 +=3D r; \
+ } \
+ ix0 +=3D ix0 + ((ix1&sign)>>31); \
+ ix1 +=3D ix1; \
+ r>>=3D1; \
+ } \
+ /* use floating add to find out rounding direction */ \
+ if((ix0|ix1)!=3D0) { \
+ z =3D one-tiny; /* trigger inexact flag */ \
+ if (z>=3Done) { \
+ z =3D one+tiny; \
+ if (q1=3D=3D(UInt)0xffffffff) { q1=3D0; q +=3D 1;} \
+ else if (z>one) { \
+ if (q1=3D=3D(UInt)0xfffffffe) q+=3D1; \
+ q1+=3D2; \
+ } else \
+ q1 +=3D (q1&1); \
+ } \
+ } \
+ ix0 =3D (q>>1)+0x3fe00000; \
+ ix1 =3D q1>>1; \
+ if ((q&1)=3D=3D1) ix1 |=3D sign; \
+ ix0 +=3D (m <<20); \
+ ix0 =3D u.w[1-bIGENDIAN] =3D ix0; \
+ ix1 =3D u.w[bIGENDIAN] =3D ix1; \
+ z =3D u.d; \
+ return z; \
+ }
+
+#if 0
+SQRT_FAST(NONE, sqrt) /* xlC generates these */
+SQRT_FAST(NONE, _sqrt) /* xlf generates these */
+#else
+SQRT_EXACT(NONE, sqrt) /* xlC generates these */
+SQRT_EXACT(NONE, _sqrt) /* xlf generates these */
+#endif
+
+#endif /* defined(VGP_ppc32_aix5) */
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
|
|
From: <sv...@va...> - 2006-10-17 01:26:19
|
Author: sewardj
Date: 2006-10-17 02:26:12 +0100 (Tue, 17 Oct 2006)
New Revision: 6254
Log:
Merge r6109:
Various minor changes to make these compile on AIX5.
Modified:
trunk/memcheck/tests/badjump.c
trunk/memcheck/tests/badjump2.c
trunk/memcheck/tests/brk.c
trunk/memcheck/tests/inits.c
trunk/memcheck/tests/malloc3.c
trunk/memcheck/tests/malloc3.stdout.exp
trunk/memcheck/tests/malloc_usable.c
trunk/memcheck/tests/manuel1.c
trunk/memcheck/tests/memalign2.c
trunk/memcheck/tests/pointer-trace.c
trunk/memcheck/tests/sigprocmask.c
trunk/memcheck/tests/stack_changes.c
trunk/memcheck/tests/stack_switch.c
trunk/memcheck/tests/str_tester.c
trunk/memcheck/tests/wrap5.c
trunk/memcheck/tests/wrap8.c
Modified: trunk/memcheck/tests/badjump.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/badjump.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/badjump.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -1,7 +1,7 @@
=20
int main ( void )
{
-#if defined(__powerpc64__)
+#if defined(__powerpc64__) || defined(_AIX)
/* on ppc64-linux, a function pointer points to a function
descriptor, not to the function's entry point. Hence to get
uniform behaviour on all supported targets - a jump to 0xE000000
Modified: trunk/memcheck/tests/badjump2.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/badjump2.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/badjump2.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -24,7 +24,9 @@
/* Install own SIGSEGV handler */
sigsegv_new.sa_handler =3D SIGSEGV_handler;
sigsegv_new.sa_flags =3D 0;
+#if !defined(_AIX)
sigsegv_new.sa_restorer =3D NULL;
+#endif
res =3D sigemptyset( &sigsegv_new.sa_mask );
assert(res =3D=3D 0);
=20
@@ -33,8 +35,8 @@
=20
if (__builtin_setjmp(myjmpbuf) =3D=3D 0) {
// Jump to zero; will cause seg fault
-#if defined(__powerpc64__)
- unsigned long long int fake_fndescr[3];
+#if defined(__powerpc64__) || defined(_AIX)
+ unsigned long int fake_fndescr[3];
fake_fndescr[0] =3D 0;
fake_fndescr[1] =3D 0;
fake_fndescr[2] =3D 0;
Modified: trunk/memcheck/tests/brk.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/brk.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/brk.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -1,6 +1,8 @@
#include <assert.h>
#include <stdio.h>
-#include <sys/syscall.h>
+#if !defined(_AIX)
+# include <sys/syscall.h>
+#endif
#include <sys/types.h>
#include <unistd.h>
=20
@@ -27,7 +29,9 @@
vals[8] =3D EOL;
=20
for (i =3D 0; EOL !=3D vals[i]; i++) {
+# if !defined(_AIX)
res =3D (void*)syscall(__NR_brk, vals[i]);
+# endif
}
=20
assert( 0 =3D=3D brk(orig_ds) ); // libc brk()
Modified: trunk/memcheck/tests/inits.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/inits.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/inits.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -11,10 +11,10 @@
int l;
static int ls;
=20
- if (gs =3D=3D 0xDEADBEEF) printf("1!\n");
- if (g =3D=3D 0xDEADBEEF) printf("2!\n");
- if (ls =3D=3D 0xDEADBEEF) printf("3!\n");
- if (l =3D=3D 0xDEADBEEF) printf("4!\n"); // complains
+ if (gs =3D=3D 0xCAFEBABE) printf("1!\n");
+ if (g =3D=3D 0xCAFEBABE) printf("2!\n");
+ if (ls =3D=3D 0xCAFEBABE) printf("3!\n");
+ if (l =3D=3D 0xCAFEBABE) printf("4!\n"); // complains
=20
return 0;
}
Modified: trunk/memcheck/tests/malloc3.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/malloc3.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/malloc3.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -9,23 +9,23 @@
char* p;
=20
p =3D malloc(0);
- printf("malloc(0) =3D %p\n", p);
+ printf("malloc(0) =3D 0x%lx\n", (unsigned long)p);
free(p);
=20
p =3D malloc(-1);
- printf("malloc(-1) =3D %p\n", p);
+ printf("malloc(-1) =3D 0x%lx\n", (unsigned long)p);
free(p);
=20
p =3D calloc(0,1);
- printf("calloc(0,1) =3D %p\n", p);
+ printf("calloc(0,1) =3D 0x%lx\n", (unsigned long)p);
free(p);
=20
p =3D calloc(0,-1);
- printf("calloc(0,-1) =3D %p\n", p);
+ printf("calloc(0,-1) =3D 0x%lx\n", (unsigned long)p);
free(p);
=20
p =3D calloc(-1,-1);
- printf("calloc(-1,-1) =3D %p\n", p);
+ printf("calloc(-1,-1) =3D 0x%lx\n", (unsigned long)p);
free(p);
=20
return 0;
Modified: trunk/memcheck/tests/malloc3.stdout.exp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/malloc3.stdout.exp 2006-10-17 01:25:13 UTC (rev =
6253)
+++ trunk/memcheck/tests/malloc3.stdout.exp 2006-10-17 01:26:12 UTC (rev =
6254)
@@ -1,5 +1,5 @@
malloc(0) =3D 0x........
-malloc(-1) =3D (nil)
+malloc(-1) =3D 0x........
calloc(0,1) =3D 0x........
-calloc(0,-1) =3D (nil)
-calloc(-1,-1) =3D (nil)
+calloc(0,-1) =3D 0x........
+calloc(-1,-1) =3D 0x........
Modified: trunk/memcheck/tests/malloc_usable.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/malloc_usable.c 2006-10-17 01:25:13 UTC (rev 625=
3)
+++ trunk/memcheck/tests/malloc_usable.c 2006-10-17 01:26:12 UTC (rev 625=
4)
@@ -7,6 +7,8 @@
{
// Since our allocations are in multiples of 8, 99 will round up to 1=
04.
int* x =3D malloc(99);
+# if !defined(_AIX)
assert(104 =3D=3D malloc_usable_size(x));
+# endif
return 0;
}
Modified: trunk/memcheck/tests/manuel1.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/manuel1.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/manuel1.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -4,7 +4,7 @@
{
int x;
=20
- printf ("x =3D %d\n", x=3D=3D0xDEADBEEF ? 99 : 88);
+ printf ("x =3D %d\n", x=3D=3D0xCAFEBABE ? 99 : 88);
=20
return 0;
}
Modified: trunk/memcheck/tests/memalign2.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/memalign2.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/memalign2.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -25,7 +25,11 @@
int* p;
int res;
assert(sizeof(long int) =3D=3D sizeof(void*));
- =20
+
+# if defined(_AIX)
+ printf("AIX 5.2 knows about neither memalign() nor posix_memalign().\=
n");
+
+# else
p =3D memalign(0, 100); assert(0 =3D=3D (long)p % 8);
p =3D memalign(1, 100); assert(0 =3D=3D (long)p % 8);
p =3D memalign(2, 100); assert(0 =3D=3D (long)p % 8);
@@ -45,7 +49,7 @@
p =3D memalign(4096, 100); assert(0 =3D=3D (long)p % 4096);
p =3D memalign(4097, 100); assert(0 =3D=3D (long)p % 8192);
=20
- #define PM(a,b,c) posix_memalign((void**)a, b, c)
+# define PM(a,b,c) posix_memalign((void**)a, b, c)
=20
res =3D PM(&p, -1,100); assert(EINVAL =3D=3D res);
res =3D PM(&p, 0, 100); assert(0 =3D=3D res && 0 =3D=3D (long)p =
% 8);
@@ -64,6 +68,8 @@
res =3D PM(&p, 4096, 100); assert(0 =3D=3D res &&
0 =3D=3D (long)p % 4096=
);=20
res =3D PM(&p, 4097, 100); assert(EINVAL =3D=3D res);
+
+# endif
=20
return 0;
}
Modified: trunk/memcheck/tests/pointer-trace.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/pointer-trace.c 2006-10-17 01:25:13 UTC (rev 625=
3)
+++ trunk/memcheck/tests/pointer-trace.c 2006-10-17 01:26:12 UTC (rev 625=
4)
@@ -9,6 +9,10 @@
#include <fcntl.h>
#include <unistd.h>
=20
+#if !defined(MAP_NORESERVE)
+# define MAP_NORESERVE 0
+#endif
+
int main()
{
char **volatile ptrs;
Modified: trunk/memcheck/tests/sigprocmask.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/sigprocmask.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/sigprocmask.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -1,7 +1,9 @@
=20
#include <signal.h>
#include <stdio.h>
-#include <sys/syscall.h>
+#if !defined(_AIX)
+# include <sys/syscall.h>
+#endif
#include <unistd.h>
=20
// Reg test for bug #93328: we were using too-big sigset types, and thus
@@ -11,7 +13,7 @@
{
int x[6], *s, *os, i;
=20
-#if defined(__NR_sigprocmask) && !defined(__powerpc64__)
+#if defined(__NR_sigprocmask) && !defined(__powerpc64__) && !defined(_AI=
X)
=20
x[0] =3D 0x11111111;
x[1] =3D 0x89abcdef;
Modified: trunk/memcheck/tests/stack_changes.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/stack_changes.c 2006-10-17 01:25:13 UTC (rev 625=
3)
+++ trunk/memcheck/tests/stack_changes.c 2006-10-17 01:26:12 UTC (rev 625=
4)
@@ -10,10 +10,16 @@
// This test is checking the libc context calls (setcontext, etc.) and
// checks that Valgrind notices their stack changes properly.
=20
-struct ucontext ctx1, ctx2, oldc;
+#if defined(_AIX)
+typedef ucontext_t mycontext;
+#else /* linux */
+typedef struct ucontext mycontext;
+#endif
+
+mycontext ctx1, ctx2, oldc;
int count;
=20
-void hello(struct ucontext *newc)
+void hello(mycontext *newc)
{
printf("hello, world: %d\n", count);
if (count++ =3D=3D 2)
@@ -21,7 +27,7 @@
setcontext(newc);
}
=20
-int init_context(struct ucontext *uc)
+int init_context(mycontext *uc)
{
void *stack;
int ret;
Modified: trunk/memcheck/tests/stack_switch.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/stack_switch.c 2006-10-17 01:25:13 UTC (rev 6253=
)
+++ trunk/memcheck/tests/stack_switch.c 2006-10-17 01:26:12 UTC (rev 6254=
)
@@ -1,8 +1,18 @@
#define _XOPEN_SOURCE 600
#define _BSD_SOURCE
=20
+#include <stdio.h>
+
+#if defined(_AIX)
+int main(int argc, char **argv)=20
+{
+ printf("this test is linux-specific\n");
+ return 0;
+}
+
+#else
+
#include <sched.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -53,3 +63,5 @@
=20
exit( 0 );
}
+
+#endif /* !defined(_AIX) */
Modified: trunk/memcheck/tests/str_tester.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/str_tester.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/str_tester.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -463,6 +463,7 @@
}
}
=20
+#if !defined(_AIX)
static void
test_strchrnul (void)
{
@@ -496,7 +497,9 @@
}
}
}
+#endif /* !defined(_AIX) */
=20
+#if !defined(_AIX)
static void
test_rawmemchr (void)
{
@@ -523,6 +526,7 @@
}
}
}
+#endif /* !defined(_AIX) */
=20
static void
test_index (void)
@@ -570,6 +574,7 @@
}
}
=20
+#if !defined(_AIX)
static void
test_memrchr (void)
{
@@ -615,6 +620,7 @@
}
}
}
+#endif /* !defined(_AIX) */
=20
static void
test_rindex (void)
@@ -890,6 +896,7 @@
equal(one+4, "c", 50);
=20
{
+# if !defined(_AIX)
char text[] =3D "This,is,a,test";
char *list =3D strdupa (text);
equal (strsep (&list, ","), "This", 51);
@@ -897,6 +904,7 @@
equal (strsep (&list, ","), "a", 53);
equal (strsep (&list, ","), "test", 54);
check (strsep (&list, ",") =3D=3D NULL, 55);
+# endif
}
=20
cp =3D strcpy(one, "a,b, c,, ,d,");
@@ -1049,6 +1057,7 @@
}
}
=20
+#if !defined(_AIX)
static void
test_mempcpy (void)
{
@@ -1085,6 +1094,7 @@
equal (two, "hi there", 12 + (i * 6));
}
}
+#endif /* !defined(_AIX) */
=20
static void
test_memmove (void)
@@ -1390,11 +1400,15 @@
/* strchr. */
test_strchr ();
=20
+# if !defined(_AIX)
/* strchrnul. */
test_strchrnul ();
+# endif
=20
+# if !defined(_AIX)
/* rawmemchr. */
test_rawmemchr ();
+# endif
=20
/* index - just like strchr. */
test_index ();
@@ -1402,8 +1416,10 @@
/* strrchr. */
test_strrchr ();
=20
+# if !defined(_AIX)
/* memrchr. */
test_memrchr ();
+# endif
=20
/* rindex - just like strrchr. */
test_rindex ();
@@ -1441,8 +1457,10 @@
/* memmove - must work on overlap. */
test_memmove ();
=20
+# if !defined(_AIX)
/* mempcpy */
test_mempcpy ();
+# endif
=20
/* memccpy. */
test_memccpy ();
@@ -1479,7 +1497,7 @@
else
{
status =3D EXIT_FAILURE;
- printf("%Zd errors.\n", errors);
+ printf("%d errors.\n", (int)errors);
}
=20
return status;
Modified: trunk/memcheck/tests/wrap5.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/wrap5.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/wrap5.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -1,6 +1,7 @@
=20
#include <stdio.h>
#include <malloc.h>
+#include <stdlib.h>
#include "valgrind.h"
=20
/* As wrap4.c, but also throw in various calls to another redirected
Modified: trunk/memcheck/tests/wrap8.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/wrap8.c 2006-10-17 01:25:13 UTC (rev 6253)
+++ trunk/memcheck/tests/wrap8.c 2006-10-17 01:26:12 UTC (rev 6254)
@@ -1,6 +1,7 @@
=20
#include <stdio.h>
#include <malloc.h>
+#include <stdlib.h>
#include "valgrind.h"
=20
/* This is the same as wrap5.c, except that the recursion depth is 16.
|
|
From: <sv...@va...> - 2006-10-17 01:25:16
|
Author: sewardj
Date: 2006-10-17 02:25:13 +0100 (Tue, 17 Oct 2006)
New Revision: 6253
Log:
Merge r6108:
Supply our own random number generator; else this test produces different
results on different platforms.
Modified:
trunk/memcheck/tests/oset_test.c
trunk/memcheck/tests/oset_test.stdout.exp
Modified: trunk/memcheck/tests/oset_test.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/oset_test.c 2006-10-17 01:23:57 UTC (rev 6252)
+++ trunk/memcheck/tests/oset_test.c 2006-10-17 01:25:13 UTC (rev 6253)
@@ -27,12 +27,26 @@
#define vgPlain_printf printf
#define vgPlain_memset memset
#define vgPlain_memcpy memcpy
-#define vgPlain_random random
=20
#include "coregrind/m_oset.c"
=20
#define NN 1000 // Size of OSets being created
=20
+
+/* Consistent random number generator, so it produces the
+ same results on all platforms. */
+
+#define random error_do_not_use_libc_random
+
+static UInt seed =3D 0;
+static UInt myrandom( void )
+{
+ seed =3D (1103515245 * seed + 12345);
+ return seed;
+}
+
+
+
//----------------------------------------------------------------------=
-----
// Word example
//----------------------------------------------------------------------=
-----
@@ -81,8 +95,8 @@
*(vs[i]) =3D 2*i;
}
for (i =3D 0; i < NN; i++) {
- Word r1 =3D random() % NN;
- Word r2 =3D random() % NN;
+ Word r1 =3D myrandom() % NN;
+ Word r2 =3D myrandom() % NN;
Word* tmp=3D vs[r1];
vs[r1] =3D vs[r2];
vs[r2] =3D tmp;
@@ -255,8 +269,8 @@
vs[i]->b2 =3D i+1;
}
for (i =3D 0; i < NN; i++) {
- Int r1 =3D random() % NN;
- Int r2 =3D random() % NN;
+ Int r1 =3D myrandom() % NN;
+ Int r2 =3D myrandom() % NN;
Block* tmp =3D vs[r1];
vs[r1] =3D vs[r2];
vs[r2] =3D tmp;
Modified: trunk/memcheck/tests/oset_test.stdout.exp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/memcheck/tests/oset_test.stdout.exp 2006-10-17 01:23:57 UTC (re=
v 6252)
+++ trunk/memcheck/tests/oset_test.stdout.exp 2006-10-17 01:25:13 UTC (re=
v 6253)
@@ -1,357 +1,358 @@
-- start foo ----------------
-.. .. .. .. .. .. .. .. .. .. 1998
-.. .. .. .. .. .. .. .. .. 1996
+.. .. .. .. .. .. .. .. .. 1998
+.. .. .. .. .. .. .. .. 1996
.. .. .. .. .. .. .. .. .. .. 1994
-.. .. .. .. .. .. .. .. 1992
-.. .. .. .. .. .. .. .. .. 1990
+.. .. .. .. .. .. .. .. .. 1992
+.. .. .. .. .. .. .. .. .. .. 1990
.. .. .. .. .. .. .. 1988
.. .. .. .. .. .. .. .. .. 1986
.. .. .. .. .. .. .. .. .. .. 1984
.. .. .. .. .. .. .. .. 1982
-.. .. .. .. .. .. .. .. .. 1980
-.. .. .. .. .. .. 1978
+.. .. .. .. .. .. .. .. .. .. 1980
+.. .. .. .. .. .. .. .. .. 1978
.. .. .. .. .. .. .. .. .. .. 1976
-.. .. .. .. .. .. .. .. .. 1974
+.. .. .. .. .. .. 1974
.. .. .. .. .. .. .. .. .. .. 1972
-.. .. .. .. .. .. .. .. 1970
-.. .. .. .. .. .. .. .. .. 1968
-.. .. .. .. .. .. .. 1966
+.. .. .. .. .. .. .. .. .. 1970
+.. .. .. .. .. .. .. .. .. .. 1968
+.. .. .. .. .. .. .. .. 1966
.. .. .. .. .. .. .. .. .. .. 1964
.. .. .. .. .. .. .. .. .. 1962
-.. .. .. .. .. .. .. .. .. .. 1960
-.. .. .. .. .. .. .. .. .. .. .. 1958
-.. .. .. .. .. .. .. .. 1956
-.. .. .. .. .. .. .. .. .. 1954
+.. .. .. .. .. .. .. 1960
+.. .. .. .. .. .. .. .. .. .. 1958
+.. .. .. .. .. .. .. .. .. 1956
+.. .. .. .. .. .. .. .. 1954
.. .. .. .. .. .. .. .. .. .. 1952
-.. .. .. .. .. 1950
+.. .. .. .. .. .. .. .. .. 1950
.. .. .. .. .. .. .. .. .. .. 1948
-.. .. .. .. .. .. .. .. .. 1946
-.. .. .. .. .. .. .. .. .. .. 1944
+.. .. .. .. .. 1946
+.. .. .. .. .. .. .. .. .. 1944
.. .. .. .. .. .. .. .. 1942
-.. .. .. .. .. .. .. .. .. 1940
+.. .. .. .. .. .. .. 1940
.. .. .. .. .. .. .. .. .. .. 1938
-.. .. .. .. .. .. .. 1936
-.. .. .. .. .. .. .. .. .. 1934
-.. .. .. .. .. .. .. .. .. .. 1932
-.. .. .. .. .. .. .. .. 1930
+.. .. .. .. .. .. .. .. .. 1936
+.. .. .. .. .. .. .. .. 1934
+.. .. .. .. .. .. .. .. .. 1932
+.. .. .. .. .. .. 1930
.. .. .. .. .. .. .. .. .. 1928
-.. .. .. .. .. .. 1926
-.. .. .. .. .. .. .. .. .. 1924
+.. .. .. .. .. .. .. .. .. .. 1926
+.. .. .. .. .. .. .. .. 1924
.. .. .. .. .. .. .. .. .. .. 1922
-.. .. .. .. .. .. .. .. 1920
-.. .. .. .. .. .. .. .. .. 1918
+.. .. .. .. .. .. .. .. .. 1920
+.. .. .. .. .. .. .. .. .. .. 1918
.. .. .. .. .. .. .. 1916
-.. .. .. .. .. .. .. .. .. .. 1914
-.. .. .. .. .. .. .. .. .. 1912
+.. .. .. .. .. .. .. .. .. 1914
+.. .. .. .. .. .. .. .. 1912
.. .. .. .. .. .. .. .. .. .. 1910
-.. .. .. .. .. .. .. .. 1908
-.. .. .. .. .. .. .. .. .. 1906
+.. .. .. .. .. .. .. .. .. 1908
+.. .. .. .. .. .. .. .. .. .. 1906
.. .. .. .. 1904
.. .. .. .. .. .. .. .. .. 1902
.. .. .. .. .. .. .. .. 1900
-.. .. .. .. .. .. .. .. .. 1898
-.. .. .. .. .. .. .. 1896
-.. .. .. .. .. .. .. .. .. .. 1894
+.. .. .. .. .. .. .. 1898
+.. .. .. .. .. .. .. .. .. 1896
+.. .. .. .. .. .. .. .. 1894
.. .. .. .. .. .. .. .. .. 1892
-.. .. .. .. .. .. .. .. .. .. 1890
-.. .. .. .. .. .. .. .. 1888
+.. .. .. .. .. .. 1890
+.. .. .. .. .. .. .. .. .. .. 1888
.. .. .. .. .. .. .. .. .. 1886
-.. .. .. .. .. .. 1884
-.. .. .. .. .. .. .. .. .. 1882
-.. .. .. .. .. .. .. .. 1880
-.. .. .. .. .. .. .. .. .. 1878
-.. .. .. .. .. .. .. .. .. .. 1876
-.. .. .. .. .. .. .. 1874
-.. .. .. .. .. .. .. .. .. 1872
+.. .. .. .. .. .. .. .. .. .. 1884
+.. .. .. .. .. .. .. .. 1882
+.. .. .. .. .. .. .. .. .. 1880
+.. .. .. .. .. .. .. 1878
+.. .. .. .. .. .. .. .. 1876
+.. .. .. .. .. .. .. .. .. 1874
+.. .. .. .. .. 1872
.. .. .. .. .. .. .. .. .. .. 1870
-.. .. .. .. .. .. .. .. 1868
-.. .. .. .. .. .. .. .. .. 1866
-.. .. .. .. .. 1864
+.. .. .. .. .. .. .. .. .. 1868
+.. .. .. .. .. .. .. .. .. .. 1866
+.. .. .. .. .. .. .. .. 1864
.. .. .. .. .. .. .. .. .. 1862
-.. .. .. .. .. .. .. .. 1860
+.. .. .. .. .. .. .. .. .. .. 1860
.. .. .. .. .. .. .. 1858
-.. .. .. .. .. .. .. .. 1856
-.. .. .. .. .. .. 1854
-.. .. .. .. .. .. .. .. 1852
-.. .. .. .. .. .. .. .. .. 1850
-.. .. .. .. .. .. .. 1848
+.. .. .. .. .. .. .. .. .. 1856
+.. .. .. .. .. .. .. .. 1854
+.. .. .. .. .. .. .. .. .. 1852
+.. .. .. .. .. .. 1848
.. .. .. .. .. .. .. .. .. 1846
.. .. .. .. .. .. .. .. 1844
-.. .. .. .. .. .. .. .. .. 1842
-.. .. .. 1840
-.. .. .. .. .. .. .. .. .. 1838
+.. .. .. .. .. .. .. .. .. .. 1842
+.. .. .. .. .. .. .. .. .. 1840
+.. .. .. .. .. .. .. 1838
.. .. .. .. .. .. .. .. .. .. 1836
-.. .. .. .. .. .. .. .. 1834
-.. .. .. .. .. .. .. .. .. 1832
-.. .. .. .. .. .. .. 1830
-.. .. .. .. .. .. .. .. .. 1828
-.. .. .. .. .. .. .. .. 1826
+.. .. .. .. .. .. .. .. .. 1834
+.. .. .. .. .. .. .. .. .. .. 1832
+.. .. .. .. .. .. .. .. 1830
+.. .. .. .. .. .. .. .. .. .. 1828
+.. .. .. .. .. .. .. .. .. 1826
.. .. .. .. .. .. .. .. .. .. 1824
-.. .. .. .. .. .. .. .. .. 1822
-.. .. .. .. .. .. 1820
-.. .. .. .. .. .. .. .. .. .. 1818
-.. .. .. .. .. .. .. .. .. 1816
-.. .. .. .. .. .. .. .. .. .. 1814
-.. .. .. .. .. .. .. .. 1812
-.. .. .. .. .. .. .. .. .. 1810
-.. .. .. .. .. .. .. 1808
-.. .. .. .. .. .. .. .. .. 1806
+.. .. .. 1822
+.. .. .. .. .. .. .. .. 1820
+.. .. .. .. .. .. .. .. .. 1818
+.. .. .. .. .. .. .. 1816
+.. .. .. .. .. .. .. .. 1814
+.. .. .. .. .. .. 1812
+.. .. .. .. .. .. .. .. 1810
+.. .. .. .. .. .. .. .. .. 1808
+.. .. .. .. .. .. .. 1806
.. .. .. .. .. .. .. .. 1804
.. .. .. .. .. 1802
.. .. .. .. .. .. .. .. 1800
.. .. .. .. .. .. .. .. .. 1798
.. .. .. .. .. .. .. 1796
-.. .. .. .. .. .. .. .. .. 1794
-.. .. .. .. .. .. .. .. 1792
-.. .. .. .. .. .. .. .. .. 1790
-.. .. .. .. .. .. 1788
-.. .. .. .. .. .. .. .. .. 1786
-.. .. .. .. .. .. .. .. 1784
-.. .. .. .. .. .. .. .. .. 1782
-.. .. .. .. .. .. .. 1780
-.. .. .. .. .. .. .. .. .. 1778
-.. .. .. .. .. .. .. .. 1776
-.. .. .. .. .. .. .. .. .. 1774
-.. .. .. .. 1772
-.. .. .. .. .. .. .. .. .. .. 1770
-.. .. .. .. .. .. .. .. .. 1768
-.. .. .. .. .. .. .. .. 1766
-.. .. .. .. .. .. .. .. .. 1764
-.. .. .. .. .. .. .. 1762
-.. .. .. .. .. .. .. .. .. .. 1760
+.. .. .. .. .. .. .. .. 1794
+.. .. .. .. .. .. 1792
+.. .. .. .. .. .. .. .. 1790
+.. .. .. .. .. .. .. .. .. 1788
+.. .. .. .. .. .. .. 1786
+.. .. .. .. .. .. .. .. .. 1784
+.. .. .. .. .. .. .. .. 1782
+.. .. .. .. .. .. .. .. .. 1780
+.. .. .. .. 1778
+.. .. .. .. .. .. .. .. .. 1776
+.. .. .. .. .. .. .. .. 1774
+.. .. .. .. .. .. .. 1772
+.. .. .. .. .. .. .. .. 1770
+.. .. .. .. .. .. 1768
+.. .. .. .. .. .. .. .. .. 1766
+.. .. .. .. .. .. .. .. 1764
+.. .. .. .. .. .. .. .. .. 1762
+.. .. .. .. .. .. .. 1760
.. .. .. .. .. .. .. .. .. 1758
.. .. .. .. .. .. .. .. 1756
-.. .. .. .. .. .. .. .. .. 1754
-.. .. .. .. .. .. .. .. .. .. 1752
-.. .. .. .. .. .. 1750
-.. .. .. .. .. .. .. .. .. .. 1748
-.. .. .. .. .. .. .. .. .. 1746
-.. .. .. .. .. .. .. .. .. .. 1744
-.. .. .. .. .. .. .. .. 1742
-.. .. .. .. .. .. .. .. .. .. 1740
+.. .. .. .. .. 1754
+.. .. .. .. .. .. .. .. 1752
+.. .. .. .. .. .. .. 1750
+.. .. .. .. .. .. .. .. .. 1748
+.. .. .. .. .. .. .. .. 1746
+.. .. .. .. .. .. 1744
+.. .. .. .. .. .. .. .. .. 1742
+.. .. .. .. .. .. .. .. 1740
.. .. .. .. .. .. .. .. .. 1738
.. .. .. .. .. .. .. 1736
-.. .. .. .. .. .. .. .. .. .. 1734
-.. .. .. .. .. .. .. .. .. 1732
-.. .. .. .. .. .. .. .. .. .. 1730
-.. .. .. .. .. .. .. .. 1728
-.. .. .. .. .. .. .. .. .. 1726
-.. .. .. .. .. 1724
-.. .. .. .. .. .. .. .. .. 1722
-.. .. .. .. .. .. .. .. 1720
-.. .. .. .. .. .. .. .. .. 1718
+.. .. .. .. .. .. .. .. .. 1734
+.. .. .. .. .. .. .. .. .. .. 1732
+.. .. .. .. .. .. .. .. 1730
+.. .. .. .. .. .. .. .. .. 1728
+.. .. 1726
+.. .. .. .. .. .. .. .. .. 1724
+.. .. .. .. .. .. .. .. 1722
+.. .. .. .. .. .. .. .. .. 1720
+.. .. .. .. .. .. .. .. .. .. 1718
.. .. .. .. .. .. .. 1716
.. .. .. .. .. .. .. .. .. 1714
.. .. .. .. .. .. .. .. 1712
-.. .. .. .. .. .. .. .. .. 1710
-.. .. .. .. .. .. 1708
-.. .. .. .. .. .. .. .. .. 1706
-.. .. .. .. .. .. .. .. 1704
+.. .. .. .. .. .. 1710
+.. .. .. .. .. .. .. .. .. 1708
+.. .. .. .. .. .. .. .. 1706
+.. .. .. .. .. .. .. 1704
.. .. .. .. .. .. .. .. .. 1702
-.. .. .. .. .. .. .. 1700
+.. .. .. .. .. .. .. .. .. .. 1700
.. .. .. .. .. .. .. .. 1698
-.. .. 1696
-.. .. .. .. .. .. .. .. .. .. 1694
-.. .. .. .. .. .. .. .. .. 1692
-.. .. .. .. .. .. .. .. .. .. 1690
-.. .. .. .. .. .. .. .. 1688
+.. .. .. .. .. .. .. .. .. 1696
+.. .. .. .. .. 1694
+.. .. .. .. .. .. .. .. 1692
+.. .. .. .. .. .. .. .. .. 1690
+.. .. .. .. .. .. .. 1688
.. .. .. .. .. .. .. .. .. 1686
-.. .. .. .. .. .. .. .. .. .. 1684
-.. .. .. .. .. .. .. 1680
+.. .. .. .. .. .. .. .. 1684
+.. .. .. .. .. .. .. .. .. 1682
+.. .. .. .. .. .. 1680
.. .. .. .. .. .. .. .. 1678
-.. .. .. .. .. .. .. .. .. 1676
-.. .. .. .. .. .. 1672
-.. .. .. .. .. .. .. .. .. .. 1670
-.. .. .. .. .. .. .. .. .. 1668
-.. .. .. .. .. .. .. .. 1666
-.. .. .. .. .. .. .. .. .. .. .. 1664
-.. .. .. .. .. .. .. .. .. .. 1662
-.. .. .. .. .. .. .. .. .. 1660
-.. .. .. .. .. .. .. .. .. .. 1658
-.. .. .. .. .. .. .. .. .. .. .. 1656
-.. .. .. .. .. .. .. 1654
-.. .. .. .. .. .. .. .. .. 1652
-.. .. .. .. .. .. .. .. .. .. 1650
-.. .. .. .. .. .. .. .. 1648
-.. .. .. .. .. .. .. .. .. .. 1646
+.. .. .. .. .. .. .. 1676
+.. .. .. .. 1674
+.. .. .. .. .. .. .. .. 1672
+.. .. .. .. .. .. .. 1670
+.. .. .. .. .. .. .. .. 1668
+.. .. .. .. .. .. 1666
+.. .. .. .. .. .. .. .. .. 1664
+.. .. .. .. .. .. .. .. 1662
+.. .. .. .. .. .. .. 1660
+.. .. .. .. .. .. .. .. 1658
+.. .. .. .. .. 1656
+.. .. .. .. .. .. .. .. .. 1654
+.. .. .. .. .. .. .. .. 1652
+.. .. .. .. .. .. .. 1650
+.. .. .. .. .. .. .. .. .. 1648
+.. .. .. .. .. .. .. .. 1646
.. .. .. .. .. .. .. .. .. 1644
-.. .. .. .. .. .. .. .. .. .. 1642
-.. .. .. .. .. 1640
+.. .. .. .. .. .. 1642
+.. .. .. .. .. .. .. .. 1640
.. .. .. .. .. .. .. .. .. 1638
-.. .. .. .. .. .. .. .. 1636
-.. .. .. .. .. .. .. .. .. .. 1634
-.. .. .. .. .. .. .. .. .. 1632
-.. .. .. .. .. .. .. .. .. .. 1630
-.. .. .. .. .. .. .. 1628
-.. .. .. .. .. .. .. .. .. 1626
-.. .. .. .. .. .. .. .. 1624
+.. .. .. .. .. .. .. 1636
+.. .. .. .. .. .. .. .. .. 1634
+.. .. .. .. .. .. .. .. 1632
+.. .. .. .. .. .. .. .. .. 1630
+.. .. .. 1628
+.. .. .. .. .. .. .. .. 1626
+.. .. .. .. .. .. .. 1624
.. .. .. .. .. .. 1622
-.. .. .. .. .. .. .. .. .. .. 1620
-.. .. .. .. .. .. .. .. .. 1618
-.. .. .. .. .. .. .. .. .. .. 1616
+.. .. .. .. .. .. .. .. 1620
+.. .. .. .. .. .. .. 1618
+.. .. .. .. .. .. .. .. .. 1616
.. .. .. .. .. .. .. .. 1614
-.. .. .. .. .. .. .. .. .. 1612
-.. .. .. .. .. .. .. .. .. .. 1610
-.. .. .. .. .. .. .. 1608
-.. .. .. .. .. .. .. .. .. 1606
-.. .. .. .. .. .. .. .. 1604
-.. .. .. .. .. .. .. .. .. 1602
-.. .. .. .. 1600
-.. .. .. .. .. .. .. .. .. .. 1598
-.. .. .. .. .. .. .. .. .. 1596
-.. .. .. .. .. .. .. .. 1594
-.. .. .. .. .. .. .. .. .. 1592
-.. .. .. .. .. .. .. 1590
-.. .. .. .. .. .. .. .. .. 1588
+.. .. .. .. .. 1612
+.. .. .. .. .. .. .. .. .. 1610
+.. .. .. .. .. .. .. .. 1608
+.. .. .. .. .. .. .. 1606
+.. .. .. .. .. .. .. .. .. 1604
+.. .. .. .. .. .. .. .. 1602
+.. .. .. .. .. .. .. .. .. 1600
+.. .. .. .. .. .. 1598
+.. .. .. .. .. .. .. .. 1596
+.. .. .. .. .. .. .. .. .. 1594
+.. .. .. .. .. .. .. 1592
+.. .. .. .. .. .. .. .. 1590
+.. .. .. .. 1588
.. .. .. .. .. .. .. .. 1586
-.. .. .. .. .. .. .. .. .. .. 1584
+.. .. .. .. .. .. .. 1584
.. .. .. .. .. .. .. .. .. 1582
-.. .. .. .. .. .. .. .. .. .. 1580
+.. .. .. .. .. .. .. .. 1580
.. .. .. .. .. .. 1578
-.. .. .. .. .. .. .. .. .. .. 1576
-.. .. .. .. .. .. .. .. .. 1574
+.. .. .. .. .. .. .. .. 1576
+.. .. .. .. .. .. .. 1574
.. .. .. .. .. .. .. .. 1572
.. .. .. .. .. .. .. .. .. 1570
-.. .. .. .. .. .. .. 1568
-.. .. .. .. .. .. .. .. .. 1566
-.. .. .. .. .. .. .. .. 1564
+.. .. .. .. .. 1568
+.. .. .. .. .. .. .. .. 1566
+.. .. .. .. .. .. .. 1564
.. .. .. .. .. .. .. .. .. 1562
-.. .. .. .. .. 1560
-.. .. .. .. .. .. .. .. .. .. 1558
-.. .. .. .. .. .. .. .. .. 1556
+.. .. .. .. .. .. .. .. 1560
+.. .. .. .. .. .. .. .. .. 1558
+.. .. .. .. .. .. 1556
.. .. .. .. .. .. .. .. 1554
-.. .. .. .. .. .. .. .. .. .. 1552
-.. .. .. .. .. .. .. .. .. 1550
-.. .. .. .. .. .. .. 1548
-.. .. .. .. .. .. .. .. .. 1546
-.. .. .. .. .. .. .. .. 1544
-.. .. .. .. .. .. .. .. .. 1542
+.. .. .. .. .. .. .. 1552
+.. .. .. .. .. .. .. .. 1550
+.. 1548
+.. .. .. .. .. .. .. .. 1546
+.. .. .. .. .. .. .. 1544
+.. .. .. .. .. .. .. .. 1542
.. .. .. .. .. .. 1540
.. .. .. .. .. .. .. .. .. 1538
.. .. .. .. .. .. .. .. 1536
-.. .. .. .. .. .. .. .. .. 1534
-.. .. .. .. .. .. .. 1532
-.. .. .. .. .. .. .. .. 1530
+.. .. .. .. .. .. .. 1534
+.. .. .. .. .. .. .. .. 1532
+.. .. .. .. .. 1530
.. .. .. .. .. .. .. .. .. 1528
-.. .. .. 1526
-.. .. .. .. .. .. .. .. .. 1524
+.. .. .. .. .. .. .. .. 1526
+.. .. .. .. .. .. .. 1524
.. .. .. .. .. .. .. .. 1522
-.. .. .. .. .. .. .. 1520
-.. .. .. .. .. .. .. .. .. 1518
-.. .. .. .. .. .. .. .. .. .. 1516
-.. .. .. .. .. .. .. .. 1514
-.. .. .. .. .. .. .. .. .. .. 1512
-.. .. .. .. .. .. .. .. .. 1510
-.. .. .. .. .. .. 1508
-.. .. .. .. .. .. .. .. .. 1506
-.. .. .. .. .. .. .. .. 1504
-.. .. .. .. .. .. .. .. .. 1502
-.. .. .. .. .. .. .. 1500
-.. .. .. .. .. .. .. .. .. 1498
+.. .. .. .. .. .. .. .. .. 1520
+.. .. .. .. .. .. 1518
+.. .. .. .. .. .. .. .. 1516
+.. .. .. .. .. .. .. 1514
+.. .. .. .. .. .. .. .. .. 1512
+.. .. .. .. .. .. .. .. 1510
+.. .. .. .. 1508
+.. .. .. .. .. .. .. .. 1506
+.. .. .. .. .. .. .. 1504
+.. .. .. .. .. .. .. .. 1502
+.. .. .. .. .. .. 1500
+.. .. .. .. .. .. .. 1498
.. .. .. .. .. .. .. .. 1496
-.. .. .. .. .. .. .. .. .. 1494
-.. .. .. .. .. .. .. .. .. .. 1492
-.. .. .. .. .. 1490
-.. .. .. .. .. .. .. .. .. .. 1488
+.. .. .. .. .. 1494
+.. .. .. .. .. .. .. 1492
+.. .. .. .. .. .. .. .. 1490
+.. .. .. .. .. .. 1488
.. .. .. .. .. .. .. .. .. 1486
-.. .. .. .. .. .. .. .. .. .. 1484
-.. .. .. .. .. .. .. .. 1482
-.. .. .. .. .. .. .. .. .. 1480
-.. .. .. .. .. .. .. 1478
-.. .. .. .. .. .. .. .. .. .. 1476
+.. .. .. .. .. .. .. .. 1484
+.. .. .. .. .. .. .. .. .. 1482
+.. .. .. .. .. .. .. 1480
+.. .. .. .. .. .. .. .. .. 1478
+.. .. .. .. .. .. .. .. 1476
.. .. .. .. .. .. .. .. .. 1474
-.. .. .. .. .. .. .. .. 1472
+.. .. .. 1472
.. .. .. .. .. .. .. .. .. .. 1470
.. .. .. .. .. .. .. .. .. 1468
.. .. .. .. .. .. .. .. .. .. 1466
-.. .. .. .. .. .. 1464
+.. .. .. .. .. .. .. .. 1464
.. .. .. .. .. .. .. .. .. 1462
-.. .. .. .. .. .. .. .. 1460
-.. .. .. .. .. .. .. .. .. 1458
-.. .. .. .. .. .. .. 1456
-.. .. .. .. .. .. .. .. .. 1454
+.. .. .. .. .. .. .. 1460
+.. .. .. .. .. .. .. .. .. .. 1458
+.. .. .. .. .. .. .. .. .. 1456
+.. .. .. .. .. .. .. .. .. .. 1454
.. .. .. .. .. .. .. .. 1452
-.. .. .. .. .. .. .. .. .. .. 1450
-.. .. .. .. .. .. .. .. .. 1448
-.. .. .. .. 1446
-.. .. .. .. .. .. .. .. .. .. 1444
-.. .. .. .. .. .. .. .. .. 1442
-.. .. .. .. .. .. .. .. 1440
-.. .. .. .. .. .. .. .. .. 1438
-.. .. .. .. .. .. .. .. .. .. 1436
-.. .. .. .. .. .. .. 1434
-.. .. .. .. .. .. .. .. .. .. 1432
-.. .. .. .. .. .. .. .. .. 1430
-.. .. .. .. .. .. .. .. 1428
-.. .. .. .. .. .. .. .. .. .. 1426
-.. .. .. .. .. .. .. .. .. 1424
-.. .. .. .. .. .. .. .. .. .. .. 1422
+.. .. .. .. .. .. .. .. .. 1450
+.. .. .. .. .. .. .. .. .. .. 1448
+.. .. .. .. .. .. 1446
+.. .. .. .. .. .. .. .. .. 1444
+.. .. .. .. .. .. .. .. 1442
+.. .. .. .. .. .. .. .. .. 1440
+.. .. .. .. .. .. .. 1438
+.. .. .. .. .. .. .. .. 1436
+.. .. .. .. .. 1434
+.. .. .. .. .. .. .. .. .. 1432
+.. .. .. .. .. .. .. .. 1430
+.. .. .. .. .. .. .. .. .. 1428
+.. .. .. .. .. .. .. 1426
+.. .. .. .. .. .. .. .. .. .. 1424
+.. .. .. .. .. .. .. .. .. 1422
.. .. .. .. .. .. .. .. .. .. 1420
-.. .. .. .. .. .. .. .. .. .. .. 1418
-.. .. .. .. .. .. 1416
-.. .. .. .. .. .. .. .. .. .. 1414
-.. .. .. .. .. .. .. .. .. 1412
-.. .. .. .. .. .. .. .. .. .. 1410
-.. .. .. .. .. .. .. .. .. .. .. 1408
-.. .. .. .. .. .. .. .. 1406
+.. .. .. .. .. .. .. .. 1418
+.. .. .. .. .. .. .. .. .. .. 1416
+.. .. .. .. .. .. .. .. .. 1414
+.. .. .. .. .. .. 1412
+.. .. .. .. .. .. .. .. .. 1410
+.. .. .. .. .. .. .. .. 1408
+.. .. .. .. .. .. .. .. .. 1406
.. .. .. .. .. .. .. .. .. .. 1404
-.. .. .. .. .. .. .. .. .. 1402
+.. .. .. .. .. .. .. 1402
.. .. .. .. .. .. .. .. .. .. 1400
-.. .. .. .. .. .. .. 1398
+.. .. .. .. .. .. .. .. .. 1398
.. .. .. .. .. .. .. .. .. .. 1396
-.. .. .. .. .. .. .. .. .. 1394
-.. .. .. .. .. .. .. .. .. .. .. 1392
-.. .. .. .. .. .. .. .. .. .. 1390
-.. .. .. .. .. .. .. .. 1388
+.. .. .. .. .. .. .. .. 1394
+.. .. .. .. .. .. .. .. .. .. 1392
+.. .. .. .. .. .. .. .. .. 1390
+.. .. .. .. 1388
.. .. .. .. .. .. .. .. .. .. 1386
.. .. .. .. .. .. .. .. .. 1384
-.. .. .. .. .. .. .. .. .. .. 1382
-.. .. .. .. .. .. .. .. .. .. .. 1380
-.. .. .. .. .. 1378
+.. .. .. .. .. .. .. .. 1382
+.. .. .. .. .. .. .. .. .. .. 1380
+.. .. .. .. .. .. .. .. .. 1378
.. .. .. .. .. .. .. .. .. .. 1376
-.. .. .. .. .. .. .. .. .. 1374
-.. .. .. .. .. .. .. .. .. .. 1372
-.. .. .. .. .. .. .. .. 1370
-.. .. .. .. .. .. .. .. .. .. 1368
-.. .. .. .. .. .. .. .. .. 1366
-.. .. .. .. .. .. .. 1364
-.. .. .. .. .. .. .. .. .. 1362
-.. .. .. .. .. .. .. .. .. .. 1360
-.. .. .. .. .. .. .. .. 1358
-.. .. .. .. .. .. .. .. .. 1356
-.. .. .. .. .. .. 1354
-.. .. .. .. .. .. .. .. .. 1352
+.. .. .. .. .. .. .. 1374
+.. .. .. .. .. .. .. .. 1372
+.. .. .. .. .. .. .. .. .. 1370
+.. .. .. .. .. .. 1368
+.. .. .. .. .. .. .. .. .. .. 1366
+.. .. .. .. .. .. .. .. .. 1364
+.. .. .. .. .. .. .. .. .. .. 1362
+.. .. .. .. .. .. .. .. 1360
+.. .. .. .. .. .. .. .. .. 1358
+.. .. .. .. .. .. .. 1356
+.. .. .. .. .. .. .. .. .. 1354
+.. .. .. .. .. .. .. .. .. .. 1352
.. .. .. .. .. .. .. .. 1350
.. .. .. .. .. .. .. .. .. .. 1348
.. .. .. .. .. .. .. .. .. 1346
-.. .. .. .. .. .. .. 1344
-.. .. .. .. .. .. .. .. .. 1342
+.. .. .. .. .. .. .. .. .. .. 1344
+.. .. .. .. .. 1342
.. .. .. .. .. .. .. .. .. .. 1340
-.. .. .. .. .. .. .. .. 1338
-.. .. .. .. .. .. .. .. .. .. 1336
-.. .. .. .. .. .. .. .. .. 1334
-.. .. .. .. .. .. .. .. .. .. 1332
-.. 1330
-.. .. .. .. .. .. .. .. 1328
-.. .. .. .. .. .. .. .. .. 1326
-.. .. .. .. .. .. .. 1324
-.. .. .. .. .. .. .. .. .. 1322
+.. .. .. .. .. .. .. .. .. 1338
+.. .. .. .. .. .. .. .. 1336
+.. .. .. .. .. .. .. .. .. .. 1334
+.. .. .. .. .. .. .. .. .. 1332
+.. .. .. .. .. .. .. .. .. .. 1330
+.. .. .. .. .. .. .. 1328
+.. .. .. .. .. .. .. .. .. .. 1326
+.. .. .. .. .. .. .. .. .. 1324
+.. .. .. .. .. .. .. .. .. .. 1322
.. .. .. .. .. .. .. .. 1320
.. .. .. .. .. .. .. .. .. 1318
-.. .. .. .. .. .. 1316
-.. .. .. .. .. .. .. .. .. 1314
+.. .. .. .. .. .. .. .. .. .. 1316
+.. .. .. .. .. .. 1314
.. .. .. .. .. .. .. .. 1312
.. .. .. .. .. .. .. .. .. 1310
.. .. .. .. .. .. .. 1308
-.. .. .. .. .. .. .. .. .. 1306
-.. .. .. .. .. .. .. .. .. .. 1304
-.. .. .. .. .. .. .. .. 1302
-.. .. .. .. .. .. .. .. .. .. 1300
+.. .. .. .. .. .. .. .. .. .. 1306
+.. .. .. .. .. .. .. .. .. 1304
+.. .. .. .. .. .. .. .. .. .. 1302
+.. .. .. .. .. .. .. .. 1300
.. .. .. .. .. .. .. .. .. 1298
-.. .. .. .. .. 1296
-.. .. .. .. .. .. .. .. .. 1294
-.. .. .. .. .. .. .. .. 1292
-.. .. .. .. .. .. .. .. .. 1290
+.. .. .. .. .. .. .. .. .. .. 1296
+.. .. 1294
+.. .. .. .. .. .. .. .. .. 1292
+.. .. .. .. .. .. .. .. 1290
.. .. .. .. .. .. .. 1288
.. .. .. .. .. .. .. .. .. 1286
.. .. .. .. .. .. .. .. 1284
@@ -359,641 +360,640 @@
.. .. .. .. .. .. 1280
.. .. .. .. .. .. .. .. 1278
.. .. .. .. .. .. .. 1276
-.. .. .. .. .. .. .. .. 1274
-.. .. .. .. 1272
+.. .. .. .. .. 1274
+.. .. .. .. .. .. .. .. 1272
.. .. .. .. .. .. .. .. .. 1270
-.. .. .. .. .. .. .. .. 1268
+.. .. .. .. .. .. .. 1268
.. .. .. .. .. .. .. .. .. 1266
-.. .. .. .. .. .. .. 1264
-.. .. .. .. .. .. .. .. 1262
+.. .. .. .. .. .. .. .. 1264
+.. .. .. .. .. .. .. .. .. 1262
.. .. .. .. .. .. 1260
-.. .. .. .. .. .. .. .. .. .. 1258
-.. .. .. .. .. .. .. .. .. 1256
-.. .. .. .. .. .. .. .. .. .. 1254
-.. .. .. .. .. .. .. .. 1252
+.. .. .. .. .. .. .. .. .. 1258
+.. .. .. .. .. .. .. .. 1256
+.. .. .. .. .. .. .. 1254
+.. .. .. .. .. .. .. .. .. .. 1252
.. .. .. .. .. .. .. .. .. 1250
-.. .. .. .. .. .. .. 1248
+.. .. .. .. .. .. .. .. 1248
.. .. .. .. .. .. .. .. .. 1246
.. .. .. .. .. .. .. .. .. .. 1244
-.. .. .. .. .. .. .. .. 1242
+.. .. .. .. 1242
.. .. .. .. .. .. .. .. .. 1240
-.. .. .. .. .. .. .. .. .. .. 1238
-.. .. .. .. .. 1236
-.. .. .. .. .. .. .. .. .. 1234
-.. .. .. .. .. .. .. .. .. .. 1232
-.. .. .. .. .. .. .. .. 1230
+.. .. .. .. .. .. .. .. 1238
+.. .. .. .. .. .. .. .. .. 1236
+.. .. .. .. .. .. .. 1234
+.. .. .. .. .. .. .. .. 1232
+.. .. .. .. .. .. 1230
.. .. .. .. .. .. .. .. .. 1228
-.. .. .. .. .. .. .. 1226
-.. .. .. .. .. .. .. .. 1224
+.. .. .. .. .. .. .. .. 1226
+.. .. .. .. .. .. .. 1224
.. .. .. .. .. .. .. .. .. 1222
-.. .. .. .. .. .. 1220
+.. .. .. .. .. .. .. .. 1220
.. .. .. .. .. .. .. .. .. 1218
-.. .. .. .. .. .. .. .. 1216
+.. .. .. .. .. 1216
.. .. .. .. .. .. .. .. .. 1214
-.. .. .. .. .. .. .. 1212
+.. .. .. .. .. .. .. .. 1212
.. .. .. .. .. .. .. .. .. 1210
-.. .. .. .. .. .. .. .. 1208
-.. .. .. 1206
-.. .. .. .. .. .. .. .. .. 1204
-.. .. .. .. .. .. .. .. 1202
-.. .. .. .. .. .. .. 1200
+.. .. .. .. .. .. .. 1208
+.. .. .. .. .. .. .. .. 1206
+.. .. .. .. .. .. 1204
+.. .. .. .. .. .. .. .. .. 1202
+.. .. .. .. .. .. .. .. .. .. 1200
.. .. .. .. .. .. .. .. 1198
-.. .. .. .. .. .. 1196
-.. .. .. .. .. .. .. .. 1194
-.. .. .. .. .. .. .. 1192
-.. .. .. .. .. .. .. .. .. 1190
-.. .. .. .. .. .. .. .. 1188
-.. .. .. .. .. 1186
-.. .. .. .. .. .. .. .. 1184
-.. .. .. .. .. .. .. 1182
+.. .. .. .. .. .. .. .. .. 1196
+.. .. .. .. .. .. .. 1194
+.. .. .. .. .. .. .. .. .. 1192
+.. .. .. .. .. .. .. .. 1190
+.. .. .. .. .. .. .. .. .. 1188
+.. .. .. 1186
+.. .. .. .. .. .. .. .. .. 1184
+.. .. .. .. .. .. .. .. .. .. 1182
.. .. .. .. .. .. .. .. 1180
-.. .. .. .. .. .. 1178
-.. .. .. .. .. .. .. .. 1176
+.. .. .. .. .. .. .. .. .. 1178
+.. .. .. .. .. .. .. 1176
.. .. .. .. .. .. .. .. .. 1174
-.. .. .. .. .. .. .. 1172
-.. .. .. .. .. .. .. .. .. 1170
-.. .. .. .. .. .. .. .. 1168
-.. .. .. .. 1166
-.. .. .. .. .. .. .. .. 1164
-.. .. .. .. .. .. .. 1162
+.. .. .. .. .. .. .. .. .. .. 1172
+.. .. .. .. .. .. .. .. 1170
+.. .. .. .. .. .. .. .. .. 1168
+.. .. .. .. .. .. 1166
+.. .. .. .. .. .. .. .. .. .. 1164
+.. .. .. .. .. .. .. .. .. 1162
.. .. .. .. .. .. .. .. 1160
-.. .. .. .. .. .. 1158
-.. .. .. .. .. .. .. .. .. 1156
-.. .. .. .. .. .. .. .. 1154
-.. .. .. .. .. .. .. .. .. 1152
-.. .. .. .. .. .. .. 1150
-.. .. .. .. .. .. .. .. 1148
-.. .. .. .. .. 1146
+.. .. .. .. .. .. .. .. .. 1158
+.. .. .. .. .. .. .. .. .. .. 1156
+.. .. .. .. .. .. .. 1152
+.. .. .. .. .. .. .. .. .. 1150
+.. .. .. .. .. .. .. .. .. .. 1148
+.. .. .. .. .. .. .. .. 1146
.. .. .. .. .. .. .. .. .. 1144
-.. .. .. .. .. .. .. .. 1142
+.. .. .. .. .. 1142
.. .. .. .. .. .. .. .. .. 1140
-.. .. .. .. .. .. .. 1138
+.. .. .. .. .. .. .. .. 1138
.. .. .. .. .. .. .. .. .. 1136
-.. .. .. .. .. .. .. .. 1134
+.. .. .. .. .. .. .. 1134
.. .. .. .. .. .. .. .. .. 1132
-.. .. .. .. .. .. 1130
-.. .. .. .. .. .. .. .. 1128
-.. .. .. .. .. .. .. 1126
-.. .. .. .. .. .. .. .. 1124
+.. .. .. .. .. .. .. .. 1130
+.. .. .. .. .. .. .. .. .. 1128
+.. .. .. .. .. .. .. .. .. .. 1126
+.. .. .. .. .. .. 1124
.. .. .. .. .. .. .. .. .. 1122
-.. .. 1120
+.. .. .. .. .. .. .. .. 1120
.. .. .. .. .. .. .. .. .. 1118
-.. .. .. .. .. .. .. .. 1116
-.. .. .. .. .. .. .. .. .. .. 1114
-.. .. .. .. .. .. .. .. .. 1112
-.. .. .. .. .. .. .. 1110
-.. .. .. .. .. .. .. .. .. 1108
-.. .. .. .. .. .. .. .. 1106
-.. .. .. .. .. .. 1104
+.. .. .. .. .. .. .. .. .. .. 1116
+.. .. .. .. .. .. .. 1114
+.. .. .. .. .. .. .. .. 1112
+.. .. .. .. .. .. .. .. .. 1110
+.. .. .. .. 1108
+.. .. .. .. .. .. .. .. .. 1106
+.. .. .. .. .. .. .. .. 1104
.. .. .. .. .. .. .. .. .. 1102
-.. .. .. .. .. .. .. .. 1100
-.. .. .. .. .. .. .. 1098
+.. .. .. .. .. .. .. 1100
+.. .. .. .. .. .. .. .. .. 1098
.. .. .. .. .. .. .. .. .. .. 1096
-.. .. .. .. .. .. .. .. .. 1094
-.. .. .. .. .. .. .. .. 1092
-.. .. .. .. .. .. .. .. .. 1090
-.. .. .. .. .. .. .. .. .. .. 1088
-.. .. .. .. .. 1086
-.. .. .. .. .. .. .. .. .. .. 1084
-.. .. .. .. .. .. .. .. .. 1082
-.. .. .. .. .. .. .. .. .. .. 1080
-.. .. .. .. .. .. .. .. 1078
-.. .. .. .. .. .. .. .. .. 1076
-.. .. .. .. .. .. .. .. .. .. 1074
-.. .. .. .. .. .. .. 1072
+.. .. .. .. .. .. .. .. 1094
+.. .. .. .. .. .. .. .. .. 1092
+.. .. .. .. .. .. 1090
+.. .. .. .. .. .. .. .. 1088
+.. .. .. .. .. .. .. .. .. 1086
+.. .. .. .. .. .. .. 1084
+.. .. .. .. .. .. .. .. 1082
+.. .. .. .. .. .. .. .. .. 1080
+.. .. .. .. .. 1078
+.. .. .. .. .. .. .. .. 1076
+.. .. .. .. .. .. .. 1074
+.. .. .. .. .. .. .. .. 1072
.. .. .. .. .. .. .. .. .. 1070
-.. .. .. .. .. .. .. .. 1068
-.. .. .. .. .. .. .. .. .. 1066
-.. .. .. .. .. .. 1064
-.. .. .. .. .. .. .. .. .. 1062
-.. .. .. .. .. .. .. .. 1060
-.. .. .. .. .. .. .. 1058
+.. .. .. .. .. .. 1068
+.. .. .. .. .. .. .. 1066
+.. .. .. .. .. .. .. .. 1064
+1062
+.. .. .. .. .. .. .. .. .. 1060
+.. .. .. .. .. .. .. .. 1058
.. .. .. .. .. .. .. .. .. 1056
-.. .. .. .. .. .. .. .. .. .. 1054
-.. .. .. .. .. .. .. .. 1052
-.. .. .. .. .. .. .. .. .. .. 1050
-.. .. .. .. .. .. .. .. .. 1048
-.. .. .. .. 1046
-.. .. .. .. .. .. .. .. .. 1044
-.. .. .. .. .. .. .. .. 1042
-.. .. .. .. .. .. .. .. .. 1040
-.. .. .. .. .. .. .. 1038
-.. .. .. .. .. .. .. .. 1036
-.. .. .. .. .. .. .. .. .. 1034
-.. .. .. .. .. .. 1032
+.. .. .. .. .. .. .. 1054
+.. .. .. .. .. .. .. .. .. 1052
+.. .. .. .. .. .. .. .. 1050
+.. .. .. .. .. .. .. .. .. .. 1048
+.. .. .. .. .. .. .. .. .. 1046
+.. .. .. .. .. .. 1044
+.. .. .. .. .. .. .. .. .. .. 1042
+.. .. .. .. .. .. .. .. .. .. .. 1040
+.. .. .. .. .. .. .. .. .. 1038
+.. .. .. .. .. .. .. .. .. .. .. 1036
+.. .. .. .. .. .. .. .. .. .. 1034
+.. .. .. .. .. .. .. .. .. .. .. 1032
.. .. .. .. .. .. .. .. 1030
-.. .. .. .. .. .. .. 1028
+.. .. .. .. .. .. .. .. .. .. 1028
.. .. .. .. .. .. .. .. .. 1026
-.. .. .. .. .. .. .. .. 1024
-.. .. .. .. .. .. .. .. .. 1022
-.. .. .. .. .. 1020
-.. .. .. .. .. .. .. 1018
-.. .. .. .. .. .. 1016
+.. .. .. .. .. .. .. .. .. .. 1024
+.. .. .. .. .. .. .. 1022
+.. .. .. .. .. .. .. .. .. .. 1020
+.. .. .. .. .. .. .. .. .. 1018
+.. .. .. .. .. .. .. .. .. .. 1016
.. .. .. .. .. .. .. .. 1014
-.. .. .. .. .. .. .. 1012
-.. .. .. .. .. .. .. .. 1010
-.. .. .. 1008
-.. .. .. .. .. .. .. .. .. 1006
-.. .. .. .. .. .. .. .. 1004
-.. .. .. .. .. .. .. .. .. 1002
-.. .. .. .. .. .. .. 1000
-.. .. .. .. .. .. .. .. .. 998
-.. .. .. .. .. .. .. .. 996
-.. .. .. .. .. .. 994
-.. .. .. .. .. .. .. .. 992
-.. .. .. .. .. .. .. 990
+.. .. .. .. .. .. .. .. .. .. 1012
+.. .. .. .. .. .. .. .. .. 1010
+.. .. .. .. .. .. .. .. .. .. 1008
+.. .. .. .. .. 1006
+.. .. .. .. .. .. .. .. .. 1004
+.. .. .. .. .. .. .. .. 1002
+.. .. .. .. .. .. .. .. .. 1000
+.. .. .. .. .. .. .. 998
+.. .. .. .. .. .. .. .. .. .. 996
+.. .. .. .. .. .. .. .. .. 994
+.. .. .. .. .. .. .. .. .. .. 992
+.. .. .. .. .. .. .. .. 990
.. .. .. .. .. .. .. .. .. 988
-.. .. .. .. .. .. .. .. 986
-.. .. .. .. .. .. .. .. .. 984
-.. .. .. .. .. 982
-.. .. .. .. .. .. .. .. 980
-.. .. .. .. .. .. .. 978
-.. .. .. .. .. .. 976
-.. .. .. .. .. .. .. .. 974
+.. .. .. .. .. .. 986
+.. .. .. .. .. .. .. .. .. .. 984
+.. .. .. .. .. .. .. .. .. 982
+.. .. .. .. .. .. .. .. .. .. 980
+.. .. .. .. .. .. .. .. 978
+.. .. .. .. .. .. .. .. .. 976
+.. .. .. .. .. .. .. .. .. .. 974
.. .. .. .. .. .. .. 972
-.. .. .. .. .. .. .. .. 970
-.. .. .. .. .. .. .. .. .. 968
-.. .. .. .. 966
-.. .. .. .. .. .. .. .. .. 964
-.. .. .. .. .. .. .. .. 962
-.. .. .. .. .. .. .. .. .. 960
-.. .. .. .. .. .. .. 958
+.. .. .. .. .. .. .. .. .. 970
+.. .. .. .. .. .. .. .. 968
+.. .. .. .. .. .. .. .. .. 966
+.. .. .. .. 964
+.. .. .. .. .. .. .. .. .. 962
+.. .. .. .. .. .. .. .. .. .. 960
+.. .. .. .. .. .. .. .. 958
.. .. .. .. .. .. .. .. .. 956
-.. .. .. .. .. .. .. .. 954
-.. .. .. .. .. .. .. .. .. 952
-.. .. .. .. .. .. .. .. .. .. 950
+.. .. .. .. .. .. .. 954
+.. .. .. .. .. .. .. .. 952
+.. .. .. .. .. .. .. .. .. 950
.. .. .. .. .. .. 948
.. .. .. .. .. .. .. .. .. 946
-.. .. .. .. .. .. .. .. 944
-.. .. .. .. .. .. .. .. .. 942
-.. .. .. .. .. .. .. 940
-.. .. .. .. .. .. .. .. .. .. 938
-.. .. .. .. .. .. .. .. .. 936
-.. .. .. .. .. .. .. .. .. .. 934
+.. .. .. .. .. .. .. .. .. .. 944
+.. .. .. .. .. .. .. .. 942
+.. .. .. .. .. .. .. .. .. 940
+.. .. .. .. .. .. .. 938
+.. .. .. .. .. .. .. .. .. .. 936
+.. .. .. .. .. .. .. .. .. 934
.. .. .. .. .. .. .. .. 932
-.. .. .. .. .. .. .. .. .. 930
-.. .. .. .. .. .. .. .. .. .. 928
-.. .. .. .. .. 926
-.. .. .. .. .. .. .. .. .. .. 924
+.. .. .. .. .. .. .. .. .. .. 930
+.. .. .. .. .. .. .. .. .. 928
+.. .. .. .. .. .. .. .. .. .. 926
+.. .. .. .. .. 924
.. .. .. .. .. .. .. .. .. 922
.. .. .. .. .. .. .. .. 920
.. .. .. .. .. .. .. .. .. .. 918
.. .. .. .. .. .. .. .. .. 916
-.. .. .. .. .. .. .. .. .. .. 914
-.. .. .. .. .. .. .. 912
-.. .. .. .. .. .. .. .. .. 910
-.. .. .. .. .. .. .. .. 908
-.. .. .. .. .. .. .. .. .. .. 906
-.. .. .. .. .. .. .. .. .. 904
-.. .. .. .. .. .. .. .. .. .. 902
-.. .. .. .. .. .. 900
-.. .. .. .. .. .. .. .. .. 898
-.. .. .. .. .. .. .. .. 896
+.. .. .. .. .. .. .. 914
+.. .. .. .. .. .. .. .. .. 912
+.. .. .. .. .. .. .. .. 910
+.. .. .. .. .. .. 908
+.. .. .. .. .. .. .. .. 906
+.. .. .. .. .. .. .. 904
+.. .. .. .. .. .. .. .. .. 900
+.. .. .. .. .. .. .. .. 898
+.. .. .. 896
.. .. .. .. .. .. .. .. .. 894
-.. .. .. .. .. .. .. 892
-.. .. .. .. .. .. .. .. .. .. 890
-.. .. .. .. .. .. .. .. .. 888
-.. .. .. .. .. .. .. .. .. .. 886
-.. .. .. .. .. .. .. .. 884
-.. .. .. .. .. .. .. .. .. .. 882
-.. .. .. .. .. .. .. .. .. 880
-878
-.. .. .. .. .. .. .. .. .. 876
-.. .. .. .. .. .. .. .. 874
+.. .. .. .. .. .. .. .. 892
+.. .. .. .. .. .. .. .. .. 890
+.. .. .. .. .. .. .. .. .. .. 888
+.. .. .. .. .. .. .. 886
+.. .. .. .. .. .. .. .. .. .. 884
+.. .. .. .. .. .. .. .. .. 882
+.. .. .. .. .. .. .. .. .. .. .. 880
+.. .. .. .. .. .. .. .. .. .. 878
+.. .. .. .. .. .. .. .. 876
+.. .. .. .. .. .. .. .. .. .. 874
.. .. .. .. .. .. .. .. .. 872
-.. .. .. .. .. .. .. 870
-.. .. .. .. .. .. .. .. .. .. 868
-.. .. .. .. .. .. .. .. .. 866
-.. .. .. .. .. .. .. .. .. .. 864
+.. .. .. .. .. .. .. .. .. .. 870
+.. .. .. .. .. .. 868
+.. .. .. .. .. .. .. .. .. .. 866
+.. .. .. .. .. .. .. .. .. 864
.. .. .. .. .. .. .. .. 862
.. .. .. .. .. .. .. .. .. 860
-.. .. .. .. .. .. 858
-.. .. .. .. .. .. .. .. .. 856
-.. .. .. .. .. .. .. .. 854
-.. .. .. .. .. .. .. 852
-.. .. .. .. .. .. .. .. 850
-.. .. .. .. .. .. .. .. .. 848
+.. .. .. .. .. .. .. .. .. .. 858
+.. .. .. .. .. .. .. 856
+.. .. .. .. .. .. .. .. .. 854
+.. .. .. .. .. .. .. .. 852
+.. .. .. .. .. .. .. .. .. 850
+.. .. .. .. .. .. .. .. .. .. 848
.. .. .. .. .. 846
-.. .. .. .. .. .. .. .. .. 844
-.. .. .. .. .. .. .. .. 842
-.. .. .. .. .. .. .. .. .. 840
-.. .. .. .. .. .. .. 838
-.. .. .. .. .. .. .. .. .. 836
-.. .. .. .. .. .. .. .. 834
-.. .. .. .. .. .. .. .. .. 832
-.. .. .. .. .. .. 830
-.. .. .. .. .. .. .. .. 828
-.. .. .. .. .. .. .. 826
-.. .. .. .. .. .. .. .. 824
-.. .. .. .. .. .. .. .. .. 822
-.. .. .. .. 820
+.. .. .. .. .. .. .. .. .. .. 844
+.. .. .. .. .. .. .. .. .. 842
+.. .. .. .. .. .. .. .. 840
+.. .. .. .. .. .. .. .. .. 838
+.. .. .. .. .. .. .. 836
+.. .. .. .. .. .. .. .. .. 834
+.. .. .. .. .. .. .. .. .. .. 832
+.. .. .. .. .. .. .. .. 830
+.. .. .. .. .. .. .. .. .. 828
+.. .. .. .. .. .. 826
+.. .. .. .. .. .. .. .. .. 824
+.. .. .. .. .. .. .. .. 822
+.. .. .. .. .. .. .. 820
.. .. .. .. .. .. .. .. .. .. 818
.. .. .. .. .. .. .. .. .. 816
.. .. .. .. .. .. .. .. 814
.. .. .. .. .. .. .. .. .. .. 812
.. .. .. .. .. .. .. .. .. 810
-.. .. .. .. .. .. .. 808
+.. .. .. .. 808
.. .. .. .. .. .. .. .. .. 806
.. .. .. .. .. .. .. .. 804
-.. .. .. .. .. .. 802
-.. .. .. .. .. .. .. .. .. .. 800
-.. .. .. .. .. .. .. .. .. 798
-.. .. .. .. .. .. .. .. .. .. 796
-.. .. .. .. .. .. .. .. 794
-.. .. .. .. .. .. .. .. .. .. 792
-.. .. .. .. .. .. .. .. .. 790
-.. .. .. .. .. .. .. .. .. .. 788
+.. .. .. .. .. .. .. 802
+.. .. .. .. .. .. .. .. .. 800
+.. .. .. .. .. .. .. .. 798
+.. .. .. .. .. .. .. .. .. 796
+.. .. .. .. .. .. 794
+.. .. .. .. .. .. .. .. .. 792
+.. .. .. .. .. .. .. .. 790
+.. .. .. .. .. .. .. .. .. 788
.. .. .. .. .. .. .. 786
-.. .. .. .. .. .. .. .. .. 784
-.. .. .. .. .. .. .. .. .. .. 782
-.. .. .. .. .. .. .. .. 780
-.. .. .. .. .. .. .. .. .. 778
-.. .. .. .. .. .. .. .. .. .. 776
-.. .. .. .. .. 774
+.. .. .. .. .. .. .. .. 784
+.. .. .. .. .. .. .. .. .. 782
+.. .. .. .. .. 780
+.. .. .. .. .. .. .. .. .. .. 778
+.. .. .. .. .. .. .. .. .. 776
+.. .. .. .. .. .. .. .. .. .. 774
.. .. .. .. .. .. .. .. 772
-.. .. .. .. .. .. .. 770
-.. .. .. .. .. .. .. .. .. 768
-.. .. .. .. .. .. .. .. 766
-.. .. .. .. .. .. 764
-.. .. .. .. .. .. .. .. .. .. 762
-.. .. .. .. .. .. .. .. .. 760
-.. .. .. .. .. .. .. .. 758
+.. .. .. .. .. .. .. .. .. 770
+.. .. .. .. .. .. .. 768
+.. .. .. .. .. .. .. .. .. .. 766
+.. .. .. .. .. .. .. .. .. 764
+.. .. .. .. .. .. .. .. 762
+.. .. .. .. .. .. .. .. .. .. 760
+.. .. .. .. .. .. .. .. .. 758
.. .. .. .. .. .. .. .. .. .. 756
-.. .. .. .. .. .. .. .. .. 754
+.. .. .. .. .. .. 754
.. .. .. .. .. .. .. .. .. .. 752
-.. .. .. .. .. .. .. 750
-.. .. .. .. .. .. .. .. .. 748
+.. .. .. .. .. .. .. .. .. 750
+.. .. .. .. .. .. .. .. .. .. 748
.. .. .. .. .. .. .. .. 746
-.. .. .. .. .. .. .. .. .. 744
-.. .. .. 742
-.. .. .. .. .. .. .. .. 740
+.. .. .. .. .. .. .. .. .. .. 744
+.. .. .. .. .. .. .. .. .. 742
+.. .. .. .. .. .. .. .. .. .. 740
.. .. .. .. .. .. .. 738
.. .. .. .. .. .. .. .. .. 736
.. .. .. .. .. .. .. .. 734
-.. .. .. .. .. .. 732
-.. .. .. .. .. .. .. .. .. 730
-.. .. .. .. .. .. .. .. 728
-.. .. .. .. .. .. .. .. .. 726
-.. .. .. .. .. .. .. 724
-.. .. .. .. .. .. .. .. .. 722
-.. .. .. .. .. .. .. .. 720
-.. .. .. .. .. .. .. .. .. 718
-.. .. .. .. .. 716
+.. .. .. .. .. .. .. .. .. 732
+.. .. .. .. .. .. .. .. .. .. 730
+.. .. 728
+.. .. .. .. .. .. .. .. 726
+.. .. .. .. .. .. .. .. .. 724
+.. .. .. .. .. .. .. 722
+.. .. .. .. .. .. .. .. .. 720
+.. .. .. .. .. .. .. .. .. .. 718
+.. .. .. .. .. .. .. .. 716
.. .. .. .. .. .. .. .. .. 714
-.. .. .. .. .. .. .. .. 712
+.. .. .. .. .. .. 712
.. .. .. .. .. .. .. .. .. 710
-.. .. .. .. .. .. .. 708
-.. .. .. .. .. .. .. .. 706
+.. .. .. .. .. .. .. .. 708
+.. .. .. .. .. .. .. 706
.. .. .. .. .. .. .. .. .. 704
-.. .. .. .. .. .. 702
-.. .. .. .. .. .. .. .. 700
-.. .. .. .. .. .. .. .. .. 698
-.. .. .. .. .. .. .. 696
-.. .. .. .. .. .. .. .. .. 694
+.. .. .. .. .. .. .. .. 702
+.. .. .. .. .. .. .. .. .. 700
+.. .. .. .. .. 698
+.. .. .. .. .. .. .. .. 696
+.. .. .. .. .. .. .. 694
.. .. .. .. .. .. .. .. 692
.. .. .. .. .. .. .. .. .. 690
-.. .. .. .. 688
-.. .. .. .. .. .. .. .. .. 686
+.. .. .. .. .. .. 688
+.. .. .. .. .. .. .. 686
.. .. .. .. .. .. .. .. 684
-.. .. .. .. .. .. .. .. .. 682
-.. .. .. .. .. .. .. 680
-.. .. .. .. .. .. .. .. 678
+.. .. .. .. 682
+.. .. .. .. .. .. .. .. 680
+.. .. .. .. .. .. .. 678
.. .. .. .. .. .. 676
-.. .. .. .. .. .. .. .. .. 674
-.. .. .. .. .. .. .. .. 672
-.. .. .. .. .. .. .. .. .. 670
-.. .. .. .. .. .. .. 668
-.. .. .. .. .. .. .. .. 666
-.. .. .. .. .. .. .. .. .. 664
-.. .. .. .. .. 662
-.. .. .. .. .. .. .. .. .. .. 660
-.. .. .. .. .. .. .. .. .. 658
-.. .. .. .. .. .. .. .. 656
+.. .. .. .. .. .. .. .. 674
+.. .. .. .. .. .. .. 672
+.. .. .. .. .. .. .. .. 670
+.. .. .. .. .. 668
+.. .. .. .. .. .. .. .. .. 666
+.. .. .. .. .. .. .. .. 664
+.. .. .. .. .. .. .. .. .. 662
+.. .. .. .. .. .. .. 660
+.. .. .. .. .. .. .. .. 658
+.. .. .. .. .. .. 656
.. .. .. .. .. .. .. .. .. 654
-.. .. .. .. .. .. .. 652
+.. .. .. .. .. .. .. .. 652
.. .. .. .. .. .. .. .. .. 650
-.. .. .. .. .. .. .. .. 648
-.. .. .. .. .. .. 646
+.. .. .. .. .. .. .. 648
+.. .. .. .. .. .. .. .. 646
.. .. .. .. .. .. .. .. .. 644
-.. .. .. .. .. .. .. .. 642
+.. .. .. 642
.. .. .. .. .. .. .. .. .. 640
-.. .. .. .. .. .. .. 638
-.. .. .. .. .. .. .. .. .. 636
-.. .. .. .. .. .. .. .. 634
-.. .. .. .. .. .. .. .. .. .. 632
+.. .. .. .. .. .. .. .. 638
+.. .. .. .. .. .. .. 636
+.. .. .. .. .. .. .. .. .. 634
+.. .. .. .. .. .. .. .. 632
.. .. .. .. .. .. .. .. .. 630
-.. .. 628
-.. .. .. .. .. .. .. .. .. .. 626
-.. .. .. .. .. .. .. .. .. 624
-.. .. .. .. .. .. .. .. 622
-.. .. .. .. .. .. .. .. .. 620
-.. .. .. .. .. .. .. .. .. .. 618
-.. .. .. .. .. .. .. 616
-.. .. .. .. .. .. .. .. .. .. 614
+.. .. .. .. .. .. 628
+.. .. .. .. .. .. .. .. .. 626
+.. .. .. .. .. .. .. .. 624
+.. .. .. .. .. .. .. .. .. 622
+.. .. .. .. .. .. .. 620
+.. .. .. .. .. .. .. .. .. 618
+.. .. .. .. .. .. .. .. 616
+.. .. .. .. .. 614
.. .. .. .. .. .. .. .. .. 612
.. .. .. .. .. .. .. .. 610
.. .. .. .. .. .. .. .. .. .. 608
.. .. .. .. .. .. .. .. .. 606
.. .. .. .. .. .. .. .. .. .. 604
-.. .. .. .. .. .. .. .. .. .. .. 602
-.. .. .. .. .. .. 600
-.. .. .. .. .. .. .. .. .. 598
-.. .. .. .. .. .. .. .. 596
+.. .. .. .. .. .. .. 602
+.. .. .. .. .. .. .. .. .. 600
+.. .. .. .. .. .. .. .. 598
+.. .. .. .. .. .. 596
.. .. .. .. .. .. .. .. .. 594
-.. .. .. .. .. .. .. 592
-.. .. .. .. .. .. .. .. .. .. 590
-.. .. .. .. .. .. .. .. .. 588
+.. .. .. .. .. .. .. .. 592
+.. .. .. .. .. .. .. .. .. 590
+.. .. .. .. .. .. .. 588
.. .. .. .. .. .. .. .. .. .. 586
-.. .. .. .. .. .. .. .. 584
-.. .. .. .. .. .. .. .. .. 582
-.. .. .. .. .. .. .. .. .. .. 580
-.. .. .. .. .. 578
-.. .. .. .. .. .. .. .. 576
-.. .. .. .. .. .. .. .. .. 574
-.. .. .. .. .. .. .. 572
-.. .. .. .. .. .. .. .. 570
-.. .. .. .. .. .. .. .. .. 568
-.. .. .. .. .. .. 566
-.. .. .. .. .. .. .. .. .. 564
-.. .. .. .. .. .. .. .. .. .. 562
-.. .. .. .. .. .. .. .. 560
-.. .. .. .. .. .. .. .. .. 558
-.. .. .. .. .. .. .. .. .. .. 556
-.. .. .. .. .. .. .. 554
+.. .. .. .. .. .. .. .. .. 584
+.. .. .. .. .. .. .. .. 582
+.. .. .. .. .. .. .. .. .. 580
+.. .. .. .. 578
+.. .. .. .. .. .. .. .. .. 576
+.. .. .. .. .. .. .. .. 574
+.. .. .. .. .. .. .. .. .. 572
+.. .. .. .. .. .. .. 570
+.. .. .. .. .. .. .. .. .. .. 568
+.. .. .. .. .. .. .. .. .. 566
+.. .. .. .. .. .. .. .. .. .. 564
+.. .. .. .. .. .. .. .. 562
+.. .. .. .. .. .. .. .. .. 560
+.. .. .. .. .. .. .. .. .. .. 558
+.. .. .. .. .. .. 556
+.. .. .. .. .. .. .. .. .. 554
.. .. .. .. .. .. .. .. 552
-.. .. .. .. .. .. .. .. .. 550
-.. .. .. .. 548
-.. .. .. .. .. .. .. .. .. .. 546
-.. .. .. .. .. .. .. .. .. 544
+.. .. .. .. .. .. .. 550
+.. .. .. .. .. .. .. .. .. 548
+.. .. .. .. .. .. .. .. 546
+.. .. .. .. .. 544
.. .. .. .. .. .. .. .. 542
-.. .. .. .. .. .. .. .. .. .. 540
-.. .. .. .. .. .. .. .. .. 538
-.. .. .. .. .. .. .. .. .. .. 536
-.. .. .. .. .. .. .. 534
+.. .. .. .. .. .. .. .. .. 540
+.. .. .. .. .. .. .. 538
+.. .. .. .. .. .. .. .. .. 536
+.. .. .. .. .. .. .. .. 534
.. .. .. .. .. .. .. .. .. 532
-.. .. .. .. .. .. .. .. 530
-.. .. .. .. .. .. 528
-.. .. .. .. .. .. .. .. .. .. 526
-.. .. .. .. .. .. .. .. .. 524
-.. .. .. .. .. .. .. .. 522
+.. .. .. .. .. .. 530
+.. .. .. .. .. .. .. .. 528
+.. .. .. .. .. .. .. 526
+.. .. .. .. .. .. .. .. 524
+.. 522
.. .. .. .. .. .. .. .. .. .. 520
.. .. .. .. .. .. .. .. .. 518
-.. .. .. .. .. .. .. 516
+.. .. .. .. .. .. .. .. 516
.. .. .. .. .. .. .. .. .. 514
.. .. .. .. .. .. .. .. .. .. 512
-.. .. .. .. .. .. .. .. 510
+.. .. .. .. .. .. .. 510
.. .. .. .. .. .. .. .. .. 508
-.. .. .. .. .. .. .. .. .. .. 506
-.. .. .. .. .. 504
-.. .. .. .. .. .. .. .. 502
-.. .. .. .. .. .. .. 500
+.. .. .. .. .. .. .. .. 506
+.. .. .. .. .. .. .. .. .. 504
+.. .. .. .. .. .. 502
+.. .. .. .. .. .. .. .. .. .. 500
.. .. .. .. .. .. .. .. .. 498
.. .. .. .. .. .. .. .. 496
.. .. .. .. .. .. .. .. .. 494
-.. .. .. .. .. .. 492
-.. .. .. .. .. .. .. .. .. 490
-.. .. .. .. .. .. .. .. 488
-.. .. .. .. .. .. .. .. .. 486
-.. .. .. .. .. .. .. 484
-.. .. .. .. .. .. .. .. .. .. 482
+.. .. .. .. .. .. .. 492
+.. .. .. .. .. .. .. .. .. .. 490
+.. .. .. .. .. .. .. .. .. 488
+.. .. .. .. .. .. .. .. 486
+.. .. .. .. .. .. .. .. .. 484
+.. .. .. .. .. 482
.. .. .. .. .. .. .. .. .. 480
.. .. .. .. .. .. .. .. 478
-.. .. .. .. .. .. .. .. .. .. 476
-.. .. .. .. .. .. .. .. .. 474
-.. .. .. .. .. .. .. .. .. .. 472
-.. .. .. 470
+.. .. .. .. .. .. .. .. .. 476
+.. .. .. .. .. .. .. 474
+.. .. .. .. .. .. .. .. 472
+.. .. .. .. .. .. 470
.. .. .. .. .. .. .. .. 468
.. .. .. .. .. .. .. 466
-.. .. .. .. .. .. .. .. .. 464
-.. .. .. .. .. .. .. .. 462
-.. .. .. .. .. .. 460
-.. .. .. .. .. .. .. .. 458
-.. .. .. .. .. .. .. 456
+.. .. .. .. .. .. .. .. 464
+.. .. .. .. 462
+.. .. .. .. .. .. .. .. .. .. 460
+.. .. .. .. .. .. .. .. .. 458
+.. .. .. .. .. .. .. .. .. .. 456
.. .. .. .. .. .. .. .. 454
-.. .. .. .. .. .. .. .. .. 452
-.. .. .. .. .. 450
-.. .. .. .. .. .. .. .. .. 448
-.. .. .. .. .. .. .. .. 446
-.. .. .. .. .. .. .. 444
-.. .. .. .. .. .. .. .. 442
-.. .. .. .. .. .. .. .. .. 440
-.. .. .. .. .. .. 438
+.. .. .. .. .. .. .. .. .. .. 452
+.. .. .. .. .. .. .. .. .. 450
+.. .. .. .. .. .. .. .. .. .. 448
+.. .. .. .. .. .. .. 446
+.. .. .. .. .. .. .. .. 444
+.. .. .. .. .. .. .. .. .. 442
+.. .. .. .. .. .. 440
+.. .. .. .. .. .. .. .. .. .. 438
.. .. .. .. .. .. .. .. .. 436
-.. .. .. .. .. .. .. .. 434
-.. .. .. .. .. .. .. .. .. 432
-.. .. .. .. .. .. .. 430
-.. .. .. .. .. .. .. .. 428
-.. .. .. .. 426
+.. .. .. .. .. .. .. .. .. .. 434
+.. .. .. .. .. .. .. .. 432
+.. .. .. .. .. .. .. .. .. 430
+.. .. .. .. .. .. .. 428
+.. .. .. .. .. .. .. .. 426
.. .. .. .. .. .. .. .. .. 424
-.. .. .. .. .. .. .. .. 422
-.. .. .. .. .. .. .. .. .. .. 420
-.. .. .. .. .. .. .. .. .. 418
-.. .. .. .. .. .. .. 416
-.. .. .. .. .. .. .. .. .. 414
-.. .. .. .. .. .. .. .. 412
-.. .. .. .. .. .. .. .. .. .. 410
+.. .. .. .. .. 422
+.. .. .. .. .. .. .. .. .. 420
+.. .. .. .. .. .. .. .. .. .. 418
+.. .. .. .. .. .. .. .. 416
+.. .. .. .. .. .. .. .. .. .. 414
+.. .. .. .. .. .. .. .. .. 412
+.. .. .. .. .. .. .. 410
.. .. .. .. .. .. .. .. .. 408
-.. .. .. .. .. .. 406
-.. .. .. .. .. .. .. .. .. 404
-.. .. .. .. .. .. .. .. 402
-.. .. .. .. .. .. .. 400
-.. .. .. .. .. .. .. .. .. 398
-.. .. .. .. .. .. .. .. 396
-.. .. .. .. .. .. .. .. .. 394
-.. .. .. .. .. 392
-.. .. .. .. .. .. .. .. .. 390
-.. .. .. .. .. .. .. .. 388
-.. .. .. .. .. .. .. 386
+.. .. .. .. .. .. .. .. .. .. 406
+.. .. .. .. .. .. .. .. 404
+.. .. .. .. .. .. .. .. .. 402
+.. .. .. .. .. .. .. .. .. .. 400
+.. .. .. .. .. .. 398
+.. .. .. .. .. .. .. .. .. 396
+.. .. .. .. .. .. .. .. 394
+.. .. .. .. .. .. .. .. .. 392
+.. .. .. .. .. .. .. .. .. .. 390
+.. .. .. .. .. .. .. 388
+.. .. .. .. .. .. .. .. .. .. 386
.. .. .. .. .. .. .. .. .. 384
.. .. .. .. .. .. .. .. 382
-.. .. .. .. .. .. 380
-.. .. .. .. .. .. .. .. 378
-.. .. .. .. .. .. .. .. .. 376
-.. .. .. .. .. .. .. 374
-.. .. .. .. .. .. .. .. .. 372
-.. .. .. .. .. .. .. .. 370
-.. .. .. .. .. .. .. .. .. 368
-.. 366
-.. .. .. .. .. .. .. 364
-.. .. .. .. .. .. .. .. 362
-.. .. .. .. .. .. 360
-.. .. .. .. .. .. .. .. 358
-.. .. .. .. .. .. .. 356
+.. .. .. .. .. .. .. .. .. .. 380
+.. .. .. .. .. .. .. .. .. 378
+.. .. .. .. .. .. .. .. .. .. 376
+.. .. .. 374
+.. .. .. .. .. .. .. .. 372
+.. .. .. .. .. .. .. 370
+.. .. .. .. .. .. 368
+.. .. .. .. .. .. .. .. 366
+.. .. .. .. .. .. .. .. .. 364
+.. .. .. .. .. .. .. 362
+.. .. .. .. .. .. .. .. 360
+.. .. .. .. .. 358
+.. .. .. .. .. .. .. .. 356
.. .. .. .. .. .. .. .. .. 354
-.. .. .. .. .. .. .. .. 352
-.. .. .. .. .. 350
+.. .. .. .. .. .. .. 352
+.. .. .. .. .. .. .. .. .. 350
.. .. .. .. .. .. .. .. 348
-.. .. .. .. .. .. .. 346
-.. .. .. .. .. .. .. .. 344
-.. .. .. .. .. .. 342
-.. .. .. .. .. .. .. 340
-.. .. .. .. 338
+.. .. .. .. .. .. .. .. .. 346
+.. .. .. .. .. .. 344
+.. .. .. .. .. .. .. .. .. 342
+.. .. .. .. .. .. .. .. 340
+.. .. .. .. .. .. .. .. .. 338
.. .. .. .. .. .. .. 336
-.. .. .. .. .. .. .. .. 334
-.. .. .. .. .. .. 332
+.. .. .. .. .. .. .. .. .. 334
+.. .. .. .. .. .. .. .. 332
.. .. .. .. .. .. .. .. .. 330
-.. .. .. .. .. .. .. .. 328
+.. .. .. .. 328
.. .. .. .. .. .. .. .. .. 326
-.. .. .. .. .. .. .. 324
-.. .. .. .. .. .. .. .. 322
-.. .. .. .. .. .. .. .. .. 320
-.. .. .. .. .. 318
+.. .. .. .. .. .. .. .. 324
+.. .. .. .. .. .. .. 322
+.. .. .. .. .. .. .. .. 320
+.. .. .. .. .. .. 318
.. .. .. .. .. .. .. .. .. 316
.. .. .. .. .. .. .. .. 314
-.. .. .. .. .. .. .. 312
+.. .. .. .. .. .. .. .. .. .. 312
.. .. .. .. .. .. .. .. .. 310
-.. .. .. .. .. .. .. .. 308
-.. .. .. .. .. .. .. .. .. 306
-.. .. .. .. .. .. 304
+.. .. .. .. .. .. .. .. .. .. 308
+.. .. .. .. .. .. .. 306
+.. .. .. .. .. .. .. .. .. .. 304
.. .. .. .. .. .. .. .. .. 302
.. .. .. .. .. .. .. .. 300
.. .. .. .. .. .. .. .. .. 298
-.. .. .. .. .. .. .. 296
+.. .. .. .. .. 296
.. .. .. .. .. .. .. .. .. 294
.. .. .. .. .. .. .. .. 292
-.. .. .. 290
-.. .. .. .. .. .. .. .. 288
-.. .. .. .. .. .. .. .. .. 286
-.. .. .. .. .. .. .. 284
+.. .. .. .. .. .. .. .. .. 290
+.. .. .. .. .. .. .. 288
+.. .. .. .. .. .. .. .. 286
+.. .. .. .. .. .. 284
.. .. .. .. .. .. .. .. .. 282
.. .. .. .. .. .. .. .. 280
.. .. .. .. .. .. .. .. .. 278
-.. .. .. .. .. .. 276
-.. .. .. .. .. .. .. .. 274
-.. .. .. .. .. .. .. 272
+.. .. .. .. .. .. .. 276
+.. .. .. .. .. .. .. .. .. .. 274
+.. .. .. .. .. .. .. .. .. 272
.. .. .. .. .. .. .. .. 270
-.. .. .. .. .. 268
-.. .. .. .. .. .. .. .. 266
-.. .. .. .. .. .. .. 264
+.. .. .. .. .. .. .. .. .. 268
+.. .. 266
+.. .. .. .. .. .. .. .. .. 264
.. .. .. .. .. .. .. .. 262
.. .. .. .. .. .. .. .. .. 260
-.. .. .. .. .. .. 258
-.. .. .. .. .. .. .. .. 256
-.. .. .. .. .. .. .. 254
-.. .. .. .. 252
-.. .. .. .. .. .. .. .. .. .. 250
+.. .. .. .. .. .. .. 258
+.. .. .. .. .. .. .. .. .. 256
+.. .. .. .. .. .. .. .. 254
+.. .. .. .. .. .. .. .. .. 252
+.. .. .. .. .. .. 250
.. .. .. .. .. .. .. .. .. 248
.. .. .. .. .. .. .. .. 246
.. .. .. .. .. .. .. .. .. 244
.. .. .. .. .. .. .. 242
-.. .. .. .. .. .. .. .. .. 240
-.. .. .. .. .. .. .. .. 238
+.. .. .. .. .. .. .. .. 240
+.. .. .. .. .. 238
.. .. .. .. .. .. .. .. .. 236
-.. .. .. .. .. .. 234
-.. .. .. .. .. .. .. .. .. .. 232
-.. .. .. .. .. .. .. .. .. 230
-.. .. .. .. .. .. .. .. .. .. 228
-.. .. .. .. .. .. .. .. 226
-.. .. .. .. .. .. .. .. .. 224
-.. .. .. .. .. .. .. .. .. .. 222
-.. .. .. .. .. .. .. 220
-.. .. .. .. .. .. .. .. .. 218
-.. .. .. .. .. .. .. .. 216
-.. .. .. .. .. 214
-.. .. .. .. .. .. .. .. .. .. 212
-.. .. .. .. .. .. .. .. .. 210
-.. .. .. .. .. .. .. .. .. .. 208
-.. .. .. .. .. .. .. .. 206
+.. .. .. .. .. .. .. .. 234
+.. .. .. .. .. .. .. .. .. 232
+.. .. .. .. .. .. .. 230
+.. .. .. .. .. .. .. .. 228
+.. .. .. .. .. .. 226
+.. .. .. .. .. .. .. .. .. .. 224
+.. .. .. .. .. .. .. .. .. 222
+.. .. .. .. .. .. .. .. 220
+.. .. .. .. .. .. .. .. .. .. 218
+.. .. .. .. .. .. .. .. .. 216
+.. .. .. .. .. .. .. 214
+.. .. .. .. .. .. .. .. .. 212
+.. .. .. .. .. .. .. .. 210
+.. .. .. .. 208
+.. .. .. .. .. .. .. .. .. .. 206
.. .. .. .. .. .. .. .. .. 204
-.. .. .. .. .. .. .. 202
-.. .. .. .. .. .. .. .. .. 200
+.. .. .. .. .. .. .. .. .. .. 202
+.. .. .. .. .. .. .. .. 200
.. .. .. .. .. .. .. .. .. .. 198
-.. .. .. .. .. .. .. .. 196
-.. .. .. .. .. .. .. .. .. 194
-.. .. .. .. .. .. 192
-.. .. .. .. .. .. .. .. .. 190
-.. .. .. .. .. .. .. .. .. .. 188
-.. .. .. .. .. .. .. .. 186
-.. .. .. .. .. .. .. .. .. 184
-.. .. .. .. .. .. .. 182
-.. .. .. .. .. .. .. .. .. .. 180
+.. .. .. .. .. .. .. .. .. 196
+.. .. .. .. .. .. .. 194
+.. .. .. .. .. .. .. .. .. 192
+.. .. .. .. .. .. .. .. .. .. 190
+.. .. .. .. .. .. .. .. 188
+.. .. .. .. .. .. .. .. .. 186
+.. .. .. .. .. .. 184
+.. .. .. .. .. .. .. .. .. 182
+.. .. .. .. .. .. .. .. 180
.. .. .. .. .. .. .. .. .. 178
-.. .. .. .. .. .. .. .. 176
-.. .. .. .. .. .. .. .. .. 174
-.. .. 172
+.. .. .. .. .. .. .. 176
+.. .. .. .. .. .. .. .. .. .. 174
+.. .. .. .. .. .. .. .. .. 172
.. .. .. .. .. .. .. .. 170
-.. .. .. .. .. .. .. 168
-.. .. .. .. .. .. .. .. 166
-.. .. .. .. .. .. .. .. .. 164
-.. .. .. .. .. .. 162
-.. .. .. .. .. .. .. .. 160
-.. .. .. .. .. .. .. 158
-.. .. .. .. .. .. .. .. 156
-.. .. .. .. .. 154
-.. .. .. .. .. .. .. .. .. 152
-.. .. .. .. .. .. .. .. 150
-.. .. .. .. .. .. .. 148
-.. .. .. .. .. .. .. .. .. .. 146
+.. .. .. .. .. .. .. .. .. .. 168
+.. .. .. .. .. .. .. .. .. 166
+.. .. .. .. .. .. .. .. .. .. 164
+.. .. .. .. .. 162
+.. .. .. .. .. .. .. .. .. 160
+.. .. .. .. .. .. .. .. 158
+.. .. .. .. .. .. .. .. .. 156
+.. .. .. .. .. .. .. 154
+.. .. .. .. .. .. .. .. 152
+.. .. .. .. .. .. .. .. .. 150
+.. .. .. .. .. .. 148
+.. .. .. .. .. .. .. .. 146
.. .. .. .. .. .. .. .. .. 144
-.. .. .. .. .. .. .. .. .. .. 142
-.. .. .. .. .. .. .. .. 140
-.. .. .. .. .. .. .. .. .. 138
-.. .. .. .. .. .. 136
+.. .. .. .. .. .. .. 142
+.. .. .. .. .. .. .. .. .. 140
+.. .. .. .. .. .. .. .. 138
+.. .. .. .. .. .. .. .. .. .. 136
.. .. .. .. .. .. .. .. .. 134
-.. .. .. .. .. .. .. .. 132
-.. .. .. .. .. .. .. .. .. 130
+.. .. .. 132
+.. .. .. .. .. .. .. .. 130
.. .. .. .. .. .. .. 128
-.. .. .. .. .. .. .. .. 126
-.. .. .. .. 124
-.. .. .. .. .. .. .. .. 122
-.. .. .. .. .. .. .. 120
+.. .. .. .. .. .. .. .. .. 126
+.. .. .. .. .. .. .. .. 124
+.. .. .. .. .. .. 122
+.. .. .. .. .. .. .. .. .. 120
.. .. .. .. .. .. .. .. 118
-.. .. .. .. .. .. 116
+.. .. .. .. .. .. .. 116
.. .. .. .. .. .. .. .. .. 114
.. .. .. .. .. .. .. .. 112
.. .. .. .. .. .. .. .. .. 110
-.. .. .. .. .. .. .. 108
-.. .. .. .. .. .. .. .. 106
-.. .. .. .. .. .. .. .. .. 104
-.. .. .. .. .. 102
-.. .. .. .. .. .. .. .. 100
+.. .. .. .. .. 108
+.. .. .. .. .. .. .. .. .. 106
+.. .. .. .. .. .. .. .. 104
+.. .. .. .. .. .. .. .. .. 102
+.. .. .. .. .. .. .. 100
.. .. .. .. .. .. .. .. .. 98
-.. .. .. .. .. .. .. 96
-.. .. .. .. .. .. .. .. 94
-.. .. .. .. .. .. 92
-.. .. .. .. .. .. .. .. .. 90
-.. .. .. .. .. .. .. .. 88
-.. .. .. .. .. .. .. .. .. 86
-.. .. .. .. .. .. .. 84
-.. .. .. .. .. .. .. .. .. 82
-.. .. .. .. .. .. .. .. 80
-.. .. .. .. .. .. .. .. .. 78
-.. .. .. 76
-.. .. .. .. .. .. .. .. 74
-.. .. .. .. .. .. .. 72
+.. .. .. .. .. .. .. .. 96
+.. .. .. .. .. .. .. .. .. 94
+.. .. .. .. .. .. .. .. .. .. 92
+.. .. .. .. .. .. 90
+.. .. .. .. .. .. .. .. .. 88
+.. .. .. .. .. .. .. .. 86
+.. .. .. .. .. .. .. .. .. 84
+.. .. .. .. .. .. .. 82
+.. .. .. .. .. .. .. .. .. 80
+.. .. .. .. .. .. .. .. 78
+.. .. .. .. 76
+.. .. .. .. .. .. .. .. .. 74
+.. .. .. .. .. .. .. .. 72
.. .. .. .. .. .. .. .. .. 70
-.. .. .. .. .. .. .. .. 68
-.. .. .. .. .. .. 66
+.. .. .. .. .. .. .. 68
+.. .. .. .. .. .. .. .. .. .. 66
.. .. .. .. .. .. .. .. .. 64
-.. .. .. .. .. .. .. .. 62
-.. .. .. .. .. .. .. 60
-.. .. .. .. .. .. .. .. 58
-.. .. .. .. .. 56
-.. .. .. .. .. .. .. .. 54
-.. .. .. .. .. .. .. 52
-.. .. .. .. .. .. .. .. 50
-.. .. .. .. .. .. 48
-.. .. .. .. .. .. .. .. 46
-.. .. .. .. .. .. .. 44
-.. .. .. .. .. .. .. .. 42
-.. .. .. .. 40
-.. .. .. .. .. .. .. .. .. 38
-.. .. .. .. .. .. .. .. 36
-.. .. .. .. .. .. .. 34
-.. .. .. .. .. .. .. .. 32
-.. .. .. .. .. .. 30
-.. .. .. .. .. .. .. .. 28
-.. .. .. .. .. .. .. .. .. 26
-.. .. .. .. .. .. .. 24
-.. .. .. .. .. .. .. .. .. 22
-.. .. .. .. .. .. .. .. 20
-.. .. .. .. .. .. .. .. .. 18
-.. .. .. .. .. 16
-.. .. .. .. .. .. .. 14
+.. .. .. .. .. .. .. .. .. .. 62
+.. .. .. .. .. .. .. .. 60
+.. .. .. .. .. .. .. .. .. 58
+.. .. .. .. .. .. 56
+.. .. .. .. .. .. .. .. .. 54
+.. .. .. .. .. .. .. .. 52
+.. .. .. .. .. .. .. .. .. 50
+.. .. .. .. .. .. .. 48
+.. .. .. .. .. .. .. .. .. 46
+.. .. .. .. .. .. .. .. 44
+.. .. .. .. .. .. .. .. .. 42
+.. .. .. .. .. 40
+.. .. .. .. .. .. .. .. .. .. 38
+.. .. .. .. .. .. .. .. .. 36
+.. .. .. .. .. .. .. .. 34
+.. .. .. .. .. .. .. .. .. 32
+.. .. .. .. .. .. .. 30
+.. .. .. .. .. .. .. .. .. 28
+.. .. .. .. .. .. .. .. 26
+.. .. .. .. .. .. .. .. .. 24
+.. .. .. .. .. .. .. .. .. .. 22
+.. .. .. .. .. .. 20
+.. .. .. .. .. .. .. .. .. .. 18
+.. .. .. .. .. .. .. .. .. 16
+.. .. .. .. .. .. .. .. .. .. 14
.. .. .. .. .. .. .. .. 12
-.. .. .. .. .. .. 10
-.. .. .. .. .. .. .. .. 8
-.. .. .. .. .. .. .. .. .. 6
-.. .. .. .. .. .. .. 4
-.. .. .. .. .. .. .. .. 0
+.. .. .. .. .. .. .. .. .. 10
+.. .. .. .. .. .. .. .. .. .. 8
+.. .. .. .. .. .. .. 6
+.. .. .. .. .. .. .. .. .. 4
+.. .. .. .. .. .. .. .. 2
+.. .. .. .. .. .. .. .. .. 0
-- end foo ----------------
|
|
From: <sv...@va...> - 2006-10-17 01:24:03
|
Author: sewardj
Date: 2006-10-17 02:23:57 +0100 (Tue, 17 Oct 2006)
New Revision: 6252
Log:
Merge r6105:
Refactor the address space manager, so there are two implementations
of it, plus a small common supporting library.
Added:
trunk/coregrind/m_aspacemgr/aspacemgr-aix5.c
Modified:
trunk/coregrind/m_aspacemgr/aspacemgr-common.c
trunk/coregrind/m_aspacemgr/aspacemgr-linux.c
Added: trunk/coregrind/m_aspacemgr/aspacemgr-aix5.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_aspacemgr/aspacemgr-aix5.c =
(rev 0)
+++ trunk/coregrind/m_aspacemgr/aspacemgr-aix5.c 2006-10-17 01:23:57 UTC =
(rev 6252)
@@ -0,0 +1,2611 @@
+
+/*--------------------------------------------------------------------*/
+/*--- The address space manager: segment initialisation and ---*/
+/*--- tracking, stack operations ---*/
+/*--- ---*/
+/*--- Implementation for AIX5 m_aspacemgr-aix5.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* *************************************************************
+ DO NOT INCLUDE ANY OTHER FILES HERE.
+ ADD NEW INCLUDES ONLY TO priv_aspacemgr.h
+ AND THEN ONLY AFTER READING DIRE WARNINGS THERE TOO.
+ ************************************************************* */
+
+#include "priv_aspacemgr.h"
+
+
+/* Note: many of the exported functions implemented below are
+ described more fully in comments in pub_core_aspacemgr.h.
+*/
+
+/* This provides a minimal address space management facility for AIX5.
+ It is not as comprehensive, robust or efficient as its Linux
+ counterpart.
+
+ It does implement the advise/notify concept described in
+ aspacemgr-linux.c, but minimally. It only keeps track of the
+ mappings belonging to Valgrind; the client can do what it likes so
+ long as it doesn't trash Valgrind's mappings.
+
+ This is unfortunate, but the root problem is that it is impossible
+ to find out on AIX what the complete set of mappings for a process
+ is. Sure, AIX does have /proc/pid/map, but it's weak compared to
+ Linux's: it just shows some small subset of the mappings, not all
+ of them. So it is not very useful: it can't be used to discover
+ the true initial process mapping state, and it can't be used to
+ cross-check Valgrind's internal mapping table, as is done at
+ --sanity-level=3D3 and above on Linux.
+*/
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- The Address Space Manager's state. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Describes AIX5-specific segment kinds */
+typedef
+ enum {
+ ASkFree=3D1, // free space
+ ASkMText, // module text (code) mapping
+ ASkMData, // module data (& bss) mapping
+ ASkFileV, // file mapping belonging to valgrind
+ ASkAnonC, // anonymous mapping belonging to the client
+ ASkAnonV, // anonymous mapping belonging to valgrind
+ ASkShmemC, // shm mapping belonging to the client
+ ASkPreAlloc // area preallocated from sbrk
+ }
+ AixSegKind;
+
+/* Segment table entries, in summary:
+
+ ASkFree start end
+ ASkMText start end r w x sibling ismainexe fname mname
+ ASkMData start end r w x sibling
+ FileV start end r w x fname offset
+ AnonC start end r w x fromP isCH
+ AnonV start end r w x fromP
+ ShmemC start end r w x
+ PreAlloc start end
+
+ Entries are non-overlapping and cover the entire address space
+ exactly (as in the Linux aspacem). Unlike Linux there are no
+ alignment constraints, since we're just recording what's going on,
+ rather than controlling it.
+
+ MText/MData are XCOFF mapped modules, as determined by looking at
+ /proc/../map. MText is the primary entry and contains the text
+ range. MData contains the data range, if the module has a data
+ mapping (usually but not always). MText also holds the avma of the
+ corresponding data segment start, if any, (sibling field) so it can
+ be found and the two added/removed together. Similarly MData
+ contains the address of the corresponding MText (also sibling).
+
+ fname/mname only apply to MText. To find the fname/mname for MData
+ you have to look at the corresponding MText entry, which is
+ guaranteed to exist. MText may exist without a corresponding MData
+ but not vice versa. Kludge: in fact fname/mname have to be
+ allowed in MData, else read_procselfmap doesn't work.
+
+ MText may have a zero sibling pointer, indicating that there is no
+ corresponding MData. But MData must have a nonzero sibling pointer
+ since MData without MText is not allowed. Implication is that
+ neither MText nor MData may be mapped at zero as this would mess up
+ the representation, but I don't think that will ever happen since
+ AIX uses page zero as a readonly const-zero area.
+
+ For MData entries, the data section size acquired from /proc/../map
+ appears to also include the bss, so there is no need for any
+ further handling of that.
+
+ isCH indicates whether an AnonC area is part of the client heap
+ or not. May not be set for any other kind of area.
+
+ File and member names are entries into the string table.
+
+ fromP, for AnonC/AnonV, if True, indicates that the segment was
+ allocated from a PreAlloc area, and so should be returned to that
+ state upon deallocation. If False, indicates that the segment
+ should be unmapped on deallocation.
+*/
+typedef
+ struct {
+ AixSegKind kind;
+
+ /* ALL: extent */
+ /* Note: zero-length segments are not allowed. That guarantees
+ that start <=3D end. */
+ Addr start; // lowest addr in range (ALL)
+ Addr end; // highest addr in range (ALL)
+
+ /* ALL except Free */
+ Bool hasR;
+ Bool hasW;
+ Bool hasX;
+
+ /* misc */
+ Addr sibling; // MText, MData only: addr of MData/MText
+ Bool isMainExe; // MText only: is this the main executable?
+ Bool isCH; // AnonC only: is this part of the client's heap=
?
+ Bool fromP; // AnonC, AnonV only: originated from PreAlloc?
+ UChar* fname; // MText, FileV only: filename
+ UChar* mname; // MText only: member name if present
+ ULong offset; // FileV only: file offset
+ }
+ AixSegment;
+
+
+#define VG_N_ASEGMENTS 5000
+
+typedef
+ struct {
+ AixSegment seg[VG_N_ASEGMENTS];
+ Int used;
+ }
+ AixSegments;
+
+
+/* ------ start of STATE for the address-space manager ------ */
+
+/* A table of zero-terminated strings (file names etc). This
+ is only ever added to. */
+
+#define VG_N_ASTRTAB 200000
+static Int strtab_used =3D 0;
+static UChar strtab[VG_N_ASTRTAB];
+
+#define Addr_MIN ((Addr)0)
+#define Addr_MAX ((Addr)(-1ULL))
+
+/* The main array of AixSegments, in order as required. */
+
+static AixSegments asegs_pri;
+
+/* and two auxiliary arrays. */
+
+static AixSegments asegs_tnew;
+static AixSegments asegs_told;
+
+/* The assumed size of the main thread's stack, so that we can add a
+ segment for it at startup. */
+
+#define N_FAKE_STACK_PAGES 4096 /* 16M fake stack */
+
+/* Hacks which are probably for AIX 'millicode'. Note: ensure
+ these stay page aligned. */
+
+#define MAGIC_PAGES_1_BASE 0x3000
+#define MAGIC_PAGES_1_SIZE (2*0x1000)
+
+#define MAGIC_PAGES_2_BASE 0xC000
+#define MAGIC_PAGES_2_SIZE (4*0x1000)
+
+
+#define AM_SANITY_CHECK(_who) \
+ do { \
+ if (VG_(clo_sanity_level >=3D 3)) { \
+ Bool ok =3D sane_AixSegments(&asegs_pri); \
+ if (!ok) \
+ VG_(debugLog)(0,"aspace", "sanity check failed, " \
+ "who =3D %s\n", _who); \
+ aspacem_assert(ok); \
+ } \
+ } while (0)
+
+/* When preallocating a block from sbrk-world, how much extra
+ should we pre-emptively acquire? */
+
+//#define AM_PREALLOC_EXTRA (512 * 1024)
+//#define AM_PREALLOC_EXTRA 0x0800000 /* 8 M */
+#define AM_PREALLOC_EXTRA 0x4000000 /* 64 M */
+
+/* The AIX5 aspacem implementation needs to be told when it is and
+ isn't allowed to use sbrk to allocate memory. Hence: */
+Bool VG_(am_aix5_sbrk_allowed) =3D True;
+
+/* ------ end of STATE for the address-space manager ------ */
+
+/* ------ Forwards decls ------ */
+static void parse_procselfmap ( /*OUT*/ AixSegments* );
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Stuff for 4K (small-page-size) rounding. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+#define AM_4K_PAGESZ 4096
+
+static Bool AM_IS_4K_ALIGNED ( UWord w )
+{
+ UWord m =3D AM_4K_PAGESZ-1;
+ return toBool( (w & m) =3D=3D 0 );
+}
+
+static UWord AM_4K_ROUNDUP ( UWord w )
+{
+ UWord m =3D AM_4K_PAGESZ-1;
+ return (w+m) & (~m);
+}
+
+static UWord AM_64K_ROUNDUP ( UWord w )
+{
+ UWord m =3D 0x10000-1;
+ return (w+m) & (~m);
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- String table management. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Add the given string into the string table (or find an existing
+ copy of it) and return a pointer to the in-table version. The
+ pointer will be valid for the entire rest of the run. */
+
+static UChar* add_to_strtab ( UChar* str )
+{
+ Int off, len;
+ /* First, look for the string. */
+ off =3D 0;
+ while (off < strtab_used) {
+ if (0 =3D=3D VG_(strcmp)(str, &strtab[off]))
+ return &strtab[off];
+ off +=3D VG_(strlen)(&strtab[off]) + 1;
+ }
+ /* not present? we'll have to copy it then. */
+ len =3D VG_(strlen)(str);
+ if (len + 1 + strtab_used > VG_N_ASTRTAB)
+ ML_(am_barf_toolow)("VG_N_ASTRTAB");
+ off =3D strtab_used;
+ for (; *str; str++)
+ strtab[strtab_used++] =3D *str;
+ strtab[strtab_used++] =3D 0;
+ aspacem_assert(strtab_used <=3D VG_N_ASTRTAB);
+ return &strtab[off];
+}
+
+
+static Bool is_in_strtab ( UChar* str )
+{
+ if (str < &strtab[0])=20
+ return False;
+ if (str >=3D &strtab[strtab_used])
+ return False;
+ if (str > &strtab[0] && str[-1] !=3D 0)
+ return False;
+ return True;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Low level AixSegment stuff. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+static void init_AixSegment ( AixSegment* s )
+{
+ s->kind =3D 0; /* invalid */
+ s->start =3D 0;
+ s->end =3D 0;
+ s->hasR =3D False;
+ s->hasW =3D False;
+ s->hasX =3D False;
+ s->sibling =3D 0;
+ s->isMainExe =3D False;
+ s->isCH =3D False;
+ s->fromP =3D False;
+ s->fname =3D NULL;
+ s->mname =3D NULL;
+ s->offset =3D 0;
+}
+
+
+static HChar* name_of_AixSegKind ( AixSegKind sk )
+{
+ switch (sk) {
+ case ASkFree: return "Free ";
+ case ASkMText: return "MText";
+ case ASkMData: return "MData";
+ case ASkAnonV: return "AnonV";
+ case ASkAnonC: return "AnonC";
+ case ASkFileV: return "FileV";
+ case ASkShmemC: return "ShmC ";
+ case ASkPreAlloc: return "PreAl";
+ default: ML_(am_barf)("name_of_AixSegKind");
+ /*NOTREACHED*/
+ return NULL;
+ }
+}
+
+
+static=20
+void show_AixSegment ( Int logLevel, Int segNo, AixSegment* seg )
+{
+ HChar* segName =3D name_of_AixSegKind( seg->kind );
+ switch (seg->kind) {
+ case ASkFree:
+ VG_(debugLog)(logLevel, "aspacem",
+ "%3d: %s %010llx-%010llx\n",
+ segNo, /*segName*/" ",
+ (ULong)seg->start, (ULong)seg->end
+ );
+ break;
+ case ASkMText:
+ VG_(debugLog)(logLevel, "aspacem",
+ "%3d: %s %010llx-%010llx %c%c%c-- (d %010llx) %s%s%s%s\n",
+ segNo, seg->isMainExe ? "MTEXT" : "MText",
+ (ULong)seg->start, (ULong)seg->end,
+ seg->hasR ? 'r' : '-',
+ seg->hasW ? 'w' : '-',
+ seg->hasX ? 'x' : '-',
+ (ULong)seg->sibling,
+ seg->fname,
+ seg->mname ? "(" : "",
+ seg->mname ? (HChar*)seg->mname : "",
+ seg->mname ? ")" : ""
+ );
+ break;
+ case ASkMData:
+ VG_(debugLog)(logLevel, "aspacem",
+ "%3d: %s %010llx-%010llx %c%c%c-- (t %010llx)\n",
+ segNo, "MData",
+ (ULong)seg->start, (ULong)seg->end,
+ seg->hasR ? 'r' : '-',
+ seg->hasW ? 'w' : '-',
+ seg->hasX ? 'x' : '-',
+ (ULong)seg->sibling
+ );
+ break;
+ case ASkFileV:=20
+ VG_(debugLog)(logLevel, "aspacem",
+ "%3d: %s %010llx-%010llx %c%c%c-- %6lld %s\n",
+ segNo, segName,
+ (ULong)seg->start, (ULong)seg->end,
+ seg->hasR ? 'r' : '-',
+ seg->hasW ? 'w' : '-',
+ seg->hasX ? 'x' : '-',
+ seg->offset,
+ seg->fname
+ );
+ break;
+ case ASkAnonV:=20
+ case ASkAnonC:
+ case ASkShmemC:
+ VG_(debugLog)(logLevel, "aspacem",
+ "%3d: %s %010llx-%010llx %c%c%c%c%c\n",
+ segNo, segName,
+ (ULong)seg->start, (ULong)seg->end,
+ seg->hasR ? 'r' : '-',
+ seg->hasW ? 'w' : '-',
+ seg->hasX ? 'x' : '-',
+ seg->kind=3D=3DASkAnonC && seg->isCH ? 'H' : '-',
+ seg->fromP ? 'P' : '-'
+ );
+ break;
+ case ASkPreAlloc:
+ VG_(debugLog)(logLevel, "aspacem",
+ "%3d: %s %010llx-%010llx %c%c%c-- (size %llu)\n",
+ segNo, segName,
+ (ULong)seg->start, (ULong)seg->end,
+ seg->hasR ? 'r' : '-',
+ seg->hasW ? 'w' : '-',
+ seg->hasX ? 'x' : '-',
+ (ULong)seg->end - (ULong)seg->start + 1
+ );
+ break;
+ default:
+ VG_(debugLog)(logLevel, "aspacem",
+ "%3d: show_AixSegment: unknown segment\n",=20
+ segNo);
+ break;
+ }
+}
+
+
+static void init_AixSegments ( AixSegments* segs )
+{
+ segs->used =3D 1;
+ init_AixSegment( &segs->seg[0] );
+ segs->seg[0].kind =3D ASkFree;
+ segs->seg[0].start =3D Addr_MIN;
+ segs->seg[0].end =3D Addr_MAX;
+}
+
+
+static=20
+void show_AixSegments ( Int logLevel, HChar* who, AixSegments* segs )
+{
+ Int i;
+ VG_(debugLog)(logLevel, "aspacem", "<<< %s\n", who);
+ for (i =3D 0; i < segs->used; i++)
+ show_AixSegment( logLevel, i, &segs->seg[i] );
+ VG_(debugLog)(logLevel, "aspacem", ">>>\n");
+}
+
+
+static Bool sane_AixSegment ( AixSegment* seg )
+{
+ /* disallow zero and negative length segments */
+ if (seg->end < seg->start)
+ return False;
+
+ switch (seg->kind) {
+ case ASkFree:
+ if (seg->hasR || seg->hasW || seg->hasX)
+ return False;
+ if (seg->isMainExe || seg->sibling !=3D 0 || seg->offset !=3D 0=
)
+ return False;
+ if (seg->fname || seg->mname)
+ return False;
+ if (seg->isCH || seg->fromP)
+ return False;
+ break;
+ case ASkMText:
+ if (!is_in_strtab(seg->fname))
+ return False;
+ if (seg->mname && !is_in_strtab(seg->mname))
+ return False;
+ if (seg->offset !=3D 0)
+ return False;
+ if (seg->isCH || seg->fromP)
+ return False;
+ break;
+ case ASkMData:
+ if (seg->isMainExe || seg->sibling =3D=3D 0 || seg->offset !=3D=
0)
+ return False;
+ /* fname/mname have to be allowed in MData, else
+ read_procselfmap doesn't work. Unfortunately. */
+ /*
+ if (seg->fname || seg->mname)
+ return False;
+ */
+ if (seg->isCH || seg->fromP)
+ return False;
+ break;
+ case ASkFileV:
+ if (!is_in_strtab(seg->fname))
+ return False;
+ if (seg->mname !=3D NULL)
+ return False;
+ if (seg->isMainExe || seg->sibling !=3D 0)
+ return False;
+ if (seg->isCH || seg->fromP)
+ return False;
+ break;
+ case ASkShmemC:
+ case ASkAnonV:
+ case ASkAnonC:
+ if (seg->fname || seg->mname)
+ return False;
+ if (seg->isMainExe || seg->sibling !=3D 0)
+ return False;
+ if (seg->offset !=3D 0)
+ return False;
+ if (seg->kind !=3D ASkAnonC && seg->isCH)
+ return False;
+ if ( (!(seg->kind =3D=3D ASkAnonV || seg->kind =3D=3D ASkAnonC)=
)
+ && seg->fromP)
+ return False;
+ break;
+ case ASkPreAlloc:
+ if (seg->fname || seg->mname)
+ return False;
+ if (seg->isMainExe || seg->sibling !=3D 0)
+ return False;
+ if (seg->offset !=3D 0)
+ return False;
+ if (seg->kind !=3D ASkAnonC && seg->isCH)
+ return False;
+ if (seg->fromP)
+ return False;
+ if (!AM_IS_4K_ALIGNED(seg->start))
+ return False;
+ if (!AM_IS_4K_ALIGNED(seg->end + 1))
+ return False;
+ if (!(seg->hasR && seg->hasW && seg->hasX))
+ return False;
+ break;
+ default:
+ return False;
+ }
+ return True;
+}
+
+
+/* Binary search the interval array for a given address. Since the
+ array covers the entire address space the search cannot fail. */
+static Int find_asegment_idx ( AixSegments* segs, Addr a )
+{
+ Addr a_mid_lo, a_mid_hi;
+ Int mid,
+ lo =3D 0,
+ hi =3D segs->used-1;
+ aspacem_assert(lo <=3D hi);
+ while (True) {
+ /* current unsearched space is from lo to hi, inclusive. */
+ if (lo > hi) {
+ /* Not found. This can't happen. */
+ ML_(am_barf)("find_nsegment_idx: not found");
+ }
+ mid =3D (lo + hi) / 2;
+ a_mid_lo =3D segs->seg[mid].start;
+ a_mid_hi =3D segs->seg[mid].end;
+
+ if (a < a_mid_lo) { hi =3D mid-1; continue; }
+ if (a > a_mid_hi) { lo =3D mid+1; continue; }
+ aspacem_assert(a >=3D a_mid_lo && a <=3D a_mid_hi);
+ aspacem_assert(0 <=3D mid && mid < segs->used);
+ return mid;
+ }
+}
+
+
+static Bool sane_AixSegments ( AixSegments* segs )
+{
+ Int i;
+
+ /* Check endpoints */
+ if (segs->used < 1 || segs->used > VG_N_ASEGMENTS) {
+ VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad ->used");
+ return False;
+ }
+ if (segs->seg[0].start !=3D Addr_MIN
+ || segs->seg[segs->used-1].end !=3D Addr_MAX) {
+ VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad endpoints");
+ return False;
+ }
+
+ /* Check each segment, and check entire range is covered. */
+ for (i =3D 0; i < segs->used; i++) {
+ if (!sane_AixSegment( &segs->seg[i] )) {
+ VG_(debugLog)(0, "aspacem",=20
+ "sane_AixSegments: bad segment %d\n", i);
+ return False;
+ }
+ }
+ for (i =3D 1; i < segs->used; i++) {
+ if (segs->seg[i-1].end + 1 !=3D segs->seg[i].start) {
+ VG_(debugLog)(0, "aspacem",=20
+ "sane_AixSegments: bad transition at %d/%d\n",=
i-1,i);
+ return False;
+ }
+ }
+
+ /* Now we know 'seg' is safe for use in find_asegment_idx().
+ Check the sibling pointers for MText/MData.
+
+ Also check that the segment starting at address zero is neither
+ MText nor MData (since this would mess up the sibling pointer
+ representation; see comments above.) Failure of this is not per
+ se a logic failure, but it does indicate that the kernel
+ unexpectedly placed MText or MData at zero, and our
+ representation is therefore inadequate.
+ */
+ if (segs->seg[0].kind =3D=3D ASkMText || segs->seg[0].kind =3D=3D ASk=
MData) {
+ VG_(debugLog)(0, "aspacem",=20
+ "sane_AixSegments: ASkMText/ASkMData at address z=
ero\n");
+ return False;
+ }
+
+ for (i =3D 0; i < segs->used-1; i++) {
+
+ AixSegment *s1, *s2;
+
+ s1 =3D &segs->seg[i];
+
+ if (s1->kind =3D=3D ASkMData) {
+ s2 =3D &segs->seg[ find_asegment_idx(segs, s1->sibling) ];
+ if (s2->kind !=3D ASkMText
+ || find_asegment_idx(segs, s2->sibling) !=3D i) {
+ VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad sibling "
+ "link(s) for ASkData\n");
+ return False;
+ }
+ }
+
+ if (s1->kind =3D=3D ASkMText && s1->sibling !=3D 0) {
+ s2 =3D &segs->seg[ find_asegment_idx(segs, s1->sibling) ];
+ if (s2->kind !=3D ASkMData
+ || find_asegment_idx(segs, s2->sibling) !=3D i) {
+ VG_(debugLog)(0, "aspacem", "sane_AixSegments: bad sibling "
+ "link(s) for ASkText\n");
+ return False;
+ }
+ }
+
+ }
+
+ return True;
+}
+
+
+/* Try merging s2 into s1, if possible. If successful, s1 is
+ modified, and True is returned. Otherwise s1 is unchanged and
+ False is returned. */
+
+static Bool maybe_merge_asegments ( AixSegment* s1, AixSegment* s2 )
+{
+ if (s1->kind !=3D s2->kind)=20
+ return False;
+
+ if (s1->end+1 !=3D s2->start)
+ return False;
+
+ switch (s1->kind) {
+
+ case ASkFree:
+ s1->end =3D s2->end;
+ return True;
+
+ case ASkAnonC:
+ case ASkAnonV:
+ if (s1->hasR =3D=3D s2->hasR && s1->hasW =3D=3D s2->hasW=20
+ && s1->hasX =3D=3D s2->hasX && s1->isCH =3D=3D s2->isCH
+ && s1->fromP =3D=3D s2->fromP) {
+ s1->end =3D s2->end;
+ return True;
+ }
+ break;
+
+ /* not really necessary, but .. */
+ case SkFileV:
+ if (s1->hasR =3D=3D s2->hasR
+ && s1->hasW =3D=3D s2->hasW && s1->hasX =3D=3D s2->hasX
+ && s1->fname =3D=3D s2->fname
+ && s2->offset =3D=3D s1->offset
+ + ((ULong)s2->start) - ((ULong)s1->start) ) {
+ s1->end =3D s2->end;
+ return True;
+ }
+ break;
+
+ /* it's important to merge PreAlloc's back together to avoid
+ fragmenting PreAlloc'd space unnecessarily */
+ case ASkPreAlloc:
+ s1->end =3D s2->end;
+ return True;
+
+ default:
+ break;
+ }
+
+ return False;
+}
+
+
+/* Merge mergable segments in SEGS. */
+
+static void preen_asegments ( AixSegments* segs )
+{
+ Int r, w;
+
+ aspacem_assert(segs->used >=3D 1);
+ if (segs->used =3D=3D 1)
+ return;
+
+ w =3D 0;
+ for (r =3D 1; r < segs->used; r++) {
+ if (maybe_merge_asegments(&segs->seg[w], &segs->seg[r])) {
+ /* nothing */
+ } else {
+ w++;
+ if (w !=3D r)=20
+ segs->seg[w] =3D segs->seg[r];
+ }
+ }
+ w++;
+ aspacem_assert(w > 0 && w <=3D segs->used);
+ segs->used =3D w;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Modifying a segment array, and constructing segments. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Split the segment containing 'a' into two, so that 'a' is
+ guaranteed to be the start of a new segment. If 'a' is already the
+ start of a segment, do nothing. */
+
+static void split_asegment_at ( AixSegments* segs, Addr a )
+{
+ Int i, j;
+
+ aspacem_assert(a > 0);
+ aspacem_assert(segs->used >=3D 1);
+=20
+ i =3D find_asegment_idx(segs, a);
+ aspacem_assert(i >=3D 0 && i < segs->used);
+
+ if (segs->seg[i].start =3D=3D a)
+ /* 'a' is already the start point of a segment, so nothing to be
+ done. */
+ return;
+
+ /* else we have to slide the segments upwards to make a hole */
+ if (segs->used >=3D VG_N_ASEGMENTS)
+ ML_(am_barf_toolow)("VG_N_ASEGMENTS");
+ for (j =3D segs->used-1; j > i; j--)
+ segs->seg[j+1] =3D segs->seg[j];
+ segs->used++;
+
+ segs->seg[i+1] =3D segs->seg[i];
+ segs->seg[i+1].start =3D a;
+ segs->seg[i].end =3D a-1;
+
+ if (segs->seg[i].kind =3D=3D ASkFileV /* || segs->seg[i].kind =3D=3D =
ASkFileC*/)
+ segs->seg[i+1].offset=20
+ +=3D ((ULong)segs->seg[i+1].start) - ((ULong)segs->seg[i].start=
);
+
+ aspacem_assert(sane_AixSegment(&segs->seg[i]));
+ aspacem_assert(sane_AixSegment(&segs->seg[i+1]));
+}
+
+
+/* Do the minimum amount of segment splitting necessary to ensure that
+ sLo is the first address denoted by some segment and sHi is the
+ highest address denoted by some other segment. Returns the indices
+ of the lowest and highest segments in the range. */
+
+static=20
+void split_asegments_lo_and_hi ( AixSegments* segs,
+ Addr sLo, Addr sHi,
+ /*OUT*/Int* iLo,
+ /*OUT*/Int* iHi )
+{
+ aspacem_assert(sLo < sHi);
+
+ if (sLo > 0)
+ split_asegment_at(segs, sLo);
+ if (sHi < Addr_MAX)
+ split_asegment_at(segs, sHi+1);
+
+ *iLo =3D find_asegment_idx(segs,sLo);
+ *iHi =3D find_asegment_idx(segs,sHi);
+ aspacem_assert(0 <=3D *iLo && *iLo < segs->used);
+ aspacem_assert(0 <=3D *iHi && *iHi < segs->used);
+ aspacem_assert(*iLo <=3D *iHi);
+ aspacem_assert(segs->seg[*iLo].start =3D=3D sLo);
+ aspacem_assert(segs->seg[*iHi].end =3D=3D sHi);
+ /* Not that I'm overly paranoid or anything, definitely not :-) */
+}
+
+
+/* Add SEG to the collection, deleting/truncating any it overlaps.
+ This deals with all the tricky cases of splitting up segments as
+ needed. Contents of SEG are copied. */
+
+static void add_asegment ( AixSegments* segs, AixSegment* seg )
+{
+ Int i, iLo, iHi, delta;
+ Bool segment_is_sane;
+
+ Addr sStart =3D seg->start;
+ Addr sEnd =3D seg->end;
+
+ aspacem_assert(sStart <=3D sEnd);
+
+ segment_is_sane =3D sane_AixSegment(seg);
+ if (!segment_is_sane) show_AixSegment(0,0,seg);
+ aspacem_assert(segment_is_sane);
+
+ split_asegments_lo_and_hi( segs, sStart, sEnd, &iLo, &iHi );
+
+ /* Now iLo .. iHi inclusive is the range of segment indices which
+ seg will replace. If we're replacing more than one segment,
+ slide those above the range down to fill the hole. */
+ delta =3D iHi - iLo;
+ aspacem_assert(delta >=3D 0);
+ if (delta > 0) {
+ for (i =3D iLo; i < segs->used-delta; i++)
+ segs->seg[i] =3D segs->seg[i+delta];
+ segs->used -=3D delta;
+ }
+ aspacem_assert(segs->used >=3D 1);
+
+ segs->seg[iLo] =3D *seg;
+
+ preen_asegments(segs);
+ if (0) VG_(am_show_nsegments)(0,"AFTER preen (add_segment)");
+}
+
+
+/* Convert everything in SEG except MData and MText into Free,
+ then preen, so as to retain normalised form. */
+
+static void knockout_non_module_segs ( AixSegments* segs )
+{
+ Int i;
+ Addr s, e;
+ for (i =3D 0; i < segs->used; i++) {
+ if (segs->seg[i].kind =3D=3D ASkFree
+ || segs->seg[i].kind =3D=3D ASkMText
+ || segs->seg[i].kind =3D=3D ASkMData)
+ continue;
+ s =3D segs->seg[i].start;
+ e =3D segs->seg[i].end;
+ init_AixSegment( &segs->seg[i] );
+ segs->seg[i].start =3D s;
+ segs->seg[i].end =3D e;
+ segs->seg[i].kind =3D ASkFree;
+ }
+ preen_asegments(segs);
+ aspacem_assert( sane_AixSegments(segs) );
+}
+
+
+/* Copy a segment array. */
+
+static void copy_asegments_d_s ( AixSegments* dst, AixSegments* src )
+{
+ Int i;
+ aspacem_assert(src->used >=3D 1 && src->used < VG_N_ASEGMENTS);
+ dst->used =3D src->used;
+ for (i =3D 0; i < src->used; i++)
+ dst->seg[i] =3D src->seg[i];
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Re-reading /proc/../map and updating MText/MData segments ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Find out the size of the AixCodeSegChange that must be
+ presented to VG_(am_aix5_reread_procmap). */
+
+Int VG_(am_aix5_reread_procmap_howmany_directives)(void)
+{
+ /* In the worst imaginable case, all the tracked modules could have
+ disappeared and been replaced with different ones. Hence: */
+ return 2 * VG_N_ASEGMENTS;
+}
+
+
+static=20
+void add_pri_text_and_data_segs ( AixSegment* tnew, AixSegment* dnew )
+{
+ Bool dExists =3D (dnew->end - dnew->start + 1) !=3D 0;
+ aspacem_assert(tnew->kind =3D=3D ASkMText);
+ aspacem_assert(dnew->kind =3D=3D ASkMData);
+ if (dExists) {
+ aspacem_assert(tnew->sibling =3D=3D dnew->start);
+ aspacem_assert(dnew->sibling =3D=3D tnew->start);
+ add_asegment(&asegs_pri, tnew);
+ add_asegment(&asegs_pri, dnew);
+ } else {
+ aspacem_assert(tnew->sibling =3D=3D 0);
+ add_asegment(&asegs_pri, tnew);
+ }
+}
+
+static=20
+void del_pri_text_and_data_segs ( AixSegment* told, AixSegment* dold )
+{
+ AixSegment fre;
+ Bool dExists =3D (dold->end - dold->start + 1) !=3D 0;
+ aspacem_assert(told->kind =3D=3D ASkMText);
+ aspacem_assert(dold->kind =3D=3D ASkMData);
+ init_AixSegment( &fre );
+ fre.kind =3D ASkFree;
+ if (dExists) {
+ aspacem_assert(told->sibling =3D=3D dold->start);
+ aspacem_assert(dold->sibling =3D=3D told->start);
+ fre.start =3D told->start;
+ fre.end =3D told->end;
+ add_asegment(&asegs_pri, &fre);
+ fre.start =3D dold->start;
+ fre.end =3D dold->end;
+ add_asegment(&asegs_pri, &fre);
+ } else {
+ aspacem_assert(told->sibling =3D=3D 0);
+ fre.start =3D told->start;
+ fre.end =3D told->end;
+ add_asegment(&asegs_pri, &fre);
+ }
+}
+
+
+/* Tell aspacem that /proc/<pid>/map may have changed (eg following
+ __loadx) and so it should be re-read, and the code/data segment
+ list updated accordingly. The resulting array of AixCodeChangeSeg
+ directives are written to 'directives', and the number of entries
+ to *ndirectives. */
+
+void VG_(am_aix5_reread_procmap)
+ ( /*OUT*/AixCodeSegChange* directives, /*OUT*/Int* ndirectives )
+{
+ Int ixold, ixnew;
+ Bool done_old, done_new;
+ AixSegment *olds, *news;
+
+ /* First, read /proc/../map into asegs_tnew. Copy asegs_pri into
+ asegs_told, and remove everything except MData and MText, so as
+ to generate something we can sanely compare with asegs_tnew.
+ Walk asegs_told and asegs_tnew together, writing the differences
+ to 'directives', and modifying asegs_pri accordingly. */
+ parse_procselfmap( &asegs_tnew );
+ copy_asegments_d_s( &asegs_told, &asegs_pri );
+ knockout_non_module_segs( &asegs_told );
+
+ *ndirectives =3D 0;
+
+# define MODIFY_PRI(_dir, _asegs, _ixt, _acquire) \
+ do { \
+ Int _ixd; \
+ AixSegment *_segt, *_segd; \
+ AixSegment _segd_dummy; \
+ aspacem_assert(_ixt >=3D 0 && _ixt < _asegs.used); \
+ _segt =3D &_asegs.seg[_ixt]; \
+ aspacem_assert(_segt->kind =3D=3D ASkMText); \
+ if (_segt->sibling) { \
+ _ixd =3D find_asegment_idx( &_asegs, _segt->sibling ); \
+ _segd =3D &_asegs.seg[_ixd]; \
+ aspacem_assert(_segd->kind =3D=3D ASkMData); \
+ aspacem_assert(_segt->sibling =3D=3D _segd->start); \
+ } else { \
+ init_AixSegment( &_segd_dummy ); \
+ _segd_dummy.kind =3D ASkMData; \
+ _segd_dummy.start =3D 1; \
+ _segd_dummy.end =3D 0; \
+ _segd =3D &_segd_dummy; \
+ } \
+ if (_segd !=3D &_segd_dummy) \
+ aspacem_assert(_segd->sibling =3D=3D _segt->start); \
+ \
+ (_dir).code_start =3D (_segt)->start; \
+ (_dir).code_len =3D (_segt)->end - (_segt)->start + 1; \
+ (_dir).data_start =3D (_segd)->start; \
+ (_dir).data_len =3D (_segd)->end - (_segd)->start + 1; \
+ (_dir).file_name =3D (_segt)->fname; \
+ (_dir).mem_name =3D (_segt)->mname; \
+ (_dir).is_mainexe =3D (_acquire) ? (_segt)->isMainExe : False; =
\
+ (_dir).acquire =3D (_acquire); \
+ \
+ if (_acquire) { \
+ add_pri_text_and_data_segs( _segt, _segd ); \
+ } else { \
+ del_pri_text_and_data_segs( _segt, _segd ); \
+ } \
+ } while (0)
+
+ ixold =3D 0; /* indexes asegs_told */
+ ixnew =3D 0; /* indexes asegs_tnew */
+
+ while (True) {
+
+ aspacem_assert(ixold >=3D 0 && ixold < asegs_told.used);
+ aspacem_assert(ixnew >=3D 0 && ixnew < asegs_tnew.used);
+
+ /* Advance ixold and ixnew to the next MText in their
+ respective arrays. */
+ while (ixold < asegs_told.used=20
+ && asegs_told.seg[ixold].kind !=3D ASkMText) {
+ aspacem_assert(asegs_told.seg[ixold].kind =3D=3D ASkFree
+ || asegs_told.seg[ixold].kind =3D=3D ASkMData);
+ ixold++;
+ }
+ while (ixnew < asegs_tnew.used=20
+ && asegs_tnew.seg[ixnew].kind !=3D ASkMText) {
+ aspacem_assert(asegs_tnew.seg[ixnew].kind =3D=3D ASkFree
+ || asegs_tnew.seg[ixnew].kind =3D=3D ASkMData);
+ ixnew++;
+ }
+
+ aspacem_assert(ixold >=3D 0 && ixold <=3D asegs_told.used);
+ aspacem_assert(ixnew >=3D 0 && ixnew <=3D asegs_tnew.used);
+
+ done_old =3D ixold =3D=3D asegs_told.used;
+ done_new =3D ixnew =3D=3D asegs_tnew.used;
+
+ if (done_old && done_new)
+ goto both_done;
+ if (done_old && !done_new)
+ goto finishup_new;
+ if (done_new && !done_old)
+ goto finishup_old;
+
+ olds =3D &asegs_told.seg[ixold];
+ news =3D &asegs_tnew.seg[ixnew];
+
+ aspacem_assert(olds->kind =3D=3D ASkMText);
+ aspacem_assert(news->kind =3D=3D ASkMText);
+
+ if (0) {
+ show_AixSegment(0,ixold,&asegs_told.seg[ixold]);=20
+ show_AixSegment(0,ixnew,&asegs_tnew.seg[ixnew]);=20
+ VG_(debugLog)(0, "aspacem", "\n");
+ }
+
+ /* Here, if olds->start < news->start, then the old sequence has
+ an entry which the new one doesn't, so a module has been
+ unloaded. If news->start < olds->start then the new sequence
+ has a module the old one doesn't, so a module has been
+ loaded. If news->start =3D=3Dolds->start then the module is
+ unchanged. Except, we should check a bit more carefully in
+ the zero case. */
+ if (olds->start =3D=3D news->start) {
+ if (olds->start =3D=3D news->start
+ && olds->end =3D=3D news->end
+ && olds->fname =3D=3D news->fname
+ && olds->mname =3D=3D news->mname
+ && olds->sibling =3D=3D news->sibling
+ && olds->isMainExe =3D=3D news->isMainExe) {
+ /* really identical, do nothing */
+ } else {
+ /* Dubious; mark it as an unload of old and load of
+ new. */
+ MODIFY_PRI(directives[*ndirectives], asegs_told, ixold, Fals=
e);
+ (*ndirectives)++;
+ aspacem_assert(*ndirectives <=3D 2 * VG_N_ASEGMENTS);
+ MODIFY_PRI(directives[*ndirectives], asegs_tnew, ixnew, True=
);
+ (*ndirectives)++;
+ aspacem_assert(*ndirectives <=3D 2 * VG_N_ASEGMENTS);
+ }
+ ixold++;
+ ixnew++;
+ continue;
+ }
+
+ if (olds->start < news->start) {
+ /* discard olds */
+ MODIFY_PRI(directives[*ndirectives], asegs_told, ixold, False);
+ (*ndirectives)++;
+ aspacem_assert(*ndirectives <=3D 2 * VG_N_ASEGMENTS);
+ ixold++;
+ continue;
+ }
+
+ if (news->start < olds->start) {
+ /* acquire news */
+ MODIFY_PRI(directives[*ndirectives], asegs_tnew, ixnew, True);
+ (*ndirectives)++;
+ aspacem_assert(*ndirectives <=3D 2 * VG_N_ASEGMENTS);
+ ixnew++;
+ continue;
+ }
+ /* NOTREACHED */
+ aspacem_assert(0);
+ }
+
+ finishup_new:
+ olds =3D NULL;
+ aspacem_assert(ixold =3D=3D asegs_told.used);
+ aspacem_assert(ixnew < asegs_tnew.used);
+ while (ixnew < asegs_tnew.used) {
+ news =3D &asegs_tnew.seg[ixnew];
+ aspacem_assert(news->kind =3D=3D ASkMText || news->kind =3D=3D ASk=
MData
+ || news->kind =3D=3D ASkFree);
+ if (news->kind =3D=3D ASkMText) {
+ MODIFY_PRI(directives[*ndirectives], asegs_tnew, ixnew, True);
+ (*ndirectives)++;
+ aspacem_assert(*ndirectives <=3D 2 * VG_N_ASEGMENTS);
+ }
+ ixnew++;
+ }
+ goto both_done;
+
+ finishup_old:
+ news =3D NULL;
+ aspacem_assert(ixnew =3D=3D asegs_tnew.used);
+ aspacem_assert(ixold < asegs_told.used);
+ while (ixold < asegs_told.used) {
+ olds =3D &asegs_told.seg[ixold];
+ aspacem_assert(olds->kind =3D=3D ASkMText || olds->kind =3D=3D ASk=
MData
+ || olds->kind =3D=3D ASkFree);
+ if (olds->kind =3D=3D ASkMText) {
+ MODIFY_PRI(directives[*ndirectives], asegs_told, ixold, False);
+ (*ndirectives)++;
+ aspacem_assert(*ndirectives <=3D 2 * VG_N_ASEGMENTS);
+ }
+ ixold++;
+ }
+ goto both_done;
+
+ both_done:
+ aspacem_assert(ixold =3D=3D asegs_told.used);
+ aspacem_assert(ixnew =3D=3D asegs_tnew.used);
+
+ asegs_tnew.used =3D 0;
+ asegs_told.used =3D 0;
+
+ aspacem_assert( sane_AixSegments(&asegs_pri) );
+
+# undef MODIFY_PRI
+}
+
+
+/* Set the initial stack segment. Contains kludgery. Also take the
+ opportunity to create fake segs for the millicode areas. */
+
+void VG_(am_aix5_set_initial_client_sp)( Addr sp )
+{
+ static Bool done =3D False;
+ AixSegment seg;
+
+ aspacem_assert(!done);
+ done =3D True;
+
+ /* We are given the initial client SP (that of the root thread).
+ Already on the stack are argv and env. How far up does it
+ extend? We assume to the next 64k boundary. How far down does
+ it extend? We assume N_FAKE_STACK_PAGES small pages - by
+ default 16M. Establish those limits and add an AnonC rwx
+ segment. */
+
+ /* The 64k boundary is "justified" as follows. On 32-bit AIX 5.3,
+ a typical initial SP is 0x2FF22xxx, but the accessible (rw) area
+ beyond that extends up to 0x2FF2FFFF - the next 64k boundary.
+ In 64-bit mode, a typical initial SP might be
+ 0xFFF'FFFF'FFFF'E920, and the accessible area extends to
+ 0xFFF'FFFF'FFFF'FFFF. So in both cases, (64k roundup of sp) - 1
+ gives the end of the accessible area. */
+
+ VG_(debugLog)(1,"aspacem", "aix5_set_initial_client_sp( %p )\n",
+ (void*)sp);
+
+ init_AixSegment( &seg );
+ seg.kind =3D ASkAnonC;
+ seg.hasR =3D seg.hasW =3D seg.hasX =3D True;
+
+ if (sizeof(void*) =3D=3D 4
+ && ((sp & 0xFFFF0000) =3D=3D 0x2FF20000
+ || (sp & 0xFFFF0000) =3D=3D 0x2FF10000)) {
+ /* Gaaah. Special-case 32-bit mode. */
+ seg.end =3D 0x2FF2FFFF;
+ } else {
+ seg.end =3D AM_64K_ROUNDUP(sp) - 1;
+ }
+
+ seg.start =3D seg.end+1 - N_FAKE_STACK_PAGES * VKI_PAGE_SIZE;
+
+ VG_(debugLog)(1,"aspacem", "aix5_set_initial_client_sp: stack seg:\n"=
);
+ show_AixSegment(1,0, &seg);
+ add_asegment( &asegs_pri, &seg );
+
+ init_AixSegment( &seg );
+ seg.kind =3D ASkAnonC;
+ seg.hasR =3D seg.hasX =3D True;
+ seg.start =3D MAGIC_PAGES_1_BASE;
+ seg.end =3D MAGIC_PAGES_1_BASE + MAGIC_PAGES_1_SIZE - 1;
+ VG_(debugLog)(1,"aspacem", "am_aix5_set_initial_client_sp: FAKE1 seg:=
\n");
+ show_AixSegment(1,0, &seg);
+ add_asegment( &asegs_pri, &seg );
+
+ init_AixSegment( &seg );
+ seg.kind =3D ASkAnonC;
+ seg.hasR =3D seg.hasX =3D True;
+ seg.start =3D MAGIC_PAGES_2_BASE;
+ seg.end =3D MAGIC_PAGES_2_BASE + MAGIC_PAGES_2_SIZE - 1;
+ VG_(debugLog)(1,"aspacem", "am_aix5_set_initial_client_sp: FAKE2 seg:=
\n");
+ show_AixSegment(1,0, &seg);
+ add_asegment( &asegs_pri, &seg );
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Getting segment-starts. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Print out the segment array (debugging only!). */
+void VG_(am_show_nsegments) ( Int logLevel, HChar* who )
+{
+ show_AixSegments( logLevel, who, &asegs_pri );
+}
+
+/* Get the filename corresponding to this segment, if known and if it
+ has one. The returned name's storage cannot be assumed to be
+ persistent, so the caller should immediately copy the name
+ elsewhere. */
+HChar* VG_(am_get_filename)( NSegment* seg )
+{
+ ML_(am_barf)("unimplemented: VG_(am_get_filename)");
+ return NULL; /* placate gcc -Wall */
+}
+
+/* Collect up the start addresses of all non-free, non-resvn segments.
+ The interface is a bit strange in order to avoid potential
+ segment-creation races caused by dynamic allocation of the result
+ buffer *starts.
+
+ The function first computes how many entries in the result
+ buffer *starts will be needed. If this number <=3D nStarts,
+ they are placed in starts[0..], and the number is returned.
+ If nStarts is not large enough, nothing is written to
+ starts[0..], and the negation of the size is returned.
+
+ Correct use of this function may mean calling it multiple times in
+ order to establish a suitably-sized buffer. */
+
+Int VG_(am_get_segment_starts)( Addr* starts, Int nStarts )
+{
+ Int i, j, nSegs;
+
+ /* don't pass dumbass arguments */
+ aspacem_assert(nStarts >=3D 0);
+
+ nSegs =3D 0;
+ for (i =3D 0; i < asegs_pri.used; i++) {
+ if (asegs_pri.seg[i].kind =3D=3D ASkFree
+ || asegs_pri.seg[i].kind =3D=3D ASkPreAlloc)
+ continue;
+ nSegs++;
+ }
+
+ if (nSegs > nStarts) {
+ /* The buffer isn't big enough. Tell the caller how big it needs
+ to be. */
+ return -nSegs;
+ }
+
+ /* There's enough space. So write into the result buffer. */
+ aspacem_assert(nSegs <=3D nStarts);
+
+ j =3D 0;
+ for (i =3D 0; i < asegs_pri.used; i++) {
+ if (asegs_pri.seg[i].kind =3D=3D ASkFree
+ || asegs_pri.seg[i].kind =3D=3D ASkPreAlloc)
+ continue;
+ starts[j++] =3D asegs_pri.seg[i].start;
+ }
+
+ aspacem_assert(j =3D=3D nSegs); /* this should not fail */
+ return nSegs;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Sanity checking and preening of the segment array. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+Bool VG_(am_do_sync_check) ( const HChar* fn,=20
+ const HChar* file, Int line )
+{
+ /* There's nothing we can do here; just return a dummy value. */
+ return False; /* placate gcc */
+}
+
+/* Hook to allow sanity checks to be done from aspacemgr-common.c. */
+void ML_(am_do_sanity_check)( void )
+{
+ Bool ok =3D sane_AixSegments( &asegs_pri );
+ aspacem_assert(ok);
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Finding segments. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Finds the segment containing 'a'. Only returns file/anon/resvn
+ segments. On AIX5 this is pretty bogus; we fake up an entry as
+ best we can by snooping round for useful information in
+ asegs_pri. */
+
+NSegment const* VG_(am_find_nsegment) ( Addr a )
+{
+ Int i;
+ AixSegment* aseg;
+ static NSegment bogus;
+
+ /* Fill in default info. */
+ bogus.kind =3D SkAnonC;
+ bogus.start =3D 0;
+ bogus.end =3D 0;
+ bogus.smode =3D SmFixed;
+ bogus.dev =3D 0;
+ bogus.ino =3D 0;
+ bogus.mode =3D 0;
+ bogus.offset =3D 0;
+ bogus.fnIdx =3D -1;
+ bogus.hasR =3D bogus.hasW =3D bogus.hasX =3D False;
+ bogus.hasT =3D False;
+ bogus.isCH =3D False;
+ bogus.mark =3D False;
+
+ /* Go look for it in the segment table. */
+ i =3D find_asegment_idx( &asegs_pri, a );
+ aspacem_assert(i >=3D 0 && i <=3D asegs_pri.used);
+
+ aseg =3D &asegs_pri.seg[i];
+ if (aseg->kind =3D=3D ASkFree || aseg->kind =3D=3D ASkPreAlloc)
+ return NULL;
+
+ bogus.start =3D aseg->start;
+ bogus.end =3D aseg->end;
+
+ /* Refine */
+ switch (aseg->kind) {
+ case ASkMText:
+ bogus.kind =3D SkAnonC; /* hmm, pretty darn bogus */
+ bogus.hasR =3D bogus.hasX =3D True;
+ break;
+ case ASkMData:
+ bogus.kind =3D SkAnonC; /* hmm, pretty darn bogus */
+ bogus.hasR =3D bogus.hasW =3D True;
+ break;
+ case ASkShmemC:
+ bogus.kind =3D SkShmC;
+ bogus.hasR =3D aseg->hasR;
+ bogus.hasW =3D aseg->hasW;
+ bogus.hasX =3D aseg->hasX;
+ break;
+ case ASkAnonC:
+ bogus.kind =3D SkAnonC;
+ bogus.hasR =3D aseg->hasR;
+ bogus.hasW =3D aseg->hasW;
+ bogus.hasX =3D aseg->hasX;
+ bogus.isCH =3D aseg->isCH;
+ break;
+ case ASkAnonV:
+ bogus.kind =3D SkAnonV;
+ bogus.hasR =3D aseg->hasR;
+ bogus.hasW =3D aseg->hasW;
+ bogus.hasX =3D aseg->hasX;
+ break;
+ case ASkFileV:
+ bogus.kind =3D SkFileV;
+ bogus.hasR =3D aseg->hasR;
+ bogus.hasW =3D aseg->hasW;
+ bogus.hasX =3D aseg->hasX;
+ bogus.offset =3D aseg->offset;
+ break;
+ default:
+ aspacem_assert(0);
+ }
+
+ return &bogus;
+}
+
+
+/* Find the next segment along from 'here', if it is a file/anon/resvn
+ segment. */
+NSegment const* VG_(am_next_nsegment) ( NSegment* here, Bool fwds )
+{
+ ML_(am_barf)("unimplemented: VG_(am_next_nsegment)");
+ return NULL; /* placate gcc */
+}
+
+
+/* Trivial fn: return the total amount of space in anonymous mappings,
+ both for V and the client. Is used for printing stats in
+ out-of-memory messages. */
+ULong VG_(am_get_anonsize_total)( void )
+{
+ Int i;
+ ULong total =3D 0;
+ for (i =3D 0; i < asegs_pri.used; i++) {
+ if (asegs_pri.seg[i].kind =3D=3D ASkAnonC=20
+ || asegs_pri.seg[i].kind =3D=3D ASkAnonV) {
+ total +=3D (ULong)asegs_pri.seg[i].end
+ - (ULong)asegs_pri.seg[i].start + 1ULL;
+ }
+ }
+ return total;
+}
+
+
+/* Test if a piece of memory is addressable by the client with at
+ least the "prot" protection permissions by examining the underlying
+ segments. */
+Bool VG_(am_is_valid_for_client)( Addr start, SizeT len,=20
+ UInt prot )
+{
+ NSegment const * const fake =3D VG_(am_find_nsegment)(start);
+ if (!fake)
+ return False;
+ aspacem_assert(fake->start <=3D start);
+ aspacem_assert(start + len - 1 <=3D fake->end);
+ if (fake->kind =3D=3D SkAnonV || fake->kind =3D=3D SkFileV)
+ return False;
+ if ((prot & VKI_PROT_READ) && !fake->hasR)
+ return False;
+ if ((prot & VKI_PROT_WRITE) && !fake->hasW)
+ return False;
+ if ((prot & VKI_PROT_EXEC) && !fake->hasX)
+ return False;
+ return True;
+}
+
+/* Variant of VG_(am_is_valid_for_client) which allows free areas to
+ be considered part of the client's addressable space. It also
+ considers reservations to be allowable, since from the client's
+ point of view they don't exist. */
+Bool VG_(am_is_valid_for_client_or_free_or_resvn)
+ ( Addr start, SizeT len, UInt prot )
+{
+ ML_(am_barf)("unimplemented: "
+ "VG_(am_is_valid_for_client_or_free_or_resvn)");
+ /*NOTREACHED*/
+ return False;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Startup, including reading /proc/self/maps. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Initialise the address space manager, setting up the initial
+ segment list, and reading /proc/self/maps into it. This must
+ be called before any other function.
+
+ Takes a pointer to the SP at the time V gained control. This is
+ taken to be the highest usable address (more or less). Based on
+ that (and general consultation of tea leaves, etc) return a
+ suggested end address for the client's stack. */
+
+Addr VG_(am_startup) ( Addr sp_at_startup )
+{
+ aspacem_assert(sizeof(Word) =3D=3D sizeof(void*));
+ aspacem_assert(sizeof(Addr) =3D=3D sizeof(void*));
+ aspacem_assert(sizeof(SizeT) =3D=3D sizeof(void*));
+ aspacem_assert(sizeof(SSizeT) =3D=3D sizeof(void*));
+
+ asegs_tnew.used =3D 0;
+ asegs_told.used =3D 0;
+
+ asegs_pri.used =3D 1;
+ init_AixSegments( &asegs_pri );
+ aspacem_assert( sane_AixSegments(&asegs_pri) );
+
+ if (0)
+ VG_(am_show_nsegments)(0,"AFTER VG_(am_startup)");
+
+ /* We do not make an initial read of /proc/../map since doing so
+ would leave us without a way to communicate the results to a
+ caller. Hence we expect that the caller (m_main) will call
+ VG_(am_aix5_reread_procmap) soon after this call so as to get
+ the initial code/data segments recorded. */
+
+ /* Return value is irrelevant since we don't lay out the
+ client's stack; it is already done. */
+ return 0;=20
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- Preallocation (acquiring space from sbrk). ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+static
+SysRes local_do_sbrk_NO_NOTIFY( Word delta )
+{
+ SysRes res;
+ aspacem_assert(__NR_AIX5_sbrk !=3D __NR_AIX5_UNKNOWN);
+ res =3D VG_(do_syscall1)(__NR_AIX5_sbrk, (UWord)delta);
+ /* kernel produces (-1, VKI_ENOMEM) on failure. I think that's
+ ok. */
+ return res;
+}
+
+
+/* Find the ix of a prealloc section containing at least req_sz bytes,
+ or -1 if not found. Uses best-fit. */
+
+static Int find_prealloc_idx ( SizeT req_sz )
+{
+ SizeT best_sz, this_sz;
+ Int best_ix, i;
+ aspacem_assert(sizeof(SizeT) =3D=3D sizeof(Addr));
+ aspacem_assert(req_sz > 0);
+ aspacem_assert(AM_IS_4K_ALIGNED(req_sz));
+
+ best_sz =3D Addr_MAX;
+ best_ix =3D -1;
+
+ for (i =3D 0; i < asegs_pri.used; i++) {
+ AixSegment* s =3D &asegs_pri.seg[i];
+ if (s->kind !=3D ASkPreAlloc)
+ continue;
+ this_sz
+ =3D s->end + 1 - s->start;
+ aspacem_assert(this_sz > 0);
+ aspacem_assert(AM_IS_4K_ALIGNED(this_sz));
+ if (this_sz >=3D req_sz && this_sz < best_sz) {
+ best_sz =3D this_sz;
+ best_ix =3D i;
+ }
+ }
+
+ return best_ix;
+}
+
+
+/* Create a new prealloc section containing req_sz bytes. Returns
+ False if failed, True on success. */
+
+static Bool new_prealloc ( SizeT req_sz )
+{
+ SysRes sres;
+ AixSegment seg;
+ Addr start;
+ SSizeT delta;
+ HChar* why =3D NULL;
+
+ aspacem_assert(req_sz > 0);
+ aspacem_assert(AM_IS_4K_ALIGNED(req_sz));
+
+ /* m_syswrap may have decided that it's not currently safe to allow
+ allocations from sbrk-world. If so, we have to fail. */
+ if (0 && !VG_(am_aix5_sbrk_allowed)) {
+ why =3D "sbrk disallowed";
+ goto fail;
+ }
+
+ /* Get the current limit. */
+ sres =3D local_do_sbrk_NO_NOTIFY(0);
+ if (sres.isError) {
+ why =3D "initial sbrk failed";
+ goto fail;
+ }
+
+ /* Get it page aligned */
+ delta =3D AM_4K_ROUNDUP(sres.res) - sres.res;
+ aspacem_assert(delta >=3D 0 && delta < AM_4K_PAGESZ);
+ if (delta > 0) {
+ sres =3D local_do_sbrk_NO_NOTIFY(delta);
+ if (sres.isError) {
+ why =3D "aligning sbrk failed";
+ goto fail;
+ }
+ }
+
+ /* Now the brk is aligned. Try to acquire the block. */
+ sres =3D local_do_sbrk_NO_NOTIFY(0);
+ if (sres.isError)
+ return False;
+ start =3D sres.res;
+ aspacem_assert( AM_IS_4K_ALIGNED( start ));
+
+ sres =3D local_do_sbrk_NO_NOTIFY( req_sz );
+ if (sres.isError) {
+ why =3D "main sbrk failed";
+ goto fail;
+ }
+
+ /* If this fails, the kernel is acting strange. */
+ aspacem_assert( sres.res =3D=3D start );
+
+ init_AixSegment( &seg );
+ seg.start =3D start;
+ seg.end =3D start + req_sz - 1;
+ seg.kind =3D ASkPreAlloc;
+ seg.hasR =3D seg.hasW =3D seg.hasX =3D True; /* presumably */
+ add_asegment( &asegs_pri, &seg );
+
+ VG_(debugLog)(
+ 1, "aspacem", "new_prealloc: SUCCESS at 0x%llx size %lld\n",=20
+ (ULong)start, (ULong)req_sz
+ );
+ return True;
+
+ fail:
+ VG_(debugLog)(1, "aspacem", "new_prealloc: FAILED: %s\n", why);
+ return False;
+}
+
+
+/* Find the ix of a prealloc section capable of holding a block of
+ size req_sz. If none exists, try to create one first. Returns -1
+ on failure. */
+
+static Int find_or_create_prealloc_idx ( SizeT req_sz )
+{
+ Int ix;
+ SizeT req_szX;
+ Bool alloc_ok;
+
+ if (0)
+ VG_(debugLog)(0, "zz", " find_or_create_prealloc_idx ( %lu )\n",=20
+ req_sz);
+
+ aspacem_assert(sizeof(SizeT) =3D=3D sizeof(Addr));
+ aspacem_assert(req_sz > 0);
+ aspacem_assert(AM_IS_4K_ALIGNED(req_sz));
+
+ ix =3D find_prealloc_idx ( req_sz );
+ if (ix >=3D 0 && ix < asegs_pri.used)
+ return ix;
+
+ /* Not found. We'll have to allocate one. Allocate some extra at
+ the same time, so as to give a reservoir from which to satisfy
+ future requests. */
+ aspacem_assert(ix =3D=3D -1);
+
+ req_szX =3D req_sz + AM_PREALLOC_EXTRA;
+ aspacem_assert(req_szX > 0);
+ aspacem_assert(AM_IS_4K_ALIGNED(req_szX));
+
+ alloc_ok =3D new_prealloc( req_szX );
+ if (!alloc_ok)
+ return -1; /* failed */
+
+ /* We should now be able to find it in the segment table. */
+ ix =3D find_prealloc_idx( req_sz );
+ aspacem_assert(ix >=3D 0 && ix < asegs_pri.used);
+ return ix;
+}
+
+
+/*-----------------------------------------------------------------*/
+/*--- ---*/
+/*--- The core query-notify mechanism. ---*/
+/*--- ---*/
+/*-----------------------------------------------------------------*/
+
+/* Query aspacem to ask where a mapping should go. */
+
+Addr VG_(am_get_advisory) ( MapRequest* req,=20
+ Bool forClient,=20
+ /*OUT*/Bool* ok )
+{
+ ML_(am_barf)("unimplemented: VG_(am_get_advisory)");
+ /*NOTREACHED*/
+ return 0; /* placate gcc -Wall */
+}
+
+
+/* Convenience wrapper for VG_(am_get_advisory) for client floating or
+ fixed requests. If start is zero, a floating request is issued; if
+ nonzero, a fixed request at that address is issued. Same comments
+ about return values apply. */
+
+Addr VG_(am_get_advisory_client_simple) ( Addr start, SizeT len,=20
+ /*OUT*/Bool* ok )
+{
+ ML_(am_barf)("unimplemented: VG_(am_get_advisory_client_simple)");
+ /*NOTREACHED*/
+ return 0; /* placate gcc -Wall */
+}
+
+
+/* Notifies aspacem that the client completed an mmap successfully.
+ The segment array is updated accordingly. If the returned Bool is
+ True, the caller should immediately discard translations from the
+ specified address range. */
+
+Bool
+VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags,
+ Int fd, Off64T offset )
+{
+ AixSegment seg;
+ Bool needDiscard;
+
+ if (len =3D=3D 0)
+ return False;
+
+ /* Discard is needed if any of the just-trashed range had T. */
+ needDiscard =3D True; /* conservative but safe */
+
+ init_AixSegment( &seg );
+ seg.kind =3D ASkAnonC; /* XXX bogus: could be a file */
+ seg.start =3D a;
+ seg.end =3D a + len - 1;
+ seg.hasR =3D toBool(prot & VKI_PROT_READ);
+ seg.hasW =3D toBool(prot & VKI_PROT_WRITE);
+ seg.hasX =3D toBool(prot & VKI_PROT_EXEC);
+
+ if (0)
+ VG_(debugLog)(0,"aspacem","notify mmap ( %p, %ld, %ld, %ld )\n",=20
+ (void*)a, len, (UWord)prot, (UWord)flags);
+
+ add_asegment( &asegs_pri, &seg );
+ AM_SANITY_CHECK("am_notify_client_mmap");
+ return needDiscard;
+}
+
+
+/* Notifies aspacem that the client completed a shmat successfully.
+ The segment array is updated accordingly. If the returned Bool is
+ True, the caller should immediately discard translations from the
+ specified address range. */
+
+Bool
+VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot )
+{
+ AixSegment seg;
+ init_AixSegment( &seg );
+ seg.kind =3D ASkShmemC;
+ seg.start =3D a;
+ seg.end =3D seg.start + len - 1;
+ seg.hasR =3D (prot & VKI_PROT_READ) ? True : False;
+ seg.hasW =3D (prot & VKI_PROT_WRITE) ? True : False;
+ seg.hasX =3D (prot & VKI_PROT_EXEC) ? True : False;
+ add_asegment( &asegs_pri, &seg );
+ AM_SANITY_CHECK("am_notify_client_shmat");
+ if (0) VG_(am_show_nsegments)(0, "after shmat");
+ return True; /* be paranoid */
+}
+
+
+/* Notifies aspacem that an mprotect was completed successfully. The
+ segment array is updated accordingly. Note, as with
+ VG_(am_notify_munmap), it is not the job of this function to reject
+ stupid mprotects, for example the client doing mprotect of
+ non-client areas. Such requests should be intercepted earlier, by
+ the syscall wrapper for mprotect. This function merely records
+ whatever i...
[truncated message content] |
|
From: <sv...@va...> - 2006-10-17 01:23:10
|
Author: sewardj
Date: 2006-10-17 02:23:07 +0100 (Tue, 17 Oct 2006)
New Revision: 6251
Log:
Merge r6102/6103:
A new module ("Initial Image"), whose purpose is to set up the
client's initial memory and register state before running it. On
Linux this does all the stack/auxv/envp stuff which was previously
done in m_main. On AIX5 the kernel prepares the process' initial
image, so there's nothing to be done there. But LD_PRELOAD doesn't
work on AIX5, so m_initimg sets up the client so as to start by
running a short bit of code which gets the kernel to load in the core
and tool preloads and then start the client.
As a result of this, m_main gets a lot shorter and cleaner.
Added:
trunk/coregrind/m_initimg/initimg-aix5.c
trunk/coregrind/m_initimg/simple_huffman.c
Modified:
trunk/coregrind/m_initimg/initimg-linux.c
Added: trunk/coregrind/m_initimg/initimg-aix5.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_initimg/initimg-aix5.c (rev=
0)
+++ trunk/coregrind/m_initimg/initimg-aix5.c 2006-10-17 01:23:07 UTC (rev=
6251)
@@ -0,0 +1,519 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Startup: create initial process image on AIX5 ---*/
+/*--- initimg-aix5.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_debuglog.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
+#include "pub_core_libcproc.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_clientstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_mallocfree.h"
+#include "pub_core_machine.h"
+#include "pub_core_ume.h"
+#include "pub_core_options.h"
+#include "pub_core_threadstate.h" /* ThreadArchState */
+#include "pub_core_tooliface.h" /* VG_TRACK */
+#include "pub_core_trampoline.h" /* VG_(ppc32_aix5_do_preloads_then_star=
t_client) */
+#include "pub_core_syscall.h" // VG_(do_syscall1)
+#include "pub_core_initimg.h" /* self */
+
+#include "simple_huffman.c"
+
+#if !defined(VGP_ppc32_aix5) && !defined(VGP_ppc64_aix5)
+#error "This should only be compiled on AIX"
+#endif
+
+
+static void diagnose_load_failure ( void );
+
+/* --- Create the client's initial memory image. --- */
+
+ClientInitImgInfo
+ VG_(setup_client_initial_image)(
+ /*IN*/ HChar** argv,
+ /*IN*/ HChar** envp,
+ /*IN*/ HChar* toolname,
+ /*IN*/ Addr clstack_top,
+ /*IN*/ SizeT clstack_max_size
+ )
+{
+ ClientInitImgInfo ciii;
+
+ /* Set up an AIX5PreloadPage structure with the names of
+
+ $VALGRIND_LIB/PLATFORM/vgpreload_core.so
+ $VALGRIND_LIB/PLATFORM/vgpreload_TOOL.so, if it exists
+ xxx in "LD_PRELOAD=3Dxxx", if it exists
+
+ The client is started by running (on the simulator, of course)
+ VG_(ppc{32,64}_aix5_do_preloads_then_start_client), which uses
+ __loadx/_kload to load these .so's. When the preloading is
+ done, various guest registers are restored to what they are
+ really supposed to be at client startup, so these values too are
+ stored in the AIX5PreloadPage. Finally, we jump to the client's
+ entry point address.=20
+ */
+ const HChar* _so =3D ".so";
+ const HChar* vgpreload_ =3D "vgpreload_";
+ const HChar* vgpreload_core_so =3D "vgpreload_core.so";
+ const HChar* errmsg_str=20
+ =3D "valgrind: FATAL: core/tool/LD_PRELOAD=3D "
+ "preload failed.\n";
+ Int plcore_len, pltool_len, ld_pre_len, errmsg_len;
+ HChar *plcore_str, *pltool_str, *ld_pre_str;
+ Bool have_tool_so, have_ld_pre;
+
+ AIX5PreloadPage* pp;
+ UChar* pc;
+ Int szB, szPG;
+ SysRes sres;
+
+ vg_assert( toolname );
+ pltool_len =3D VG_(strlen)( VG_(libdir) )=20
+ + 1 /*slash*/
+ + VG_(strlen)(VG_PLATFORM)
+ + 1 /*slash*/
+ + VG_(strlen)( vgpreload_ )
+ + VG_(strlen)( toolname )
+ + VG_(strlen)( _so )
+ + 1 /*NUL*/;
+ vg_assert(pltool_len > 0);
+ pltool_str =3D VG_(malloc)( pltool_len );
+ pltool_str[0] =3D 0;
+ VG_(strcat)( pltool_str, VG_(libdir) );
+ VG_(strcat)( pltool_str, "/" );
+ VG_(strcat)( pltool_str, VG_PLATFORM );
+ VG_(strcat)( pltool_str, "/" );
+ VG_(strcat)( pltool_str, vgpreload_ );
+ VG_(strcat)( pltool_str, toolname );
+ VG_(strcat)( pltool_str, _so );
+ vg_assert( pltool_str[pltool_len-1] =3D=3D 0);
+ vg_assert( VG_(strlen)(pltool_str) =3D=3D pltool_len-1 );
+
+ plcore_len =3D VG_(strlen)( VG_(libdir) )=20
+ + 1 /*slash*/
+ + VG_(strlen)(VG_PLATFORM)
+ + 1 /*slash*/
+ + VG_(strlen)( vgpreload_core_so )
+ + 1 /*NUL*/;
+ vg_assert(plcore_len > 0);
+ plcore_str =3D VG_(malloc)( plcore_len );
+ plcore_str[0] =3D 0;
+ VG_(strcat)( plcore_str, VG_(libdir) );
+ VG_(strcat)( plcore_str, "/" );
+ VG_(strcat)( plcore_str, VG_PLATFORM );
+ VG_(strcat)( plcore_str, "/" );
+ VG_(strcat)( plcore_str, vgpreload_core_so );
+ vg_assert( plcore_str[plcore_len-1] =3D=3D 0 );
+ vg_assert( VG_(strlen)(plcore_str) =3D=3D plcore_len-1 );
+
+ errmsg_len =3D VG_(strlen)( errmsg_str )
+ + 1 /*NUL*/;
+
+ ld_pre_str =3D VG_(getenv)("LD_PRELOAD");
+ if (ld_pre_str && VG_(strlen)(ld_pre_str) > 0) {
+ have_ld_pre =3D True;
+ ld_pre_len =3D VG_(strlen)(ld_pre_str) + 1/*NUL*/;
+ ld_pre_str =3D VG_(malloc)( ld_pre_len );
+ ld_pre_str[0] =3D 0;
+ VG_(strcat)( ld_pre_str, VG_(getenv)("LD_PRELOAD") );
+ vg_assert( ld_pre_str[ld_pre_len-1] =3D=3D 0);
+ vg_assert( VG_(strlen)( ld_pre_str ) =3D=3D ld_pre_len - 1 );
+ } else {
+ have_ld_pre =3D False;
+ ld_pre_len =3D 0;
+ ld_pre_str =3D NULL;
+ }
+
+ VG_(debugLog)(1, "initimg", "plcore_str =3D '%s'\n", plcore_str );
+ VG_(debugLog)(1, "initimg", "pltool_str =3D '%s'\n", pltool_str );
+ VG_(debugLog)(1, "initimg", "ld_pre_str =3D '%s'\n", ld_pre_str );
+
+ if (0 !=3D VG_(access)(plcore_str, True,False,True))
+ VG_(err_config_error)("Can't find core preload "
+ "(vgpreload_core.so)");
+
+ have_tool_so =3D 0 =3D=3D VG_(access)(pltool_str, True,False,True);
+
+ /* Figure out how much space is needed for an AIX5PreloadInfo
+ followed by the three preload strings. */
+
+ vg_assert((sizeof(AIX5PreloadPage) % 4) =3D=3D 0); /* paranoia */
+
+ szB =3D sizeof(AIX5PreloadPage) + plcore_len=20
+ + (have_tool_so ? pltool_len : 0)
+ + (have_ld_pre ? ld_pre_len : 0)
+ + errmsg_len;
+ szPG =3D VG_PGROUNDUP(szB+1) / VKI_PAGE_SIZE;
+ VG_(debugLog)(2, "initimg", "preload page size: %d bytes, %d pages\n"=
, szB, szPG);
+
+ vg_assert(szB > 0);
+ vg_assert(szB < szPG * VKI_PAGE_SIZE);
+
+ /* We'll need szPG pages of anonymous, rw-, client space (needs w
+ so we can write it here) */
+ sres =3D VG_(am_mmap_anon_float_client)
+ ( szPG * VKI_PAGE_SIZE, VKI_PROT_READ|VKI_PROT_WRITE);
+ if (sres.isError)
+ VG_(err_config_error)("Can't allocate client page(s) "
+ "for preload info");
+ pp =3D (AIX5PreloadPage*)sres.res;
+
+ VG_(debugLog)(2, "initimg", "preload page allocation succeeded at %p\=
n", pp);
+
+ /* Zero out the initial structure. */
+ VG_(memset)(pp, 0, sizeof(AIX5PreloadPage));
+
+ pc =3D (UChar*)pp;
+ pc +=3D sizeof(AIX5PreloadPage);
+ VG_(memcpy)(pc, plcore_str, plcore_len);
+ pp->off_preloadcorename =3D pc - (UChar*)pp;
+ pc +=3D plcore_len;
+ if (have_tool_so) {
+ VG_(memcpy)(pc, pltool_str, pltool_len);
+ pp->off_preloadtoolname =3D pc - (UChar*)pp;
+ pc +=3D pltool_len;
+ }
+ if (have_ld_pre) {
+ VG_(memcpy)(pc, ld_pre_str, ld_pre_len);
+ pp->off_ld_preloadname =3D pc - (UChar*)pp;
+ pc +=3D ld_pre_len;
+ }
+ VG_(memcpy)(pc, errmsg_str, errmsg_len);
+ pp->off_errmsg =3D pc - (UChar*)pp;
+ pp->len_errmsg =3D errmsg_len - 1; /* -1: skip terminating NUL */
+
+ vg_assert(pc <=3D ((UChar*)pp) - 1 + szPG * VKI_PAGE_SIZE);
+
+ VG_(free)(plcore_str);
+ VG_(free)(pltool_str);
+
+ /* Fill in all the other preload page fields that we can right
+ now. */
+# if defined(VGP_ppc32_aix5)
+ vg_assert(__NR_AIX5___loadx !=3D __NR_AIX5_UNKNOWN);
+ pp->nr_load =3D __NR_AIX5___loadx;
+# else /* defined(VGP_ppc64_aix5) */
+ vg_assert(__NR_AIX5_kload !=3D __NR_AIX5_UNKNOWN);
+ pp->nr_load =3D __NR_AIX5_kload;
+# endif
+
+ vg_assert(__NR_AIX5_kwrite !=3D __NR_AIX5_UNKNOWN);
+ pp->nr_kwrite =3D __NR_AIX5_kwrite; /* kwrite */
+
+ vg_assert(__NR_AIX5__exit !=3D __NR_AIX5_UNKNOWN);
+ pp->nr__exit =3D __NR_AIX5__exit; /* _exit */
+
+ pp->p_diagnose_load_failure =3D &diagnose_load_failure;
+
+ ciii.preloadpage =3D pp;
+ ciii.intregs37 =3D 0; /* filled in in m_main.c */
+ return ciii;
+}
+
+
+/* --- Finalise the initial image and register state. --- */
+
+static UChar unz_page[VKI_PAGE_SIZE];
+
+static UInt compute_adler32 ( void* addr, UWord len )
+{
+ UInt s1 =3D 1;
+ UInt s2 =3D 0;
+ UChar* buf =3D (UChar*)addr;
+ while (len > 0) {
+ s1 +=3D buf[0];
+ s2 +=3D s1;
+ s1 %=3D 65521;
+ s2 %=3D 65521;
+ len--;
+ buf++;
+ }
+ return (s2 << 16) + s1;
+}
+
+void VG_(finalise_thread1state)( /*MOD*/ThreadArchState* arch,
+ ClientInitImgInfo ciii )
+{
+ UInt adler32_act;
+ SysRes sres;
+ /* On AIX we get a block of 37 words telling us the initial state
+ for (GPR0 .. GPR31, PC, CR, LR, CTR, XER), and we start with all
+ the other registers zeroed. */
+
+# if defined(VGP_ppc32_aix5)
+
+ vg_assert(0 =3D=3D sizeof(VexGuestPPC32State) % 8);
+
+ /* Zero out the initial state, and set up the simulated FPU in a
+ sane way. */
+ LibVEX_GuestPPC32_initialise(&arch->vex);
+
+ /* Zero out the shadow area. */
+ VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
+
+# else /* defined(VGP_ppc64_aix5) */
+
+ vg_assert(0 =3D=3D sizeof(VexGuestPPC64State) % 8);
+
+ /* Zero out the initial state, and set up the simulated FPU in a
+ sane way. */
+ LibVEX_GuestPPC64_initialise(&arch->vex);
+
+ /* Zero out the shadow area. */
+ VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
+
+# endif
+
+ /* ciii.intregs37 contains the integer register state as it needs
+ to be at client startup. These values are supplied by the
+ launcher. The 37 regs are:initial values from launcher for:
+ GPR0 .. GPR31, PC, CR, LR, CTR, XER. */
+
+ /* Put essential stuff into the new state. */
+ arch->vex.guest_GPR0 =3D (UWord)ciii.intregs37[0];
+ arch->vex.guest_GPR1 =3D (UWord)ciii.intregs37[1];
+ arch->vex.guest_GPR2 =3D (UWord)ciii.intregs37[2];
+ arch->vex.guest_GPR3 =3D (UWord)ciii.intregs37[3];
+ arch->vex.guest_GPR4 =3D (UWord)ciii.intregs37[4];
+ arch->vex.guest_GPR5 =3D (UWord)ciii.intregs37[5];
+ arch->vex.guest_GPR6 =3D (UWord)ciii.intregs37[6];
+ arch->vex.guest_GPR7 =3D (UWord)ciii.intregs37[7];
+ arch->vex.guest_GPR8 =3D (UWord)ciii.intregs37[8];
+ arch->vex.guest_GPR9 =3D (UWord)ciii.intregs37[9];
+ arch->vex.guest_GPR10 =3D (UWord)ciii.intregs37[10];
+ arch->vex.guest_GPR11 =3D (UWord)ciii.intregs37[11];
+ arch->vex.guest_GPR12 =3D (UWord)ciii.intregs37[12];
+ arch->vex.guest_GPR13 =3D (UWord)ciii.intregs37[13];
+ arch->vex.guest_GPR14 =3D (UWord)ciii.intregs37[14];
+ arch->vex.guest_GPR15 =3D (UWord)ciii.intregs37[15];
+ arch->vex.guest_GPR16 =3D (UWord)ciii.intregs37[16];
+ arch->vex.guest_GPR17 =3D (UWord)ciii.intregs37[17];
+ arch->vex.guest_GPR18 =3D (UWord)ciii.intregs37[18];
+ arch->vex.guest_GPR19 =3D (UWord)ciii.intregs37[19];
+ arch->vex.guest_GPR20 =3D (UWord)ciii.intregs37[20];
+ arch->vex.guest_GPR21 =3D (UWord)ciii.intregs37[21];
+ arch->vex.guest_GPR22 =3D (UWord)ciii.intregs37[22];
+ arch->vex.guest_GPR23 =3D (UWord)ciii.intregs37[23];
+ arch->vex.guest_GPR24 =3D (UWord)ciii.intregs37[24];
+ arch->vex.guest_GPR25 =3D (UWord)ciii.intregs37[25];
+ arch->vex.guest_GPR26 =3D (UWord)ciii.intregs37[26];
+ arch->vex.guest_GPR27 =3D (UWord)ciii.intregs37[27];
+ arch->vex.guest_GPR28 =3D (UWord)ciii.intregs37[28];
+ arch->vex.guest_GPR29 =3D (UWord)ciii.intregs37[29];
+ arch->vex.guest_GPR30 =3D (UWord)ciii.intregs37[30];
+ arch->vex.guest_GPR31 =3D (UWord)ciii.intregs37[31];
+
+ arch->vex.guest_CIA =3D (UWord)ciii.intregs37[32+0];
+ arch->vex.guest_LR =3D (UWord)ciii.intregs37[32+2];
+ arch->vex.guest_CTR =3D (UWord)ciii.intregs37[32+3];
+
+# if defined(VGP_ppc32_aix5)
+
+ LibVEX_GuestPPC32_put_CR( (UWord)ciii.intregs37[32+1], &arch->vex );
+ LibVEX_GuestPPC32_put_XER( (UWord)ciii.intregs37[32+4], &arch->vex );
+
+ /* Set the cache line size (KLUDGE) */
+ VG_(machine_ppc32_set_clszB)( 128 );
+
+# else /* defined(VGP_ppc64_aix5) */
+
+ LibVEX_GuestPPC64_put_CR( (UWord)ciii.intregs37[32+1], &arch->vex );
+ LibVEX_GuestPPC64_put_XER( (UWord)ciii.intregs37[32+4], &arch->vex );
+
+ /* Set the cache line size (KLUDGE) */
+ VG_(machine_ppc64_set_clszB)( 128 );
+
+# endif
+
+ /* Fix up the client's command line. Its argc/v/envp is in r3/4/5
+ (32-bit AIX) or r14/15/16 (64-bit AIX). but that is for the
+ Valgrind invokation as a whole. Hence we need to decrement argc
+ and advance argv to step over the args for Valgrind, and the
+ name of the Valgrind tool exe bogusly inserted by the launcher
+ (hence the "+1"). */
+
+# if defined(VGP_ppc32_aix5)
+
+ vg_assert(arch->vex.guest_GPR3 >=3D 1 + VG_(args_for_valgrind).used);
+ arch->vex.guest_GPR3 -=3D (1 + VG_(args_for_valgrind).used);
+ arch->vex.guest_GPR4 +=3D sizeof(UWord) * (1 + VG_(args_for_valgrind)=
.used);
+
+# else /* defined(VGP_ppc64_aix5) */
+
+ vg_assert(arch->vex.guest_GPR14 >=3D 1 + VG_(args_for_valgrind).used)=
;
+ arch->vex.guest_GPR14 -=3D (1 + VG_(args_for_valgrind).used);
+ arch->vex.guest_GPR15 +=3D sizeof(UWord) * (1 + VG_(args_for_valgrind=
).used);
+
+# endif
+
+ /* At this point the guest register state is correct for client
+ startup. However, that's not where we want to start; in fact we
+ want to start at VG_(ppc{3,64}2_aix5_do_preloads_then_start_client=
),
+ passing it ciii.preloadpage in r3. This will load the core/tool
+ preload .so's, then restore r2-r10 from what's stashed in the
+ preloadpage, and then start the client really. Hence: */
+
+ /* Save r2-r10 and the client start point in preloadpage */
+ ciii.preloadpage->r2 =3D (ULong)arch->vex.guest_GPR2;
+ ciii.preloadpage->r3 =3D (ULong)arch->vex.guest_GPR3;
+ ciii.preloadpage->r4 =3D (ULong)arch->vex.guest_GPR4;
+ ciii.preloadpage->r5 =3D (ULong)arch->vex.guest_GPR5;
+ ciii.preloadpage->r6 =3D (ULong)arch->vex.guest_GPR6;
+ ciii.preloadpage->r7 =3D (ULong)arch->vex.guest_GPR7;
+ ciii.preloadpage->r8 =3D (ULong)arch->vex.guest_GPR8;
+ ciii.preloadpage->r9 =3D (ULong)arch->vex.guest_GPR9;
+ ciii.preloadpage->r10 =3D (ULong)arch->vex.guest_GPR10;
+ ciii.preloadpage->client_start =3D (ULong)arch->vex.guest_CIA;
+
+
+# if defined(VGP_ppc32_aix5)
+
+ /* Set up to start at VG_(ppc32_aix5_do_preloads_then_start_client) *=
/
+ arch->vex.guest_CIA =3D (UWord)&VG_(ppc32_aix5_do_preloads_then_start=
_client);
+
+# else /* defined(VGP_ppc64_aix5) */
+
+ /* Set up to start at VG_(ppc64_aix5_do_preloads_then_start_client) *=
/
+ arch->vex.guest_CIA =3D (UWord)&VG_(ppc64_aix5_do_preloads_then_start=
_client);
+
+# endif
+
+ arch->vex.guest_GPR3 =3D (UWord)ciii.preloadpage;
+
+ /* The rest of the preloadpage fields will already have been filled
+ in by VG_(setup_client_initial_image). So we're done. */
+
+ /* Finally, decompress the page compressed by the launcher. We
+ can't do this any earlier, because the page is (effectively)
+ decompressed in place, which trashes ciii.intregs37. So we have
+ to wait till this point, at which we're done with ciii.intregs37
+ (to be precise, with what it points at). */
+ VG_(debugLog)(1, "initimg", "decompressing page at %p\n",=20
+ (void*)ciii.compressed_page);
+ vg_assert(VG_IS_PAGE_ALIGNED(ciii.compressed_page));
+
+ Huffman_Uncompress( (void*)ciii.compressed_page, unz_page,
+ VKI_PAGE_SIZE, VKI_PAGE_SIZE );
+ adler32_act =3D compute_adler32(unz_page, VKI_PAGE_SIZE);
+
+ VG_(debugLog)(1, "initimg",=20
+ "decompress done, adler32s: act 0x%x, exp 0x%x\n",
+ adler32_act, ciii.adler32_exp );
+
+ VG_(memcpy)((void*)ciii.compressed_page, unz_page, VKI_PAGE_SIZE);
+
+ VG_(debugLog)(1, "initimg", "copy back done\n");
+
+ /* Tell the tool that we just wrote to the registers. */
+ VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
+ sizeof(VexGuestArchState));
+
+ /* Determine the brk limit. */
+ VG_(debugLog)(1, "initimg", "establishing current brk ..\n");
+ vg_assert(__NR_AIX5_sbrk !=3D __NR_AIX5_UNKNOWN);
+ sres =3D VG_(do_syscall1)(__NR_AIX5_sbrk, 0);
+ vg_assert(sres.err =3D=3D 0); /* assert no error */
+ VG_(brk_base) =3D VG_(brk_limit) =3D sres.res;
+ VG_(debugLog)(1, "initimg", ".. brk =3D %p\n", (void*)VG_(brk_base));
+}
+
+
+/* --- Diagnose preload failures. --- */
+
+/* This is a nasty but effective kludge. The address of the following
+ function is put into the preload page. So, if a preload failure
+ happens, we call here to get helpful info printed out (the call
+ site is in m_trampoline.S). This is a dirty hack (1) because
+ diagnose_load_failure runs on the simulated CPU, not the real one
+ and (2) because it induces a libc dependency. Oh well. */
+
+/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
+#include <stdlib.h>
+#include <sys/ldr.h>
+/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
+
+static void diagnose_load_failure ( void )
+{
+# define NBUF 1024
+ UChar buf[NBUF];
+ VG_(debugLog)(0, "initimg", "Diagnosing load failure\n");
+ if (sizeof(void*) =3D=3D 8) {
+ VG_(debugLog)(0, "initimg", "Can't safely do loadquery() "
+ "in 64-bit mode. Sorry.\n");
+ /* because this requires dynamic linking to be working (IIRC)
+ and it isn't; the tool file's dynamic linking was never done,
+ because it was loaded by the bootstrap stub, which simply did
+ sys_kload() but didn't make usla do the relevant
+ relocations. */
+ } else {
+ UChar** p;
+ Int r =3D loadquery(L_GETMESSAGES, buf, NBUF);
+ VG_(debugLog)(0, "initimg", "loadquery returned %d (0 =3D success)=
\n", r);
+ p =3D (UChar**)(&buf[0]);
+ for (; *p; p++)
+ VG_(debugLog)(0, "initimg", "\"%s\"\n", *p);
+ VG_(debugLog)(0, "initimg", "Use /usr/sbin/execerror to make "
+ "sense of above string(s)\n");
+ VG_(debugLog)(0, "initimg", "See also comments at the bottom of\n"=
);
+ VG_(debugLog)(0, "initimg", "coregrind/m_initimg/"
+ "initimg-aix5.c (in Valgrind sources)\=
n");
+ }
+# undef NBUF
+}
+
+/* Take the strings that this prints out and feed them
+ to /usr/sbin/execerror. For example, it might print
+
+ (ld 3 1 __libc_freeres /foo/bar/ppc32-aix5/vgpreload_core.so
+
+ in which case=20
+
+ $ execerror xyzzy \
+ "(ld 3 1 __libc_freeres /foo/bar/ppc32-aix5/vgpreload_core.so"
+
+ gets you
+
+ Could not load program xyzzy:
+ rtld: 0712-001 Symbol __libc_freeres was referenced
+ from module /foo/bar/ppc32-aix5/vgpreload_core.so(),=20
+ but a runtime definition
+ of the symbol was not found.
+*/
+
+/*--------------------------------------------------------------------*/
+/*--- initimg-aix5.c ---*/
+/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/m_initimg/initimg-linux.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_initimg/initimg-linux.c 2006-10-17 01:08:19 UTC (re=
v 6250)
+++ trunk/coregrind/m_initimg/initimg-linux.c 2006-10-17 01:23:07 UTC (re=
v 6251)
@@ -187,7 +187,7 @@
executable. This is needed for attaching to GDB. */
res =3D VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
if (!res.isError)
- VG_(cl_exec_fd) =3D res.val;
+ VG_(cl_exec_fd) =3D res.res;
=20
/* Copy necessary bits of 'info' that were filled in */
*client_ip =3D info->init_ip;
@@ -809,7 +809,7 @@
VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
);
vg_assert(!sres.isError);
- vg_assert(sres.val =3D=3D anon_start);
+ vg_assert(sres.res =3D=3D anon_start);
}
=20
=20
Added: trunk/coregrind/m_initimg/simple_huffman.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_initimg/simple_huffman.c (r=
ev 0)
+++ trunk/coregrind/m_initimg/simple_huffman.c 2006-10-17 01:23:07 UTC (r=
ev 6251)
@@ -0,0 +1,513 @@
+/***********************************************************************=
**
+* Name: huffman.c
+* Author: Marcus Geelnard
+* Description: Huffman coder/decoder implementation.
+* Reentrant: Yes
+* $Id: huffman.c,v 1.6 2004/12/14 18:59:40 marcus256 Exp $
+*
+* This is a very straight forward implementation of a Huffman coder and
+* decoder.
+*
+* Primary flaws with this primitive implementation are:
+* - Slow bit stream implementation
+* - Fairly slow decoding (slower than encoding)
+* - Maximum tree depth of 32 (the coder aborts if any code exceeds a
+* size of 32 bits). If I'm not mistaking, this should not be possible
+* unless the input buffer is larger than 2^32 bytes, which is not
+* supported by the coder anyway (max 2^32-1 bytes can be specified wi=
th
+* an unsigned 32-bit integer).
+*
+* On the other hand, there are a few advantages of this implementation:
+* - The Huffman tree is stored in a very compact form, requiring only
+* 12 bits per symbol (for 8 bit symbols), meaning a maximum of 384
+* bytes overhead.
+* - The Huffman coder does quite well in situations where the data is
+* noisy, in which case most dictionary based coders run into problems=
.
+*
+* Possible improvements (probably not worth it):
+* - Partition the input data stream into blocks, where each block has
+* its own Huffman tree. With variable block sizes, it should be
+* possible to find locally optimal Huffman trees, which in turn could
+* reduce the total size.
+* - Allow for a few different predefined Huffman trees, which could
+* reduce the size of a block even further.
+*-----------------------------------------------------------------------=
--
+* Copyright (c) 2003-2004 Marcus Geelnard
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must no=
t
+* claim that you wrote the original software. If you use this softwar=
e
+* in a product, an acknowledgment in the product documentation would
+* be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must no=
t
+* be misrepresented as being the original software.
+*
+* 3. This notice may not be removed or altered from any source
+* distribution.
+*
+* Marcus Geelnard
+* marcus.geelnard at home.se
+************************************************************************=
*/
+
+/* Modified May 06 by Julian Seward for use in Valgrind.
+ - changed integral types to V's versions (UInt, UChar etc)
+ - added initialisation in _Huffman_WriteBits, as described in
+ comment in that function.
+*/
+
+/***********************************************************************=
**
+* Types used for Huffman coding
+************************************************************************=
*/
+
+typedef struct {
+ UInt Symbol;
+ UInt Count;
+ UInt Code;
+ UInt Bits;
+} huff_sym_t;
+
+typedef struct {
+ UChar *BytePtr;
+ UInt BitPos;
+} huff_bitstream_t;
+
+
+
+/***********************************************************************=
**
+* INTERNAL FUNCTIONS =
*
+************************************************************************=
*/
+
+
+/***********************************************************************=
**
+* _Huffman_InitBitstream() - Initialize a bitstream.
+************************************************************************=
*/
+
+static void _Huffman_InitBitstream( huff_bitstream_t *stream,
+ UChar *buf )
+{
+ stream->BytePtr =3D buf;
+ stream->BitPos =3D 0;
+}
+
+
+/***********************************************************************=
**
+* _Huffman_ReadBits() - Read bits from a bitstream.
+************************************************************************=
*/
+
+static UInt _Huffman_ReadBits( huff_bitstream_t *stream,
+ UInt bits )
+{
+ UInt x, bit, count;
+ UChar *buf;
+
+ /* Get current stream state */
+ buf =3D stream->BytePtr;
+ bit =3D stream->BitPos;
+
+ /* Extract bits */
+ x =3D 0;
+ for( count =3D 0; count < bits; ++ count )
+ {
+ x =3D (x<<1) + (*buf & (1<<(7-bit)) ? 1 : 0);
+ bit =3D (bit+1) & 7;
+ if( !bit )
+ {
+ ++ buf;
+ }
+ }
+
+ /* Store new stream state */
+ stream->BytePtr =3D buf;
+ stream->BitPos =3D bit;
+
+ return x;
+}
+
+
+/***********************************************************************=
**
+* _Huffman_WriteBits() - Write bits to a bitstream.
+************************************************************************=
*/
+
+static void _Huffman_WriteBits( huff_bitstream_t *stream, UInt x,
+ UInt bits )
+{
+ UInt bit, count;
+ UChar *buf;
+ UInt mask;
+
+ /* Get current stream state */
+ buf =3D stream->BytePtr;
+ bit =3D stream->BitPos;
+
+ /* Append bits */
+ mask =3D 1 << (bits-1);
+ for( count =3D 0; count < bits; ++ count )
+ {
+ /* If we're starting a new byte, zero it out, so that the
+ resulting byte sequence looks completely defined from
+ Valgrind's point of view. If this doesn't happen then the
+ last byte in the stream may look partially undefined. */
+ if (bit =3D=3D 0)
+ *buf =3D 0;
+ *buf =3D (*buf & (0xff^(1<<(7-bit)))) +
+ ((x & mask ? 1 : 0) << (7-bit));
+ x <<=3D 1;
+ bit =3D (bit+1) & 7;
+ if( !bit )
+ {
+ ++ buf;
+ }
+ }
+
+ /* Store new stream state */
+ stream->BytePtr =3D buf;
+ stream->BitPos =3D bit;
+}
+
+
+/***********************************************************************=
**
+* _Huffman_Hist() - Calculate (sorted) histogram for a block of data.
+************************************************************************=
*/
+
+static void _Huffman_Hist( UChar *in, huff_sym_t *sym,
+ UInt size )
+{
+ Int k, swaps;
+ huff_sym_t tmp;
+
+ /* Clear/init histogram */
+ for( k =3D 0; k < 256; ++ k )
+ {
+ sym[k].Symbol =3D k;
+ sym[k].Count =3D 0;
+ sym[k].Code =3D 0;
+ sym[k].Bits =3D 0;
+ }
+
+ /* Build histogram */
+ for( k =3D size; k; -- k )
+ {
+ sym[ *in ++ ].Count ++;
+ }
+
+ /* Sort histogram - most frequent symbol first (bubble sort) */
+ do
+ {
+ swaps =3D 0;
+ for( k =3D 0; k < 255; ++ k )
+ {
+ if( sym[k].Count < sym[k+1].Count )
+ {
+ tmp =3D sym[k];
+ sym[k] =3D sym[k+1];
+ sym[k+1] =3D tmp;
+ swaps =3D 1;
+ }
+ }
+ }
+ while( swaps );
+}
+
+
+/***********************************************************************=
**
+* _Huffman_MakeTree() - Generate a Huffman tree.
+************************************************************************=
*/
+
+static void _Huffman_MakeTree( huff_sym_t *sym, huff_bitstream_t *stream=
,
+ UInt code, UInt bits, UInt first,
+ UInt last )
+{
+ UInt k, size, size_a, size_b, last_a, first_b;
+
+ /* Is this a leaf node? */
+ if( first =3D=3D last )
+ {
+ /* Append symbol to tree description */
+ _Huffman_WriteBits( stream, 1, 1 );
+ _Huffman_WriteBits( stream, sym[first].Symbol, 8 );
+
+ /* Store code info in symbol array */
+ sym[first].Code =3D code;
+ sym[first].Bits =3D bits;
+ return;
+ }
+ else
+ {
+ /* This was not a leaf node */
+ _Huffman_WriteBits( stream, 0, 1 );
+ }
+
+ /* Total size of interval */
+ size =3D 0;
+ for( k =3D first; k <=3D last; ++ k )
+ {
+ size +=3D sym[k].Count;
+ }
+
+ /* Find size of branch a */
+ size_a =3D 0;
+ for( k =3D first; size_a < ((size+1)>>1) && k < last; ++ k )
+ {
+ size_a +=3D sym[k].Count;
+ }
+
+ /* Non-empty branch? */
+ if( size_a > 0 )
+ {
+ /* Continue branching */
+ _Huffman_WriteBits( stream, 1, 1 );
+
+ /* Branch a cut in histogram */
+ last_a =3D k-1;
+
+ /* Create branch a */
+ _Huffman_MakeTree( sym, stream, (code<<1)+0, bits+1,
+ first, last_a );
+ }
+ else
+ {
+ /* This was an empty branch */
+ _Huffman_WriteBits( stream, 0, 1 );
+ }
+
+ /* Size of branch b */
+ size_b =3D size - size_a;
+
+ /* Non-empty branch? */
+ if( size_b > 0 )
+ {
+ /* Continue branching */
+ _Huffman_WriteBits( stream, 1, 1 );
+
+ /* Branch b cut in histogram */
+ first_b =3D k;
+
+ /* Create branch b */
+ _Huffman_MakeTree( sym, stream, (code<<1)+1, bits+1,
+ first_b, last );
+ }
+ else
+ {
+ /* This was an empty branch */
+ _Huffman_WriteBits( stream, 0, 1 );
+ }
+}
+
+
+/***********************************************************************=
**
+* _Huffman_RecoverTree() - Recover a Huffman tree from a bitstream.
+************************************************************************=
*/
+
+static void _Huffman_RecoverTree( huff_sym_t *sym,
+ huff_bitstream_t *stream, UInt code, UInt bits,
+ UInt *symnum )
+{
+ UInt symbol;
+
+ /* Is this a leaf node? */
+ if( _Huffman_ReadBits( stream, 1 ) )
+ {
+ /* Get symbol from tree description */
+ symbol =3D _Huffman_ReadBits( stream, 8 );
+
+ /* Store code info in symbol array */
+ sym[*symnum].Symbol =3D symbol;
+ sym[*symnum].Code =3D code;
+ sym[*symnum].Bits =3D bits;
+
+ /* Increase symbol counter */
+ *symnum =3D *symnum + 1;
+
+ return;
+ }
+
+ /* Non-empty branch? */
+ if( _Huffman_ReadBits( stream, 1 ) )
+ {
+ /* Create branch a */
+ _Huffman_RecoverTree( sym, stream, (code<<1)+0, bits+1,
+ symnum );
+ }
+
+ /* Non-empty branch? */
+ if( _Huffman_ReadBits( stream, 1 ) )
+ {
+ /* Create branch b */
+ _Huffman_RecoverTree( sym, stream, (code<<1)+1, bits+1,
+ symnum );
+ }
+}
+
+
+
+
+/***********************************************************************=
**
+* PUBLIC FUNCTIONS =
*
+************************************************************************=
*/
+
+
+/***********************************************************************=
**
+* Huffman_Compress() - Compress a block of data using a Huffman coder.
+* in - Input (uncompressed) buffer.
+* out - Output (compressed) buffer. This buffer must be 384 bytes
+* larger than the input buffer.
+* insize - Number of input bytes.
+* The function returns the size of the compressed data.
+************************************************************************=
*/
+static
+Int Huffman_Compress( UChar *in, UChar *out,
+ UInt insize )
+{
+ huff_sym_t sym[ 256 ], tmp;
+ huff_bitstream_t stream;
+ UInt k, total_bytes, swaps, symbol, last_symbol;
+
+ /* Do we have anything to compress? */
+ if( insize < 1 ) return 0;
+
+ /* Initialize bitstream */
+ _Huffman_InitBitstream( &stream, out );
+
+ /* Calculate and sort histogram for input data */
+ _Huffman_Hist( in, sym, insize );
+
+ /* Find number of used symbols */
+ for( last_symbol =3D 255; sym[last_symbol].Count =3D=3D 0; -- last_s=
ymbol );
+
+ /* Special case: In order to build a correct tree, we need at least
+ two symbols (otherwise we get zero-bit representations). */
+ if( last_symbol =3D=3D 0 ) ++ last_symbol;
+
+ /* Build Huffman tree */
+ _Huffman_MakeTree( sym, &stream, 0, 0, 0, last_symbol );
+
+ /* Was any code > 32 bits? (we do not handle that at present) */
+ for( k =3D 0; k < 255; ++ k )
+ {
+ if( sym[k].Bits > 32 )
+ {
+ return 0;
+ }
+ }
+
+ /* Sort histogram - first symbol first (bubble sort) */
+ do
+ {
+ swaps =3D 0;
+ for( k =3D 0; k < 255; ++ k )
+ {
+ if( sym[k].Symbol > sym[k+1].Symbol )
+ {
+ tmp =3D sym[k];
+ sym[k] =3D sym[k+1];
+ sym[k+1] =3D tmp;
+ swaps =3D 1;
+ }
+ }
+ }
+ while( swaps );
+
+ /* Encode input stream */
+ for( k =3D 0; k < insize; ++ k )
+ {
+ symbol =3D in[ k ];
+ _Huffman_WriteBits( &stream, sym[symbol].Code,
+ sym[symbol].Bits );
+ }
+
+ /* Calculate size of output data */
+ total_bytes =3D (Int)(stream.BytePtr - out);
+ if( stream.BitPos > 0 )
+ {
+ ++ total_bytes;
+ }
+
+ return total_bytes;
+}
+
+
+
+/***********************************************************************=
**
+* Huffman_Uncompress() - Uncompress a block of data using a Huffman
+* decoder.
+* in - Input (compressed) buffer.
+* out - Output (uncompressed) buffer. This buffer must be large
+* enough to hold the uncompressed data.
+* insize - Number of input bytes.
+* outsize - Number of output bytes.
+************************************************************************=
*/
+static
+void Huffman_Uncompress( UChar *in, UChar *out,
+ UInt insize, UInt outsize )
+{
+ huff_sym_t sym[ 256 ], tmp;
+ huff_bitstream_t stream;
+ UInt k, m, symbol_count, swaps;
+ UChar *buf;
+ UInt bits, delta_bits, new_bits, code;
+
+ /* Do we have anything to decompress? */
+ if( insize < 1 ) return;
+
+ /* Initialize bitstream */
+ _Huffman_InitBitstream( &stream, in );
+
+ /* Clear tree/histogram */
+ for( k =3D 0; k < 256; ++ k )
+ {
+ sym[k].Bits =3D 0x7fffffff;
+ }
+
+ /* Recover Huffman tree */
+ symbol_count =3D 0;
+ _Huffman_RecoverTree( sym, &stream, 0, 0, &symbol_count );
+
+ /* Sort histogram - shortest code first (bubble sort) */
+ do
+ {
+ swaps =3D 0;
+ for( k =3D 0; k < symbol_count-1; ++ k )
+ {
+ if( sym[k].Bits > sym[k+1].Bits )
+ {
+ tmp =3D sym[k];
+ sym[k] =3D sym[k+1];
+ sym[k+1] =3D tmp;
+ swaps =3D 1;
+ }
+ }
+ }
+ while( swaps );
+
+ /* Decode input stream */
+ buf =3D out;
+ for( k =3D 0; k < outsize; ++ k )
+ {
+ /* Search tree for matching code */
+ bits =3D 0;
+ code =3D 0;
+ for( m =3D 0; m < symbol_count; ++ m )
+ {
+ delta_bits =3D sym[m].Bits - bits;
+ if( delta_bits )
+ {
+ new_bits =3D _Huffman_ReadBits( &stream, delta_bits );
+ code =3D code | (new_bits << (32-bits-delta_bits));
+ bits =3D sym[m].Bits;
+ }
+ if( code =3D=3D (sym[m].Code << (32-sym[m].Bits)) )
+ {
+ *buf ++ =3D (UChar) sym[m].Symbol;
+ break;
+ }
+ }
+ }
+}
|
|
From: <sv...@va...> - 2006-10-17 01:08:23
|
Author: sewardj Date: 2006-10-17 02:08:19 +0100 (Tue, 17 Oct 2006) New Revision: 6250 Log: Merge r6101: Syscall wrappers for AIX5. Unfortunately they duplicate some of the stuff in syswrap-generic.c since making that compile on AIX is just too difficult. Added: trunk/coregrind/m_syswrap/priv_syswrap-aix5.h trunk/coregrind/m_syswrap/syscall-ppc32-aix5.S trunk/coregrind/m_syswrap/syscall-ppc64-aix5.S trunk/coregrind/m_syswrap/syswrap-aix5.c trunk/coregrind/m_syswrap/syswrap-ppc32-aix5.c trunk/coregrind/m_syswrap/syswrap-ppc64-aix5.c [... diff too large to include ...] |
|
From: <sv...@va...> - 2006-10-17 01:07:24
|
Author: sewardj
Date: 2006-10-17 02:07:21 +0100 (Tue, 17 Oct 2006)
New Revision: 6249
Log:
Merge r6100:
Code for reading XCOFF32 and XCOFF64 symbol tables and line numbers.
Added:
trunk/coregrind/m_debuginfo/priv_readxcoff.h
trunk/coregrind/m_debuginfo/readxcoff.c
Added: trunk/coregrind/m_debuginfo/priv_readxcoff.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/priv_readxcoff.h =
(rev 0)
+++ trunk/coregrind/m_debuginfo/priv_readxcoff.h 2006-10-17 01:07:21 UTC =
(rev 6249)
@@ -0,0 +1,46 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Read XCOFF format debug info. priv_readxcoff.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PRIV_READXCOFF_H
+#define __PRIV_READXCOFF_H
+
+
+/* Read whatever info we can from an XCOFF object file. */
+extern
+Bool ML_(read_xcoff_debug_info) ( struct _SegInfo* si,
+ Addr data_addr,
+ SSizeT data_len,
+ Bool is_mainexe );
+
+#endif /* ndef __PRIV_READXCOFF_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Added: trunk/coregrind/m_debuginfo/readxcoff.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/readxcoff.c (rev =
0)
+++ trunk/coregrind/m_debuginfo/readxcoff.c 2006-10-17 01:07:21 UTC (rev =
6249)
@@ -0,0 +1,2680 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Read XCOFF debug info. readxcoff.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* This file reads XCOFF symbol tables and debug info.
+ Known limitations:
+
+ * only one text section per object file is handled
+
+ * C_BINCL/C_EINCL handling is wrong, so functions defined in files
+ included from other files will end up with the wrong file name
+ and possibly line numbers. Fixable.
+
+ * The line number reader leans heavily on the fact that the generic
+ line number canonicaliser in storage.c truncates overlapping
+ ranges.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h" /* struct vki_stat et al */
+#include "pub_core_debuginfo.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_mallocfree.h"
+#include "pub_core_libcfile.h" /* stat, open, close */
+#include "pub_core_aspacemgr.h" /* for mmaping debuginfo files */
+#include "pub_core_options.h" /* VG_(clo_trace_symtab) */
+#include "priv_storage.h"
+#include "priv_readxcoff.h" /* self */
+
+/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
+#if defined(VGP_ppc32_aix5)
+# define __XCOFF32__ 1
+# undef __XCOFF64__
+#elif defined(VGP_ppc64_aix5)
+# define __XCOFF64__ 1
+# undef __XCOFF32__
+#else
+# error "This file should only be compiled on AIX"
+#endif
+#include <xcoff.h>
+
+#undef __AR_SMALL__
+#define __AR_BIG__ 1
+#include <ar.h>
+/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
+
+/* Debug stuff */
+#define SHOW_LD_STRTAB 1 /* loader string tables */
+#define SHOW_LD_SYMTAB 1 /* loader symbol table */
+#define SHOW_LD_RELTAB 1 /* loader reloc table */
+#define SHOW_STRTAB 1 /* main string table */
+#define SHOW_SYMS_P1 1 /* P1: find text sym starts */
+#define SHOW_SYMS_P2 1 /* P2: find text sym ends */
+#define SHOW_SYMS_P3 1 /* P3: src filenames & fn start/end line #s *=
/
+#define SHOW_SYMS_P4 1 /* P4: line numbers */
+#define SHOW_SYMS_P5 1 /* P5: find TOC pointers */
+#define SHOW_SYMS_P6 1 /* P6: finalise symbol info */
+
+#define SHOW_AR_DETAILS 0 /* show details of .a file internals */
+
+#define SHOW VG_(clo_trace_symtab)
+
+/* A small stack of filenames is maintained for dealing
+ with BINCL/EINCL symbol table entries. */
+
+#define N_FILENAME_STACK 16
+
+/* Phase 5 (find TOC pointers) has two implementations, the official
+ version, which involves reading the data segment symbols, and the
+ kludgey version, which basically scans the (actual loaded) data
+ segment to find structs which look like function descriptors. */
+
+#if 1
+# undef OFFICIAL_PHASE5
+#else
+# define OFFICIAL_PHASE5 1
+#endif
+
+/*------------------------------------------------------------*/
+/*--- Read XCOFF format debug info. ---*/
+/*------------------------------------------------------------*/
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+
+// priv
+struct _XArray {
+ void* (*alloc) ( SizeT );
+ void (*free) ( void* );
+ Word (*cmpFn) ( void*, void* );
+ Word elemSzB;
+ void* arr;
+ Word usedsize;
+ Word totsize;
+ Bool sorted;
+};
+
+// public
+typedef void XArray;
+
+/* Create new XArray, using given allocation and free function, and
+ for elements of the specified size. Alloc fn must not fail. */
+extern=20
+XArray* newXA ( void*(*alloc_fn)(SizeT),=20
+ void(*free_fn)(void*),
+ Word elemSzB );
+
+/* Free all memory associated with an XArray. */
+void deleteXA ( XArray* );
+
+/* Set the comparison function for this XArray. */
+void setCmpFnXA ( XArray*, Word (*compar)(void*,void*) );
+
+/* Add an element to an XArray. Element is copied into the XArray. */
+void addToXA ( XArray*, void* elem );
+
+/* Sort an XArray using its comparison function, if set; else bomb. */
+void sortXA ( XArray* );
+
+/* Lookup (by binary search) 'key' in the array. Set *first to be the
+ index of the first, and *last to be the index of the last matching
+ value found. If any values are found, return True, else return
+ False, and don't change *first or *last. Bomb if the array is not
+ sorted. */
+Bool lookupXA ( XArray*, void* key, Word* first, Word* last );
+
+/* How big is the XArray now? */
+Word sizeXA ( XArray* );
+
+/* Index into the XArray. */
+void* indexXA ( XArray*, Word );
+
+/* Drop the last n elements of an XArray. */
+void dropTailXA ( XArray*, Word );
+
+///////////////////////
+
+XArray* newXA ( void*(*alloc_fn)(SizeT),=20
+ void(*free_fn)(void*),
+ Word elemSzB )
+{
+ struct _XArray* xa;
+ vg_assert(alloc_fn);
+ vg_assert(free_fn);
+ vg_assert(elemSzB > 0);
+ xa =3D alloc_fn( sizeof(struct _XArray) );
+ vg_assert(xa);
+ xa->alloc =3D alloc_fn;
+ xa->free =3D free_fn;
+ xa->cmpFn =3D NULL;
+ xa->elemSzB =3D elemSzB;
+ xa->usedsize =3D 0;
+ xa->totsize =3D 0;
+ xa->sorted =3D False;
+ xa->arr =3D NULL;
+ return xa;
+}
+
+void deleteXA ( XArray* xao )
+{
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ vg_assert(xa->free);
+ if (xa->arr);
+ xa->free(xa->arr);
+ xa->free(xa);
+}
+
+void setCmpFnXA ( XArray* xao, Word (*compar)(void*,void*) )
+{
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ vg_assert(compar);
+ xa->cmpFn =3D compar;
+ xa->sorted =3D False;
+}
+
+void addToXA ( XArray* xao, void* elem )
+{
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ vg_assert(elem);
+ vg_assert(xa->totsize >=3D 0);
+ vg_assert(xa->usedsize >=3D 0 && xa->usedsize <=3D xa->totsize);
+ if (xa->usedsize =3D=3D xa->totsize) {
+ void* tmp;
+ Word newsz;
+ if (xa->totsize =3D=3D 0)
+ vg_assert(!xa->arr);
+ if (xa->totsize > 0)
+ vg_assert(xa->arr);
+ newsz =3D xa->totsize=3D=3D0 ? 2 : 2 * xa->totsize;
+ if (0)=20
+ VG_(printf)("addToXA: increasing from %ld to %ld\n",=20
+ xa->totsize, newsz);
+ tmp =3D xa->alloc(newsz * xa->elemSzB);
+ vg_assert(tmp);
+ if (xa->usedsize > 0)=20
+ VG_(memcpy)(tmp, xa->arr, xa->usedsize * xa->elemSzB);
+ if (xa->arr)
+ xa->free(xa->arr);
+ xa->arr =3D tmp;
+ xa->totsize =3D newsz;
+ }
+ vg_assert(xa->usedsize < xa->totsize);
+ vg_assert(xa->arr);
+ VG_(memcpy)( ((UChar*)xa->arr) + xa->usedsize * xa->elemSzB,
+ elem, xa->elemSzB );
+ xa->usedsize++;
+ xa->sorted =3D False;
+}
+
+// Generic shell sort. Like stdlib.h's qsort().
+static void ssort( void* base, Word nmemb, Word size,
+ Word (*compar)(void*, void*) )
+{
+ Int incs[14] =3D { 1, 4, 13, 40, 121, 364, 1093, 3280,
+ 9841, 29524, 88573, 265720,
+ 797161, 2391484 };
+ Int lo =3D 0;
+ Int hi =3D nmemb-1;
+ Int i, j, h, bigN, hp;
+
+ bigN =3D hi - lo + 1; if (bigN < 2) return;
+ hp =3D 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
+
+ #define SORT \
+ for ( ; hp >=3D 0; hp--) { \
+ h =3D incs[hp]; \
+ for (i =3D lo + h; i <=3D hi; i++) { \
+ ASSIGN(v,0, a,i); \
+ j =3D i; \
+ while (COMPAR(a,(j-h), v,0) > 0) { \
+ ASSIGN(a,j, a,(j-h)); \
+ j =3D j - h; \
+ if (j <=3D (lo + h - 1)) break; \
+ } \
+ ASSIGN(a,j, v,0); \
+ } \
+ }
+
+ // General case
+ {
+ char* a =3D base;
+ char v[size]; // will be at least 'size' bytes
+
+ #define ASSIGN(dst, dsti, src, srci) \
+ VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
+
+ #define COMPAR(dst, dsti, src, srci) \
+ compar( &dst[size*(dsti)], &src[size*(srci)] )
+
+ SORT;
+
+ #undef ASSIGN
+ #undef COMPAR
+ }
+ #undef SORT
+}
+
+void sortXA ( XArray* xao )
+{
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ vg_assert(xa->cmpFn);
+ ssort( xa->arr, xa->usedsize, xa->elemSzB, xa->cmpFn );
+ xa->sorted =3D True;
+}
+
+Bool lookupXA ( XArray* xao, void* key, Word* first, Word* last )
+{
+ Word lo, mid, hi, cres;
+ void* midv;
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ vg_assert(xa->cmpFn);
+ vg_assert(xa->sorted);
+ lo =3D 0;
+ hi =3D xa->usedsize-1;
+ while (True) {
+ /* current unsearched space is from lo to hi, inclusive. */
+ if (lo > hi) return False; /* not found */
+ mid =3D (lo + hi) / 2;
+ midv =3D indexXA( xa, mid );
+ cres =3D xa->cmpFn( key, midv );
+ if (cres < 0) { hi =3D mid-1; continue; }
+ if (cres > 0) { lo =3D mid+1; continue; }
+ /* Found it, at mid. See how far we can expand this. */
+ vg_assert(xa->cmpFn( key, indexXA(xa, lo) ) >=3D 0);
+ vg_assert(xa->cmpFn( key, indexXA(xa, hi) ) <=3D 0);
+ *first =3D *last =3D mid;
+ while (*first > 0=20
+ && 0 =3D=3D xa->cmpFn( key, indexXA(xa, (*first)-1)))
+ (*first)--;
+ while (*last < xa->usedsize-1
+ && 0 =3D=3D xa->cmpFn( key, indexXA(xa, (*last)+1)))
+ (*last)++;
+ return True;
+ }
+}
+
+Word sizeXA ( XArray* xao )
+{
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ return xa->usedsize;
+}
+
+void* indexXA ( XArray* xao, Word n )
+{
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ vg_assert(n >=3D 0);
+ vg_assert(n < xa->usedsize);
+ return ((char*)xa->arr) + n * xa->elemSzB;
+}
+
+void dropTailXA ( XArray* xao, Word n )
+{
+ struct _XArray* xa =3D (struct _XArray*)xao;
+ vg_assert(xa);
+ vg_assert(n >=3D 0);
+ vg_assert(n <=3D xa->usedsize);
+ xa->usedsize -=3D n;
+}
+
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+
+/* COFF uses a strange way to represent symbol names. A symbol is an
+ eight-byte field.
+
+ In 32-bit mode: if the first four bytes are zero, then the second
+ four bytes give the offset into the string table where the string
+ really is. Otherwise, the whole 8-byte thing is itself the name.
+
+ In 64-bit mode: a four-byte field at offset 8 is always interpreted
+ as an offset into the string table.
+
+ For a symbol of length 8, in 32-bit mode, there is no obvious way
+ to zero-terminate it. One solution is to copy the name into
+ dynamically allocated memory, but that complicates storage
+ management.
+
+ An alternative solution, used here, is to represent a name as a
+ (data, length) pair instead of the traditional zero-terminated
+ string. Such a pair can be constructed for any XCOFF symbol name,
+ and has the advantages that (1) no dynamic memory is required, and
+ (2) the name is guaranteed to be accessible as long as the object
+ image is mapped in.
+
+ What the .vec points at must not be modified; if you want to do
+ that, copy it elsewhere first.
+*/
+
+typedef
+ struct {
+ UChar* vec; /* the text of the name */
+ UInt len; /* length of the text */
+ }
+ Name;
+
+static Name maybeDerefStrTab( SYMENT* sym,
+ UChar* oi_strtab, UWord oi_n_strtab)
+{
+ Name res;
+ static UChar* bogus=20
+ =3D (UChar*)"**_Error_Dereferencing_COFF_String_Table_**";
+ UChar* bytes =3D (UChar*)sym;
+
+# if defined(VGP_ppc32_aix5)
+ if (bytes[0]=3D=3D0 && bytes[1]=3D=3D0 && bytes[2]=3D=3D0 && bytes[3]=
=3D=3D0) {
+ UInt off =3D *(UInt*)&bytes[4];
+ if (oi_strtab && oi_n_strtab > 0 && off < oi_n_strtab) {
+ res.vec =3D &oi_strtab[off];
+ res.len =3D VG_(strlen)(res.vec);
+ return res;
+ } else
+ goto bad;
+ } else {
+ Int i;
+ res.vec =3D bytes;
+ res.len =3D 8;
+ for (i =3D 0; i < 8; i++)
+ if (bytes[i] =3D=3D 0)
+ res.len--;
+ return res;
+ }
+
+# elif defined(VGP_ppc64_aix5)
+ ULong off =3D (ULong)( *(UInt*)&bytes[8] );
+ if (oi_strtab && oi_n_strtab > 0 && off < oi_n_strtab) {
+ res.vec =3D &oi_strtab[off];
+ res.len =3D VG_(strlen)(res.vec);
+ return res;
+ } else
+ goto bad;
+
+# else
+# error "Unknown platform"
+# endif
+
+ bad:
+ res.vec =3D bogus;
+ res.len =3D VG_(strlen)(bogus);
+ return res;
+}
+
+
+/* Similar scheme for extracting names from C_FILE auxiliary entries,
+ except that the 32-bit scheme appears to be always used, even for
+ XCOFF64. */
+
+static Name maybeDerefStrTab_fname ( UChar* bytes,
+ UChar* oi_strtab, UWord oi_n_strtab=
)
+{
+ Name res;
+ static UChar* bogus=20
+ =3D (UChar*)"**_Error_Dereferencing_COFF_String_Table_**";
+
+ if (bytes[0]=3D=3D0 && bytes[1]=3D=3D0 && bytes[2]=3D=3D0 && bytes[3]=
=3D=3D0) {
+ UInt off =3D *(UInt*)&bytes[4];
+ if (oi_strtab && oi_n_strtab > 0 && off < oi_n_strtab) {
+ res.vec =3D &oi_strtab[off];
+ res.len =3D VG_(strlen)(res.vec);
+ return res;
+ } else
+ goto bad;
+ } else {
+ Int i;
+ res.vec =3D bytes;
+ res.len =3D 8;
+ for (i =3D 0; i < 8; i++)
+ if (bytes[i] =3D=3D 0)
+ res.len--;
+ return res;
+ }
+
+ bad:
+ res.vec =3D bogus;
+ res.len =3D VG_(strlen)(bogus);
+ return res;
+}
+
+
+static Name mk_const_Name ( HChar* str )
+{
+ Name res;
+ res.vec =3D str;
+ res.len =3D VG_(strlen)(res.vec);
+ return res;
+}
+
+static Name mk_empty_Name ( void )
+{
+ Name res;
+ res.vec =3D "";
+ res.len =3D 0;
+ return res;
+}
+
+static Bool is_empty_Name ( Name name )
+{
+ return name.len =3D=3D 0;
+}
+
+static Bool eq_string_Name ( Name name, UChar* str )
+{
+ UInt i;
+ for (i =3D 0; i < name.len; i++) {
+ if (str[i] =3D=3D 0)
+ return False;
+ if (str[i] !=3D name.vec[i])
+ return False;
+ }
+ if (str[name.len] =3D=3D 0)
+ return True;
+ else
+ return False;
+}
+
+static Word cmp_Names ( Name n1, Name n2 )
+{
+ UInt i =3D 0;
+ while (1) {
+ vg_assert(i >=3D 0 && i <=3D n1.len);
+ vg_assert(i >=3D 0 && i <=3D n2.len);
+ if (i =3D=3D n1.len && i =3D=3D n2.len)
+ return 0;
+ if (i =3D=3D n1.len && i < n2.len)
+ return -1;
+ if (i < n1.len && i =3D=3D n2.len)
+ return 1;
+ if (n1.vec[i] < n2.vec[i])
+ return -1;
+ if (n1.vec[i] > n2.vec[i])
+ return 1;
+ i++;
+ }
+}
+
+static void print_Name ( Name name )
+{
+ UInt i;
+ for (i =3D 0; i < name.len; i++)
+ VG_(printf)("%c", name.vec[i]);
+}
+
+
+static UChar sanitiseChar ( UChar c )
+{
+ if (c < 32 || c > 127)
+ c =3D '?';
+ return c;
+}
+
+static HChar* name_of_filhdr_f_magic ( Int magic )
+{
+ switch (magic) {
+ case 0x01DF: return "xcoff32";
+ case 0x01EF: return "xcoff64-upto-aix43";
+ case 0x01F7: return "xcoff64-from-aix51";
+ default: return "unknown-xcoff-header-magic";
+ }
+}
+
+static HChar* name_of_scnhdr_s_flags ( Int flags )
+{
+ switch (flags & 0xFFFF) {
+ case STYP_REG: return "\"regular\"";
+ case STYP_PAD: return "\"padding\"";
+ case STYP_TEXT: return "text only";
+ case STYP_DATA: return "data only";
+ case STYP_BSS: return "bss only";
+ case STYP_EXCEPT: return "Exception";
+ case STYP_INFO: return "Comment";
+ case STYP_LOADER: return "Loader";
+ case STYP_DEBUG: return "Debug";
+ case STYP_TYPCHK: return "Typecheck";
+ case STYP_OVRFLO: return "Overflow";
+ default: return "unknown-section-header-name";
+ }
+}
+
+static HChar* name_of_syment_n_sclass ( Int sclass )
+{
+ static HChar buf[10];
+ switch (sclass) {
+ /* dbx ones (>=3D 0x80) */
+ case C_GSYM: return "gsym";
+ case C_LSYM: return "lsym";
+ case C_PSYM: return "psym";
+ case C_RSYM: return "rsym";
+ case C_RPSYM: return "rpsym";
+ case C_STSYM: return "stsym";
+ case C_DECL: return "decl";
+ case C_FUN: return "fun";
+ case C_BSTAT: return "bstat";
+ case C_ESTAT: return "estat";
+ /* non-dbx ones (< 0x80) */
+ case C_STAT: return "STAT";
+ case C_FILE: return "FILE";
+ case C_HIDEXT: return "HIDEXT";
+ case C_EXT: return "EXT";
+ case C_FCN: return "FCN";
+ case C_BINCL: return "BINCL";
+ case C_EINCL: return "EINCL";
+ case C_BLOCK: return "BLOCK";
+ case C_WEAKEXT: return "WEAKEXT";
+ default:
+ VG_(sprintf)(buf, "??%d??", sclass);
+ return buf;
+ }
+}
+
+typedef=20
+ struct {
+ Name name; /* symbol's name */
+ Addr first; /* first address; always known */
+ Addr last; /* last address; may be an overestimate */
+
+ Name fname; /* source file name, if known */
+ Int slnno; /* starting line #, or 0 if unknown */
+ Int elnno; /* ending line #, or 0 if unknown */
+
+ UWord r2value; /* what r2 should be for this fn (tocptr) */
+ Bool r2known; /* do we have a r2 value? */
+ }=20
+ XCoffSym;
+
+static void init_XCoffSym( XCoffSym* sym )
+{
+ sym->name =3D mk_empty_Name();
+ sym->first =3D 0;
+ sym->last =3D 0;
+ sym->fname =3D mk_empty_Name();
+ sym->slnno =3D 0;
+ sym->elnno =3D 0;
+ sym->r2known =3D False;
+ sym->r2value =3D False;
+}
+
+/* Compare XCoffSyms by their start address. */
+static Word cmp_XCoffSym_by_start ( void* v1, void* v2 )
+{
+ XCoffSym* s1 =3D (XCoffSym*)v1;
+ XCoffSym* s2 =3D (XCoffSym*)v2;
+ if (s1->first < s2->first) return -1;
+ if (s1->first > s2->first) return 1;
+ return 0;
+}
+
+/* Compare XCoffSyms by a slightly weaker ordering, returning zero
+ (equivalence) for any overlap, and -1 or 1 otherwise. */
+static Word cmp_XCoffSym_by_overlap ( void* v1, void* v2 )
+{
+ XCoffSym* s1 =3D (XCoffSym*)v1;
+ XCoffSym* s2 =3D (XCoffSym*)v2;
+ if (s1->last < s2->first) return -1;
+ if (s2->last < s1->first) return 1;
+ return 0;
+}
+
+/* Compare XCoffSyms by their start address, and for equal addresses,
+ use the name as a secondary sort key. */
+static Word cmp_XCoffSym_by_start_then_name ( void* v1, void* v2 )
+{
+ XCoffSym* s1 =3D (XCoffSym*)v1;
+ XCoffSym* s2 =3D (XCoffSym*)v2;
+ if (s1->first < s2->first) return -1;
+ if (s1->first > s2->first) return 1;
+ return cmp_Names(s1->name, s2->name);
+}
+
+
+/* csect_idx is an index in the symbol table (start, n_entries) to a
+ symbol defining a csect. If possible, find the bounds of the csect
+ and assign them to *first and *last, and return True; else return
+ False. sntext_1based_if_known is the 1-based number of the text
+ section. Note: computes stated VMAs, not actual VMAs. */
+
+#if defined(VGP_ppc32_aix5)
+# define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */
+# define CSECT(PP) (((AUXENT*)(PP))->x_csect)
+# define CSECT_LEN(PP) (CSECT(PP).x_scnlen)
+# define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp))
+# define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp))
+# define CSECT_SCLAS(PP) (CSECT(PP).x_smclas)
+
+#elif defined(VGP_ppc64_aix5)
+# define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */
+# define CSECT(PP) (((AUXENT*)(PP))->x_csect)
+# define CSECT_LEN(PP) ((((ULong)(CSECT(PP).x_scnlen_hi)) << 32) \
+ | ((ULong)(CSECT(PP).x_scnlen_lo)))
+# define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp))
+# define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp))
+# define CSECT_SCLAS(PP) (CSECT(PP).x_smclas)
+
+#else
+# error "Unknown platform"
+
+#endif
+
+
+#define SYM_IX(_tab,_n) ((SYMENT*)(((UChar*)(_tab)) + SYMESZ * (_n)))
+
+static=20
+Bool get_csect_bounds ( UChar* start, UWord n_entries,
+ UWord csect_idx,=20
+ Int sntext_1based_if_known,
+ /*OUT*/UChar** first, /*OUT*/UChar** last )
+{
+ Bool is_text;
+ SYMENT* cssym;
+ AUXENT* csaux;
+
+ vg_assert(SYMESZ =3D=3D 18); /* both for XCOFF32 and XCOFF64 */
+
+ if (n_entries < 2)
+ return False;
+ if (csect_idx+1 >=3D n_entries)
+ return False;
+ cssym =3D (SYMENT*)SYM_IX(start, csect_idx);
+ csaux =3D (AUXENT*)SYM_IX(start, csect_idx+1);
+ is_text =3D sntext_1based_if_known !=3D -1
+ && (Int)cssym->n_scnum =3D=3D sntext_1based_if_known;
+
+ if (!is_text)
+ return False;
+
+ if (cssym->n_sclass =3D=3D C_EXT || cssym->n_sclass =3D=3D C_HIDEXT) =
{
+ if (cssym->n_numaux =3D=3D 1) {
+ if (CSECT_SMTYP(csaux) =3D=3D XTY_SD) {
+ if (0) VG_(printf)("GCB: SD: len is %ld\n", CSECT_LEN(csaux)=
);
+ *first =3D (UChar*)(cssym->n_value);
+ *last =3D *first + CSECT_LEN(csaux)-1;
+ return True;
+ }
+ } else {
+ /* Possibly complain or take evasive action here. In fact
+ I've yet to see a case where a csect definition symbol has
+ n_numaux !=3D 1. */
+ }
+ }
+ return False;
+}
+
+static void* malloc_AR_SYMTAB ( SizeT nbytes ) {
+ return VG_(arena_malloc)(VG_AR_SYMTAB, nbytes);
+}
+static void free_AR_SYMTAB ( void* ptr ) {
+ return VG_(arena_free)(VG_AR_SYMTAB, ptr);
+}
+
+/* Read symbol and line number info for the given text section. (This
+ is the central routine for XCOFF reading.) Returns NULL on
+ success, or the text of an error message otherwise. */
+static=20
+HChar* read_symbol_table (=20
+ /*MOD*/SegInfo* si,
+
+ /* location of symbol table */
+ UChar* oi_symtab, UWord oi_nent_symtab,
+
+ /* location of string table */
+ UChar* oi_strtab, UWord oi_n_strtab,
+
+ /* location of debug section (stabs strings, if any) */
+ UChar* oi_debug, UWord oi_n_debug,
+
+ /* location of line number info, if any */
+ UChar* oi_lnos, UWord oi_nent_lnos,
+
+ /* section indices */
+ Int sntext_1based_if_known,
+ Int sndata_1based_if_known,
+
+ /* where the mapped data section is */
+ Addr data_avma,=20
+ UWord data_alen,
+ UWord data_alen_from_auxhdr,
+
+ /* where the mapped toc is (in the data section,
+ presumably), if known */
+ Addr toc_avma,
+
+ /* stated-to-actual VMA offsets */=20
+ Word text_bias,
+ Word data_bias=20
+ )
+{
+ SYMENT* sym;
+ SYMENT* aux;
+ UInt i, j, nsyms, k, m;
+ Name name;
+ Bool is_text, is_data;
+ XArray* syms =3D NULL; /* XArray of XCoffSyms */
+
+ /* If the TOC avma is obviously bogus, get rid of it */
+ {=20
+ UWord data_maxlen =3D data_alen;
+ if (data_maxlen < data_alen_from_auxhdr)
+ data_maxlen =3D data_alen_from_auxhdr;
+
+ //VG_(printf)(" toc_avma %p\n", toc_avma);
+ //VG_(printf)("data_avma %p\n", data_avma);
+ //VG_(printf)("dxxx_avma %p\n", data_avma + data_maxlen);
+
+ if (toc_avma !=3D 0
+ && (toc_avma < data_avma || toc_avma >=3D data_avma + data_maxl=
en))
+ toc_avma =3D 0;
+ //VG_(printf)("2toc_avma %p\n", toc_avma);
+ }
+
+ /* We can't just treat this as an array of SYMENTs, because C
+ thinks they have size 20 whereas the spec says they have size 18
+ (alignment padding) so doing the obvious thing screws up. Hence
+ we have to calculate the offset of each entry manually. */
+
+ if (0) VG_(printf)("size of SYMENT =3D %ld\n", sizeof(SYMENT));
+
+ /* ----------------------------------------------------------
+ Phase 1: first make a pass through the symbols, looking for
+ stuff in the text segment. Calculate their actual VMAs,
+ dump any outside the text segment actual VMA bounds, and=20
+ add the rest to 'syms'.
+ ---------------------------------------------------------- */
+
+ syms =3D newXA( malloc_AR_SYMTAB, free_AR_SYMTAB, sizeof(XCoffSym) );
+
+ if (SHOW && SHOW_SYMS_P1) {
+ VG_(printf)("--- BEGIN Phase1 (find text symbol starts) ---\n");
+ VG_(printf)("--- note: shown addresses are STATED VMAs ---\n");
+ }
+
+ i =3D 0;
+ while (1) {
+
+ if (i >=3D oi_nent_symtab)
+ break;
+
+ sym =3D SYM_IX(oi_symtab, i);
+ is_text =3D sntext_1based_if_known !=3D -1
+ && (Int)sym->n_scnum =3D=3D sntext_1based_if_known;
+ is_data =3D sndata_1based_if_known !=3D -1
+ && (Int)sym->n_scnum =3D=3D sndata_1based_if_known;
+
+ if (SHOW && SHOW_SYMS_P1)
+ VG_(printf)("Phase1: %5d+%d ", i, (Int)sym->n_numaux);
+
+ name =3D mk_const_Name("(unknown)");
+ if (sym->n_scnum =3D=3D N_DEBUG && sym->n_sclass =3D=3D C_FUN)
+ name =3D maybeDerefStrTab( sym, oi_debug, oi_n_debug );
+ else=20
+ if (sym->n_sclass & DBXMASK)
+ name =3D mk_const_Name("(dbxstr)");
+ else
+ name =3D maybeDerefStrTab( sym, oi_strtab, oi_n_strtab);
+
+ if (SHOW && SHOW_SYMS_P1) {
+ VG_(printf)("%5s(%2d) %6s 0x%016llx ",=20
+ is_text ? "text" : is_data ? "data" : "other",
+ (Int)sym->n_scnum,=20
+ name_of_syment_n_sclass(sym->n_sclass),=20
+ (ULong)sym->n_value);
+ print_Name(name);
+ VG_(printf)("\n");
+ }
+
+ i++;
+ i +=3D sym->n_numaux;
+
+ if (!is_text)
+ continue;
+
+ /* --- BEGIN regular(ish) symbol --- */
+ if ((sym->n_sclass =3D=3D C_EXT || sym->n_sclass =3D=3D C_HIDEXT)
+ && (sym->n_numaux =3D=3D 1 || sym->n_numaux =3D=3D 2)) {
+ /* Dealing with a symbol with a csect entry. By convention
+ (according to IBM docs) the csect entry is the last
+ auxiliary for this symbol, if there is more than one
+ auxiliary present; hence "SYM_IX(oi_symtab, i-1)" below. */
+
+ aux =3D SYM_IX(oi_symtab, i-1);
+ if (0) VG_(printf)("symtype is %d\n", CSECT_SMTYP(aux));
+
+ if (CSECT_SMTYP(aux) =3D=3D XTY_SD) {
+ /* Aux is a csect definition. This is relatively rare,
+ but at least it is simple: the CSECT_LEN(aux) field
+ contains it's length, so we just heave that into the
+ pot for phase 2. */
+ XCoffSym cand;
+ if (0) VG_(printf)("SD: len is %d\n", (Int)CSECT_LEN(aux));
+ if (0) VG_(printf)("SD: proposed %p\n", sym->n_value);
+ init_XCoffSym(&cand);
+ cand.first =3D sym->n_value;
+ cand.last =3D cand.first + (UWord)CSECT_LEN(aux) - 1;
+
+ cand.first +=3D text_bias;
+ cand.last +=3D text_bias;
+ cand.name =3D name;
+
+ if (cand.last < si->start || cand.first >=3D si->start+si->s=
ize)
+ continue;
+ if (cand.last < cand.first)
+ continue;
+ if (is_empty_Name(name))
+ continue;
+ addToXA(syms, &cand);
+ }
+
+ if (CSECT_SMTYP(aux) =3D=3D XTY_LD) {
+ /* Aux is a label definition. This is the common case. */
+ XCoffSym cand;
+ Bool ok;
+ UChar *csect_first, *csect_last;
+ /* x_scnlen contains the symbol table entry of the
+ containing csect. Use the symbol's stated vma and csect
+ end as the initial approximation of this symbol's start
+ and length. The length will get revised downwards in
+ Phase 2. */
+ init_XCoffSym(&cand);
+ ok =3D get_csect_bounds( oi_symtab, oi_nent_symtab,=20
+ CSECT_LEN(aux),=20
+ sntext_1based_if_known,
+ &csect_first, &csect_last );
+ if (0 && ok)
+ VG_(printf)("new csect svma %p %p\n", csect_first, csect_=
last);
+ if (ok && ((UWord)csect_first) <=3D ((UWord)sym->n_value)
+ && ((UWord)sym->n_value) <=3D ((UWord)csect_last)) {
+ if (0) {
+ VG_(printf)("LD: in a csect %p %p\n",=20
+ csect_first, csect_last);
+ VG_(printf)("CAND: %p .. %p %s\n",=20
+ (void*)sym->n_value, (void*)csect_last, na=
me);
+ }
+ cand.first =3D sym->n_value;
+ cand.last =3D (Addr)csect_last;
+ } else {
+ if (0) {
+ VG_(printf)("LD: can't compute csect bounds?!\n");
+ VG_(printf)("CAND: %p .. %p %s\n",=20
+ (HChar*)sym->n_value,
+ (HChar*)sym->n_value+1, name);
+ }
+ cand.first =3D sym->n_value;
+ cand.last =3D cand.first + 1;
+ }
+
+ /* cand.first is a stated VMA; turn it into an actual VMA
+ and ignore it if not in the actual text segment. */
+
+ cand.first +=3D text_bias;
+ cand.last +=3D text_bias;
+ cand.name =3D name;
+
+ if (cand.last < si->start || cand.first >=3D si->start+si->s=
ize)
+ continue;
+ if (cand.last < cand.first)
+ continue;
+ if (is_empty_Name(name))
+ continue;
+
+ addToXA(syms, &cand);
+ }
+ }
+ /* --- END regular(ish) symbol --- */
+
+ }
+
+ /* ----------------------------------------------------------
+ Phase 2: suitable text symbols have been put into 'syms'. Their
+ start addresses are correct, but end addresses are those of the
+ containing csect, which is in general way too long. This phase
+ clips the ends so that the ranges no longer overlap, and thereby
+ constrains each symbol's range to something which, for the most
+ part, is correct.
+ ---------------------------------------------------------- */
+
+ nsyms =3D sizeXA(syms);
+
+ if (SHOW && SHOW_SYMS_P1)
+ VG_(printf)("Phase1 acquired %d text symbols\n", nsyms);
+
+ if (SHOW && SHOW_SYMS_P2) {
+ VG_(printf)("--- BEGIN Phase2 (find text symbol ends) ---\n");
+ VG_(printf)("--- note: shown addresses are ACTUAL VMAs ---\n");
+ }
+
+ setCmpFnXA(syms, cmp_XCoffSym_by_start_then_name);
+ sortXA(syms);
+
+ /* We only know for sure the start addresses (actual VMAs) of
+ symbols, and an overestimation of their end addresses. So sort
+ by start address, then clip each symbol so that its end address
+ does not overlap with the next one along.
+
+ There is a small refinement: if a group of symbols have the same
+ address, treat them as a group: find the next symbol along that
+ has a higher start address, and clip all of the group
+ accordingly. This clips the group as a whole so as not to
+ overlap following symbols. This leaves prefersym() in
+ storage.c, which is not XCOFF-specific, to later decide which of
+ the symbols in the group to keep.=20
+
+ Another refinement is that we need to get rid of symbols which,
+ after clipping, have identical starts, ends, and names. So the
+ sorting uses the name as a secondary key.
+ */
+
+ for (i =3D 0; i < nsyms; i++) {
+ for (k =3D i+1;=20
+ k < nsyms=20
+ && ((XCoffSym*)indexXA(syms,i))->first=20
+ =3D=3D ((XCoffSym*)indexXA(syms,k))->first;=20
+ k++)
+ ;
+ /* So now [i .. k-1] is a group all with the same start address.
+ Clip their ending addresses so they don't overlap [k]. In
+ the normal case (no overlaps), k =3D=3D i+1. */
+ if (k < nsyms) {
+ XCoffSym* next =3D (XCoffSym*)indexXA(syms,k);
+ for (m =3D i; m < k; m++) {
+ XCoffSym* here =3D (XCoffSym*)indexXA(syms,m);
+ vg_assert(here->first < next->first);
+ if (here->last >=3D next->first)
+ here->last =3D next->first-1;
+ }
+ }
+ i =3D k-1;
+ vg_assert(i <=3D nsyms);
+ }
+
+ j =3D 0;
+ if (nsyms > 0) {
+ j =3D 1;
+ for (i =3D 1; i < nsyms; i++) {
+ vg_assert(j <=3D i);
+ XCoffSym* s_j1 =3D (XCoffSym*)indexXA(syms, j-1);
+ XCoffSym* s_j =3D (XCoffSym*)indexXA(syms, j);
+ XCoffSym* s_i =3D (XCoffSym*)indexXA(syms, i);
+ if (s_i->first !=3D s_j1->first
+ || s_i->last !=3D s_j1->last
+ || 0 !=3D cmp_Names(s_i->name, s_j1->name)) {
+ *s_j =3D *s_i;
+ j++;
+ } else {
+ if (SHOW && SHOW_SYMS_P2) {
+ VG_(printf)("Phase2: dump duplicate ");=20
+ print_Name(s_i->name);
+ VG_(printf)("\n");
+ }
+ }
+ }
+ }
+ vg_assert(j >=3D 0 && j <=3D nsyms);
+ dropTailXA(syms, nsyms - j);
+ nsyms =3D j;
+
+ if (1) {
+ for (i =3D 0; i < nsyms; i++) {
+ XCoffSym* s =3D (XCoffSym*)indexXA(syms, i);
+ if (SHOW && SHOW_SYMS_P2) {
+ VG_(printf)("Phase2: %d 0x%lx 0x%lx ",=20
+ i, s->first, s->last);
+ print_Name(s->name);
+ VG_(printf)("\n");
+ }
+ }
+ }
+
+ /* ----------------------------------------------------------
+ Phase 3: rescan the symbol table, looking for info on function
+ start/end line numbers and source file names. Generally
+ this will be absent for sources compiled without -g.
+ ---------------------------------------------------------- */
+
+ if (SHOW && SHOW_SYMS_P3) {
+ VG_(printf)("--- BEGIN Phase3 (find src filenames "
+ "& fn start/end line #s) ---\n");
+ VG_(printf)("--- note: shown addresses are STATED VMAs ---\n");
+ }
+
+ /* The lookupXAs in the C_FUN(.bf) part have to operate by
+ inclusion. Hence: */
+ setCmpFnXA(syms, cmp_XCoffSym_by_overlap);
+ sortXA(syms);
+
+ /* In this loop, p3currsym is maintained as a pointer to the most
+ recent XCoffSym identified as FCN(.bf) (function start).
+ Subsequent FCN(.ef) (function end) indications are compared
+ against said symbol. This assumes that function start/end
+ indications are not nested. */
+
+ XCoffSym* p3currsym =3D NULL;
+
+ /* Maintain a stack of filenames. We allow the stack pointer to go
+ beyond the end, but obviously nothing is stored in this
+ imaginary part of the stack. */
+ Name filenames[N_FILENAME_STACK];
+ Int filenames_used =3D 1;
+
+ Name name_unknown =3D mk_empty_Name();
+ Name name_overflow =3D mk_const_Name("(filename_stack_overflow)");
+
+ for (i =3D 0; i < N_FILENAME_STACK; i++)
+ filenames[i] =3D name_unknown;
+
+# define FNAME_PUSH(_fname) \
+ do { \
+ vg_assert(filenames_used >=3D 1);\
+ if (filenames_used < N_FILENAME_STACK)\
+ filenames[filenames_used] =3D (_fname);\
+ filenames_used++;\
+ } while (0)
+
+# define FNAME_POP \
+ do {\
+ vg_assert(filenames_used >=3D 1);\
+ if (filenames_used > 1 && filenames_used <=3D N_FILENAME_STACK)=
\
+ filenames[filenames_used-1] =3D name_unknown; \
+ if (filenames_used > 1)\
+ filenames_used--;\
+ } while (0)
+
+# define FNAME_GET_TOP \
+ (filenames_used > N_FILENAME_STACK \
+ ? name_overflow \
+ : filenames[filenames_used-1])
+
+# define FNAME_SET_TOP(_fname) \
+ do {\
+ vg_assert(filenames_used >=3D 1);\
+ filenames[filenames_used-1] =3D (_fname);\
+ } while (0)
+
+
+ i =3D 0;
+ while (1) {
+
+ if (i >=3D oi_nent_symtab)
+ break;
+
+ sym =3D SYM_IX(oi_symtab, i);
+ is_text =3D sntext_1based_if_known !=3D -1
+ && (Int)sym->n_scnum =3D=3D sntext_1based_if_known;
+ is_data =3D sndata_1based_if_known !=3D -1
+ && (Int)sym->n_scnum =3D=3D sndata_1based_if_known;
+
+ if (0 && SHOW && SHOW_SYMS_P3)
+ VG_(printf)("Phase3: %5d+%d ", i, (Int)sym->n_numaux);
+
+ name =3D mk_const_Name("(unknown)");
+ if (sym->n_scnum =3D=3D N_DEBUG && sym->n_sclass =3D=3D C_FUN)
+ name =3D maybeDerefStrTab( sym, oi_debug, oi_n_debug );
+ else=20
+ if (sym->n_sclass & DBXMASK)
+ name =3D mk_const_Name("(dbxstr)");
+ else
+ name =3D maybeDerefStrTab( sym, oi_strtab, oi_n_strtab);
+
+ if (0 && SHOW && SHOW_SYMS_P3) {
+ VG_(printf)("%5s(%2d) %6s 0x%016llx ",=20
+ is_text ? "text" : is_data ? "data" : "other",
+ (Int)sym->n_scnum,=20
+ name_of_syment_n_sclass(sym->n_sclass),=20
+ (ULong)sym->n_value);
+ print_Name(name);
+ VG_(printf)("\n");
+ }
+
+ i++;
+ i +=3D sym->n_numaux;
+
+ /* --- BEGIN C_FILE [source file] --- */
+ /* There are two variants of C_FILE: a simple one with n_numaux
+ =3D=3D 0, where the primary name is what we're after, and anoth=
er
+ variant with n_numaux =3D=3D 3, in which we have to hunt around
+ in the auxiliary entries to find the file name. gcc produces
+ exclusively the first kind, and xlc a mixture of both. */
+ if (sym->n_sclass =3D=3D C_FILE && sym->n_numaux =3D=3D 0) {
+ if (!is_empty_Name(name))
+ FNAME_SET_TOP(name);
+ if (SHOW && SHOW_SYMS_P3) {
+ VG_(printf)("Phase3: %5d+%d FILE ",
+ i-1-sym->n_numaux, (Int)sym->n_numaux );
+ print_Name(name);
+ VG_(printf)("\n");
+ }
+ continue;
+ }
+ if (sym->n_sclass =3D=3D C_FILE && sym->n_numaux > 1=20
+ && sym->n_numaux <=3D 5 /*stay sane*/)=
{
+ for (k =3D 0; k < sym->n_numaux; k++) {
+ aux =3D SYM_IX(oi_symtab, i - sym->n_numaux + k);
+ Name fname
+ =3D maybeDerefStrTab_fname(=20
+ (UChar*)&((AUXENT*)aux)->x_file.x_fname,
+ oi_strtab, oi_n_strtab);
+ if (((AUXENT*)aux)->x_file._x.x_ftype =3D=3D XFT_FN) {
+ if (!is_empty_Name(fname))
+ FNAME_SET_TOP(fname);
+ if (SHOW && SHOW_SYMS_P3) {
+ VG_(printf)("Phase3: %5d+%d FILE ",
+ i-1-sym->n_numaux, (Int)sym->n_numaux );
+ print_Name(fname);
+ VG_(printf)("\n");
+ }
+ break;
+ }
+ }
+ continue;
+ }
+ /* --- END C_FILE [source file] --- */
+
+ /* --- BEGIN C_BINCL [beginning of include] --- */
+ if (sym->n_sclass =3D=3D C_BINCL && sym->n_numaux =3D=3D 0) {
+ FNAME_PUSH(name);
+ if (SHOW && SHOW_SYMS_P3)
+ VG_(printf)("Phase3: %5d+%d BINCL %s\n",
+ i-1-sym->n_numaux, (Int)sym->n_numaux,=20
+ name );
+ continue;
+ }
+ /* --- END C_BINCL [beginning of include] --- */
+
+ /* --- BEGIN C_EINCL [end of include] --- */
+ if (sym->n_sclass =3D=3D C_EINCL && sym->n_numaux =3D=3D 0) {
+ FNAME_POP;
+ if (SHOW && SHOW_SYMS_P3)
+ VG_(printf)("Phase3: %5d+%d EINCL %s\n",
+ i-1-sym->n_numaux, (Int)sym->n_numaux,=20
+ name );
+ continue;
+ }
+ /* --- END C_EINCL [end of include] --- */
+
+ /* everything else that is interesting is in the text
+ section. */
+ if (!is_text)
+ continue;
+=20
+ /* --- BEGIN C_FCN(.bf) [function begin mark] --- */
+ if (sym->n_sclass =3D=3D C_FCN=20
+ && sym->n_numaux =3D=3D 1=20
+ && eq_string_Name(name, ".bf")) {
+ /* aux is BLOCK */
+ aux =3D SYM_IX(oi_symtab, i-1);
+ Addr fn_start_avma =3D ((Addr)sym->n_value) + text_bias;
+ Int fn_start_lnno =3D ((AUXENT*)aux)->x_sym.x_misc.x_lnsz.x_ln=
no;
+ /* Look in 'syms' to see if we have anything for address
+ fn_avma. */
+ XCoffSym key;
+ VG_(memset)(&key, 0, sizeof(key));
+ key.first =3D fn_start_avma;
+ key.last =3D fn_start_avma;
+ Word ix_lo, ix_hi;
+
+ /* Search for all symbols intersecting fn_start_avma. */
+ Bool found =3D lookupXA(syms, &key, &ix_lo, &ix_hi);
+ if (found) {
+ /* All the 'syms' entries from ix_lo to ix_hi match. */
+
+ for (k =3D ix_lo; k <=3D ix_hi; k++) {
+ XCoffSym* tsym =3D (XCoffSym*)indexXA(syms,k);
+
+ /* note the start line number */
+ if (tsym->slnno =3D=3D 0 && fn_start_lnno > 0)
+ tsym->slnno =3D fn_start_lnno;
+
+ /* also the current filename, if we know it */
+ if (is_empty_Name(tsym->fname)=20
+ && !is_empty_Name(FNAME_GET_TOP))=20
+ tsym->fname =3D FNAME_GET_TOP;
+
+ /* remember the first in the range as the new current
+ (I've never seen a range with > 1) */
+ if (k =3D=3D ix_lo)
+ p3currsym =3D tsym;
+ if (SHOW && SHOW_SYMS_P3) {
+ VG_(printf)("Phase3: %5d+%d FCN(.bf) 0x%016llx "
+ "lnno=3D%-4d ",=20
+ i-1-sym->n_numaux, (Int)sym->n_numaux,=20
+ (ULong)sym->n_value,
+ fn_start_lnno );
+ print_Name(tsym->name);
+ VG_(printf)("\n");
+ if (!is_empty_Name(tsym->fname)) {
+ VG_(printf)("Phase3: ");
+ print_Name(tsym->fname);
+ VG_(printf)("\n");
+ }
+ }
+ }
+ }
+ continue;
+ }
+ /* --- END C_FCN(.bf) [function begin mark] --- */
+
+ /* --- BEGIN C_FCN(.ef) [function end mark] --- */
+ if (sym->n_sclass =3D=3D C_FCN=20
+ && sym->n_numaux =3D=3D 1=20
+ && eq_string_Name(name, ".ef")) {
+ /* aux is BLOCK */
+ aux =3D SYM_IX(oi_symtab, i-1);
+ /* In this case the n_value field appears to give the address
+ of the first insn following the end of the function.
+ Hence the - 1. */
+ Addr fn_end_avma =3D ((Addr)sym->n_value) + text_bias - 1;
+ Int fn_end_lnno =3D ((AUXENT*)aux)->x_sym.x_misc.x_lnsz.x_lnno=
;
+
+ if (p3currsym
+ && fn_end_avma >=3D p3currsym->first
+ && fn_end_avma <=3D p3currsym->last) {
+ if (p3currsym->elnno =3D=3D 0 && fn_end_lnno > 0)
+ p3currsym->elnno =3D fn_end_lnno;
+ if (SHOW && SHOW_SYMS_P3) {
+ VG_(printf)("Phase3: %5d+%d FCN(.ef) 0x%016llx "
+ "lnno=3D%-4d ",=20
+ i-1-sym->n_numaux, (Int)sym->n_numaux,=20
+ (ULong)sym->n_value,
+ fn_end_lnno );
+ print_Name(p3currsym->name);
+ VG_(printf)("\n");
+ }
+ if (fn_end_avma < p3currsym->last) {
+ /* also take the opportunity to trim the symbol's
+ length to something less than established by the
+ initial estimation done by Phases 1 and 2. */
+ if (0) VG_(printf)("trim end from %p to %p\n",=20
+ p3currsym->last, fn_end_avma);
+ p3currsym->last =3D fn_end_avma;
+ }
+ }
+ continue;
+ }
+ /* --- END C_FCN(.ef) [function end mark] --- */
+
+ }
+
+ /* ----------------------------------------------------------
+ Phase 4: read and enumerate the line number entries, if=20
+ there are any. This depends on knowing the function start/end
+ line numbers established in Phase 3.
+ ---------------------------------------------------------- */
+
+ if (SHOW && SHOW_SYMS_P4) {
+ VG_(printf)("--- BEGIN Phase4 (read line number info) ---\n");
+ VG_(printf)("--- note: shown addresses are ACTUAL VMAs ---\n");
+ }
+
+ /* Re-sort 'syms' using the compare-start-addresses ordering, so we
+ can use that in subsequent searches. */
+ setCmpFnXA(syms, cmp_XCoffSym_by_start);
+ sortXA(syms);
+
+ if (oi_lnos && oi_nent_lnos > 0) {
+
+# if defined(VGP_ppc32_aix5)
+ vg_assert(LINESZ =3D=3D 6); /* XCOFF32 */
+# elif defined(VGP_ppc64_aix5)
+ vg_assert(LINESZ =3D=3D 12); /* XCOFF64 */
+# else
+# error "Unknown plat"
+# endif
+
+# define LNO_IX(_tab,_n) \
+ ((LINENO*)(((UChar*)(_tab)) + LINESZ * (_n)))
+
+ /* Current fn that we are processing line numbers for */
+ XCoffSym* p4currsym =3D NULL;
+
+ /* SegInfo's string table pointer for p4currsym's file name.
+ Allocated on demand, so as not to waste space in the
+ SegInfo's string table. */
+ UChar* si_fname_str =3D NULL;
+
+ /* Ditto the directory name, if we can manage it. */
+ UChar* si_dname_str =3D NULL;
+
+ for (i =3D 0; i < oi_nent_lnos; i++) {
+ LINENO* lno =3D LNO_IX(oi_lnos,i);
+
+ if (lno->l_lnno =3D=3D 0) {
+ /* New fn. We get given the index in the symbol table of
+ the relevant function. It should be a C_EXT, C_WEAKEXT
+ or C_HIDEXT flavour, according to the IBM docs. */
+ Int sym_ix =3D (Int)lno->l_addr.l_symndx;
+ sym =3D SYM_IX(oi_symtab, sym_ix);
+ if (!(sym->n_sclass =3D=3D C_EXT=20
+ || sym->n_sclass =3D=3D C_WEAKEXT=20
+ || sym->n_sclass =3D=3D C_HIDEXT))
+ return "readxcoff.c: invalid symbol reference"
+ " in line number info";
+ /* For these 3 symbol kinds, the n_value field is the
+ symbol's stated VMA. Convert this to an actual VMA and
+ use that to find the associated XCoffSym. */
+ Addr sym_avma =3D ((Addr)sym->n_value) + text_bias;
+
+ XCoffSym key;
+ VG_(memset)(&key, 0, sizeof(key));
+ key.first =3D sym_avma;
+ Word ix_lo, ix_hi;
+
+ Bool found =3D lookupXA(syms, &key, &ix_lo, &ix_hi);
+ if (found) {
+ /* All the 'syms' entries from ix_lo to ix_hi match.
+ Just use the lowest (sigh ..) */
+ p4currsym =3D (XCoffSym*)indexXA(syms, ix_lo);
+ } else {
+ /* We can't find the relevant sym, but we still have to
+ wade through the line number info for this function
+ until we get to the starting record for the next
+ one. */
+ p4currsym =3D NULL;
+ }
+
+ /* If we decide to add any line info for this fn to the
+ SegInfo, we'll allocate this. Otherwise don't
+ bother. */
+ si_fname_str =3D NULL;
+ si_dname_str =3D NULL;
+
+ if (SHOW && SHOW_SYMS_P4) {
+ VG_(printf)("Phase4: new fn (%d found), avma 0x%016llx "=
,=20
+ (Int)(ix_hi-ix_lo+1),
+ (ULong)sym_avma );
+ if (p4currsym)
+ print_Name(p4currsym->name);
+ else
+ VG_(printf)("UNKNOWN");
+ VG_(printf)("\n");
+ }
+
+ } else {
+ /* Line number entry for the current fn. */
+ if (!p4currsym)
+ continue;
+ Int line_no =3D (Int)(UInt)lno->l_lnno;
+ line_no +=3D (p4currsym->slnno - 1);
+ Addr line_first_avma =3D ((Addr)lno->l_addr.l_paddr) + text_=
bias;
+ if (line_first_avma < p4currsym->first
+ || line_first_avma > p4currsym->last)
+ continue;
+ Addr line_last_avma =3D p4currsym->last;
+ /* Try to refine the last_avma by looking at the next
+ line's entry. */
+
+ /* XXX: TODO. What we have currently works only because
+ the generic line number canonicaliser truncates
+ overlapping address ranges in the way which we happen
+ to need anyway. */
+ if (SHOW && SHOW_SYMS_P4)
+ VG_(printf)("Phase4: line %d 0x%016llx - 0x%016llx\n",=20
+ line_no, (ULong)line_first_avma,=20
+ (ULong)line_last_avma);
+
+ /* This now has to be allocated. Try and figure out the
+ dir name at the same time. This is a bit ugly in that
+ it involves messing with the string after it's been
+ copied into the SegInfo's string table, but seems
+ harmless enough. */
+ if ((!si_fname_str) && !is_empty_Name(p4currsym->fname)) {
+ si_dname_str =3D NULL;
+ si_fname_str =3D ML_(addStr)(si, p4currsym->fname.vec,
+ p4currsym->fname.len);
+ UChar* lastslash =3D VG_(strrchr)(si_fname_str, '/');
+ if (lastslash)
+ vg_assert(lastslash[0] =3D=3D '/');
+ if (lastslash[1] !=3D 0) {
+ si_dname_str =3D si_fname_str;
+ lastslash[0] =3D 0; /* replace the / with a NUL
+ terminator */
+ si_fname_str =3D lastslash+1;
+ if (0) VG_(printf)("XXX %s %s\n", si_dname_str,=20
+ si_fname_str);
+ }
+ }
+ /* finally .. */
+ if (line_no >=3D 0)
+ ML_(addLineInfo)(si, si_fname_str, si_dname_str,
+ line_first_avma, line_last_avma+1,
+ line_no, i/*debugging only*/);
+ }
+ }
+
+# undef LNO_IX
+ }
+
+#if defined(OFFICIAL_PHASE5)
+ /* ----------------------------------------------------------
+ Phase 5: Do another trawl of the XCOFF symbol table, looking
+ for TOC entries for the entries we've already placed in 'syms'.
+ ---------------------------------------------------------- */
+
+ if (SHOW && SHOW_SYMS_P5)
+ VG_(printf)("--- BEGIN official Phase5 (find TOC pointers) ---\n")=
;
+
+ Bool is_cfun;
+
+ i =3D 0;
+ while (1) {
+
+ if (i >=3D oi_nent_symtab)
+ break;
+
+ sym =3D SYM_IX(oi_symtab, i);
+ is_text =3D sntext_1based_if_known !=3D -1
+ && (Int)sym->n_scnum =3D=3D sntext_1based_if_known;
+ is_data =3D sndata_1based_if_known !=3D -1
+ && (Int)sym->n_scnum =3D=3D sndata_1based_if_known;
+ is_cfun =3D sym->n_scnum =3D=3D N_DEBUG=20
+ && sym->n_sclass =3D=3D C_FUN;
+
+ i++;
+ i +=3D sym->n_numaux;
+
+ if (!is_cfun && !is_data)
+ continue;
+
+ if (SHOW && SHOW_SYMS_P5)
+ VG_(printf)("Phase5o: %5d+%d ", i-1-sym->n_numaux,=20
+ (Int)sym->n_numaux);
+
+ name =3D mk_const_Name("(unknown)");
+ if (is_cfun)
+ name =3D maybeDerefStrTab( sym, oi_debug, oi_n_debug );
+ else=20
+ if (sym->n_sclass & DBXMASK)
+ name =3D mk_const_Name("(dbxstr)");
+ else
+ name =3D maybeDerefStrTab( sym, oi_strtab, oi_n_strtab);
+
+ if (SHOW && SHOW_SYMS_P5) {
+ VG_(printf)("%5s(%2d) %6s svma 0x%016llx ",=20
+ is_text ? "text" : is_data ? "data" : "other",
+ (Int)sym->n_scnum,=20
+ name_of_syment_n_sclass(sym->n_sclass),=20
+ (ULong)sym->n_value);
+ print_Name(name);
+ VG_(printf)("\n");
+ }
+
+ Addr avma =3D (Addr)sym->n_value + data_bias;
+ if (0) VG_(printf)("data sym: avma %p, limits %p-%p\n",=20
+ avma, data_avma,data_avma + data_alen);
+
+ /* Does avma point to 3 valid words inside the actual data
+ segment? iow, can it possibly be a valid function
+ descriptor? If not, move on. */
+ if (! (avma >=3D data_avma=20
+ && avma + 3 * sizeof(Word) <=3D data_avma + data_alen) )
+ continue;
+
+ UWord* fndescr =3D (UWord*)avma;
+
+ if (SHOW && SHOW_SYMS_P5)=20
+ VG_(printf)(" fndescr =3D {0x%lx,0x%lx}\n",=20
+ fndescr[0], fndescr[1]);
+
+ /* Another check: fndescr[0], the entry point, must point inside
+ the actual text segment. Discard any that don't. */
+
+ Addr fndescr_0 =3D (Addr)fndescr[0];
+ if (fndescr_0 < si->start || fndescr_0 >=3D si->start+si->size)
+ continue;
+
+ /* Let's suppose that fndescr is the descriptor for a
+ function with name NAME. If that's so, then 'syms'
+ acquired by stage 2 should have an entry of name '.NAME'
+ whose address is fndescr[0]. If so, then fndescr[1] must
+ be the relevant r2 value for it. */
+ /* Look in 'syms' to see if we have anything for address
+ fndescr[0]. */
+ XCoffSym key;
+ VG_(memset)(&key, 0, sizeof(key));
+ key.first =3D fndescr_0;
+ Word ix_lo, ix_hi;
+ Bool found =3D lookupXA(syms, &key, &ix_lo, &ix_hi);
+ if (found) {
+ /* So all the 'syms' entries from ix_lo to ix_hi have an
+ address which matches the entry point address stated in
+ this descriptor. For each one, as a final sanity
+ check, see if the 'syms' entry has a name .NAME where
+ NAME is that of the data symbol currently under
+ consideration. If so, it's a pretty good bet that this
+ descriptor matches the text symbol we already have, and
+ so we have a valid tocptr value from fndescr[1]. */
+ for (k =3D ix_lo; k <=3D ix_hi; k++) {
+ XCoffSym* tsym =3D (XCoffSym*)indexXA(syms,k);
+ vg_assert(!is_empty_Name(tsym->name));
+ /* VG_(printf)("cmp %s %s\n", name, tsym->name); */
+ /* VG_(printf)("found matching %d %s\n", k, tsym->name); */
+ if (tsym->name.len =3D=3D 1 + name.len
+ && tsym->name.vec[0] =3D=3D '.'
+ && 0 =3D=3D VG_(memcmp)(&tsym->name.vec[1],
+ &name.vec[0], name.len)) {
+ Addr r2val =3D fndescr[1];
+ if (tsym->r2known) {
+ if (tsym->r2value !=3D r2val)
+ /* COMPLAIN - conflicting r2 values*/ ;
+ } else {
+ tsym->r2known =3D True;
+ tsym->r2value =3D r2val;
+ }
+ }
+ }
+ }
+
+ }
+
+#else /* !defined(OFFICIAL_PHASE5) */
+ /* ----------------------------------------------------------
+ Alternative kludgey Phase 5: find TOC entries for 'syms' by the
+ blunt-instrument approach of scanning the actual data section
+ and noting anything that looks like a function descriptor.
+ This is dangerous in the sense that if there are any 3 word
+ structs which are not real function descriptors but just happen
+ to look like them, then those will be included too. =20
+ Seems unlikely though.
+ ---------------------------------------------------------- */
+
+ if (SHOW && SHOW_SYMS_P5)
+ VG_(printf)("--- BEGIN kludged Phase5 (find TOC pointers) ---\n");
+
+ if (SHOW)
+ VG_(printf)("Phase5: actual data segment: %p %p\n",
+ data_avma, data_avma + data_alen);
+
+ /* Skip obviously-missing data sections. */
+ if (data_avma !=3D 0 && data_alen >=3D sizeof(UWord)) {
+
+ /* set up for inspecting all the aligned words in the actual
+ data section. */
+
+ Addr tmp =3D (Addr)data_avma;
+ while (tmp & (sizeof(UWord)-1))
+ tmp++;
+
+ UWord* first_data_word =3D (UWord*)tmp;
+ tmp =3D data_avma + data_alen - sizeof(UWord);
+ while (tmp & (sizeof(UWord)-1))
+ tmp--;
+ UWord* last_data_word =3D (UWord*)tmp;
+
+ if (SHOW)=20
+ VG_(printf)("Phase5: data segment conservatively aligned %p %p\=
n",=20
+ first_data_word, last_data_word);
+
+ UWord* wP =3D first_data_...
[truncated message content] |
|
From: <sv...@va...> - 2006-10-17 01:06:50
|
Author: sewardj
Date: 2006-10-17 02:06:44 +0100 (Tue, 17 Oct 2006)
New Revision: 6248
Log:
Merge r6099:
Dispatchers for AIX5.
Added:
trunk/coregrind/m_dispatch/dispatch-ppc32-aix5.S
trunk/coregrind/m_dispatch/dispatch-ppc64-aix5.S
Added: trunk/coregrind/m_dispatch/dispatch-ppc32-aix5.S
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_dispatch/dispatch-ppc32-aix5.S =
(rev 0)
+++ trunk/coregrind/m_dispatch/dispatch-ppc32-aix5.S 2006-10-17 01:06:44 =
UTC (rev 6248)
@@ -0,0 +1,682 @@
+
+/*--------------------------------------------------------------------*/
+/*--- The core dispatch loop, for jumping to a code address. ---*/
+/*--- dispatch-ppc32-aix5.S ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics_asm.h"
+#include "pub_core_dispatch_asm.h"
+#include "pub_core_transtab_asm.h"
+#include "libvex_guest_offsets.h" /* for OFFSET_ppc32_CIA */
+
+
+/*------------------------------------------------------------*/
+/*--- ---*/
+/*--- The dispatch loop. VG_(run_innerloop) is used to ---*/
+/*--- run all translations except no-redir ones. ---*/
+/*--- ---*/
+/*------------------------------------------------------------*/
+
+/*----------------------------------------------------*/
+/*--- Incomprehensible TOC mumbo-jumbo nonsense. ---*/
+/*----------------------------------------------------*/
+
+/* No, I don't have a clue either. I just compiled a bit of
+ C with gcc and copied the assembly code it produced. */
+
+/* Basically "lwz rd, tocent__foo(2)" gets &foo into rd. */
+
+ .file "dispatch-ppc32-aix5.S"
+ .machine "any"
+ .toc
+ .csect .text[PR]
+ .toc
+tocent__vgPlain_dispatch_ctr:
+ .tc vgPlain_dispatch_ctr[TC],vgPlain_dispatch_ctr[RW]
+tocent__vgPlain_machine_ppc32_has_VMX:
+ .tc vgPlain_machine_ppc32_has_VMX[TC],vgPlain_machine_ppc32_has_VMX[=
RW]
+tocent__vgPlain_machine_ppc32_has_FP:
+ .tc vgPlain_machine_ppc32_has_FP[TC],vgPlain_machine_ppc32_has_FP[RW=
]
+tocent__vgPlain_tt_fast:
+ .tc vgPlain_tt_fast[TC],vgPlain_tt_fast[RW]
+tocent__vgPlain_tt_fastN:
+ .tc vgPlain_tt_fast[TC],vgPlain_tt_fastN[RW]
+ .csect .text[PR]
+ .align 2
+ .globl vgPlain_run_innerloop
+ .globl .vgPlain_run_innerloop
+ .csect vgPlain_run_innerloop[DS]
+vgPlain_run_innerloop:
+ .long .vgPlain_run_innerloop, TOC[tc0], 0
+ .csect .text[PR]
+
+/*----------------------------------------------------*/
+/*--- Preamble (set everything up) ---*/
+/*----------------------------------------------------*/
+
+/* signature:
+UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
+*/
+.vgPlain_run_innerloop:
+ /* r3 holds guest_state */
+ /* r4 holds do_profiling */
+ /* Rather than attempt to make sense of the AIX ABI, just
+ drop r1 by 256 (to get away from the caller's frame), then
+ 512 (to give ourselves a 512-byte save area), and then
+ another 256 (to clear our save area). In all, drop r1 by 1024
+ and dump stuff on the stack at 256(1)..768(1). */
+
+ /* ----- entry point to VG_(run_innerloop) ----- */
+ /* For AIX/ppc32 we do: LR-> +8(parent_sp), CR-> +4(parent_sp) =
*/
+
+ /* Save lr and cr*/
+ mflr 0
+ stw 0,8(1)
+ mfcr 0
+ stw 0,4(1)
+
+ /* New stack frame */
+ stwu 1,-1024(1) /* sp should maintain 16-byte alignment */
+
+ /* Save callee-saved registers... */
+ /* r3, r4 are live here, so use r5 */
+ lwz 5,tocent__vgPlain_machine_ppc32_has_FP(2)
+ lwz 5,0(5)
+ cmplwi 5,0
+ beq LafterFP1
+
+ /* Floating-point reg save area : 144 bytes at r1[256..399] */
+ stfd 31,392(1)
+ stfd 30,384(1)
+ stfd 29,376(1)
+ stfd 28,368(1)
+ stfd 27,360(1)
+ stfd 26,352(1)
+ stfd 25,344(1)
+ stfd 24,336(1)
+ stfd 23,328(1)
+ stfd 22,320(1)
+ stfd 21,312(1)
+ stfd 20,304(1)
+ stfd 19,296(1)
+ stfd 18,288(1)
+ stfd 17,280(1)
+ stfd 16,272(1)
+ stfd 15,264(1)
+ stfd 14,256(1)
+LafterFP1:
+
+ /* General reg save area : 76 bytes at r1[400 .. 475] */
+ stw 31,472(1)
+ stw 30,468(1)
+ stw 29,464(1)
+ stw 28,460(1)
+ stw 27,456(1)
+ stw 26,452(1)
+ stw 25,448(1)
+ stw 24,444(1)
+ stw 23,440(1)
+ stw 22,436(1)
+ stw 21,432(1)
+ stw 20,428(1)
+ stw 19,424(1)
+ stw 18,420(1)
+ stw 17,416(1)
+ stw 16,412(1)
+ stw 15,408(1)
+ stw 14,404(1)
+ /* Probably not necessary to save r13 (thread-specific ptr),
+ as VEX stays clear of it... but what the hell. */
+ stw 13,400(1)
+
+ /* It's necessary to save/restore VRSAVE in the AIX / Darwin ABI=
.
+ The Linux kernel might not actually use VRSAVE for its intend=
ed
+ purpose, but it should be harmless to preserve anyway. */
+ /* r3, r4 are live here, so use r5 */
+ lwz 5,tocent__vgPlain_machine_ppc32_has_VMX(2)
+ lwz 5,0(5)
+ cmplwi 5,0
+ beq LafterVMX1
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// /* VRSAVE save word : 4 bytes at r1[476 .. 479] */
+// mfspr 5,256 /* vrsave reg is spr number 256 */
+// stw 5,476(1)
+//
+// /* Vector reg save area (quadword aligned):=20
+// 192 bytes at r1[480 .. 671] */
+// li 5,656
+// stvx 31,5,1
+// li 5,640
+// stvx 30,5,1
+// li 5,624
+// stvx 29,5,1
+// li 5,608
+// stvx 28,5,1
+// li 5,592
+// stvx 27,5,1
+// li 5,576
+// stvx 26,5,1
+// li 5,560
+// stvx 25,5,1
+// li 5,544
+// stvx 25,5,1
+// li 5,528
+// stvx 23,5,1
+// li 5,512
+// stvx 22,5,1
+// li 5,496
+// stvx 21,5,1
+// li 5,480
+// stvx 20,5,1
+LafterVMX1:
+
+ /* Local variable space... */
+ /* Put the original guest state pointer at r1[128]. We
+ will need to refer to it each time round the dispatch loop.
+ Apart from that, we can use r1[0 .. 128] and r1[132 .. 255]
+ as scratch space. */
+
+ /* r3 holds guest_state */
+ /* r4 holds do_profiling */
+ mr 31,3 /* r31 (generated code gsp) =3D r3 */
+ stw 3,128(1) /* stash orig guest_state ptr */
+
+ /* hold dispatch_ctr in r29 */
+ lwz 5,tocent__vgPlain_dispatch_ctr(2)
+ lwz 29,0(5)
+
+ /* set host FPU control word to the default mode expected=20
+ by VEX-generated code. See comments in libvex.h for
+ more info. */
+ lwz 5,tocent__vgPlain_machine_ppc32_has_FP(2)
+ lwz 5,0(5)
+ cmplwi 5,0
+ beq LafterFP2
+
+ /* get zero into f3 (tedious) */
+ /* note: fsub 3,3,3 is not a reliable way to do this,=20
+ since if f3 holds a NaN or similar then we don't necessarily
+ wind up with zero. */
+ li 5,0
+ stw 5,64(1) /* r1[64] is scratch */
+ lfs 3,64(1)
+ mtfsf 0xFF,3 /* fpscr =3D f3 */
+LafterFP2:
+
+ /* set host AltiVec control word to the default mode expected=20
+ by VEX-generated code. */
+ lwz 5,tocent__vgPlain_machine_ppc32_has_VMX(2)
+ lwz 5,0(5)
+ cmplwi 5,0
+ beq LafterVMX2
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// vspltisw 3,0x0 /* generate zero */
+// mtvscr 3
+LafterVMX2:
+
+ /* fetch %CIA into r3 */
+ lwz 3,OFFSET_ppc32_CIA(31)
+
+ /* fall into main loop (the right one) */
+ /* r4 =3D do_profiling. It's probably trashed after here,
+ but that's OK: we don't need it after here. */
+ cmplwi 4,0
+ beq VG_(run_innerloop__dispatch_unprofiled)
+ b VG_(run_innerloop__dispatch_profiled)
+ /*NOTREACHED*/
+
+/*----------------------------------------------------*/
+/*--- NO-PROFILING (standard) dispatcher ---*/
+/*----------------------------------------------------*/
+
+.globl VG_(run_innerloop__dispatch_unprofiled)
+VG_(run_innerloop__dispatch_unprofiled):
+ /* At entry: Live regs:
+ r1 (=3Dsp)
+ r3 (=3DCIA =3D next guest address)
+ r29 (=3Ddispatch_ctr)
+ r31 (=3Dguest_state)
+ Stack state:
+ 128(r1) (=3Dorig guest_state)
+ */
+
+ /* Has the guest state pointer been messed with? If yes, exit. */
+ lwz 5,128(1) /* original guest_state ptr */
+ cmpw 5,31
+ bne gsp_changed
+
+ /* save the jump address in the guest state */
+ stw 3,OFFSET_ppc32_CIA(31)
+
+ /* Are we out of timeslice? If yes, defer to scheduler. */
+ addi 29,29,-1
+ cmplwi 29,0
+ beq counter_is_zero
+
+ /* try a fast lookup in the translation cache */
+ /* r4 =3D VG_TT_FAST_HASH(addr) * sizeof(ULong*)
+ =3D ((r3 >>u 2) & VG_TT_FAST_MASK) << 2 */
+ rlwinm 4,3, 0, 32-2-VG_TT_FAST_BITS, 31-2
+
+ lwz 5,tocent__vgPlain_tt_fast(2) /* r5 =3D &tt_fast */
+
+ lwzx 5,5,4 /* r5 =3D tt_fast[r5] */
+
+ lwz 6,4(5) /* big-endian, so comparing 2nd 32bit word */
+ cmpw 3,6
+ bne fast_lookup_failed
+
+ /* Found a match. Call tce[1], which is 8 bytes along, since
+ each tce element is a 64-bit int. */
+ addi 8,5,8
+ mtctr 8
+
+ /* run the translation */
+ bctrl
+
+ /* On return from guest code:
+ r3 holds destination (original) address.
+ r31 may be unchanged (guest_state), or may indicate further
+ details of the control transfer requested to *r3.
+ */
+
+ /* start over */
+ b VG_(run_innerloop__dispatch_unprofiled)
+ /*NOTREACHED*/
+
+/*----------------------------------------------------*/
+/*--- PROFILING dispatcher (can be much slower) ---*/
+/*----------------------------------------------------*/
+
+.globl VG_(run_innerloop__dispatch_profiled)
+VG_(run_innerloop__dispatch_profiled):
+ /* At entry: Live regs:
+ r1 (=3Dsp)
+ r3 (=3DCIA =3D next guest address)
+ r29 (=3Ddispatch_ctr)
+ r31 (=3Dguest_state)
+ Stack state:
+ 128(r1) (=3Dorig guest_state)
+ */
+
+ /* Has the guest state pointer been messed with? If yes, exit. */
+ lwz 5,128(1) /* original guest_state ptr */
+ cmpw 5,31
+ bne gsp_changed
+
+ /* save the jump address in the guest state */
+ stw 3,OFFSET_ppc32_CIA(31)
+
+ /* Are we out of timeslice? If yes, defer to scheduler. */
+ addi 29,29,-1
+ cmplwi 29,0
+ beq counter_is_zero
+
+ /* try a fast lookup in the translation cache */
+ /* r4 =3D VG_TT_FAST_HASH(addr) * sizeof(ULong*)
+ =3D ((r3 >>u 2) & VG_TT_FAST_MASK) << 2 */
+ rlwinm 4,3, 0, 32-2-VG_TT_FAST_BITS, 31-2
+
+ lwz 5,tocent__vgPlain_tt_fast(2) /* r5 =3D &tt_fast */
+
+ lwzx 5,5,4 /* r5 =3D tt_fast[r4] */
+
+ lwz 6,4(5) /* big-endian, so comparing 2nd 32bit word */
+ cmpw 3,6
+ bne fast_lookup_failed
+
+ /* increment bb profile counter */
+ lwz 9,tocent__vgPlain_tt_fastN(2) /* r9 =3D &tt_fastN */
+ lwzx 7,9,4 /* r7 =3D tt_fastN[r4] */
+ lwz 10,0(7)
+ addi 10,10,1
+ stw 10,0(7)
+=09
+ /* Found a match. Call tce[1], which is 8 bytes along, since
+ each tce element is a 64-bit int. */
+ addi 8,5,8
+ mtctr 8
+
+ /* run the translation */
+ bctrl
+
+ /* On return from guest code:
+ r3 holds destination (original) address.
+ r31 may be unchanged (guest_state), or may indicate further
+ details of the control transfer requested to *r3.
+ */
+
+ /* start over */
+ b VG_(run_innerloop__dispatch_profiled)
+ /*NOTREACHED*/
+
+/*----------------------------------------------------*/
+/*--- exit points ---*/
+/*----------------------------------------------------*/
+
+gsp_changed:
+ /* Someone messed with the gsp (in r31). Have to
+ defer to scheduler to resolve this. dispatch ctr
+ is not yet decremented, so no need to increment. */
+ /* %CIA is NOT up to date here. First, need to write
+ %r3 back to %CIA, but without trashing %r31 since
+ that holds the value we want to return to the scheduler.
+ Hence use %r5 transiently for the guest state pointer. */
+ lwz 5,128(1) /* original guest_state ptr */
+ stw 3,OFFSET_ppc32_CIA(5)
+ mr 3,31 /* r3 =3D new gsp value */
+ b run_innerloop_exit
+ /*NOTREACHED*/
+
+counter_is_zero:
+ /* %CIA is up to date */
+ /* back out decrement of the dispatch counter */
+ addi 29,29,1
+ li 3,VG_TRC_INNER_COUNTERZERO
+ b run_innerloop_exit
+
+fast_lookup_failed:
+ /* %CIA is up to date */
+ /* back out decrement of the dispatch counter */
+ addi 29,29,1
+ li 3,VG_TRC_INNER_FASTMISS
+ b run_innerloop_exit
+
+
+
+/* All exits from the dispatcher go through here.
+ r3 holds the return value.=20
+*/
+run_innerloop_exit:=20
+ /* We're leaving. Check that nobody messed with
+ VSCR or FPSCR. */
+
+ /* Using r10 - value used again further on, so don't trash! */
+ lwz 10,tocent__vgPlain_machine_ppc32_has_FP(2)
+ lwz 10,0(10)
+ cmplwi 10,0
+ beq LafterFP8
+
+ /* Set fpscr back to a known state, since vex-generated code
+ may have messed with fpscr[rm]. */
+ li 5,0
+ stw 5,64(1) /* r1[64] is scratch */
+ lfs 3,64(1)
+ mtfsf 0xFF,3 /* fpscr =3D f3 */
+LafterFP8:
+
+ /* Using r11 - value used again further on, so don't trash! */
+ lwz 11,tocent__vgPlain_machine_ppc32_has_VMX(2)
+ lwz 11,0(11)
+ cmplwi 11,0
+ beq LafterVMX8
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// /* Check VSCR[NJ] =3D=3D 1 */
+// /* first generate 4x 0x00010000 */
+// vspltisw 4,0x1 /* 4x 0x00000001 */
+// vspltisw 5,0x0 /* zero */
+// vsldoi 6,4,5,0x2 /* <<2*8 =3D> 4x 0x00010000 =
*/
+// /* retrieve VSCR and mask wanted bits */
+// mfvscr 7
+// vand 7,7,6 /* gives NJ flag */
+// vspltw 7,7,0x3 /* flags-word to all lanes *=
/
+// vcmpequw. 8,6,7 /* CR[24] =3D 1 if v6 =3D=3D=
v7 */
+// bt 24,invariant_violation /* branch if all_equal */
+LafterVMX8:
+
+ /* otherwise we're OK */
+ b run_innerloop_exit_REALLY
+
+
+invariant_violation:
+ li 3,VG_TRC_INVARIANT_FAILED
+ b run_innerloop_exit_REALLY
+
+run_innerloop_exit_REALLY:
+ /* r3 holds VG_TRC_* value to return */
+
+ /* Write ctr to VG(dispatch_ctr) */
+ lwz 5,tocent__vgPlain_dispatch_ctr(2)
+ stw 29,0(5)
+
+ /* Restore callee-saved registers... */
+
+ /* r10 already holds VG_(machine_ppc32_has_FP) value */
+ cmplwi 10,0
+ beq LafterFP9
+
+ /* Floating-point regs */
+ lfd 31,392(1)
+ lfd 30,384(1)
+ lfd 29,376(1)
+ lfd 28,368(1)
+ lfd 27,360(1)
+ lfd 26,352(1)
+ lfd 25,344(1)
+ lfd 24,336(1)
+ lfd 23,328(1)
+ lfd 22,320(1)
+ lfd 21,312(1)
+ lfd 20,304(1)
+ lfd 19,296(1)
+ lfd 18,288(1)
+ lfd 17,280(1)
+ lfd 16,272(1)
+ lfd 15,264(1)
+ lfd 14,256(1)
+LafterFP9:
+
+ /* General regs */
+ lwz 31,472(1)
+ lwz 30,468(1)
+ lwz 29,464(1)
+ lwz 28,460(1)
+ lwz 27,456(1)
+ lwz 26,452(1)
+ lwz 25,448(1)
+ lwz 24,444(1)
+ lwz 23,440(1)
+ lwz 22,436(1)
+ lwz 21,432(1)
+ lwz 20,428(1)
+ lwz 19,424(1)
+ lwz 18,420(1)
+ lwz 17,416(1)
+ lwz 16,412(1)
+ lwz 15,408(1)
+ lwz 14,404(1)
+ lwz 13,400(1)
+
+ /* r11 already holds VG_(machine_ppc32_has_VMX) value */
+ cmplwi 11,0
+ beq LafterVMX9
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// /* VRSAVE */
+// lwz 4,476(1)
+// mtspr 4,256 /* VRSAVE reg is spr number 256 */
+//
+// /* Vector regs */
+// li 4,656
+// lvx 31,4,1
+// li 4,640
+// lvx 30,4,1
+// li 4,624
+// lvx 29,4,1
+// li 4,608
+// lvx 28,4,1
+// li 4,592
+// lvx 27,4,1
+// li 4,576
+// lvx 26,4,1
+// li 4,560
+// lvx 25,4,1
+// li 4,544
+// lvx 24,4,1
+// li 4,528
+// lvx 23,4,1
+// li 4,512
+// lvx 22,4,1
+// li 4,496
+// lvx 21,4,1
+// li 4,480
+// lvx 20,4,1
+LafterVMX9:
+
+ /* r3 is live here; don't trash it */
+ /* restore lr,cr,sp */
+ addi 4,1,1024 /* r4 =3D old SP */
+ lwz 0,8(4)
+ mtlr 0
+ lwz 0,4(4)
+ mtcr 0
+ mr 1,4
+ blr
+
+LT..vgPlain_run_innerloop:
+ .long 0
+ .byte 0,0,32,64,0,0,2,0
+ .long 0
+ .long LT..vgPlain_run_innerloop-.vgPlain_run_innerloop
+ .short 13
+ .byte "vgPlain_run_innerloop"
+ .align 2
+_section_.text:
+ .csect .data[RW],3
+ .long _section_.text
+
+/*------------------------------------------------------------*/
+/*--- ---*/
+/*--- A special dispatcher, for running no-redir ---*/
+/*--- translations. Just runs the given translation once. ---*/
+/*--- ---*/
+/*------------------------------------------------------------*/
+=09
+/* signature:
+void VG_(run_a_noredir_translation) ( UWord* argblock );
+*/
+
+/* Run a no-redir translation. argblock points to 4 UWords, 2 to carry =
args
+ and 2 to carry results:
+ 0: input: ptr to translation
+ 1: input: ptr to guest state
+ 2: output: next guest PC
+ 3: output: guest state pointer afterwards (=3D=3D thread return co=
de)
+*/
+.csect .text[PR]
+.align 2
+.globl .VG_(run_a_noredir_translation)
+.VG_(run_a_noredir_translation):
+
+ /* Rather than attempt to make sense of the AIX ABI, just
+ drop r1 by 256 (to get away from the caller's frame), then
+ 512 (to give ourselves a 512-byte save area), and then
+ another 256 (to clear our save area). In all, drop r1 by 1024
+ and dump stuff on the stack at 256(1)..768(1). */
+ /* At entry, r3 points to argblock */
+
+ /* ----- entry point to VG_(run_innerloop) ----- */
+ /* For AIX/ppc32 we do: LR-> +8(parent_sp), CR-> +4(parent_sp) =
*/
+
+ /* Save lr and cr*/
+ mflr 0
+ stw 0,8(1)
+ mfcr 0
+ stw 0,4(1)
+
+ /* New stack frame */
+ stwu 1,-1024(1) /* sp should maintain 16-byte alignment */
+
+ /* General reg save area : 76 bytes at r1[400 .. 475] */
+ stw 31,472(1)
+ stw 30,468(1)
+ stw 29,464(1)
+ stw 28,460(1)
+ stw 27,456(1)
+ stw 26,452(1)
+ stw 25,448(1)
+ stw 24,444(1)
+ stw 23,440(1)
+ stw 22,436(1)
+ stw 21,432(1)
+ stw 20,428(1)
+ stw 19,424(1)
+ stw 18,420(1)
+ stw 17,416(1)
+ stw 16,412(1)
+ stw 15,408(1)
+ stw 14,404(1)
+ stw 13,400(1)
+ stw 3,396(1) /* will need it later */
+=09
+ lwz 31,4(3) /* rd argblock[1] */
+ lwz 30,0(3) /* rd argblock[0] */
+ mtlr 30 /* run translation */
+ blrl
+
+ lwz 4,396(1) /* &argblock */
+ stw 3, 8(4) /* wr argblock[2] */
+ stw 31,12(4) /* wr argblock[3] */
+ =09
+ /* General regs */
+ lwz 31,472(1)
+ lwz 30,468(1)
+ lwz 29,464(1)
+ lwz 28,460(1)
+ lwz 27,456(1)
+ lwz 26,452(1)
+ lwz 25,448(1)
+ lwz 24,444(1)
+ lwz 23,440(1)
+ lwz 22,436(1)
+ lwz 21,432(1)
+ lwz 20,428(1)
+ lwz 19,424(1)
+ lwz 18,420(1)
+ lwz 17,416(1)
+ lwz 16,412(1)
+ lwz 15,408(1)
+ lwz 14,404(1)
+ lwz 13,400(1)
+
+ /* restore lr,cr,sp */
+ addi 4,1,1024 /* r4 =3D old SP */
+ lwz 0,8(4)
+ mtlr 0
+ lwz 0,4(4)
+ mtcr 0
+ mr 1,4
+ blr
+
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Added: trunk/coregrind/m_dispatch/dispatch-ppc64-aix5.S
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_dispatch/dispatch-ppc64-aix5.S =
(rev 0)
+++ trunk/coregrind/m_dispatch/dispatch-ppc64-aix5.S 2006-10-17 01:06:44 =
UTC (rev 6248)
@@ -0,0 +1,656 @@
+
+/*--------------------------------------------------------------------*/
+/*--- The core dispatch loop, for jumping to a code address. ---*/
+/*--- dispatch-ppc64-aix5.S ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics_asm.h"
+#include "pub_core_dispatch_asm.h"
+#include "pub_core_transtab_asm.h"
+#include "libvex_guest_offsets.h" /* for OFFSET_ppc64_CIA */
+
+
+/*------------------------------------------------------------*/
+/*--- ---*/
+/*--- The dispatch loop. VG_(run_innerloop) is used to ---*/
+/*--- run all translations except no-redir ones. ---*/
+/*--- ---*/
+/*------------------------------------------------------------*/
+
+/*----------------------------------------------------*/
+/*--- Incomprehensible TOC mumbo-jumbo nonsense. ---*/
+/*----------------------------------------------------*/
+
+/* No, I don't have a clue either. I just compiled a bit of
+ C with gcc and copied the assembly code it produced. */
+
+/* Basically "ld rd, tocent__foo(2)" gets &foo into rd. */
+
+ .file "dispatch-ppc64-aix5.S"
+ .machine "ppc64"
+ .toc
+ .csect .text[PR]
+ .toc
+tocent__vgPlain_dispatch_ctr:
+ .tc vgPlain_dispatch_ctr[TC],vgPlain_dispatch_ctr[RW]
+tocent__vgPlain_machine_ppc64_has_VMX:
+ .tc vgPlain_machine_ppc64_has_VMX[TC],vgPlain_machine_ppc64_has_VMX[=
RW]
+tocent__vgPlain_tt_fast:
+ .tc vgPlain_tt_fast[TC],vgPlain_tt_fast[RW]
+tocent__vgPlain_tt_fastN:
+ .tc vgPlain_tt_fast[TC],vgPlain_tt_fastN[RW]
+ .csect .text[PR]
+ .align 2
+ .globl vgPlain_run_innerloop
+ .globl .vgPlain_run_innerloop
+ .csect vgPlain_run_innerloop[DS]
+vgPlain_run_innerloop:
+ .llong .vgPlain_run_innerloop, TOC[tc0], 0
+ .csect .text[PR]
+
+/*----------------------------------------------------*/
+/*--- Preamble (set everything up) ---*/
+/*----------------------------------------------------*/
+
+/* signature:
+UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
+*/
+.vgPlain_run_innerloop:
+
+ /* r3 holds guest_state */
+ /* r4 holds do_profiling */
+ /* Rather than attempt to make sense of the AIX ABI, just
+ drop r1 by 512 (to get away from the caller's frame), then
+ 1024 (to give ourselves a 1024-byte save area), and then
+ another 512 (to clear our save area). In all, drop r1 by 2048
+ and dump stuff on the stack at 512(1)..1536(1). */
+
+ /* ----- entry point to VG_(run_innerloop) ----- */
+ /* For AIX/ppc64 we do: LR-> +16(parent_sp), CR-> +8(parent_sp)=
*/
+
+ /* Save lr and cr*/
+ mflr 0
+ std 0,16(1)
+ mfcr 0
+ std 0,8(1)
+
+ /* New stack frame */
+ stdu 1,-2048(1) /* sp should maintain 16-byte alignment */
+
+ /* Save callee-saved registers... */
+ /* r3, r4 are live here, so use r5 */
+
+ /* Floating-point reg save area : 144 bytes at r1[256+256..256+3=
99] */
+ stfd 31,256+392(1)
+ stfd 30,256+384(1)
+ stfd 29,256+376(1)
+ stfd 28,256+368(1)
+ stfd 27,256+360(1)
+ stfd 26,256+352(1)
+ stfd 25,256+344(1)
+ stfd 24,256+336(1)
+ stfd 23,256+328(1)
+ stfd 22,256+320(1)
+ stfd 21,256+312(1)
+ stfd 20,256+304(1)
+ stfd 19,256+296(1)
+ stfd 18,256+288(1)
+ stfd 17,256+280(1)
+ stfd 16,256+272(1)
+ stfd 15,256+264(1)
+ stfd 14,256+256(1)
+
+ /* General reg save area : 76 bytes at r1[256+400 .. 256+543] */
+ std 31,256+544(1)
+ std 30,256+536(1)
+ std 29,256+528(1)
+ std 28,256+520(1)
+ std 27,256+512(1)
+ std 26,256+504(1)
+ std 25,256+496(1)
+ std 24,256+488(1)
+ std 23,256+480(1)
+ std 22,256+472(1)
+ std 21,256+464(1)
+ std 20,256+456(1)
+ std 19,256+448(1)
+ std 18,256+440(1)
+ std 17,256+432(1)
+ std 16,256+424(1)
+ std 15,256+416(1)
+ std 14,256+408(1)
+ /* Probably not necessary to save r13 (thread-specific ptr),
+ as VEX stays clear of it... but what the hell. */
+ std 13,256+400(1)
+
+ /* It's necessary to save/restore VRSAVE in the AIX / Darwin ABI=
.
+ The Linux kernel might not actually use VRSAVE for its intend=
ed
+ purpose, but it should be harmless to preserve anyway. */
+ /* r3, r4 are live here, so use r5 */
+ ld 5,tocent__vgPlain_machine_ppc64_has_VMX(2)
+ ld 5,0(5)
+ cmpldi 5,0
+ beq LafterVMX1
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// /* VRSAVE save word : 4 bytes at r1[476 .. 479] */
+// mfspr 5,256 /* vrsave reg is spr number 256 */
+// stw 5,476(1)
+//
+// /* Vector reg save area (quadword aligned):=20
+// 192 bytes at r1[480 .. 671] */
+// li 5,656
+// stvx 31,5,1
+// li 5,640
+// stvx 30,5,1
+// li 5,624
+// stvx 29,5,1
+// li 5,608
+// stvx 28,5,1
+// li 5,592
+// stvx 27,5,1
+// li 5,576
+// stvx 26,5,1
+// li 5,560
+// stvx 25,5,1
+// li 5,544
+// stvx 25,5,1
+// li 5,528
+// stvx 23,5,1
+// li 5,512
+// stvx 22,5,1
+// li 5,496
+// stvx 21,5,1
+// li 5,480
+// stvx 20,5,1
+LafterVMX1:
+
+ /* Local variable space... */
+ /* Put the original guest state pointer at r1[256]. We
+ will need to refer to it each time round the dispatch loop.
+ Apart from that, we can use r1[0 .. 255] and r1[264 .. 511]
+ as scratch space. */
+
+ /* r3 holds guest_state */
+ /* r4 holds do_profiling */
+ mr 31,3 /* r31 (generated code gsp) =3D r3 */
+ std 3,256(1) /* stash orig guest_state ptr */
+
+ /* hold dispatch_ctr (NOTE: 32-bit value) in r29 */
+ ld 5,tocent__vgPlain_dispatch_ctr(2)
+ lwz 29,0(5)
+
+ /* set host FPU control word to the default mode expected=20
+ by VEX-generated code. See comments in libvex.h for
+ more info. */
+ /* get zero into f3 (tedious) */
+ /* note: fsub 3,3,3 is not a reliable way to do this,=20
+ since if f3 holds a NaN or similar then we don't necessarily
+ wind up with zero. */
+ li 5,0
+ std 5,128(1) /* r1[128] is scratch */
+ lfd 3,128(1)
+ mtfsf 0xFF,3 /* fpscr =3D f3 */
+
+ /* set host AltiVec control word to the default mode expected=20
+ by VEX-generated code. */
+ ld 5,tocent__vgPlain_machine_ppc64_has_VMX(2)
+ ld 5,0(5)
+ cmpldi 5,0
+ beq LafterVMX2
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// vspltisw 3,0x0 /* generate zero */
+// mtvscr 3
+LafterVMX2:
+
+ /* fetch %CIA into r3 */
+ ld 3,OFFSET_ppc64_CIA(31)
+
+ /* fall into main loop (the right one) */
+ /* r4 =3D do_profiling. It's probably trashed after here,
+ but that's OK: we don't need it after here. */
+ cmpldi 4,0
+ beq VG_(run_innerloop__dispatch_unprofiled)
+ b VG_(run_innerloop__dispatch_profiled)
+ /*NOTREACHED*/
+
+/*----------------------------------------------------*/
+/*--- NO-PROFILING (standard) dispatcher ---*/
+/*----------------------------------------------------*/
+
+.globl VG_(run_innerloop__dispatch_unprofiled)
+VG_(run_innerloop__dispatch_unprofiled):
+ /* At entry: Live regs:
+ r1 (=3Dsp)
+ r3 (=3DCIA =3D next guest address)
+ r29 (=3Ddispatch_ctr)
+ r31 (=3Dguest_state)
+ Stack state:
+ 256(r1) (=3Dorig guest_state)
+ */
+
+ /* Has the guest state pointer been messed with? If yes, exit. */
+ ld 5,256(1) /* original guest_state ptr */
+ cmpd 5,31
+ bne gsp_changed
+
+ /* save the jump address in the guest state */
+ std 3,OFFSET_ppc64_CIA(31)
+
+ /* Are we out of timeslice? If yes, defer to scheduler. */
+ addi 29,29,-1
+ cmplwi 29,0 /* yes, lwi - is 32-bit */
+ beq counter_is_zero
+
+ /* try a fast lookup in the translation cache */
+ /* r4 =3D VG_TT_FAST_HASH(addr) * sizeof(ULong*)
+ =3D ((r3 >>u 2) & VG_TT_FAST_MASK) << 3 */
+ rldicl 4,3, 62, 64-VG_TT_FAST_BITS
+ sldi 4,4,3
+
+ ld 5,tocent__vgPlain_tt_fast(2) /* r5 =3D &tt_fast */
+
+ ldx 5,5,4 /* r5 =3D VG_(tt_fast)[VG_TT_FAST_HASH(addr)] */
+ ld 6,0(5) /* r6 =3D (r5)->orig_addr */
+ cmpd 3,6
+ bne fast_lookup_failed
+
+ /* Found a match. Call tce[1], which is 8 bytes along, since
+ each tce element is a 64-bit int. */
+ addi 8,5,8
+ mtctr 8
+
+ /* run the translation */
+ bctrl
+
+ /* On return from guest code:
+ r3 holds destination (original) address.
+ r31 may be unchanged (guest_state), or may indicate further
+ details of the control transfer requested to *r3.
+ */
+
+ /* start over */
+ b VG_(run_innerloop__dispatch_unprofiled)
+ /*NOTREACHED*/
+
+/*----------------------------------------------------*/
+/*--- PROFILING dispatcher (can be much slower) ---*/
+/*----------------------------------------------------*/
+
+.globl VG_(run_innerloop__dispatch_profiled)
+VG_(run_innerloop__dispatch_profiled):
+ /* At entry: Live regs:
+ r1 (=3Dsp)
+ r3 (=3DCIA =3D next guest address)
+ r29 (=3Ddispatch_ctr)
+ r31 (=3Dguest_state)
+ Stack state:
+ 256(r1) (=3Dorig guest_state)
+ */
+
+ /* Has the guest state pointer been messed with? If yes, exit. */
+ ld 5,256(1) /* original guest_state ptr */
+ cmpd 5,31
+ bne gsp_changed
+
+ /* save the jump address in the guest state */
+ std 3,OFFSET_ppc64_CIA(31)
+
+ /* Are we out of timeslice? If yes, defer to scheduler. */
+ addi 29,29,-1
+ cmplwi 29,0 /* yes, lwi - is 32-bit */
+ beq counter_is_zero
+
+ /* try a fast lookup in the translation cache */
+ /* r4 =3D VG_TT_FAST_HASH(addr) * sizeof(ULong*)
+ =3D ((r3 >>u 2) & VG_TT_FAST_MASK) << 3 */
+ rldicl 4,3, 62, 64-VG_TT_FAST_BITS
+ sldi 4,4,3
+
+ ld 5,tocent__vgPlain_tt_fast(2) /* r5 =3D &tt_fast */
+
+ ldx 5,5,4 /* r5 =3D VG_(tt_fast)[VG_TT_FAST_HASH(addr)] */
+ ld 6,0(5) /* r6 =3D (r5)->orig_addr */
+ cmpd 3,6
+ bne fast_lookup_failed
+
+ /* increment bb profile counter */
+ ld 9,tocent__vgPlain_tt_fastN(2) /* r9 =3D &tt_fastN */
+ ldx 7,9,4 /* r7 =3D tt_fastN[r4] */
+ lwz 10,0(7)
+ addi 10,10,1
+ stw 10,0(7)
+=09
+ /* Found a match. Call tce[1], which is 8 bytes along, since
+ each tce element is a 64-bit int. */
+ addi 8,5,8
+ mtctr 8
+
+ /* run the translation */
+ bctrl
+
+ /* On return from guest code:
+ r3 holds destination (original) address.
+ r31 may be unchanged (guest_state), or may indicate further
+ details of the control transfer requested to *r3.
+ */
+
+ /* start over */
+ b VG_(run_innerloop__dispatch_profiled)
+ /*NOTREACHED*/
+
+/*----------------------------------------------------*/
+/*--- exit points ---*/
+/*----------------------------------------------------*/
+
+gsp_changed:
+ /* Someone messed with the gsp (in r31). Have to
+ defer to scheduler to resolve this. dispatch ctr
+ is not yet decremented, so no need to increment. */
+ /* %CIA is NOT up to date here. First, need to write
+ %r3 back to %CIA, but without trashing %r31 since
+ that holds the value we want to return to the scheduler.
+ Hence use %r5 transiently for the guest state pointer. */
+ ld 5,256(1) /* original guest_state ptr */
+ std 3,OFFSET_ppc64_CIA(5)
+ mr 3,31 /* r3 =3D new gsp value */
+ b run_innerloop_exit
+ /*NOTREACHED*/
+
+counter_is_zero:
+ /* %CIA is up to date */
+ /* back out decrement of the dispatch counter */
+ addi 29,29,1
+ li 3,VG_TRC_INNER_COUNTERZERO
+ b run_innerloop_exit
+
+fast_lookup_failed:
+ /* %CIA is up to date */
+ /* back out decrement of the dispatch counter */
+ addi 29,29,1
+ li 3,VG_TRC_INNER_FASTMISS
+ b run_innerloop_exit
+
+
+
+/* All exits from the dispatcher go through here.
+ r3 holds the return value.=20
+*/
+run_innerloop_exit:=20
+ /* We're leaving. Check that nobody messed with
+ VSCR or FPSCR. */
+
+ /* Set fpscr back to a known state, since vex-generated code
+ may have messed with fpscr[rm]. */
+ li 5,0
+ std 5,128(1) /* r1[128] is scratch */
+ lfd 3,128(1)
+ mtfsf 0xFF,3 /* fpscr =3D f3 */
+
+ /* Using r11 - value used again further on, so don't trash! */
+ ld 11,tocent__vgPlain_machine_ppc64_has_VMX(2)
+ ld 11,0(11)
+ cmpldi 11,0
+ beq LafterVMX8
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// /* Check VSCR[NJ] =3D=3D 1 */
+// /* first generate 4x 0x00010000 */
+// vspltisw 4,0x1 /* 4x 0x00000001 */
+// vspltisw 5,0x0 /* zero */
+// vsldoi 6,4,5,0x2 /* <<2*8 =3D> 4x 0x00010000 =
*/
+// /* retrieve VSCR and mask wanted bits */
+// mfvscr 7
+// vand 7,7,6 /* gives NJ flag */
+// vspltw 7,7,0x3 /* flags-word to all lanes *=
/
+// vcmpequw. 8,6,7 /* CR[24] =3D 1 if v6 =3D=3D=
v7 */
+// bt 24,invariant_violation /* branch if all_equal */
+LafterVMX8:
+
+ /* otherwise we're OK */
+ b run_innerloop_exit_REALLY
+
+
+invariant_violation:
+ li 3,VG_TRC_INVARIANT_FAILED
+ b run_innerloop_exit_REALLY
+
+run_innerloop_exit_REALLY:
+ /* r3 holds VG_TRC_* value to return */
+
+ /* Write ctr to VG(dispatch_ctr) */
+ ld 5,tocent__vgPlain_dispatch_ctr(2)
+ stw 29,0(5) /* yes, really stw */
+
+ /* Restore callee-saved registers... */
+
+ /* Floating-point regs */
+ lfd 31,256+392(1)
+ lfd 30,256+384(1)
+ lfd 29,256+376(1)
+ lfd 28,256+368(1)
+ lfd 27,256+360(1)
+ lfd 26,256+352(1)
+ lfd 25,256+344(1)
+ lfd 24,256+336(1)
+ lfd 23,256+328(1)
+ lfd 22,256+320(1)
+ lfd 21,256+312(1)
+ lfd 20,256+304(1)
+ lfd 19,256+296(1)
+ lfd 18,256+288(1)
+ lfd 17,256+280(1)
+ lfd 16,256+272(1)
+ lfd 15,256+264(1)
+ lfd 14,256+256(1)
+
+ /* General regs */
+ ld 31,256+544(1)
+ ld 30,256+536(1)
+ ld 29,256+528(1)
+ ld 28,256+520(1)
+ ld 27,256+512(1)
+ ld 26,256+504(1)
+ ld 25,256+496(1)
+ ld 24,256+488(1)
+ ld 23,256+480(1)
+ ld 22,256+472(1)
+ ld 21,256+464(1)
+ ld 20,256+456(1)
+ ld 19,256+448(1)
+ ld 18,256+440(1)
+ ld 17,256+432(1)
+ ld 16,256+424(1)
+ ld 15,256+416(1)
+ ld 14,256+408(1)
+ ld 13,256+400(1)
+
+ /* r11 already holds VG_(machine_ppc64_has_VMX) value */
+ cmpldi 11,0
+ beq LafterVMX9
+
+// Sigh. AIX 5.2 has no idea that Altivec exists.
+// /* VRSAVE */
+// lwz 4,476(1)
+// mtspr 4,256 /* VRSAVE reg is spr number 256 */
+//
+// /* Vector regs */
+// li 4,656
+// lvx 31,4,1
+// li 4,640
+// lvx 30,4,1
+// li 4,624
+// lvx 29,4,1
+// li 4,608
+// lvx 28,4,1
+// li 4,592
+// lvx 27,4,1
+// li 4,576
+// lvx 26,4,1
+// li 4,560
+// lvx 25,4,1
+// li 4,544
+// lvx 24,4,1
+// li 4,528
+// lvx 23,4,1
+// li 4,512
+// lvx 22,4,1
+// li 4,496
+// lvx 21,4,1
+// li 4,480
+// lvx 20,4,1
+LafterVMX9:
+
+ /* r3 is live here; don't trash it */
+ /* restore lr,cr,sp */
+ addi 4,1,2048 /* r4 =3D old SP */
+ ld 0,16(4)
+ mtlr 0
+ ld 0,8(4)
+ mtcr 0
+ mr 1,4
+ blr
+
+LT..vgPlain_run_innerloop:
+ .long 0
+ .byte 0,0,32,64,0,0,1,0
+ .long 0
+ .long LT..vgPlain_run_innerloop-.vgPlain_run_innerloop
+ .short 3
+ .byte "vgPlain_run_innerloop"
+ .align 2
+_section_.text:
+ .csect .data[RW],3
+ .llong _section_.text
+
+/*------------------------------------------------------------*/
+/*--- ---*/
+/*--- A special dispatcher, for running no-redir ---*/
+/*--- translations. Just runs the given translation once. ---*/
+/*--- ---*/
+/*------------------------------------------------------------*/
+=09
+/* signature:
+void VG_(run_a_noredir_translation) ( UWord* argblock );
+*/
+
+/* Run a no-redir translation. argblock points to 4 UWords, 2 to carry =
args
+ and 2 to carry results:
+ 0: input: ptr to translation
+ 1: input: ptr to guest state
+ 2: output: next guest PC
+ 3: output: guest state pointer afterwards (=3D=3D thread return co=
de)
+*/
+.csect .text[PR]
+.align 2
+.globl .VG_(run_a_noredir_translation)
+.VG_(run_a_noredir_translation):
+ /* Rather than attempt to make sense of the AIX ABI, just
+ drop r1 by 512 (to get away from the caller's frame), then
+ 1024 (to give ourselves a 1024-byte save area), and then
+ another 1024 (to clear our save area). In all, drop r1 by 2048
+ and dump stuff on the stack at 512(1)..1536(1). */
+ /* At entry, r3 points to argblock */
+
+ /* ----- entry point to VG_(run_innerloop) ----- */
+ /* For AIX/ppc64 we do: LR-> +16(parent_sp), CR-> +8(parent_sp)=
*/
+
+ /* Save lr and cr*/
+ mflr 0
+ std 0,16(1)
+ mfcr 0
+ std 0,8(1)
+
+ /* New stack frame */
+ stdu 1,-2048(1) /* sp should maintain 16-byte alignment */
+
+ /* General reg save area : 160 bytes at r1[512 .. 671] */
+ std 31,664(1)
+ std 30,656(1)
+ std 29,648(1)
+ std 28,640(1)
+ std 27,632(1)
+ std 26,624(1)
+ std 25,616(1)
+ std 24,608(1)
+ std 23,600(1)
+ std 22,592(1)
+ std 21,584(1)
+ std 20,576(1)
+ std 19,568(1)
+ std 18,560(1)
+ std 17,552(1)
+ std 16,544(1)
+ std 15,536(1)
+ std 14,528(1)
+ std 13,520(1)
+ std 3,512(1) /* will need it later */
+=09
+ ld 31,8(3) /* rd argblock[1] */
+ ld 30,0(3) /* rd argblock[0] */
+ mtlr 30 /* run translation */
+ blrl
+
+ ld 4,512(1) /* &argblock */
+ std 3, 16(4) /* wr argblock[2] */
+ std 31,24(4) /* wr argblock[3] */
+ =09
+ /* General regs */
+ ld 31,664(1)
+ ld 30,656(1)
+ ld 29,648(1)
+ ld 28,640(1)
+ ld 27,632(1)
+ ld 26,624(1)
+ ld 25,616(1)
+ ld 24,608(1)
+ ld 23,600(1)
+ ld 22,592(1)
+ ld 21,584(1)
+ ld 20,576(1)
+ ld 19,568(1)
+ ld 18,560(1)
+ ld 17,552(1)
+ ld 16,544(1)
+ ld 15,536(1)
+ ld 14,528(1)
+ ld 13,520(1)
+
+ /* restore lr,cr,sp */
+ addi 4,1,2048 /* r4 =3D old SP */
+ ld 0,16(4)
+ mtlr 0
+ ld 0,8(4)
+ mtcr 0
+ mr 1,4
+ blr
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
|
|
From: <sv...@va...> - 2006-10-17 01:05:59
|
Author: sewardj
Date: 2006-10-17 02:05:57 +0100 (Tue, 17 Oct 2006)
New Revision: 6247
Log:
Merge r6097:
Stub implementation for AIX5.
Added:
trunk/coregrind/m_coredump/coredump-ppc32-aix5.c
trunk/coregrind/m_coredump/coredump-ppc64-aix5.c
Added: trunk/coregrind/m_coredump/coredump-ppc32-aix5.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_coredump/coredump-ppc32-aix5.c =
(rev 0)
+++ trunk/coregrind/m_coredump/coredump-ppc32-aix5.c 2006-10-17 01:05:57 =
UTC (rev 6247)
@@ -0,0 +1,43 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Dumping core. coredump-ppc32-aix5.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_coredump.h" /* self */
+
+void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si, UInt max_=
size)
+{
+ /* not implemented */
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Added: trunk/coregrind/m_coredump/coredump-ppc64-aix5.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_coredump/coredump-ppc64-aix5.c =
(rev 0)
+++ trunk/coregrind/m_coredump/coredump-ppc64-aix5.c 2006-10-17 01:05:57 =
UTC (rev 6247)
@@ -0,0 +1,43 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Dumping core. coredump-ppc64-aix5.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ 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.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_coredump.h" /* self */
+
+void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si, UInt max_=
size)
+{
+ /* not implemented */
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
|