1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/****************************************************************
* *
* Copyright (c) 2011-2015 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "dollar_zlevel.h"
#include "error_trap.h"
#include "golevel.h"
#include "cache.h"
#include "cmd_qlf.h"
#include "hashtab.h"
#include "hashtab_objcode.h"
#include "hashtab_mname.h"
#include <rtnhdr.h>
#include "stack_frame.h"
#include "mprof.h"
#include "gtm_unlink_all.h"
#include "zbreak.h"
#include "gtm_text_alloc.h"
#include "parse_file.h"
#include "zro_shlibs.h"
#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsblk.h"
#include "gdsbml.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsfhead.h"
#include "srcline.h"
#include "gtmci.h" /* for GTM_CIMOD */
#include "dm_setup.h" /* for GTM_DMOD */
#include "urx.h"
#include "stringpool.h"
#include "zr_unlink_rtn.h"
#ifdef GTM_TRIGGER
#include "gv_trigger.h"
#include "gtm_trigger.h"
#include "gv_trigger_protos.h"
#endif
GBLREF boolean_t is_tracing_on;
GBLREF gv_key *gv_currkey;
GBLREF hash_table_objcode cache_table;
GBLREF int dollar_truth;
GBLREF int indir_cache_mem_size;
GBLREF rtn_tabent *rtn_names, *rtn_names_end, *rtn_names_top, *rtn_fst_table;
GBLREF stack_frame *frame_pointer;
GBLREF gv_namehead *gv_target_list;
/* Routine to do the following:
*
* 1. Stop M-Profiling.
* 2. Unwind the M stack back to level 1
* 3. (re)Initialize $ECODE, $REFERENCE and $TEST.
* 4. Remove all triggers. This includes not only the trigger routines but the trigger definitions and
* linkages in the gvt_trigger struct anchored off of the gv_target.
* 5. Unlink all M routines. This includes getting rid of their linkage entries, breakpoints,
* and $TEXT() caches and re-initializing the routine table.
* 6. Empty the indirect cache.
* 7. Close the shared libraries associated with M programs and reopen them after the unroll if any
* are present in $ZROUTINES.
*
* Currently called from op_zgoto() but could be called from elsewhere if needed in the future.
*
* Note this routine removes all loaded programs but the intial base-frame on the stack has the address of whatever
* the first program is (GTM$DMOD in a direct mode situation or the starting program in a -run invocation). It is up
* to the caller to set the base frame with this address so the stack has no unknown references in it.
*/
void gtm_unlink_all(void)
{
rtn_tabent *rtab;
rhdtyp *rtnhdr, *rhdr, *next_rhdr;
ht_ent_mname *tabent_mname;
textElem *telem;
ht_ent_objcode *tabent_obj, *topent;
cache_entry *csp;
mname_entry key;
routine_source *src_tbl;
gv_namehead *gvt;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
/* Step 1: Stop M-Profiling */
if (is_tracing_on)
turn_tracing_off(NULL);
/* Step 2: Unwind M stack back to level 0 */
GOLEVEL(0, TRUE);
assert(0 == dollar_zlevel());
/* Step 3: re-Initialize $ECODE, $REFERENCE, and $TEST */
NULLIFY_DOLLAR_ECODE; /* Clears $ECODE and results returned for $STACK */
if (NULL != gv_currkey)
{ /* Clears $REFERENCE */
gv_currkey->end = 0;
gv_currkey->base[0] = KEY_DELIMITER;
}
dollar_truth = FALSE; /* aka $TEST */
/* Step 4: Remove all triggers */
# ifdef GTM_TRIGGER
for (gvt = gv_target_list; gvt; gvt = gvt->next_gvnh)
gvtr_free(gvt);
# endif
/* Step 5: Unlink all routines, remove $TEXT cache and remove breakpoints. Note that for the purposes of this section,
* there is no difference between normal routines and trigger routines. Both are being removed completely so the code
* below is a hodgepodge of code from zlput_rname and gtm_trigger_cleanup(). Note process in reverse order so we can
* move rtn_names_end up leaving processed entries (whose keys no longer work) off the end of the table without moving
* anything. This is necessary because removing ZBREAK points can call find_rtn_hdr so this table needs to remain in
* a usable state while we are doing this.
*/
for (rtab = rtn_names_end; rtab > rtn_names; rtab--, rtn_names_end = rtab)
{ /* [0] is not used (for some reason) */
rtnhdr = rtab->rt_adr;
if ((0 == strcmp(rtnhdr->routine_name.addr, GTM_DMOD)) || (0 == strcmp(rtnhdr->routine_name.addr, GTM_CIMOD)))
{ /* If the routine is GTM$DMOD or GTM$CI, it is allocated in one chunk by make_*mode(). Release it in
* one chunk too.
*/
GTM_TEXT_FREE(rtnhdr);
} else
zr_unlink_rtn(rtnhdr, TRUE);
}
/* All programs have been removed. If this is the "first" table allocated which cannot be removed, just reinitialize
* the table and we're done. If a new table, release it, recover the first table, initialize and we're done.
*/
if (rtn_names != rtn_fst_table)
{
free(rtn_names);
rtn_names = rtn_fst_table;
assert(NULL != rtn_fst_table);
}
memset(rtn_names, 0, SIZEOF(rtn_tabent));
rtn_names_end = rtn_names_top = rtn_names;
/* Step 5: Empty the indirect cache */
for (tabent_obj = cache_table.base, topent = cache_table.top; tabent_obj < topent; tabent_obj++)
{ /* Run through the hashtable getting rid of all the entries. Not bothering with the cleanups
* like are done in cache_table_rebuild since we are going to re-init the table.
*/
if (HTENT_VALID_OBJCODE(tabent_obj, cache_entry, csp))
{
GTM_TEXT_FREE(csp);
}
}
reinitialize_hashtab_objcode(&cache_table); /* Completely re-initialize the hash table */
indir_cache_mem_size = 0;
/* Step 6: Close all M code shared libraries */
zro_shlibs_unlink_all();
}
|