mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
Merging branch/2023-05-16/interior-pointers for github pull request <https://github.com/ravenbrook/mps/pull/223>.
GitHub-reference: https://github.com/Ravenbrook/mps/issues/223
This commit is contained in:
commit
8de6f8af38
19 changed files with 738 additions and 112 deletions
240
mps/code/addrobj.c
Normal file
240
mps/code/addrobj.c
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/* addrobj.c: BASE ADDRESS FROM INTERIOR POINTER TEST
|
||||
*
|
||||
* Copyright (c) 2023 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .overview This test is for mps_addr_object(). Its intention is to
|
||||
* verify that the function returns the appropriate base pointer to an
|
||||
* object when provided with an interior pointer. It also tests that the
|
||||
* function fails appropriately when the provided with a pointer to
|
||||
* unmanaged memory, or to an object in a pool that doesn't support this
|
||||
* feature.
|
||||
*
|
||||
* .limitations Objects that have been moved should cause the function to
|
||||
* fail with MPS_RES_FAIL, however this is not tested. It could be tested if
|
||||
* a testbench deliberately created a forwarding object, however this might
|
||||
* confuse a pool that does automatic garbage collection such as AMC or AMCZ,
|
||||
* so any such test would need to be designed to handle that.
|
||||
* This test only examines behaviour in AMCZ and MVFF pools, i.e. A pool (AMCZ)
|
||||
* which currently implements mps_addr_object() and one (MVFF) that doesn't.
|
||||
*/
|
||||
|
||||
#include "mps.h"
|
||||
#include "testlib.h"
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpscamc.h"
|
||||
#include "mpscmvff.h"
|
||||
#include "stdio.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Define an object size to allocate. The size chosen doesn't matter much, except that this testbench assumes
|
||||
that the object is large enough that a pointer could point to the interior of the object, without also
|
||||
pointing to the base pointer of the object at the same time. For char pointers, this is probably 2 bytes.
|
||||
Since we are using the Dylan library, we define the size of the object in terms of Dylan slots. See
|
||||
fmtdytst.c for details of the Dylan object structure.*/
|
||||
#define N_SLOT_TESTOBJ 100
|
||||
|
||||
static void test_main(void)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_pool_t amcz_pool, mvff_pool;
|
||||
mps_ap_t obj_ap;
|
||||
mps_fmt_t obj_fmt;
|
||||
mps_root_t testobj_root;
|
||||
mps_res_t res;
|
||||
/* In another testbench (extcon.c) we observed unreliable failures to do with registering the cold end
|
||||
of the stack. See GitHub issue #210
|
||||
<https://github.com/Ravenbrook/mps/issues/210>. For now, we
|
||||
declare this as a separate root. */
|
||||
static mps_addr_t testobj;
|
||||
mps_addr_t out, in;
|
||||
|
||||
/* Create arena */
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none), "mps_arena_create_k");
|
||||
|
||||
|
||||
/* INTRO TO TESTS: There are several tests. They test the expected "normal" operation of the
|
||||
function, using an interior pointer, also corner cases where the interior pointer equals the
|
||||
base pointer, where it equals the limit pointer. We also test asking about an address in unmanaged
|
||||
memory, and about an address in a pool which currently does not support mps_addr_object. If you write
|
||||
more tests, describe them here.*/
|
||||
|
||||
|
||||
/* TEST 1: Test using an interior pointer in an object in an AMCZ pool.
|
||||
At the time of writing this test, the AMCZ pool is the only pool where
|
||||
there exists a requirement to provide base addresses from interior pointers.
|
||||
Currently, the AMCZ pool (and by extension, the AMC pool which shares the same
|
||||
module as AMCZ) is the only pool for which mps_addr_object is implemented */
|
||||
|
||||
/* Use the dylan format for convenience */
|
||||
die(dylan_fmt(&obj_fmt, arena), "dylan_fmt");
|
||||
|
||||
/* Create the pool */
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, obj_fmt);
|
||||
die(mps_pool_create_k(&amcz_pool, arena, mps_class_amcz(), args), "mps_pool_create_k amcz");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
/* Create an area of ambiguous pointers to keep the object alive and in place, in this case
|
||||
the area only contains room for a single reference since we are only using one object to test */
|
||||
die(mps_root_create_area(&testobj_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
&testobj, &testobj+1,
|
||||
mps_scan_area, NULL),
|
||||
"mps_root_create_area");
|
||||
|
||||
/* Create the allocation point */
|
||||
die(mps_ap_create_k(&obj_ap, amcz_pool, mps_args_none), "mps_ap_create_k");
|
||||
|
||||
/* Make a Dylan object, size = (N_SLOT_TESTOBJ+2) * sizeof(mps_word_t).
|
||||
(See fmtdytst.c for size calculation) */
|
||||
{
|
||||
/* Because make_dylan_vector returns its pointer-to-object as an mps_word_t rather than an
|
||||
mps_addr_t, and commits the object, we need to somehow safely allocate our object without
|
||||
type punning and without risking that our object be destroyed.
|
||||
Rather than redefine our reference table with type mps_word_t, which hides the intention of the table,
|
||||
park the arena to disable garbage collection. Allocate our dylan object on the (unregistered) stack
|
||||
storing its address in an mps_word_t. Then store this mps_word_t as an mps_addr_t in our reference
|
||||
table, and release the arena since our object is now safely pinned.
|
||||
Another approach would be to create another static registered root for ambiguous references of type
|
||||
mps_word_t and then copy to the mps_addr_t root, which would avoid needing to park the arena.
|
||||
*/
|
||||
mps_word_t p_word;
|
||||
mps_arena_park(arena);
|
||||
die(make_dylan_vector(&p_word, obj_ap, N_SLOT_TESTOBJ), "make_dylan_vector");
|
||||
/* If we hadn't parked the arena, our vector might have been GC'd here */
|
||||
testobj = (mps_addr_t)p_word;
|
||||
mps_arena_release(arena);
|
||||
}
|
||||
|
||||
/* Construct a pointer to roughly halfway inside the object */
|
||||
in = (mps_addr_t)((char *)testobj + (N_SLOT_TESTOBJ/2) * sizeof(mps_word_t));
|
||||
|
||||
/* Ensure that this is an interior pointer, and not the base pointer,
|
||||
since we want to make sure we are testing with a true interior pointer and not
|
||||
one that also happens to be the base pointer. This Insist is intended to protect
|
||||
against the testbench losing its ability to test "true" interior pointers (i.e. ones
|
||||
which don't match the base pointer) if the test object sizes were changed to be very
|
||||
small. Note that we don't currently consider the "limit" of the object as a corner case
|
||||
(so we don't Insist(in != limit) ) but we do consider limit+1, i.e. the pointer to the
|
||||
next object to be a corner case. This test could be updated to consider in == limit as a
|
||||
corner case. */
|
||||
Insist(in > testobj);
|
||||
|
||||
/* Do Test */
|
||||
res = mps_addr_object(&out, arena, in);
|
||||
Insist(out == testobj);
|
||||
Insist(res == MPS_RES_OK);
|
||||
printf("Interior pointer input: passed\n");
|
||||
|
||||
|
||||
/* TEST 2: Test using the base pointer itself as an input*/
|
||||
|
||||
in = testobj;
|
||||
|
||||
/* Do Test */
|
||||
res = mps_addr_object(&out, arena, in);
|
||||
Insist(out == testobj);
|
||||
Insist(res == MPS_RES_OK);
|
||||
printf("Base pointer input: passed\n");
|
||||
|
||||
|
||||
|
||||
/* TEST 3: Test using a pointer one-off-the-end of the object*/
|
||||
|
||||
in = (mps_addr_t)((char *)testobj + (N_SLOT_TESTOBJ + 2) * sizeof(mps_word_t));
|
||||
|
||||
/* Do Test */
|
||||
res = mps_addr_object(&out, arena, in);
|
||||
Insist(res == MPS_RES_FAIL);
|
||||
printf("Pointer to next object input: passed\n");
|
||||
|
||||
|
||||
/* Clean up from above tests */
|
||||
mps_root_destroy(testobj_root);
|
||||
mps_ap_destroy(obj_ap);
|
||||
mps_pool_destroy(amcz_pool);
|
||||
mps_fmt_destroy(obj_fmt);
|
||||
|
||||
|
||||
/* TEST 4: Test using a pointer in unmanaged memory */
|
||||
|
||||
/* Use malloc to allocate non-mps-managed memory on the heap */
|
||||
in = malloc(sizeof(mps_word_t));
|
||||
Insist(NULL != in);
|
||||
|
||||
/* Do the test */
|
||||
res = mps_addr_object(&out, arena, in);
|
||||
|
||||
/* Expect MPS to fail to find a base pointer for addresses not in managed memory */
|
||||
Insist(res == MPS_RES_FAIL);
|
||||
printf("Pointer to unmanaged memory input: passed\n");
|
||||
|
||||
/* clean up from this test */
|
||||
if (NULL != in)
|
||||
free(in);
|
||||
|
||||
|
||||
/* TEST 5: Test using a pointer in a pool which currently doesn't implement mps_addr_object */
|
||||
|
||||
/* Create mvff pool for which mps_addr_object is not implemented */
|
||||
die(mps_pool_create_k(&mvff_pool, arena, mps_class_mvff(), mps_args_none), "mps_pool_create_k mvff");
|
||||
|
||||
/* allocate an object (just some memory) in this pool */
|
||||
die(mps_alloc(&in, mvff_pool, sizeof(mps_word_t)), "mps_alloc");
|
||||
|
||||
/* Do the test */
|
||||
res = mps_addr_object(&out, arena, in);
|
||||
|
||||
Insist(res == MPS_RES_UNIMPL);
|
||||
printf("Pointer to object in pool where mps_addr_object not implemented: passed\n");
|
||||
|
||||
|
||||
/* If more tests are added here, briefly describe them above under "INTRO TO TESTS" comment */
|
||||
|
||||
/* Final clean up */
|
||||
mps_free(mvff_pool, in, sizeof(mps_word_t));
|
||||
mps_pool_destroy(mvff_pool);
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
testlib_init(argc, argv);
|
||||
|
||||
test_main();
|
||||
|
||||
printf("%s: Conculsion, failed to find any defects.\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2022-2023 Ravenbrook Limited <https://www.ravenbrook.com/>.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -1364,6 +1364,22 @@ Bool ArenaHasAddr(Arena arena, Addr addr)
|
|||
return TractOfAddr(&tract, arena, addr);
|
||||
}
|
||||
|
||||
/* ArenaAddrObject -- return base pointer of managed object */
|
||||
Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr)
|
||||
{
|
||||
Tract tract;
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
|
||||
if (!TractOfAddr(&tract, arena, addr)) {
|
||||
/* address does not belong to the arena */
|
||||
return ResFAIL;
|
||||
}
|
||||
|
||||
return PoolAddrObject(pReturn, TractPool(tract), addr);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ LIB_TARGETS=mps.a mpsplan.a
|
|||
|
||||
TEST_TARGETS=\
|
||||
abqtest \
|
||||
addrobj \
|
||||
airtest \
|
||||
amcss \
|
||||
amcsshe \
|
||||
|
|
@ -446,6 +447,9 @@ ifdef VARIETY
|
|||
$(PFM)/$(VARIETY)/abqtest: $(PFM)/$(VARIETY)/abqtest.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/addrobj: $(PFM)/$(VARIETY)/addrobj.o \
|
||||
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/airtest: $(PFM)/$(VARIETY)/airtest.o \
|
||||
$(FMTSCMOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
|
|
|
|||
|
|
@ -177,6 +177,9 @@ $(PFM)\cool\mps.lib: $(MPMOBJ)
|
|||
$(PFM)\$(VARIETY)\abqtest.exe: $(PFM)\$(VARIETY)\abqtest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\addrobj.exe: $(PFM)\$(VARIETY)\addrobj.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\airtest.exe: $(PFM)\$(VARIETY)\airtest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTSCHEMEOBJ) $(TESTLIBOBJ)
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ LIB_TARGETS=mps.lib
|
|||
|
||||
TEST_TARGETS=\
|
||||
abqtest.exe \
|
||||
addrobj.exe \
|
||||
airtest.exe \
|
||||
amcss.exe \
|
||||
amcsshe.exe \
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@ extern Res PoolTraceBegin(Pool pool, Trace trace);
|
|||
extern void PoolFreeWalk(Pool pool, FreeBlockVisitor f, void *p);
|
||||
extern Size PoolTotalSize(Pool pool);
|
||||
extern Size PoolFreeSize(Pool pool);
|
||||
extern Res PoolAddrObject(Addr *pReturn, Pool pool, Addr addr);
|
||||
|
||||
extern Res PoolAbsInit(Pool pool, Arena arena, PoolClass klass, ArgList arg);
|
||||
extern void PoolAbsFinish(Inst inst);
|
||||
|
|
@ -267,6 +268,7 @@ extern void PoolTrivFreeWalk(Pool pool, FreeBlockVisitor f, void *p);
|
|||
extern PoolDebugMixin PoolNoDebugMixin(Pool pool);
|
||||
extern BufferClass PoolNoBufferClass(void);
|
||||
extern Size PoolNoSize(Pool pool);
|
||||
extern Res PoolTrivAddrObject(Addr *pReturn, Pool pool, Addr addr);
|
||||
|
||||
/* See .critical.macros. */
|
||||
#define PoolFreeMacro(pool, old, size) Method(Pool, pool, free)(pool, old, size)
|
||||
|
|
@ -536,6 +538,7 @@ extern Res ArenaStartCollect(Globals globals, TraceStartWhy why);
|
|||
extern Res ArenaCollect(Globals globals, TraceStartWhy why);
|
||||
extern Bool ArenaBusy(Arena arena);
|
||||
extern Bool ArenaHasAddr(Arena arena, Addr addr);
|
||||
extern Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr);
|
||||
extern void ArenaChunkInsert(Arena arena, Chunk chunk);
|
||||
extern void ArenaChunkRemoved(Arena arena, Chunk chunk);
|
||||
extern void ArenaAccumulateTime(Arena arena, Clock start, Clock now);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ typedef struct mps_pool_class_s {
|
|||
PoolRampEndMethod rampEnd; /* end a ramp pattern */
|
||||
PoolFramePushMethod framePush; /* push an allocation frame */
|
||||
PoolFramePopMethod framePop; /* pop an allocation frame */
|
||||
PoolAddrObjectMethod addrObject; /* return object's base pointer */
|
||||
PoolFreeWalkMethod freewalk; /* walk over free blocks */
|
||||
PoolBufferClassMethod bufferClass; /* default BufferClass of pool */
|
||||
PoolDebugMixinMethod debugMixin; /* find the debug mixin, if any */
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ typedef Res (*PoolFramePushMethod)(AllocFrame *frameReturn,
|
|||
Pool pool, Buffer buf);
|
||||
typedef Res (*PoolFramePopMethod)(Pool pool, Buffer buf,
|
||||
AllocFrame frame);
|
||||
typedef Res (*PoolAddrObjectMethod)(Addr *pReturn, Pool pool, Addr addr);
|
||||
typedef void (*PoolFreeWalkMethod)(Pool pool, FreeBlockVisitor f, void *p);
|
||||
typedef BufferClass (*PoolBufferClassMethod)(void);
|
||||
typedef PoolDebugMixin (*PoolDebugMixinMethod)(Pool pool);
|
||||
|
|
|
|||
|
|
@ -845,6 +845,8 @@ extern mps_res_t _mps_fix2(mps_ss_t, mps_addr_t *);
|
|||
(ss)->_ufs = _mps_ufs; \
|
||||
MPS_END
|
||||
|
||||
/* Misc interface */
|
||||
extern mps_res_t mps_addr_object(mps_addr_t *p_o, mps_arena_t arena, mps_addr_t addr);
|
||||
|
||||
#endif /* mps_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
buildPhases = (
|
||||
);
|
||||
dependencies = (
|
||||
319F7A192A30D2F000E5B418 /* PBXTargetDependency */,
|
||||
3104AFF6156D37BC000A585A /* PBXTargetDependency */,
|
||||
3114A644156E94FB001E0AA3 /* PBXTargetDependency */,
|
||||
22FACEF1188809B5000FDBC1 /* PBXTargetDependency */,
|
||||
|
|
@ -89,8 +90,6 @@
|
|||
3114A677156E961C001E0AA3 /* PBXTargetDependency */,
|
||||
3114A612156E943B001E0AA3 /* PBXTargetDependency */,
|
||||
22B2BC3D18B643B300C33E63 /* PBXTargetDependency */,
|
||||
2291A5E6175CB207001D4920 /* PBXTargetDependency */,
|
||||
2291A5E8175CB20E001D4920 /* PBXTargetDependency */,
|
||||
3114A5CC156E932C001E0AA3 /* PBXTargetDependency */,
|
||||
3114A5EA156E93C4001E0AA3 /* PBXTargetDependency */,
|
||||
22EA3F4820D2B23F0065F5B6 /* PBXTargetDependency */,
|
||||
|
|
@ -158,16 +157,6 @@
|
|||
2291A5B5175CAB2F001D4920 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
2291A5B7175CAB2F001D4920 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
2291A5BE175CAB4E001D4920 /* awlutth.c in Sources */ = {isa = PBXBuildFile; fileRef = 2291A5A9175CAA9B001D4920 /* awlutth.c */; };
|
||||
2291A5C5175CAFCA001D4920 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
2291A5C6175CAFCA001D4920 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
2291A5C7175CAFCA001D4920 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; };
|
||||
2291A5C8175CAFCA001D4920 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
2291A5CB175CAFCA001D4920 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
2291A5D8175CB05F001D4920 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
2291A5D9175CB05F001D4920 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
2291A5DA175CB05F001D4920 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; };
|
||||
2291A5DB175CB05F001D4920 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
2291A5DD175CB05F001D4920 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
2291A5ED175CB5E2001D4920 /* landtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 2291A5E9175CB4EC001D4920 /* landtest.c */; };
|
||||
22B2BC2E18B6434F00C33E63 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
|
||||
22B2BC3718B6437C00C33E63 /* scheme-advanced.c in Sources */ = {isa = PBXBuildFile; fileRef = 22B2BC2B18B6434000C33E63 /* scheme-advanced.c */; };
|
||||
|
|
@ -301,6 +290,12 @@
|
|||
3124CAFC156BE82900753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
318DA8D31892B27E0089718C /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
319F7A082A30D08500E5B418 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
319F7A0A2A30D08500E5B418 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
319F7A0B2A30D08500E5B418 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
319F7A0C2A30D08500E5B418 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; };
|
||||
319F7A0E2A30D08500E5B418 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
319F7A172A30D11400E5B418 /* addrobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 319F7A152A30D11400E5B418 /* addrobj.c */; };
|
||||
31A47BA4156C1E130039B1C2 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
|
||||
31D60007156D3C6200337B26 /* segsmss.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D60006156D3C5F00337B26 /* segsmss.c */; };
|
||||
31D60008156D3C7400337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
|
|
@ -468,20 +463,6 @@
|
|||
remoteGlobalIDString = 2291A5AC175CAB2F001D4920;
|
||||
remoteInfo = awlutth;
|
||||
};
|
||||
2291A5C3175CAFCA001D4920 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
|
||||
remoteInfo = mps;
|
||||
};
|
||||
2291A5D5175CB05F001D4920 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
|
||||
remoteInfo = mps;
|
||||
};
|
||||
229E228719EAB10D00E21417 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -923,6 +904,20 @@
|
|||
remoteGlobalIDString = 31108A3A1C6B90E900E728EA;
|
||||
remoteInfo = tagtest;
|
||||
};
|
||||
319F7A062A30D08500E5B418 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
|
||||
remoteInfo = mps;
|
||||
};
|
||||
319F7A182A30D2F000E5B418 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 319F7A042A30D08500E5B418;
|
||||
remoteInfo = addrobj;
|
||||
};
|
||||
31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -1092,24 +1087,6 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
2291A5CC175CAFCA001D4920 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
2291A5DE175CB05F001D4920 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
22B2BC3118B6434F00C33E63 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -1407,6 +1384,15 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
319F7A0F2A30D08500E5B418 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
31D6000B156D3CB200337B26 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -1729,6 +1715,8 @@
|
|||
31942AA91C8EC446001AAF32 /* sp.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = sp.txt; path = ../design/sp.txt; sourceTree = "<group>"; };
|
||||
31942AAB1C8EC446001AAF32 /* stack-scan.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "stack-scan.txt"; path = "../design/stack-scan.txt"; sourceTree = "<group>"; };
|
||||
31942AB01C8EC446001AAF32 /* testthr.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = testthr.txt; path = ../design/testthr.txt; sourceTree = "<group>"; };
|
||||
319F7A142A30D08500E5B418 /* addrobj */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = addrobj; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
319F7A152A30D11400E5B418 /* addrobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = addrobj.c; sourceTree = "<group>"; };
|
||||
31A47BA3156C1E130039B1C2 /* mps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mps.c; sourceTree = "<group>"; };
|
||||
31C83ADD1786281C0031A0DB /* protxc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = protxc.h; sourceTree = "<group>"; };
|
||||
31CD33BB173A9F1500524741 /* mpscams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mpscams.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1856,22 +1844,6 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2291A5CA175CAFCA001D4920 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2291A5CB175CAFCA001D4920 /* libmps.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2291A5DC175CB05F001D4920 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2291A5DD175CB05F001D4920 /* libmps.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
22B2BC3018B6434F00C33E63 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -2134,6 +2106,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
319F7A0D2A30D08500E5B418 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
319F7A0E2A30D08500E5B418 /* libmps.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
31D6000A156D3CB200337B26 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -2340,6 +2320,7 @@
|
|||
3124CAB3156BE1B700753214 /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
319F7A152A30D11400E5B418 /* addrobj.c */,
|
||||
3114A63D156E94EA001E0AA3 /* abqtest.c */,
|
||||
22FACED1188807FF000FDBC1 /* airtest.c */,
|
||||
3124CAF5156BE81100753214 /* amcss.c */,
|
||||
|
|
@ -2485,6 +2466,7 @@
|
|||
223E796519EAB00B00DC26A6 /* sncss */,
|
||||
22EA3F4520D2B0D90065F5B6 /* forktest */,
|
||||
2265D71D20E53F9C003019E8 /* mpseventpy */,
|
||||
319F7A142A30D08500E5B418 /* addrobj */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -3365,6 +3347,24 @@
|
|||
productReference = 318DA8CD1892B0F30089718C /* djbench */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
319F7A042A30D08500E5B418 /* addrobj */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 319F7A102A30D08500E5B418 /* Build configuration list for PBXNativeTarget "addrobj" */;
|
||||
buildPhases = (
|
||||
319F7A072A30D08500E5B418 /* Sources */,
|
||||
319F7A0D2A30D08500E5B418 /* Frameworks */,
|
||||
319F7A0F2A30D08500E5B418 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
319F7A052A30D08500E5B418 /* PBXTargetDependency */,
|
||||
);
|
||||
name = addrobj;
|
||||
productName = finalcv;
|
||||
productReference = 319F7A142A30D08500E5B418 /* addrobj */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
31D6000C156D3CB200337B26 /* awluthe */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 31D60014156D3CB200337B26 /* Build configuration list for PBXNativeTarget "awluthe" */;
|
||||
|
|
@ -3555,6 +3555,7 @@
|
|||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
English,
|
||||
en,
|
||||
);
|
||||
mainGroup = 31EEABD8156AAE9E00714D05;
|
||||
|
|
@ -3617,6 +3618,7 @@
|
|||
31FCAE0917692403008C034C /* scheme */,
|
||||
22B2BC2C18B6434F00C33E63 /* scheme-advanced */,
|
||||
31108A3A1C6B90E900E728EA /* tagtest */,
|
||||
319F7A042A30D08500E5B418 /* addrobj */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
|
@ -4090,6 +4092,18 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
319F7A072A30D08500E5B418 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
319F7A172A30D11400E5B418 /* addrobj.c in Sources */,
|
||||
319F7A082A30D08500E5B418 /* testlib.c in Sources */,
|
||||
319F7A0A2A30D08500E5B418 /* fmtdy.c in Sources */,
|
||||
319F7A0B2A30D08500E5B418 /* fmtdytst.c in Sources */,
|
||||
319F7A0C2A30D08500E5B418 /* fmtno.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
31D60009156D3CB200337B26 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -4287,16 +4301,6 @@
|
|||
target = 2291A5AC175CAB2F001D4920 /* awlutth */;
|
||||
targetProxy = 2291A5BF175CAB5F001D4920 /* PBXContainerItemProxy */;
|
||||
};
|
||||
2291A5C2175CAFCA001D4920 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
targetProxy = 2291A5C3175CAFCA001D4920 /* PBXContainerItemProxy */;
|
||||
};
|
||||
2291A5D4175CB05F001D4920 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
targetProxy = 2291A5D5175CB05F001D4920 /* PBXContainerItemProxy */;
|
||||
};
|
||||
229E228819EAB10D00E21417 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 223E795819EAB00B00DC26A6 /* sncss */;
|
||||
|
|
@ -4612,6 +4616,16 @@
|
|||
target = 31108A3A1C6B90E900E728EA /* tagtest */;
|
||||
targetProxy = 314CB6EA1C6D272A0073CA42 /* PBXContainerItemProxy */;
|
||||
};
|
||||
319F7A052A30D08500E5B418 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
targetProxy = 319F7A062A30D08500E5B418 /* PBXContainerItemProxy */;
|
||||
};
|
||||
319F7A192A30D2F000E5B418 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 319F7A042A30D08500E5B418 /* addrobj */;
|
||||
targetProxy = 319F7A182A30D2F000E5B418 /* PBXContainerItemProxy */;
|
||||
};
|
||||
31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
|
|
@ -4891,34 +4905,6 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
2291A5CE175CAFCA001D4920 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
2291A5CF175CAFCA001D4920 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
2291A5E0175CB05F001D4920 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
2291A5E1175CB05F001D4920 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
22B2BC3318B6434F00C33E63 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
|
@ -5633,20 +5619,6 @@
|
|||
};
|
||||
name = RASH;
|
||||
};
|
||||
318DA8E51892C0D00089718C /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = RASH;
|
||||
};
|
||||
318DA8E61892C0D00089718C /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = RASH;
|
||||
};
|
||||
318DA8E71892C0D00089718C /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
|
@ -5816,6 +5788,27 @@
|
|||
};
|
||||
name = RASH;
|
||||
};
|
||||
319F7A112A30D08500E5B418 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
319F7A122A30D08500E5B418 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
319F7A132A30D08500E5B418 /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = RASH;
|
||||
};
|
||||
31D60015156D3CB200337B26 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
|
@ -6553,6 +6546,16 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
319F7A102A30D08500E5B418 /* Build configuration list for PBXNativeTarget "addrobj" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
319F7A112A30D08500E5B418 /* Debug */,
|
||||
319F7A122A30D08500E5B418 /* Release */,
|
||||
319F7A132A30D08500E5B418 /* RASH */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
31D60014156D3CB200337B26 /* Build configuration list for PBXNativeTarget "awluthe" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "319F7A042A30D08500E5B418"
|
||||
BuildableName = "addrobj"
|
||||
BlueprintName = "addrobj"
|
||||
ReferencedContainer = "container:mps.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
viewDebuggingEnabled = "No">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "319F7A042A30D08500E5B418"
|
||||
BuildableName = "addrobj"
|
||||
BlueprintName = "addrobj"
|
||||
ReferencedContainer = "container:mps.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "319F7A042A30D08500E5B418"
|
||||
BuildableName = "addrobj"
|
||||
BlueprintName = "addrobj"
|
||||
ReferencedContainer = "container:mps.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "3114A5D5156E93A0001E0AA3"
|
||||
BuildableName = "finaltest"
|
||||
BlueprintName = "finaltest"
|
||||
ReferencedContainer = "container:mps.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
viewDebuggingEnabled = "No">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "3114A5D5156E93A0001E0AA3"
|
||||
BuildableName = "finaltest"
|
||||
BlueprintName = "finaltest"
|
||||
ReferencedContainer = "container:mps.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "3114A5D5156E93A0001E0AA3"
|
||||
BuildableName = "finaltest"
|
||||
BlueprintName = "finaltest"
|
||||
ReferencedContainer = "container:mps.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -448,6 +448,37 @@ mps_bool_t mps_addr_pool(mps_pool_t *mps_pool_o,
|
|||
}
|
||||
|
||||
|
||||
/* mps_addr_object -- find base pointer of a managed object */
|
||||
|
||||
mps_res_t mps_addr_object(mps_addr_t *p_o, mps_arena_t arena, mps_addr_t addr)
|
||||
{
|
||||
Res res;
|
||||
Addr p;
|
||||
|
||||
AVER(p_o != NULL);
|
||||
|
||||
/* This function cannot be called while walking the heap, unlike
|
||||
* mps_arena_has_addr(). This is because it is designed to be called
|
||||
* with an active mutator, so takes the arena lock. This is in order
|
||||
* that it sees a consistent view of MPS structures and the heap,
|
||||
* and can peek behind the barrier.
|
||||
*/
|
||||
ArenaEnter(arena);
|
||||
AVERT(Arena, arena);
|
||||
res = ArenaAddrObject(&p, arena, (Addr)addr);
|
||||
ArenaLeave(arena);
|
||||
/* We require the object to be ambiguously referenced (hence pinned)
|
||||
* so that p doesn't become invalid before it is written to *p_o.
|
||||
* (We can't simply put this write before the ArenaLeave(), because
|
||||
* p_o could point to MPS-managed memory that is behind a barrier.)
|
||||
*/
|
||||
if (res == ResOK)
|
||||
*p_o = (mps_addr_t)p;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* mps_addr_fmt -- what format might this address have?
|
||||
*
|
||||
* .per-pool: There's no reason why all objects in a pool should have
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ Bool PoolClassCheck(PoolClass klass)
|
|||
CHECKL(FUNCHECK(klass->debugMixin));
|
||||
CHECKL(FUNCHECK(klass->totalSize));
|
||||
CHECKL(FUNCHECK(klass->freeSize));
|
||||
CHECKL(FUNCHECK(klass->addrObject));
|
||||
|
||||
/* Check that pool classes overide sets of related methods. */
|
||||
CHECKL((klass->init == PoolAbsInit) ==
|
||||
|
|
@ -303,6 +304,21 @@ Size PoolFreeSize(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* PoolAddrObject -- return base pointer from interior pointer
|
||||
*
|
||||
* Note: addr is not necessarily inside the pool, even though
|
||||
* mps_addr_object dispatches via the tract table. This allows this
|
||||
* function to be used more generally internally. The pool should
|
||||
* check (it has to anyway).
|
||||
*/
|
||||
|
||||
Res PoolAddrObject(Addr *pReturn, Pool pool, Addr addr)
|
||||
{
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
return Method(Pool, pool, addrObject)(pReturn, pool, addr);
|
||||
}
|
||||
|
||||
/* PoolDescribe -- describe a pool */
|
||||
|
||||
Res PoolDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ DEFINE_CLASS(Pool, AbstractPool, klass)
|
|||
klass->debugMixin = PoolNoDebugMixin;
|
||||
klass->totalSize = PoolNoSize;
|
||||
klass->freeSize = PoolNoSize;
|
||||
klass->addrObject = PoolTrivAddrObject;
|
||||
klass->sig = PoolClassSig;
|
||||
AVERT(PoolClass, klass);
|
||||
}
|
||||
|
|
@ -476,6 +477,16 @@ Size PoolNoSize(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
Res PoolTrivAddrObject(Addr *pReturn, Pool pool, Addr addr)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(pReturn != NULL);
|
||||
UNUSED(addr);
|
||||
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2020 Ravenbrook Limited <https://www.ravenbrook.com/>.
|
||||
|
|
|
|||
|
|
@ -1893,6 +1893,90 @@ static void amcWalkAll(Pool pool, FormattedObjectsVisitor f, void *p, size_t s)
|
|||
}
|
||||
}
|
||||
|
||||
/* AMCAddrObject -- return base pointer from interior pointer
|
||||
*
|
||||
* amcAddrObjectSearch implements the scan for an object containing
|
||||
* the interior pointer by skipping using format methods.
|
||||
*
|
||||
* AMCAddrObject locates the segment containing the interior pointer
|
||||
* and wraps amcAddrObjectSearch in the necessary shield operations to
|
||||
* give it access.
|
||||
*/
|
||||
|
||||
static Res amcAddrObjectSearch(Addr *pReturn,
|
||||
Pool pool,
|
||||
Addr objBase,
|
||||
Addr searchLimit,
|
||||
Addr addr)
|
||||
{
|
||||
Format format;
|
||||
Size hdrSize;
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(objBase <= searchLimit);
|
||||
|
||||
format = pool->format;
|
||||
hdrSize = format->headerSize;
|
||||
while (objBase < searchLimit) {
|
||||
Addr objRef = AddrAdd(objBase, hdrSize);
|
||||
Addr objLimit = AddrSub((*format->skip)(objRef), hdrSize);
|
||||
AVER(objBase < objLimit);
|
||||
|
||||
if (addr < objLimit) {
|
||||
AVER(objBase <= addr);
|
||||
AVER(addr < objLimit);
|
||||
|
||||
/* Don't return base pointer if object is moved */
|
||||
if (NULL == (*format->isMoved)(objRef)) {
|
||||
*pReturn = objRef;
|
||||
return ResOK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
objBase = objLimit;
|
||||
}
|
||||
return ResFAIL;
|
||||
}
|
||||
|
||||
static Res AMCAddrObject(Addr *pReturn, Pool pool, Addr addr)
|
||||
{
|
||||
Res res;
|
||||
Arena arena;
|
||||
Addr base, limit;
|
||||
Buffer buffer;
|
||||
Seg seg;
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
if (!SegOfAddr(&seg, arena, addr) || SegPool(seg) != pool)
|
||||
return ResFAIL;
|
||||
|
||||
base = SegBase(seg);
|
||||
if (SegBuffer(&buffer, seg))
|
||||
/* We use BufferGetInit here (and not BufferScanLimit) because we
|
||||
* want to be able to find objects that have been allocated and
|
||||
* committed since the last flip. These objects lie between the
|
||||
* addresses returned by BufferScanLimit (which returns the value
|
||||
* of init at the last flip) and BufferGetInit.
|
||||
*
|
||||
* Strictly speaking we only need a limit that is at least the
|
||||
* maximum of the objects on the segments. This is because addr
|
||||
* *must* point inside a live object and we stop skipping once we
|
||||
* have found it. The init pointer serves this purpose.
|
||||
*/
|
||||
limit = BufferGetInit(buffer);
|
||||
else
|
||||
limit = SegLimit(seg);
|
||||
|
||||
ShieldExpose(arena, seg);
|
||||
res = amcAddrObjectSearch(pReturn, pool, base, limit, addr);
|
||||
ShieldCover(arena, seg);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* AMCTotalSize -- total memory allocated from the arena */
|
||||
|
||||
|
|
@ -2008,6 +2092,7 @@ DEFINE_CLASS(Pool, AMCZPool, klass)
|
|||
klass->bufferClass = amcBufClassGet;
|
||||
klass->totalSize = AMCTotalSize;
|
||||
klass->freeSize = AMCFreeSize;
|
||||
klass->addrObject = AMCAddrObject;
|
||||
AVERT(PoolClass, klass);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ New features
|
|||
:ref:`topic-scanning-protocol`. This allows the client program to
|
||||
safely update references in the visited objects.
|
||||
|
||||
#. The new function :c:func:`mps_addr_object` allows clients to
|
||||
discover the base pointer of an object from a pointer to anywhere
|
||||
inside the object. This is intended to support stack tracing and
|
||||
debugging for client programs that allocate their code on the
|
||||
heap.
|
||||
|
||||
#. A :term:`virtual memory arena` can now be configured to call
|
||||
functions when it acquires a new chunk of :term:`address space`,
|
||||
and when it returns a chunk of address space to the operation
|
||||
|
|
|
|||
|
|
@ -1054,6 +1054,52 @@ Arena introspection and debugging
|
|||
:c:func:`mps_addr_fmt`.
|
||||
|
||||
|
||||
.. c:function:: mps_res_t mps_addr_object(mps_addr_t *p_o, mps_arena_t arena, mps_addr_t addr)
|
||||
|
||||
Find the :term:`base pointer` of an :term:`object` if provided with an
|
||||
:term:`interior pointer` to that object, or the object's base pointer,
|
||||
provided the object exists in a pool that supports this feature.
|
||||
|
||||
``p_o`` points to a location that will hold the object's base pointer.
|
||||
|
||||
``arena`` is an arena.
|
||||
|
||||
``addr`` is an address that might be an interior or base pointer.
|
||||
|
||||
Returns MPS_RES_OK if a base pointer to an object into which ``addr``
|
||||
points was successfully returned.
|
||||
|
||||
Returns MPS_RES_FAIL if ``addr`` points to memory not managed by the
|
||||
``arena`` or if ``addr`` points to the interior of an object which has
|
||||
been moved by a :term:`moving memory manager`.
|
||||
|
||||
Returns MPS_RES_UNIMPL if ``addr`` is found to be managed by a :term:`pool`
|
||||
which does not currently implement this feature.
|
||||
|
||||
:c:func:`mps_addr_object` allows client programs that allocate
|
||||
code on the heap to implement debugging and stack tracing, in that it provides
|
||||
a way to unwind a client program's stack by finding the block of code to which the
|
||||
program counter or function return addresses currently point. It can be called
|
||||
multiple times as needed to build a complete trace of the client program's stack.
|
||||
|
||||
This function does not support debugging in situations where the arena
|
||||
itself has encountered a runtime error. For cases where the MPS encounters
|
||||
runtime errors, see :c:func:`mps_arena_postmortem`.
|
||||
|
||||
.. note::
|
||||
|
||||
This function is intended to assist with debugging fatal
|
||||
errors in the :term:`client program`. It is not expected to be
|
||||
needed in normal use, i.e. as part of the regular operation of code in
|
||||
production, since it is not optimized for performance. If you find yourself
|
||||
wanting to use this function other than in the use case described, there may
|
||||
be a better way to meet your requirements: please
|
||||
:ref:`contact us <contact>`.
|
||||
|
||||
If you would like this function to work in a pool in which it's currently
|
||||
unimplemented, please :ref:`contact us <contact>`.
|
||||
|
||||
|
||||
.. index::
|
||||
single: arena extension callbacks; introduction
|
||||
single: extension callbacks; introduction
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
Test case Flags Notes
|
||||
============= ================ ==========================================
|
||||
abqtest
|
||||
addrobj
|
||||
airtest
|
||||
amcss =P
|
||||
amcsshe =P
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue